提交 10287bae 编写于 作者: S Sebastian Andrzej Siewior 提交者: Felipe Balbi

usb: gadget: always update HS/SS descriptors and create a copy of them

HS and SS descriptors are staticaly created. They are updated during the
bind process with the endpoint address, string id or interface numbers.

After that, the descriptor chain is linked to struct usb_function which
is used by composite in order to serve the GET_DESCRIPTOR requests,
number of available configs and so on.

There is no need to assign the HS descriptor only if the UDC supports
HS speed because composite won't report those to the host if HS support
has not been reached. The same reasoning is valid for SS.

This patch makes sure each function updates HS/SS descriptors
unconditionally and uses the newly introduced helper function to create a
copy the descriptors for the speed which is supported by the UDC.

While at that, also rename f->descriptors to f->fs_descriptors in order
to make it more explicit what that means.

Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: NSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: NFelipe Balbi <balbi@ti.com>
上级 0f9df939
...@@ -107,7 +107,7 @@ int config_ep_by_speed(struct usb_gadget *g, ...@@ -107,7 +107,7 @@ int config_ep_by_speed(struct usb_gadget *g,
} }
/* else: fall through */ /* else: fall through */
default: default:
speed_desc = f->descriptors; speed_desc = f->fs_descriptors;
} }
/* find descriptors */ /* find descriptors */
for_each_ep_desc(speed_desc, d_spd) { for_each_ep_desc(speed_desc, d_spd) {
...@@ -200,7 +200,7 @@ int usb_add_function(struct usb_configuration *config, ...@@ -200,7 +200,7 @@ int usb_add_function(struct usb_configuration *config,
* as full speed ... it's the function drivers that will need * as full speed ... it's the function drivers that will need
* to avoid bulk and ISO transfers. * to avoid bulk and ISO transfers.
*/ */
if (!config->fullspeed && function->descriptors) if (!config->fullspeed && function->fs_descriptors)
config->fullspeed = true; config->fullspeed = true;
if (!config->highspeed && function->hs_descriptors) if (!config->highspeed && function->hs_descriptors)
config->highspeed = true; config->highspeed = true;
...@@ -363,7 +363,7 @@ static int config_buf(struct usb_configuration *config, ...@@ -363,7 +363,7 @@ static int config_buf(struct usb_configuration *config,
descriptors = f->hs_descriptors; descriptors = f->hs_descriptors;
break; break;
default: default:
descriptors = f->descriptors; descriptors = f->fs_descriptors;
} }
if (!descriptors) if (!descriptors)
...@@ -620,7 +620,7 @@ static int set_config(struct usb_composite_dev *cdev, ...@@ -620,7 +620,7 @@ static int set_config(struct usb_composite_dev *cdev,
descriptors = f->hs_descriptors; descriptors = f->hs_descriptors;
break; break;
default: default:
descriptors = f->descriptors; descriptors = f->fs_descriptors;
} }
for (; *descriptors; ++descriptors) { for (; *descriptors; ++descriptors) {
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <linux/usb/gadget.h> #include <linux/usb/gadget.h>
#include <linux/usb/composite.h>
/** /**
* usb_descriptor_fillbuf - fill buffer with descriptors * usb_descriptor_fillbuf - fill buffer with descriptors
...@@ -158,3 +158,40 @@ usb_copy_descriptors(struct usb_descriptor_header **src) ...@@ -158,3 +158,40 @@ usb_copy_descriptors(struct usb_descriptor_header **src)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(usb_copy_descriptors); EXPORT_SYMBOL_GPL(usb_copy_descriptors);
int usb_assign_descriptors(struct usb_function *f,
struct usb_descriptor_header **fs,
struct usb_descriptor_header **hs,
struct usb_descriptor_header **ss)
{
struct usb_gadget *g = f->config->cdev->gadget;
if (fs) {
f->fs_descriptors = usb_copy_descriptors(fs);
if (!f->fs_descriptors)
goto err;
}
if (hs && gadget_is_dualspeed(g)) {
f->hs_descriptors = usb_copy_descriptors(hs);
if (!f->hs_descriptors)
goto err;
}
if (ss && gadget_is_superspeed(g)) {
f->ss_descriptors = usb_copy_descriptors(ss);
if (!f->ss_descriptors)
goto err;
}
return 0;
err:
usb_free_all_descriptors(f);
return -ENOMEM;
}
EXPORT_SYMBOL_GPL(usb_assign_descriptors);
void usb_free_all_descriptors(struct usb_function *f)
{
usb_free_descriptors(f->fs_descriptors);
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->ss_descriptors);
}
EXPORT_SYMBOL_GPL(usb_free_all_descriptors);
...@@ -658,37 +658,22 @@ acm_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -658,37 +658,22 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
acm->notify_req->complete = acm_cdc_notify_complete; acm->notify_req->complete = acm_cdc_notify_complete;
acm->notify_req->context = acm; acm->notify_req->context = acm;
/* copy descriptors */
f->descriptors = usb_copy_descriptors(acm_fs_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when /* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at * hardware is dual speed, all bulk-capable endpoints work at
* both speeds * both speeds
*/ */
if (gadget_is_dualspeed(c->cdev->gadget)) { acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
acm_hs_in_desc.bEndpointAddress = acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
acm_fs_in_desc.bEndpointAddress;
acm_hs_out_desc.bEndpointAddress =
acm_fs_out_desc.bEndpointAddress;
acm_hs_notify_desc.bEndpointAddress = acm_hs_notify_desc.bEndpointAddress =
acm_fs_notify_desc.bEndpointAddress; acm_fs_notify_desc.bEndpointAddress;
/* copy descriptors */ acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(acm_hs_function); acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress;
}
if (gadget_is_superspeed(c->cdev->gadget)) { status = usb_assign_descriptors(f, acm_fs_function, acm_hs_function,
acm_ss_in_desc.bEndpointAddress = acm_ss_function);
acm_fs_in_desc.bEndpointAddress; if (status)
acm_ss_out_desc.bEndpointAddress =
acm_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(acm_ss_function);
if (!f->ss_descriptors)
goto fail; goto fail;
}
DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
acm->port_num, acm->port_num,
...@@ -720,11 +705,7 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -720,11 +705,7 @@ acm_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
struct f_acm *acm = func_to_acm(f); struct f_acm *acm = func_to_acm(f);
if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_all_descriptors(f);
usb_free_descriptors(f->hs_descriptors);
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
usb_free_descriptors(f->descriptors);
gs_free_req(acm->notify, acm->notify_req); gs_free_req(acm->notify, acm->notify_req);
kfree(acm); kfree(acm);
} }
......
...@@ -743,42 +743,24 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -743,42 +743,24 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
ecm->notify_req->context = ecm; ecm->notify_req->context = ecm;
ecm->notify_req->complete = ecm_notify_complete; ecm->notify_req->complete = ecm_notify_complete;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(ecm_fs_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when /* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at * hardware is dual speed, all bulk-capable endpoints work at
* both speeds * both speeds
*/ */
if (gadget_is_dualspeed(c->cdev->gadget)) { hs_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
hs_ecm_in_desc.bEndpointAddress = hs_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
fs_ecm_in_desc.bEndpointAddress;
hs_ecm_out_desc.bEndpointAddress =
fs_ecm_out_desc.bEndpointAddress;
hs_ecm_notify_desc.bEndpointAddress = hs_ecm_notify_desc.bEndpointAddress =
fs_ecm_notify_desc.bEndpointAddress; fs_ecm_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */ ss_ecm_in_desc.bEndpointAddress = fs_ecm_in_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(ecm_hs_function); ss_ecm_out_desc.bEndpointAddress = fs_ecm_out_desc.bEndpointAddress;
if (!f->hs_descriptors)
goto fail;
}
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_ecm_in_desc.bEndpointAddress =
fs_ecm_in_desc.bEndpointAddress;
ss_ecm_out_desc.bEndpointAddress =
fs_ecm_out_desc.bEndpointAddress;
ss_ecm_notify_desc.bEndpointAddress = ss_ecm_notify_desc.bEndpointAddress =
fs_ecm_notify_desc.bEndpointAddress; fs_ecm_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */ status = usb_assign_descriptors(f, ecm_fs_function, ecm_hs_function,
f->ss_descriptors = usb_copy_descriptors(ecm_ss_function); ecm_ss_function);
if (!f->ss_descriptors) if (status)
goto fail; goto fail;
}
/* NOTE: all that is done without knowing or caring about /* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code * the network link ... which is unavailable to this code
...@@ -796,11 +778,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -796,11 +778,6 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
if (f->descriptors)
usb_free_descriptors(f->descriptors);
if (f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
if (ecm->notify_req) { if (ecm->notify_req) {
kfree(ecm->notify_req->buf); kfree(ecm->notify_req->buf);
usb_ep_free_request(ecm->notify, ecm->notify_req); usb_ep_free_request(ecm->notify, ecm->notify_req);
...@@ -826,11 +803,7 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -826,11 +803,7 @@ ecm_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "ecm unbind\n"); DBG(c->cdev, "ecm unbind\n");
if (gadget_is_superspeed(c->cdev->gadget)) usb_free_all_descriptors(f);
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
kfree(ecm->notify_req->buf); kfree(ecm->notify_req->buf);
usb_ep_free_request(ecm->notify, ecm->notify_req); usb_ep_free_request(ecm->notify, ecm->notify_req);
......
...@@ -274,38 +274,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -274,38 +274,20 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENOMEM; status = -ENOMEM;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(eem_fs_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when /* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at * hardware is dual speed, all bulk-capable endpoints work at
* both speeds * both speeds
*/ */
if (gadget_is_dualspeed(c->cdev->gadget)) { eem_hs_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
eem_hs_in_desc.bEndpointAddress = eem_hs_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
eem_fs_in_desc.bEndpointAddress;
eem_hs_out_desc.bEndpointAddress =
eem_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(eem_hs_function);
if (!f->hs_descriptors)
goto fail;
}
if (gadget_is_superspeed(c->cdev->gadget)) { eem_ss_in_desc.bEndpointAddress = eem_fs_in_desc.bEndpointAddress;
eem_ss_in_desc.bEndpointAddress = eem_ss_out_desc.bEndpointAddress = eem_fs_out_desc.bEndpointAddress;
eem_fs_in_desc.bEndpointAddress;
eem_ss_out_desc.bEndpointAddress =
eem_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */ status = usb_assign_descriptors(f, eem_fs_function, eem_hs_function,
f->ss_descriptors = usb_copy_descriptors(eem_ss_function); eem_ss_function);
if (!f->ss_descriptors) if (status)
goto fail; goto fail;
}
DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n", DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_superspeed(c->cdev->gadget) ? "super" :
...@@ -314,11 +296,7 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -314,11 +296,7 @@ eem_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
if (f->descriptors) usb_free_all_descriptors(f);
usb_free_descriptors(f->descriptors);
if (f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
if (eem->port.out_ep) if (eem->port.out_ep)
eem->port.out_ep->driver_data = NULL; eem->port.out_ep->driver_data = NULL;
if (eem->port.in_ep) if (eem->port.in_ep)
...@@ -336,11 +314,7 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -336,11 +314,7 @@ eem_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "eem unbind\n"); DBG(c->cdev, "eem unbind\n");
if (gadget_is_superspeed(c->cdev->gadget)) usb_free_all_descriptors(f);
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
kfree(eem); kfree(eem);
} }
......
...@@ -2097,7 +2097,7 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, ...@@ -2097,7 +2097,7 @@ static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep,
if (isHS) if (isHS)
func->function.hs_descriptors[(long)valuep] = desc; func->function.hs_descriptors[(long)valuep] = desc;
else else
func->function.descriptors[(long)valuep] = desc; func->function.fs_descriptors[(long)valuep] = desc;
if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT) if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT)
return 0; return 0;
...@@ -2249,7 +2249,7 @@ static int ffs_func_bind(struct usb_configuration *c, ...@@ -2249,7 +2249,7 @@ static int ffs_func_bind(struct usb_configuration *c,
* numbers without worrying that it may be described later on. * numbers without worrying that it may be described later on.
*/ */
if (likely(full)) { if (likely(full)) {
func->function.descriptors = data->fs_descs; func->function.fs_descriptors = data->fs_descs;
ret = ffs_do_descs(ffs->fs_descs_count, ret = ffs_do_descs(ffs->fs_descs_count,
data->raw_descs, data->raw_descs,
sizeof data->raw_descs, sizeof data->raw_descs,
......
...@@ -573,7 +573,6 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -573,7 +573,6 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
goto fail; goto fail;
hidg_interface_desc.bInterfaceNumber = status; hidg_interface_desc.bInterfaceNumber = status;
/* allocate instance-specific endpoints */ /* allocate instance-specific endpoints */
status = -ENODEV; status = -ENODEV;
ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc); ep = usb_ep_autoconfig(c->cdev->gadget, &hidg_fs_in_ep_desc);
...@@ -609,20 +608,15 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -609,20 +608,15 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
hidg_desc.desc[0].wDescriptorLength = hidg_desc.desc[0].wDescriptorLength =
cpu_to_le16(hidg->report_desc_length); cpu_to_le16(hidg->report_desc_length);
/* copy descriptors */
f->descriptors = usb_copy_descriptors(hidg_fs_descriptors);
if (!f->descriptors)
goto fail;
if (gadget_is_dualspeed(c->cdev->gadget)) {
hidg_hs_in_ep_desc.bEndpointAddress = hidg_hs_in_ep_desc.bEndpointAddress =
hidg_fs_in_ep_desc.bEndpointAddress; hidg_fs_in_ep_desc.bEndpointAddress;
hidg_hs_out_ep_desc.bEndpointAddress = hidg_hs_out_ep_desc.bEndpointAddress =
hidg_fs_out_ep_desc.bEndpointAddress; hidg_fs_out_ep_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(hidg_hs_descriptors);
if (!f->hs_descriptors) status = usb_assign_descriptors(f, hidg_fs_descriptors,
hidg_hs_descriptors, NULL);
if (status)
goto fail; goto fail;
}
mutex_init(&hidg->lock); mutex_init(&hidg->lock);
spin_lock_init(&hidg->spinlock); spin_lock_init(&hidg->spinlock);
...@@ -649,9 +643,7 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -649,9 +643,7 @@ static int __init hidg_bind(struct usb_configuration *c, struct usb_function *f)
usb_ep_free_request(hidg->in_ep, hidg->req); usb_ep_free_request(hidg->in_ep, hidg->req);
} }
usb_free_descriptors(f->hs_descriptors); usb_free_all_descriptors(f);
usb_free_descriptors(f->descriptors);
return status; return status;
} }
...@@ -668,9 +660,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -668,9 +660,7 @@ static void hidg_unbind(struct usb_configuration *c, struct usb_function *f)
kfree(hidg->req->buf); kfree(hidg->req->buf);
usb_ep_free_request(hidg->in_ep, hidg->req); usb_ep_free_request(hidg->in_ep, hidg->req);
/* free descriptors copies */ usb_free_all_descriptors(f);
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
kfree(hidg->report_desc); kfree(hidg->report_desc);
kfree(hidg); kfree(hidg);
......
...@@ -177,6 +177,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -177,6 +177,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev; struct usb_composite_dev *cdev = c->cdev;
struct f_loopback *loop = func_to_loop(f); struct f_loopback *loop = func_to_loop(f);
int id; int id;
int ret;
/* allocate interface ID(s) */ /* allocate interface ID(s) */
id = usb_interface_id(c, f); id = usb_interface_id(c, f);
...@@ -201,22 +202,19 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -201,22 +202,19 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
loop->out_ep->driver_data = cdev; /* claim */ loop->out_ep->driver_data = cdev; /* claim */
/* support high speed hardware */ /* support high speed hardware */
if (gadget_is_dualspeed(c->cdev->gadget)) {
hs_loop_source_desc.bEndpointAddress = hs_loop_source_desc.bEndpointAddress =
fs_loop_source_desc.bEndpointAddress; fs_loop_source_desc.bEndpointAddress;
hs_loop_sink_desc.bEndpointAddress = hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
fs_loop_sink_desc.bEndpointAddress;
f->hs_descriptors = hs_loopback_descs;
}
/* support super speed hardware */ /* support super speed hardware */
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_loop_source_desc.bEndpointAddress = ss_loop_source_desc.bEndpointAddress =
fs_loop_source_desc.bEndpointAddress; fs_loop_source_desc.bEndpointAddress;
ss_loop_sink_desc.bEndpointAddress = ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
fs_loop_sink_desc.bEndpointAddress;
f->ss_descriptors = ss_loopback_descs; ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs,
} ss_loopback_descs);
if (ret)
return ret;
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n", DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
(gadget_is_superspeed(c->cdev->gadget) ? "super" : (gadget_is_superspeed(c->cdev->gadget) ? "super" :
...@@ -228,6 +226,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -228,6 +226,7 @@ loopback_bind(struct usb_configuration *c, struct usb_function *f)
static void static void
loopback_unbind(struct usb_configuration *c, struct usb_function *f) loopback_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
usb_free_all_descriptors(f);
kfree(func_to_loop(f)); kfree(func_to_loop(f));
} }
...@@ -379,7 +378,6 @@ static int __init loopback_bind_config(struct usb_configuration *c) ...@@ -379,7 +378,6 @@ static int __init loopback_bind_config(struct usb_configuration *c)
return -ENOMEM; return -ENOMEM;
loop->function.name = "loopback"; loop->function.name = "loopback";
loop->function.descriptors = fs_loopback_descs;
loop->function.bind = loopback_bind; loop->function.bind = loopback_bind;
loop->function.unbind = loopback_unbind; loop->function.unbind = loopback_unbind;
loop->function.set_alt = loopback_set_alt; loop->function.set_alt = loopback_set_alt;
......
...@@ -2904,9 +2904,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -2904,9 +2904,7 @@ static void fsg_unbind(struct usb_configuration *c, struct usb_function *f)
} }
fsg_common_put(common); fsg_common_put(common);
usb_free_descriptors(fsg->function.descriptors); usb_free_all_descriptors(&fsg->function);
usb_free_descriptors(fsg->function.hs_descriptors);
usb_free_descriptors(fsg->function.ss_descriptors);
kfree(fsg); kfree(fsg);
} }
...@@ -2916,6 +2914,8 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -2916,6 +2914,8 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_gadget *gadget = c->cdev->gadget; struct usb_gadget *gadget = c->cdev->gadget;
int i; int i;
struct usb_ep *ep; struct usb_ep *ep;
unsigned max_burst;
int ret;
fsg->gadget = gadget; fsg->gadget = gadget;
...@@ -2939,26 +2939,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -2939,26 +2939,11 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
ep->driver_data = fsg->common; /* claim the endpoint */ ep->driver_data = fsg->common; /* claim the endpoint */
fsg->bulk_out = ep; fsg->bulk_out = ep;
/* Copy descriptors */
f->descriptors = usb_copy_descriptors(fsg_fs_function);
if (unlikely(!f->descriptors))
return -ENOMEM;
if (gadget_is_dualspeed(gadget)) {
/* Assume endpoint addresses are the same for both speeds */ /* Assume endpoint addresses are the same for both speeds */
fsg_hs_bulk_in_desc.bEndpointAddress = fsg_hs_bulk_in_desc.bEndpointAddress =
fsg_fs_bulk_in_desc.bEndpointAddress; fsg_fs_bulk_in_desc.bEndpointAddress;
fsg_hs_bulk_out_desc.bEndpointAddress = fsg_hs_bulk_out_desc.bEndpointAddress =
fsg_fs_bulk_out_desc.bEndpointAddress; fsg_fs_bulk_out_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(fsg_hs_function);
if (unlikely(!f->hs_descriptors)) {
usb_free_descriptors(f->descriptors);
return -ENOMEM;
}
}
if (gadget_is_superspeed(gadget)) {
unsigned max_burst;
/* Calculate bMaxBurst, we know packet size is 1024 */ /* Calculate bMaxBurst, we know packet size is 1024 */
max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15); max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15);
...@@ -2971,13 +2956,10 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -2971,13 +2956,10 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
fsg_fs_bulk_out_desc.bEndpointAddress; fsg_fs_bulk_out_desc.bEndpointAddress;
fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst;
f->ss_descriptors = usb_copy_descriptors(fsg_ss_function); ret = usb_assign_descriptors(f, fsg_fs_function, fsg_hs_function,
if (unlikely(!f->ss_descriptors)) { fsg_ss_function);
usb_free_descriptors(f->hs_descriptors); if (ret)
usb_free_descriptors(f->descriptors); goto autoconf_fail;
return -ENOMEM;
}
}
return 0; return 0;
...@@ -2986,7 +2968,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -2986,7 +2968,6 @@ static int fsg_bind(struct usb_configuration *c, struct usb_function *f)
return -ENOTSUPP; return -ENOTSUPP;
} }
/****************************** ADD FUNCTION ******************************/ /****************************** ADD FUNCTION ******************************/
static struct usb_gadget_strings *fsg_strings_array[] = { static struct usb_gadget_strings *fsg_strings_array[] = {
......
...@@ -414,8 +414,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -414,8 +414,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f)
kfree(midi->id); kfree(midi->id);
midi->id = NULL; midi->id = NULL;
usb_free_descriptors(f->descriptors); usb_free_all_descriptors(f);
usb_free_descriptors(f->hs_descriptors);
kfree(midi); kfree(midi);
} }
...@@ -882,9 +881,10 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -882,9 +881,10 @@ f_midi_bind(struct usb_configuration *c, struct usb_function *f)
* both speeds * both speeds
*/ */
/* copy descriptors, and track endpoint copies */ /* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(midi_function); f->fs_descriptors = usb_copy_descriptors(midi_function);
if (!f->descriptors) if (!f->fs_descriptors)
goto fail_f_midi; goto fail_f_midi;
if (gadget_is_dualspeed(c->cdev->gadget)) { if (gadget_is_dualspeed(c->cdev->gadget)) {
bulk_in_desc.wMaxPacketSize = cpu_to_le16(512); bulk_in_desc.wMaxPacketSize = cpu_to_le16(512);
bulk_out_desc.wMaxPacketSize = cpu_to_le16(512); bulk_out_desc.wMaxPacketSize = cpu_to_le16(512);
......
...@@ -1208,30 +1208,18 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -1208,30 +1208,18 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
ncm->notify_req->context = ncm; ncm->notify_req->context = ncm;
ncm->notify_req->complete = ncm_notify_complete; ncm->notify_req->complete = ncm_notify_complete;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(ncm_fs_function);
if (!f->descriptors)
goto fail;
/* /*
* support all relevant hardware speeds... we expect that when * support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at * hardware is dual speed, all bulk-capable endpoints work at
* both speeds * both speeds
*/ */
if (gadget_is_dualspeed(c->cdev->gadget)) { hs_ncm_in_desc.bEndpointAddress = fs_ncm_in_desc.bEndpointAddress;
hs_ncm_in_desc.bEndpointAddress = hs_ncm_out_desc.bEndpointAddress = fs_ncm_out_desc.bEndpointAddress;
fs_ncm_in_desc.bEndpointAddress;
hs_ncm_out_desc.bEndpointAddress =
fs_ncm_out_desc.bEndpointAddress;
hs_ncm_notify_desc.bEndpointAddress = hs_ncm_notify_desc.bEndpointAddress =
fs_ncm_notify_desc.bEndpointAddress; fs_ncm_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */ status = usb_assign_descriptors(f, ncm_fs_function, ncm_hs_function,
f->hs_descriptors = usb_copy_descriptors(ncm_hs_function); NULL);
if (!f->hs_descriptors)
goto fail;
}
/* /*
* NOTE: all that is done without knowing or caring about * NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code * the network link ... which is unavailable to this code
...@@ -1248,9 +1236,7 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -1248,9 +1236,7 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
if (f->descriptors) usb_free_all_descriptors(f);
usb_free_descriptors(f->descriptors);
if (ncm->notify_req) { if (ncm->notify_req) {
kfree(ncm->notify_req->buf); kfree(ncm->notify_req->buf);
usb_ep_free_request(ncm->notify, ncm->notify_req); usb_ep_free_request(ncm->notify, ncm->notify_req);
...@@ -1276,9 +1262,7 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -1276,9 +1262,7 @@ ncm_unbind(struct usb_configuration *c, struct usb_function *f)
DBG(c->cdev, "ncm unbind\n"); DBG(c->cdev, "ncm unbind\n");
if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_all_descriptors(f);
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
kfree(ncm->notify_req->buf); kfree(ncm->notify_req->buf);
usb_ep_free_request(ncm->notify, ncm->notify_req); usb_ep_free_request(ncm->notify, ncm->notify_req);
......
...@@ -331,23 +331,19 @@ obex_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -331,23 +331,19 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
obex->port.out = ep; obex->port.out = ep;
ep->driver_data = cdev; /* claim */ ep->driver_data = cdev; /* claim */
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(fs_function);
/* support all relevant hardware speeds... we expect that when /* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at * hardware is dual speed, all bulk-capable endpoints work at
* both speeds * both speeds
*/ */
if (gadget_is_dualspeed(c->cdev->gadget)) {
obex_hs_ep_in_desc.bEndpointAddress = obex_hs_ep_in_desc.bEndpointAddress =
obex_fs_ep_in_desc.bEndpointAddress; obex_fs_ep_in_desc.bEndpointAddress;
obex_hs_ep_out_desc.bEndpointAddress = obex_hs_ep_out_desc.bEndpointAddress =
obex_fs_ep_out_desc.bEndpointAddress; obex_fs_ep_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */ status = usb_assign_descriptors(f, fs_function, hs_function, NULL);
f->hs_descriptors = usb_copy_descriptors(hs_function); if (status)
} goto fail;
/* Avoid letting this gadget enumerate until the userspace /* Avoid letting this gadget enumerate until the userspace
* OBEX server is active. * OBEX server is active.
...@@ -368,6 +364,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -368,6 +364,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
usb_free_all_descriptors(f);
/* we might as well release our claims on endpoints */ /* we might as well release our claims on endpoints */
if (obex->port.out) if (obex->port.out)
obex->port.out->driver_data = NULL; obex->port.out->driver_data = NULL;
...@@ -382,9 +379,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -382,9 +379,7 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
static void static void
obex_unbind(struct usb_configuration *c, struct usb_function *f) obex_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_all_descriptors(f);
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
kfree(func_to_obex(f)); kfree(func_to_obex(f));
} }
......
...@@ -515,14 +515,14 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -515,14 +515,14 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
fp->in_ep = ep; fp->in_ep = ep;
ep->driver_data = fp; /* Claim */ ep->driver_data = fp; /* Claim */
pn_hs_sink_desc.bEndpointAddress = pn_hs_sink_desc.bEndpointAddress = pn_fs_sink_desc.bEndpointAddress;
pn_fs_sink_desc.bEndpointAddress; pn_hs_source_desc.bEndpointAddress = pn_fs_source_desc.bEndpointAddress;
pn_hs_source_desc.bEndpointAddress =
pn_fs_source_desc.bEndpointAddress;
/* Do not try to bind Phonet twice... */ /* Do not try to bind Phonet twice... */
fp->function.descriptors = fs_pn_function; status = usb_assign_descriptors(f, fs_pn_function, hs_pn_function,
fp->function.hs_descriptors = hs_pn_function; NULL);
if (status)
goto err;
/* Incoming USB requests */ /* Incoming USB requests */
status = -ENOMEM; status = -ENOMEM;
...@@ -551,7 +551,7 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -551,7 +551,7 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f)
for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++) for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++)
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
err: err:
usb_free_all_descriptors(f);
if (fp->out_ep) if (fp->out_ep)
fp->out_ep->driver_data = NULL; fp->out_ep->driver_data = NULL;
if (fp->in_ep) if (fp->in_ep)
...@@ -573,6 +573,7 @@ pn_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -573,6 +573,7 @@ pn_unbind(struct usb_configuration *c, struct usb_function *f)
if (fp->out_reqv[i]) if (fp->out_reqv[i])
usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); usb_ep_free_request(fp->out_ep, fp->out_reqv[i]);
usb_free_all_descriptors(f);
kfree(fp); kfree(fp);
} }
......
...@@ -722,42 +722,22 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -722,42 +722,22 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
rndis->notify_req->context = rndis; rndis->notify_req->context = rndis;
rndis->notify_req->complete = rndis_response_complete; rndis->notify_req->complete = rndis_response_complete;
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(eth_fs_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when /* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at * hardware is dual speed, all bulk-capable endpoints work at
* both speeds * both speeds
*/ */
if (gadget_is_dualspeed(c->cdev->gadget)) { hs_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
hs_in_desc.bEndpointAddress = hs_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
fs_in_desc.bEndpointAddress; hs_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
hs_out_desc.bEndpointAddress =
fs_out_desc.bEndpointAddress; ss_in_desc.bEndpointAddress = fs_in_desc.bEndpointAddress;
hs_notify_desc.bEndpointAddress = ss_out_desc.bEndpointAddress = fs_out_desc.bEndpointAddress;
fs_notify_desc.bEndpointAddress; ss_notify_desc.bEndpointAddress = fs_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(eth_hs_function);
if (!f->hs_descriptors)
goto fail;
}
if (gadget_is_superspeed(c->cdev->gadget)) { status = usb_assign_descriptors(f, eth_fs_function, eth_hs_function,
ss_in_desc.bEndpointAddress = eth_ss_function);
fs_in_desc.bEndpointAddress; if (status)
ss_out_desc.bEndpointAddress =
fs_out_desc.bEndpointAddress;
ss_notify_desc.bEndpointAddress =
fs_notify_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(eth_ss_function);
if (!f->ss_descriptors)
goto fail; goto fail;
}
rndis->port.open = rndis_open; rndis->port.open = rndis_open;
rndis->port.close = rndis_close; rndis->port.close = rndis_close;
...@@ -788,12 +768,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -788,12 +768,7 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors) usb_free_all_descriptors(f);
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
if (f->descriptors)
usb_free_descriptors(f->descriptors);
if (rndis->notify_req) { if (rndis->notify_req) {
kfree(rndis->notify_req->buf); kfree(rndis->notify_req->buf);
...@@ -822,11 +797,7 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -822,11 +797,7 @@ rndis_unbind(struct usb_configuration *c, struct usb_function *f)
rndis_exit(); rndis_exit();
rndis_string_defs[0].id = 0; rndis_string_defs[0].id = 0;
if (gadget_is_superspeed(c->cdev->gadget)) usb_free_all_descriptors(f);
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
kfree(rndis->notify_req->buf); kfree(rndis->notify_req->buf);
usb_ep_free_request(rndis->notify, rndis->notify_req); usb_ep_free_request(rndis->notify, rndis->notify_req);
......
...@@ -213,34 +213,20 @@ gser_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -213,34 +213,20 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
gser->port.out = ep; gser->port.out = ep;
ep->driver_data = cdev; /* claim */ ep->driver_data = cdev; /* claim */
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(gser_fs_function);
/* support all relevant hardware speeds... we expect that when /* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at * hardware is dual speed, all bulk-capable endpoints work at
* both speeds * both speeds
*/ */
if (gadget_is_dualspeed(c->cdev->gadget)) { gser_hs_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
gser_hs_in_desc.bEndpointAddress = gser_hs_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
gser_fs_in_desc.bEndpointAddress;
gser_hs_out_desc.bEndpointAddress =
gser_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
}
if (gadget_is_superspeed(c->cdev->gadget)) {
gser_ss_in_desc.bEndpointAddress =
gser_fs_in_desc.bEndpointAddress;
gser_ss_out_desc.bEndpointAddress =
gser_fs_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */
f->ss_descriptors = usb_copy_descriptors(gser_ss_function);
if (!f->ss_descriptors)
goto fail;
}
gser_ss_in_desc.bEndpointAddress = gser_fs_in_desc.bEndpointAddress;
gser_ss_out_desc.bEndpointAddress = gser_fs_out_desc.bEndpointAddress;
status = usb_assign_descriptors(f, gser_fs_function, gser_hs_function,
gser_ss_function);
if (status)
goto fail;
DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n", DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
gser->port_num, gser->port_num,
gadget_is_superspeed(c->cdev->gadget) ? "super" : gadget_is_superspeed(c->cdev->gadget) ? "super" :
...@@ -263,11 +249,7 @@ gser_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -263,11 +249,7 @@ gser_bind(struct usb_configuration *c, struct usb_function *f)
static void static void
gser_unbind(struct usb_configuration *c, struct usb_function *f) gser_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
if (gadget_is_dualspeed(c->cdev->gadget)) usb_free_all_descriptors(f);
usb_free_descriptors(f->hs_descriptors);
if (gadget_is_superspeed(c->cdev->gadget))
usb_free_descriptors(f->ss_descriptors);
usb_free_descriptors(f->descriptors);
kfree(func_to_gser(f)); kfree(func_to_gser(f));
} }
......
...@@ -319,6 +319,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -319,6 +319,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev; struct usb_composite_dev *cdev = c->cdev;
struct f_sourcesink *ss = func_to_ss(f); struct f_sourcesink *ss = func_to_ss(f);
int id; int id;
int ret;
/* allocate interface ID(s) */ /* allocate interface ID(s) */
id = usb_interface_id(c, f); id = usb_interface_id(c, f);
...@@ -387,11 +388,8 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -387,11 +388,8 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
isoc_maxpacket = 1024; isoc_maxpacket = 1024;
/* support high speed hardware */ /* support high speed hardware */
if (gadget_is_dualspeed(c->cdev->gadget)) { hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress;
hs_source_desc.bEndpointAddress = hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress;
fs_source_desc.bEndpointAddress;
hs_sink_desc.bEndpointAddress =
fs_sink_desc.bEndpointAddress;
/* /*
* Fill in the HS isoc descriptors from the module parameters. * Fill in the HS isoc descriptors from the module parameters.
...@@ -407,14 +405,9 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -407,14 +405,9 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket; hs_iso_sink_desc.wMaxPacketSize = isoc_maxpacket;
hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11; hs_iso_sink_desc.wMaxPacketSize |= isoc_mult << 11;
hs_iso_sink_desc.bInterval = isoc_interval; hs_iso_sink_desc.bInterval = isoc_interval;
hs_iso_sink_desc.bEndpointAddress = hs_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
fs_iso_sink_desc.bEndpointAddress;
f->hs_descriptors = hs_source_sink_descs;
}
/* support super speed hardware */ /* support super speed hardware */
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_source_desc.bEndpointAddress = ss_source_desc.bEndpointAddress =
fs_source_desc.bEndpointAddress; fs_source_desc.bEndpointAddress;
ss_sink_desc.bEndpointAddress = ss_sink_desc.bEndpointAddress =
...@@ -440,11 +433,12 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -440,11 +433,12 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst; ss_iso_sink_comp_desc.bMaxBurst = isoc_maxburst;
ss_iso_sink_comp_desc.wBytesPerInterval = ss_iso_sink_comp_desc.wBytesPerInterval =
isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1); isoc_maxpacket * (isoc_mult + 1) * (isoc_maxburst + 1);
ss_iso_sink_desc.bEndpointAddress = ss_iso_sink_desc.bEndpointAddress = fs_iso_sink_desc.bEndpointAddress;
fs_iso_sink_desc.bEndpointAddress;
f->ss_descriptors = ss_source_sink_descs; ret = usb_assign_descriptors(f, fs_source_sink_descs,
} hs_source_sink_descs, ss_source_sink_descs);
if (ret)
return ret;
DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n", DBG(cdev, "%s speed %s: IN/%s, OUT/%s, ISO-IN/%s, ISO-OUT/%s\n",
(gadget_is_superspeed(c->cdev->gadget) ? "super" : (gadget_is_superspeed(c->cdev->gadget) ? "super" :
...@@ -458,6 +452,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -458,6 +452,7 @@ sourcesink_bind(struct usb_configuration *c, struct usb_function *f)
static void static void
sourcesink_unbind(struct usb_configuration *c, struct usb_function *f) sourcesink_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
usb_free_all_descriptors(f);
kfree(func_to_ss(f)); kfree(func_to_ss(f));
} }
...@@ -773,7 +768,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c) ...@@ -773,7 +768,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c)
return -ENOMEM; return -ENOMEM;
ss->function.name = "source/sink"; ss->function.name = "source/sink";
ss->function.descriptors = fs_source_sink_descs;
ss->function.bind = sourcesink_bind; ss->function.bind = sourcesink_bind;
ss->function.unbind = sourcesink_unbind; ss->function.unbind = sourcesink_unbind;
ss->function.set_alt = sourcesink_set_alt; ss->function.set_alt = sourcesink_set_alt;
......
...@@ -319,38 +319,22 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -319,38 +319,22 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
geth->port.out_ep = ep; geth->port.out_ep = ep;
ep->driver_data = cdev; /* claim */ ep->driver_data = cdev; /* claim */
/* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(fs_eth_function);
if (!f->descriptors)
goto fail;
/* support all relevant hardware speeds... we expect that when /* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at * hardware is dual speed, all bulk-capable endpoints work at
* both speeds * both speeds
*/ */
if (gadget_is_dualspeed(c->cdev->gadget)) { hs_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
hs_subset_in_desc.bEndpointAddress =
fs_subset_in_desc.bEndpointAddress;
hs_subset_out_desc.bEndpointAddress = hs_subset_out_desc.bEndpointAddress =
fs_subset_out_desc.bEndpointAddress; fs_subset_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */ ss_subset_in_desc.bEndpointAddress = fs_subset_in_desc.bEndpointAddress;
f->hs_descriptors = usb_copy_descriptors(hs_eth_function);
if (!f->hs_descriptors)
goto fail;
}
if (gadget_is_superspeed(c->cdev->gadget)) {
ss_subset_in_desc.bEndpointAddress =
fs_subset_in_desc.bEndpointAddress;
ss_subset_out_desc.bEndpointAddress = ss_subset_out_desc.bEndpointAddress =
fs_subset_out_desc.bEndpointAddress; fs_subset_out_desc.bEndpointAddress;
/* copy descriptors, and track endpoint copies */ status = usb_assign_descriptors(f, fs_eth_function, hs_eth_function,
f->ss_descriptors = usb_copy_descriptors(ss_eth_function); ss_eth_function);
if (!f->ss_descriptors) if (status)
goto fail; goto fail;
}
/* NOTE: all that is done without knowing or caring about /* NOTE: all that is done without knowing or caring about
* the network link ... which is unavailable to this code * the network link ... which is unavailable to this code
...@@ -364,11 +348,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -364,11 +348,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
return 0; return 0;
fail: fail:
if (f->descriptors) usb_free_all_descriptors(f);
usb_free_descriptors(f->descriptors);
if (f->hs_descriptors)
usb_free_descriptors(f->hs_descriptors);
/* we might as well release our claims on endpoints */ /* we might as well release our claims on endpoints */
if (geth->port.out_ep) if (geth->port.out_ep)
geth->port.out_ep->driver_data = NULL; geth->port.out_ep->driver_data = NULL;
...@@ -383,11 +363,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -383,11 +363,7 @@ geth_bind(struct usb_configuration *c, struct usb_function *f)
static void static void
geth_unbind(struct usb_configuration *c, struct usb_function *f) geth_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
if (gadget_is_superspeed(c->cdev->gadget)) usb_free_all_descriptors(f);
usb_free_descriptors(f->ss_descriptors);
if (gadget_is_dualspeed(c->cdev->gadget))
usb_free_descriptors(f->hs_descriptors);
usb_free_descriptors(f->descriptors);
geth_string_defs[1].s = NULL; geth_string_defs[1].s = NULL;
kfree(func_to_geth(f)); kfree(func_to_geth(f));
} }
......
...@@ -630,7 +630,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -630,7 +630,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_composite_dev *cdev = c->cdev; struct usb_composite_dev *cdev = c->cdev;
struct f_audio *audio = func_to_audio(f); struct f_audio *audio = func_to_audio(f);
int status; int status;
struct usb_ep *ep; struct usb_ep *ep = NULL;
f_audio_build_desc(audio); f_audio_build_desc(audio);
...@@ -659,21 +659,14 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -659,21 +659,14 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f)
status = -ENOMEM; status = -ENOMEM;
/* copy descriptors, and track endpoint copies */ /* copy descriptors, and track endpoint copies */
f->descriptors = usb_copy_descriptors(f_audio_desc); status = usb_assign_descriptors(f, f_audio_desc, f_audio_desc, NULL);
if (status)
/* goto fail;
* support all relevant hardware speeds... we expect that when
* hardware is dual speed, all bulk-capable endpoints work at
* both speeds
*/
if (gadget_is_dualspeed(c->cdev->gadget)) {
f->hs_descriptors = usb_copy_descriptors(f_audio_desc);
}
return 0; return 0;
fail: fail:
if (ep)
ep->driver_data = NULL;
return status; return status;
} }
...@@ -682,8 +675,7 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -682,8 +675,7 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
struct f_audio *audio = func_to_audio(f); struct f_audio *audio = func_to_audio(f);
usb_free_descriptors(f->descriptors); usb_free_all_descriptors(f);
usb_free_descriptors(f->hs_descriptors);
kfree(audio); kfree(audio);
} }
......
...@@ -998,9 +998,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) ...@@ -998,9 +998,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress;
hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize; hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize;
fn->descriptors = usb_copy_descriptors(fs_audio_desc); ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL);
if (gadget_is_dualspeed(gadget)) if (ret)
fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc); goto err;
prm = &agdev->uac2.c_prm; prm = &agdev->uac2.c_prm;
prm->max_psize = hs_epout_desc.wMaxPacketSize; prm->max_psize = hs_epout_desc.wMaxPacketSize;
...@@ -1029,8 +1029,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) ...@@ -1029,8 +1029,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn)
err: err:
kfree(agdev->uac2.p_prm.rbuf); kfree(agdev->uac2.p_prm.rbuf);
kfree(agdev->uac2.c_prm.rbuf); kfree(agdev->uac2.c_prm.rbuf);
usb_free_descriptors(fn->hs_descriptors); usb_free_all_descriptors(fn);
usb_free_descriptors(fn->descriptors);
if (agdev->in_ep) if (agdev->in_ep)
agdev->in_ep->driver_data = NULL; agdev->in_ep->driver_data = NULL;
if (agdev->out_ep) if (agdev->out_ep)
...@@ -1042,8 +1041,6 @@ static void ...@@ -1042,8 +1041,6 @@ static void
afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn) afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
{ {
struct audio_dev *agdev = func_to_agdev(fn); struct audio_dev *agdev = func_to_agdev(fn);
struct usb_composite_dev *cdev = cfg->cdev;
struct usb_gadget *gadget = cdev->gadget;
struct uac2_rtd_params *prm; struct uac2_rtd_params *prm;
alsa_uac2_exit(agdev); alsa_uac2_exit(agdev);
...@@ -1053,10 +1050,7 @@ afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn) ...@@ -1053,10 +1050,7 @@ afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn)
prm = &agdev->uac2.c_prm; prm = &agdev->uac2.c_prm;
kfree(prm->rbuf); kfree(prm->rbuf);
usb_free_all_descriptors(fn);
if (gadget_is_dualspeed(gadget))
usb_free_descriptors(fn->hs_descriptors);
usb_free_descriptors(fn->descriptors);
if (agdev->in_ep) if (agdev->in_ep)
agdev->in_ep->driver_data = NULL; agdev->in_ep->driver_data = NULL;
......
...@@ -583,9 +583,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -583,9 +583,7 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f)
usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); usb_ep_free_request(cdev->gadget->ep0, uvc->control_req);
kfree(uvc->control_buf); kfree(uvc->control_buf);
kfree(f->descriptors); usb_free_all_descriptors(f);
kfree(f->hs_descriptors);
kfree(f->ss_descriptors);
kfree(uvc); kfree(uvc);
} }
...@@ -651,17 +649,11 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -651,17 +649,11 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
/* sanity check the streaming endpoint module parameters */ /* sanity check the streaming endpoint module parameters */
if (streaming_maxpacket > 1024) if (streaming_maxpacket > 1024)
streaming_maxpacket = 1024; streaming_maxpacket = 1024;
/* Copy descriptors for FS. */
f->descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
/* support high speed hardware */
if (gadget_is_dualspeed(cdev->gadget)) {
/* /*
* Fill in the HS descriptors from the module parameters for the * Fill in the HS descriptors from the module parameters for the Video
* Video Streaming endpoint. * Streaming endpoint.
* NOTE: We assume that the user knows what they are doing and * NOTE: We assume that the user knows what they are doing and won't
* won't give parameters that their UDC doesn't support. * give parameters that their UDC doesn't support.
*/ */
uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket; uvc_hs_streaming_ep.wMaxPacketSize = streaming_maxpacket;
uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11; uvc_hs_streaming_ep.wMaxPacketSize |= streaming_mult << 11;
...@@ -669,17 +661,11 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -669,17 +661,11 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc_hs_streaming_ep.bEndpointAddress = uvc_hs_streaming_ep.bEndpointAddress =
uvc_fs_streaming_ep.bEndpointAddress; uvc_fs_streaming_ep.bEndpointAddress;
/* Copy descriptors. */
f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
}
/* support super speed hardware */
if (gadget_is_superspeed(c->cdev->gadget)) {
/* /*
* Fill in the SS descriptors from the module parameters for the * Fill in the SS descriptors from the module parameters for the Video
* Video Streaming endpoint. * Streaming endpoint.
* NOTE: We assume that the user knows what they are doing and * NOTE: We assume that the user knows what they are doing and won't
* won't give parameters that their UDC doesn't support. * give parameters that their UDC doesn't support.
*/ */
uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket; uvc_ss_streaming_ep.wMaxPacketSize = streaming_maxpacket;
uvc_ss_streaming_ep.bInterval = streaming_interval; uvc_ss_streaming_ep.bInterval = streaming_interval;
...@@ -691,9 +677,12 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -691,9 +677,12 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
uvc_ss_streaming_ep.bEndpointAddress = uvc_ss_streaming_ep.bEndpointAddress =
uvc_fs_streaming_ep.bEndpointAddress; uvc_fs_streaming_ep.bEndpointAddress;
/* Copy descriptors. */ /* Copy descriptors */
f->fs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_FULL);
if (gadget_is_dualspeed(cdev->gadget))
f->hs_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_HIGH);
if (gadget_is_superspeed(c->cdev->gadget))
f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER); f->ss_descriptors = uvc_copy_descriptors(uvc, USB_SPEED_SUPER);
}
/* Preallocate control endpoint request. */ /* Preallocate control endpoint request. */
uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); uvc->control_req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL);
...@@ -741,9 +730,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -741,9 +730,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f)
kfree(uvc->control_buf); kfree(uvc->control_buf);
} }
kfree(f->descriptors); usb_free_all_descriptors(f);
kfree(f->hs_descriptors);
kfree(f->ss_descriptors);
return ret; return ret;
} }
......
...@@ -983,8 +983,10 @@ static int __init printer_func_bind(struct usb_configuration *c, ...@@ -983,8 +983,10 @@ static int __init printer_func_bind(struct usb_configuration *c,
{ {
struct printer_dev *dev = container_of(f, struct printer_dev, function); struct printer_dev *dev = container_of(f, struct printer_dev, function);
struct usb_composite_dev *cdev = c->cdev; struct usb_composite_dev *cdev = c->cdev;
struct usb_ep *in_ep, *out_ep; struct usb_ep *in_ep;
struct usb_ep *out_ep = NULL;
int id; int id;
int ret;
id = usb_interface_id(c, f); id = usb_interface_id(c, f);
if (id < 0) if (id < 0)
...@@ -1010,6 +1012,11 @@ static int __init printer_func_bind(struct usb_configuration *c, ...@@ -1010,6 +1012,11 @@ static int __init printer_func_bind(struct usb_configuration *c,
hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress;
hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress;
ret = usb_assign_descriptors(f, fs_printer_function,
hs_printer_function, NULL);
if (ret)
return ret;
dev->in_ep = in_ep; dev->in_ep = in_ep;
dev->out_ep = out_ep; dev->out_ep = out_ep;
return 0; return 0;
...@@ -1018,6 +1025,7 @@ static int __init printer_func_bind(struct usb_configuration *c, ...@@ -1018,6 +1025,7 @@ static int __init printer_func_bind(struct usb_configuration *c,
static void printer_func_unbind(struct usb_configuration *c, static void printer_func_unbind(struct usb_configuration *c,
struct usb_function *f) struct usb_function *f)
{ {
usb_free_all_descriptors(f);
} }
static int printer_func_set_alt(struct usb_function *f, static int printer_func_set_alt(struct usb_function *f,
...@@ -1110,8 +1118,6 @@ static int __init printer_bind_config(struct usb_configuration *c) ...@@ -1110,8 +1118,6 @@ static int __init printer_bind_config(struct usb_configuration *c)
dev = &usb_printer_gadget; dev = &usb_printer_gadget;
dev->function.name = shortname; dev->function.name = shortname;
dev->function.descriptors = fs_printer_function;
dev->function.hs_descriptors = hs_printer_function;
dev->function.bind = printer_func_bind; dev->function.bind = printer_func_bind;
dev->function.setup = printer_func_setup; dev->function.setup = printer_func_setup;
dev->function.unbind = printer_func_unbind; dev->function.unbind = printer_func_unbind;
......
...@@ -2240,6 +2240,7 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -2240,6 +2240,7 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
struct usb_gadget *gadget = c->cdev->gadget; struct usb_gadget *gadget = c->cdev->gadget;
struct usb_ep *ep; struct usb_ep *ep;
int iface; int iface;
int ret;
iface = usb_interface_id(c, f); iface = usb_interface_id(c, f);
if (iface < 0) if (iface < 0)
...@@ -2290,6 +2291,11 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f) ...@@ -2290,6 +2291,11 @@ static int usbg_bind(struct usb_configuration *c, struct usb_function *f)
uasp_ss_status_desc.bEndpointAddress; uasp_ss_status_desc.bEndpointAddress;
uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress; uasp_fs_cmd_desc.bEndpointAddress = uasp_ss_cmd_desc.bEndpointAddress;
ret = usb_assign_descriptors(f, uasp_fs_function_desc,
uasp_hs_function_desc, uasp_ss_function_desc);
if (ret)
goto ep_fail;
return 0; return 0;
ep_fail: ep_fail:
pr_err("Can't claim all required eps\n"); pr_err("Can't claim all required eps\n");
...@@ -2305,6 +2311,7 @@ static void usbg_unbind(struct usb_configuration *c, struct usb_function *f) ...@@ -2305,6 +2311,7 @@ static void usbg_unbind(struct usb_configuration *c, struct usb_function *f)
{ {
struct f_uas *fu = to_f_uas(f); struct f_uas *fu = to_f_uas(f);
usb_free_all_descriptors(f);
kfree(fu); kfree(fu);
} }
...@@ -2385,9 +2392,6 @@ static int usbg_cfg_bind(struct usb_configuration *c) ...@@ -2385,9 +2392,6 @@ static int usbg_cfg_bind(struct usb_configuration *c)
if (!fu) if (!fu)
return -ENOMEM; return -ENOMEM;
fu->function.name = "Target Function"; fu->function.name = "Target Function";
fu->function.descriptors = uasp_fs_function_desc;
fu->function.hs_descriptors = uasp_hs_function_desc;
fu->function.ss_descriptors = uasp_ss_function_desc;
fu->function.bind = usbg_bind; fu->function.bind = usbg_bind;
fu->function.unbind = usbg_unbind; fu->function.unbind = usbg_unbind;
fu->function.set_alt = usbg_set_alt; fu->function.set_alt = usbg_set_alt;
......
...@@ -119,7 +119,7 @@ struct usb_configuration; ...@@ -119,7 +119,7 @@ struct usb_configuration;
struct usb_function { struct usb_function {
const char *name; const char *name;
struct usb_gadget_strings **strings; struct usb_gadget_strings **strings;
struct usb_descriptor_header **descriptors; struct usb_descriptor_header **fs_descriptors;
struct usb_descriptor_header **hs_descriptors; struct usb_descriptor_header **hs_descriptors;
struct usb_descriptor_header **ss_descriptors; struct usb_descriptor_header **ss_descriptors;
......
...@@ -939,6 +939,13 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v) ...@@ -939,6 +939,13 @@ static inline void usb_free_descriptors(struct usb_descriptor_header **v)
kfree(v); kfree(v);
} }
struct usb_function;
int usb_assign_descriptors(struct usb_function *f,
struct usb_descriptor_header **fs,
struct usb_descriptor_header **hs,
struct usb_descriptor_header **ss);
void usb_free_all_descriptors(struct usb_function *f);
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
/* utility to simplify map/unmap of usb_requests to/from DMA */ /* utility to simplify map/unmap of usb_requests to/from DMA */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册