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 __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 __init msg_do_config(struct usb_configuration *c) { static const struct fsg_operations ops = { .thread_exits = msg_thread_exits, }; static struct fsg_common common; struct fsg_common *retp; struct fsg_config config; int ret; if (gadget_is_otg(c->cdev->gadget)) { c->descriptors = otg_desc; c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } fsg_config_from_params(&config, &mod_data); config.ops = &ops; retp = fsg_common_init(&common, c->cdev, &config); if (IS_ERR(retp)) return PTR_ERR(retp); ret = fsg_bind_config(c->cdev, c, &common); fsg_common_put(&common); return ret; }
static int __init 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, hostaddr); if (ret < 0) return ret; ret = acm_bind_config(c, 0); if (ret < 0) return ret; ret = fsg_add(c->cdev, c, fsg_common); if (ret < 0) return ret; if (ret < 0) return ret; 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; } #ifdef CONFIG_USB_MITs status = acm_bind_config(c, 0); if (status < 0) return status; status = ecm_bind_config(c, hostaddr); if (status < 0) return status; #else status = ecm_bind_config(c, hostaddr); if (status < 0) return status; status = acm_bind_config(c, 0); if (status < 0) return status; #endif return 0; }
static int __init gs_bind(struct usb_composite_dev *cdev) { int status; struct usb_gadget *gadget = cdev->gadget; /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ if (gadget->vendor_id && gadget->product_id) { device_desc.idVendor = cpu_to_le16(gadget->vendor_id); device_desc.idProduct = cpu_to_le16(gadget->product_id); } else { device_desc.idVendor = cpu_to_le16(GS_VENDOR_ID); if (use_acm) device_desc.idProduct = cpu_to_le16(GS_CDC_PRODUCT_ID); else device_desc.idProduct = cpu_to_le16(GS_PRODUCT_ID); } strings_dev[USB_GADGET_MANUFACTURER_IDX].s = gadget->manufacturer; strings_dev[USB_GADGET_PRODUCT_IDX].s = gadget->productname; status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; status = strings_dev[STRING_DESCRIPTION_IDX].id; serial_config_driver.iConfiguration = status; if (gadget_is_otg(cdev->gadget)) { serial_config_driver.descriptors = otg_desc; serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } /* register our configuration */ if (use_acm) { status = serial_register_ports(cdev, &serial_config_driver, "acm"); usb_ep_autoconfig_reset(cdev->gadget); } else if (use_obex) status = serial_register_ports(cdev, &serial_config_driver, "obex"); else { status = serial_register_ports(cdev, &serial_config_driver, "gser"); } if (status < 0) goto fail; usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "%s\n", GS_VERSION_NAME); return 0; fail: return status; }
static int gs_bind(struct usb_composite_dev *cdev) { 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) goto fail; device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; status = strings_dev[STRING_DESCRIPTION_IDX].id; serial_config_driver.iConfiguration = status; 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 fail; } usb_otg_descriptor_init(cdev->gadget, usb_desc); otg_desc[0] = usb_desc; otg_desc[1] = NULL; } serial_config_driver.descriptors = otg_desc; serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } /* register our configuration */ if (use_acm) { status = serial_register_ports(cdev, &serial_config_driver, "acm"); usb_ep_autoconfig_reset(cdev->gadget); } else if (use_obex) status = serial_register_ports(cdev, &serial_config_driver, "obex"); else { status = serial_register_ports(cdev, &serial_config_driver, "gser"); } if (status < 0) goto fail1; usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "%s\n", GS_VERSION_NAME); return 0; fail1: kfree(otg_desc[0]); otg_desc[0] = NULL; fail: return status; }
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 __init ncm_do_config(struct usb_configuration *c) { /* */ if (gadget_is_otg(c->cdev->gadget)) { c->descriptors = otg_desc; c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } return ncm_bind_config(c, hostaddr); }
/* * We may not have an RNDIS configuration, but if we do it needs to be * the first one present. That's to make Microsoft's drivers happy, * and to follow DOCSIS 1.0 (cable modem standard). */ static int __init rndis_do_config(struct usb_configuration *c) { /* 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; } return rndis_bind_config(c, hostaddr, 0, manufacturer); }
/* * We may not have an RNDIS configuration, but if we do it needs to be * the first one present. That's to make Microsoft's drivers happy, * and to follow DOCSIS 1.0 (cable modem standard). */ static int __init rndis_do_config(struct usb_configuration *c) { /* 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; } return rndis_bind_config(c, hostaddr, cpu_to_le16(CDC_VENDOR_NUM), strings_dev[STRING_MANUFACTURER_IDX].s); }
static int __init audio_do_config(struct usb_configuration *c) { /* 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; } audio_bind_config(c); return 0; }
static int __gfs_do_config(struct usb_configuration *c, int (*eth)(struct usb_configuration *c, u8 *ethaddr), u8 *ethaddr) { int ret; int index = 0; if (WARN_ON(!gfs_ffs_data)) return -ENODEV; if (gadget_is_otg(c->cdev->gadget)) { c->descriptors = gfs_otg_desc; c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } if (eth) { ret = eth(c, ethaddr); if (unlikely(ret < 0)) return ret; } ret = functionfs_add(c->cdev, c, gfs_ffs_data); if (unlikely(ret < 0)) return ret; /* After previous do_configs there may be some invalid * pointers in c->interface array. This happens every time * a user space function with fewer interfaces than a user * space function that was run before the new one is run. The * compasit's set_config() assumes that if there is no more * then MAX_CONFIG_INTERFACES interfaces in a configuration * then there is a NULL pointer after the last interface in * c->interface array. We need to make sure this is true. */ if (c->next_interface_id < ARRAY_SIZE(c->interface)) { c->interface[c->next_interface_id] = NULL; printk(KERN_ERR "=== usb_interface index = %d\n", c->next_interface_id); dump_stack(); for( index = 0 ; index < c->next_inteface_id ; index++ ) { printk(KERN_ERR "index = %d , function = %x \n", index , c->interface[index] ); } } return 0; }
/* * We _always_ have an ECM or CDC Subset configuration. */ static int __init eth_do_config(struct usb_configuration *c) { /* 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 (can_support_ecm(c->cdev->gadget)) return ecm_bind_config(c, hostaddr); else return geth_bind_config(c, hostaddr); }
/* * change our operational config. must agree with the code * that returns config descriptors, and altsetting code. */ static int fastboot_set_config(struct fastboot_dev *dev, unsigned number, gfp_t gfp_flags) { int result = 0; struct usb_gadget *gadget = dev->gadget; fastboot_reset_config(dev); switch (number) { case DEV_CONFIG_VALUE: result = set_fastboot_config(dev, gfp_flags); break; default: result = -EINVAL; /* FALL THROUGH */ case 0: break; } if (result) { if (number) fastboot_reset_config(dev); usb_gadget_vbus_draw(dev->gadget, gadget_is_otg(dev->gadget) ? 8 : 100); } else { char *speed; unsigned power; power = 2 * fastboot_config.bMaxPower; usb_gadget_vbus_draw(dev->gadget, power); switch (gadget->speed) { case USB_SPEED_FULL: speed = "full"; break; #ifdef CONFIG_USB_GADGET_DUALSPEED case USB_SPEED_HIGH: speed = "high"; break; #endif default: speed = "?"; break; } dev->config = number; debug("%s speed config #%d: %d mA, %s\n", speed, number, power, driver_desc); } return result; }
static int __init eth_do_config(struct usb_configuration *c) { if (gadget_is_otg(c->cdev->gadget)) { c->descriptors = otg_desc; c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } if (use_eem) return eem_bind_config(c); else if (can_support_ecm(c->cdev->gadget)) return ecm_bind_config(c, hostaddr); else return geth_bind_config(c, hostaddr); }
/* * 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 __init acm_ms_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; } status = acm_bind_config(c, 0); if (status < 0) return status; status = fsg_bind_config(c->cdev, c, &fsg_common); if (status < 0) return status; return 0; }
static int __init msg_do_config(struct usb_configuration *c) { struct fsg_common *common; struct fsg_config config; int ret; if (gadget_is_otg(c->cdev->gadget)) { c->descriptors = otg_desc; c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } fsg_config_from_params(&config, &mod_data); config.thread_exits = (void(*)(struct fsg_common*))&msg_cleanup; common = fsg_common_init(0, c->cdev, &config); if (IS_ERR(common)) return PTR_ERR(common); ret = fsg_add(c->cdev, c, common); fsg_common_put(common); return ret; }
/* * 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; }
/* * config descriptors are also handcrafted. these must agree with code * that sets configurations, and with code managing interfaces and their * altsettings. other complexity may come from: * * - high speed support, including "other speed config" rules * - multiple configurations * - interfaces with alternate settings * - embedded class or vendor-specific descriptors * * this handles high speed, and has a second config that could as easily * have been an alternate interface setting (on most hardware). * * NOTE: to demonstrate (and test) more USB capabilities, this driver * should include an altsetting to test interrupt transfers, including * high bandwidth modes at high speed. (Maybe work like Intel's test * device?) */ static int config_buf(struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index) { int is_source_sink; int len; const struct usb_descriptor_header **function; int hs = 0; /* two configurations will always be index 0 and index 1 */ if (index > 1) return -EINVAL; is_source_sink = loopdefault ? (index == 1) : (index == 0); if (gadget_is_dualspeed(gadget)) { hs = (gadget->speed == USB_SPEED_HIGH); if (type == USB_DT_OTHER_SPEED_CONFIG) hs = !hs; } if (hs) function = is_source_sink ? hs_source_sink_function : hs_loopback_function; else function = is_source_sink ? fs_source_sink_function : fs_loopback_function; /* for now, don't advertise srp-only devices */ if (!gadget_is_otg(gadget)) function++; len = usb_gadget_config_buf(is_source_sink ? &source_sink_config : &loopback_config, buf, USB_BUFSIZ, function); if (len < 0) return len; ((struct usb_config_descriptor *) buf)->bDescriptorType = type; return len; }
/* * 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; }
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; }
static int __init gs_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; int status; status = gserial_setup(cdev->gadget, n_ports); if (status < 0) return status; /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ /* device description: manufacturer, product */ snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); status = usb_string_id(cdev); if (status < 0) goto fail; strings_dev[STRING_MANUFACTURER_IDX].id = status; device_desc.iManufacturer = status; status = usb_string_id(cdev); if (status < 0) goto fail; strings_dev[STRING_PRODUCT_IDX].id = status; device_desc.iProduct = status; /* config description */ status = usb_string_id(cdev); if (status < 0) goto fail; strings_dev[STRING_DESCRIPTION_IDX].id = status; serial_config_driver.iConfiguration = status; /* set up other descriptors */ gcnum = usb_gadget_controller_number(gadget); if (gcnum >= 0) device_desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM | gcnum); else { /* this is so simple (for now, no altsettings) that it * SHOULD NOT have problems with bulk-capable hardware. * so warn about unrcognized controllers -- don't panic. * * things like configuration and altsetting numbering * can need hardware-specific attention though. */ pr_warning("gs_bind: controller '%s' not recognized\n", gadget->name); device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM | 0x0099); } if (gadget_is_otg(cdev->gadget)) { serial_config_driver.descriptors = otg_desc; serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } /* register our configuration */ status = usb_add_config(cdev, &serial_config_driver); if (status < 0) goto fail; INFO(cdev, "%s\n", GS_VERSION_NAME); return 0; fail: gserial_cleanup(); 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; }
static int __init zero_bind(struct usb_gadget *gadget) { struct zero_dev *dev; struct usb_ep *ep; int gcnum; /* FIXME this can't yet work right with SH ... it has only * one configuration, numbered one. */ if (gadget_is_sh(gadget)) return -ENODEV; /* Bulk-only drivers like this one SHOULD be able to * autoconfigure on any sane usb controller driver, * but there may also be important quirks to address. */ usb_ep_autoconfig_reset(gadget); ep = usb_ep_autoconfig(gadget, &fs_source_desc); if (!ep) { autoconf_fail: pr_err("%s: can't autoconfigure on %s\n", shortname, gadget->name); return -ENODEV; } EP_IN_NAME = ep->name; ep->driver_data = ep; /* claim */ ep = usb_ep_autoconfig(gadget, &fs_sink_desc); if (!ep) goto autoconf_fail; EP_OUT_NAME = ep->name; ep->driver_data = ep; /* claim */ gcnum = usb_gadget_controller_number(gadget); if (gcnum >= 0) device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); else { /* gadget zero is so simple (for now, no altsettings) that * it SHOULD NOT have problems with bulk-capable hardware. * so warn about unrcognized controllers, don't panic. * * things like configuration and altsetting numbering * can need hardware-specific attention though. */ pr_warning("%s: controller '%s' not recognized\n", shortname, gadget->name); device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); } /* ok, we made sense of the hardware ... */ dev = kzalloc(sizeof(*dev), GFP_KERNEL); if (!dev) return -ENOMEM; spin_lock_init(&dev->lock); dev->gadget = gadget; set_gadget_data(gadget, dev); init_timer(&dev->resume); dev->resume.function = zero_autoresume; dev->resume.data = (unsigned long) dev; /* preallocate control response and buffer */ dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); if (!dev->req) goto enomem; dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); if (!dev->req->buf) goto enomem; dev->req->complete = zero_setup_complete; device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; if (gadget_is_dualspeed(gadget)) { /* assume ep0 uses the same value for both speeds ... */ dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; /* and that all endpoints are dual-speed */ hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; } if (gadget_is_otg(gadget)) { otg_descriptor.bmAttributes |= USB_OTG_HNP, source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } usb_gadget_set_selfpowered(gadget); if (autoresume) { source_sink_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; loopback_config.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } gadget->ep0->driver_data = dev; INFO(dev, "%s, version: " DRIVER_VERSION "\n", longname); INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, EP_OUT_NAME, EP_IN_NAME); snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); return 0; enomem: zero_unbind(gadget); return -ENOMEM; }
static int __init gs_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; int status; status = gserial_setup(cdev->gadget, n_ports); if (status < 0) return status; snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); status = usb_string_id(cdev); if (status < 0) goto fail; strings_dev[STRING_MANUFACTURER_IDX].id = status; device_desc.iManufacturer = status; status = usb_string_id(cdev); if (status < 0) goto fail; strings_dev[STRING_PRODUCT_IDX].id = status; device_desc.iProduct = status; status = usb_string_id(cdev); if (status < 0) goto fail; strings_dev[STRING_DESCRIPTION_IDX].id = status; serial_config_driver.iConfiguration = status; gcnum = usb_gadget_controller_number(gadget); if (gcnum >= 0) device_desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM | gcnum); else { pr_warning("gs_bind: controller '%s' not recognized\n", gadget->name); device_desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM | 0x0099); } if (gadget_is_otg(cdev->gadget)) { serial_config_driver.descriptors = otg_desc; serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } status = usb_add_config(cdev, &serial_config_driver); if (status < 0) goto fail; INFO(cdev, "%s\n", GS_VERSION_NAME); return 0; fail: gserial_cleanup(); return status; }
static int acm_ms_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; struct fsg_opts *opts; struct fsg_config config; int status; f_acm_inst = usb_get_function_instance("acm"); if (IS_ERR(f_acm_inst)) return PTR_ERR(f_acm_inst); fi_msg = usb_get_function_instance("mass_storage"); if (IS_ERR(fi_msg)) { status = PTR_ERR(fi_msg); goto fail_get_msg; } /* set up mass storage function */ fsg_config_from_params(&config, &fsg_mod_data, fsg_num_buffers); opts = fsg_opts_from_func_inst(fi_msg); opts->no_configfs = true; status = fsg_common_set_num_buffers(opts->common, fsg_num_buffers); if (status) goto fail; status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); if (status) goto fail_set_cdev; fsg_common_set_sysfs(opts->common, true); status = fsg_common_create_luns(opts->common, &config); if (status) goto fail_set_cdev; fsg_common_set_inquiry_string(opts->common, config.vendor_name, config.product_name); /* * 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) goto fail_string_ids; device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; if (gadget_is_otg(gadget) && !otg_desc[0]) { struct usb_descriptor_header *usb_desc; usb_desc = usb_otg_descriptor_alloc(gadget); if (!usb_desc) goto fail_string_ids; usb_otg_descriptor_init(gadget, usb_desc); otg_desc[0] = usb_desc; otg_desc[1] = NULL; } /* register our configuration */ status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config); if (status < 0) goto fail_otg_desc; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); return 0; /* error recovery */ fail_otg_desc: kfree(otg_desc[0]); otg_desc[0] = NULL; fail_string_ids: fsg_common_remove_luns(opts->common); fail_set_cdev: fsg_common_free_buffers(opts->common); fail: usb_put_function_instance(fi_msg); fail_get_msg: usb_put_function_instance(f_acm_inst); return status; }