现在的位置: 首页 > 综合 > 正文

Linux-USB Gadget : Part 6: dummy hcd 驱动简介

2013年10月04日 ⁄ 综合 ⁄ 共 4802字 ⁄ 字号 评论关闭

Linux-USB Gadget : Part 6: dummy hcd 驱动简介

作者: zjujoe 转载请注明出处

Emailzjujoe@yahoo.com

BLOGhttp://blog.csdn.net/zjujoe

前言

一直没有弄明白 dummy hcd 到底有什么用,因为它位于 gadget 目录里,以为是一个软件模拟的 udc 驱动。但是想想 gadget
驱动功能需要主机端触发,不知道这么一个假的 udc 驱动到底怎么触发数据传输。

今天简单的分析了一下代码。发现原来 dummy hcd 包含了 host controller device controller 驱动, 这样, 就可以在同一台机器上进行 host device 端的传输。如果你正在写主机端的 client 驱动或者设备端的 gadget 驱动,使用 dummy hcd 是很高效的。 下面简单分析一下这个驱动。

代码

看一下初始化代码:

 

2021 static int __init init (void)

2022 {

2023        
int     retval;

2024

2025         if (usb_disabled
())

2026                
return -ENODEV;

2027

2028         retval
= platform_driver_register
(&dummy_hcd_driver);

2029         if
(retval < 0)

2030                
return retval;

2031

2032         retval
= platform_driver_register
(&dummy_udc_driver);

2033         if
(retval < 0)

2034                
goto err_register_udc_driver;

2035

2036         retval
= platform_device_register
(&the_hcd_pdev);

2037         if
(retval < 0)

2038                
goto err_register_hcd;

2039

2040         retval
= platform_device_register
(&the_udc_pdev);

2041         if
(retval < 0)

2042                
goto err_register_udc;

2043         return
retval;

2044

2045 err_register_udc:

2046         platform_device_unregister
(&the_hcd_pdev);

2047 err_register_hcd:

2048         platform_driver_unregister
(&dummy_udc_driver);

2049 err_register_udc_driver:

2050         platform_driver_unregister
(&dummy_hcd_driver);

2051         return
retval;

2052 }

2053 module_init
(init);

 

同时注册了 usb 主机端、设备端 的驱动及设备。再看一下该“设备”提供的 端点”:

 

124
static const char *const ep_name [] =
{

125         ep0name,                                /*
everyone has ep0 */

126

127         /* act like a net2280: high
speed, six configurable endpoints */

128         "ep-a", "ep-b",
"ep-c", "ep-d", "ep-e", "ep-f",

129

130         /*
or like pxa250: fifteen fixed function endpoints */

131         "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso",
"ep5in-int",

132         "ep6in-bulk", "ep7out-bulk",
"ep8in-iso",
"ep9out-iso", "ep10in-int",

133         "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",

134                
"ep15in-int",

135

136         /*
or like sa1100: two fixed function endpoints */

137         "ep1out-bulk", "ep2in-bulk",

138 };

 

可见,dummy_hcd 提供了丰富的端点类型。可以用来测试各种上层驱动。

 

再研究一下数据是怎么在host 端和 client 端进行传输的, 我们使用
kft
工具画出一次数据传输的函数调用流程:

 

 

数据通过 usb_submit_urb 提交后,函数
dummy_timer
会调用 transfer 函数进行数据传输:

 

1065
/* transfer up to a frame's worth; caller must own lock */

1066
static int

1067
transfer
(struct dummy
*dum, struct urb
*urb, struct dummy_ep
*ep, int limit)

1068
{

1069         struct dummy_request    *req;

1070

。。。

1111                         /* else transfer
packet(s) */

1112                         ubuf = urb->transfer_buffer
+ urb->actual_length;

1113                         rbuf = req->req.buf +
req->req.actual;

1114                         if (to_host)

1115                                 memcpy (ubuf,
rbuf, len);

1116                         else

1117                                 memcpy (rbuf,
ubuf, len);

1118                         ep->last_io = jiffies;

。。。

 

这里, transfer 函数会调用 memcpy 进行数据传输

 

再看一下控制传输, 先看调用图:


以及代码:

1238 /* drive both sides of the transfers; looks
like irq handlers to

1239
 * both drivers except the
callbacks aren't in_irq().

1240
 */

1241
static void dummy_timer
(unsigned long _dum)

1242
{

。。。

1336                
/* handle control requests */

1337                
if (ep == &dum->ep [0] && ep->setup_stage) {

1338                         struct usb_ctrlrequest          setup;

1339                         int                             value = 1;

1340                         struct dummy_ep                 *ep2;

1341                         unsigned                        w_index;

1342                         unsigned                        w_value;

1343

1344                 
       setup =
*(struct usb_ctrlrequest*)
urb->setup_packet;

1345                         w_index = le16_to_cpu(setup.wIndex);

1346                         w_value = le16_to_cpu(setup.wValue);

1347                         if (le16_to_cpu(setup.wLength)
!=

1348                                         urb->transfer_buffer_length)
{

1349                                 maybe_set_status
(urb, -EOVERFLOW);

1350                                 goto
return_urb;

1351                         }

1352

。。。

1366

1367                         /* gadget driver
never sees set_address or operations

1368                          * on standard feature
flags.  some hardware doesn't

1369                          * even expose them.

1370                          */

1371                         ep->last_io = jiffies;

1372                         ep->setup_stage =
0;

1373                         ep->halted = 0;

1374                         switch (setup.bRequest)
{

1375                         case USB_REQ_SET_ADDRESS:

1376                                 if (setup.bRequestType
!= Dev_Request)

1377                                         break;

1378                                 dum->address =
w_value;

1379                                 maybe_set_status
(urb, 0);

1380                                 dev_dbg (udc_dev(dum),
"set_address = %d/n",

1381                                                
w_value);

1382                                 value = 0;

抱歉!评论已关闭.