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; }
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; }
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; }
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; }
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; }
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); }
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; }
/* * 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; } }
/* * 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; }
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; }
/* * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
/* * 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; }
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; }
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; }
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; }
/** * 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; }
/** * 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 }
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; }
/** * 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; }
/** * 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; }