电子文章 | 电子资料下载 | 家电维修 | 维修资料下载 | 加入收藏 | 全站地图
您现在所在位置:电子爱好者电子文章接口定义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

  作者:刘洪涛,www.5idzw.com嵌入式学院讲师。

  Linux USB 设备端驱动有两部分组成。一部分是USB 设备控制器(USB Device Controller, UDC)驱动、另一部分是硬件无关的功能驱动(如:鼠标、u盘、usb串口、usb网络等);也可以分为3层的,分别是:controller Drivers、Gadget Drivers、Upper Layers,大概意思都差不多。

  一、控制器(USB device Controller, UDC)驱动

  Gadget 框架提出了一套标准 API, 在底层, USB 设备控制器驱动则实现这一套 API, 不同的 UDC需要不同的驱动, 甚至基于同样的 UDC 的不同板子也需要进行代码修改。这一层是硬件相关层。

  Linux 标准内核里支持各种主流 SOC 的 udc 驱动,如:S3C2410、PXA270等。你可以通过内核直接配置支持。你也可以通过修改它们获取更高的效率。如:s3c2410_uda.c 中并没有利用到控制器的dma功能,你可以根据需要修改它。

  要理解UDC驱动代码就必须对相应的硬件控制器熟悉。当然,如果你对此不感兴趣,或没时间熟悉,也可以暂时跳过对硬件相关部分。本文也侧重于对软件结构的描述,不关心硬件细节。

  下面给出在UDC驱动中涉及到的一些关键数据结构及API,参考s3c2410_uda.c

  1.关键的数据结构及API

  gadget api 提供了usb device controller 驱动和上层gadget驱动交互的接口。下面列出一些关键的数据结构。

  struct usb_gadget {//代表一个UDC设备

  /* readonly to gadget driver */

  const struct usb_gadget_ops *ops; //设备的操作集

  struct usb_ep *ep0; //ep0(USB协议中的端点0), 处理setup()请求

  struct list_head ep_list; /* of usb_ep */本设备支持的端点链表

  enum usb_device_speed speed; //如:USB_SPEED_LOW、USB_SPEED_FULL等

  unsigned is_dualspeed:1; //支持full/high speed

  unsigned is_otg:1; //OTG的特性

  unsigned is_a_peripheral:1; //当前是A-peripheral,而不是A-host

  unsigned b_hnp_enable:1;

  unsigned a_hnp_support:1;

  unsigned a_alt_hnp_support:1;

  const char *name;

  struct device dev;

  };

  struct usb_gadget_driver {//代表一个gadget设备driver,如:file_storage.c中的fsg_driver

  //又如:如zero.c中的zero_driver

  char *function; //一个字符串,如"Gadget Zero"

  enum usb_device_speed speed;

  int (*bind)(struct usb_gadget *);

  void (*unbind)(struct usb_gadget *);

  int (*setup)(struct usb_gadget *,

  const struct usb_ctrlrequest *);

  void (*disconnect)(struct usb_gadget *);

  void (*suspend)(struct usb_gadget *);

  void (*resume)(struct usb_gadget *)

  /* FIXME support safe rmmod */

  struct device_driver driver;

  };

  struct usb_gadget_ops {//代表设备的操作集

  int (*get_frame)(struct usb_gadget *);

  int (*wakeup)(struct usb_gadget *);

  int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered);

  nt (*vbus_session) (struct usb_gadget *, int is_active);

  int (*vbus_draw) (struct usb_gadget *, unsigned mA);

  int (*pullup) (struct usb_gadget *, int is_on);

  int (*ioctl)(struct usb_gadget *,

  unsigned code, unsigned long param);

  };

  struct usb_ep {//代表一个端点

  void *driver_data //

  ...

  const struct usb_ep_ops *ops; //端点的操作集,如上

  struct list_head ep_list; //gadget的所有ep的list

  ...

  };

  struct usb_ep_ops {//表示端点的操作集

  ...

  int (*queue) (struct usb_ep *ep, struct usb_request *req,

  gfp_t gfp_flags); //将一个usb_request提交给endpoint

  //是数据传输的关键函数

  ...

  };

  struct usb_request {//表示一个传输的请求,这与usb host端的urb类似

  void *buf;

  unsigned length;

  dma_addr_t dma;

  unsigned no_interrupt:1;

  unsigned zero:1;

  unsigned short_not_ok:1;

  void (*complete)(struct usb_ep *ep,

  struct usb_request *req);

  void *context;

  struct list_head list;

  int status;

  unsigned actual;

  };

  上述结构中具体每项的含义可以参考http://tali.admingilde.org/linux-docbook/gadget/

  如:struct usb_request

  在http://tali.admingilde.org/linux-docbook/gadget/re02.html中

  Name

  struct usb_request — describes one i/o request

  Synopsis

  struct usb_request {

  void * buf;

  unsigned length;

  dma_addr_t dma;

  unsigned no_interrupt:1;

  unsigned zero:1;

  unsigned short_not_ok:1;

  void (* complete) (struct usb_ep *ep,struct usb_request *req);

  void * context;

  struct list_head list;

  int status;

  unsigned actual;

  };

  Members

  buf

  Buffer used for data. Always provide this; some controllers only use PIO, or don't use DMA for some endpoints.

  length

  Length of that data

  dma

  DMA address corresponding to 'buf'. If you don't set this field, and the usb controller needs one, it is responsible for mapping and unmapping the         buffer.

  no_interrupt

  If true, hints that no completion irq is needed. Helpful sometimes with deep request queues that are handled directly by DMA controllers.

  zero

  If true, when writing data, makes the last packet be “short” by adding a zero length packet as needed;

  short_not_ok

  When reading data, makes short packets be treated as errors (queue stops advancing till cleanup).

  complete

  Function called when request completes, so this request and its buffer may be re-used. Reads terminate with a short packet, or when the buffer         fills, whichever comes first. When writes terminate, some data bytes will usually still be in flight (often in a hardware fifo). Errors (for reads or writes)         stop the queue from advancing until the completion function returns, so that any transfers invalidated by the error may first be dequeued.

  context

  For use by the completion callback

  list

  For use by the gadget driver.

  status

  Reports completion code, zero or a negative errno. Normally, faults block the transfer queue from advancing until the completion callback returns.        Code “-ESHUTDOWN” indicates completion caused by device disconnect, or when the driver disabled the endpoint.

  actual

  Reports bytes transferred to/from the buffer. For reads (OUT transfers) this may be less than the requested length. If the short_not_ok flag is set,        short reads are treated as errors even when status otherwise indicates successful completion. Note that for writes (IN transfers) some data bytes may        still reside in a device-side FIFO when the request is reported as complete.

[1] [2]  下一页

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