Teensy 打造手机游戏辅助器-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 5208|回复: 7

Teensy 打造手机游戏辅助器

[复制链接]
发表于 2018-8-29 21:11 | 显示全部楼层 |阅读模式
最近我在玩一个安卓的射击游戏。 偶然发现可以使用鼠标进行游戏,但是使用鼠标有下面两条:
1.     鼠标右键会导致游戏闪退
2.     不同武器射击方式有差别。例如:狙击枪长按鼠标左键打开瞄准镜,速成“开镜”,瞄准目标后抬起左键立即射击;机关枪最好用三连发点射。

为此,我使用 Teensy 搭配 USB Host Mini 做了一个转接器,将USB鼠标操作解析过滤之后再送入手机。
我使用的是微软 InteliMouse Optical1.1A 鼠标。这款鼠标有5个按键,使用到的只有左键和右键。在设计上,可以其中前者用来发射,后者用来切换不同的射击模式。
image001.png                               

首先需要解析这个鼠标的数据。使用之前介绍过很多次的 USBlyzer进行分析,第一步查看描述符了解鼠标数据的格式:
Microsoft USBIntelliMouse Optical
  
Connection Status
  
  
Device connected
  
  
Current Configuration
  
  
1
  
  
Speed
  
  
Low (1.5 Mbit/s)
  
  
Device Address
  
  
5
  
  
Number Of Open Pipes
  
  
1
  
Device Descriptor Microsoft5-Button Mouse with IntelliEye(TM)
  
Offset
  
  
Field
  
  
Size
  
  
Value
  
  
Description
  
  
0
  
  
bLength
  
  
1
  
  
12h
  
  
1
  
  
bDescriptorType
  
  
1
  
  
01h
  
  
Device
  
  
2
  
  
bcdUSB
  
  
2
  
  
0110h
  
  
USB Spec 1.1
  
  
4
  
  
bDeviceClass
  
  
1
  
  
00h
  
  
Class info in Ifc Descriptors
  
  
5
  
  
bDeviceSubClass
  
  
1
  
  
00h
  
  
6
  
  
bDeviceProtocol
  
  
1
  
  
00h
  
  
7
  
  
bMaxPacketSize0
  
  
1
  
  
08h
  
  
8 bytes
  
  
8
  
  
idVendor
  
  
2
  
  
045Eh
  
  
10
  
  
idProduct
  
  
2
  
  
0039h
  
  
12
  
  
bcdDevice
  
  
2
  
  
0300h
  
  
3.00
  
  
14
  
  
iManufacturer
  
  
1
  
  
01h
  
  
"Microsoft"
  
  
15
  
  
iProduct
  
  
1
  
  
03h
  
  
"Microsoft 5-Button Mouse  with IntelliEye(TM)"
  
  
16
  
  
iSerialNumber
  
  
1
  
  
00h
  
  
17
  
  
bNumConfigurations
  
  
1
  
  
01h
  
Configuration Descriptor1 Bus Powered, 100 mA
  
Offset
  
  
Field
  
  
Size
  
  
Value
  
  
Description
  
  
0
  
  
bLength
  
  
1
  
  
09h
  
  
1
  
  
bDescriptorType
  
  
1
  
  
02h
  
  
Configuration
  
  
2
  
  
wTotalLength
  
  
2
  
  
0022h
  
  
4
  
  
bNumInterfaces
  
  
1
  
  
01h
  
  
5
  
  
bConfigurationValue
  
  
1
  
  
01h
  
  
6
  
  
iConfiguration
  
  
1
  
  
00h
  
  
7
  
  
bmAttributes
  
  
1
  
  
A0h
  
  
Bus Powered, Remote Wakeup
  
  
4..0: Reserved
  
  
...00000
  
  
5: Remote Wakeup
  
  
..1.....
  
  
Yes
  
  
6: Self Powered
  
  
.0......
  
  
No, Bus Powered
  
  
7: Reserved (set to one)
  (bus-powered for 1.0)
  
  
1.......
  
  
8
  
  
bMaxPower
  
  
1
  
  
32h
  
  
100 mA
  
Interface Descriptor 0/0 HID,1 Endpoint
  
Offset
  
  
Field
  
  
Size
  
  
Value
  
  
Description
  
  
0
  
  
bLength
  
  
1
  
  
09h
  
  
1
  
  
bDescriptorType
  
  
1
  
  
04h
  
  
Interface
  
  
2
  
  
bInterfaceNumber
  
  
1
  
  
00h
  
  
3
  
  
bAlternateSetting
  
  
1
  
  
00h
  
  
4
  
  
bNumEndpoints
  
  
1
  
  
01h
  
  
5
  
  
bInterfaceClass
  
  
1
  
  
03h
  
  
HID
  
  
6
  
  
bInterfaceSubClass
  
  
1
  
  
01h
  
  
Boot Interface
  
  
7
  
  
bInterfaceProtocol
  
  
1
  
  
02h
  
  
Mouse
  
  
8
  
  
iInterface
  
  
1
  
  
00h
  
HID Descriptor
  
Offset
  
  
Field
  
  
Size
  
  
Value
  
  
Description
  
  
0
  
  
bLength
  
  
1
  
  
09h
  
  
1
  
  
bDescriptorType
  
  
1
  
  
21h
  
  
HID
  
  
2
  
  
bcdHID
  
  
2
  
  
0110h
  
  
1.10
  
  
4
  
  
bCountryCode
  
  
1
  
  
00h
  
  
5
  
  
bNumDescriptors
  
  
1
  
  
01h
  
  
6
  
  
bDescriptorType
  
  
1
  
  
22h
  
  
Report
  
  
7
  
  
wDescriptorLength
  
  
2
  
  
0048h
  
  
72 bytes
  
Endpoint Descriptor 81 1In, Interrupt, 10 ms
  
Offset
  
  
Field
  
  
Size
  
  
Value
  
  
Description
  
  
0
  
  
bLength
  
  
1
  
  
07h
  
  
1
  
  
bDescriptorType
  
  
1
  
  
05h
  
  
Endpoint
  
  
2
  
  
bEndpointAddress
  
  
1
  
  
81h
  
  
1 In
  
  
3
  
  
bmAttributes
  
  
1
  
  
03h
  
  
Interrupt
  
  
1..0: Transfer Type
  
  
......11
  
  
Interrupt
  
  
7..2: Reserved
  
  
000000..
  
  
4
  
  
wMaxPacketSize
  
  
2
  
  
0004h
  
  
4 bytes
  
  
6
  
  
bInterval
  
  
1
  
  
0Ah
  
  
10 ms
  
Interface 0 HID ReportDescriptor Mouse
  
Item Tag (Value)
  
  
Raw Data
  
  
Usage Page (Generic Desktop)
  
  
05 01
  
  
Usage (Mouse)
  
  
09 02
  
  
Collection (Application)
  
  
A1 01
  
  
    Usage  (Pointer)
  
  
09 01
  
  
    Collection  (Physical)
  
  
A1 00
  
  
        Usage  Page (Button)
  
  
05 09
  
  
        Usage  Minimum (Button 1)
  
  
19 01
  
  
        Usage  Maximum (Button 5)
  
  
29 05
  
  
        Logical  Minimum (0)
  
  
15 00
  
  
        Logical  Maximum (1)
  
  
25 01
  
  
        Report  Size (1)
  
  
75 01
  
  
        Report  Count (5)
  
  
95 05
  
  
        Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit)
  
  
81 02
  
  
        Report  Size (3)
  
  
75 03
  
  
        Report  Count (1)
  
  
95 01
  
  
        Input (Cnst,Ary,Abs)
  
  
81 01
  
  
        Usage  Page (Generic Desktop)
  
  
05 01
  
  
        Usage  (X)
  
  
09 30
  
  
        Usage  (Y)
  
  
09 31
  
  
        Usage  (Wheel)
  
  
09 38
  
  
        Logical  Minimum (-127)
  
  
15 81
  
  
        Logical  Maximum (127)
  
  
25 7F
  
  
        Report  Size (8)
  
  
75 08
  
  
        Report  Count (3)
  
  
95 03
  
  
        Input (Data,Var,Rel,NWrp,Lin,Pref,NNul,Bit)
  
  
81 06
  
  
    End Collection
  
  
C0
  
  
    Usage Page
  
  
05 FF
  
  
    Usage
  
  
09 02
  
  
    Logical  Minimum (0)
  
  
15 00
  
  
    Logical  Maximum (1)
  
  
25 01
  
  
    Report  Size (1)
  
  
75 01
  
  
    Report  Count (1)
  
  
95 01
  
  
    Feature (Data,Var,Abs,NWrp,Lin,NPrf,NNul,NVol,Bit)
  
  
B1 22
  
  
    Report  Size (7)
  
  
75 07
  
  
    Report  Count (1)
  
  
95 01
  
  
    Feature (Cnst,Ary,Abs,NWrp,Lin,Pref,NNul,NVol,Bit)
  
  
B1 01
  
  
End Collection
  
  
C0
  
This report was generated by USBlyzer
关注点在 HID Descriptor上。同时,移动鼠标按下按键结合抓取数据的功能:

   image002.png image003.png image004.png
最终确定鼠标发出来的数据格式如下:
  
偏移
  
长度(Byte)
功能
0
1
Report ID
1
1
按键信息
  
BIT0:左键
  
BIT1:右键
  
BIT2:中键
  
BIT3:左下键
  
BIT4:右下键
2
1
X 方向移动距离,范围 -127~+127
4
1
Y 方向移动距离,范围 -127~+127
6
1
滚轮,范围 -127~+127

有了上面的数据格式,配合USB Host Shield可以得知鼠标的操作,比如:移动多少距离,是否按下鼠标左键。和之前的解析方式类似,这次选择的是USBHost Mini,它和之前使用的USBHOST Shield都是同一个作者设计的,使用相同的核心芯片(MAX3421E),因此使用的库和调用方法是相同的。具体的 rework 方法可以在之前的帖子中看到。
image005.png

相比键盘鼠标对于时间非常敏感,高速的读取和解析是必要的,为了保证游戏体验这次使用 Teensy3.2。这是一款Arduino 兼容板,和Arduino相比,它速度更快(Teensy3.272Mhz64K 内存),同时和Arduino代码100%兼容,无需专门修改 Arduino 代码即可烧写运行。 此外,Teensy3.2 引脚都是3.3V 的,因此,可以直接将它 USB Host 相连。为了方便使用笔者又设计了一块不包含任何元件的转接板,使用时只要将Teensy Shield一同插到转接板即可工作。

image009.gif
image008.gif
拿到PCB之后焊接排插,将Teensy 3.2 USBHOST MINI 插接在一起即可工作:
image010.jpg
此外,使用 D2/D3/D4 Pin连接3LED,分别表示:正常射击,三连发射击和模拟长按射击,不同模式使用鼠标右键顺序切换。正常射击模式

完整代码

msmouse.ino
[mw_shl_code=c,true]#include <SPI.h>

#include "msParser.h"



USB Usb;

MSPARSER msparser(&Usb);



bool printTilt;



void setup() {

  Serial.begin(115200);



  //3个状态指示灯用来指示状态

  pinMode(2,OUTPUT);

  pinMode(3,OUTPUT);

  pinMode(4,OUTPUT);



  if (Usb.Init() == -1) {

    Serial.print(F("\r\nOSC did not start"));

    while (1); // Halt

  }

  Serial.println(F("\r\nSteelSeries SRW-S1 Steering Wheel example started"));

  msparser.SetMode(0);

}



void loop() {

  Usb.Task();



  if (msparser.connected()) {

    if (printTilt) { // Show tilt angle using the LEDs

    }

  }

}

[/mw_shl_code]

msParser.h

[mw_shl_code=c,true]#ifndef __srws1_h__
#define __srws1_h__
#include <hiduniversal.h>
//鼠标的PID和VID
#define STEELSERIES_VID      0x045E
#define STEELSERIES_SRWS1_PID 0x0039
class MSPARSER : public HIDUniversal {
public:
        MSPARSER(USB*p) : HIDUniversal(p) {};
        voidSetMode(int Current);
        int  GetMode();
        boolconnected() {
                returnHIDUniversal::isReady() && HIDUniversal::VID == STEELSERIES_VID&& HIDUniversal::PID == STEELSERIES_SRWS1_PID;
        };
private:
        voidParseHIDData(USBHID *hid, bool is_rpt_id, uint8_t len, uint8_t *buf); // Calledby the HIDUniversal library
        uint8_tOnInitSuccessful() { // Called by the HIDUniversal library on success
                if(HIDUniversal::VID != STEELSERIES_VID || HIDUniversal::PID !=STEELSERIES_SRWS1_PID) // Make sure the right device is actually connected
                       return 1;
                return0;
        };
        int Mode=0;
};
#endif[/mw_shl_code]


这是完成主要工作的文件
msParser.cpp
[mw_shl_code=c,true]#include "msParser.h"
#include <Mouse.h>
//设置当前的射击模式
void MSPARSER::SetMode(int Current)
{
  digitalWrite(2,LOW);
  digitalWrite(3,LOW);
  digitalWrite(4,LOW);
Serial.print("Current");
Serial.println(Current);
  switch (Current) {
    case 0: //Mode 0 正常模式,鼠标信息只是Bypass
     digitalWrite(2,HIGH);
      break;
    case 1: //Mode 1 速射模式,模拟快速按键
     digitalWrite(3,HIGH);
      break;
    case 2: //Mode 2 狙击枪模式,模拟按下一段时间设计
     digitalWrite(4,HIGH);
      break;
    default:
    break;
  }
  Mode=Current;
}
//返回当前的射击模式
int MSPARSER::GetMode()
{
  return Mode;
}
//解析USB鼠标的数据
void MSPARSER::ParseHIDData(USBHID *hid, bool is_rpt_id,uint8_t len, uint8_t *buf) {
        if(HIDUniversal::VID != STEELSERIES_VID || HIDUniversal::PID !=STEELSERIES_SRWS1_PID)
               return;
        if (len&& buf)  {
                //输出收到的数据
                for(uint8_t i = 0; i < len; i++) {
                       if (buf<0x10) {Serial.print("0");}
                       Serial.print(buf,HEX);
                       Serial.print(" ");
                }
                Serial.println();
                //如果鼠标移动了,那么也让模拟鼠标相同的移动
                if((buf[1]!=0)||(buf[2]!=0)) {
                    Mouse.move(buf[1],buf[2]);
                  }
                  
                if(buf[0]&1!=0) {  //如果按下鼠标左键
                  if (GetMode()==0) { //正产模式
                     Mouse.press(MOUSE_LEFT);
                    }
                  if(GetMode()==1) { //速射模式,打三发
                     Mouse.press(MOUSE_LEFT);
                     delay(10);
                     Mouse.release(MOUSE_LEFT);
                     delay(10);
                     Mouse.press(MOUSE_LEFT);
                     delay(10);
                     Mouse.release(MOUSE_LEFT);
                     delay(10);
                     Mouse.press(MOUSE_LEFT);
                     delay(10);
                     Mouse.release(MOUSE_LEFT);
                   }  
                  if(GetMode()==2) { //狙击模式,长按然后马上发射
                     Mouse.press(MOUSE_LEFT);
                     delay(500);
                     Mouse.release(MOUSE_LEFT);
                    }
                }
                elseif (Mouse.isPressed(MOUSE_LEFT)){
                   Mouse.release(MOUSE_LEFT);
                  }
               
                if((buf[0]&2)!=0) {
                 Serial.println("Fired");
                    SetMode((GetMode()+1)%3);
                 }  
        }
}[/mw_shl_code]

最后,将鼠标接在USB Host Mini 上,然后再将 Teensy 连接到手机上就可以快乐的进行游戏了。除了打得准,我相信鼠标能让你的手更轻松………
游戏视频可以在 https://zhuanlan.zhihu.com/p/43195205 看到
发表于 2019-2-23 21:44 | 显示全部楼层
https://blog.csdn.net/skdev/article/details/48528293
发表于 2019-2-23 21:47 | 显示全部楼层
我之前也做过类似的 不过是用stm32实现的 在stm32cubeMX构建的时候改一下描述符就可以了 只是不能直接插鼠标啊 看来hostusb这块板用处大大哟
发表于 2019-2-23 21:49 | 显示全部楼层
哈哈 游戏是死亡之屋吧 我在wii上和ps3上都玩过
发表于 2019-2-23 22:23 | 显示全部楼层
“它速度更快(Teensy3.2,72Mhz,64K 内存),同时和Arduino代码100%兼容,无需专门修改 Arduino 代码即可烧写运行。”能具体讲讲吗,teensy家族只有这款100%兼容arduino代码吗?其他的像teensy2.0 teensy2.0++呢?这么问是因为这两块现在比较偏移。
发表于 2019-2-23 22:26 | 显示全部楼层
我还想知道teensy可以干哪些arduino不可以干的事,感觉arduino家族里也有可以直接被电脑认到的,像leonardo promicro 甚至用nicohoodHID也可以,不懂为什么teensy能入你的法眼哈,有空的话希望听你聊聊
发表于 2019-2-23 22:28 | 显示全部楼层
之前看过Arduino for Musicians: A Complete Guide to Arduino and Teensy Microcontrollers这本,但里面只是很少一部分提到了teensy,不知道你有没有什么资料可以推荐
 楼主| 发表于 2019-2-24 01:53 | 显示全部楼层
impking 发表于 2019-2-23 22:28
之前看过Arduino for Musicians: A Complete Guide to Arduino and Teensy Microcontrollers这本,但里面只 ...

直接看 teensy 制造商网站
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 11:31 , Processed in 0.089188 second(s), 18 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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