极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 18576|回复: 8

Arduino 控制USB设备(7)解析USB鼠标的例子(下)

[复制链接]
发表于 2015-9-11 22:33:30 | 显示全部楼层 |阅读模式
前面实现了HP 鼠标数据的读取,下面继续研究 DELL 的鼠标。还是首先运行取得描述符的程序,结果如下:

Start
Device addressed... Requesting device descriptor.
Device descriptor:

Descriptor Length:        12
USB version:        1.10
Class:        00 Use class information in the Interface Descriptor
Subclass:        00
Protocol:        00
Max.packet size:        08
Vendor ID:        2188
Product ID:        0AE1
Revision ID:        0100
Mfg.string index:        00
Prod.string index:        01 Length: 38 Contents: USB OPTICAL MOUSE
Serial number index:        00
Number of conf.:        01

Configuration number 0
Total configuration length: 34 bytes

Configuration descriptor:
Total length:        0022
Number of interfaces:        01
Configuration value:        01
Configuration string:        00
Attributes:        A0 Remote Wakeup
Max.power:        32 100ma

Interface descriptor:
Interface number:        00
Alternate setting:        00
Endpoints:        01
Class:        03 HID (Human Interface Device)
Subclass:        01
Protocol:        02
Interface string:        00

HID descriptor:
Descriptor length:        09 9 bytes
HID version:        1.11
Country Code:        0 Not Supported
Class Descriptors:        1
Class Descriptor Type:        22 Report
Class Descriptor Length:66 bytes

HID report descriptor:

Length: 1 Type: Global        Tag: Usage Page        Generic Desktop Controls Data: 01
Length: 1 Type: Local        Tag: Usage        Data: 02
Length: 1 Type: Main        Tag: Collection        Application (mouse, keyboard) Data: 01
Length: 1 Type: Global        Tag: Report ID        Data: 01
Length: 1 Type: Local        Tag: Usage        Data: 01
Length: 1 Type: Main        Tag: Collection        Physical (group of axes) Data: 00
Length: 1 Type: Global        Tag: Usage Page        Button Data: 09
Length: 1 Type: Local        Tag: Usage Minimum        Data: 01
Length: 1 Type: Local        Tag: Usage Maximum        Data: 03
Length: 1 Type: Global        Tag: Logical Minimum        Data: 00
Length: 1 Type: Global        Tag: Logical Maximum        Data: 01
Length: 1 Type: Global        Tag: Report Count        Data: 03
Length: 1 Type: Global        Tag: Report Size        Data: 01
Length: 1 Type: Main        Tag: Input        Data,Variable,Absolute,No Wrap,Linear,Preferred State,No Null Position,Non-volatile(Ignore for Input), Data: 02
Length: 1 Type: Global        Tag: Report Count        Data: 01
Length: 1 Type: Global        Tag: Report Size        Data: 05
Length: 1 Type: Main        Tag: Input        Constant,Array,Absolute,No Wrap,Linear,Preferred State,No Null Position,Non-volatile(Ignore for Input), Data: 01
Length: 1 Type: Global        Tag: Usage Page        Generic Desktop Controls Data: 01
Length: 1 Type: Local        Tag: Usage        Data: 30
Length: 1 Type: Local        Tag: Usage        Data: 31
Length: 2 Type: Global        Tag: Logical Minimum        Data: 00 Data: F8
Length: 2 Type: Global        Tag: Logical Maximum        Data: FF Data: 07
Length: 1 Type: Global        Tag: Report Size        Data: 0C
Length: 1 Type: Global        Tag: Report Count        Data: 02
Length: 1 Type: Main        Tag: Input        Data,Variable,Relative,No Wrap,Linear,Preferred State,No Null Position,Non-volatile(Ignore for Input), Data: 06
Length: 1 Type: Local        Tag: Usage        Data: 38
Length: 1 Type: Global        Tag: Logical Minimum        Data: 81
Length: 1 Type: Global        Tag: Logical Maximum        Data: 7F
Length: 1 Type: Global        Tag: Report Size        Data: 08
Length: 1 Type: Global        Tag: Report Count        Data: 01
Length: 1 Type: Main        Tag: Input        Data,Variable,Relative,No Wrap,Linear,Preferred State,No Null Position,Non-volatile(Ignore for Input), Data: 06
Length: 0 Type: Main        Tag: End Collection
Length: 0 Type: Main        Tag: End Collection

Endpoint descriptor:
Endpoint address:        01 Direction: IN
Attributes:        03 Transfer type: Interrupt
Max.packet size:        0006
Polling interval:        0A 10 ms

同样,尝试之前的 Get_Report 方式的程序,得到的却是不停的输出的错误信息:

Setup packet error: 7
Mouse Poll Error: 7

没有办法直接了解这个错误编号的含义,最后只能用逻辑分析仪分析产生问题的原因:



可以看到当发送Get_Report之后,Device 会返回STALL 。

对比之前能够正常工作的 HP 鼠标,收到 Get_Report 后,会返回 ACK 还会继续通讯。



查看资料上说,返回STALL有可能是因为设备不支持该指令…… Windows的设备经常会出现这样的情况:可以正常工作,但是未必完整的 follow 工业标准。

上面的方法行不通,只能用中断方式来获取数据。我去掉了切换 Boot Protocol 的代码

  1. /* Mouse communication via interrupt endpoint  */
  2. /* Assumes EP1 as interrupt IN ep              */
  3. #include "max3421e.h"
  4. #include "usb.h"

  5. #define DEVADDR 1
  6. #define CONFVALUE 1
  7. #define EP_MAXPKTSIZE 5
  8. EP_RECORD ep_record[ 2 ];  //endpoint record structure for the mouse


  9. void setup();
  10. void loop();

  11. MAX3421E Max;
  12. USB Usb;

  13. void setup()
  14. {
  15.     Serial.begin( 115200 );
  16.     Serial.println("Start");
  17.     Max.powerOn();
  18.     delay( 200 );
  19. }

  20. void loop()
  21. {
  22. byte rcode;
  23.     Max.Task();
  24.     Usb.Task();
  25.     if( Usb.getUsbTaskState() == USB_STATE_CONFIGURING ) {
  26.         mouse1_init();
  27.     }//if( Usb.getUsbTaskState() == USB_STATE_CONFIGURING...
  28.     if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) {  //poll the keyboard
  29.         rcode = mouse1_poll();
  30.         if( rcode ) {
  31.           Serial.print("Mouse Poll Error: ");
  32.           Serial.println( rcode, HEX );
  33.         }//if( rcode...
  34.     }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING...
  35. }
  36. /* Initialize mouse */
  37. void mouse1_init( void )
  38. {
  39. byte rcode = 0;  //return code
  40. byte tmpdata;
  41. byte* byte_ptr = &tmpdata;
  42.   /**/
  43.   ep_record[ 0 ] = *( Usb.getDevTableEntry( 0,0 ));  //copy endpoint 0 parameters
  44.   ep_record[ 1 ].MaxPktSize = EP_MAXPKTSIZE;
  45.   ep_record[ 1 ].sndToggle = bmSNDTOG0;
  46.   ep_record[ 1 ].rcvToggle = bmRCVTOG0;
  47.   Usb.setDevTableEntry( 1, ep_record );              //plug kbd.endpoint parameters to devtable
  48.   /* Configure device */
  49.   rcode = Usb.setConf( DEVADDR, 0, CONFVALUE );
  50.   if( rcode ) {
  51.     Serial.print("Error configuring mouse. Return code : ");
  52.     Serial.println( rcode, HEX );
  53.     while(1);  //stop
  54.   }//if( rcode...
  55.   
  56.   rcode = Usb.setIdle( DEVADDR, 0, 0, 0, tmpdata );
  57.   if( rcode ) {
  58.     Serial.print("Set Idle error. Return code : ");
  59.     Serial.println( rcode, HEX );
  60.     while(1);  //stop
  61.   }
  62.   
  63.   rcode = Usb.getIdle( DEVADDR, 0, 0, 0, (char *)byte_ptr );
  64.   if( rcode ) {
  65.     Serial.print("Get Idle error. Return code : ");
  66.     Serial.println( rcode, HEX );
  67.     while(1);  //stop
  68.   }
  69.   Serial.print("Idle Rate: ");
  70.   Serial.print(( tmpdata * 4 ), DEC );        //rate is returned in multiples of 4ms
  71.   Serial.println(" ms");
  72.   tmpdata = 0;
  73.   rcode = Usb.setIdle( DEVADDR, 0, 0, 0, tmpdata );
  74.   if( rcode ) {
  75.     Serial.print("Set Idle error. Return code : ");
  76.     Serial.println( rcode, HEX );
  77.     while(1);  //stop
  78.   }
  79.   Usb.setUsbTaskState( USB_STATE_RUNNING );
  80.   return;
  81. }
  82. /* Poll mouse via interrupt endpoint and print result */
  83. /* assumes EP1 as interrupt endpoint                  */
  84. byte mouse1_poll( void )
  85. {
  86.   byte rcode,i;
  87.   char buf[ 6 ] = { 0 };                          //mouse report buffer

  88.   unsigned long int libuf[ sizeof(buf) ];
  89.   unsigned long int x;
  90.   unsigned long int y;

  91.   
  92.   /* poll mouse */
  93.   rcode = Usb.inTransfer( DEVADDR, 1, sizeof(buf), buf, 1 );  //

  94.     if( rcode ) {  //error
  95.       if( rcode == 0x04 ) {  //NAK
  96.         rcode = 0;
  97.       }
  98.       return( rcode );
  99.     }
  100.     /* print buffer */
  101.     if( buf[ 1 ] & 0x01 ) {
  102.       Serial.println("Button1 pressed ");
  103.     }
  104.     if( buf[ 1 ] & 0x02 ) {
  105.       Serial.println("Button2 pressed ");
  106.     }
  107.     if( buf[ 1 ] & 0x04 ) {
  108.       Serial.println("Button3 pressed ");
  109.     }
  110.    
  111.     for (int i=0;i<sizeof(buf);i++) {
  112.        libuf[i]=(buf[i]) & 0xff;
  113.     }
  114.    
  115.     /*  
  116.     Serial.print(libuf[0],HEX); Serial.print("  ");
  117.     Serial.print(libuf[1],HEX); Serial.print("  ");
  118.     Serial.print(libuf[2],HEX); Serial.print("  ");
  119.     Serial.print(libuf[3],HEX); Serial.print("  ");     
  120.     Serial.print(libuf[4],HEX); Serial.print("  ");         
  121.     Serial.print(libuf[5],HEX); Serial.print("  ");            
  122.     Serial.println("");
  123.     */
  124.    
  125.     Serial.print("X-axis: ");
  126.     x=((libuf[3] & 0xF)<<8)+(libuf[2] & 0xFF );
  127.     if (x & 0x800) {
  128.       Serial.print("-");
  129.       x = ((~x) & 0x7FF) +1;
  130.     }
  131.    
  132.     Serial.print(x, HEX);  Serial.print("   ");
  133.    
  134.     Serial.print("Y-axis: ");   
  135.     y=(((libuf[3]>>4) & 0xF) +((libuf[4] & 0xFF )<<4));
  136.     if (y & 0x800) {
  137.       Serial.print("-");
  138.       y = ((~y) & 0x7FF) +1;
  139.     }   
  140.     Serial.print(y, HEX); Serial.print("   ");

  141.     Serial.print("Wheel: ");   
  142.     Serial.println(buf [5] & 0xFF, HEX);   

  143.     return( rcode );
  144. }
复制代码


和前面那个程序相比,这个特别之处在于返回值多了 Report_ID ,对于我们处理数据来说,只是有效数据从 Buf[1] 开始,其他地方并无特别。

运行结果



完整代码下载

http://www.lab-z.com/ausb7/

基本上,鼠标的玩法就是这些。可以用鼠标做很多好玩的东西。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复

使用道具 举报

发表于 2015-9-12 09:13:17 | 显示全部楼层
那个数据图非常专业呢,是用什么软件实现的?
回复 支持 反对

使用道具 举报

发表于 2015-9-12 10:33:11 | 显示全部楼层
楼主厉害,真是高大上啊,我看不明白啊
回复 支持 反对

使用道具 举报

发表于 2015-9-12 22:15:47 | 显示全部楼层
能否提供一下你那个分析仪的详细信息?我也想采购一个
回复 支持 反对

使用道具 举报

 楼主| 发表于 2015-9-13 07:57:52 | 显示全部楼层
maxims 发表于 2015-9-12 22:15
能否提供一下你那个分析仪的详细信息?我也想采购一个

Advisor T3   Ultra-portable SuperSpeed USB analyzer delivers market leading accuracy at an extraordinary price

http://teledynelecroy.com/protoc ... pid=103&mid=511
回复 支持 反对

使用道具 举报

发表于 2015-9-13 18:54:21 | 显示全部楼层
zoologist 发表于 2015-9-13 07:57
Advisor T3   Ultra-portable SuperSpeed USB analyzer delivers market leading accuracy at an extraor ...

看起来好高端的样子。。。。搞不懂~估计价格也不便宜吧?
回复 支持 反对

使用道具 举报

发表于 2015-9-14 07:46:47 | 显示全部楼层
不是你个人买的啊?
回复 支持 反对

使用道具 举报

发表于 2016-10-17 16:44:45 | 显示全部楼层
楼主 我有个想法 用鼠标来探测一些机器的直线晃动的距离和频率 给出一些正确和不正确报警的反馈?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2016-10-21 15:34:44 | 显示全部楼层
蒸馏水--野妄 发表于 2016-10-17 16:44
楼主 我有个想法 用鼠标来探测一些机器的直线晃动的距离和频率 给出一些正确和不正确报警的反馈?

可以的 没问题
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|联系我们|极客工坊

GMT+8, 2026-6-10 03:27 , Processed in 0.040683 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表