色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

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

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

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

          return req;

          }

          ssize_t

          usb_zero_read (struct file * file, const char __user * buf, size_t count,loff_t * f_pos) //讀設(shè)備

          {

          struct zero_dev *dev =file->private_data;

          struct usb_request *req;

          int status;

          struct usb_ep *ep;

          struct usb_ * = dev->;

          ssize_t ret = 0;

          int result;

          ep=dev->out_ep;

          source_sink_start_ep(ep);//構(gòu)造、遞交讀請(qǐng)求

          if (count 0)

          return -EINVAL;

          interruptible_sleep_on (dev->bulkrq);//睡眠,等到請(qǐng)求完成

          if (copy_to_user (buf,dev->data,dev->data_size)) //拷貝讀取的數(shù)據(jù)到用戶空間

          {

          ret = -EFAULT;

          }

          else

          {

          ret = dev->data_size;

          }

          return ret;

          }

          struct file_operations usb_zero_fops = {

          .owner = THIS_MODULE,

          .read = usb_zero_read,

          .open = usb_zero_open,

          .release = usb_zero_release,

          };

          static void

          usb_zero_setup_cdev (struct zero_dev *dev, int minor)//注冊(cè)字符設(shè)備

          {

          int err, devno = MKDEV (usb_zero_major, minor);

          cdev_init(dev->cdev, usb_zero_fops);

          dev->cdev.owner = THIS_MODULE;

          err = cdev_add (dev->cdev, devno, 1);

          if (err)

          printk (Error adding usb_rcvn);

          }

          static void zero_setup_complete(struct usb_ep *ep, struct usb_request *req)//配置端點(diǎn)0的請(qǐng)求

          完成處理

          {

          if (req->status || req->actual != req->length)

          printk(setup complete --> %d, %d/%dn,

          req->status, req->actual, req->length);

          }

          static void zero_reset_config(struct zero_dev *dev) //復(fù)位配置

          {

          usb_ep_disable(dev->out_ep);

          dev->out_ep = NULL;

          }

          static void zero_disconnect(struct usb_gadget *gadget)//卸載時(shí)被調(diào)用,做一些注銷工作

          {

          struct zero_dev *dev = get_gadget_data(gadget);

          unsigned long flags;

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

          cdev_del ((dev->cdev));

          zero_reset_config(dev);

          printk(in %sn,__FUNCTION__);

          }

          static int config_buf(struct usb_gadget *gadget,

          u8 *buf, u8 type, unsigned index)

          {

          //int is_source_sink;

          int len;

          const struct usb_descriptor_header **function;

          int hs = 0;

          function =fs_loopback_function;//根據(jù)fs_loopback_function,得到長(zhǎng)度,

          //此處len=配置(9)+1個(gè)接口(9)+1個(gè)端點(diǎn)(7)=25

          len = usb_gadget_config_buf(loopback_config,

          buf, _BUFSIZ, function);

          if (len 0)

          return len;

          ((struct usb_config_descriptor *) buf)->bDescriptorType = type;

          return len;

          }

          static int set_loopback_config(struct zero_dev *dev)

          {

          int result = 0;

          struct usb_ep *ep;

          struct usb_gadget *gadget = dev->gadget;

          ep=dev->out_ep;

          const struct usb_endpoint_descriptor *d;

          d = fs_sink_desc;

          result = usb_ep_enable(ep, d); //激活端點(diǎn)

          //printk();

          if (result == 0) {

          printk(connectedn); //如果成功,打印“connected”

          }

          else

          printk(can't enable %s, result %dn, ep->name, result);

          return result;

          }

          static int zero_set_config(struct zero_dev *dev, unsigned number)

          {

          int result = 0;

          struct usb_gadget *gadget = dev->gadget;

          result = set_loopback_config(dev);//激活設(shè)備

          if (result)

          zero_reset_config(dev); //復(fù)位設(shè)備

          else {

          char *speed;

          switch (gadget->speed) {

          case _SPEED_LOW: speed = low; break;

          case _SPEED_FULL: speed = full; break;

          case USB_SPEED_HIGH: speed = high; break;

          default: speed = ; break;

          }

          }

          return result;

          }

          /***

          zero_setup完成USB設(shè)置階段和具體功能相關(guān)的交互部分

          ***/

          static int

          zero_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)

          {

          struct zero_dev *dev = get_gadget_data(gadget);

          struct usb_request *req = dev->req;

          int value = -EOPNOTSUPP;

          u16 w_index = le16_to_cpu(ctrl->wIndex);

          u16 w_value = le16_to_cpu(ctrl->wValue);

          u16 w_length = le16_to_cpu(ctrl->wLength);

          /* usually this stores reply data in the pre-allocated ep0 buffer,

          * but config change events will reconfigure hardware.

          */

          req->zero = 0;

          switch (ctrl->bRequest) {

          case USB_REQ_GET_DESCRIPTOR: //獲取描述符

          if (ctrl->bRequestType != USB_DIR_IN)

          goto unknown;

          switch (w_value >> 8) {

          case USB_DT_DEVICE: //獲取設(shè)備描述符

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

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




          評(píng)論


          相關(guān)推薦

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

          關(guān)閉