[PATCH v3 32/36] usb: gadget: f_phonet: conversion to new API

From: Robert Baldyga
Date: Fri Dec 11 2015 - 06:27:53 EST


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-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/