Big and small developed four and gadget Related drivers , Character driven 、g_multi、g_ether、g_zero, Put yourself here to gadget The development of their own perception of the record .

 

Want to know gadget, You have to understand the framework , know composite、gadget、udc The connection between the three , know usb The function of descriptors .

One usb device There is a device descriptor .

There is one or more configuration descriptors

A configuration descriptor has one or more interfaces ( stay gadget End , The formal name of the interface is usb_func).

One interface has 0 One or more endpoints .

 

To write gadget The key to success is to understand udc、gadget、composite The connection and structure level among the three , in application gadget It doesn't need us to write it , What we need to write ourselves is composite layer , And to the ground udc Layer modification , Let's start with a detailed introduction of the three .

1、composite English means compound , It's supposed to be writing usb gadget Layer device drivers are all integrated together , Through a unified function usb_composite_register register . Different function , The squalid , So it's called composite layer .

On this floor , The related structures and functions we need to pay attention to are as follows :

 

struct usb_composite_dev { // As composite Composite equipment , all composite Devices must implement the device .
    struct usb_gadget        *gadget; // Equipment and gadget Interaction ,gadget and udc Interaction .
    struct usb_request        *req;   // Each device comes with one usb request , All data interactions are sent through the request .
    struct usb_configuration    *config;  A device has one or more configurations .
    /* private: */
    /* internals */
    unsigned int            suspended:1;
    struct usb_device_descriptor    desc;  // Device descriptor , only
    struct list_head        configs; // To configure
    struct list_head        gstrings; // Character description
    struct usb_composite_driver    *driver; // Device bound drivers
    u8                next_string_id;  
    char                *def_manufacturer;  // Default manufacturer
    /* the gadget driver won't enable the data pullup
     * while the deactivation count is nonzero.
     */
    unsigned            deactivations;
    /* the composite driver won't complete the control transfer's
     * data/status stages till delayed_status is zero.
     */
    int                delayed_status;
    /* protects deactivations and delayed_status counts*/
    spinlock_t            lock;
};

307 struct usb_composite_driver {  // all compesite The drive must fill the structure .
308     const char              *name;
309     const struct usb_device_descriptor  *dev; // Must be realized
310     struct usb_gadget_strings       **strings;
311     enum usb_device_speed           max_speed;
312     unsigned        needs_serial:1;
313    
314     int         (*bind)(struct usb_composite_dev *cdev); // Must be realized
315     int         (*unbind)(struct usb_composite_dev *); // Must be realized
316    
317     void            (*disconnect)(struct usb_composite_dev *);
318    
319     /* global suspend hooks */
320     void            (*suspend)(struct usb_composite_dev *);
321     void            (*resume)(struct usb_composite_dev *);
322     struct usb_gadget_driver        gadget_driver; // This place is driven by composite Provide , All and composite Relevant drivers will be assigned by default . The driver is
323 };

 

 852 struct usb_gadget_driver {  // The driver is usbcore and composite It's an essential part of interaction between people , The connection between the two is mainly maintained by him , The kernel has already provided , It doesn't need us to achieve .
 853     char            *function;
 854     enum usb_device_speed   max_speed;
 855     int         (*bind)(struct usb_gadget *gadget,
 856                     struct usb_gadget_driver *driver);
 857     void            (*unbind)(struct usb_gadget *);
 858     int         (*setup)(struct usb_gadget *,    // Enumeration is an essential function in the process . There is no need to drive to achieve .
 859                     const struct usb_ctrlrequest *);
 860     void            (*disconnect)(struct usb_gadget *);
 861     void            (*suspend)(struct usb_gadget *);
 862     void            (*resume)(struct usb_gadget *);
 863    
 864     /* FIXME support safe rmmod */
 865     struct device_driver    driver;
 866 };

 

 

 

1772 static const struct usb_gadget_driver composite_driver_template = { // be-all composite The device will be registered at gadet When driving, use this instance to fill in .
                                                                         // I think the reason for this is gadget There will always be only one driver ,composite You can do whatever you want . Reflect the idea of stratification .
1773     .bind       = composite_bind,      
1774     .unbind     = composite_unbind,    
1775                                        
1776     .setup      = composite_setup,     
1777     .disconnect = composite_disconnect,                                                                                                                           
1778                                        
1779     .suspend    = composite_suspend,   
1780     .resume     = composite_resume,    
1781                                        
1782     .driver = {                        
1783         .owner      = THIS_MODULE,     
1784     },                                 
1785 };

 

 

Let's start with composite Driven registration process , After that, I will introduce the writing process of driver .

With zero.c For example :                                                                                                                    

  1.  

    static int __init init(void)  
    {  
        return usb_composite_register(&zero_driver);  
    }
    usb_composite_register(&zero_driver);
    1========》 driver->gadget_driver = composite_driver_template; // This process does not involve the analysis of compoite Device registration operation ,
                                                            // It's going to be composite Relevant information registered in the driver is filled in to gadget in , utilize gadget Go and udc Dealing with
         ---->return usb_gadget_probe_driver(gadget_driver);   This function first determines bind setup And so on . It doesn't need us to achieve .
         ---->  list_for_each_entry(udc, &udc_list, list) // Look for registered in the kernel udc example , Found, proceed to the next step , No exit . Driver registration failed .
         ---->  ret = udc_bind_to_driver(udc, driver);  // take udc and gadget Drivers are bound together .
    2======》 udc_bind_to_driver(udc, driver);
         ---->404     ret = driver->bind(udc->gadget, driver);// The key is this function , At the beginning of the author's analysis , Thought it was composite Of bind function , Later, it became clear that it was gadget layer
                                                              // Of bind function composite_bind , Will be introduced later .
        -----> ret = usb_gadget_udc_start(udc->gadget, driver); // Everything is in place ,udc The relevant settings have been written to the register .
        -----> ret = usb_gadget_connect(udc->gadget); // Insert host usb mouth , Check D+ The change of the level . That is, enumeration overshoot
    3=====》 composite_bind // The most important function . Is to understand gadget The key to design 

     

     

     

     

    1672 static int composite_bind(struct usb_gadget *gadget,// This function zhu If you implement configuration descriptor interface and other operations .
    1673         struct usb_gadget_driver *gdriver)
    1674 {           
    1675     struct usb_composite_dev    *cdev;
    1676     struct usb_composite_driver *composite = to_cdriver(gdriver);                                                                                                 
    1677     int             status = -ENOMEM;
    1678             
    1679     cdev = kzalloc(sizeof *cdev, GFP_KERNEL);
    1680     if (!cdev)
    1681         return status;
    1682             
    1683     spin_lock_init(&cdev->lock);
    1684     cdev->gadget = gadget;
    1685     set_gadget_data(gadget, cdev);
    1686     INIT_LIST_HEAD(&cdev->configs);
    1687     INIT_LIST_HEAD(&cdev->gstrings);
    1688             
    1689     status = composite_dev_prepare(composite, cdev);
    1690     if (status)
    1691         goto fail;
    1692             
    1693     /* composite gadget needs to assign strings for whole device (like
    1694     ┊* serial number), register function drivers, potentially update
    1695     ┊* power state and consumption, etc
    1696     ┊*/     
    1697     /* This is where you start calling the driver bind function */
    1698     status = composite->bind(cdev);
    1699     if (status < 0)
    1700         goto fail;
    1701             
    1702     update_unchanged_dev_desc(&cdev->desc, composite->dev);
    1703             
    1704     /* has userspace failed to provide a serial number? */
    1705     if (composite->needs_serial && !cdev->desc.iSerialNumber)
    1706         WARNING(cdev, "userspace failed to provide iSerialNumber\n");
    1707             
    1708     INFO(cdev, "%s ready\n", composite->name);
    1709     return 0;
    1710             
    1711 fail:       
    1712     __composite_unbind(gadget, false);
    1713     return status;
    }
    1====》  composite_bind
        ---->1676  struct usb_composite_driver *composite = to_cdriver(gdriver);  // This function will be gadet Convert to composite The key to . stay gadget Drivers are linked when they register .
                                                                                  //return container_of(gdrv, struct usb_composite_driver, gadget_driver);  
        ---->cdev = kzalloc(sizeof *cdev, GFP_KERNEL); // Realization cdev equipment .
        ---->set_gadget_data(gadget, cdev); // Fill in private data , So that the kernel can pass gadget obtain cdev.
        ---->INIT_LIST_HEAD(&cdev->configs); // Initialization configuration description list , At the beginning, I introduced , A device has one or more configurations .
        ---->1689     status = composite_dev_prepare(composite, cdev);  // This function is very important , Include usb_request、complete( Callback function implementation )、 Device and driver binding, etc )
        ---->1698 status = composite->bind(cdev) // This is where you start calling the driver bind function , This function will be described in detail later .
        ----> INFO(cdev, "%s ready\n", composite->name); // thus ,composite Device created successfully .

     

     

     

    1610 int composite_dev_prepare(struct usb_composite_driver *composite,  // This function mainly implements the most important usb_request, For endpoints 0, That is, controlling the endpoint
    1611         struct usb_composite_dev *cdev)                                                                                                                           
    1612 {   
    1613     struct usb_gadget *gadget = cdev->gadget;
    1614     int ret = -ENOMEM;
    1615     
    1616     /* preallocate control response and buffer */
    1617     cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); // Request control endpoint usb request
    1618     if (!cdev->req)
    1619         return -ENOMEM;
    1620     
    1621     cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); // The requested content will remain here
    1622     if (!cdev->req->buf)
    1623         goto fail;
    1624     
    1625     ret = device_create_file(&gadget->dev, &dev_attr_suspended);// Create device files , be located /sys/class/dev Under the table of contents
    1626     if (ret)
    1627         goto fail_dev;
    1628     
    1629     cdev->req->complete = composite_setup_complete;   // Callback function .
    1630     gadget->ep0->driver_data = cdev; // Get the device through the endpoint .
    1631     
    1632     cdev->driver = composite; // take composite Devices and drivers are tied together , therefore usb gadget There is no enumeration process at the end , The driver registered directly , Create device .
    1633     
    1634     /*
    1635     ┊* As per USB compliance update, a device that is actively drawing
    1636     ┊* more than 100mA from USB must report itself as bus-powered in
    1637     ┊* the GetStatus(DEVICE) call.
    1638     ┊*/
    1639     if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW)
    1640         usb_gadget_set_selfpowered(gadget);
    1641     
    1642     /* interface and string IDs start at zero via kzalloc.
    1643     ┊* we force endpoints to start unassigned; few controller
    1644     ┊* drivers will zero ep->driver_data.
    1645     ┊*/
    1646     usb_ep_autoconfig_reset(gadget);  //
    1647     return 0;
    1648 fail_dev
      
    1649 kfree(cdev->req->buf);
    1650 fail:
    /*  Here the knowledge is initialized usb Configure linked lists , Interfaces and endpoints are not instantiated , So the endpoint driver_data Reset to null again , Batch input and output point number is 0;
    1642 /* interface and string IDs start at zero via kzalloc.
    1643 ┊* we force endpoints to start unassigned; few controller
    1644 ┊* drivers will zero ep->driver_data.
    1645 ┊*/ 
    1646 usb_ep_autoconfig_reset(gadget);
    */  
    1651 usb_ep_free_request(gadget->ep0, cdev->req);  
      1652 cdev->req = NULL;
      1653 return ret;
      1654 }

     


    The next step is going to be a crucial one , call composite Driven bind function .

    1.  

       

       

      275 static int __init zero_bind(struct usb_composite_dev *cdev) // Inside is the realization of composite The key of equipment , Design to strings, Configuration descriptor , Interface (function)、 Instantiation of endpoints .
      /276 {                  
      277     struct f_ss_opts    *ss_opts;
      278     struct f_lb_opts    *lb_opts;
      279     int         status;
      280                    
      281     /* Allocate string descriptor numbers ... note that string
      282     ┊* contents can be overridden by the composite_dev glue.
      283     ┊*/            
      284     status = usb_string_ids_tab(cdev, strings_dev);
      285     if (status < 0)
      286         return status;
      287                    
      288     device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;// Manufacturer
      289     device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;// product Id
      290     device_desc.iSerialNumber = strings_dev[USB_GADGET_SERIAL_IDX].id;// Device serial number function index , I think it is aimed at many function In terms of equipment .
      291                    
      292     setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
      293                    
      294     func_inst_ss = usb_get_function_instance("SourceSink"); // obtain function, The implementation here is very clever , adopt usb_function_register Realization .
      295     if (IS_ERR(func_inst_ss))
      296         return PTR_ERR(func_inst_ss);
      297                    
      298     ss_opts =  container_of(func_inst_ss, struct f_ss_opts, func_inst);
      299     ss_opts->pattern = gzero_options.pattern;
      300     ss_opts->isoc_interval = gzero_options.isoc_interval;
      301     ss_opts->isoc_maxpacket = gzero_options.isoc_maxpacket;
      302     ss_opts->isoc_mult = gzero_options.isoc_mult;
      303     ss_opts->isoc_maxburst = gzero_options.isoc_maxburst;
      304     ss_opts->bulk_buflen = gzero_options.bulk_buflen; // Every time you send buf size
      305              
      306     func_ss = usb_get_function(func_inst_ss); // obtain source_link example , Similarly passed usb_function_register Register to get .
      307     if (IS_ERR(func_ss)) {
      308         status = PTR_ERR(func_ss);
      309         goto err_put_func_inst_ss;
      310     }              
      311     
      312     func_inst_lb = usb_get_function_instance("Loopback");
      313     if (IS_ERR(func_inst_lb)) {
      314         status = PTR_ERR(func_inst_lb);
      315         goto err_put_func_ss;
      316     }             
      317     
      318     lb_opts = container_of(func_inst_lb, struct f_lb_opts, func_inst);
      319     lb_opts->bulk_buflen = gzero_options.bulk_buflen; // stay usb_function_registe It's already allocated at the time of registration .
      320     lb_opts->qlen = gzero_options.qlen;
      321     
      322     func_lb = usb_get_function(func_inst_lb);
      323     if (IS_ERR(func_lb)) {
      324         status = PTR_ERR(func_lb);
      325         goto err_put_func_inst_lb;
      326     }             
      327     
      328     sourcesink_driver.iConfiguration = strings_dev[USB_GZERO_SS_DESC].id;// Set configuration descriptor index
      329     loopback_driver.iConfiguration = strings_dev[USB_GZERO_LB_DESC].id;
      330     
      331     /* support autoresume for remote wakeup testing */
      332     sourcesink_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
      333     loopback_driver.bmAttributes &= ~USB_CONFIG_ATT_WAKEUP;
      334     sourcesink_driver.descriptors = NULL;
      335     loopback_driver.descriptors = NULL;
      336     if (autoresume) {
      337         sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
      338         loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
      339         autoresume_step_ms = autoresume * 1000;
      340     }             
      341     
      342     /* support OTG systems */
      343     if (gadget_is_otg(cdev->gadget)) {
      344         sourcesink_driver.descriptors = otg_desc;
      345         sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
      346         loopback_driver.descriptors = otg_desc;
      347         loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
      348     }
      349                    
      350     /* Register primary, then secondary configuration.  Note that
      351     ┊* SH3 only allows one config...
      352     ┊*/            
      353     if (loopdefault) {// If only support loopback It's the loop mode .
      354         usb_add_config_only(cdev, &loopback_driver);// be loopback Configure register first
      355         usb_add_config_only(cdev, &sourcesink_driver);// After registration
      356     } else {       
      357         usb_add_config_only(cdev, &sourcesink_driver);// ditto
      358         usb_add_config_only(cdev, &loopback_driver);
      359     }              
      360     status = usb_add_function(&sourcesink_driver, func_ss);// Bind function as interface to configuration descriptor , Here's another one bind operation , It's very deep .
      361     if (status)    
      362         goto err_conf_flb;
      363                    
      364     usb_ep_autoconfig_reset(cdev->gadget);// To reset ep
      365     status = usb_add_function(&loopback_driver, func_lb);
      366     if (status)    
      367         goto err_conf_flb;
      368                    
      369     usb_ep_autoconfig_reset(cdev->gadget);
      370     usb_composite_overwrite_options(cdev, &coverwrite);// Support for parameter passing . modify iverdor iproduct etc. .
      371                    
      372     INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
      373                    
      374     return 0;      
      375                    
      376 err_conf_flb:      
      377     usb_put_function(func_lb);
      378     func_lb = NULL;
      379 err_put_func_inst_lb:
      380     usb_put_function_instance(func_inst_lb);
      381     func_inst_lb = NULL;
      382 err_put_func_ss:   
      383     usb_put_function(func_ss);
      384     func_ss = NULL;
      385 err_put_func_inst_ss:
      386     usb_put_function_instance(func_inst_ss);
      387     func_inst_ss = NULL;                                                                                                                                           
      388     return status; 
      389 }

       

      189 int usb_add_function(struct usb_configuration *config, // Instantiate the interface in the configuration .
       190         struct usb_function *function)
       191 {  
       192     int value = -EINVAL;
       193    
       194     DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",
       195             function->name, function,
       196             config->label, config);
       197    
       198     if (!function->set_alt || !function->disable)// Whether the interface is set set_alt function , This function call indicates that the current interface is available , Other interfaces are not available .
       199         goto done;
       200    
       201     function->config = config;
       202     list_add_tail(&function->list, &config->functions);
       203    
       204     /* REVISIT *require* function->bind? */
         205 if (function->bind) {
       206 value = function->bind(config, function);// For a configuration with multiple interfaces cdev equipment , Again function Conduct bin operation .
         207 if (value < 0) {
         208 list_del(&function->list);
         209 function->config = NULL;
         210 }
         211 } else
         212 value = 0;
         213 
         214 /* We allow configurations that don't work at both speeds.
         215 ┊* If we run into a lowspeed Linux system, treat it the same
         216 ┊* as full speed ... it's the function drivers that will need
         217 ┊* to avoid bulk and ISO transfers.
         218 ┊*/
         219 if (!config->fullspeed && function->fs_descriptors)
         220 config->fullspeed = true;
         221 if (!config->highspeed && function->hs_descriptors)
         222 config->highspeed = true;
         223 if (!config->superspeed && function->ss_descriptors)
         224 config->superspeed = true;
         225 
         226 done:
         227 if (value)
         228 DBG(config->cdev, "adding '%s'/%p --> %d\n",
         229 function->name, function, value);
         230 return value; 
         231 }

       

      With f_loopback.c Medium bind For example .

  2.  

    175 static int loopback_bind(struct usb_configuration *c, struct usb_function *f) // Tie configuration and functionality together
    176 {                   
    177     struct usb_composite_dev *cdev = c->cdev;
    178     struct f_loopback   *loop = func_to_loop(f);
    179     int         id; 
    180     int ret;        
    181                     
    182     /* allocate interface ID(s) */
    183     id = usb_interface_id(c, f);// Generally from 0 Start configuration . Assign interface id Number
    184     if (id < 0)     
    185         return id;  
    186     loopback_intf.bInterfaceNumber = id;
    187                     
    188     id = usb_string_id(cdev);// Get the character descriptor index
    189     if (id < 0)     
    190         return id;  
    191     strings_loopback[0].id = id;
    192     loopback_intf.iInterface = id;
    193                      
    194     /* allocate endpoints */
    195                      
    196     loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);// Assign batch input endpoints
    197     if (!loop->in_ep) {
    198 autoconf_fail:       
    199         ERROR(cdev, "%s: can't autoconfigure on %s\n",
    200             f->name, cdev->gadget->name);
    201         return -ENODEV;
    202     }                
    203     loop->in_ep->driver_data = cdev;    /* claim */
    204                      
    205     loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);// Assign batch output endpoints
    206     if (!loop->out_ep)
    207         goto autoconf_fail;
    208     loop->out_ep->driver_data = cdev;   /* claim */
    209                      
    210     /* support high speed hardware */
    211     hs_loop_source_desc.bEndpointAddress =
    212         fs_loop_source_desc.bEndpointAddress;
    213     hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
    214                      
    215     /* support super speed hardware */
    216     ss_loop_source_desc.bEndpointAddress =
    217         fs_loop_source_desc.bEndpointAddress;
    218     ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
    219                      
    220     ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs, // The main setting here is usb Speed .
    221             ss_loopback_descs);
    222     if (ret)         
    223         return ret;  
    224                      
    225     DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
    226     ┊   (gadget_is_superspeed(c->cdev->gadget) ? "super" :
    227     ┊   ┊(gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
    228             f->name, loop->in_ep->name, loop->out_ep->name);
    229     return 0;        
    230 }

     

    thus gadget The framework only drives the registration process . Next, we will introduce the process driven registration .

    1. fill usb_composite_driver Drive instance , call usb_composite_probe Make a note .
    2. Substitute stealthily , fill usb_composite Driving medium gadget_driver, call usb_gadget_probe_driver(gadget_driver); bring udc Can and composite Connect devices .
    3. call udc_bind_to_driver, Slowly udc and composite Bind together .
    4. call driver->bind(udc->gadget, driver); It's actually a call composite_bind function , This function is implemented by the kernel . The main purpose of this function is to create cdev equipment , Will really drive and cdev Bind together .
    5. After that, call the written driver bind function . At this time, it is mainly about cdev Equipment configuration and function Fill in . The device has to be configured , Configuration must have interfaces .
    6. For many function The driver , Must bind again bind function , This time, it's mainly about setting up interfaces id, Instantiation ep etc. .
    7. front 6 The completion of step operation , Express composite The device driver has been registered successfully . After success ? That's about the right udc Operating the ,udc Enter request connection state , Waiting for the interrupt response .
    8. Interrupt response is to respond to the enumeration operation initiated by the master device , Complete the enumeration process , Enumeration response is mainly called function->setup function . The enumeration process will be covered in another article .