最近我在查看一款鼠标的 HID 描述符时,遇到一个定义 AC Pan 搞不清楚意思:
直接看 USB HID协议上面解释也比较简单,看不懂
鼠标是最普通的款式,上面有三个按键,左右已经滚轮下面的一个按键,此外就只有滚轮了。当然我也没有找到发出 AC Pan 的方法。
想来想去可以使用 Leonardo 来进行验证,把这个值发出来看看系统有什么变化,也能了解功能。
为此,特地修改 Arduino 鼠标的描述符,在 \libraries\Mouse\src\Mouse.cpp 中加入 AC Pan。
static const uint8_t _hidReportDescriptor[] PROGMEM = { // Mouse 0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x01, // USAGE (Pointer) 0xa1, 0x00, // COLLECTION (Physical) 0x85, 0x01, // REPORT_ID (1) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x03, // USAGE_MAXIMUM (Button 3) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x95, 0x03, // REPORT_COUNT (3) 0x75, 0x01, // REPORT_SIZE (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x05, // REPORT_SIZE (5) 0x81, 0x03, // INPUT (Cnst,Var,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x09, 0x38, // USAGE (Wheel) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x03, // REPORT_COUNT (3) 0x81, 0x06, // INPUT (Data,Var,Rel) //LABZ_DEBUG_Start 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) 0x0a, 0x38, 0x02, // USAGE (AC Pan) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x01, // REPORT_COUNT (1) 0x81, 0x06, // INPUT (Data,Var,Rel) //LABZ_DEBUG_End 0xc0, // END_COLLECTION 0xc0, // END_COLLECTION };
当然,做了上面的修改之后,每次发出的消息不再是4个Bytes(Button,X,Y,Wheel),而多了一个。相应的下面的函数也要进行修改,多发出一个 Pan值。
void Mouse_::move(signed char x, signed char y, signed char wheel,signed char pan) { uint8_t m[5]; m[0] = _buttons; m[1] = x; m[2] = y; m[3] = wheel; m[4] = pan; HID().SendReport(1,m,5); }
修改好库之后,再编写一个测试代码,使用 Pin 7 8 拉低来发出 Pan -1 和 +1
#include <Mouse.h> // set pin numbers for the five buttons: const int upButton = 2; const int downButton = 3; const int leftButton = 4; const int rightButton = 5; const int mouseButton = 6; const int pan1 = 7; const int pan2 = 8; int range = 5; // output range of X or Y movement; affects movement speed int responseDelay = 10; // response delay of the mouse, in ms void setup() { // initialize the buttons' inputs: pinMode(upButton, INPUT_PULLUP); pinMode(downButton, INPUT_PULLUP); pinMode(leftButton, INPUT_PULLUP); pinMode(rightButton, INPUT_PULLUP); pinMode(mouseButton, INPUT_PULLUP); pinMode(pan1, INPUT_PULLUP); pinMode(pan2, INPUT_PULLUP); // initialize mouse control: Mouse.begin(); } void loop() { // read the buttons: int upState = digitalRead(upButton); int downState = digitalRead(downButton); int rightState = digitalRead(rightButton); int leftState = digitalRead(leftButton); int clickState = digitalRead(mouseButton); // calculate the movement distance based on the button states: int xDistance = (leftState - rightState) * range; int yDistance = (upState - downState) * range; // if X or Y is non-zero, move: if ((xDistance != 0) || (yDistance != 0)) { Mouse.move(xDistance, yDistance, 0,0); } if(digitalRead(pan1)==LOW) { Mouse.move(xDistance, yDistance, 0,1); Mouse.move(0, 0, 0,0); } if(digitalRead(pan2)==LOW) { Mouse.move(xDistance, yDistance, 0,-1); Mouse.move(0, 0, 0,0); } // if the mouse button is pressed: if (clickState == HIGH) { // if the mouse is not pressed, press it: if (!Mouse.isPressed(MOUSE_LEFT)) { Mouse.press(MOUSE_LEFT); } } // else the mouse button is not pressed: else { // if the mouse is pressed, release it: if (Mouse.isPressed(MOUSE_LEFT)) { Mouse.release(MOUSE_LEFT); } } // a delay so the mouse doesn't move too fast: delay(responseDelay); }
最终的实验表明, AC Pan 是类似水平方向的滚轮,在使用 Excel 这样的软件经常需要水平方向的滚动用这个功能会很方便。
修改后的完整库下载: