Add usb_desc_dump project
This commit is contained in:
parent
d14a00c44e
commit
ec2652ee9a
5 changed files with 1492 additions and 0 deletions
47
converter/usb_desc_dump/Makefile
Normal file
47
converter/usb_desc_dump/Makefile
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
TARGET ?= usb_desc_dump
|
||||
TMK_DIR ?= ../../tmk_core
|
||||
TARGET_DIR ?= .
|
||||
SRC ?= desc_dump.cpp
|
||||
CONFIG_H ?= config.h
|
||||
|
||||
# MCU name
|
||||
MCU ?= atmega32u4
|
||||
# Processor frequency.
|
||||
F_CPU ?= 16000000
|
||||
|
||||
#
|
||||
# LUFA specific
|
||||
#
|
||||
ARCH ?= AVR8
|
||||
F_USB ?= $(F_CPU)
|
||||
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT
|
||||
|
||||
#
|
||||
# Build Options
|
||||
#
|
||||
MOUSEKEY_ENABLE ?= no # Mouse keys
|
||||
EXTRAKEY_ENABLE ?= no # Media control and System control
|
||||
CONSOLE_ENABLE ?= yes # Console for debug
|
||||
COMMAND_ENABLE ?= no # Commands for debug and configuration
|
||||
NKRO_ENABLE ?= no # USB Nkey Rollover
|
||||
|
||||
# Boot Section Size in bytes
|
||||
OPT_DEFS += -DBOOTLOADER_SIZE=4096
|
||||
OPT_DEFS += -DNO_ACTION_TAPPING
|
||||
OPT_DEFS += -DNO_ACTION_LAYER
|
||||
OPT_DEFS += -DNO_ACTION_MACRO
|
||||
OPT_DEFS += -DNO_DEBUG
|
||||
|
||||
#LDFLAGS += -Wl,--relax
|
||||
|
||||
# program Leonardo
|
||||
PROGRAM_CMD = avrdude -p$(MCU) -cavr109 -b57600 -Uflash:w:$(TARGET).hex -P$(DEV)
|
||||
|
||||
# Search Path
|
||||
VPATH += $(TARGET_DIR)
|
||||
VPATH += $(TMK_DIR)
|
||||
|
||||
include $(TMK_DIR)/protocol/usb_hid.mk
|
||||
include $(TMK_DIR)/protocol/lufa.mk
|
||||
include $(TMK_DIR)/common.mk
|
||||
include $(TMK_DIR)/rules.mk
|
||||
91
converter/usb_desc_dump/README.md
Normal file
91
converter/usb_desc_dump/README.md
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
USB Descriptor Dumper
|
||||
=====================
|
||||
2021-06-30
|
||||
|
||||
`usb_desc_dump` read USB descriptors and shows in HEX dump.
|
||||
This works on TMK USB-USB converter and USB Host Shield with Arduino Leonardo.
|
||||
USB hub is not supported. Device should be plugged directly.
|
||||
|
||||
Following descriptors are supported.
|
||||
|
||||
- Device Descriptor
|
||||
- Configuration Descriptor
|
||||
- Interface Descriptor
|
||||
- Endpoint Descriptor
|
||||
- HID Descriptor
|
||||
- HID Report descriptor
|
||||
|
||||
|
||||
|
||||
Example optput:
|
||||
|
||||
usb_state: 90
|
||||
|
||||
Address:01
|
||||
lowspeed:01
|
||||
idVendor:046A
|
||||
idProduct:0011
|
||||
|
||||
Device Descriptor:
|
||||
12 01 00 02 00 00 00 08 6A 04 11 00 00 01 00 00
|
||||
00 01
|
||||
|
||||
Config0: len:0022
|
||||
09 02 22 00 01 01 00 A0 32 09 04 00 00 01 03 01
|
||||
01 00 09 21 11 01 00 01 22 40 00 07 05 81 03 08
|
||||
00 0A
|
||||
|
||||
Report0: len:0040
|
||||
05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01
|
||||
75 01 95 08 81 02 95 01 75 08 81 01 95 03 75 01
|
||||
05 08 19 01 29 03 91 02 95 05 75 01 91 01 95 06
|
||||
75 08 15 00 26 DD 00 05 07 19 00 29 DD 81 00 C0
|
||||
|
||||
|
||||
|
||||
To check descriptor content use 'USB Descriptor and Request Parser' on line.
|
||||
|
||||
- https://eleccelerator.com/usbdescreqparser/
|
||||
|
||||
|
||||
Or you can use command line tool like hidrd.
|
||||
|
||||
- https://github.com/DIGImend/hidrd
|
||||
|
||||
$ cat | hidrd-convert -i hex -o spec
|
||||
05 01 09 06 A1 01 05 07 19 E0 29 E7 15 00 25 01
|
||||
75 01 95 08 81 02 95 01 75 08 81 01 95 03 75 01
|
||||
05 08 19 01 29 03 91 02 95 05 75 01 91 01 95 06
|
||||
75 08 15 00 26 DD 00 05 07 19 00 29 DD 81 00 C0
|
||||
Usage Page (Desktop), ; Generic desktop controls (01h)
|
||||
Usage (Keyboard), ; Keyboard (06h, application collection)
|
||||
Collection (Application),
|
||||
Usage Page (Keyboard), ; Keyboard/keypad (07h)
|
||||
Usage Minimum (KB Leftcontrol), ; Keyboard left control (E0h, dynamic value)
|
||||
Usage Maximum (KB Right GUI), ; Keyboard right GUI (E7h, dynamic value)
|
||||
Logical Minimum (0),
|
||||
Logical Maximum (1),
|
||||
Report Size (1),
|
||||
Report Count (8),
|
||||
Input (Variable),
|
||||
Report Count (1),
|
||||
Report Size (8),
|
||||
Input (Constant),
|
||||
Report Count (3),
|
||||
Report Size (1),
|
||||
Usage Page (LED), ; LEDs (08h)
|
||||
Usage Minimum (01h),
|
||||
Usage Maximum (03h),
|
||||
Output (Variable),
|
||||
Report Count (5),
|
||||
Report Size (1),
|
||||
Output (Constant),
|
||||
Report Count (6),
|
||||
Report Size (8),
|
||||
Logical Minimum (0),
|
||||
Logical Maximum (221),
|
||||
Usage Page (Keyboard), ; Keyboard/keypad (07h)
|
||||
Usage Minimum (None), ; No event (00h, selector)
|
||||
Usage Maximum (KP Hexadecimal), ; Keypad Hexadecimal (DDh, selector)
|
||||
Input,
|
||||
End Collection
|
||||
1072
converter/usb_desc_dump/binary/usb_desc_dump.hex
Normal file
1072
converter/usb_desc_dump/binary/usb_desc_dump.hex
Normal file
File diff suppressed because it is too large
Load diff
52
converter/usb_desc_dump/config.h
Normal file
52
converter/usb_desc_dump/config.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
Copyright 2012 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
|
||||
#define VENDOR_ID 0xFEED
|
||||
#define PRODUCT_ID 0x005B
|
||||
#define DEVICE_VER 0x0814
|
||||
#define MANUFACTURER TMK
|
||||
#define PRODUCT USB Descriptor Dumper
|
||||
|
||||
|
||||
#define DESCRIPTION Product from TMK keyboard firmware project
|
||||
|
||||
|
||||
/* matrix size */
|
||||
#define MATRIX_ROWS 0
|
||||
#define MATRIX_COLS 0
|
||||
|
||||
/* key combination for command */
|
||||
#define IS_COMMAND() (keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)))
|
||||
|
||||
|
||||
// Disable power saving in USB suspend loop but remote wakeup is still valid.
|
||||
// This allows keep USB::Task() going during suspend without power down time delay.
|
||||
//#define NO_SUSPEND_POWER_DOWN
|
||||
|
||||
|
||||
// Disable USB startup wait, which can delays starting UHS2 Task() for 350-600ms.
|
||||
//#define NO_USB_STARTUP_WAIT_LOOP
|
||||
|
||||
// Disable USB suspend loop, which blocks UHS2 Task() while power saving.
|
||||
// Note that this also disables power saving and remote wakeup from keyboard completely.
|
||||
//#define NO_USB_SUSPEND_LOOP
|
||||
|
||||
#endif
|
||||
230
converter/usb_desc_dump/desc_dump.cpp
Normal file
230
converter/usb_desc_dump/desc_dump.cpp
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
Copyright 2021 Jun Wako <wakojun@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
/*
|
||||
* USB Host Shield HID keyboards
|
||||
*/
|
||||
#include "Usb.h"
|
||||
#include "usbhub.h"
|
||||
#include "usbhid.h"
|
||||
|
||||
#include "timer.h"
|
||||
#include "matrix.h"
|
||||
#include "keymap.h"
|
||||
#include "hook.h"
|
||||
// This should be placed after Host Shield lib headers to override
|
||||
#include "print.h"
|
||||
|
||||
|
||||
USB Usb;
|
||||
USBHub hub1(&Usb);
|
||||
|
||||
|
||||
#define BUF_SIZE 256
|
||||
uint8_t buf[BUF_SIZE];
|
||||
|
||||
#define RBUF_SIZE 256
|
||||
uint8_t rbuf[RBUF_SIZE];
|
||||
|
||||
|
||||
void printHEX(uint8_t hex)
|
||||
{
|
||||
xprintf("%02X", hex);
|
||||
}
|
||||
|
||||
void printHEX(uint16_t hex)
|
||||
{
|
||||
xprintf("%02X", hex>>8);
|
||||
xprintf("%02X", hex);
|
||||
}
|
||||
|
||||
void printVal(const char* name, uint8_t hex)
|
||||
{
|
||||
xprintf("%s:%02X\r\n", name, hex);
|
||||
}
|
||||
|
||||
void printVal(const char* name, uint16_t hex)
|
||||
{
|
||||
xprintf("%s:%04X\r\n", name, hex);
|
||||
}
|
||||
|
||||
void printError(uint8_t rcode)
|
||||
{
|
||||
xprintf("\r\nERROR:%02X\r\n", rcode);
|
||||
}
|
||||
|
||||
void dumpBuf(int len, uint8_t* buf)
|
||||
{
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (i % 16)
|
||||
print(" ");
|
||||
else if (i != 0)
|
||||
print("\r\n");
|
||||
xprintf("%02X ", buf[i]);
|
||||
}
|
||||
print("\r\n");
|
||||
}
|
||||
|
||||
uint8_t dumpReportDesc(UsbDevice *pdev, uint16_t iface, uint16_t len)
|
||||
{
|
||||
uint8_t rcode = 0;
|
||||
Usb.ctrlReq(pdev->address.devAddress, 0x00, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
|
||||
HID_DESCRIPTOR_REPORT, iface, len, RBUF_SIZE, rbuf, NULL);
|
||||
if (rcode) return rcode;
|
||||
dumpBuf(len, rbuf);
|
||||
return rcode;
|
||||
}
|
||||
|
||||
void scanConfigDesc(UsbDevice *pdev, uint16_t tl, uint8_t* pB)
|
||||
{
|
||||
uint8_t iface = 0;
|
||||
while (pB < buf + tl) {
|
||||
switch (*(pB+1)) {
|
||||
case USB_DESCRIPTOR_DEVICE:
|
||||
break;
|
||||
case USB_DESCRIPTOR_CONFIGURATION:
|
||||
break;
|
||||
case USB_DESCRIPTOR_STRING:
|
||||
break;
|
||||
case USB_DESCRIPTOR_ENDPOINT:
|
||||
break;
|
||||
case USB_DESCRIPTOR_INTERFACE: {
|
||||
USB_INTERFACE_DESCRIPTOR *pI = (USB_INTERFACE_DESCRIPTOR *)pB;
|
||||
iface = pI->bInterfaceNumber;
|
||||
break;
|
||||
}
|
||||
case HID_DESCRIPTOR_HID: {
|
||||
USB_HID_DESCRIPTOR *pH = (USB_HID_DESCRIPTOR *)pB;
|
||||
xprintf("\r\nReport%d: len:%04X\r\n", iface, pH->wDescriptorLength);
|
||||
if (pH->bDescrType == HID_DESCRIPTOR_REPORT) {
|
||||
dumpReportDesc(pdev, iface, pH->wDescriptorLength);
|
||||
} else {
|
||||
printVal("Unknown HID Desc Type:", pH->bDescrType);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printVal("Unknown Desc Type:", *(pB+1));
|
||||
return;
|
||||
}
|
||||
pB += *pB;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dumpConfigDesc(UsbDevice *pdev, uint8_t numConf)
|
||||
{
|
||||
uint8_t rcode = 0;
|
||||
for (uint8_t i = 0; i < numConf; i++) {
|
||||
xprintf("\r\nConfig%d:", i);
|
||||
|
||||
rcode = Usb.getConfDescr(pdev->address.devAddress, 0, sizeof(USB_CONFIGURATION_DESCRIPTOR), i, buf);
|
||||
if (rcode) return rcode;
|
||||
USB_CONFIGURATION_DESCRIPTOR *pC = (USB_CONFIGURATION_DESCRIPTOR *)&buf;
|
||||
uint16_t tl = pC->wTotalLength;
|
||||
printVal(" len", tl);
|
||||
|
||||
rcode = Usb.getConfDescr(pdev->address.devAddress, 0, (tl < BUF_SIZE ? tl : BUF_SIZE), i, buf);
|
||||
if (rcode) return rcode;
|
||||
dumpBuf(tl, buf);
|
||||
|
||||
scanConfigDesc(pdev, tl, buf);
|
||||
}
|
||||
return rcode;
|
||||
}
|
||||
|
||||
void dumpDescriptors(UsbDevice *pdev)
|
||||
{
|
||||
uint8_t rcode = 0;
|
||||
|
||||
xprintf("\r\nAddress:%02X\r\n", pdev->address.devAddress);
|
||||
xprintf("lowspeed:%02X\r\n", pdev->lowspeed);
|
||||
|
||||
//
|
||||
// Device Descriptor
|
||||
//
|
||||
rcode = Usb.getDevDescr(pdev->address.devAddress, 0, sizeof(USB_DEVICE_DESCRIPTOR), buf);
|
||||
if (rcode) { printError(rcode); }
|
||||
USB_DEVICE_DESCRIPTOR *pD = (USB_DEVICE_DESCRIPTOR *)&buf;
|
||||
printVal("idVendor", pD->idVendor);
|
||||
printVal("idProduct", pD->idProduct);
|
||||
print("\r\nDevice Descriptor:\r\n");
|
||||
dumpBuf(sizeof(USB_DEVICE_DESCRIPTOR), buf);
|
||||
|
||||
|
||||
//
|
||||
// Configuration Descriptor
|
||||
//
|
||||
uint8_t numConf = pD->bNumConfigurations;
|
||||
rcode = dumpConfigDesc(pdev, numConf);
|
||||
if (rcode) { printError(rcode); }
|
||||
|
||||
Usb.GetAddressPool().FreeAddress(pdev->address.devAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
uint16_t timer;
|
||||
void matrix_init(void) {
|
||||
}
|
||||
|
||||
void hook_early_init(void) {
|
||||
Usb.Init();
|
||||
}
|
||||
|
||||
void hook_late_init(void) {
|
||||
timer = timer_read();
|
||||
}
|
||||
|
||||
uint8_t matrix_scan(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
void hook_keyboard_loop(void) {
|
||||
static bool waiting = true;
|
||||
static uint8_t usb_state = 0;
|
||||
|
||||
|
||||
Usb.Task();
|
||||
|
||||
if (usb_state != Usb.getUsbTaskState()) {
|
||||
usb_state = Usb.getUsbTaskState();
|
||||
xprintf("usb_state: %02X\n", usb_state);
|
||||
if (!waiting) waiting = true;
|
||||
}
|
||||
|
||||
// Wait for console startutp
|
||||
if (timer_elapsed(timer) < 3000) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Usb.getUsbTaskState() == USB_STATE_RUNNING && waiting) {
|
||||
Usb.ForEachUsbDevice(&dumpDescriptors);
|
||||
waiting = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Keymap unused
|
||||
const uint8_t keymaps[][MATRIX_ROWS][MATRIX_COLS] PROGMEM = {};
|
||||
const action_t fn_actions[] PROGMEM = {0};
|
||||
Loading…
Add table
Reference in a new issue