static __init int cdc_do_config(struct usb_configuration *c)
{
	struct fsg_opts *fsg_opts;
	int ret;

	if (gadget_is_otg(c->cdev->gadget)) {
		c->descriptors = otg_desc;
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	f_ecm = usb_get_function(fi_ecm);
	if (IS_ERR(f_ecm))
		return PTR_ERR(f_ecm);

	ret = usb_add_function(c, f_ecm);
	if (ret < 0)
		goto err_func_ecm;

	/* implicit port_num is zero */
	f_acm_multi = usb_get_function(fi_acm);
	if (IS_ERR(f_acm_multi)) {
		ret = PTR_ERR(f_acm_multi);
		goto err_func_acm;
	}

	ret = usb_add_function(c, f_acm_multi);
	if (ret)
		goto err_conf;

	f_msg_multi = usb_get_function(fi_msg);
	if (IS_ERR(f_msg_multi)) {
		ret = PTR_ERR(f_msg_multi);
		goto err_fsg;
	}

	fsg_opts = fsg_opts_from_func_inst(fi_msg);
	ret = fsg_common_run_thread(fsg_opts->common);
	if (ret)
		goto err_run;

	ret = usb_add_function(c, f_msg_multi);
	if (ret)
		goto err_run;

	return 0;
err_run:
	usb_put_function(f_msg_multi);
err_fsg:
	usb_remove_function(c, f_acm_multi);
err_conf:
	usb_put_function(f_acm_multi);
err_func_acm:
	usb_remove_function(c, f_ecm);
err_func_ecm:
	usb_put_function(f_ecm);
	return ret;
}
Exemple #2
0
static int dtf_bind_config(struct usb_configuration *c)
{
	struct dtf_dev  *dev = _dtf_dev;
	int ret;

	_dbgmsg( "IN\n" );

	dev->cdev = c->cdev;
	dev->function.name = "dtf";
	dev->function.descriptors = vFs_dtf_descs;
	dev->function.hs_descriptors = vHs_dtf_descs;
	dev->function.bind = dtf_function_bind;
	dev->function.unbind = dtf_function_unbind;
	dev->function.setup = dtf_function_setup;
	dev->function.set_alt = dtf_function_set_alt;
	dev->function.disable = dtf_function_disable;
	dev->function.suspend = dtf_function_suspend;
	dev->function.resume = dtf_function_resume;

	dev->mCtrl_ep_enbl = 0;
	dev->mData_ep_enbl = 0;

	_dbgmsg_gadget( "usb_add_function\n" );
	ret = usb_add_function(c, &dev->function);
	_dbgmsg( "OUT(%d)\n", ret );

	return ret;
}
/**
 * gser_bind_config - add a generic serial function to a configuration
 * @c: the configuration to support the serial instance
 * @port_num: /dev/ttyGS* port this interface will use
 * Context: single threaded during gadget setup
 *
 * Returns zero on success, else negative errno.
 *
 * Caller must have called @gserial_setup() with enough ports to
 * handle all the ones it binds.  Caller is also responsible
 * for calling @gserial_cleanup() before module unload.
 */
int gser_bind_config(struct usb_configuration *c, u8 port_num)
{
	struct f_gser	*gser;
	int		status;

	/* REVISIT might want instance-specific strings to help
	 * distinguish instances ...
	 */

	/* maybe allocate device-global string ID */
	if (gser_string_defs[0].id == 0) {
		status = usb_string_id(c->cdev);
		if (status < 0)
			return status;
		gser_string_defs[0].id = status;
	}

	/* allocate and initialize one new instance */
	gser = kzalloc(sizeof *gser, GFP_KERNEL);
	if (!gser)
		return -ENOMEM;

#ifdef CONFIG_MODEM_SUPPORT
	spin_lock_init(&gser->lock);
#endif
	gser->port_num = port_num;

	gser->port.func.name = "gser";
	gser->port.func.strings = gser_strings;
	gser->port.func.bind = gser_bind;
	gser->port.func.unbind = gser_unbind;
	gser->port.func.set_alt = gser_set_alt;
	gser->port.func.disable = gser_disable;
	gser->transport		= gserial_ports[port_num].transport;
#ifdef CONFIG_MODEM_SUPPORT
	/* We support only three ports for now */
	if (port_num == 0)
		gser->port.func.name = "modem";
	else if (port_num == 1)
		gser->port.func.name = "nmea";
	else
//zz
		gser->port.func.name = "at";
//zz
	gser->port.func.setup = gser_setup;
	gser->port.connect = gser_connect;
	gser->port.get_dtr = gser_get_dtr;
	gser->port.get_rts = gser_get_rts;
	gser->port.send_carrier_detect = gser_send_carrier_detect;
	gser->port.send_ring_indicator = gser_send_ring_indicator;
	gser->port.send_modem_ctrl_bits = gser_send_modem_ctrl_bits;
	gser->port.disconnect = gser_disconnect;
	gser->port.send_break = gser_send_break;
#endif

	status = usb_add_function(c, &gser->port.func);
	if (status)
		kfree(gser);
	return status;
}
Exemple #4
0
static int __init ncm_do_config(struct usb_configuration *c)
{
	int status;

	/* FIXME alloc iConfiguration string, set it in c->strings */

	if (gadget_is_otg(c->cdev->gadget)) {
		c->descriptors = otg_desc;
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	f_ncm = usb_get_function(f_ncm_inst);
	if (IS_ERR(f_ncm)) {
		status = PTR_ERR(f_ncm);
		return status;
	}

	status = usb_add_function(c, f_ncm);
	if (status < 0) {
		usb_put_function(f_ncm);
		return status;
	}

	return 0;
}
Exemple #5
0
static int msg_do_config(struct usb_configuration *c)
{
	struct fsg_opts *opts;
	int ret;

	if (gadget_is_otg(c->cdev->gadget)) {
		c->descriptors = otg_desc;
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	opts = fsg_opts_from_func_inst(fi_msg);

	f_msg = usb_get_function(fi_msg);
	if (IS_ERR(f_msg))
		return PTR_ERR(f_msg);

	ret = fsg_common_run_thread(opts->common);
	if (ret)
		goto put_func;

	ret = usb_add_function(c, f_msg);
	if (ret)
		goto put_func;

	return 0;

put_func:
	usb_put_function(f_msg);
	return ret;
}
Exemple #6
0
static __init int cdc_do_config(struct usb_configuration *c)
{
	int ret;

	if (gadget_is_otg(c->cdev->gadget)) {
		c->descriptors = otg_desc;
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	ret = ecm_bind_config(c, host_mac, the_dev);
	if (ret < 0)
		return ret;

	/* implicit port_num is zero */
	f_acm_multi = usb_get_function(fi_acm);
	if (IS_ERR(f_acm_multi))
		return PTR_ERR(f_acm_multi);

	ret = usb_add_function(c, f_acm_multi);
	if (ret)
		goto err_conf;

	ret = fsg_bind_config(c->cdev, c, &fsg_common);
	if (ret < 0)
		goto err_fsg;

	return 0;
err_fsg:
	usb_remove_function(c, f_acm_multi);
err_conf:
	usb_put_function(f_acm_multi);
	return ret;
}
Exemple #7
0
static int acc_bind_config(struct usb_configuration *c)
{
	struct acc_dev *dev = _acc_dev;
	int ret;

	printk(KERN_INFO "acc_bind_config\n");

	/* allocate a string ID for our interface */
	if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) {
		ret = usb_string_id(c->cdev);
		if (ret < 0)
			return ret;
		acc_string_defs[INTERFACE_STRING_INDEX].id = ret;
		acc_interface_desc.iInterface = ret;
	}

	dev->cdev = c->cdev;
	dev->function.name = "accessory";
	dev->function.strings = acc_strings,
	dev->function.descriptors = fs_acc_descs;
	dev->function.hs_descriptors = hs_acc_descs;
	dev->function.bind = acc_function_bind;
	dev->function.unbind = acc_function_unbind;
	dev->function.set_alt = acc_function_set_alt;
	dev->function.disable = acc_function_disable;

	return usb_add_function(c, &dev->function);
}
Exemple #8
0
static int thor_func_init(struct usb_configuration *c)
{
	struct f_thor *f_thor;
	int status;

	debug("%s: cdev: 0x%p\n", __func__, c->cdev);

	f_thor = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_thor));
	if (!f_thor)
		return -ENOMEM;

	memset(f_thor, 0, sizeof(*f_thor));

	f_thor->usb_function.name = "f_thor";
	f_thor->usb_function.bind = thor_func_bind;
	f_thor->usb_function.unbind = thor_unbind;
	f_thor->usb_function.setup = thor_func_setup;
	f_thor->usb_function.set_alt = thor_func_set_alt;
	f_thor->usb_function.disable = thor_func_disable;

	status = usb_add_function(c, &f_thor->usb_function);
	if (status)
		free(f_thor);

	return status;
}
static int acc_bind_config(struct usb_configuration *c)
{
	struct acc_dev *dev;
	int ret;

	printk(KERN_INFO "acc_bind_config\n");

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;

	/* allocate a string ID for our interface */
	if (acc_string_defs[INTERFACE_STRING_INDEX].id == 0) {
		ret = usb_string_id(c->cdev);
		if (ret < 0)
			return ret;
		acc_string_defs[INTERFACE_STRING_INDEX].id = ret;
		acc_interface_desc.iInterface = ret;
	}

	spin_lock_init(&dev->lock);
	init_waitqueue_head(&dev->read_wq);
	init_waitqueue_head(&dev->write_wq);
	atomic_set(&dev->open_excl, 0);
	INIT_LIST_HEAD(&dev->tx_idle);
	INIT_DELAYED_WORK(&dev->work, acc_work);

	dev->cdev = c->cdev;
	dev->function.name = "accessory";
	dev->function.strings = acc_strings,
	dev->function.descriptors = fs_acc_descs;
	dev->function.hs_descriptors = hs_acc_descs;
	dev->function.bind = acc_function_bind;
	dev->function.unbind = acc_function_unbind;
	dev->function.setup = acc_function_setup;
	dev->function.set_alt = acc_function_set_alt;
	dev->function.disable = acc_function_disable;
	dev->function.disabled = 1;

	/* _acc_dev must be set before calling usb_gadget_register_driver */
	_acc_dev = dev;

	ret = misc_register(&acc_device);
	if (ret)
		goto err1;

	ret = usb_add_function(c, &dev->function);
	if (ret)
		goto err2;

	return 0;

err2:
	misc_deregister(&acc_device);
err1:
	kfree(dev);
	printk(KERN_ERR "USB accessory gadget driver failed to initialize\n");
	return ret;
}
Exemple #10
0
/*
 * We _always_ have an ECM, CDC Subset, or EEM configuration.
 */
static int __init eth_do_config(struct usb_configuration *c)
{
	int status = 0;

	/* FIXME alloc iConfiguration string, set it in c->strings */

	if (gadget_is_otg(c->cdev->gadget)) {
		c->descriptors = otg_desc;
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	if (use_eem) {
		f_eem = usb_get_function(fi_eem);
		if (IS_ERR(f_eem))
			return PTR_ERR(f_eem);

		status = usb_add_function(c, f_eem);
		if (status < 0)
			usb_put_function(f_eem);

		return status;
	} else if (can_support_ecm(c->cdev->gadget)) {
		f_ecm = usb_get_function(fi_ecm);
		if (IS_ERR(f_ecm))
			return PTR_ERR(f_ecm);

		status = usb_add_function(c, f_ecm);
		if (status < 0)
			usb_put_function(f_ecm);

		return status;
	} else {
		f_geth = usb_get_function(fi_geth);
		if (IS_ERR(f_geth))
			return PTR_ERR(f_geth);

		status = usb_add_function(c, f_geth);
		if (status < 0)
			usb_put_function(f_geth);

		return status;
	}

}
Exemple #11
0
/*
 * We _always_ have both ACM and mass storage functions.
 */
static int acm_ms_do_config(struct usb_configuration *c)
{
	struct fsg_opts *opts;
	int	status;

	if (gadget_is_otg(c->cdev->gadget)) {
		c->descriptors = otg_desc;
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	opts = fsg_opts_from_func_inst(fi_msg);

	f_acm = usb_get_function(f_acm_inst);
	if (IS_ERR(f_acm))
		return PTR_ERR(f_acm);

	f_msg = usb_get_function(fi_msg);
	if (IS_ERR(f_msg)) {
		status = PTR_ERR(f_msg);
		goto put_acm;
	}

	status = usb_add_function(c, f_acm);
	if (status < 0)
		goto put_msg;

	status = fsg_common_run_thread(opts->common);
	if (status)
		goto remove_acm;

	status = usb_add_function(c, f_msg);
	if (status)
		goto remove_acm;

	return 0;
remove_acm:
	usb_remove_function(c, f_acm);
put_msg:
	usb_put_function(f_msg);
put_acm:
	usb_put_function(f_acm);
	return status;
}
Exemple #12
0
static int audio_do_config(struct usb_configuration *c)
{
	int status;

	/* FIXME alloc iConfiguration string, set it in c->strings */

	if (gadget_is_otg(c->cdev->gadget)) {
		c->descriptors = otg_desc;
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

#ifdef CONFIG_GADGET_UAC1
	f_uac1 = usb_get_function(fi_uac1);
	if (IS_ERR(f_uac1)) {
		status = PTR_ERR(f_uac1);
		return status;
	}

	status = usb_add_function(c, f_uac1);
	if (status < 0) {
		usb_put_function(f_uac1);
		return status;
	}
#else
	f_uac2 = usb_get_function(fi_uac2);
	if (IS_ERR(f_uac2)) {
		status = PTR_ERR(f_uac2);
		return status;
	}

	status = usb_add_function(c, f_uac2);
	if (status < 0) {
		usb_put_function(f_uac2);
		return status;
	}
#endif

	return 0;
}
Exemple #13
0
/*
 * We _always_ have both CDC ECM and CDC ACM functions.
 */
static int __init cdc_do_config(struct usb_configuration *c)
{
	int	status;

	if (gadget_is_otg(c->cdev->gadget)) {
		c->descriptors = otg_desc;
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	f_ecm = usb_get_function(fi_ecm);
	if (IS_ERR(f_ecm)) {
		status = PTR_ERR(f_ecm);
		goto err_get_ecm;
	}

	status = usb_add_function(c, f_ecm);
	if (status)
		goto err_add_ecm;

	f_acm = usb_get_function(fi_serial);
	if (IS_ERR(f_acm)) {
		status = PTR_ERR(f_acm);
		goto err_get_acm;
	}

	status = usb_add_function(c, f_acm);
	if (status)
		goto err_add_acm;
	return 0;

err_add_acm:
	usb_put_function(f_acm);
err_get_acm:
	usb_remove_function(c, f_ecm);
err_add_ecm:
	usb_put_function(f_ecm);
err_get_ecm:
	return status;
}
Exemple #14
0
int hidg_bind_config(struct usb_configuration *c,
                     struct hidg_func_descriptor *fdesc, int index)
{
    struct f_hidg *hidg;
    int status;

    if (index >= minors)
        return -ENOENT;

    /* maybe allocate device-global string IDs, and patch descriptors */
    if (ct_func_string_defs[CT_FUNC_HID_IDX].id == 0) {
        status = usb_string_id(c->cdev);
        if (status < 0)
            return status;
        ct_func_string_defs[CT_FUNC_HID_IDX].id = status;
        hidg_interface_desc.iInterface = status;
    }

    /* allocate and initialize one new instance */
    hidg = kzalloc(sizeof *hidg, GFP_KERNEL);
    if (!hidg)
        return -ENOMEM;

    hidg->minor = index;
    hidg->bInterfaceSubClass = fdesc->subclass;
    hidg->bInterfaceProtocol = fdesc->protocol;
    hidg->report_length = fdesc->report_length;
    hidg->report_desc_length = fdesc->report_desc_length;
    hidg->report_desc = kmemdup(fdesc->report_desc,
                                fdesc->report_desc_length,
                                GFP_KERNEL);
    if (!hidg->report_desc) {
        kfree(hidg);
        return -ENOMEM;
    }

    hidg->func.name    = "hid";
    hidg->func.strings = ct_func_strings;
    hidg->func.bind    = hidg_bind;
    hidg->func.unbind  = hidg_unbind;
    hidg->func.set_alt = hidg_set_alt;
    hidg->func.disable = hidg_disable;
    hidg->func.setup   = hidg_setup;

    status = usb_add_function(c, &hidg->func);
    if (status)
        kfree(hidg);

    return status;
}
Exemple #15
0
static int midi_bind_config(struct usb_configuration *c)
{
    int status;

    f_midi = usb_get_function(fi_midi);
    if (IS_ERR(f_midi))
        return PTR_ERR(f_midi);

    status = usb_add_function(c, f_midi);
    if (status < 0) {
        usb_put_function(f_midi);
        return status;
    }

    return 0;
}
Exemple #16
0
static int tcm_do_config(struct usb_configuration *c)
{
	int status;

	f_tcm = usb_get_function(fi_tcm);
	if (IS_ERR(f_tcm))
		return PTR_ERR(f_tcm);

	status = usb_add_function(c, f_tcm);
	if (status < 0) {
		usb_put_function(f_tcm);
		return status;
	}

	return 0;
}
Exemple #17
0
static int serial_register_ports(struct usb_composite_dev *cdev,
		struct usb_configuration *c, const char *f_name)
{
	int i;
	int ret;

	ret = usb_add_config_only(cdev, c);
	if (ret)
		goto out;

	for (i = 0; i < n_ports; i++) {

		fi_serial[i] = usb_get_function_instance(f_name);
		if (IS_ERR(fi_serial[i])) {
			ret = PTR_ERR(fi_serial[i]);
			goto fail;
		}

		f_serial[i] = usb_get_function(fi_serial[i]);
		if (IS_ERR(f_serial[i])) {
			ret = PTR_ERR(f_serial[i]);
			goto err_get_func;
		}

		ret = usb_add_function(c, f_serial[i]);
		if (ret)
			goto err_add_func;
	}

	return 0;

err_add_func:
	usb_put_function(f_serial[i]);
err_get_func:
	usb_put_function_instance(fi_serial[i]);

fail:
	i--;
	while (i >= 0) {
		usb_remove_function(c, f_serial[i]);
		usb_put_function(f_serial[i]);
		usb_put_function_instance(fi_serial[i]);
		i--;
	}
out:
	return ret;
}
Exemple #18
0
int mtp_bind_config(struct usb_configuration *c)
{
	int ret = 0;
	int status;

	printk(KERN_INFO "Gadget Usb: mtp_bind_config\n");
	init_waitqueue_head(&g_usb_mtp_context.rx_wq);
	init_waitqueue_head(&g_usb_mtp_context.tx_wq);
	init_waitqueue_head(&g_usb_mtp_context.ctl_rx_wq);
	init_waitqueue_head(&g_usb_mtp_context.ctl_tx_wq);

	INIT_LIST_HEAD(&g_usb_mtp_context.rx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.rx_done_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.tx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_done_reqs);

	status = usb_string_id(c->cdev);
	if (status >= 0) {
		mtp_string_defs1[STRING_INTERFACE].id = status;
		intf_desc.iInterface = status;
	}

	mtp_string_defs2[STRING_MTP].id = mtp_ext_str_idx;

	g_usb_mtp_context.cdev = c->cdev;
	g_usb_mtp_context.function.name = "mtp";
	g_usb_mtp_context.function.descriptors = fs_mtp_descs;
	g_usb_mtp_context.function.hs_descriptors = hs_mtp_descs;
	g_usb_mtp_context.function.strings = mtp_strings;
	g_usb_mtp_context.function.bind = mtp_function_bind;
	g_usb_mtp_context.function.unbind = mtp_function_unbind;
	g_usb_mtp_context.function.setup = mtp_function_setup;
	g_usb_mtp_context.function.set_alt = mtp_function_set_alt;
	g_usb_mtp_context.function.disable = mtp_function_disable;

	/* start disabled */
	g_usb_mtp_context.function.hidden = 1;

	ret = usb_add_function(c, &g_usb_mtp_context.function);
	if (ret) {
		mtp_err("MTP gadget driver failed to initialize\n");
		return ret;
	}

	return 0;
}
Exemple #19
0
static int rockusb_add(struct usb_configuration *c)
{
	struct f_rockusb *f_rkusb = get_rkusb();
	int status;

	debug("%s: cdev: 0x%p\n", __func__, c->cdev);

	f_rkusb->usb_function.name = "f_rockusb";
	f_rkusb->usb_function.bind = rockusb_bind;
	f_rkusb->usb_function.unbind = rockusb_unbind;
	f_rkusb->usb_function.set_alt = rockusb_set_alt;
	f_rkusb->usb_function.disable = rockusb_disable;
	f_rkusb->usb_function.strings = rkusb_strings;

	status = usb_add_function(c, &f_rkusb->usb_function);
	if (status) {
		free(f_rkusb);
		rockusb_func = f_rkusb;
	}
	return status;
}
Exemple #20
0
/*
 * We _always_ have both ACM and mass storage functions.
 */
static int __init acm_ms_do_config(struct usb_configuration *c)
{
	struct f_serial_opts *opts;
	int	status;

	if (gadget_is_otg(c->cdev->gadget)) {
		c->descriptors = otg_desc;
		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	f_acm_inst = usb_get_function_instance("acm");
	if (IS_ERR(f_acm_inst))
		return PTR_ERR(f_acm_inst);

	opts = container_of(f_acm_inst, struct f_serial_opts, func_inst);
	opts->port_num = tty_line;

	f_acm = usb_get_function(f_acm_inst);
	if (IS_ERR(f_acm)) {
		status = PTR_ERR(f_acm);
		goto err_func;
	}

	status = usb_add_function(c, f_acm);
	if (status < 0)
		goto err_conf;

	status = fsg_bind_config(c->cdev, c, &fsg_common);
	if (status < 0)
		goto err_fsg;

	return 0;
err_fsg:
	usb_remove_function(c, f_acm);
err_conf:
	usb_put_function(f_acm);
err_func:
	usb_put_function_instance(f_acm_inst);
	return status;
}
Exemple #21
0
int rawbulk_bind_config(struct usb_configuration *c, int transfer_id) {

    int rc;   
    struct rawbulk_function *fn = rawbulk_lookup_function(transfer_id);

    if (!fn)
        return -ENOMEM;
        
    printk(KERN_INFO "add %s to config.\n", fn->longname);

    if (fn->string_defs[0].id == 0) {
        rc = usb_string_id(c->cdev);
        if (rc < 0)
            return rc;
        fn->string_defs[0].id = rc;
        fn->interface.iInterface = rc;
    }

    if (!fn->initialized) {
        fn->function.name = fn->longname;
        fn->function.setup = rawbulk_function_setup;
        fn->function.bind = rawbulk_function_bind;
        fn->function.unbind = rawbulk_function_unbind;
        fn->function.set_alt = rawbulk_function_setalt;
        fn->function.disable = rawbulk_function_disable;

        INIT_WORK(&fn->activator, do_activate);
        /*if(fn->transfer_id == RAWBULK_TID_MODEM) {
            INIT_WORK(&flow_control, modem_flow_control);
            INIT_WORK(&dtr_status, dtr_status_query);
        }*/ 
            fn->initialized = 1;
    }

    rc = usb_add_function(c, &fn->function);
    if (rc < 0)
        printk(KERN_ERR "%s - failed to config %d.\n", __func__, rc);

    return rc;
}
Exemple #22
0
int cloner_function_bind_config(struct usb_configuration *c)
{
	int status = 0;
	struct cloner *cloner = calloc(sizeof(struct cloner),1);

	if (!cloner)
		return -ENOMEM;

	cloner->usb_function.name = "vendor burnner interface";
	cloner->usb_function.bind = f_cloner_bind;
	cloner->usb_function.hs_descriptors = hs_intf_descs;
	cloner->usb_function.descriptors = fs_intf_descs;
	cloner->usb_function.set_alt = f_cloner_set_alt;
	cloner->usb_function.setup = f_cloner_setup_handle;
	cloner->usb_function.strings= burn_intf_string_tab;
	cloner->usb_function.disable = f_cloner_disable;
	cloner->usb_function.unbind = f_cloner_unbind;

	cloner->args = malloc(ARGS_LEN);
	cloner->args->transfer_data_chk = 1;
	cloner->args->write_back_chk = 1;
	cloner->skip_spl_size = 0;

	cloner->inited = 0;

	if (cloner_moudle_init())
		return -EINVAL;

	INIT_LIST_HEAD(&cloner->usb_function.list);
	bitmap_zero(cloner->usb_function.endpoints,32);

	status =  usb_add_function(c,&cloner->usb_function);
	if (status)
		free(cloner);
	return status;
}
int
rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
                         u32 vendorID, const char *manufacturer, struct eth_dev *dev)
{
    struct f_rndis	*rndis;
    int		status;

    if (!can_support_rndis(c) || !ethaddr)
        return -EINVAL;

    /* setup RNDIS itself */
    status = rndis_init();
    if (status < 0)
        return status;

    if (rndis_string_defs[0].id == 0) {
        status = usb_string_ids_tab(c->cdev, rndis_string_defs);
        if (status)
            return status;

        rndis_control_intf.iInterface = rndis_string_defs[0].id;
        rndis_data_intf.iInterface = rndis_string_defs[1].id;
        rndis_iad_descriptor.iFunction = rndis_string_defs[2].id;
    }

    /* allocate and initialize one new instance */
    status = -ENOMEM;
    rndis = kzalloc(sizeof *rndis, GFP_KERNEL);
    if (!rndis)
        goto fail;

    __rndis = rndis;

    memcpy(rndis->ethaddr, ethaddr, ETH_ALEN);
    rndis->vendorID = vendorID;
    rndis->manufacturer = manufacturer;

    rndis->port.ioport = dev;
    /* RNDIS activates when the host changes this filter */
    rndis->port.cdc_filter = 0;

    /* RNDIS has special (and complex) framing */
    rndis->port.header_len = sizeof(struct rndis_packet_msg_type);
    rndis->port.wrap = rndis_add_header;
    rndis->port.unwrap = rndis_rm_hdr;
    rndis->port.ul_max_pkts_per_xfer = rndis_ul_max_pkt_per_xfer;
    rndis->port.dl_max_pkts_per_xfer = rndis_dl_max_pkt_per_xfer;
    rndis->port.rx_trigger_enabled = rx_trigger_enabled;

    rndis->port.func.name = "rndis";
    rndis->port.func.strings = rndis_strings;
    /* descriptors are per-instance copies */
    rndis->port.func.bind = rndis_bind;
    rndis->port.func.unbind = rndis_unbind;
    rndis->port.func.set_alt = rndis_set_alt;
    rndis->port.func.setup = rndis_setup;
    rndis->port.func.disable = rndis_disable;

    status = usb_add_function(c, &rndis->port.func);
    if (status) {
        kfree(rndis);
fail:
        rndis_exit();
    }
    return status;
}
Exemple #24
0
static int zero_bind(struct usb_composite_dev *cdev)
{
	struct f_ss_opts	*ss_opts;
	struct f_lb_opts	*lb_opts;
	int			status;

	/* Allocate string descriptor numbers ... note that string
	 * contents can be overridden by the composite_dev glue.
	 */
	status = usb_string_ids_tab(cdev, strings_dev);
	if (status < 0)
		return status;

	device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
	device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
	device_desc.iSerialNumber = strings_dev[USB_GADGET_SERIAL_IDX].id;

	setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);

	func_inst_ss = usb_get_function_instance("SourceSink");
	if (IS_ERR(func_inst_ss))
		return PTR_ERR(func_inst_ss);

	ss_opts =  container_of(func_inst_ss, struct f_ss_opts, func_inst);
	ss_opts->pattern = gzero_options.pattern;
	ss_opts->isoc_interval = gzero_options.isoc_interval;
	ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket;
	ss_opts->isoc_mult = gzero_options.isoc_mult;
	ss_opts->isoc_maxburst = gzero_options.isoc_maxburst;
	ss_opts->bulk_buflen = gzero_options.bulk_buflen;

	func_ss = usb_get_function(func_inst_ss);
	if (IS_ERR(func_ss)) {
		status = PTR_ERR(func_ss);
		goto err_put_func_inst_ss;
	}

	func_inst_lb = usb_get_function_instance("Loopback");
	if (IS_ERR(func_inst_lb)) {
		status = PTR_ERR(func_inst_lb);
		goto err_put_func_ss;
	}

	lb_opts = container_of(func_inst_lb, struct f_lb_opts, func_inst);
	lb_opts->bulk_buflen = gzero_options.bulk_buflen;
	lb_opts->qlen = gzero_options.qlen;

	func_lb = usb_get_function(func_inst_lb);
	if (IS_ERR(func_lb)) {
		status = PTR_ERR(func_lb);
		goto err_put_func_inst_lb;
	}

	sourcesink_driver.iConfiguration = strings_dev[USB_GZERO_SS_DESC].id;
	loopback_driver.iConfiguration = strings_dev[USB_GZERO_LB_DESC].id;

	/* support autoresume for remote wakeup testing */
	sourcesink_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
	loopback_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
	sourcesink_driver.descriptors = NULL;
	loopback_driver.descriptors = NULL;
	if (autoresume) {
		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
		autoresume_step_ms = autoresume * 1000;
	}

	/* support OTG systems */
	if (gadget_is_otg(cdev->gadget)) {
		if (!otg_desc[0]) {
			struct usb_descriptor_header *usb_desc;

			usb_desc = usb_otg_descriptor_alloc(cdev->gadget);
			if (!usb_desc) {
				status = -ENOMEM;
				goto err_conf_flb;
			}
			usb_otg_descriptor_init(cdev->gadget, usb_desc);
			otg_desc[0] = usb_desc;
			otg_desc[1] = NULL;
		}
		sourcesink_driver.descriptors = otg_desc;
		sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
		loopback_driver.descriptors = otg_desc;
		loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
	}

	/* Register primary, then secondary configuration.  Note that
	 * SH3 only allows one config...
	 */
	if (loopdefault) {
		usb_add_config_only(cdev, &loopback_driver);
		usb_add_config_only(cdev, &sourcesink_driver);
	} else {
		usb_add_config_only(cdev, &sourcesink_driver);
		usb_add_config_only(cdev, &loopback_driver);
	}
	status = usb_add_function(&sourcesink_driver, func_ss);
	if (status)
		goto err_free_otg_desc;

	usb_ep_autoconfig_reset(cdev->gadget);
	status = usb_add_function(&loopback_driver, func_lb);
	if (status)
		goto err_free_otg_desc;

	usb_ep_autoconfig_reset(cdev->gadget);
	usb_composite_overwrite_options(cdev, &coverwrite);

	INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);

	return 0;

err_free_otg_desc:
	kfree(otg_desc[0]);
	otg_desc[0] = NULL;
err_conf_flb:
	usb_put_function(func_lb);
	func_lb = NULL;
err_put_func_inst_lb:
	usb_put_function_instance(func_inst_lb);
	func_inst_lb = NULL;
err_put_func_ss:
	usb_put_function(func_ss);
	func_ss = NULL;
err_put_func_inst_ss:
	usb_put_function_instance(func_inst_ss);
	func_inst_ss = NULL;
	return status;
}
Exemple #25
0
/**
 * uvc_bind_config - add a UVC function to a configuration
 * @c: the configuration to support the UVC instance
 * Context: single threaded during gadget setup
 *
 * Returns zero on success, else negative errno.
 *
 * Caller must have called @uvc_setup(). Caller is also responsible for
 * calling @uvc_cleanup() before module unload.
 */
int __init
uvc_bind_config(struct usb_configuration *c,
		const struct uvc_descriptor_header * const *control,
		const struct uvc_descriptor_header * const *fs_streaming,
		const struct uvc_descriptor_header * const *hs_streaming)
{
	struct uvc_device *uvc;
	int ret = 0;

	/* TODO Check if the USB device controller supports the required
	 * features.
	 */
	if (!gadget_is_dualspeed(c->cdev->gadget))
		return -EINVAL;

	uvc = kzalloc(sizeof(*uvc), GFP_KERNEL);
	if (uvc == NULL)
		return -ENOMEM;

	uvc->state = UVC_STATE_DISCONNECTED;

	/* Validate the descriptors. */
	if (control == NULL || control[0] == NULL ||
	    control[0]->bDescriptorSubType != UVC_VC_HEADER)
		goto error;

	if (fs_streaming == NULL || fs_streaming[0] == NULL ||
	    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
		goto error;

	if (hs_streaming == NULL || hs_streaming[0] == NULL ||
	    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
		goto error;

	uvc->desc.control = control;
	uvc->desc.fs_streaming = fs_streaming;
	uvc->desc.hs_streaming = hs_streaming;

	/* Allocate string descriptor numbers. */
	if ((ret = usb_string_id(c->cdev)) < 0)
		goto error;
	uvc_en_us_strings[UVC_STRING_ASSOCIATION_IDX].id = ret;
	uvc_iad.iFunction = ret;

	if ((ret = usb_string_id(c->cdev)) < 0)
		goto error;
	uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id = ret;
	uvc_control_intf.iInterface = ret;

	if ((ret = usb_string_id(c->cdev)) < 0)
		goto error;
	uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id = ret;
	uvc_streaming_intf_alt0.iInterface = ret;
	uvc_streaming_intf_alt1.iInterface = ret;

	/* Register the function. */
	uvc->func.name = "uvc";
	uvc->func.strings = uvc_function_strings;
	uvc->func.bind = uvc_function_bind;
	uvc->func.unbind = uvc_function_unbind;
	uvc->func.get_alt = uvc_function_get_alt;
	uvc->func.set_alt = uvc_function_set_alt;
	uvc->func.disable = uvc_function_disable;
	uvc->func.setup = uvc_function_setup;

	ret = usb_add_function(c, &uvc->func);
	if (ret)
		kfree(uvc);

	return 0;

error:
	kfree(uvc);
	return ret;
}
Exemple #26
0
/**
 * ecm_bind_config - add CDC Ethernet network link to a configuration
 * @c: the configuration to support the network link
 * @ethaddr: a buffer in which the ethernet address of the host side
 *	side of the link was recorded
 * Context: single threaded during gadget setup
 *
 * Returns zero on success, else negative errno.
 *
 * Caller must have called @gether_setup().  Caller is also responsible
 * for calling @gether_cleanup() before module unload.
 */
int
ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
{
	struct f_ecm	*ecm;
	int		status;
	
	if (!can_support_ecm(c->cdev->gadget) || !ethaddr)
		return -EINVAL;

	/* maybe allocate device-global string IDs */
	if (ecm_string_defs[0].id == 0) {

		/* control interface label */
		status = 5;

		if (status < 0)
			return status;
		ecm_string_defs[0].id = status;
		ecm_control_intf.iInterface = status;

#ifdef CONFIG_LGE_USB_GADGET_DRIVER
		/* MAC address */
		status = usb_string_id(c->cdev);
		if (status < 0)
			return status;
		ecm_string_defs[1].id = status;
		pr_info("%s: iMACAddress = %d\n", __func__, status);
		ecm_desc.iMACAddress = status;
#endif

		/* data interface label */
		status = usb_string_id(c->cdev);
		if (status < 0)
			return status;
		ecm_string_defs[2].id = status;
		ecm_data_intf.iInterface = status;

/* NOTE : if NOT defined */
#ifndef CONFIG_LGE_USB_GADGET_DRIVER

		/* MAC address */
		status = usb_string_id(c->cdev);
		if (status < 0)
			return status;
		ecm_string_defs[1].id = status;
		ecm_desc.iMACAddress = status;
#endif
	}

	/* allocate and initialize one new instance */
	ecm = kzalloc(sizeof *ecm, GFP_KERNEL);
	if (!ecm)
		return -ENOMEM;

	/* export host's Ethernet address in CDC format */
	snprintf(ecm->ethaddr, sizeof ecm->ethaddr,
		"%02X%02X%02X%02X%02X%02X",
		ethaddr[0], ethaddr[1], ethaddr[2],
		ethaddr[3], ethaddr[4], ethaddr[5]);
	ecm_string_defs[1].s = ecm->ethaddr;

	ecm->port.cdc_filter = DEFAULT_FILTER;

#ifdef CONFIG_LGE_USB_GADGET_DRIVER
        ecm->port.func.name = "ecm";
#else
	ecm->port.func.name = "cdc_ethernet";
#endif
	ecm->port.func.strings = ecm_strings;
	/* descriptors are per-instance copies */
	ecm->port.func.bind = ecm_bind;
	ecm->port.func.unbind = ecm_unbind;
	ecm->port.func.set_alt = ecm_set_alt;
	ecm->port.func.get_alt = ecm_get_alt;
	ecm->port.func.setup = ecm_setup;
	ecm->port.func.disable = ecm_disable;
	ecm->port.func.suspend = ecm_suspend;
	ecm->port.func.resume  = ecm_resume;

	status = usb_add_function(c, &ecm->port.func);
	if (status) {
		ecm_string_defs[1].s = NULL;
		kfree(ecm);
	}
	return status;
}
int  mtp_function_add(struct usb_composite_dev *cdev,
	struct usb_configuration *c)
#endif
{
	int ret = 0;
	int status;

	init_waitqueue_head(&g_usb_mtp_context.rx_wq);
	init_waitqueue_head(&g_usb_mtp_context.tx_wq);
	init_waitqueue_head(&g_usb_mtp_context.ctl_rx_wq);
	init_waitqueue_head(&g_usb_mtp_context.ctl_tx_wq);

	INIT_LIST_HEAD(&g_usb_mtp_context.rx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.rx_done_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.tx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_reqs);
	INIT_LIST_HEAD(&g_usb_mtp_context.ctl_rx_done_reqs);

	status = usb_string_id(c->cdev);
	if (status >= 0) {
		mtp_string_defs[STRING_INTERFACE].id = status;
        intf_desc.iInterface = status;
	}

	mtp_string_defs[STRING_MTP].id = mtp_ext_str_idx;

#ifdef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT
    g_usb_mtp_context.cdev = c->cdev;
#else
	g_usb_mtp_context.cdev = cdev;
#endif
	g_usb_mtp_context.function.name = "mtp";
	g_usb_mtp_context.function.descriptors = fs_mtp_descs;
	g_usb_mtp_context.function.hs_descriptors = hs_mtp_descs;
	g_usb_mtp_context.function.strings = mtp_strings;
	g_usb_mtp_context.function.bind = mtp_function_bind;
	g_usb_mtp_context.function.unbind = mtp_function_unbind;
	g_usb_mtp_context.function.setup = mtp_function_setup;
	g_usb_mtp_context.function.set_alt = mtp_function_set_alt;
	g_usb_mtp_context.function.disable = mtp_function_disable;

#ifndef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT
	ret = mtp_function_init();
	if (ret)
		goto mtp_exit;

	ret = misc_register(&mtp_enable_device);
	if (ret)
		goto misc_deregister;
#endif

#ifdef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT
	/* start disabled */
	g_usb_mtp_context.function.disabled = 1;
#endif

	ret = usb_add_function(c, &g_usb_mtp_context.function);
	if (ret) {
		mtp_err("MTP gadget driver failed to initialize\n");
		return ret;
	}

	return 0;

#ifndef CONFIG_LGE_USB_GADGET_FUNC_BIND_ONLY_INIT
mtp_misc_deregister:
	misc_deregister(&mtp_enable_device);
mtp_exit:
	mtp_function_exit();
	return ret;
#endif

}
Exemple #28
0
static int __init nokia_bind_config(struct usb_configuration *c)
{
	struct usb_function *f_acm;
	struct usb_function *f_phonet = NULL;
	struct usb_function *f_obex1 = NULL;
	struct usb_function *f_ecm;
	struct usb_function *f_obex2 = NULL;
	int status = 0;
	int obex1_stat = -1;
	int obex2_stat = -1;
	int phonet_stat = -1;

	if (!IS_ERR(fi_phonet)) {
		f_phonet = usb_get_function(fi_phonet);
		if (IS_ERR(f_phonet))
			pr_debug("could not get phonet function\n");
	}

	if (!IS_ERR(fi_obex1)) {
		f_obex1 = usb_get_function(fi_obex1);
		if (IS_ERR(f_obex1))
			pr_debug("could not get obex function 0\n");
	}

	if (!IS_ERR(fi_obex2)) {
		f_obex2 = usb_get_function(fi_obex2);
		if (IS_ERR(f_obex2))
			pr_debug("could not get obex function 1\n");
	}

	f_acm = usb_get_function(fi_acm);
	if (IS_ERR(f_acm)) {
		status = PTR_ERR(f_acm);
		goto err_get_acm;
	}

	f_ecm = usb_get_function(fi_ecm);
	if (IS_ERR(f_ecm)) {
		status = PTR_ERR(f_ecm);
		goto err_get_ecm;
	}

	if (!IS_ERR_OR_NULL(f_phonet)) {
		phonet_stat = usb_add_function(c, f_phonet);
		if (phonet_stat)
			pr_debug("could not add phonet function\n");
	}

	if (!IS_ERR_OR_NULL(f_obex1)) {
		obex1_stat = usb_add_function(c, f_obex1);
		if (obex1_stat)
			pr_debug("could not add obex function 0\n");
	}

	if (!IS_ERR_OR_NULL(f_obex2)) {
		obex2_stat = usb_add_function(c, f_obex2);
		if (obex2_stat)
			pr_debug("could not add obex function 1\n");
	}

	status = usb_add_function(c, f_acm);
	if (status)
		goto err_conf;

	status = usb_add_function(c, f_ecm);
	if (status) {
		pr_debug("could not bind ecm config %d\n", status);
		goto err_ecm;
	}
	if (c == &nokia_config_500ma_driver) {
		f_acm_cfg1 = f_acm;
		f_ecm_cfg1 = f_ecm;
		f_phonet_cfg1 = f_phonet;
		f_obex1_cfg1 = f_obex1;
		f_obex2_cfg1 = f_obex2;
	} else {
		f_acm_cfg2 = f_acm;
		f_ecm_cfg2 = f_ecm;
		f_phonet_cfg2 = f_phonet;
		f_obex1_cfg2 = f_obex1;
		f_obex2_cfg2 = f_obex2;
	}

	return status;
err_ecm:
	usb_remove_function(c, f_acm);
err_conf:
	if (!obex2_stat)
		usb_remove_function(c, f_obex2);
	if (!obex1_stat)
		usb_remove_function(c, f_obex1);
	if (!phonet_stat)
		usb_remove_function(c, f_phonet);
	usb_put_function(f_ecm);
err_get_ecm:
	usb_put_function(f_acm);
err_get_acm:
	if (!IS_ERR_OR_NULL(f_obex2))
		usb_put_function(f_obex2);
	if (!IS_ERR_OR_NULL(f_obex1))
		usb_put_function(f_obex1);
	if (!IS_ERR_OR_NULL(f_phonet))
		usb_put_function(f_phonet);
	return status;
}
Exemple #29
0
/**
 * gser_bind_config - add a generic serial function to a configuration
 * @c: the configuration to support the serial instance
 * @port_num: /dev/ttyGS* port this interface will use
 * Context: single threaded during gadget setup
 *
 * Returns zero on success, else negative errno.
 *
 * Caller must have called @gserial_setup() with enough ports to
 * handle all the ones it binds.  Caller is also responsible
 * for calling @gserial_cleanup() before module unload.
 */
int gser_bind_config(struct usb_configuration *c, u8 port_num)
{
	struct f_gser	*gser;
	int		status;
	struct port_info *p = &gserial_ports[port_num];

	if (p->func_type == USB_FSER_FUNC_NONE) {
		pr_info("%s: non function port : %d\n", __func__, port_num);
		return 0;
	}
	pr_info("%s: type:%d, trasport: %s\n", __func__, p->func_type,
			transport_to_str(p->transport));

	/* REVISIT might want instance-specific strings to help
	 * distinguish instances ...
	 */

	/* maybe allocate device-global string ID */
	/* HTC modem port_num is 0 */
#if 0
	if (port_num != 0) {
		if (gser_string_defs[0].id == 0) {
			status = usb_string_id(c->cdev);
			if (status < 0)
				return status;
			gser_string_defs[0].id = status;
		}
	}
#endif

	if (modem_string_defs[0].id == 0 &&
			p->func_type == USB_FSER_FUNC_MODEM) {
		status = usb_string_id(c->cdev);
		if (status < 0) {
			printk(KERN_ERR "%s: return %d\n", __func__, status);
			return status;
		}
		modem_string_defs[0].id = status;
	}

	if (modem_string_defs[1].id == 0 &&
			p->func_type == USB_FSER_FUNC_MODEM_MDM) {
		status = usb_string_id(c->cdev);
		if (status < 0) {
			printk(KERN_ERR "%s: return %d\n", __func__, status);
			return status;
		}
		modem_string_defs[1].id = status;
	}

	if (gser_string_defs[0].id == 0 &&
			(p->func_type == USB_FSER_FUNC_SERIAL
			|| p->func_type == USB_FSER_FUNC_AUTOBOT)) {
		status = usb_string_id(c->cdev);
		if (status < 0) {
			printk(KERN_ERR "%s: return %d\n", __func__, status);
			return status;
		}
		gser_string_defs[0].id = status;
	}

	/* allocate and initialize one new instance */
	gser = kzalloc(sizeof *gser, GFP_KERNEL);
	if (!gser)
		return -ENOMEM;

#ifdef CONFIG_MODEM_SUPPORT
	spin_lock_init(&gser->lock);
#endif
	gser->port_num = port_num;

	gser->port.func.name = "gser";
	gser->port.func.strings = gser_strings;
	gser->port.func.bind = gser_bind;
	gser->port.func.unbind = gser_unbind;
	gser->port.func.set_alt = gser_set_alt;
	gser->port.func.disable = gser_disable;
	gser->transport		= gserial_ports[port_num].transport;
#ifdef CONFIG_MODEM_SUPPORT
	/* We support only two ports for now */
	if (port_num == 0) {
		gser->port.func.name = "modem";
	} else
		gser->port.func.name = "nmea";


	gser->port.func.setup = gser_setup;
	gser->port.connect = gser_connect;
	gser->port.get_dtr = gser_get_dtr;
	gser->port.get_rts = gser_get_rts;
	gser->port.send_carrier_detect = gser_send_carrier_detect;
	gser->port.send_ring_indicator = gser_send_ring_indicator;
	gser->port.send_modem_ctrl_bits = gser_send_modem_ctrl_bits;
	gser->port.disconnect = gser_disconnect;
	gser->port.send_break = gser_send_break;
#endif

	switch (p->func_type) {
	case USB_FSER_FUNC_MODEM:
		gser->port.func.name = "modem";
		gser->port.func.strings = modem_strings;
		gser_interface_desc.iInterface = modem_string_defs[0].id;
		break;
	case USB_FSER_FUNC_MODEM_MDM:
		gser->port.func.name = "modem_mdm";
		gser->port.func.strings = modem_strings;
		gser_interface_desc.iInterface = modem_string_defs[1].id;
		break;
	case USB_FSER_FUNC_SERIAL:
	case USB_FSER_FUNC_AUTOBOT:
		gser->port.func.name = "serial";
		gser->port.func.strings = gser_strings;
		gser_interface_desc.iInterface = gser_string_defs[0].id;
		break;
	case USB_FSER_FUNC_NONE:
	default	:
		break;
	}


	status = usb_add_function(c, &gser->port.func);
	if (status)
		kfree(gser);
	return status;
}
Exemple #30
0
/**
 * uvc_bind_config - add a UVC function to a configuration
 * @c: the configuration to support the UVC instance
 * Context: single threaded during gadget setup
 *
 * Returns zero on success, else negative errno.
 *
 * Caller must have called @uvc_setup(). Caller is also responsible for
 * calling @uvc_cleanup() before module unload.
 */
int __init
uvc_bind_config(struct usb_configuration *c,
		const struct uvc_descriptor_header * const *fs_control,
		const struct uvc_descriptor_header * const *ss_control,
		const struct uvc_descriptor_header * const *fs_streaming,
		const struct uvc_descriptor_header * const *hs_streaming,
		const struct uvc_descriptor_header * const *ss_streaming)
{
	struct uvc_device *uvc;
	int ret = 0;

	/* TODO Check if the USB device controller supports the required
	 * features.
	 */
	if (!gadget_is_dualspeed(c->cdev->gadget))
		return -EINVAL;

	uvc = kzalloc(sizeof(*uvc), GFP_KERNEL);
	if (uvc == NULL)
		return -ENOMEM;

	uvc->state = UVC_STATE_DISCONNECTED;

	/* Validate the descriptors. */
	if (fs_control == NULL || fs_control[0] == NULL ||
	    fs_control[0]->bDescriptorSubType != UVC_VC_HEADER)
		goto error;

	if (ss_control == NULL || ss_control[0] == NULL ||
	    ss_control[0]->bDescriptorSubType != UVC_VC_HEADER)
		goto error;

	if (fs_streaming == NULL || fs_streaming[0] == NULL ||
	    fs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
		goto error;

	if (hs_streaming == NULL || hs_streaming[0] == NULL ||
	    hs_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
		goto error;

	if (ss_streaming == NULL || ss_streaming[0] == NULL ||
	    ss_streaming[0]->bDescriptorSubType != UVC_VS_INPUT_HEADER)
		goto error;

	uvc->desc.fs_control = fs_control;
	uvc->desc.ss_control = ss_control;
	uvc->desc.fs_streaming = fs_streaming;
	uvc->desc.hs_streaming = hs_streaming;
	uvc->desc.ss_streaming = ss_streaming;

	/* String descriptors are global, we only need to allocate string IDs
	 * for the first UVC function. UVC functions beyond the first (if any)
	 * will reuse the same IDs.
	 */
	if (uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id == 0) {
		ret = usb_string_ids_tab(c->cdev, uvc_en_us_strings);
		if (ret)
			goto error;
		uvc_iad.iFunction =
			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
		uvc_control_intf.iInterface =
			uvc_en_us_strings[UVC_STRING_CONTROL_IDX].id;
		ret = uvc_en_us_strings[UVC_STRING_STREAMING_IDX].id;
		uvc_streaming_intf_alt0.iInterface = ret;
		uvc_streaming_intf_alt1.iInterface = ret;
	}

	/* Register the function. */
	uvc->func.name = "uvc";
	uvc->func.strings = uvc_function_strings;
	uvc->func.bind = uvc_function_bind;
	uvc->func.unbind = uvc_function_unbind;
	uvc->func.get_alt = uvc_function_get_alt;
	uvc->func.set_alt = uvc_function_set_alt;
	uvc->func.disable = uvc_function_disable;
	uvc->func.setup = uvc_function_setup;

	ret = usb_add_function(c, &uvc->func);
	if (ret)
		kfree(uvc);

	return ret;

error:
	kfree(uvc);
	return ret;
}