Generate descriptors in new format and attach them to USB function in prep_descs(). Implement prep_vendor_descs() to supply class specific descriptors. Change set_alt() implementation and implement clear_alt() operation. Remove boilerplate code. Signed-off-by: Robert Baldyga <r.baldyga@xxxxxxxxxxx> --- drivers/usb/gadget/function/f_phonet.c | 225 +++++++++++---------------------- 1 file changed, 75 insertions(+), 150 deletions(-) diff --git a/drivers/usb/gadget/function/f_phonet.c b/drivers/usb/gadget/function/f_phonet.c index 157441d..da35b77 100644 --- a/drivers/usb/gadget/function/f_phonet.c +++ b/drivers/usb/gadget/function/f_phonet.c @@ -162,29 +162,19 @@ pn_hs_source_desc = { .wMaxPacketSize = cpu_to_le16(512), }; -static struct usb_descriptor_header *fs_pn_function[] = { - (struct usb_descriptor_header *) &pn_control_intf_desc, - (struct usb_descriptor_header *) &pn_header_desc, - (struct usb_descriptor_header *) &pn_phonet_desc, - (struct usb_descriptor_header *) &pn_union_desc, - (struct usb_descriptor_header *) &pn_data_nop_intf_desc, - (struct usb_descriptor_header *) &pn_data_intf_desc, - (struct usb_descriptor_header *) &pn_fs_sink_desc, - (struct usb_descriptor_header *) &pn_fs_source_desc, - NULL, -}; +USB_COMPOSITE_ENDPOINT(ep_sink, &pn_fs_sink_desc, + &pn_hs_sink_desc, NULL, NULL); +USB_COMPOSITE_ENDPOINT(ep_source, &pn_fs_source_desc, + &pn_hs_source_desc, NULL, NULL); -static struct usb_descriptor_header *hs_pn_function[] = { - (struct usb_descriptor_header *) &pn_control_intf_desc, - (struct usb_descriptor_header *) &pn_header_desc, - (struct usb_descriptor_header *) &pn_phonet_desc, - (struct usb_descriptor_header *) &pn_union_desc, - (struct usb_descriptor_header *) &pn_data_nop_intf_desc, - (struct usb_descriptor_header *) &pn_data_intf_desc, - (struct usb_descriptor_header *) &pn_hs_sink_desc, - (struct usb_descriptor_header *) &pn_hs_source_desc, - NULL, -}; +USB_COMPOSITE_ALTSETTING(intf0alt0, &pn_control_intf_desc); +USB_COMPOSITE_ALTSETTING(intf1alt0, &pn_data_nop_intf_desc); +USB_COMPOSITE_ALTSETTING(intf1alt1, &pn_data_intf_desc, &ep_sink, &ep_source); + +USB_COMPOSITE_INTERFACE(intf0, &intf0alt0); +USB_COMPOSITE_INTERFACE(intf1, &intf1alt0, &intf1alt1); + +USB_COMPOSITE_DESCRIPTORS(phonet_descs, &intf0, &intf1); /*-------------------------------------------------------------------------*/ @@ -391,8 +381,6 @@ static void __pn_reset(struct usb_function *f) netif_carrier_off(dev); port->usb = NULL; - usb_ep_disable(fp->out_ep); - usb_ep_disable(fp->in_ep); if (fp->rx.skb) { dev_kfree_skb_irq(fp->rx.skb); fp->rx.skb = NULL; @@ -402,20 +390,13 @@ static void __pn_reset(struct usb_function *f) static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct f_phonet *fp = func_to_pn(f); - struct usb_gadget *gadget = fp->function.config->cdev->gadget; - - if (intf == pn_control_intf_desc.bInterfaceNumber) - /* control interface, no altsetting */ - return (alt > 0) ? -EINVAL : 0; + int status, i; - if (intf == pn_data_intf_desc.bInterfaceNumber) { + if (intf == 0) { struct net_device *dev = fp->dev; struct phonet_port *port = netdev_priv(dev); /* data intf (0: inactive, 1: active) */ - if (alt > 1) - return -EINVAL; - spin_lock(&port->lock); if (fp->in_ep->enabled) @@ -424,72 +405,81 @@ static int pn_set_alt(struct usb_function *f, unsigned intf, unsigned alt) if (alt == 1) { int i; - if (config_ep_by_speed(gadget, f, fp->in_ep) || - config_ep_by_speed(gadget, f, fp->out_ep)) { - fp->in_ep->desc = NULL; - fp->out_ep->desc = NULL; - spin_unlock(&port->lock); - return -EINVAL; - } - usb_ep_enable(fp->out_ep); - usb_ep_enable(fp->in_ep); + fp->out_ep = usb_function_get_ep(f, intf, 0); + if (!fp->out_ep) + return -ENODEV; + fp->in_ep = usb_function_get_ep(f, intf, 1); + if (!fp->out_ep) + return -ENODEV; port->usb = fp; fp->out_ep->driver_data = fp; fp->in_ep->driver_data = fp; + /* Incoming USB requests */ + status = -ENOMEM; + for (i = 0; i < phonet_rxq_size; i++) { + struct usb_request *req; + + req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL); + if (!req) + goto err_req; + + req->complete = pn_rx_complete; + fp->out_reqv[i] = req; + } + + /* Outgoing USB requests */ + fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL); + if (!fp->in_req) + goto err_req; + netif_carrier_on(dev); for (i = 0; i < phonet_rxq_size; i++) pn_rx_submit(fp, fp->out_reqv[i], GFP_ATOMIC); } spin_unlock(&port->lock); - return 0; } - return -EINVAL; -} - -static int pn_get_alt(struct usb_function *f, unsigned intf) -{ - struct f_phonet *fp = func_to_pn(f); - - if (intf == pn_control_intf_desc.bInterfaceNumber) - return 0; - - if (intf == pn_data_intf_desc.bInterfaceNumber) { - struct phonet_port *port = netdev_priv(fp->dev); - u8 alt; - - spin_lock(&port->lock); - alt = port->usb != NULL; - spin_unlock(&port->lock); - return alt; - } + return 0; - return -EINVAL; +err_req: + for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++) + usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); + return status; } -static void pn_disconnect(struct usb_function *f) +static void pn_clear_alt(struct usb_function *f, unsigned intf, unsigned alt) { struct f_phonet *fp = func_to_pn(f); struct phonet_port *port = netdev_priv(fp->dev); unsigned long flags; + int i; /* remain disabled until set_alt */ spin_lock_irqsave(&port->lock, flags); __pn_reset(f); spin_unlock_irqrestore(&port->lock, flags); + + /* We are already disconnected */ + if (fp->in_req) + usb_ep_free_request(fp->in_ep, fp->in_req); + for (i = 0; i < phonet_rxq_size; i++) + if (fp->out_reqv[i]) + usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); } /*-------------------------------------------------------------------------*/ -static int pn_bind(struct usb_configuration *c, struct usb_function *f) +static int pn_prep_descs(struct usb_function *f) { - struct usb_composite_dev *cdev = c->cdev; - struct usb_gadget *gadget = cdev->gadget; - struct f_phonet *fp = func_to_pn(f); - struct usb_ep *ep; - int status, i; + return usb_function_set_descs(f, &phonet_descs); +} + +static int pn_prep_vendor_descs(struct usb_function *f) +{ + struct usb_composite_dev *cdev = f->config->cdev; + int status, intf0_id, intf1_id; struct f_phonet_opts *phonet_opts; @@ -503,78 +493,29 @@ static int pn_bind(struct usb_configuration *c, struct usb_function *f) * with regard to phonet_opts->bound access */ if (!phonet_opts->bound) { - gphonet_set_gadget(phonet_opts->net, gadget); + gphonet_set_gadget(phonet_opts->net, cdev->gadget); status = gphonet_register_netdev(phonet_opts->net); if (status) return status; phonet_opts->bound = true; } - /* Reserve interface IDs */ - status = usb_interface_id(c, f); - if (status < 0) - goto err; - pn_control_intf_desc.bInterfaceNumber = status; - pn_union_desc.bMasterInterface0 = status; - - status = usb_interface_id(c, f); - if (status < 0) - goto err; - pn_data_nop_intf_desc.bInterfaceNumber = status; - pn_data_intf_desc.bInterfaceNumber = status; - pn_union_desc.bSlaveInterface0 = status; - - /* Reserve endpoints */ - status = -ENODEV; - ep = usb_ep_autoconfig(gadget, &pn_fs_sink_desc); - if (!ep) - goto err; - fp->out_ep = ep; - - ep = usb_ep_autoconfig(gadget, &pn_fs_source_desc); - if (!ep) - goto err; - fp->in_ep = ep; - - pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress; - pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress; - - /* Do not try to bind Phonet twice... */ - status = usb_assign_descriptors(f, fs_pn_function, hs_pn_function, - NULL); - if (status) - goto err; - - /* Incoming USB requests */ - status = -ENOMEM; - for (i = 0; i < phonet_rxq_size; i++) { - struct usb_request *req; + intf0_id = usb_get_interface_id(f, 0); + intf1_id = usb_get_interface_id(f, 1); - req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL); - if (!req) - goto err_req; + pn_union_desc.bMasterInterface0 = intf0_id; + pn_union_desc.bSlaveInterface0 = intf1_id; - req->complete = pn_rx_complete; - fp->out_reqv[i] = req; - } + pn_data_intf_desc.bInterfaceNumber = intf1_id; - /* Outgoing USB requests */ - fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL); - if (!fp->in_req) - goto err_req; + usb_altset_add_vendor_desc(f, 0, 0, + (struct usb_descriptor_header *)&pn_header_desc); + usb_altset_add_vendor_desc(f, 0, 0, + (struct usb_descriptor_header *)&pn_phonet_desc); + usb_altset_add_vendor_desc(f, 0, 0, + (struct usb_descriptor_header *)&pn_union_desc); - INFO(cdev, "USB CDC Phonet function\n"); - INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name, - fp->out_ep->name, fp->in_ep->name); return 0; - -err_req: - for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++) - usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); - usb_free_all_descriptors(f); -err: - ERROR(cdev, "USB CDC Phonet: cannot autoconfigure\n"); - return status; } static inline struct f_phonet_opts *to_f_phonet_opts(struct config_item *item) @@ -654,21 +595,6 @@ static void phonet_free(struct usb_function *f) kfree(phonet); } -static void pn_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct f_phonet *fp = func_to_pn(f); - int i; - - /* We are already disconnected */ - if (fp->in_req) - usb_ep_free_request(fp->in_ep, fp->in_req); - for (i = 0; i < phonet_rxq_size; i++) - if (fp->out_reqv[i]) - usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); - - usb_free_all_descriptors(f); -} - static struct usb_function *phonet_alloc(struct usb_function_instance *fi) { struct f_phonet *fp; @@ -684,11 +610,10 @@ static struct usb_function *phonet_alloc(struct usb_function_instance *fi) fp->dev = opts->net; fp->function.name = "phonet"; - fp->function.bind = pn_bind; - fp->function.unbind = pn_unbind; + fp->function.prep_descs = pn_prep_descs; + fp->function.prep_vendor_descs = pn_prep_vendor_descs; fp->function.set_alt = pn_set_alt; - fp->function.get_alt = pn_get_alt; - fp->function.disable = pn_disconnect; + fp->function.clear_alt = pn_clear_alt; fp->function.free_func = phonet_free; spin_lock_init(&fp->rx.lock); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html