主题 : 完成了一个将MINI2440做为下位机的USB通讯程序 复制链接 | 浏览器收藏 | 打印
级别: 新手上路
UID: 69838
精华: 0
发帖: 11
金钱: 55 两
威望: 11 点
综合积分: 22 分
注册时间: 2012-05-11
最后登录: 2016-12-02
楼主  发表于: 2012-06-13 10:10

 完成了一个将MINI2440做为下位机的USB通讯程序

最近完成了一个与MINI2440 USB通讯的程序,  感觉整个过程还是比较简单的,在这里记录下来. 以下过程是基于linux-2.6.32.2-mini2440-20110413来进行的.

MINI2440里的驱动程序是在论坛里有人发的zebra_mouse的基础上改进过来的, 是基于gadget的驱动程序。  不过那个程序只有读数据的:即MINI2440发送数据到主机, 不能写数据到MINI2440里.

更改起来也比较容易, 参考gadget下的printer的驱动,就可以很轻松的完成.
实际的过程就是printer里的read, zebra_mouse_ioctl两部分加到zebra_mouse里去
然后添加相关的变量及程序段就可以了.

接下来是比较关键的一步, 就是更改USB的配置.

以前看USB入门的时候, 总会要求去看USB协议. 这是个好办法, 但估计会有80%的人跟我一样,看的一头雾水,还不知道怎么回事.  这绝对是个误区.

后来通过一些实际的程序, 才知道,学习USB可以不用从那部分开始, 从一些现有的程序上去改, 反到更快, 只要知道更改哪些就好了 USB麻烦的地方也就是需要知道改哪些. 其实可以通过一些USB软件,如USBlyzer来查看就行了..

针对这个zebra_mouse程序, 我需要的实现的功能是上位机能发送/读取MINI2440中的数据. 所以要更改的只是设置到进与出就好了。

USB的数据是通过endpoint来传输的, 所以对zebra_mouse 的更改就是更改endpoint就可以了.

原程序中只有EP0, 将数据输出到上位机, 程序如下:
static struct usb_endpoint_descriptor fs_ep_in_desc = {
    .bLength =        USB_DT_ENDPOINT_SIZE,
    .bDescriptorType =    USB_DT_ENDPOINT,
    .bEndpointAddress =    USB_DIR_IN,
    .bmAttributes =        USB_ENDPOINT_XFER_INT,
    .wMaxPacketSize =    __constant_cpu_to_le16(2),
    .bInterval =        32,    // frames -> 32 ms
};

关键的参数有
bEndpointAddress =    USB_DIR_IN,
bmAttributes =        USB_ENDPOINT_XFER_INT,
wMaxPacketSize =    __constant_cpu_to_le16(2),

分别对应的是数据输入(上位机到MINI2440), 中断传输, 以及包长度.
我更改为:
static struct usb_endpoint_descriptor fs_ep_in_desc = {
    .bLength =        USB_DT_ENDPOINT_SIZE,
    .bDescriptorType =    USB_DT_ENDPOINT,
    .bEndpointAddress =    USB_DIR_IN,
    .bmAttributes =        USB_ENDPOINT_XFER_INT,
    .wMaxPacketSize =    __constant_cpu_to_le16(64),
    .bInterval =        32,    // frames -> 32 ms
};
只更改了包长度. 具体为什么是64? 估计在USB协议中能找到.

另外还需要加入一个用来数据输出的(MINI2440到上位机的) EP,
static struct usb_endpoint_descriptor fs_ep_out_desc = {
    .bLength =        USB_DT_ENDPOINT_SIZE,
    .bDescriptorType =    USB_DT_ENDPOINT,
    .bEndpointAddress =    USB_DIR_OUT,
    .bmAttributes =        USB_ENDPOINT_XFER_INT,
    .wMaxPacketSize =    __constant_cpu_to_le16(64),
    .bInterval =        32,    // frames -> 32 ms
};


这样就ok了, 是不是很简单? 不过还有两点没完成
更改完EP后, 还需要对USB接口描述进行修改.  这部分其实就是告诉上位机, 我这个USB设备是什么东西..
要改的地方也很简单. 原文是:
static struct usb_interface_descriptor intf_desc = {
    .bLength =        0x09,
    .bDescriptorType =    0x04,//USB_DT_INTERFACE,
    .bInterfaceNumber =    0x00,//DEV_CONFIG_VALUE,
    .bNumEndpoints =    0x01,
    .bInterfaceClass =    0x03,//USB_CLASS_HID,
    .bInterfaceSubClass =    0x00,    /* Printer Sub-Class */
    .bInterfaceProtocol =    0x00,    /* Bi-Directional */
    .iInterface =        0x00
};

更改为
static struct usb_interface_descriptor intf_desc = {
    .bLength =        0x09,
    .bDescriptorType =    0x04,//USB_DT_INTERFACE,
    .bInterfaceNumber =    0x00,//DEV_CONFIG_VALUE,
    .bNumEndpoints =    0x02,
    .bInterfaceClass =    0x00,//USB_CLASS_HID,
    .bInterfaceSubClass =    0x00,    /* Printer Sub-Class */
    .bInterfaceProtocol =    0x00,    /* Bi-Directional */
    .iInterface =        0x00
};


只改了红字部分, 不要被注释迷惑了.
更改的部分是告诉主机这次的USB设备有2个ep, 是普通设备. 不是HID.

接下来更改是PID和VID.  这两个数据有很重要的作用, 除了告诉上位机这个USB设备是谁的以外, 还关乎到了上位机的驱动程序.
原文是
#define PRINTER_VENDOR_NUM    0x8888        /* NetChip */
#define PRINTER_PRODUCT_NUM    0x7777        /* Linux-USB Printer Gadget */

我更改成了:
#define PRINTER_VENDOR_NUM    0x10c4        /* NetChip */
#define PRINTER_PRODUCT_NUM    0x0000        /* Linux-USB Printer Gadget */

0x10c4是Silicon Laboratories公司的ID号, 就是那个C8051F的单片机的那个.
改成这个原因主要是因为wndows的驱动程序是现成的. 我不用费劲的再去整什么DDK了.
多说一句, 只要Zebra_mouse里的PID, VID能跟inf文件里的pid, vid对上就行了, 不管描述的字符串是什么. 如果你发现更改了描述字符串还不行, 换个USB口或重装下驱动试下.

这样万事ok了, 编译一下, 然后发现很多错误. 原来是将printer里的代码复制过去后, 很多变量没改.
改好, 编译, 虽然还有警告, 但毕竟是编译通过了. 然后开始测试.

先加载驱动 s3c2410_udc.ko, 再加载zebra_mouse.ko, 然后运行usbmouse2,



看起来是不是和串口的调试有点类似?

至于PC端上位机的编写,可以在网上找一下这个:45785280C8051f(USB).rar,  是C8051的USB通讯例子, 用这个就行.

附件是相关的代码, 运行程序以及windows下的驱动.
zebro_mouse.rar (41 K) 下载次数:322


其他遗留问题:
编译有警告, 有机会再认真改吧.
测试程序在读写数据的时候是阻塞方式的, 不太好, 不知道有没有可能改成非阻塞的.


级别: 新手上路
UID: 28111
精华: 0
发帖: 48
金钱: 245 两
威望: 49 点
综合积分: 96 分
注册时间: 2010-09-06
最后登录: 2012-08-23
1楼  发表于: 2012-07-07 18:09
很厉害,如果能和你交流的话应该能学很多的东西
:)
级别: 骑士
UID: 61588
精华: 5
发帖: 248
金钱: 1500 两
威望: 300 点
综合积分: 596 分
注册时间: 2012-01-02
最后登录: 2018-03-05
2楼  发表于: 2012-08-14 16:56
厉害,厉害!!!
:)
级别: 骑士
UID: 61588
精华: 5
发帖: 248
金钱: 1500 两
威望: 300 点
综合积分: 596 分
注册时间: 2012-01-02
最后登录: 2018-03-05
3楼  发表于: 2012-08-14 16:56
:)
级别: 骑士
UID: 61588
精华: 5
发帖: 248
金钱: 1500 两
威望: 300 点
综合积分: 596 分
注册时间: 2012-01-02
最后登录: 2018-03-05
4楼  发表于: 2012-08-14 17:13
”以前看USB入门的时候, 总会要求去看USB协议. 这是个好办法, 但估计会有80%的人跟我一样,看的一头雾水,还不知道怎么回事.  这绝对是个误区.“

太有同感了,可惜领导没认识到,老让我抱着   协议 看!!!!!


你救了我!!
:)
级别: 骑士
UID: 61588
精华: 5
发帖: 248
金钱: 1500 两
威望: 300 点
综合积分: 596 分
注册时间: 2012-01-02
最后登录: 2018-03-05
5楼  发表于: 2012-08-14 17:36
win下的驱动不是友善提供的DWN用的吧? 我怎么安装不上呢????
级别: 侠客
UID: 69671
精华: 0
发帖: 65
金钱: 325 两
威望: 65 点
综合积分: 130 分
注册时间: 2012-05-09
最后登录: 2015-07-02
6楼  发表于: 2013-06-19 17:13
我购买的板子 是Tiny210 v1.0  linux -2.6.35.7  (编译环境与目标版一致 ) 我想将这个设备作为鼠标用 ,我参考了论坛上的程序

http://www.aiothome.net/read.php?tid-20933.html
http://www.aiothome.net/read.php?tid-2538.html
(S3C2440(S3C2410)当做USB HID鼠标用.
            引用:  先打开内核的Gadget支持,加载上s3c2410_udc,之后编译附件里的zebra_mouse.c为驱动并加载.插上电脑可识别为HID鼠标,之后再编译mouse_test,运行,就可以看到鼠标自己会走了.)
但这个程序是mini2440 的 (对应芯片 s3c2440  其可以使用s3c2410 _udc 驱动 )

我现在遇到的问题是 s3c2410_udc 驱动 无法加载

我的板子芯片是s5pv210  这个是否可以使用 s3c2410 _udc 驱动 如果可以是否 去掉Kconfig中的Depend on Arch_s3c2410 编译进内核 ( 尝试这么做 内核没有成功加载udc驱动,  ) 又将这个模块编译为ko  模块文件, 系统无法加载 这个ko 文件 ,如果不可以使用这个 s3c2410 _udc 驱动  请问应该怎么做  可否联系我qq 41485179
谢谢
级别: 新手上路
UID: 114939
精华: 0
发帖: 1
金钱: 5 两
威望: 1 点
综合积分: 2 分
注册时间: 2015-04-29
最后登录: 2015-06-06
7楼  发表于: 2015-05-17 10:12
您好,请问一下您的截图上面的usbDebug是那个程序呢?还有我们这个程序是开发板作为下位机,就是说电脑这边在操作就好了,为何截图里面还有运行usbmouse2这个程序呢?希望和您交流一下。