mirror of
https://github.com/justinian/edmfd_firmware.git
synced 2025-12-10 08:44:31 -08:00
Get BOS/WinUSB set up
This commit is contained in:
@@ -3,7 +3,7 @@
|
|||||||
#include "blink.hh"
|
#include "blink.hh"
|
||||||
#include "hid.hh"
|
#include "hid.hh"
|
||||||
#include "usb_descriptors.hh"
|
#include "usb_descriptors.hh"
|
||||||
#include "hid/hid_device.h"
|
#include "class/hid/hid_device.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// TinyUSB Callbacks
|
// TinyUSB Callbacks
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#include "bsp/board_api.h"
|
#include "bsp/board_api.h"
|
||||||
#include "tusb.h"
|
#include "tusb.h"
|
||||||
|
|
||||||
#include "usb_descriptors.hh"
|
#include "usb_descriptors.hh"
|
||||||
|
|
||||||
|
|
||||||
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
||||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
||||||
*
|
*
|
||||||
@@ -13,7 +15,7 @@
|
|||||||
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
_PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
|
||||||
|
|
||||||
#define USB_VID 0x4a33 // J3 in ascii
|
#define USB_VID 0x4a33 // J3 in ascii
|
||||||
#define USB_BCD 0x0200
|
#define USB_BCD 0x0201
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// TinyUSB callbacks
|
// TinyUSB callbacks
|
||||||
@@ -21,6 +23,7 @@ extern "C" {
|
|||||||
uint8_t const * tud_hid_descriptor_report_cb(uint8_t);
|
uint8_t const * tud_hid_descriptor_report_cb(uint8_t);
|
||||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t);
|
uint8_t const * tud_descriptor_configuration_cb(uint8_t);
|
||||||
uint16_t const * tud_descriptor_string_cb(uint8_t, uint16_t);
|
uint16_t const * tud_descriptor_string_cb(uint8_t, uint16_t);
|
||||||
|
uint8_t const * tud_descriptor_bos_cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
@@ -71,22 +74,13 @@ uint8_t const * tud_hid_descriptor_report_cb(uint8_t) {
|
|||||||
// String Descriptors
|
// String Descriptors
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
enum class strings : uint8_t {
|
|
||||||
language_id,
|
|
||||||
manufacturer,
|
|
||||||
product,
|
|
||||||
serial,
|
|
||||||
interface,
|
|
||||||
_count
|
|
||||||
};
|
|
||||||
|
|
||||||
// array of pointer to string descriptors
|
// array of pointer to string descriptors
|
||||||
char16_t const *string_desc_arr[size_t(strings::_count)] = {
|
char16_t const *string_desc_arr[size_t(strings::_count)] = {
|
||||||
u"\u0409", // 0: is supported language is English (0x0409)
|
u"\u0409", // 0: is supported language is English (0x0409)
|
||||||
u"j3gaming", // 1: Manufacturer
|
u"j3gaming", // 1: Manufacturer
|
||||||
u"EDMFD", // 2: Product
|
u"EDMFD", // 2: Product
|
||||||
nullptr, // 3: Serials will use unique ID if possible
|
nullptr, // 3: Serials will use unique ID if possible
|
||||||
u"screen control", // 4: screen interface
|
u"EDMFD Screen", // 4: screen interface
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr size_t desc_len = 32;
|
static constexpr size_t desc_len = 32;
|
||||||
@@ -123,21 +117,18 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
|
|||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Configuration Descriptor
|
// Configuration Descriptor
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
static constexpr size_t config_total_len = TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_VENDOR_DESC_LEN;
|
static constexpr size_t config_total_len = TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_VENDOR_DESC_LEN;
|
||||||
enum class interface : uint8_t { HID, vendor, _count };
|
|
||||||
enum class endpoint : uint8_t { HID = 0x81, vendor_out = 0x02, vendor_in = 0x82 };
|
|
||||||
|
|
||||||
uint8_t const desc_configuration[config_total_len] = {
|
uint8_t const desc_configuration[config_total_len] = {
|
||||||
// Config number, interface count, string index, total length, attribute, power in mA
|
// Config number, interface count, string index, total length, attribute, power in mA
|
||||||
TUD_CONFIG_DESCRIPTOR(1, uint8_t(interface::_count), 0, config_total_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
TUD_CONFIG_DESCRIPTOR(1, uint8_t(interface::_count), 0, config_total_len, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||||
|
|
||||||
|
// Interface number, string index, EP Out & IN address, EP size
|
||||||
|
TUD_VENDOR_DESCRIPTOR(uint8_t(interface::vendor), uint8_t(strings::interface), uint8_t(endpoint::vendor_out), uint8_t(endpoint::vendor_in), 64),
|
||||||
|
|
||||||
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
|
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
|
||||||
TUD_HID_DESCRIPTOR(uint8_t(interface::HID), 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), uint8_t(endpoint::HID), CFG_TUD_HID_EP_BUFSIZE, 5),
|
TUD_HID_DESCRIPTOR(uint8_t(interface::HID), 0, HID_ITF_PROTOCOL_NONE, sizeof(desc_hid_report), uint8_t(endpoint::HID), CFG_TUD_HID_EP_BUFSIZE, 5),
|
||||||
|
|
||||||
// Interface number, string index, EP Out & IN address, EP size
|
|
||||||
TUD_VENDOR_DESCRIPTOR(uint8_t(interface::vendor), uint8_t(strings::interface), uint8_t(endpoint::vendor_out), uint8_t(endpoint::vendor_in), 64)
|
|
||||||
|
|
||||||
// CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
// CDC: Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||||
//TUD_CDC_DESCRIPTOR(uint8_t(interface::CDC), 4, uint8_t(endpoint::CDCnotify), 8, uint8_t(endpoint::CDCout), uint8_t(endpoint::CDCin), 64)
|
//TUD_CDC_DESCRIPTOR(uint8_t(interface::CDC), 4, uint8_t(endpoint::CDCnotify), 8, uint8_t(endpoint::CDCout), uint8_t(endpoint::CDCin), 64)
|
||||||
};
|
};
|
||||||
@@ -152,3 +143,66 @@ uint8_t const * tud_descriptor_configuration_cb(uint8_t index) {
|
|||||||
// This example use the same configuration for both high and full speed mode
|
// This example use the same configuration for both high and full speed mode
|
||||||
return desc_configuration;
|
return desc_configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// BOS Descriptor
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
static constexpr uint8_t bos_total_len = (TUD_BOS_DESC_LEN + TUD_BOS_MICROSOFT_OS_DESC_LEN);
|
||||||
|
|
||||||
|
uint8_t const desc_bos[] = {
|
||||||
|
// total length, number of device caps
|
||||||
|
TUD_BOS_DESCRIPTOR(bos_total_len, 1),
|
||||||
|
|
||||||
|
// Microsoft OS 2.0 descriptor
|
||||||
|
TUD_BOS_MS_OS_20_DESCRIPTOR(ms_os_20_desc_len, uint8_t(vendor_req::microsoft)),
|
||||||
|
};
|
||||||
|
static_assert(sizeof(desc_bos) == bos_total_len, "Incorrect BOS length");
|
||||||
|
|
||||||
|
uint8_t const * tud_descriptor_bos_cb() { return desc_bos; }
|
||||||
|
|
||||||
|
uint8_t const desc_ms_os_20[ms_os_20_desc_len] = {
|
||||||
|
// Set header
|
||||||
|
U16_TO_U8S_LE(0x000A), // length
|
||||||
|
U16_TO_U8S_LE(MS_OS_20_SET_HEADER_DESCRIPTOR), // type
|
||||||
|
U32_TO_U8S_LE(0x06030000), // windows version
|
||||||
|
U16_TO_U8S_LE(ms_os_20_desc_len), // total length
|
||||||
|
|
||||||
|
// Configuration subset header
|
||||||
|
U16_TO_U8S_LE(0x0008), // length
|
||||||
|
U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_CONFIGURATION), // type
|
||||||
|
0, // configuration index
|
||||||
|
0, // reserved
|
||||||
|
U16_TO_U8S_LE(ms_os_20_desc_len-0x0A), // configuration total length
|
||||||
|
|
||||||
|
// Function Subset header: length, type, first interface, reserved, subset length
|
||||||
|
U16_TO_U8S_LE(0x0008), // length
|
||||||
|
U16_TO_U8S_LE(MS_OS_20_SUBSET_HEADER_FUNCTION), // type
|
||||||
|
uint8_t(interface::vendor), // first interface
|
||||||
|
0, // reserved
|
||||||
|
U16_TO_U8S_LE(ms_os_20_desc_len-0x0A-0x08), // subset total length
|
||||||
|
|
||||||
|
// MS OS 2.0 Compatible ID descriptor
|
||||||
|
U16_TO_U8S_LE(0x0014), // length
|
||||||
|
U16_TO_U8S_LE(MS_OS_20_FEATURE_COMPATBLE_ID), // type
|
||||||
|
'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00, // compatible ID
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // sub-compatible
|
||||||
|
|
||||||
|
// MS OS 2.0 Registry property descriptor: length, type
|
||||||
|
U16_TO_U8S_LE(ms_os_20_desc_len-0x0A-0x08-0x08-0x14), // length
|
||||||
|
U16_TO_U8S_LE(MS_OS_20_FEATURE_REG_PROPERTY), // type
|
||||||
|
U16_TO_U8S_LE(0x0007), // wPropertyDataType
|
||||||
|
|
||||||
|
U16_TO_U8S_LE(0x002A), // wPropertyNameLength and PropertyName "DeviceInterfaceGUIDs\0" in UTF-16
|
||||||
|
'D', 0x00, 'e', 0x00, 'v', 0x00, 'i', 0x00, 'c', 0x00, 'e', 0x00, 'I', 0x00, 'n', 0x00, 't', 0x00, 'e', 0x00,
|
||||||
|
'r', 0x00, 'f', 0x00, 'a', 0x00, 'c', 0x00, 'e', 0x00, 'G', 0x00, 'U', 0x00, 'I', 0x00, 'D', 0x00, 's', 0x00, 0x00, 0x00,
|
||||||
|
|
||||||
|
U16_TO_U8S_LE(0x0050), // wPropertyDataLength and bPropertyData: “{4b028455-9b3c-4cf4-8992-3c4c40b76d96}\0”.
|
||||||
|
'{', 0x00, '4', 0x00, 'B', 0x00, '0', 0x00, '2', 0x00, '8', 0x00, '4', 0x00, '5', 0x00, '5', 0x00, '-', 0x00,
|
||||||
|
'9', 0x00, 'B', 0x00, '3', 0x00, 'C', 0x00, '-', 0x00, '4', 0x00, 'C', 0x00, 'F', 0x00, '4', 0x00, '-', 0x00,
|
||||||
|
'8', 0x00, '9', 0x00, '9', 0x00, '2', 0x00, '-', 0x00, '3', 0x00, 'C', 0x00, '4', 0x00, 'C', 0x00, '4', 0x00,
|
||||||
|
'0', 0x00, 'B', 0x00, '7', 0x00, '6', 0x00, 'D', 0x00, '9', 0x00, '6', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(desc_ms_os_20) == ms_os_20_desc_len, "Incorrect MS OS Desc size");
|
||||||
|
|
||||||
|
|||||||
@@ -4,3 +4,23 @@ enum class descriptor {
|
|||||||
gamepad = 1,
|
gamepad = 1,
|
||||||
_count
|
_count
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class strings : uint8_t {
|
||||||
|
language_id,
|
||||||
|
manufacturer,
|
||||||
|
product,
|
||||||
|
serial,
|
||||||
|
interface,
|
||||||
|
_count
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class interface : uint8_t { vendor, HID, _count };
|
||||||
|
enum class endpoint : uint8_t { HID = 0x81, vendor_out = 0x02, vendor_in = 0x82 };
|
||||||
|
|
||||||
|
enum class vendor_req : uint8_t {
|
||||||
|
microsoft = 1,
|
||||||
|
edmfd
|
||||||
|
};
|
||||||
|
|
||||||
|
extern uint8_t const desc_ms_os_20[];
|
||||||
|
static constexpr size_t ms_os_20_desc_len = 0xb2;
|
||||||
@@ -1,13 +1,33 @@
|
|||||||
#include "bsp/board_api.h"
|
#include "bsp/board_api.h"
|
||||||
#include "vendor/vendor_device.h"
|
#include "class/vendor/vendor_device.h"
|
||||||
|
|
||||||
#include "blink.hh"
|
#include "blink.hh"
|
||||||
|
#include "usb_descriptors.hh"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
// TinyUSB callbacks
|
// TinyUSB callbacks
|
||||||
|
bool tud_Ivendor_control_xfer_cb(uint8_t, uint8_t, tusb_control_request_t const*);
|
||||||
void tud_vendor_rx_cb(uint8_t, uint8_t const*, uint16_t);
|
void tud_vendor_rx_cb(uint8_t, uint8_t const*, uint16_t);
|
||||||
void tud_vendor_tx_cb(uint8_t, uint32_t);
|
void tud_vendor_tx_cb(uint8_t, uint32_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const* request) {
|
||||||
|
// nothing to with DATA & ACK stage
|
||||||
|
if (stage != CONTROL_STAGE_SETUP) return true;
|
||||||
|
|
||||||
|
if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_VENDOR &&
|
||||||
|
vendor_req(request->bRequest) == vendor_req::microsoft &&
|
||||||
|
request->wIndex == 7) {
|
||||||
|
|
||||||
|
// Get Microsoft OS 2.0 compatible descriptor
|
||||||
|
return tud_control_xfer(rhport, request, const_cast<void*>(static_cast<const void*>(desc_ms_os_20)), ms_os_20_desc_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// stall unknown request
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Invoked when received new data
|
// Invoked when received new data
|
||||||
void tud_vendor_rx_cb(uint8_t, uint8_t const* buffer, uint16_t bufsize) {
|
void tud_vendor_rx_cb(uint8_t, uint8_t const* buffer, uint16_t bufsize) {
|
||||||
tud_vendor_write(buffer, bufsize);
|
tud_vendor_write(buffer, bufsize);
|
||||||
|
|||||||
Reference in New Issue
Block a user