gentleman 发表于 2023-9-4 08:35:10

USB-HID 手柄制作 (一)

本帖最后由 gentleman 于 2023-9-4 08:37 编辑

注意本文使用了微软360手柄的PID VID ,仅供交流学习使用。


本文使用设备描述符 等信息均来自互联网


       基于试验箱usb鼠标例程修改。


       先更换设备描述符
      
      
char code DEVICEDESC =
    {
      // 0x12,                   //bLength(18);
      // 0x01,                   //bDescriptorType(Device);
      // 0x00,0x02,            //bcdUSB(2.00);
      // 0x00,                   //bDeviceClass(0);
      // 0x00,                   //bDeviceSubClass0);
      // 0x00,                   //bDeviceProtocol(0);
      // 0x40,                   //bMaxPacketSize0(64);
      // 0xbf,0x34,            //idVendor(34BF);
      // 0x04,0xff,            //idProduct(FF04);
      // 0x00,0x01,            //bcdDevice(1.00);
      // 0x01,                   //iManufacturer(1);
      // 0x02,                   //iProduct(2);
      // 0x00,                   //iSerialNumber(0);
      // 0x01,                   //bNumConfigurations(1);

      0x12,       // bLength(18);
      0x01,       // bDescriptorType(Device);
      0x00, 0x02, // bcdUSB(2.00);
      0xFF,       // bDeviceClass(0);
      0xFF,       // bDeviceSubClass0);
      0xFF,       // bDeviceProtocol(0);
      0x40,       // bMaxPacketSize0(64);
      0x5e, 0x04, // idVendor(34BF);
      0x8e, 0x02, // idProduct(FF04);
      0x14, 0x01, // bcdDevice(1.00);
      0x01,       // iManufacturer(1);
      0x02,       // iProduct(2);
      0x03,       // iSerialNumber(0);
      0x01,       // bNumConfigurations(1);
};配置描述符

char code CONFIGDESC=
{
    0x09,       // bLength(9);
      0x02,       // bDescriptorType(Configuration);
      0x99, 0x00, // wTotalLength(41);
      0x04,       // bNumInterfaces(1);
      0x01,       // bConfigurationValue(1);
      0x00,       // iConfiguration(0);
      0xa0,       // bmAttributes(BUSPower);
      0xfa,       // MaxPower(100mA);

      /* ---------------------------------------------------- */
      // Interface 0: Control Data
      0x09, // bLength
      0x04, // bDescriptorType (INTERFACE)
      0x00, // bInterfaceNumber
      0x00, // bAlternateSetting
      0x02, // bNumEndpoints
      0xFF, // bInterfaceClass
      0x5D, // bInterfaceSubClass
      0x01, // bInterfaceProtocol
      0x00, // iInterface
      // Unknown Descriptor (If0)
      0x11,                         // bLength
      0x21,                         // bDescriptorType
      0x00, 0x01, 0x01, 0x25,       // ???
      0x81,                         // bEndpointAddress (IN, 1)
      0x14,                         // bMaxDataSize
      0x00, 0x00, 0x00, 0x00, 0x13, // ???
      0x01,                         // bEndpointAddress (OUT, 1)
      0x08,                         // bMaxDataSize
      0x00, 0x00,                   // ???
      // Endpoint 1: Control Surface Send
      0x07,       // bLength
      0x05,       // bDescriptorType (ENDPOINT)
      0x81,       // bEndpointAddress (IN, 1)
      0x03,       // bmAttributes
      0x20, 0x00, // wMaxPacketSize
      0x04,       // bInterval
      // Endpoint 1: Control Surface Receive
      0x07,       // bLength
      0x05,       // bDescriptorType (ENDPOINT)
      0x01,       // bEndpointAddress (OUT, 1)
      0x03,       // bmAttributes
      0x20, 0x00, // wMaxPacketSize
      0x08,       // bInterval
      /* ---------------------------------------------------- */
      // Interface 1: Headset (and Expansion Port?)
      0x09, // bLength
      0x04, // bDescriptorType (INTERFACE)
      0x01, // bInterfaceNumber
      0x00, // bAlternateSetting
      0x04, // bNumEndpoints
      0xFF, // bInterfaceClass
      0x5D, // bInterfaceSubClass
      0x03, // bInterfaceProtocol
      0x00, // iInterface
      // Unknown Descriptor (If1)
      0x1B,                               // bLength
      0x21,                               // bDescriptorType
      0x00, 0x01, 0x01, 0x01,             // ???
      0x82,                               // bEndpointAddress (IN, 2)
      0x40,                               // bMaxDataSize
      0x01,                               // ???
      0x02,                               // bEndpointAddress (OUT, 2)
      0x20,                               // bMaxDataSize
      0x16,                               // ???
      0x83,                               // bEndpointAddress (IN, 3)
      0x00,                               // bMaxDataSize
      0x00, 0x00, 0x00, 0x00, 0x00, 0x16, // ???
      0x03,                               // bEndpointAddress (OUT, 3)
      0x00,                               // bMaxDataSize
      0x00, 0x00, 0x00, 0x00, 0x00,       // ???
      // Endpoint 2: Microphone Data Send
      0x07,       // bLength
      0x05,       // bDescriptorType (ENDPOINT)
      0x82,       // bEndpointAddress (IN, 2)
      0x03,       // bmAttributes
      0x20, 0x00, // wMaxPacketSize
      0x02,       // bInterval
      // Endpoint 2: Headset Audio Receive
      0x07,       // bLength
      0x05,       // bDescriptorType (ENDPOINT)
      0x02,       // bEndpointAddress (OUT, 2)
      0x03,       // bmAttributes
      0x20, 0x00, // wMaxPacketSize
      0x04,       // bInterval
      // Endpoint 3: Unknown, Send
      0x07,       // bLength
      0x05,       // bDescriptorType (ENDPOINT)
      0x83,       // bEndpointAddress (IN, 3)
      0x03,       // bmAttributes
      0x20, 0x00, // wMaxPacketSize
      0x40,       // bInterval
      // Endpoint 3: Unknown, Receive
      0x07,       // bLength
      0x05,       // bDescriptorType (ENDPOINT)
      0x03,       // bEndpointAddress (OUT, 3)
      0x03,       // bmAttributes
      0x20, 0x00, // wMaxPacketSize
      0x10,       // bInterval
      /* ---------------------------------------------------- */
      // Interface 2: Unknown
      0x09, // bLength
      0x04, // bDescriptorType (INTERFACE)
      0x02, // bInterfaceNumber
      0x00, // bAlternateSetting
      0x01, // bNumEndpoints
      0xFF, // bInterfaceClass
      0x5D, // bInterfaceSubClass
      0x02, // bInterfaceProtocol
      0x00, // iInterface
      // Unknown Descriptor (If2)
      0x09,                   // bLength
      0x21,                   // bDescriptorType
      0x00, 0x01, 0x01, 0x22, // ???
      0x84,                   // bEndpointAddress (IN, 4)
      0x07,                   // bMaxDataSize
      0x00,                   // ???
      // Endpoint 4: Unknown, Send
      0x07,       // bLength
      0x05,       // bDescriptorType (ENDPOINT)
      0x84,       // bEndpointAddress (IN, 4)
      0x03,       // bmAttributes
      0x20, 0x00, // wMaxPacketSize
      0x10,       // bInterval
      /* ---------------------------------------------------- */
      // Interface 3: Security Method
      0x09, // bLength
      0x04, // bDescriptorType (INTERFACE)
      0x03, // bInterfaceNumber
      0x00, // bAlternateSetting
      0x00, // bNumEndpoints
      0xFF, // bInterfaceClass
      0xFD, // bInterfaceSubClass
      0x13, // bInterfaceProtocol
      0x04, // iInterface
      // Unknown Descriptor (If3)
      0x06,                   // bLength
      0x41,                   // bDescriptorType
      0x00, 0x01, 0x01, 0x03, // ???
};



在usb_req_class.c中添加测试数据

BYTE test[] = {0x00, 0x14,
               0x0f, // 第一组按键RL   SE   ST   RI   LE   DO   UP
               0xf0, // 第二组按键YX   B    A    NOPME   RB   LB
               0xff, // LT
               0xff, // RT
               0xff, // LX   双字
               0xff, // LX2
               0x00, // LY
               0x00, // LY2
               0xff, // RX
               0xff, // RX2
               0x78, // RY
               0x00, // RY2
               0x00, 0x00, 0x00, 0x00, 0x00, 0x00};和手柄按键/轴 有关的 是2~13 字节
已经写了注释

修改原程序扫描键码后发送数据的 函数void usb_class_in()


void usb_class_in()
{
    BYTE button;
    BYTE i;

    if (DeviceState != DEVSTATE_CONFIGURED)
      return;

    if (!UsbInBusy && fKeyOK) {
      fKeyOK = 0;

      button = 0;
      button = 0;
      button = 0;

      switch (bKeyCode) {
            case 0xfe:
                button = 0x01;
                break;
            case 0xfd:
                button = 0x04;
                break;
            case 0xfb:
                button = 0x02;
                break;
            case 0xef:
                button = 0xfc;
                break;
            case 0xdf:
                button = 0x04;
                break;
            case 0xbf:
                button = 0xfc;
                break;
            case 0x7f:
                button = 0x04;
                break;
      }

      IE2 &= ~0x80; // EUSB = 0;
      UsbInBusy = 1;
      usb_write_reg(INDEX, 1);
      // for (i = 0; i < 3; i++) {
      //   // usb_write_reg(FIFO1, button);
      //   //usb_write_fifo(FIFO1, test7, 7);
      // }

      usb_write_fifo(FIFO1, test, 20);

      usb_write_reg(INCSR1, INIPRDY);

      IE2 |= 0x80; // EUSB = 1;
    }
}测试效果



按下试验箱矩阵键盘任意键
可以看到 ABXY 四个按键被成功按下
证明通信正常

第一步就先到这里,后面再去修改矩阵键盘的扫描,让他实现不同的功能



沈洁 发表于 2023-9-4 09:35:43

强烈支持原创

gentleman 发表于 2023-9-4 11:23:24

沈洁 发表于 2023-9-4 09:35
强烈支持原创

{:4_188:}水平有限,抛砖引玉。

沈洁 发表于 2023-9-4 14:35:54

gentleman 发表于 2023-9-4 11:23
水平有限,抛砖引玉。

这么好的帖子怎么能不顶上去呢?

rayrakey 发表于 2023-9-19 16:43:56

楼主威武

gentleman 发表于 2023-9-19 18:46:20

rayrakey 发表于 2023-9-19 16:43
楼主威武

{:4_165:}
页: [1]
查看完整版本: USB-HID 手柄制作 (一)