1. UDC驱动是作为platform driver向platform子系统注册的,因此UDC驱动首先就需要实现struct platform_driver结构中的函数成员:
struct platform_driver {
int (*probe)(struct platform_device *); //驱动和设备绑定
int (*remove)(struct platform_device *); //支持热插拔的设备移除
void (*shutdown)(struct platform_device *); //设备关闭
int (*suspend)(struct platform_device *, pm_message_t state); //电源管理相关,挂起设备
int (*resume)(struct platform_device *); //电源管理相关,恢复设备
struct device_driver driver;
struct platform_device_id *id_table; //驱动和设备匹配信息
};
在下面的源码分析中以s3c2410_udc.c文件为例:
static struct platform_driver udc_driver_2410 = {
.driver = {
.name = "s3c2410-usbgadget",
.owner = THIS_MODULE,
},
.probe = s3c2410_udc_probe,
.remove = s3c2410_udc_remove,
.suspend = s3c2410_udc_suspend,
.resume = s3c2410_udc_resume,
};
其中以s3c2410_udc_probe和s3c2410_udc_remove函数最为重要,s3c2410_udc_probe函数实现驱动和设备的匹配绑定,并分配资源;而s3c2410_udc_remove函数实现资源的释放。
static int s3c2410_udc_probe(struct platform_device *pdev)
{
struct s3c2410_udc *udc = &memory; //s3c2410的UDC设备,在其中对usb_gadget设备对象和端点等进行了初始化
struct device *dev = &pdev->dev;
int retval;
int irq;
//获取总线时钟并使能
usb_bus_clock = clk_get(NULL, "usb-bus-gadget");
clk_enable(usb_bus_clock);
//获取设备时钟并使能
udc_clock = clk_get(NULL, "usb-device");
clk_enable(udc_clock);
mdelay(10);
spin_lock_init (&udc->lock); //初始化设备的自旋锁
udc_info = pdev->dev.platform_data;
rsrc_start = S3C2410_PA_USBDEV; //s3c2410 UDC端口起始地址
rsrc_len = S3C24XX_SZ_USBDEV; //s3c2410端口地址长度
if (!request_mem_region(rsrc_start, rsrc_len, gadget_name)) //申请端口资源
return -EBUSY;
base_addr = ioremap(rsrc_start, rsrc_len); //端口映射
if (!base_addr) {
retval = -ENOMEM;
goto err_mem;
}
device_initialize(&udc->gadget.dev); //初始化device设备对象
udc->gadget.dev.parent = &pdev->dev; //当前UDC设备的父设备对象是platform_device
udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
the_controller = udc;
platform_set_drvdata(pdev, udc); //驱动和设备绑定,在platform_device结构中保存udc设备对象
/*重新初始化设备*/
s3c2410_udc_disable(udc);
s3c2410_udc_reinit(udc);
/* irq setup after old hardware state is cleaned up */
/*申请中断,并绑定中断函数,中断函数是UDC功能驱动的入口函数*/
retval = request_irq(IRQ_USBD, s3c2410_udc_irq, IRQF_DISABLED, gadget_name, udc);
if (udc_info && udc_info->vbus_pin > 0) {
retval = gpio_request(udc_info->vbus_pin, "udc vbus");
irq = gpio_to_irq(udc_info->vbus_pin);
retval = request_irq(irq, s3c2410_udc_vbus_irq, IRQF_DISABLED | IRQF_TRIGGER_RISING| IRQF_TRIGGER_FALLING | IRQF_SHARED,gadget_name, udc);
}
else {
udc->vbus = 1;
}
if (s3c2410_udc_debugfs_root) { //创建虚拟文件debugfs
udc->regs_info = debugfs_create_file("registers", S_IRUGO, s3c2410_udc_debugfs_root,udc, &s3c2410_udc_debugfs_fops);
if (!udc->regs_info)
dev_warn(dev, "debugfs file creation failed\n");
}
dev_dbg(dev, "probe ok\n");
return 0;
err_gpio_claim:
if (udc_info && udc_info->vbus_pin > 0)
gpio_free(udc_info->vbus_pin);
err_int:
free_irq(IRQ_USBD, udc);
err_map:
iounmap(base_addr);
err_mem:
release_mem_region(rsrc_start, rsrc_len);
return retval;
}
从s3c2410_udc_probe函数可以看出,probe函数主要完成的就是将platform_device设备对象和UDC设备对象建立关系,UDC设备和驱动的一些初始化工作,并申请驱动所需的资源,若端口区间、中断号等,并将中断函数和中断号绑定。这个中断处理函数非常重要,对这个设备的所有操作都将从中断函数入口。
static int s3c2410_udc_remove(struct platform_device *pdev)
{
struct s3c2410_udc *udc = platform_get_drvdata(pdev); //获取UDC设备对象,在probe函数中绑定的
unsigned int irq;
if (udc->driver) //设备的驱动usb_gadget_driver对象,说明设备正在使用
return -EBUSY;
debugfs_remove(udc->regs_info); //移除debugfs文件系统中建立的文件
if (udc_info && udc_info->vbus_pin > 0) {
irq = gpio_to_irq(udc_info->vbus_pin);
free_irq(irq, udc);
}
free_irq(IRQ_USBD, udc); //释放中断
/*释放端口资源*/
iounmap(base_addr);
release_mem_region(rsrc_start, rsrc_len);
/*解除绑定*/
platform_set_drvdata(pdev, NULL);
/*释放时钟*/
if (!IS_ERR(udc_clock) && udc_clock != NULL) {
clk_disable(udc_clock);
clk_put(udc_clock);
udc_clock = NULL;
}
if (!IS_ERR(usb_bus_clock) && usb_bus_clock != NULL) {
clk_disable(usb_bus_clock);
clk_put(usb_bus_clock);
usb_bus_clock = NULL;
}
dev_dbg(&pdev->dev, "%s: remove ok\n", __func__);
return 0;
}
可以看出,remove函数基本上是probe函数的逆操作,将probe函数中申请的资源释放掉。
2. UDC驱动程序还需要为上层实现usb_gadget_register_driver和usb_gadget_unregister_driver两个gadget driver注册接口,这两个函数将实现gadget driver和udc driver绑定。
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
{
struct s3c2410_udc *udc = the_controller; //UDC设备对象
int retval;
/* Sanity checks */
if (!udc)
return -ENODEV;
/*UDC设备只能绑定一个gadget driver对象*/
if (udc->driver)
return -EBUSY;
/*检查gadget driver是否实现了绑定函数、setup函数。同时低速设备也不支持gadget driver*/
if (!driver->bind || !driver->setup|| driver->speed < USB_SPEED_FULL) {
printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n",driver->bind, driver->setup, driver->speed);
return -EINVAL;
}
//支持卸载的话,还需要实现unbind函数
#if defined(MODULE)
if (!driver->unbind) {
printk(KERN_ERR "Invalid driver: no unbind method\n");
return -EINVAL;
}
#endif
/* Hook the driver */
/*将gadget driver和udc设备绑定*/
udc->driver = driver;
udc->gadget.dev.driver = &driver->driver;
/* Bind the driver */
if ((retval = device_add(&udc->gadget.dev)) != 0) { //完成gadget设备在内核中的注册
printk(KERN_ERR "Error in device_add() : %d\n",retval);
goto register_error;
}
if ((retval = driver->bind (&udc->gadget)) != 0) {//gadget驱动绑定函数
device_del(&udc->gadget.dev);
goto register_error;
}
/* Enable udc */
//使能UDC设备
s3c2410_udc_enable(udc);
return 0;
register_error:
udc->driver = NULL;
udc->gadget.dev.driver = NULL;
return retval;
}
/*gadget 驱动注销函数*/
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
{
struct s3c2410_udc *udc = the_controller;
if (!udc)
return -ENODEV;
/*驱动必须和注册时的驱动是一致的,同时实现了unbind函数*/
if (!driver || driver != udc->driver || !driver->unbind)
return -EINVAL;
dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n", driver->driver.name);
/*调用gadget driver实现的unbind函数*/
driver->unbind(&udc->gadget);
device_del(&udc->gadget.dev); //和register函数中的device_add对应
udc->driver = NULL;//这个很重要,这里说明gadget驱动注销之后,才能移除udc设备
/* Disable udc */
/*关闭设备*/
s3c2410_udc_disable(udc);
return 0;
}
3. 中断函数
中断处理函数是UDC驱动层的核心函数,由于UDC是从设备,主机端是控制端,所有的操作都是主机端发起的,所以中断处理函数是UDC驱动层的核心函数。
static irqreturn_t s3c2410_udc_irq(int dummy, void *_dev)
{
struct s3c2410_udc *dev = _dev; //UDC设备对象
int usb_status;
int usbd_status;
int pwr_reg;
int ep0csr;
int i;
u32 idx;
unsigned long flags;
spin_lock_irqsave(&dev->lock, flags);
/* Driver connected ? */
if (!dev->driver) { //还没有和驱动绑定,清除中断
/* Clear interrupts */
udc_write(udc_read(S3C2410_UDC_USB_INT_REG), S3C2410_UDC_USB_INT_REG);
udc_write(udc_read(S3C2410_UDC_EP_INT_REG),S3C2410_UDC_EP_INT_REG);
}
/* Save index */
idx = udc_read(S3C2410_UDC_INDEX_REG); //这是哪个端点产生中断的索引号
/* Read status registers */
usb_status = udc_read(S3C2410_UDC_USB_INT_REG); //UDC设备状态
usbd_status = udc_read(S3C2410_UDC_EP_INT_REG); //UDC产生中断的端点状态
pwr_reg = udc_read(S3C2410_UDC_PWR_REG);
udc_writeb(base_addr, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG);
ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
dprintk(DEBUG_NORMAL, "usbs=%02x, usbds=%02x, pwr=%02x ep0csr=%02x\n", usb_status, usbd_status, pwr_reg, ep0csr);
/*
开始中断的实际处理,这里的中断只有两种类型:
1. UDC设备中断: 重置、挂起和恢复
2. 端点中断
*/
/* UDC设备RESET操作处理 */
if (usb_status & S3C2410_UDC_USBINT_RESET) { //Reset中断
/* two kind of reset :
* - reset start -> pwr reg = 8
* - reset end -> pwr reg = 0
**/
dprintk(DEBUG_NORMAL, "USB reset csr %x pwr %x\n", ep0csr, pwr_reg);
dev->gadget.speed = USB_SPEED_UNKNOWN;
udc_write(0x00, S3C2410_UDC_INDEX_REG);
udc_write((dev->ep[0].ep.maxpacket & 0x7ff) >> 3, S3C2410_UDC_MAXP_REG);
dev->address = 0;
dev->ep0state = EP0_IDLE;
dev->gadget.speed = USB_SPEED_FULL;
/* clear interrupt */
udc_write(S3C2410_UDC_USBINT_RESET, S3C2410_UDC_USB_INT_REG);
udc_write(idx, S3C2410_UDC_INDEX_REG);
spin_unlock_irqrestore(&dev->lock, flags);
return IRQ_HANDLED;
}
/* UDC设备RESUME操作处理 */
if (usb_status & S3C2410_UDC_USBINT_RESUME) { //Resume中断
dprintk(DEBUG_NORMAL, "USB resume\n");
/* clear interrupt */
udc_write(S3C2410_UDC_USBINT_RESUME, S3C2410_UDC_USB_INT_REG);
if (dev->gadget.speed != USB_SPEED_UNKNOWN && dev->driver&& dev->driver->resume)//调用resume函数
dev->driver->resume(&dev->gadget);
}
/* UDC设备SUSPEND操作处理 */
if (usb_status & S3C2410_UDC_USBINT_SUSPEND) { //Suspend中断
dprintk(DEBUG_NORMAL, "USB suspend\n");
/* clear interrupt */
udc_write(S3C2410_UDC_USBINT_SUSPEND, S3C2410_UDC_USB_INT_REG);
if (dev->gadget.speed != USB_SPEED_UNKNOWN && dev->driver&& dev->driver->suspend)//调用suspend函数
dev->driver->suspend(&dev->gadget);
dev->ep0state = EP0_IDLE;
}
/* 下面就是端点中断得处理 */
/* 首先是控制端点(端点0)的中断处理*/
/* check on ep0csr != 0 is not a good idea as clearing in_pkt_ready
* generate an interrupt
*/
if (usbd_status & S3C2410_UDC_INT_EP0) { //端点0的中断
dprintk(DEBUG_VERBOSE, "USB ep0 irq\n");
/* Clear the interrupt bit by setting it to 1 */
udc_write(S3C2410_UDC_INT_EP0, S3C2410_UDC_EP_INT_REG);
s3c2410_udc_handle_ep0(dev); //处理端点0
}
/* 其他端点,就是数据传输的处理*/
for (i = 1; i < S3C2410_ENDPOINTS; i++) { //遍历所有端点,找出中断的端点
u32 tmp = 1 << i;
if (usbd_status & tmp) {
dprintk(DEBUG_VERBOSE, "USB ep%d irq\n", i);
/* Clear the interrupt bit by setting it to 1 */
udc_write(tmp, S3C2410_UDC_EP_INT_REG);
s3c2410_udc_handle_ep(&dev->ep[i]); //处理对应端点
}
}
dprintk(DEBUG_VERBOSE, "irq: %d s3c2410_udc_done.\n", IRQ_USBD);
/* Restore old index */
udc_write(idx, S3C2410_UDC_INDEX_REG);
spin_unlock_irqrestore(&dev->lock, flags);
return IRQ_HANDLED;
}
4. 端点操作函数
端点操作函数是UDC驱动的基础,因为大部分的动作其实都是和端点相关的,如数据传输等。
首先来看中断函数中涉及的两个函数,一个是端点0的处理函数,一个是其他端点的处理函数。
static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev)
{
u32 ep0csr;
struct s3c2410_ep *ep = &dev->ep[0];
struct s3c2410_request *req;
struct usb_ctrlrequest crq;
if (list_empty(&ep->queue))
req = NULL;
else
req = list_entry(ep->queue.next, struct s3c2410_request, queue);
/* We make the assumption that S3C2410_UDC_IN_CSR1_REG equal to
* S3C2410_UDC_EP0_CSR_REG when index is zero */
udc_write(0, S3C2410_UDC_INDEX_REG);
ep0csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
dprintk(DEBUG_NORMAL, "ep0csr %x ep0state %s\n", ep0csr, ep0states[dev->ep0state]);
/* clear stall status */
if (ep0csr & S3C2410_UDC_EP0_CSR_SENTSTL) { //清除STALL状态
s3c2410_udc_nuke(dev, ep, -EPIPE);
dprintk(DEBUG_NORMAL, "... clear SENT_STALL ...\n");
s3c2410_udc_clear_ep0_sst(base_addr);
dev->ep0state = EP0_IDLE;
return;
}
/* clear setup end */
if (ep0csr & S3C2410_UDC_EP0_CSR_SE) {
dprintk(DEBUG_NORMAL, "... serviced SETUP_END ...\n");
s3c2410_udc_nuke(dev, ep, 0);
s3c2410_udc_clear_ep0_se(base_addr);
dev->ep0state = EP0_IDLE;
}
/*端点0的状态处理*/
switch (dev->ep0state) {
case EP0_IDLE:
s3c2410_udc_handle_ep0_idle(dev, ep, &crq, ep0csr); //在这个函数中会调用上层提供的gadget_driver中实现的setup函数来处理控制数据包
break;
case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */ //向主机发送数据
dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n");
if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) {
s3c2410_udc_write_fifo(ep, req); //写UDC FIFO
}
break;
case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */ //从主机接收数据
dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n");
if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req ) {
s3c2410_udc_read_fifo(ep,req);
}
break;
case EP0_END_XFER:
dprintk(DEBUG_NORMAL, "EP0_END_XFER ... what now?\n");
dev->ep0state = EP0_IDLE;
break;
case EP0_STALL:
dprintk(DEBUG_NORMAL, "EP0_STALL ... what now?\n");
dev->ep0state = EP0_IDLE;
break;
}
}
/*
* handle_ep - Manage I/O endpoints
其他端点的处理函数,主要是数据发送和接收
*/
static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep)
{
struct s3c2410_request *req;
int is_in = ep->bEndpointAddress & USB_DIR_IN;
u32 ep_csr1;
u32 idx;
if (likely (!list_empty(&ep->queue))) //取出申请
req = list_entry(ep->queue.next, struct s3c2410_request, queue);
else
req = NULL;
idx = ep->bEndpointAddress & 0x7F; //端点地址
if (is_in) { //向主机发送数据
udc_write(idx, S3C2410_UDC_INDEX_REG);
ep_csr1 = udc_read(S3C2410_UDC_IN_CSR1_REG);
dprintk(DEBUG_VERBOSE, "ep%01d write csr:%02x %d\n", idx, ep_csr1, req ? 1 : 0);
if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) {
dprintk(DEBUG_VERBOSE, "st\n");
udc_write(idx, S3C2410_UDC_INDEX_REG);
udc_write(ep_csr1 & ~S3C2410_UDC_ICSR1_SENTSTL, S3C2410_UDC_IN_CSR1_REG);
return;
}
if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) {
s3c2410_udc_write_fifo(ep,req);
}
}
else //从主机接收数据
{
udc_write(idx, S3C2410_UDC_INDEX_REG);
ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG);
dprintk(DEBUG_VERBOSE, "ep%01d rd csr:%02x\n", idx, ep_csr1);
if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) {
udc_write(idx, S3C2410_UDC_INDEX_REG);
udc_write(ep_csr1 & ~S3C2410_UDC_OCSR1_SENTSTL, S3C2410_UDC_OUT_CSR1_REG);
return;
}
if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
s3c2410_udc_read_fifo(ep,req);
}
}
}
端点操作函数集:端点的基本操作函数
static const struct usb_ep_ops s3c2410_ep_ops = {
.enable = s3c2410_udc_ep_enable, //端点使能
.disable = s3c2410_udc_ep_disable, //关闭端点
.alloc_request = s3c2410_udc_alloc_request, //分配一个请求
.free_request = s3c2410_udc_free_request, //释放请求
.queue = s3c2410_udc_queue, //向端点提交一个请求
.dequeue = s3c2410_udc_dequeue, //从端点请求队列中删除一个请求
.set_halt = s3c2410_udc_set_halt,
};
主要分析queue这个函数,因为上层主要和这个函数打交道,接收或发送数据都需要对应的端点队列提交请求
static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
{
struct s3c2410_request *req = to_s3c2410_req(_req);
struct s3c2410_ep *ep = to_s3c2410_ep(_ep);
struct s3c2410_udc *dev;
u32 ep_csr = 0;
int fifo_count = 0;
unsigned long flags;
if (unlikely (!_ep || (!ep->desc && ep->ep.name != ep0name))) {
dprintk(DEBUG_NORMAL, "%s: invalid args\n", __func__);
return -EINVAL;
}
dev = ep->dev;
if (unlikely (!dev->driver|| dev->gadget.speed == USB_SPEED_UNKNOWN)) {
return -ESHUTDOWN;
}
local_irq_save (flags);
if (unlikely(!_req || !_req->complete || !_req->buf || !list_empty(&req->queue))) {
if (!_req)
dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__);
else {
dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n", __func__, !_req->complete,!_req->buf, !list_empty(&req->queue));
}
local_irq_restore(flags);
return -EINVAL;
}
_req->status = -EINPROGRESS;
_req->actual = 0;
dprintk(DEBUG_VERBOSE, "%s: ep%x len %d\n", __func__, ep->bEndpointAddress, _req->length);
if (ep->bEndpointAddress) { //设置端点号
udc_write(ep->bEndpointAddress & 0x7F, S3C2410_UDC_INDEX_REG);
ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN) ? S3C2410_UDC_IN_CSR1_REG: S3C2410_UDC_OUT_CSR1_REG);
fifo_count = s3c2410_udc_fifo_count_out();
}
else
{
udc_write(0, S3C2410_UDC_INDEX_REG);
ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG);
fifo_count = s3c2410_udc_fifo_count_out();
}
/* kickstart this i/o queue? */
if (list_empty(&ep->queue) && !ep->halted) { //该端点队列为空,且没有关闭,则直接完成申请
if (ep->bEndpointAddress == 0 /* ep0 */) { //端点0
switch (dev->ep0state) {
case EP0_IN_DATA_PHASE:
if (!(ep_csr&S3C2410_UDC_EP0_CSR_IPKRDY) && s3c2410_udc_write_fifo(ep,req)) {
dev->ep0state = EP0_IDLE;
req = NULL;
}
break;
case EP0_OUT_DATA_PHASE:
if ((!_req->length)|| ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)&& s3c2410_udc_read_fifo(ep,req))) {
dev->ep0state = EP0_IDLE;
req = NULL;
}
break;
default:
local_irq_restore(flags);
return -EL2HLT;
}
}
else if ((ep->bEndpointAddress & USB_DIR_IN) != 0 && (!(ep_csr&S3C2410_UDC_OCSR1_PKTRDY)) && s3c2410_udc_write_fifo(ep, req)) {
req = NULL;
}
else if ((ep_csr & S3C2410_UDC_OCSR1_PKTRDY)&& fifo_count&&s3c2410_udc_read_fifo(ep, req)) {
req = NULL;
}
}
/* pio or dma irq handler advances the queue. */
if (likely (req != 0))
list_add_tail(&req->queue, &ep->queue); //加入队列,等待中断处理
local_irq_restore(flags);
dprintk(DEBUG_VERBOSE, "%s ok\n", __func__);
return 0;
}
UDC驱动中还有一个重要函数,在数据传输或接收完成,即一个请求完成之后,会调用这个请求的完成函数来通知上层驱动。
static void s3c2410_udc_done(struct s3c2410_ep *ep, struct s3c2410_request *req, int status)
{
unsigned halted = ep->halted;
list_del_init(&req->queue); //将这个请求从端点请求队列中删除
if (likely (req->req.status == -EINPROGRESS))
req->req.status = status; //返回完成状态
else
status = req->req.status;
ep->halted = 1;
req->req.complete(&ep->ep, &req->req);
ep->halted = halted;
}
总结:
UDC设备驱动层的源码就分析得差不多了,其他很多函数都是操作寄存器,与UDC设备密切相关,但总的来说完成的功能都是一致的。可以发现,在UDC设备驱动层主要需要做以下几个工作:
1. 对usb_gadget、usb_ep、usb_request三个标准数据结构进行封装,根据自己UDC的一些设备特性,设计对应的自己的数据结构;
2. 实现platform_driver数据结构中的函数,将UDC设备驱动向platform系统进行注册;
3. 实现usb_gadget_ops函数集,这些函数主要是操作UDC设备的一些特性(针对设备);
4. 实现usb_ep_ops函数集,这些函数主要是操作端点的功能,如请求分配和提交等(针对端点);
5. 实现UDC设备的中断处理函数,这个函数基本上就是UDC设备驱动的核心;
6.实现上层功能驱动注册接口函数:
int usb_gadget_register_driver(struct usb_gadget_driver *driver)
int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)