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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值