usb_desc_dump: build form arduino ino file

This commit is contained in:
tmk 2021-07-20 22:48:48 +09:00
parent cf8712fda7
commit 44ee4f3fcd
6 changed files with 1358 additions and 1516 deletions

View file

@ -1,7 +1,8 @@
TARGET ?= usb_desc_dump
TMK_DIR ?= ../../tmk_core
TARGET_DIR ?= .
SRC ?= desc_dump.cpp
SRC ?= ino.cpp
CONFIG_H ?= config.h
# MCU name
@ -24,15 +25,13 @@ 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
NO_KEYBOARD ?= yes # No keyboard interface
# 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
EXTRACPPFLAGS = -fpermissive
# program Leonardo
PROGRAM_CMD = avrdude -p$(MCU) -cavr109 -b57600 -Uflash:w:$(TARGET).hex -P$(DEV)
@ -41,7 +40,49 @@ PROGRAM_CMD = avrdude -p$(MCU) -cavr109 -b57600 -Uflash:w:$(TARGET).hex -P$(DEV)
VPATH += $(TARGET_DIR)
VPATH += $(TMK_DIR)
#
# USB_desc_dump build setting
#
include $(TMK_DIR)/protocol/usb_hid.mk
USB_DESC_DUMP_DIR = $(USB_HOST_SHIELD_DIR)/examples/USB_desc_dump
SRC += $(USB_DESC_DUMP_DIR)/USB_desc_dump.cpp
SRC += $(USB_HOST_SHIELD_DIR)/hidescriptorparser.cpp
# Print Standard descriptor
OPT_DEFS += -DPRINT_DESC
#OPT_DEFS += -DNO_PRINT_DESC
# Print High-speed Hub descriptor
#OPT_DEFS += -DPRINT_DESC_HSHUB
OPT_DEFS += -DNO_PRINT_DESC_HSHUB
# Print HID Report descriptor
#OPT_DEFS += -DPRINT_DESC_REPORT
OPT_DEFS += -DNO_PRINT_DESC_REPORT
include $(TMK_DIR)/protocol/lufa.mk
include $(TMK_DIR)/common.mk
include $(TMK_DIR)/rules.mk
$(OBJDIR)/$(USB_DESC_DUMP_DIR)/USB_desc_dump.cpp.o : $(OBJDIR)/$(USB_DESC_DUMP_DIR)/USB_desc_dump.cpp $(OBJDIR)/$(USB_DESC_DUMP_DIR)/desc.h
@echo
mkdir -p $(@D)
@echo $(MSG_COMPILING_CPP) $<
$(CC) -c $(ALL_CPPFLAGS) $< -o $@
$(OBJDIR)/$(USB_DESC_DUMP_DIR)/USB_desc_dump.cpp : $(TMK_DIR)/$(USB_DESC_DUMP_DIR)/USB_desc_dump.ino
@echo
mkdir -p $(@D)
$(COPY) $< $@
$(OBJDIR)/$(USB_DESC_DUMP_DIR)/desc.h : $(TMK_DIR)/$(USB_DESC_DUMP_DIR)/desc.h
@echo
mkdir -p $(@D)
$(COPY) $< $@

View file

@ -1,10 +1,10 @@
USB Descriptor Dumper
=====================
2021-07-08
2021-07-20
`usb_desc_dump` read USB descriptors and shows in HEX dump.
`Usb_desc_dump` gets USB descriptors and shows in HEX dump and human readable form.
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.
@ -15,6 +15,15 @@ Following descriptors are supported.
- HID Descriptor
- HID Report descriptor
- String Descriptor
- Device Qualifier*
- Other Speed*
- Audio/MIDI Class*
*: partly supported
See source code for the detail.
- https://github.com/tmk/USB_Host_Shield_2.0/tree/master/examples/USB_desc_dump
@ -23,35 +32,91 @@ Example optput:
```
usb_state: 90
Address:01
lowspeed:01
idVendor:046A
idProduct:0011
//////////////////////////////////////////////////////////////////////
// USB_desc_dump
// Address: 01
// Lowspeed: 00
Device Descriptor:
// Devicer dump:
12 01 00 02 00 00 00 08 6A 04 11 00 00 01 00 00
00 01
Config0: len:0022
// Device:
bLength: 12
bDescriptorType: 01
bcdUSB: 0200
bDeviceClass: 00
bDeviceSubClass: 00
bDeviceProtocol: 00
bMaxPacketSize0: 08
idVendor: 046A
idProduct: 0011
bcdDevice: 0100
iManufacturer: 00
iProduct: 00
iSerialNumber: 00
bNumConfigurations: 01
// Config0 dump: 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
// Config:
bLength: 09
bDescriptorType: 02
wTotalLength: 0022
bNumInterfaces: 01
bConfigurationValue: 01
iConfiguration: 00
bmAttributes: A0
bMaxPower: 32
// Interface0.0:
bLength: 09
bDescriptorType: 04
bInterfaceNumber: 00
bAlternateSetting: 00
bNumEndpoints: 01
bInterfaceClass: 03
bInterfaceSubClass: 01
bInterfaceProtocol: 01
iInterface: 00
// HID:
bLength: 09
bDescriptorType: 21
bcdHID: 0111
bCountryCode: 00
bNumDescriptors: 01
bDescrType: 22
wDescriptorLength: 0040
// Report0 dump: 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
// Endpoint:
bLength: 07
bDescriptorType: 05
bEndpointAddress: 81
bmAttributes: 03
wMaxPacketSize: 0008
bInterval: 0A
// Parse data here: http://eleccelerator.com/usbdescreqparser/
```
To check descriptor content use 'USB Descriptor and Request Parser' on line.
To inspect descriptor content closely use 'USB Descriptor and Request Parser' on line.
- https://eleccelerator.com/usbdescreqparser/
Or you can use command line tool like hidrd.
Also you can use command line tool `hidrd-convert` like below.
- https://github.com/DIGImend/hidrd
@ -61,6 +126,8 @@ $ cat | hidrd-convert -i hex -o spec
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
^D
Usage Page (Desktop), ; Generic desktop controls (01h)
Usage (Keyboard), ; Keyboard (06h, application collection)
Collection (Application),

File diff suppressed because it is too large Load diff

View file

@ -1,340 +0,0 @@
/*
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"
#define AUDIO_CLASS_INTERFACE 0x24
#define AUDIO_CLASS_ENDPOINT 0x25
USB Usb;
USBHub hub1(&Usb);
#define BUF_SIZE 512
uint8_t buf[BUF_SIZE];
uint16_t langid = 0;
EpInfo epInfo[1];
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, bool commented = false)
{
for (int i = 0; i < len; i++) {
if (i % 16)
print(" ");
else {
if (i != 0) print("\r\n");
if (commented) print("// ");
}
xprintf("%02X ", buf[i]);
}
print("\r\n");
}
class dumpCallback : public USBReadParser {
public:
void Parse(const uint16_t len, const uint8_t *pbuf, const uint16_t &offset) {
for (int i = 0; i < len; i++) {
if ((offset + i) % 16)
print(" ");
else {
if ((offset + i) != 0) print("\r\n");
}
printHEX(pbuf[i]);
}
}
} dumper;
void printStringDescriptor(UsbDevice *pdev, uint8_t index, uint16_t langid)
{
uint8_t sbuf[256];
uint8_t rcode, len;
if (index == 0) return;
rcode = Usb.getStrDescr(pdev->address.devAddress, 0, 1, index, langid, sbuf);
if (rcode) { printError(rcode); return; }
len = (sbuf[0] > sizeof(sbuf) ? sizeof(sbuf) : sbuf[0]);
rcode = Usb.getStrDescr(pdev->address.devAddress, 0, len, index, langid, sbuf);
if (rcode) { printError(rcode); return; }
xprintf("String%d: ", index);
for (uint8_t i = 2; (i + 1) < len; i += 2) {
if (sbuf[i + 1] != 0) continue;
//xputc(sbuf[i + 1]);
xputc(sbuf[i]);
}
print("\r\n");
dumpBuf(sbuf[0], sbuf, true);
}
uint8_t dumpReportDesc(UsbDevice *pdev, uint16_t iface, uint16_t len)
{
uint8_t rbuf[64];
uint8_t rcode = 0;
rcode = Usb.ctrlReq(pdev->address.devAddress, 0x00, bmREQ_HID_REPORT, USB_REQUEST_GET_DESCRIPTOR, 0x00,
HID_DESCRIPTOR_REPORT, iface, len, sizeof(rbuf), rbuf, &dumper);
print("\r\n");
if (rcode) { printError(rcode); }
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;
// String Descriptor
if (pI->iInterface) {
print("\r\n// iInterface: ");
printStringDescriptor(pdev, pI->iInterface, langid);
}
break;
}
case HID_DESCRIPTOR_HID: {
USB_HID_DESCRIPTOR *pH = (USB_HID_DESCRIPTOR *)pB;
xprintf("\r\n// Report%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;
}
case USB_DESCRIPTOR_DEBUG:
case USB_DESCRIPTOR_INTERFACE_ASSOCIATION:
case USB_DESCRIPTOR_BOS:
case USB_DESCRIPTOR_DEVICE_CAPABILITY:
case USB_DESCRIPTOR_SS_USB_EP_COMPANION:
case USB_DESCRIPTOR_SSP_ISO_EP_COMPANION:
// Class specific
case AUDIO_CLASS_INTERFACE:
case AUDIO_CLASS_ENDPOINT:
break;
default:
printVal("// Unknown Desc Type:", *(pB+1));
break;
}
pB += *pB;
}
}
uint8_t dumpConfigDesc(UsbDevice *pdev, uint8_t numConf)
{
uint8_t rcode = 0;
for (uint8_t i = 0; i < numConf; i++) {
xprintf("\r\n// Config%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;
printVal(" len", pC->wTotalLength);
uint16_t conf_len = (pC->wTotalLength < BUF_SIZE ? pC->wTotalLength : BUF_SIZE);
rcode = Usb.getConfDescr(pdev->address.devAddress, 0, conf_len, i, buf);
if (rcode) return rcode;
dumpBuf(conf_len, buf);
if (pC->wTotalLength > BUF_SIZE) println("Buffer is not enough!");
// String Descriptor
if (pC->iConfiguration) {
print("\r\n// iConfiguration: ");
printStringDescriptor(pdev, pC->iConfiguration, langid);
}
// Set Configuration
Usb.setConf(pdev->address.devAddress, 0, pC->bConfigurationValue);
scanConfigDesc(pdev, conf_len, buf);
}
return rcode;
}
void dumpDescriptors(UsbDevice *pdev)
{
uint8_t rcode = 0;
xprintf("\r\n// Address:%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);
// set maxpacketsize0
epInfo[0].epAddr = 0;
epInfo[0].maxPktSize = pD->bMaxPacketSize0;
epInfo[0].bmNakPower = USB_NAK_MAX_POWER;
UsbDevice *p = Usb.GetAddressPool().GetUsbDevicePtr(pdev->address.devAddress);
p->epinfo = epInfo;
// String Descriptor
if (pD->iManufacturer || pD->iProduct || pD->iSerialNumber) {
uint8_t sbuf[4];
rcode = Usb.getStrDescr(pdev->address.devAddress, 0, 4, 0, 0, sbuf);
if (rcode == 0) {
langid = (sbuf[3] << 8) | sbuf[2];
printVal("// langid", langid);
println("\r\n// String0:");
dumpBuf(sbuf[0], sbuf, true);
}
}
if (pD->iManufacturer) {
print("\r\n// iManufacturer: ");
printStringDescriptor(pdev, pD->iManufacturer, langid);
}
if (pD->iProduct) {
print("\r\n// iProduct: ");
printStringDescriptor(pdev, pD->iProduct, langid);
}
if (pD->iSerialNumber) {
print("\r\n// iSerialNumber: ");
printStringDescriptor(pdev, pD->iSerialNumber, langid);
}
print("\r\n// Device 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);
println("\r\n// Parse data here: http://eleccelerator.com/usbdescreqparser/");
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};

View file

@ -0,0 +1,37 @@
/*
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.
*/
#include "Arduino.h"
#include "hook.h"
void hook_early_init(void) {
// arduino
setup();
}
void hook_late_init(void) {
}
void hook_main_loop(void) {
// arduino
loop();
}

@ -1 +1 @@
Subproject commit b6128f252700a8dd2d12400c55680ef67cdcac86
Subproject commit 96112d43858b5c5327565c36bd8ea2192ec77d1b