[lkml]   [2011]   [Aug]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
    SubjectRe: [PATCHv2] usb: gadget: get rid of USB_GADGET_DUALSPEED and USB_GADGET_SUPERSPEED
    On Thu, 18 Aug 2011 19:27:21 +0200, Alan Stern <>  

    > On Thu, 18 Aug 2011, Michal Nazarewicz wrote:
    >> For the most part, usb_composite_probe() is called only once in module's
    >> init function. As far as I know, only g_ffs calls it several times. So
    >> in all cases expect for g_ffs, composite_driver.speed =
    >> min(composite_driver.speed,
    >> driver->max_speed) should have the same effect as composite_driver.speed
    >> = driver->max_speed.
    >> > For example, if you have a composite gadget where one of the function
    >> > drivers can handle SuperSpeed and the other can't go beyond high
    >> speed,
    >> > the overall gadget must never run faster than high speed.
    >> Shouldn't that be dealt in usb_add_function()? I cannot see any code
    >> that would do that here atm though.

    > Maybe you're right. But isn't that too late? The UDC driver has to
    > know the gadget driver's limitations before it can connect to the host.

    usb_add_function() is called before usb_composite_probe() which only then
    calls usb_gadget_probe_driver().

    What's more, if I understand it correctly, comment in usb_add_function()
    says that we support all the speeds usb_composite_driver structure claims
    we do but then return different sets of functions depending on speed. Ie.
    if a function is only full speed and host requests high speed,
    will lack that function. The comment in question is:

    /* We allow configurations that don't work at both speeds.
    * If we run into a lowspeed Linux system, treat it the same
    * as full speed ... it's the function drivers that will need
    * to avoid bulk and ISO transfers. */

    usb_add_function() then proceeds to set config->fullspeed,
    and config->superspeed depending on what descriptors function provides.

    Those are later used in config_desc() where it iterates over all
    configurations checking which have functions supporting given speed:

    list_for_each_entry(c, &cdev->configs, list) {
    switch (speed) {
    case USB_SPEED_SUPER: if (!c->superspeed) continue; break;
    case USB_SPEED_HIGH: if (!c->highspeed) continue; break;
    default: if (!c->fullspeed) continue;
    if (w_value == 0)
    return config_buf(c, speed, cdev->req->buf, type);

    config_buf() at the same time, iterates over all functions and skips the
    that do not provide descriptors for given speed:

    list_for_each_entry(f, &config->functions, list) {
    switch (speed) {
    case USB_SPEED_SUPER: descriptors = f->ss_descriptors; break;
    case USB_SPEED_HIGH: descriptors = f->hs_descriptors; break;
    default: descriptors = f->descriptors;
    if (!descriptors)

    So I think that your suggestion to use composite_driver.speed =
    driver->max_speed was by all means correct.

    Best regards, _ _
    .o. | Liege of Serenely Enlightened Majesty of o' \,=./ `o
    ..o | Computer Science, Michal "mina86" Nazarewicz (o o)
    ooo +-----<email/xmpp:>-----ooO--(_)--Ooo--

     \ /
      Last update: 2011-08-18 22:15    [W:0.024 / U:7.640 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site