A little research on Linux gadget routine analysis __linux

Source: Internet
Author: User
origin:https://blog.csdn.net/wuyuwei45/article/details/8939716

The more effective way to learn gadget is to study routines carefully after mastering the basic structure. Not only gadget, but other Linux drivers or subsystems. In addition, the peripheral drivers of Linux usually have layered concept, with object-oriented ideas, so the study of code is a more effective way to understand.

Generally a Linux USB device driver, including two parts, one is the CPU USB controller part of the driver, driver file name is often xxx_udc.c, this part of the drive is related to the hardware CPU, including register settings, DMA settings, and this part also soft USB Gadget architecture of things, usually this part of the code is relatively boring and difficult to understand, each CPU platform, this part of the code is very different, but fortunately this part of the Code General Factory Chamber of Commerce to provide. The second is gadget function drive, if the USB controller driver is the body, then this part is the soul, USB to be in the communication is what type of equipment (HID. Keyboard. U disk. , how to transmit and so on are all implemented in this partial drive.

The Linux kernel source driver/usb/gadget/zero.c is a good gadget function-driven framework that is intended to be used by the kernel developers to facilitate Third-party USB controllers to drive developer Test UDC drivers.

First on a routine, this routine is Huaqingyuan see Liu Hongtao a routine written in the USB driver section, although routines still have a lot of optimizations and redundancies, this routine is a wonderful illustration of how to develop a gadget feature driver, although the way in which a registered character device driver is described in a routine is stale.

Before I put this routine on, I changed part of the code format for easy reading.[CPP] View Plain Copy/*    * zero.c -- gadget zero, for simple usb  development   * All rights reserved.   */       /*  #define  VERBOSE_DEBUG */      #include  <linux/kernel.h>    #include  <linux/utsname.h>   #include  <linux/device.h>   # include <linux/usb/ch9.h>   #include  <linux/usb/gadget.h>   #include   "Gadget_chips.h"    #include  <linux/slab.h>   #include  <linux/ module.h>   #include  <linux/init.h>   #include  <linux/usb/input.h>    #include  <linux/cdev.h>   #include  <asm/uaccess.h>   # include <linux/fs.h>   #include  <linux/poll.h>   #include  < Linux/types.h> /* size_t */   #include  <linux/errno.h> /* error codes  */   #include  <asm/system.h>   #include  <asm/io.h>   # include <linux/sched.h>     /*-------------------------------------------------- -----------------------*/   static const char shortname[] =  "Zero";    static const char loopback[] =  "Loop input to output";    static const char longname[] =  "Gadget zero";   static const  char source_sink[] =  "Source and sink data";   #define   string_manufacturer 25   #define  STRING_PRODUCT 42   #define  string_ serial 101   #define  STRING_SOURCE_SINK 250   #define  string_loopback  251     //#define  DRIVER_VENDOR_NUM 0x0525 /* NetChip */  //# define driver_product_num 0xa4a0 /* linux-usb  "Gadget zero"  */   define driver_vendor_num 0x5345 /* netchip */   #define  driver_product_ num 0x1234 /* linux-usb  "Gadget zero"  */      static int  usb_zero_major = 251;  /*----------------------------------------------------------- --------------*/   static const char *ep_out_name; /* sink */   /*-------------------------------------------------------------------------*/     /*  big enough to hold our biggest descriptor */   #define   usb_bufsiz 256   struct zero_dev    {       // Zero deviceStructure        spinlock_t lock;       struct usb _gadget *gadget;       struct usb_request *req; /* for  control responses */       struct usb_ep *out_ep;        struct cdev cdev;       unsigned  char data[128];       unsigned int data_size;        wait_queue_head_t bulkrq;   };   #define  config_loopback  2   static struct usb_device_descriptor device_desc =    {         //Device Descriptor        .bLength =  sizeof device_desc,       .bDescriptorType = USB_DT_DEVICE,        .bcdusb = __constant_cpu_to_le16 (0x0110),       . bdeviceclass = usb_class_vendor_spec,       .idvendor = __ Constant_cpu_to_le16 (driver_vendor_num),       .idproduct = __constant_ Cpu_to_le16 (driver_product_num),       .imanufacturer = string_ manufacturer,       .iProduct = STRING_PRODUCT,        .iSerialNumber = STRING_SERIAL,       .bnumconfigurations  = 1,  };   Static struct usb_endpoint_descriptor fs_sink_desc  =    {        //Endpoint Descriptor         .bLength = USB_DT_ENDPOINT_SIZE,       .bdescriptortype =  usb_dt_endpoint,       .bendpointaddress = usb_dir_out, //on the host side, output         .bmAttributes = USB_ENDPOINT_XFER_BULK,    };       static struct usb_config_descriptor loopback_config =    {         //Configuration Descriptor        .bLength = sizeof  loopback_config,       .bDescriptorType = USB_DT_CONFIG,       /* compute wTotalLength on the fly */        .bNumInterfaces = 1,       .bConfigurationValue  = config_loopback,       .iConfiguration = STRING_LOOPBACK,        .bmattributes = usb_config_att_one | usb_config_att_ Selfpower, &nbSp     .bMaxPower = 1, /* self-powered */    };        static const struct usb_interface_descriptor loopback_intf =     {        //Interface descriptor        . blength = sizeof loopback_intf,       .bdescriptortype =  USB_DT_INTERFACE,       .bNumEndpoints = 1,        .bInterfaceClass = USB_CLASS_VENDOR_SPEC,       . iinterface = string_loopback,  };     /* static strings,  in UTF-8 */   #define  STRING_MANUFACTURER          25   #define  STRING_PRODUCT               42   #define  STRING_SERIAL                101   #define  STRING_SOURCE_SINK           250   #define  STRING_LOOPBACK              251   static char manufacturer[50];   /* default serial number takes at least two packets */    static char serial[] =  "0123456789.0123456789.0123456789";   static  struct usb_string strings[] =    {         //String Descriptor        { STRING_MANUFACTURER, manufacturer, },        { STRING_PRODUCT, longname, },        { string_serial, serial, },       { string_loopback, loopback, },        { STRING_SOURCE_SINK, source_sink, },        { } /* end of list */  };      static struct usb_gadget_strings stringtab =    {        .language = 0x0409, /* en-us */       . strings = strings,  };      static const struct usb_ descriptor_header *fs_loopback_function[] =    {        ( struct usb_descriptor_header *)  &loopback_intf,        (struct  usb_descriptor_header *)  &fs_sink_desc,       NULL,   };   &Nbsp;     Static void free_ep_req (struct usb_ep *ep, struct usb_ Request *req)    {       kfree (req->buf);        usb_ep_free_request (ep, req);  }      Static struct usb _request *alloc_ep_req (struct usb_ep *ep, unsigned length)/allocation request    {        struct usb_request *req;       req =  usb_ep_alloc_request (ep, gfp_atomic);       if  (req)        {           req->length =  length;           req->buf = kmalloc ( length, gfp_atomic);           if  (!REQ-&GT;BUF)   &nbsp         {                usb_ep_free_request (ep, req);                req = NULL;            }       }       return req;   }      Static void source_sink_complete (struct usb_ep *ep,  STRUCT&NBSP;USB_REQUEST&NBSP;*REQ)//Request completion function    {       struct zero_ dev *dev = ep->driver_data;       int status =  req->status;       switch  (status)          {           case 0: /* normal  completion */                    if  (EP&NBSP;==&NBSP;DEV-&GT;OUT_EP)                      {                        memcpy (dev->data, req- >buf, req->actual)//Return data copy to Req->buf, //dev->data_size=req->length;                          dev->data_size=req->actual; //actual length for req->actual; needs confirmation req –>short_not_ OK is 0. Reference gadget.h comments                on Usb_request structure      }                 break; &nbsp         /* this endpoint is normally active  while we ' re configured */           case  -ECONNABORTED: /* hardware forced ep reset */            case -econnreset:   /* request dequeued  */           case -ESHUTDOWN:     /* disconnect from host */           &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK ("%s gone  (%d),  %d/%d/n",  ep- >name, status,req->actual, req->length);            case -EOVERFLOW:            /*  buffer overrun on read means that           * we  Didn ' t provide a big enough           *  buffer.           */            default:            #if  1    &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK ("%s complete  --> %d, %d/%d/n ", ep->name,                status, req->actual, req->length);             #endif            case - eremoteio: /* short read */                break;       }       free_ep_req (ep, req);        wake_up_interruptible  (&AMP;DEV-&GT;BULKRQ);  //Wake read function    }      Static struct usb_request *source_sink_start_ep (struct usb_ep &NBSP;*EP)//constructs and sends read requests    {       struct usb_request *req;        int status;   &NBSP;&NBSP;&NBSP;&NBSP;//PRINTK ("in %s/n", __ function__);       req = alloc_ep_req (ep, 128);        if  (!req)            return NULL;        memset (req->buf, 0, req->length);        req->complete = source_sink_complete; //Request Completion function         staTus = usb_ep_queue (ep, req, gfp_atomic)  //Submit Request        if   (status)         {             struct zero_dev *dev = ep->driver_data;       &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;PRINTK ("start %s --> %d/n", ep->name,  Status);            free_ep_req (ep, req);             req = NULL;        }       return req;  }      Static  int usb_zero_open  (Struct inode *inode, struct file *file)  // Open Equipment    {       struct zero_dev *dev = container_of   (Inode->i_cdev,  struct zero_dev, cdev)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.