diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-14 14:57:16 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-14 14:57:16 -0800 |
commit | e7cf773d431a63a2417902696fcc9e0ebdc83bbe (patch) | |
tree | 86dbdceb7d91226507a3af0d57e03b0ca664b22e /drivers/usb/gadget/legacy | |
parent | 7a02d089695a1217992434f03a78aa32bad85b5c (diff) | |
parent | 81e1dadfb5b2d47aa513ad60b1c9cf0ea17b6514 (diff) |
Merge tag 'usb-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
Pull USB updates from Greg KH:
"Here's the big set of USB and PHY patches for 3.19-rc1.
The normal churn in the USB gadget area is in here, as well as xhci
and other individual USB driver updates. The PHY tree is also in
here, as there were dependancies on the USB tree.
All of these have been in linux-next"
* tag 'usb-3.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (351 commits)
arm: omap3: twl: remove usb phy init data
usbip: fix error handling in stub_probe()
usb: gadget: udc: missing curly braces
USB: mos7720: delete some unneeded code
wusb: replace memset by memzero_explicit
usbip: remove unneeded structure
usb: xhci: fix comment for PORT_DEV_REMOVE
xhci: don't use the same variable for stopped and halted rings current TD
xhci: clear extra bits from slot context when setting max exit latency
xhci: cleanup finish_td function
USB: adutux: NULL dereferences on disconnect
usb: chipidea: fix platform_no_drv_owner.cocci warnings
usb: chipidea: Fixed a few typos in comments
Documentation: bindings: add doc for the USB2 ChipIdea USB driver
usb: chipidea: add a usb2 driver for ci13xxx
usb: chipidea: fix phy handling
usb: chipidea: remove duplicate dev_set_drvdata for host_start
usb: chipidea: parameter 'mode' isn't needed for hw_device_reset
usb: chipidea: add controller reset API
usb: chipidea: remove flag CI_HDRC_REQUIRE_TRANSCEIVER
...
Diffstat (limited to 'drivers/usb/gadget/legacy')
-rw-r--r-- | drivers/usb/gadget/legacy/Kconfig | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/dbgp.c | 26 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/gmidi.c | 43 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/hid.c | 79 | ||||
-rw-r--r-- | drivers/usb/gadget/legacy/printer.c | 65 |
5 files changed, 168 insertions, 47 deletions
diff --git a/drivers/usb/gadget/legacy/Kconfig b/drivers/usb/gadget/legacy/Kconfig index 24392d269709..fd48ef3af4eb 100644 --- a/drivers/usb/gadget/legacy/Kconfig +++ b/drivers/usb/gadget/legacy/Kconfig @@ -287,6 +287,7 @@ config USB_MIDI_GADGET depends on SND select USB_LIBCOMPOSITE select SND_RAWMIDI + select USB_F_MIDI help The MIDI Gadget acts as a USB Audio device, with one MIDI input and one MIDI output. These MIDI jacks appear as @@ -419,6 +420,7 @@ endif # TTY config USB_G_HID tristate "HID Gadget" select USB_LIBCOMPOSITE + select USB_F_HID help The HID gadget driver provides generic emulation of USB Human Interface Devices (HID). diff --git a/drivers/usb/gadget/legacy/dbgp.c b/drivers/usb/gadget/legacy/dbgp.c index 1b075132f8f1..633683a72a11 100644 --- a/drivers/usb/gadget/legacy/dbgp.c +++ b/drivers/usb/gadget/legacy/dbgp.c @@ -237,7 +237,7 @@ static void dbgp_unbind(struct usb_gadget *gadget) static unsigned char tty_line; #endif -static int __init dbgp_configure_endpoints(struct usb_gadget *gadget) +static int dbgp_configure_endpoints(struct usb_gadget *gadget) { int stp; @@ -273,19 +273,10 @@ static int __init dbgp_configure_endpoints(struct usb_gadget *gadget) dbgp.serial->in->desc = &i_desc; dbgp.serial->out->desc = &o_desc; - - if (gserial_alloc_line(&tty_line)) { - stp = 3; - goto fail_3; - } +#endif return 0; -fail_3: - dbgp.o_ep->driver_data = NULL; -#else - return 0; -#endif fail_2: dbgp.i_ep->driver_data = NULL; fail_1: @@ -324,10 +315,17 @@ static int __init dbgp_bind(struct usb_gadget *gadget, err = -ENOMEM; goto fail; } + + if (gserial_alloc_line(&tty_line)) { + stp = 4; + err = -ENODEV; + goto fail; + } #endif + err = dbgp_configure_endpoints(gadget); if (err < 0) { - stp = 4; + stp = 5; goto fail; } @@ -383,6 +381,10 @@ static int dbgp_setup(struct usb_gadget *gadget, #ifdef CONFIG_USB_G_DBGP_PRINTK err = dbgp_enable_ep(); #else + err = dbgp_configure_endpoints(gadget); + if (err < 0) { + goto fail; + } err = gserial_connect(dbgp.serial, tty_line); #endif if (err < 0) diff --git a/drivers/usb/gadget/legacy/gmidi.c b/drivers/usb/gadget/legacy/gmidi.c index 3d696b86ff76..e02a095294ac 100644 --- a/drivers/usb/gadget/legacy/gmidi.c +++ b/drivers/usb/gadget/legacy/gmidi.c @@ -37,7 +37,7 @@ #include "gadget_chips.h" -#include "f_midi.c" +#include "u_midi.h" /*-------------------------------------------------------------------------*/ @@ -115,8 +115,13 @@ static struct usb_gadget_strings *dev_strings[] = { NULL, }; +static struct usb_function_instance *fi_midi; +static struct usb_function *f_midi; + static int __exit midi_unbind(struct usb_composite_dev *dev) { + usb_put_function(f_midi); + usb_put_function_instance(fi_midi); return 0; } @@ -130,28 +135,54 @@ static struct usb_configuration midi_config = { static int __init midi_bind_config(struct usb_configuration *c) { - return f_midi_bind_config(c, index, id, - in_ports, out_ports, - buflen, qlen); + 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 __init midi_bind(struct usb_composite_dev *cdev) { + struct f_midi_opts *midi_opts; int status; + fi_midi = usb_get_function_instance("midi"); + if (IS_ERR(fi_midi)) + return PTR_ERR(fi_midi); + + midi_opts = container_of(fi_midi, struct f_midi_opts, func_inst); + midi_opts->index = index; + midi_opts->id = id; + midi_opts->in_ports = in_ports; + midi_opts->out_ports = out_ports; + midi_opts->buflen = buflen; + midi_opts->qlen = qlen; + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) - return status; + goto put; device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; midi_config.iConfiguration = strings_dev[STRING_DESCRIPTION_IDX].id; status = usb_add_config(cdev, &midi_config, midi_bind_config); if (status < 0) - return status; + goto put; usb_composite_overwrite_options(cdev, &coverwrite); pr_info("%s\n", longname); return 0; +put: + usb_put_function_instance(fi_midi); + return status; } static __refdata struct usb_composite_driver midi_driver = { diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c index 778613eb37af..633fe7e07688 100644 --- a/drivers/usb/gadget/legacy/hid.c +++ b/drivers/usb/gadget/legacy/hid.c @@ -17,11 +17,14 @@ #include <linux/list.h> #include <linux/module.h> #include <linux/usb/composite.h> +#include <linux/usb/g_hid.h> #include "gadget_chips.h" #define DRIVER_DESC "HID Gadget" #define DRIVER_VERSION "2010/03/16" +#include "u_hid.h" + /*-------------------------------------------------------------------------*/ #define HIDG_VENDOR_NUM 0x0525 /* XXX NetChip */ @@ -29,17 +32,9 @@ /*-------------------------------------------------------------------------*/ -/* - * kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ -#include "f_hid.c" - - struct hidg_func_node { + struct usb_function_instance *fi; + struct usb_function *f; struct list_head node; struct hidg_func_descriptor *func; }; @@ -113,8 +108,8 @@ static struct usb_gadget_strings *dev_strings[] = { static int __init do_config(struct usb_configuration *c) { - struct hidg_func_node *e; - int func = 0, status = 0; + struct hidg_func_node *e, *n; + int status = 0; if (gadget_is_otg(c->cdev->gadget)) { c->descriptors = otg_desc; @@ -122,11 +117,24 @@ static int __init do_config(struct usb_configuration *c) } list_for_each_entry(e, &hidg_func_list, node) { - status = hidg_bind_config(c, e->func, func++); - if (status) - break; + e->f = usb_get_function(e->fi); + if (IS_ERR(e->f)) + goto put; + status = usb_add_function(c, e->f); + if (status < 0) { + usb_put_function(e->f); + goto put; + } } + return 0; +put: + list_for_each_entry(n, &hidg_func_list, node) { + if (n == e) + break; + usb_remove_function(c, n->f); + usb_put_function(n->f); + } return status; } @@ -143,6 +151,8 @@ static int __init hid_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; struct list_head *tmp; + struct hidg_func_node *n, *m; + struct f_hid_opts *hid_opts; int status, funcs = 0; list_for_each(tmp, &hidg_func_list) @@ -151,10 +161,20 @@ static int __init hid_bind(struct usb_composite_dev *cdev) if (!funcs) return -ENODEV; - /* set up HID */ - status = ghid_setup(cdev->gadget, funcs); - if (status < 0) - return status; + list_for_each_entry(n, &hidg_func_list, node) { + n->fi = usb_get_function_instance("hid"); + if (IS_ERR(n->fi)) { + status = PTR_ERR(n->fi); + goto put; + } + hid_opts = container_of(n->fi, struct f_hid_opts, func_inst); + hid_opts->subclass = n->func->subclass; + hid_opts->protocol = n->func->protocol; + hid_opts->report_length = n->func->report_length; + hid_opts->report_desc_length = n->func->report_desc_length; + hid_opts->report_desc = n->func->report_desc; + } + /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. @@ -162,24 +182,37 @@ static int __init hid_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) - return status; + goto put; device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; /* register our configuration */ status = usb_add_config(cdev, &config_driver, do_config); if (status < 0) - return status; + goto put; usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); return 0; + +put: + list_for_each_entry(m, &hidg_func_list, node) { + if (m == n) + break; + usb_put_function_instance(m->fi); + } + return status; } static int __exit hid_unbind(struct usb_composite_dev *cdev) { - ghid_cleanup(); + struct hidg_func_node *n; + + list_for_each_entry(n, &hidg_func_list, node) { + usb_put_function(n->f); + usb_put_function_instance(n->fi); + } return 0; } @@ -260,7 +293,7 @@ module_init(hidg_init); static void __exit hidg_cleanup(void) { - platform_driver_unregister(&hidg_plat_driver); usb_composite_unregister(&hidg_driver); + platform_driver_unregister(&hidg_plat_driver); } module_exit(hidg_cleanup); diff --git a/drivers/usb/gadget/legacy/printer.c b/drivers/usb/gadget/legacy/printer.c index 6474081dcbaf..90545980542f 100644 --- a/drivers/usb/gadget/legacy/printer.c +++ b/drivers/usb/gadget/legacy/printer.c @@ -208,6 +208,43 @@ static struct usb_descriptor_header *hs_printer_function[] = { NULL }; +/* + * Added endpoint descriptors for 3.0 devices + */ + +static struct usb_endpoint_descriptor ss_ep_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor ss_ep_in_comp_desc = { + .bLength = sizeof(ss_ep_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, +}; + +static struct usb_endpoint_descriptor ss_ep_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor ss_ep_out_comp_desc = { + .bLength = sizeof(ss_ep_out_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, +}; + +static struct usb_descriptor_header *ss_printer_function[] = { + (struct usb_descriptor_header *) &intf_desc, + (struct usb_descriptor_header *) &ss_ep_in_desc, + (struct usb_descriptor_header *) &ss_ep_in_comp_desc, + (struct usb_descriptor_header *) &ss_ep_out_desc, + (struct usb_descriptor_header *) &ss_ep_out_comp_desc, + NULL +}; + static struct usb_otg_descriptor otg_descriptor = { .bLength = sizeof otg_descriptor, .bDescriptorType = USB_DT_OTG, @@ -220,7 +257,20 @@ static const struct usb_descriptor_header *otg_desc[] = { }; /* maxpacket and other transfer characteristics vary by speed. */ -#define ep_desc(g, hs, fs) (((g)->speed == USB_SPEED_HIGH)?(hs):(fs)) +static inline struct usb_endpoint_descriptor *ep_desc(struct usb_gadget *gadget, + struct usb_endpoint_descriptor *fs, + struct usb_endpoint_descriptor *hs, + struct usb_endpoint_descriptor *ss) +{ + switch (gadget->speed) { + case USB_SPEED_SUPER: + return ss; + case USB_SPEED_HIGH: + return hs; + default: + return fs; + } +} /*-------------------------------------------------------------------------*/ @@ -793,11 +843,12 @@ set_printer_interface(struct printer_dev *dev) { int result = 0; - dev->in_ep->desc = ep_desc(dev->gadget, &hs_ep_in_desc, &fs_ep_in_desc); + dev->in_ep->desc = ep_desc(dev->gadget, &fs_ep_in_desc, &hs_ep_in_desc, + &ss_ep_in_desc); dev->in_ep->driver_data = dev; - dev->out_ep->desc = ep_desc(dev->gadget, &hs_ep_out_desc, - &fs_ep_out_desc); + dev->out_ep->desc = ep_desc(dev->gadget, &fs_ep_out_desc, + &hs_ep_out_desc, &ss_ep_out_desc); dev->out_ep->driver_data = dev; result = usb_ep_enable(dev->in_ep); @@ -1016,9 +1067,11 @@ autoconf_fail: /* assumes that all endpoints are dual-speed */ hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; + ss_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; + ss_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; ret = usb_assign_descriptors(f, fs_printer_function, - hs_printer_function, NULL); + hs_printer_function, ss_printer_function); if (ret) return ret; @@ -1253,7 +1306,7 @@ static __refdata struct usb_composite_driver printer_driver = { .name = shortname, .dev = &device_desc, .strings = dev_strings, - .max_speed = USB_SPEED_HIGH, + .max_speed = USB_SPEED_SUPER, .bind = printer_bind, .unbind = printer_unbind, }; |