LINUX 自定义USB Gadget HID 设备

最近在搞自定义的Gadget hid设备,内核版本:LINUX3.15       使用开发板:ATMEL SAMA5D3  编译环境:Ubuntu 12.04

首先配置内核,进入Device driver 菜单

 [*] USB support  --->  

进入此菜单

选择最后一项 <*>   USB Gadget Support  --->  

 --- USB Gadget Support                                            
  │ │    [*]   Debugging messages (DEVELOPMENT)                             
  │ │    [*]     Verbose debugging Messages (DEVELOPMENT)                 
  │ │    [*]   Debugging information files (DEVELOPMENT)                    
  │ │    [*]   Debugging information files in debugfs (DEVELOPMENT)        
  │ │    (2)   Maximum VBUS Power usage (2-500 mA)                       
  │ │    (2)   Number of storage pipeline buffers                           
  │ │          USB Peripheral Controller  --->                             
  │ │    <*>   USB Gadget Drivers (HID Gadget)  --->                      
  │ │  

进入最后一项        

       配置最后一项              (X) HID Gadget                         

保存退出。

2、添加设备

hid相关源码在linux内核源码下的driver/usb/gadget/里面。

首先打开hid.c 文件

在/****************************** Some noise ******************************/

下面你会看到driver的结构体变量

static __refdata struct usb_composite_driver hidg_driver = {
.name = "g_hid",
.dev = &device_desc,
.strings = dev_strings,
.max_speed = USB_SPEED_HIGH,
.bind = hid_bind,
.unbind = __exit_p(hid_unbind),
};


static struct platform_driver hidg_plat_driver = {
.remove = hidg_plat_driver_remove,
.driver = {
.owner = THIS_MODULE,
.name = "hidg",
},
};

这里我们只需要添加与platform_driver 相对应的device就行了usb_composite_driver 不需要添加device 。下面是我添加的设备

struct platform_device hidg_plat_device = {
    .name           = "hidg",
    .id             = 0,
    .num_resources  = 0,
    .resource       = 0,
    .dev.platform_data = &hidg_plat_pdata,
};

另外hidg_plat_pdata需要根据自己需要匹配报告描述符。可以是键盘、鼠标、或者是HID-complant-device。配置完后记得要注册进内核。

我们在hidg_init初始化函数里面进行注册。

  status = platform_device_register(&hidg_plat_device);
    if (status < 0)
        return status;

同样在内核卸载函数hidg_cleanup里面进行卸载处理platform_device_unregister(&hidg_plat_driver);

更改完后,编译内核。烧尽开发板。

3、解决错误

为了观察我们自定义的hid设备是否成功,我们打开bus hound 软件。这时,当你插上usb设备。在bus hound上面也行会显示下面的信息:

------  -----  ------------------------  ----------------  -----  ------------------  ------------

  21.0  CTL    80 06 00 01  00 00 12 00  GET DESCRIPTOR    2.8sc         1.1.0        13:45:02.409  
  21.0  IN     12 01 00 02  00 00 00 40  .......@          7.0ms         1.2.0        13:45:02.416  
               83 04 05 00  15 03 01 02  ........                        1.2.8                      
               00 01                     ..                              1.2.16                     
  21.0  CTL    80 06 00 02  00 00 09 00  GET DESCRIPTOR     35us         2.1.0        13:45:02.416  
  21.0  IN     09 02 29 00  01 01 00 c0  ..).....          7.0ms         2.2.0        13:45:02.423  
               01                        .                               2.2.8                      
  21.0  CTL    80 06 00 02  00 00 29 00  GET DESCRIPTOR     36us         3.1.0        13:45:02.423  
  21.0  IN     09 02 29 00  01 01 00 c0  ..).....          7.0ms         3.2.0        13:45:02.430  
               01 09 04 00  00 02 03 00  ........                        3.2.8                      
               00 04 09 21  01 01 00 01  ...!....                        3.2.16                     
               22 54 00 07  05 81 03 40  "T.....@                        3.2.24                     
               00 04 07 05  02 03 40 00  ......@.                        3.2.32                     
               04                        .                               3.2.40                     
  21.0  CTL    00 09 01 00  00 00 00 00  SET CONFIG         17us         4.1.0        13:45:02.430  
  21.0  CTL    21 0a 00 00  00 00 00 00  SET IDLE           63ms         5.1.0        13:45:02.494  
  21.0  USTS   c0000004                  stall pid          11ms         5.2.0        13:45:02.505 
  21.0  CTL    81 06 00 22  00 00 94 00  GET DESCRIPTOR     14us         6.1.0        13:45:02.505  
  21.0  IN     05 ff 09 ff  a1 01 85 01  ........           14ms         6.2.0        13:45:02.519  
               05 01 19 00  29 ff 15 00  ....)...                        6.2.8                      
               25 ff 75 3f  95 08 81 02  %.u?....                        6.2.16                     
               05 02 19 00  29 ff 15 00  ....)...                        6.2.24                     
               25 ff 75 3f  95 08 91 02  %.u?....                        6.2.32                     
               c0 05 01 09  06 a1 01 85  ........                        6.2.40                     
               02 05 07 19  e0 29 e7 15  .....)..                        6.2.48                     
               00 25 01 95  08 75 01 81  .%...u..                        6.2.56                     
               02 95 01 75  08 81 03 95  ...u....                        6.2.64                     
               06 75 08 25  ff 19 00 29  .u.%...)                        6.2.72                     

               65 81 00 c0               e...                            6.2.80             

我们发现中间有一行错误信息 USTS   c0000004                  stall pid          11ms         5.2.0        13:45:02.505  。这是window提示的错误。      

这是主机在获取  描述符时没有获取到,当我的设备(当然不是所有的设备)收到主机发送的请求bRequest=0a时,在driver/usb/gadget/f_hid.c文件的hidg_setup函数, 发现没有匹配的选项,就直接进入default:
printk( "Unknown request 0x%x\n", ctrl->bRequest);
goto stall;
break;

直接结束了,这样主机就没有枚举成功,为了让主机继续枚举下去,我们在这个函数中加了一个选项。在default上面添加如下代码

 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8  
            | USB_REQ_GET_INTERFACE):  
            VDBG(cdev, "get_interface | wLenght=%d\n", ctrl->wLength);  
            /* send an empty report */  
            length = min_t(unsigned, length, hidg->report_length);  
            memset(req->buf, 0x0, length);  
            goto respond;  
            break;
        //patched by hds
default:
printk( "Unknown request 0x%x\n", ctrl->bRequest);
goto stall;
break;

保存,编译内核,加载内核。插上设备发现错误没有出现。

但是当我通信的时候去出现了下面的错误

IN     01 ea fd 01  01 55 00 00  .....U..          520ms      2002.1.0        17:24:32.392  
               00 00 00 00  00 00 00 00  ........                     2002.1.8                      
               00 00 00 00  00 00 00 00  ........                     2002.1.16                     
               00 00 00 00  00 00 00 00  ........                     2002.1.24                     
  19    IN     01 ea fd 01  01 55 00 00  .....U..           19us      2003.1.0        17:24:32.392  
               00 00 00 00  00 00 00 00  ........                     2003.1.8                      
               00 00 00 00  00 00 00 00  ........                     2003.1.16                     
               00 00 00 00  00 00 00 00  ........                     2003.1.24                     
  18.2  OUT    01 ca ee 01  ce 00 00 00  ........          966us      2004.1.0        17:24:32.393  
               00 00 00 00  00 00 00 00  ........                     2004.1.8                      
               00 00 00 00  00 00 00 00  ........                     2004.1.16                     
               00 00 00 00  00 00 00 00  ........                     2004.1.24                     
  19    OUT    01 ca ee 01  ce 00 00 00  ........            9us      2005.1.0        17:24:32.393  
               00 00 00 00  00 00 00 00  ........                     2005.1.8                      
               00 00 00 00  00 00 00 00  ........                     2005.1.16                     
               00 00 00 00  00 00 00 00  ........                     2005.1.24                     
  18.1  IN     01 ea fe 01  01 b1 00 00  ........          520ms      2006.1.0        17:24:32.913  
               00 00 00 00  00 00 00 00  ........                     2006.1.8                      
               00 00 00 00  00 00 00 00  ........                     2006.1.16                     
               00 00 00 00  00 00 00 00  ........                     2006.1.24                     
  19    IN     01 ea fe 01  01 b1 00 00  ........           15us      2007.1.0        17:24:32.913  
               00 00 00 00  00 00 00 00  ........                     2007.1.8                      
               00 00 00 00  00 00 00 00  ........                     2007.1.16                     
               00 00 00 00  00 00 00 00  ........                     2007.1.24                     
  18.2  USTS   c0000011                  xact error        2.9ms      2008.1.0        17:24:32.916  
  18.1  IN     01 ea ff 01  01 1a 00 00  ........          526ms      2009.1.0        17:24:33.443  
               00 00 00 00  00 00 00 00  ........                     2009.1.8                      
               00 00 00 00  00 00 00 00  ........                     2009.1.16                     
               00 00 00 00  00 00 00 00  ........                     2009.1.24                     
  19    IN     01 ea ff 01  01 1a 00 00  ........           18us      2010.1.0        17:24:33.443  
               00 00 00 00  00 00 00 00  ........                     2010.1.8                      
               00 00 00 00  00 00 00 00  ........                     2010.1.16                     
               00 00 00 00  00 00 00 00  ........                     2010.1.24                     
  18.2  USTS   c0000030                  endpoint halted   138us      2011.1.0        17:24:33.443  

每次交互读写几分钟后就出现这样的错误。

哎,大概找个一个礼拜的时间,把内核调试信息都打开了,什么调试信息更是加的哪里都有。整的很乱。。。

首先,大概许多同学还不知道怎么打开当前内核文件的调试信息的,我也是网上搜的,这里跟大家一起分享一下。

 1、打开调试开关:你调试的文件中必然包含了<linux/device.h>,或者《linux/paltforam_device.h》,后者包含了前者,在包含此头文件之前,使用#define DEBUG 1 来打开调试开关:例如
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <linux/module.h>
#define DEBUG    1
#include <linux/platform_device.h>

但是这个打开了之后,也不能顺利的输出信息,原因是printk有默认的信息级别。

2、修改文件kernel/printk文件
/* printk's without a loglevel use this.. */
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */

/* We show everything that is MORE important than this.. */
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
#define DEFAULT_CONSOLE_LOGLEVEL 8 /* anything MORE serious than KERN_DEBUG */
   其中
DEFAULT_CONSOLE_LOGLEVEL为终端console输出的最低级别,比这严重的都将输出。原来该值为7,则调试信息无法输出,修改为8则全部有输出


听老大讲,是因为2方面。

1、我用的是台式机的前面插口,这的插口电流没有后面足,而且这usb接口是经主板引接过来的,会有信号损耗。


2、我连接usb设备的usb线也选择的太长了,有一米多吧。2者加起来,导致信号丢失。造成window报错。

主要还是因为第一点,直接把线拔掉插在后面usb接口,错误不在出现了。

感觉usb水很深,学了大概半个月了,也是一知半解。有错误的地方,请高手指点。。。

猜你喜欢

转载自blog.csdn.net/a_tu_/article/details/43021977