电子文章 | 电子资料下载 | 家电维修 | 维修资料下载 | 加入收藏 | 全站地图
您现在所在位置:电子爱好者电子文章接口定义USB gadget设备驱动解析(3)

USB gadget设备驱动解析(3)

11-20 14:46:22 | http://www.5idzw.com | 接口定义 | 人气:262
标签:接口技术,微机原理与接口技术,单片机原理与接口技术,http://www.5idzw.com USB gadget设备驱动解析(3),http://www.5idzw.com

  Description

  These are allocated/freed through the endpoint they're used with. The hardware's driver can add extra per-request data to the memory it returns,whichoften avoids separate memory allocations (potential failures), later when the request is queued.

  Request flags affect request handling, such as whether a zero length packet is written (the “zero” flag), whether a short read should be treated as anerror (blocking request queue advance, the “short_not_ok” flag), or hinting that an interrupt is not required (the “no_interrupt” flag, for use with deeprequest queues).

  Bulk endpoints can use any size buffers, and can also be used for interrupt transfers. interrupt-only endpoints can be much less functional.

  2、为USB gadget功能驱动提供的注册、注销函数

  EXPORT_SYMBOL(usb_gadget_unregister_driver); //注销一个USB gadget功能驱动

  EXPORT_SYMBOL(usb_gadget_register_driver);//注册一个USB gadget功能驱动

  二、USB gadget功能驱动

  如果内核已经支持了SOC的UDC驱动,很多时候,我们可以只关心这部分代码的编写。那么我们如何编写出一个类似usb 功能驱动呢?

  usb 功能驱动应该至少要实现如下功能:

  .       实现USB协议中端点0部分和具体功能相关的部分(UDC驱动无法帮我们完成的部分)。如:USB_REQ_GET_DESCRIPTOR、USB_REQ_GET_CONFIGURATION等;

  完成了这个功能以后,USB主机端系统就会设别出我们是一个什么样的设备。

  .       实现数据交互功能

  即如何实现向硬件控制器的端点发出读、写请求来完成数据交互;

  .       具体功能的实现如:如何实现一个usb net驱动,或是一个usb storage驱动。

  接下来以zero.c为例,说明这3个方面是如何实现的。

  1、zero设备介绍

  作为一个简单的 gadget 驱动,zero 的功能基于两个 BULK 端点实现了简单的输入输出功能, 它可以用作写新的 gadget 驱动的一个实例。

  两个 BULK 端点为一个 IN 端点, 一个 OUT端点。基于这两个(由底层提供的)端点,g_zero 驱动实现了两个 configuration。 第一个 configuration 提供了 sink/source功能:两个端点一个负责输入,一个负责输出,其中输出的内容根据设置可以是全0,也可以是按照某种算法生成的数据。另一个 configuration 提供了 loopback 接口, IN 端点负责把从 OUT 端点收到的数据反馈给 Host.

  2、zero设备注册、注销

  static int __init init(void)

  {

  return usb_gadget_register_driver(&zero_driver);

  }

  module_init(init);

  static struct usb_gadget_driver zero_driver = {

  #ifdef CONFIG_USB_GADGET_DUALSPEE

  .speed = USB_SPEED_HIGH,

  #else

  .speed = USB_SPEED_FULL,

  #endif

  .function = (char *) longname,

  .bind = zero_bind,

  .unbind = __exit_p(zero_unbind),

  .setup = zero_setup,

  .disconnect = zero_disconnect,

  .suspend = zero_suspend,

  .resume = zero_resume,

  .driver = {

  .name = (char *) shortname,

  .owner = THIS_MODULE,

  },

  };

  构建一个usb_gadget_driver,调用usb_gadget_register_driver注册函数即可注册一个usb gadget驱动。需要注意的是,目前S3C2410主机控制器只能注册一个gadget功能驱动。这主要是由协议决定的。参考s3c2410_udc.c中的这段代码

  int usb_gadget_register_driver(struct usb_gadget_driver *driver)

  {……

  if (udc->driver)//如果已经注册过了

  return -EBUSY;

  ……

  }

  3、usb_gadget_driver结构

  事实上我们的工作就是构建这个usb_gadget_driver结构。那么这个结构这样和我们上面要实现的3个目标联系起来呢。

  .       Setup (zero_setup)

  处理host端发来的request,如:处理host端发来的get_descriptor请求。 在这实现了前面提到的必须要实现的第一个功能。

  .       bind (zero_bind)

  绑定dev与driver,在gadget driver,注册驱动时被usb_gadget_register_driver调用,绑定之后driver才能处理setup请求

  另外,通过usb_ep_autoconfig函数,可以分配到名为EP_IN_NAME、EP_OUT_NAME两个端点。后面可以对两个端点发起数据传输请求,和USB 主机端的urb请求非常相似,大家可以和urb对照一些。

  发起数据请求大致有以下几步:

  struct usb_request *req;

  req = alloc_ep_req(ep, buflen);//分配请求,数据传输的方向由ep本身决定

  req->complete = source_sink_complete; //请求完成后的处理函数

  status = usb_ep_queue(ep, req, GFP_ATOMIC);//递交请求

  free_ep_req(ep, req);//释放请求,通常在请求处理函数complete中调用

  .       通常在bind和unbind函数中注册具体的功能驱动

  如果为了实现某个特定功能需要在设备端注册字符、块、网络设备驱动的话,选择的场

  合通常是bind中注册,unbind中卸载。如ether.c文件中:

  static int __init

  eth_bind (struct usb_gadget *gadget)

  {

  ……

  status = register_netdev (dev->net); //注册网卡驱动

  ……

  }

  static void /* __init_or_exit */

  eth_unbind (struct usb_gadget *gadget)

  {

  ……

  unregister_netdev (dev->net); //注销网卡驱动

  ……

  }

  这也让我们对在设备端实现一个字符、块、网络驱动的结构有了一些了解。

  总结

  本文对gadget的驱动结构做了简要的介绍。下一篇将介绍如何编写一个简单的gadget驱动及应用测试程序。

  “本文由www.5idzw.comhttp://www.5idzw.com提供”


上一页  [1] [2] 

,USB gadget设备驱动解析(3)