USB设备驱动程序-USB Gadget Driver

转载 2017年01月03日 08:42:55

USB设备驱动程序-USB Gadget Driver(三)

4680阅读 0评论2013-10-10 visualfan
分类:LINUX

Gadget设备层

       这一层是可选的,介于UDC驱动层和Gadget功能层之间。主要源码在composite.c和composite.h文件中,设备层其实和硬件无关,主要实现一些通用性的代码,减少gadget功能层的代码重复工作。Gadget设备层其中承上启下的作用,联系Gadget功能层和UDC驱动层。

       将composite源码独立出来,还为复合设备的实现提供了一个通用性的框架。复合设备是指在一个配置描述符中支持多个功能,或者支持多个配置的设备中,每个配置都有一个不同的功能。如一个设备同时支持网络和存储,一个设备同时支持键盘和鼠标功能等。

Gadget设备层的主要数据结构:

1. Function

struct usb_function { //描述一个配置的一个功能

                                    const char *name; //功能名称

                                    struct usb_gadget_strings **strings; //string数组,通过bind中分配的id访问

                                    struct usb_descriptor_header **descriptors; //全速和低速的描述符表,用于bind中分配的接口描述符和string描述符

                                    struct usb_descriptor_header **hs_descriptors; //高速描述符表

                                     struct usb_configuration *config;//调用usb_add_function()函数赋值,是这个功能关联的配置描述符

                                   /* REVISIT: bind() functions can be marked __init, which

                                     * makes trouble for section mismatch analysis. See if

                                     * we can't restructure things to avoid mismatching.

                                     * Related: unbind() may kfree() but bind() won't...

                                    */

                                    /* configuration management: bind/unbind */

                                     /*在Gadget注册时,分配资源*/

                                   int (*bind)(struct usb_configuration *, struct usb_function *);

                                    /*unbind的逆操作*/

                                    void (*unbind)(struct usb_configuration *, struct usb_function *);

                                   /* runtime state management */

                                   /*重新配置altsetting,*/

                                   int (*set_alt)(struct usb_function *,unsigned interface, unsigned alt);

                                   /*获取当前altsetting*/

                                   int (*get_alt)(struct usb_function *, unsigned interface);

                                     /*关闭功能*/

                                     void (*disable)(struct usb_function *);

                                     /*接口相关的控制处理*/

                                    int (*setup)(struct usb_function *, const struct usb_ctrlrequest *);

                                    /*电源管理相关的挂起和恢复功能*/

                                    void (*suspend)(struct usb_function *);

                                    void (*resume)(struct usb_function *);

                                   /* private: */

                                  /* internals */

                                    struct list_head list;

                                     DECLARE_BITMAP(endpoints, 32);

};

2. Config

struct usb_configuration { //表示一个Gadget配置

                                              const char *label; //配置名称

                                   struct usb_gadget_strings **strings; //字符串表

                                    const struct usb_descriptor_header **descriptors; //功能描述符表

                                      /* REVISIT: bind() functions can be marked __init, which

                                        * makes trouble for section mismatch analysis. See if

                                         * we can't restructure things to avoid mismatching...

                                       */

                                       /* configuration management: bind/unbind */

                                       /*在usb_add_config函数中调用,分配资源等*/

                                        int (*bind)(struct usb_configuration *);

                                        void (*unbind)(struct usb_configuration *);

                                     /*处理驱动框架不能处理的配置控制请求*/

                                          int (*setup)(struct usb_configuration *, const struct usb_ctrlrequest *);

                                     /* fields in the config descriptor */

                                     /*用来赋值配置描述符*/

                                      u8 bConfigurationValue;

                                       u8 iConfiguration;

                                       u8 bmAttributes;

                                       u8 bMaxPower;

                                   /*和composite设备关联,在usb_add_config函数中设置*/

                                      struct usb_composite_dev *cdev;

                                   /* private: */

                                    /* internals */

                                       struct list_head list;

                                        struct list_head functions; //功能链表

                                        u8 next_interface_id;

                                        unsigned highspeed:1;

                                         unsigned fullspeed:1;

                                          struct usb_function *interface[MAX_CONFIG_INTERFACES];

};

3. Driver

struct usb_composite_driver {

                                                  const char *name; //驱动名称

                                                  const struct usb_device_descriptor *dev; //设备描述符

                                                  struct usb_gadget_strings **strings; //字符串表

                                                   /* REVISIT: bind() functions can be marked __init, which

                                                    * makes trouble for section mismatch analysis. See if

                                                    * we can't restructure things to avoid mismatching...

                                                     */

                                                  int (*bind)(struct usb_composite_dev *);

                                                  int (*unbind)(struct usb_composite_dev *);

                                                  /* global suspend hooks */

                                                 void (*suspend)(struct usb_composite_dev *);

                                                 void (*resume)(struct usb_composite_dev *);

};

4. Dev

struct usb_composite_dev { //表示一个composite设备

                                             struct usb_gadget *gadget; //关联的gadget

                                             struct usb_request *req; //用于控制响应,提前分配的

                                              unsigned bufsiz; //req中提前分配的buffer长度

                                             struct usb_configuration *config; //当前配置

                                                        /* private: */

                                              /* internals */

                                            struct usb_device_descriptor desc;

                                            struct list_head configs; //配置链表

                                             struct usb_composite_driver *driver;

                                              u8 next_string_id;

                                           /* the gadget driver won't enable the data pullup

                                             * while the deactivation count is nonzero.

                                            */

                                             unsigned deactivations;

                                             /* protects at least deactivation count */

                                            spinlock_t lock;

};

其中重要的函数:

1.

static int __init composite_bind(struct usb_gadget *gadget)

{

          struct usb_composite_dev *cdev;

           int status = -ENOMEM;

           cdev = kzalloc(sizeof *cdev, GFP_KERNEL); //分配一个composite设备对象

           if (!cdev)

                         return status;

            spin_lock_init(&cdev->lock);

            /*将udc gadget和composite设备建立关系*/

             cdev->gadget = gadget;

            set_gadget_data(gadget, cdev);

             INIT_LIST_HEAD(&cdev->configs); //初始化配置链表

               /* preallocate control response and buffer */

              /*分配控制端点的请求数据结构和缓存区*/

             cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);

             if (!cdev->req)

                                      goto fail;

             cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); //分配控制请求的缓冲区

            if (!cdev->req->buf)

                                      goto fail;

             cdev->req->complete = composite_setup_complete; //端的0的完成函数

             gadget->ep0->driver_data = cdev;

              cdev->bufsiz = USB_BUFSIZ;

               cdev->driver = composite;

           /*设置gadget的供电模式*/

            usb_gadget_set_selfpowered(gadget);

          /* interface and string IDs start at zero via kzalloc.

           * we force endpoints to start unassigned; few controller

           * drivers will zero ep->driver_data.

           */

           /*将所有端点的driver_data成员清零*/

            usb_ep_autoconfig_reset(cdev->gadget);

         /* composite gadget needs to assign strings for whole device (like

           * serial number), register function drivers, potentially update

           * power state and consumption, etc

          */

         /*调用功能层提供的bind函数,分配资源*/

         status = composite->bind(cdev);

         if (status < 0)

                          goto fail;

          /*设置composite设备的设备描述符*/

          cdev->desc = *composite->dev;

           cdev->desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

          /* standardized runtime overrides for device ID data */

          /*设置composite设备的设备描述符信息*/

         if (idVendor)

                        cdev->desc.idVendor = cpu_to_le16(idVendor);

         if (idProduct)

                       cdev->desc.idProduct = cpu_to_le16(idProduct);

        if (bcdDevice)

                       cdev->desc.bcdDevice = cpu_to_le16(bcdDevice);

         /* strings can't be assigned before bind() allocates the

          * releavnt identifiers

          */

          /*设置字符串描述符*/

        if (cdev->desc.iManufacturer && iManufacturer)

                          string_override(composite->strings, cdev->desc.iManufacturer, iManufacturer);

       if (cdev->desc.iProduct && iProduct)

                         string_override(composite->strings, cdev->desc.iProduct, iProduct);

      if (cdev->desc.iSerialNumber && iSerialNumber)

                          string_override(composite->strings, cdev->desc.iSerialNumber, iSerialNumber);

         INFO(cdev, "%s ready\n", composite->name);

          return 0;

fail:

               composite_unbind(gadget);

              return status;

}

Composite_bind函数主要完成UDC驱动层gadget设备和设备层composite设备关系的建立,分配控制端点0的请求数据结构,设置设备描述符,并调用功能层的bind函数分配功能层所需要的资源等工作。

2.

static void /* __init_or_exit */ composite_unbind(struct usb_gadget *gadget)

{

                  struct usb_composite_dev *cdev = get_gadget_data(gadget);

                             /* composite_disconnect() must already have been called

                    * by the underlying peripheral controller driver!

                     * so there's no i/o concurrency that could affect the

                     * state protected by cdev->lock.

                    */

                    WARN_ON(cdev->config);

                   while ( !list_empty(&cdev->configs)) { //遍历设备的配置链表

                                      struct usb_configuration *c;

                                      c = list_first_entry(&cdev->configs, struct usb_configuration, list);

                                      while (!list_empty(&c->functions)) { //遍历这个配置下的所有功能

                                                             struct usb_function *f;

                                                              f = list_first_entry(&c->functions, struct usb_function, list);

                                                               list_del(&f->list);

                                                              if (f->unbind) { //调用功能的unbind函数

                                                                                     DBG(cdev, "unbind function '%s'/%p\n", f->name, f);

                                                                                     f->unbind(c, f);

                                                                                     /* may free memory for "f" */

                                                                }

                                         }

                                        list_del(&c->list);

                                        if (c->unbind) { //调用配置的unbind函数

                                                            DBG(cdev, "unbind config '%s'/%p\n", c->label, c);

                                                                      c->unbind(c);

                                                            /* may free memory for "c" */

                                          }

                   }

                  if (composite->unbind) //调用功能驱动的unbind函数

                                  composite->unbind(cdev);

                 if (cdev->req) { //释放分配的控制请求的缓存区

                                 kfree(cdev->req->buf);

                                usb_ep_free_request(gadget->ep0, cdev->req);

                 }

                kfree(cdev); //释放composite设备

                set_gadget_data(gadget, NULL);

                composite = NULL;

}

Unbind函数完成bind函数中分配的资源,并遍历所有配置和各个配置下的功能,调用其对应得unbind函数来释放资源。

其他重要函数:

在配置中增加一个功能,每个配置初始化后都必须至少有一个功能。

int __init usb_add_function(struct usb_configuration *config, struct usb_function *function)

{

                 int value = -EINVAL;

                  DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n",function->name, function,config->label, config);

                  if (!function->set_alt || !function->disable)

                                           goto done;

                  /*设置功能所属配置,并将功能加入配置的链表中*/

                   function->config = config;

                   list_add_tail(&function->list, &config->functions);

                   /* REVISIT *require* function->bind? */

                   if (function->bind) { //调用功能的bind函数

                                                  value = function->bind(config, function); //分配这个功能所需要的资源

                                                   if (value < 0) {

                                                                         list_del(&function->list);

                                                                         function->config = NULL;

                                                   }

                    }

                    else

                                     value = 0;

                   /* 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.

                      */

                   if (!config->fullspeed && function->descriptors)

                                                   config->fullspeed = true;

                    if (!config->highspeed && function->hs_descriptors)

                                                 config->highspeed = true;

         done:

                   if (value)

                                DBG(config->cdev, "adding '%s'/%p --> %d\n", function->name, function, value);

                  return value;

}

/*为设备增加一个配置,这个实现原理和在配置下增加一个功能类似*/

int __init usb_add_config(struct usb_composite_dev *cdev, struct usb_configuration *config)

{

                 int status = -EINVAL;

                  struct usb_configuration *c;

                  DBG(cdev, "adding config #%u '%s'/%p\n", config->bConfigurationValue, config->label, config);

                  if (!config->bConfigurationValue || !config->bind)

                                            goto done;

                     /* Prevent duplicate configuration identifiers */

                         list_for_each_entry(c, &cdev->configs, list) { //若配置已经加入了,则不需要再加

                                                 if (c->bConfigurationValue == config->bConfigurationValue) {

                                                                                    status = -EBUSY;

                                                                                     goto done;

                                                 }

                            }

                        /*将这个配置加入composite设备*/

                         config->cdev = cdev;

                         list_add_tail(&config->list, &cdev->configs);

                         /*初始化这个配置的功能链表头*/

                         INIT_LIST_HEAD(&config->functions);

                         config->next_interface_id = 0;

                          status = config->bind(config); //完成这个配置的资源分配

                           if (status < 0) {

                                                       list_del(&config->list);

                                                      config->cdev = NULL;

                            }

                            else

                            {

                                                      unsigned i;

                                                      DBG(cdev, "cfg %d/%p speeds:%s%s\n", config->bConfigurationValue, config, config->highspeed ? " high" : "",

                                                              config->fullspeed? (gadget_is_dualspeed(cdev->gadget)? " full": " full/low"): "");

                                                      for (i = 0; i < MAX_CONFIG_INTERFACES; i++) { //查看这个配置下有哪有功能

                                                                                     struct usb_function *f = config->interface[i];

                                                                                     if (!f)

                                                                                             continue;

                                                                                     DBG(cdev, " interface %d = %s/%p\n",i, f->name, f);

                                                         }

                            }

                          /* set_alt(), or next config->bind(), sets up

                            * ep->driver_data as needed.

                          */

                           //将gadget设备的所有端点的driver_data清零

                            usb_ep_autoconfig_reset(cdev->gadget);

              done:

                           if (status)

                                           DBG(cdev, "added config '%s'/%u --> %d\n", config->label, config->bConfigurationValue, status);

                           return status;

}

 

/*设置一个配置*/

static int set_config(struct usb_composite_dev *cdev, const struct usb_ctrlrequest *ctrl, unsigned number)

{

                   struct usb_gadget *gadget = cdev->gadget;

                   struct usb_configuration *c = NULL;

                    int result = -EINVAL;

                    unsigned power = gadget_is_otg(gadget) ? 8 : 100;

                     int tmp;

                   if (cdev->config)

                                  reset_config(cdev); //清除设备目前使用的配置

                  if (number) { //根据配置值找到对应的配置

                                       list_for_each_entry(c, &cdev->configs, list) {

                                                                          if (c->bConfigurationValue == number) {

                                                                                                        result = 0;

                                                                                                        break;

                                                                          }

                                      }

                                     if (result < 0) //没有找到这个配置

                                                      goto done;

                 }

                else

                          result = 0;

              INFO(cdev, "%s speed config #%d: %s\n", ({ char *speed;

                           switch (gadget->speed) {

                                              case USB_SPEED_LOW: speed = "low"; break;

                                             case USB_SPEED_FULL: speed = "full"; break;

                                            case USB_SPEED_HIGH: speed = "high"; break;

                                             default: speed = "?"; break;

                           } ; speed; }), number, c ? c->label : "unconfigured");

          if (!c)

                      goto done;

         cdev->config = c; //设置为设备使用的配置

        /* Initialize all interfaces by setting them to altsetting zero. */

           for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) {

                                struct usb_function *f = c->interface[tmp];

                                struct usb_descriptor_header **descriptors;

                                if (!f)

                                                           break;

                                 /*

                                           * Record which endpoints are used by the function. This is used

                                          * to dispatch control requests targeted at that endpoint to the

                                          * function's setup callback instead of the current

                                          * configuration's setup callback.

                                 */

                                if (gadget->speed == USB_SPEED_HIGH)

                                                      descriptors = f->hs_descriptors;

                                else

                                                      descriptors = f->descriptors;

                               for (; *descriptors; ++descriptors) { //遍历功能的所有端点描述符

                                                     struct usb_endpoint_descriptor *ep;

                                                    int addr;

                                                    if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT)

                                                                                      continue;

                                                     ep = (struct usb_endpoint_descriptor *)*descriptors;

                                                     addr = ((ep->bEndpointAddress & 0x80) >> 3) | (ep->bEndpointAddress & 0x0f);

                                                   set_bit(addr, f->endpoints); //这个功能采用的端点号

                                  }

                                  result = f->set_alt(f, tmp, 0); //设置功能的默认值

                                 if (result < 0) {

                                                    DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n", tmp, f->name, f, result);

                                                    reset_config(cdev);

                                                     goto done;

                                   }

                 }

               /* when we return, be sure our power usage is valid */

                        power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW;

    done:

             usb_gadget_vbus_draw(gadget, power);

              return result;

}

/*这个setup函数完成了ep0所需要处理的而底层不能处理的功能,由于这一个层实现了这个函数,所以功能层就不需要关注于USB协议的这些事务性处理,而重点放在需要实现的功能上*/

static int composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)

{

                  struct usb_composite_dev *cdev = get_gadget_data(gadget); //由gadget获取composite设备

                  struct usb_request *req = cdev->req; //控制请求

                  int value = -EOPNOTSUPP;

                   u16 w_index = le16_to_cpu(ctrl->wIndex);

                    u8 intf = w_index & 0xFF;

                    u16 w_value = le16_to_cpu(ctrl->wValue);

                   u16 w_length = le16_to_cpu(ctrl->wLength);

                 struct usb_function *f = NULL;

                 u8 endp;

               /* partial re-init of the response message; the function or the

                   * gadget might need to intercept e.g. a control-OUT completion

                * when we delegate to it.

                */

              //初始化响应请求信息

                req->zero = 0;

                req->complete = composite_setup_complete;

               req->length = USB_BUFSIZ;

               gadget->ep0->driver_data = cdev;

               switch (ctrl->bRequest) { //根据请求类型处理

                                                 /* we handle all standard USB descriptors */

                                               case USB_REQ_GET_DESCRIPTOR: //返回描述符

                                                                        if (ctrl->bRequestType != USB_DIR_IN)

                                                                                                      goto unknown;

                                                                       switch (w_value >> 8) {

                                                                                                   case USB_DT_DEVICE: //返回设备描述符

                                                                                                                         cdev->desc.bNumConfigurations =  count_configs(cdev, USB_DT_DEVICE);

                                                                                                                          value = min(w_length, (u16) sizeof cdev->desc);

                                                                                                                          memcpy(req->buf, &cdev->desc, value);

                                                                                                                          break;

                                                                                                     case USB_DT_DEVICE_QUALIFIER: //返回qualifier描述符

                                                                                                                          if (!gadget_is_dualspeed(gadget))

                                                                                                                                                           break;

                                                                                                                           device_qual(cdev);

                                                                                                                          value = min_t(int, w_length, sizeof(struct usb_qualifier_descriptor));

                                                                                                                          break;

                                                                                                    case USB_DT_OTHER_SPEED_CONFIG:

                                                                                                                           if (!gadget_is_dualspeed(gadget))

                                                                                                                                                               break;

                                                                                                                            /* FALLTHROUGH */

                                                                                                    case USB_DT_CONFIG: //返回配置描述符

                                                                                                                           value = config_desc(cdev, w_value);

                                                                                                                           if (value >= 0)

                                                                                                                                                  value = min(w_length, (u16) value);

                                                                                                                            break;

                                                                                                      case USB_DT_STRING: //返回字符串描述符

                                                                                                                             value = get_string(cdev, req->buf, w_index, w_value & 0xff);

                                                                                                                             if (value >= 0)

                                                                                                                                                      value = min(w_length, (u16) value);

                                                                                                                             break;

                                                                                       }

                                                                             break;

                                                                             /* any number of configs can work */

                                       case USB_REQ_SET_CONFIGURATION: //设置配置

                                                                            if (ctrl->bRequestType != 0)

                                                                                                      goto unknown;

                                                                           if (gadget_is_otg(gadget)) {

                                                                                                    if (gadget->a_hnp_support)

                                                                                                                          DBG(cdev, "HNP available\n");

                                                                                                     else if (gadget->a_alt_hnp_support)

                                                                                                                          DBG(cdev, "HNP on another port\n");

                                                                                                    else

                                                                                                                         VDBG(cdev, "HNP inactive\n");

                                                                               }

                                                                            spin_lock(&cdev->lock);

                                                                             value = set_config(cdev, ctrl, w_value);

                                                                             spin_unlock(&cdev->lock);

                                                                             break;

                                   case USB_REQ_GET_CONFIGURATION: //返回当前配置

                                                                          if (ctrl->bRequestType != USB_DIR_IN)

                                                                                                                  goto unknown;

                                                                         if (cdev->config)

                                                                                                                *(u8 *)req->buf = cdev->config->bConfigurationValue;

                                                                         else

                                                                                                                   *(u8 *)req->buf = 0;

                                                                          value = min(w_length, (u16) 1);

                                                                           break;

                            /* function drivers must handle get/set altsetting; if there's

                             * no get() method, we know only altsetting zero works.

                             */

                           case USB_REQ_SET_INTERFACE: //设置接口设置

                                                                         if (ctrl->bRequestType != USB_RECIP_INTERFACE)

                                                                                                                         goto unknown;

                                                                        if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)

                                                                                                                          break;

                                                                        f = cdev->config->interface[intf];

                                                                        if (!f)

                                                                                     break;

                                                                       if (w_value && !f->set_alt)

                                                                                      break;

                                                                      value = f->set_alt(f, w_index, w_value);

                                                                       break;

                                 case USB_REQ_GET_INTERFACE: //返回接口设置

                                                                   if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE))

                                                                                                    goto unknown;

                                                                  if (!cdev->config || w_index >= MAX_CONFIG_INTERFACES)

                                                                                                    break;

                                                                    f = cdev->config->interface[intf];

                                                                  if (!f)

                                                                                                break;

                                                                  /* lots of interfaces only need altsetting zero... */

                                                                   value = f->get_alt ? f->get_alt(f, w_index) : 0;

                                                                   if (value < 0)

                                                                                                    break;

                                                                  *((u8 *)req->buf) = value;

                                                                  value = min(w_length, (u16) 1);

                                                                   break;

                                default:

   unknown:

              VDBG(cdev, "non-core control req%02x.%02x v%04x i%04x l%d\n",ctrl->bRequestType, ctrl->bRequest,w_value, w_index, w_length);

              /* functions always handle their interfaces and endpoints...

                * punt other recipients (other, WUSB, ...) to the current

                * configuration code.

                *

                * REVISIT it could make sense to let the composite device

                * take such requests too, if that's ever needed: to work

                * in config 0, etc.

              */

          switch (ctrl->bRequestType & USB_RECIP_MASK) {

                       case USB_RECIP_INTERFACE:

                                       f = cdev->config->interface[intf];

                                       break;

                      case USB_RECIP_ENDPOINT:

                                      endp = ((w_index & 0x80) >> 3) | (w_index & 0x0f);

                                       list_for_each_entry(f, &cdev->config->functions, list) {

                                                    if (test_bit(endp, f->endpoints))

                                                                                     break;

                                         }

                                       if (&f->list == &cdev->config->functions)

                                                                     f = NULL;

                                     break;

       }

       if (f && f->setup)

                       value = f->setup(f, ctrl);

     else {

                        struct usb_configuration *c;

                         c = cdev->config;

                         if (c && c->setup)

                                       value = c->setup(c, ctrl);

       }

     goto done;

}

   /* respond with data transfer before status phase? */

    if (value >= 0) {

                           req->length = value;

                              req->zero = value < w_length;

                          value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);

                        if (value < 0) {

                                        DBG(cdev, "ep_queue --> %d\n", value);

                                         req->status = 0;

                                       composite_setup_complete(gadget->ep0, req);

                      }

         }

done:

           /* device either stalls (value < 0) or reports success */

             return value;

}


USB设备驱动程序-USB Gadget Driver(二)

1. UDC驱动是作为platform driver向platform子系统注册的,因此UDC驱动首先就需要实现struct platform_driver结构中的函数成员: struct ...
  • lxy9712
  • lxy9712
  • 2016年03月22日 16:24
  • 578

USB设备驱动程序-USB Gadget Driver(三)

Gadget设备层        这一层是可选的,介于UDC驱动层和Gadget功能层之间。主要源码在composite.c和composite.h文件中,设备层其实和硬件无关,主要实现一些通用...
  • lxy9712
  • lxy9712
  • 2016年03月22日 16:27
  • 594

USB设备驱动程序-USB Gadget Driver(四)

Gadget 功能层 Gadget功能层完成USB设备的具体功能,其表现的形式各不相同,如键盘、鼠标、存储和网卡等等。功能层不仅涉及到Gadget驱动相关的内容,还涉及到其功能相关的内核子系统。...
  • lxy9712
  • lxy9712
  • 2016年03月22日 16:28
  • 465

转-用Driver Studio工具包开发WDM型的USB设备驱动程序

前文所提及的WDM驱动程序开发方法,笔者都曾尝试过。个人认为用DriverStudio开发工具包来开发USB驱动程序行之有效。其中的Driver Wizard是创建WDM驱动程序框架的一个很好的工具,...

windows CE下的USB设备驱动程序分析 .

随着USB设备的不断增加,我们这些开发人员也就多了对USB设备进行驱动程序开发的工作。但是对于很多初学者来说,存在以下三个困难:      一是对WinCE的驱动程序结构了解得太少,没办法得心应手的...
  • js_gary
  • js_gary
  • 2012年02月09日 17:21
  • 1328

怎样写linux下的USB设备驱动程序

引言 随着人们生活水平的提高,我们用到的USB设备也越来越多,但是Linux在硬件配置上仍然没有做到完全即插即用,对于Linux怎样配置和使用他们,也越来越成为困扰我们的一大问题;本文的目地是使大家...

怎样写linux下的USB设备驱动程序

怎样写linux下的USB设备驱动程序 引言 随着人们生活水平的提高,我们用到的USB设备也越来越多,但是Linux在硬件配置上仍然没有做到完全即插即用,对于Linux怎样配置和使用他们,也越...

怎样写linux下的USB设备驱动程序

引言 随着人们生活水平的提高,我们用到的USB设备也越来越多,但是Linux在硬件配置上仍然没有做到完全即插即用,对于Linux怎样配置和使用他们,也越来越成为困扰我们的一大问题;本文的目地是使大家了...

USB设备驱动程序(二)

USB设备驱动程序中的结构 在Linux内核中,使用struct usb_driver结构描述一个USB驱动。 struct usb_driver { int devnum; /*USB设备...

怎样写linux下的USB设备驱动程序

怎样写linux下的USB设备驱动程序 引言 随着人们生活水平的提高,我们用到的USB设备也越来越多,但是Linux在硬件配置上仍然没有做到完全即插即用,对于Linux怎样配置和使用他...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:USB设备驱动程序-USB Gadget Driver
举报原因:
原因补充:

(最多只允许输入30个字)