USB Usage AC Pan

最近我在查看一款鼠标的 HID 描述符时,遇到一个定义 AC Pan 搞不清楚意思:

ac1

直接看 USB HID协议上面解释也比较简单,看不懂

ac2

鼠标是最普通的款式,上面有三个按键,左右已经滚轮下面的一个按键,此外就只有滚轮了。当然我也没有找到发出 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 这样的软件经常需要水平方向的滚动用这个功能会很方便。

修改后的完整库下载:

Mouse

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注