三、gadget API
要了解gadget API,只需要理解头文件(usb_gadget.h)中几个重要的数据结构就可以了。详细的字段介绍看h文件注释。
(1)
struct usb_gadget {
const struct usb_gadget_ops *ops;
struct usb_ep *ep0;
struct list_head ep_list;
enum usb_device_speed speed;
unsigned is_dualspeed:1;
unsigned is_otg:1;
unsigned is_a_peripheral:1;
unsigned b_hnp_enable:1;
unsigned a_hnp_support:1;
unsigned a_alt_hnp_support:1;
const char *name;
struct device dev;
};
该结构表示一个USB device controller(UDC),在udc driver中初始化,它对gadget driver是只读的。
(2)
struct usb_gadget_driver {
char *function;
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 *);
struct device_driver driver;
};
这个结构表示我们的gadget驱动,其中的函数需要在gadget driver中实现,是编码的重点之一。具体实现可参考zero.c文件,下面简单介绍一下各个函数的功能:
Bind中主要执行gadget driver的初始化,它会被usb_gadget_register_driver函数调用,而usb_gadget_register_driver一般在模块初始化时调用。usb_gadget_register_driver执行完之后,device可以被主机探测到。
Unbind与bind相反,被usb_gadget_unregister_driver调用。
Setup处理主机发过来的request,例如读decriptors,配置configuration等。因此,setup函数中一般包含switch,case语句。
Disconnect在设备与主机断开时被调用。
(3)
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;
};
usb_request 表示一个传输的请求,与host端的urb很相似。它有一个complete字段,指定当request完成时的回调函数。
(4)
struct usb_ep {
void *driver_data;
const char *name;
const struct usb_ep_ops *ops;
struct list_head ep_list;
unsigned maxpacket:16;
};
struct usb_ep 表示一个端点(EP),usb_gadget中有所有EP的list。
(5)
struct usb_ep_ops {
int (*enable) (struct usb_ep *ep,
const struct usb_endpoint_descriptor *desc);
int (*disable) (struct usb_ep *ep);
struct usb_request *(*alloc_request) (struct usb_ep *ep,
gfp_t gfp_flags);
void (*free_request) (struct usb_ep *ep, struct usb_request *req);
void *(*alloc_buffer) (struct usb_ep *ep, unsigned bytes,
dma_addr_t *dma, gfp_t gfp_flags);
void (*free_buffer) (struct usb_ep *ep, void *buf, dma_addr_t dma,
unsigned bytes);
// NOTE: on 2.6, drivers may also use dma_map() and
// dma_sync_single_*() to directly manage dma overhead.
int (*queue) (struct usb_ep *ep, struct usb_request *req,
gfp_t gfp_flags);
int (*dequeue) (struct usb_ep *ep, struct usb_request *req);
int (*set_halt) (struct usb_ep *ep, int value);
int (*fifo_status) (struct usb_ep *ep);
void (*fifo_flush) (struct usb_ep *ep);
};
struct usb_ep_ops表示端点的操作,其中queue函数将一个usb_request提交给某个EndPoint,是进行数据传输的关键函数。
四、总结
本文是自己对学习使用Gadget API的一些总结,记录下来以防时间一长就忘记了。