diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 93217fc86c12..a5f67e14daf2 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -508,6 +508,9 @@ config USB_U_SERIAL config USB_F_SERIAL tristate +config USB_F_OBEX + tristate + choice tristate "USB Gadget Drivers" default USB_ETH diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 34bb49a131e9..6afd16659e78 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -43,6 +43,8 @@ obj-$(CONFIG_USB_F_SS_LB) += usb_f_ss_lb.o obj-$(CONFIG_USB_U_SERIAL) += u_serial.o usb_f_serial-y := f_serial.o obj-$(CONFIG_USB_F_SERIAL) += usb_f_serial.o +usb_f_obex-y := f_obex.o +obj-$(CONFIG_USB_F_OBEX) += usb_f_obex.o # # USB gadget drivers diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 36a004563b82..439b666120c2 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c @@ -72,7 +72,7 @@ static struct usb_gadget_strings *obex_strings[] = { /*-------------------------------------------------------------------------*/ -static struct usb_interface_descriptor obex_control_intf __initdata = { +static struct usb_interface_descriptor obex_control_intf = { .bLength = sizeof(obex_control_intf), .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = 0, @@ -83,7 +83,7 @@ static struct usb_interface_descriptor obex_control_intf __initdata = { .bInterfaceSubClass = USB_CDC_SUBCLASS_OBEX, }; -static struct usb_interface_descriptor obex_data_nop_intf __initdata = { +static struct usb_interface_descriptor obex_data_nop_intf = { .bLength = sizeof(obex_data_nop_intf), .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = 1, @@ -93,7 +93,7 @@ static struct usb_interface_descriptor obex_data_nop_intf __initdata = { .bInterfaceClass = USB_CLASS_CDC_DATA, }; -static struct usb_interface_descriptor obex_data_intf __initdata = { +static struct usb_interface_descriptor obex_data_intf = { .bLength = sizeof(obex_data_intf), .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = 2, @@ -103,14 +103,14 @@ static struct usb_interface_descriptor obex_data_intf __initdata = { .bInterfaceClass = USB_CLASS_CDC_DATA, }; -static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = { +static struct usb_cdc_header_desc obex_cdc_header_desc = { .bLength = sizeof(obex_cdc_header_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, .bcdCDC = cpu_to_le16(0x0120), }; -static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { +static struct usb_cdc_union_desc obex_cdc_union_desc = { .bLength = sizeof(obex_cdc_union_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_UNION_TYPE, @@ -118,7 +118,7 @@ static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { .bSlaveInterface0 = 2, }; -static struct usb_cdc_obex_desc obex_desc __initdata = { +static struct usb_cdc_obex_desc obex_desc = { .bLength = sizeof(obex_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_OBEX_TYPE, @@ -127,7 +127,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = { /* High-Speed Support */ -static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { +static struct usb_endpoint_descriptor obex_hs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -136,7 +136,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { +static struct usb_endpoint_descriptor obex_hs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -145,7 +145,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_descriptor_header *hs_function[] __initdata = { +static struct usb_descriptor_header *hs_function[] = { (struct usb_descriptor_header *) &obex_control_intf, (struct usb_descriptor_header *) &obex_cdc_header_desc, (struct usb_descriptor_header *) &obex_desc, @@ -160,7 +160,7 @@ static struct usb_descriptor_header *hs_function[] __initdata = { /* Full-Speed Support */ -static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = { +static struct usb_endpoint_descriptor obex_fs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -168,7 +168,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = { +static struct usb_endpoint_descriptor obex_fs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, @@ -176,7 +176,7 @@ static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = { .bmAttributes = USB_ENDPOINT_XFER_BULK, }; -static struct usb_descriptor_header *fs_function[] __initdata = { +static struct usb_descriptor_header *fs_function[] = { (struct usb_descriptor_header *) &obex_control_intf, (struct usb_descriptor_header *) &obex_cdc_header_desc, (struct usb_descriptor_header *) &obex_desc, @@ -290,14 +290,43 @@ static void obex_disconnect(struct gserial *g) /*-------------------------------------------------------------------------*/ -static int __init -obex_bind(struct usb_configuration *c, struct usb_function *f) +/* Some controllers can't support CDC OBEX ... */ +static inline bool can_support_obex(struct usb_configuration *c) +{ + /* Since the first interface is a NOP, we can ignore the + * issue of multi-interface support on most controllers. + * + * Altsettings are mandatory, however... + */ + if (!gadget_supports_altsettings(c->cdev->gadget)) + return false; + + /* everything else is *probably* fine ... */ + return true; +} + +static int obex_bind(struct usb_configuration *c, struct usb_function *f) { struct usb_composite_dev *cdev = c->cdev; struct f_obex *obex = func_to_obex(f); int status; struct usb_ep *ep; + if (!can_support_obex(c)) + return -EINVAL; + + if (obex_string_defs[OBEX_CTRL_IDX].id == 0) { + status = usb_string_ids_tab(c->cdev, obex_string_defs); + if (status < 0) + return status; + obex_control_intf.iInterface = + obex_string_defs[OBEX_CTRL_IDX].id; + + status = obex_string_defs[OBEX_DATA_IDX].id; + obex_data_nop_intf.iInterface = status; + obex_data_intf.iInterface = status; + } + /* allocate instance-specific interface IDs, and patch descriptors */ status = usb_interface_id(c, f); @@ -376,29 +405,16 @@ fail: return status; } +#ifdef USBF_OBEX_INCLUDED + static void -obex_unbind(struct usb_configuration *c, struct usb_function *f) +obex_old_unbind(struct usb_configuration *c, struct usb_function *f) { obex_string_defs[OBEX_CTRL_IDX].id = 0; usb_free_all_descriptors(f); kfree(func_to_obex(f)); } -/* Some controllers can't support CDC OBEX ... */ -static inline bool can_support_obex(struct usb_configuration *c) -{ - /* Since the first interface is a NOP, we can ignore the - * issue of multi-interface support on most controllers. - * - * Altsettings are mandatory, however... - */ - if (!gadget_supports_altsettings(c->cdev->gadget)) - return false; - - /* everything else is *probably* fine ... */ - return true; -} - /** * obex_bind_config - add a CDC OBEX function to a configuration * @c: the configuration to support the CDC OBEX instance @@ -412,21 +428,6 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num) struct f_obex *obex; int status; - if (!can_support_obex(c)) - return -EINVAL; - - if (obex_string_defs[OBEX_CTRL_IDX].id == 0) { - status = usb_string_ids_tab(c->cdev, obex_string_defs); - if (status < 0) - return status; - obex_control_intf.iInterface = - obex_string_defs[OBEX_CTRL_IDX].id; - - status = obex_string_defs[OBEX_DATA_IDX].id; - obex_data_nop_intf.iInterface = status; - obex_data_intf.iInterface = status; - } - /* allocate and initialize one new instance */ obex = kzalloc(sizeof *obex, GFP_KERNEL); if (!obex) @@ -441,7 +442,7 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num) obex->port.func.strings = obex_strings; /* descriptors are per-instance copies */ obex->port.func.bind = obex_bind; - obex->port.func.unbind = obex_unbind; + obex->port.func.unbind = obex_old_unbind; obex->port.func.set_alt = obex_set_alt; obex->port.func.get_alt = obex_get_alt; obex->port.func.disable = obex_disable; @@ -453,5 +454,83 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num) return status; } +#else + +static void obex_free_inst(struct usb_function_instance *f) +{ + struct f_serial_opts *opts; + + opts = container_of(f, struct f_serial_opts, func_inst); + gserial_free_line(opts->port_num); + kfree(opts); +} + +static struct usb_function_instance *obex_alloc_inst(void) +{ + struct f_serial_opts *opts; + int ret; + + opts = kzalloc(sizeof(*opts), GFP_KERNEL); + if (!opts) + return ERR_PTR(-ENOMEM); + + opts->func_inst.free_func_inst = obex_free_inst; + ret = gserial_alloc_line(&opts->port_num); + if (ret) { + kfree(opts); + return ERR_PTR(ret); + } + + return &opts->func_inst; +} + +static void obex_free(struct usb_function *f) +{ + struct f_obex *obex; + + obex = func_to_obex(f); + kfree(obex); +} + +static void obex_unbind(struct usb_configuration *c, struct usb_function *f) +{ + obex_string_defs[OBEX_CTRL_IDX].id = 0; + usb_free_all_descriptors(f); +} + +struct usb_function *obex_alloc(struct usb_function_instance *fi) +{ + struct f_obex *obex; + struct f_serial_opts *opts; + + /* allocate and initialize one new instance */ + obex = kzalloc(sizeof(*obex), GFP_KERNEL); + if (!obex) + return ERR_PTR(-ENOMEM); + + opts = container_of(fi, struct f_serial_opts, func_inst); + + obex->port_num = opts->port_num; + + obex->port.connect = obex_connect; + obex->port.disconnect = obex_disconnect; + + obex->port.func.name = "obex"; + obex->port.func.strings = obex_strings; + /* descriptors are per-instance copies */ + obex->port.func.bind = obex_bind; + obex->port.func.unbind = obex_unbind; + obex->port.func.set_alt = obex_set_alt; + obex->port.func.get_alt = obex_get_alt; + obex->port.func.disable = obex_disable; + obex->port.func.free_func = obex_free; + + return &obex->port.func; +} + +DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc); + +#endif + MODULE_AUTHOR("Felipe Balbi"); MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index f829a80f27f6..eebdd0e0b1d6 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -37,7 +37,7 @@ * 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_ecm.c" +#define USBF_OBEX_INCLUDED #include "f_obex.c" #include "f_phonet.c" #include "u_ether.c" diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 9d215c4c2275..664da6493239 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -36,6 +36,7 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ +#define USBF_OBEX_INCLUDED #include "f_obex.c" /*-------------------------------------------------------------------------*/