<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > Linux USB gadget設(shè)備驅(qū)動(dòng)解析(4)--編寫一個(gè)gadget驅(qū)動(dòng)

          Linux USB gadget設(shè)備驅(qū)動(dòng)解析(4)--編寫一個(gè)gadget驅(qū)動(dòng)

          作者: 時(shí)間:2012-08-06 來源:網(wǎng)絡(luò) 收藏

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

          memcpy(req->buf, device_desc, value);

          break;

          case _DT_CONFIG: //獲取配置,注意:會(huì)根據(jù)fs_loopback_function讀取到接口、端點(diǎn)描述符,注意通過config_buf完成讀取數(shù)據(jù)及數(shù)量的統(tǒng)計(jì)。

          value = config_buf(, req->buf,

          w_value >> 8,

          w_value 0xff);

          if (value >= 0)

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

          break;

          case _DT_STRING:

          value = usb__get_string(stringtab,

          w_value 0xff, req->buf);

          if (value >= 0)

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

          break;

          }

          break;

          case _REQ_SET_CONFIGURATION:

          if (ctrl->bRequestType != 0)

          goto unknown;

          spin_lock(dev->lock);

          value = zero_set_config(dev, w_value);//激活相應(yīng)的端點(diǎn)

          spin_unlock(dev->lock);

          break;

          default:

          unknown:

          printk(

          unknown control req%02x.%02x v%04x i%04x l%dn,

          ctrl->bRequestType, ctrl->bRequest,

          w_value, w_index, w_length);

          }

          /* respond with data transfer before status phase */

          if (value >= 0) {

          req->length = value;

          req->zero = value w_length;

          value = usb_ep_queue(->ep0, req, GFP_ATOMIC);//通過端點(diǎn)0完成setup

          if (value 0) {

          printk(ep_queue --> %dn, value);

          req->status = 0;

          zero_setup_complete(gadget->ep0, req);

          }

          }

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

          return value;

          }

          static void zero_unbind(struct usb_gadget *gadget) //解除綁定

          {

          struct zero_dev *dev = get_gadget_data(gadget);

          printk(unbindn);

          unregister_chrdev_region (MKDEV (usb_zero_major, 0), 1);

          cdev_del ((dev->cdev));

          /* we've already been disconnected ... no i/o is active */

          if (dev->req) {

          dev->req->length = USB_BUFSIZ;

          free_ep_req(gadget->ep0, dev->req);

          }

          kfree(dev);

          set_gadget_data(gadget, NULL);

          }

          static int __init zero_bind(struct usb_gadget *gadget) //綁定過程

          {

          struct zero_dev *dev;

          struct usb_ep *ep;

          int gcnum;

          usb_ep_autoconfig_reset(gadget);

          ep = usb_ep_autoconfig(gadget, fs_sink_desc);//根據(jù)端點(diǎn)描述符及控制器端點(diǎn)情況,分配合適的端點(diǎn)。

          if (!ep)

          goto enomem;

          EP_OUT_NAME = ep->name; //記錄名稱

          gcnum = usb_gadget_controller_number(gadget);//獲得控制器代號(hào)

          if (gcnum >= 0)

          device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);//賦值設(shè)備描述符

          else {

          pr_warning(%s: controller '%s' not recognizedn,

          shortname, gadget->name);

          device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);

          }

          dev = kzalloc(sizeof(*dev), GFP_KERNEL); //分配設(shè)備結(jié)構(gòu)體

          if (!dev)

          return -ENOMEM;

          spin_lock_init(dev->lock);

          dev->gadget = gadget;

          set_gadget_data(gadget, dev);

          dev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);//分配請(qǐng)求

          if (!dev->req)

          goto enomem;

          dev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL);

          if (!dev->req->buf)

          goto enomem;

          dev->req->complete = zero_setup_complete;

          dev->out_ep=ep; //記錄端點(diǎn)(就是接收host端數(shù)據(jù)的端點(diǎn))

          printk(name=%sn,dev->out_ep->name); //打印出這個(gè)端點(diǎn)的名稱

          ep->driver_data=dev;

          device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;

          usb_gadget_set_selfpowered(gadget);

          gadget->ep0->driver_data = dev;

          snprintf(manufacturer, sizeof manufacturer, %s %s with %s,

          init_utsname()->sysname, init_utsname()->release,

          gadget->name);

          /**************************字符設(shè)備注冊(cè)*******************/

          dev_t usb_zero_dev = MKDEV (usb_zero_major, 0);

          int result = register_chrdev_region (usb_zero_dev, 1, usb_zero);

          if (result 0)

          {

          printk (KERN_NOTICE Unable to get usb_transfer region, error %dn,result);

          return 0;

          }

          usb_zero_setup_cdev (dev, 0);

          return 0;

          enomem:

          zero_unbind(gadget);

          return -ENOMEM;

          }

          /*-------------------------------------------------------------------------*/

          static struct usb_gadget_driver zero_driver = { //gadget的核心數(shù)據(jù)結(jié)構(gòu)

          #ifdef CONFIG_USB_GADGET_DUALSPEED

          .speed = USB_SPEED_HIGH,

          #else

          .speed = USB_SPEED_FULL,

          #endif

          .function = (char *) longname,

          .bind = zero_bind,

          .unbind = __exit_p(zero_unbind),

          .setup = zero_setup,

          linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)

          linux相關(guān)文章:linux教程




          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();