• usb_gadget_probe_driver


    #define CONFIGFS_ATTR(_pfx, _name)            \
    static struct configfs_attribute _pfx##attr_##_name = {    \
        .ca_name    = __stringify(_name),        \
        .ca_mode    = S_IRUGO | S_IWUSR,        \
        .ca_owner    = THIS_MODULE,            \
        .show        = _pfx##_name##_show,        \
        .store        = _pfx##_name##_store,        \
    }

    CONFIGFS_ATTR(gadget_dev_desc_, UDC);

    configfs:

    static ssize_t gadget_dev_desc_UDC_store(struct config_item *item,
            const char *page, size_t len)
    {
        struct gadget_info *gi = to_gadget_info(item);
        char *name;
        int ret;

        if (strlen(page) < len)
            return -EOVERFLOW;

        name = kstrdup(page, GFP_KERNEL);
        if (!name)
            return -ENOMEM;
        if (name[len - 1] == '\n')
            name[len - 1] = '\0';

        mutex_lock(&gi->lock);

        if (!strlen(name)) {
            ret = unregister_gadget(gi);
            if (ret)
                goto err;
            kfree(name);
        } else {
            if (gi->composite.gadget_driver.udc_name) {
                ret = -EBUSY;
                goto err;
            }
            gi->composite.gadget_driver.udc_name = name;
            ret = usb_gadget_probe_driver(&gi->composite.gadget_driver);
            if (ret) {
                gi->composite.gadget_driver.udc_name = NULL;
                goto err;
            }
        }
        mutex_unlock(&gi->lock);
        return len;
    err:
        kfree(name);
        mutex_unlock(&gi->lock);
        return ret;
    }

    legacy:

    int usb_composite_probe(struct usb_composite_driver *driver)
    {
        struct usb_gadget_driver *gadget_driver;

        if (!driver || !driver->dev || !driver->bind)
            return -EINVAL;

        if (!driver->name)
            driver->name = "composite";

        driver->gadget_driver = composite_driver_template;
        gadget_driver = &driver->gadget_driver;

        gadget_driver->function =  (char *) driver->name;
        gadget_driver->driver.name = driver->name;
        gadget_driver->max_speed = driver->max_speed;

        return usb_gadget_probe_driver(gadget_driver);
    }

    int usb_gadget_probe_driver(struct usb_gadget_driver *driver)
    {
        struct usb_udc        *udc = NULL;
        int            ret = -ENODEV;

        if (!driver || !driver->bind || !driver->setup)
            return -EINVAL;

        mutex_lock(&udc_lock);
        if (driver->udc_name) {
            list_for_each_entry(udc, &udc_list, list) {
                ret = strcmp(driver->udc_name, dev_name(&udc->dev));
                if (!ret)
                    break;
            }
            if (ret)
                ret = -ENODEV;
            else if (udc->driver)
                ret = -EBUSY;
            else
                goto found;
        } else {
            list_for_each_entry(udc, &udc_list, list) {
                /* For now we take the first one */
                if (!udc->driver)
                    goto found;
            }
        }

        if (!driver->match_existing_only) {
            list_add_tail(&driver->pending, &gadget_driver_pending_list);
            pr_info("udc-core: couldn't find an available UDC - added [%s] to list of pending drivers\n",
                driver->function);
            ret = 0;
        }

        mutex_unlock(&udc_lock);
        return ret;
    found:
        ret = udc_bind_to_driver(udc, driver);
        mutex_unlock(&udc_lock);
        return ret;
    }

    configfs, usb eth:

    echo "0x0502" > idVendor
    echo "0x3235" > idProduct
    mkdir functions/rndis.rn0
    mkdir configs/c1.1
    ln -s functions/rndis.rn0 configs/c1.1/
    echo 4800000.usb > UDC

    int usb_function_register(struct usb_function_driver *newf)
    {
        struct usb_function_driver *fd;
        int ret;

        ret = -EEXIST;

        mutex_lock(&func_lock);
        list_for_each_entry(fd, &func_list, list) {
            if (!strcmp(fd->name, newf->name))
                goto out;
        }
        ret = 0;
        list_add_tail(&newf->list, &func_list);
    out:
        mutex_unlock(&func_lock);
        return ret;
    }

    struct usb_function_instance *usb_get_function_instance(const char *name)
    {
        struct usb_function_instance *fi;
        int ret;

        fi = try_get_usb_function_instance(name);
        if (!IS_ERR(fi))
            return fi;
        ret = PTR_ERR(fi);
        if (ret != -ENOENT)
            return fi;
        ret = request_module("usbfunc:%s", name);
        if (ret < 0)
            return ERR_PTR(ret);
        return try_get_usb_function_instance(name);
    }

    static struct usb_function_instance *try_get_usb_function_instance(const char *name)
    {
        struct usb_function_driver *fd;
        struct usb_function_instance *fi;

        fi = ERR_PTR(-ENOENT);
        mutex_lock(&func_lock);
        list_for_each_entry(fd, &func_list, list) {

            if (strcmp(name, fd->name))
                continue;

            if (!try_module_get(fd->mod)) {
                fi = ERR_PTR(-EBUSY);
                break;
            }
            fi = fd->alloc_inst();
            if (IS_ERR(fi))
                module_put(fd->mod);
            else
                fi->fd = fd;
            break;
        }
        mutex_unlock(&func_lock);
        return fi;
    }

  • 相关阅读:
    多线程的实现方式
    EasyCVR视频监控+AI智能分析网关如何助力木材厂安全生产?
    kafka的“直接内存映射技术”,有没有内存修改数据的问题?
    【学习笔记】ARC11123
    Unity 如何查看编译的耗时?
    保姆级教程:个人深度学习工作站配置指南
    ssh互信配置失败,仍需要输密码
    基于Python实现情感分析实验
    解锁未知:探索 Web3 的创新与前景
    liunx下软链接和硬链接的用法
  • 原文地址:https://blog.csdn.net/wmzjzwlzs/article/details/128009164