summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2019-09-03 14:44:46 -0400
committerDan Halbert <halbert@halwitz.org>2019-09-03 14:44:46 -0400
commit42f5edbd331b27c7096f57da2affd7561287c17f (patch)
treea7d86861f2b2e64ea673ec658f503eb8857d15e8
parent1d973a08038148ce20aaa43863721df6328318b7 (diff)
WIP
-rw-r--r--ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk3
-rw-r--r--ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk4
-rw-r--r--shared-module/usb_hid/Device.c4
-rw-r--r--shared-module/usb_hid/__init__.c18
-rw-r--r--supervisor/supervisor.mk10
-rw-r--r--tools/gen_usb_descriptor.py79
-rw-r--r--tools/hid_report_descriptors.py60
7 files changed, 156 insertions, 22 deletions
diff --git a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
index 3c43776f5..e62bec85f 100644
--- a/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/circuitplayground_express/mpconfigboard.mk
@@ -3,6 +3,9 @@ USB_VID = 0x239A
USB_PID = 0x8019
USB_PRODUCT = "CircuitPlayground Express"
USB_MANUFACTURER = "Adafruit Industries LLC"
+#USB_HID_DEVICES = KEYBOARD,XAC_COMPATIBLE_GAMEPAD
+USB_HID_DEVICES = XAC_COMPATIBLE_GAMEPAD
+
CHIP_VARIANT = SAMD21G18A
CHIP_FAMILY = samd21
diff --git a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
index b4a00b654..72fba7dd7 100644
--- a/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
+++ b/ports/atmel-samd/boards/trinket_m0/mpconfigboard.mk
@@ -1,12 +1,16 @@
LD_FILE = boards/samd21x18-bootloader.ld
USB_VID = 0x239A
USB_PID = 0x801F
+
+USB_HID_DEVICES=MOUSE,KEYBOARD,XAC_COMPATIBLE_GAMEPAD
+
USB_PRODUCT = "Trinket M0"
USB_MANUFACTURER = "Adafruit Industries LLC"
CHIP_VARIANT = SAMD21E18A
CHIP_FAMILY = samd21
+
INTERNAL_FLASH_FILESYSTEM = 1
LONGINT_IMPL = NONE
CIRCUITPY_SMALL_BUILD = 1
diff --git a/shared-module/usb_hid/Device.c b/shared-module/usb_hid/Device.c
index 26d70cb82..bed7d163f 100644
--- a/shared-module/usb_hid/Device.c
+++ b/shared-module/usb_hid/Device.c
@@ -48,9 +48,7 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t*
// Wait until interface is ready, timeout = 2 seconds
uint64_t end_ticks = ticks_ms + 2000;
while ( (ticks_ms < end_ticks) && !tud_hid_ready() ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP;
-#endif
+ RUN_BACKGROUND_TASKS;
}
if ( !tud_hid_ready() ) {
diff --git a/shared-module/usb_hid/__init__.c b/shared-module/usb_hid/__init__.c
index f14fdd41e..3ce26a1a1 100644
--- a/shared-module/usb_hid/__init__.c
+++ b/shared-module/usb_hid/__init__.c
@@ -53,6 +53,10 @@ static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL];
static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD];
#endif
+#ifdef USB_HID_REPORT_ID_XAC_COMPATIBLE_GAMEPAD
+static uint8_t xac_compatible_gamepad_report_buffer[USB_HID_REPORT_LENGTH_XAC_COMPATIBLE_GAMEPAD];
+#endif
+
#ifdef USB_HID_REPORT_ID_DIGITIZER
static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER];
#endif
@@ -113,6 +117,17 @@ usb_hid_device_obj_t usb_hid_devices[] = {
},
#endif
+#ifdef USB_HID_REPORT_ID_XAC_COMPATIBLE_GAMEPAD
+ {
+ .base = { .type = &usb_hid_device_type } ,
+ .report_buffer = xac_compatible_gamepad_report_buffer ,
+ .report_id = USB_HID_REPORT_ID_XAC_COMPATIBLE_GAMEPAD ,
+ .report_length = USB_HID_REPORT_LENGTH_XAC_COMPATIBLE_GAMEPAD ,
+ .usage_page = HID_USAGE_PAGE_DESKTOP ,
+ .usage = HID_USAGE_DESKTOP_GAMEPAD ,
+ },
+#endif
+
#ifdef USB_HID_REPORT_ID_DIGITIZER
{
.base = { .type = &usb_hid_device_type } ,
@@ -150,5 +165,8 @@ mp_obj_tuple_t common_hal_usb_hid_devices = {
#if USB_HID_NUM_DEVICES >= 6
(mp_obj_t) &usb_hid_devices[5],
#endif
+#if USB_HID_NUM_DEVICES >= 7
+#error "Too many USB HID devices"
+#endif
}
};
diff --git a/supervisor/supervisor.mk b/supervisor/supervisor.mk
index 2d50e7a8b..016188dfd 100644
--- a/supervisor/supervisor.mk
+++ b/supervisor/supervisor.mk
@@ -81,6 +81,14 @@ else
CFLAGS += -DUSB_AVAILABLE
endif
+ifndef USB_DEVICES
+USB_DEVICES = "CDC,MSC,AUDIO,HID"
+endif
+
+ifndef USB_HID_DEVICES
+USB_HID_DEVICES = "KEYBOARD,MOUSE,CONSUMER,GAMEPAD"
+endif
+
SUPERVISOR_O = $(addprefix $(BUILD)/, $(SRC_SUPERVISOR:.c=.o)) $(BUILD)/autogen_display_resources.o
$(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h
@@ -98,6 +106,8 @@ autogen_usb_descriptor.intermediate: ../../tools/gen_usb_descriptor.py Makefile
--vid $(USB_VID)\
--pid $(USB_PID)\
--serial_number_length $(USB_SERIAL_NUMBER_LENGTH)\
+ --devices $(USB_DEVICES) \
+ --hid_devices $(USB_HID_DEVICES) \
--output_c_file $(BUILD)/autogen_usb_descriptor.c\
--output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h
diff --git a/tools/gen_usb_descriptor.py b/tools/gen_usb_descriptor.py
index 10bbf5066..f782f9afc 100644
--- a/tools/gen_usb_descriptor.py
+++ b/tools/gen_usb_descriptor.py
@@ -8,6 +8,15 @@ sys.path.append("../../tools/usb_descriptor")
from adafruit_usb_descriptor import audio, audio10, cdc, hid, midi, msc, standard, util
import hid_report_descriptors
+ALL_DEVICES='CDC,MSC,AUDIO,HID'
+ALL_DEVICES_SET=frozenset(ALL_DEVICES.split(','))
+DEFAULT_DEVICES='CDC,MSC,AUDIO,HID'
+
+ALL_HID_DEVICES='KEYBOARD,MOUSE,CONSUMER,SYS_CONTROL,GAMEPAD,DIGITIZER,XAC_COMPATIBLE_GAMEPAD'
+ALL_HID_DEVICES_SET=frozenset(ALL_HID_DEVICES.split(','))
+# Digitizer works on Linux but conflicts with mouse, so omit it.
+DEFAULT_HID_DEVICES='KEYBOARD,MOUSE,CONSUMER,GAMEPAD'
+
parser = argparse.ArgumentParser(description='Generate USB descriptors.')
parser.add_argument('--manufacturer', type=str,
help='manufacturer of the device')
@@ -19,11 +28,24 @@ parser.add_argument('--pid', type=lambda x: int(x, 16),
help='product id')
parser.add_argument('--serial_number_length', type=int, default=32,
help='length needed for the serial number in digits')
+parser.add_argument('--devices', type=lambda l: frozenset(l.split(',')), default=DEFAULT_DEVICES,
+ help='devices to include in descriptor (AUDIO includes MIDI support)')
+parser.add_argument('--hid_devices', type=lambda l: frozenset(l.split(',')), default=DEFAULT_HID_DEVICES,
+ help='HID devices to include in HID report descriptor')
parser.add_argument('--output_c_file', type=argparse.FileType('w'), required=True)
parser.add_argument('--output_h_file', type=argparse.FileType('w'), required=True)
args = parser.parse_args()
+unknown_devices = list(args.devices - ALL_DEVICES_SET)
+if unknown_devices:
+ raise ValueError("Unknown device(s)", unknown_devices)
+
+unknown_hid_devices = list(args.hid_devices - ALL_HID_DEVICES_SET)
+if unknown_hid_devices:
+ raise ValueError("Unknown HID devices(s)", unknown_hid_devices)
+
+
class StringIndex:
"""Assign a monotonically increasing index to each unique string. Start with 0."""
string_to_index = {}
@@ -138,16 +160,27 @@ msc_interfaces = [
)
]
-# Include only these HID devices.
-# DIGITIZER works on Linux but conflicts with MOUSE, so leave it out for now.
-hid_devices = ("KEYBOARD", "MOUSE", "CONSUMER", "GAMEPAD")
-
-combined_hid_report_descriptor = hid.ReportDescriptor(
+# Sort by Report ID for consistency.
+hid_devices = sorted(args.hid_devices, key=lambda name: hid_report_descriptors.REPORT_IDS[name])
+
+# When there's only one hid_device, it can't be in a composite descriptor.
+# It has no report id (indicated by 0), so remove the existing one.
+
+#if len(hid_devices) == 1:
+if False:
+ name = hid_devices[0]
+ combined_hid_report_descriptor = hid.ReportDescriptor(
+ description=name,
+ report_descriptor=hid_report_descriptors.remove_report_id(
+ hid_report_descriptors.REPORT_DESCRIPTORS[name].report_descriptor))
+ hid_report_ids_dict = { name : 0 }
+else:
+ combined_hid_report_descriptor = hid.ReportDescriptor(
description="MULTIDEVICE",
report_descriptor=b''.join(
hid_report_descriptors.REPORT_DESCRIPTORS[name].report_descriptor for name in hid_devices ))
+ hid_report_ids_dict = { name: hid_report_descriptors.REPORT_IDS[name] for name in hid_devices }
-hid_report_ids_dict = { name: hid_report_descriptors.REPORT_IDS[name] for name in hid_devices }
hid_report_lengths_dict = { name: hid_report_descriptors.REPORT_LENGTHS[name] for name in hid_devices }
hid_max_report_length = max(hid_report_lengths_dict.values())
@@ -271,19 +304,27 @@ cdc_iad = standard.InterfaceAssociationDescriptor(
bFunctionProtocol=cdc.CDC_PROTOCOL_NONE)
descriptor_list = []
-descriptor_list.append(cdc_iad)
-descriptor_list.extend(cdc_interfaces)
-descriptor_list.extend(msc_interfaces)
-# Only add the control interface because other audio interfaces are managed by it to ensure the
-# correct ordering.
-descriptor_list.append(audio_control_interface)
-# Put the CDC IAD just before the CDC interfaces.
-# There appears to be a bug in the Windows composite USB driver that requests the
-# HID report descriptor with the wrong interface number if the HID interface is not given
-# first. However, it still fetches the descriptor anyway. We could reorder the interfaces but
-# the Windows 7 Adafruit_usbser.inf file thinks CDC is at Interface 0, so we'll leave it
-# there for backwards compatibility.
-descriptor_list.extend(hid_interfaces)
+
+if 'CDC' in args.devices:
+ # Put the CDC IAD just before the CDC interfaces.
+ # There appears to be a bug in the Windows composite USB driver that requests the
+ # HID report descriptor with the wrong interface number if the HID interface is not given
+ # first. However, it still fetches the descriptor anyway. We could reorder the interfaces but
+ # the Windows 7 Adafruit_usbser.inf file thinks CDC is at Interface 0, so we'll leave it
+ # there for backwards compatibility.
+ descriptor_list.append(cdc_iad)
+ descriptor_list.extend(cdc_interfaces)
+
+if 'MSC' in args.devices:
+ descriptor_list.extend(msc_interfaces)
+
+if 'AUDIO' in args.devices:
+ # Only add the control interface because other audio interfaces are managed by it to ensure the
+ # correct ordering.
+ descriptor_list.append(audio_control_interface)
+
+if 'HID' in args.devices:
+ descriptor_list.extend(hid_interfaces)
configuration = standard.ConfigurationDescriptor(
description="Composite configuration",
diff --git a/tools/hid_report_descriptors.py b/tools/hid_report_descriptors.py
index f3b28ebcf..4902657af 100644
--- a/tools/hid_report_descriptors.py
+++ b/tools/hid_report_descriptors.py
@@ -31,6 +31,11 @@ HID specific descriptors
from adafruit_usb_descriptor import hid
+def remove_report_id(report_descriptor_bytes):
+ #return report_descriptor_bytes
+ report_id_pos = report_descriptor_bytes.index(0x85)
+ return report_descriptor_bytes[:report_id_pos] + report_descriptor_bytes[report_id_pos + 2:]
+
REPORT_IDS = {
"KEYBOARD" : 1,
"MOUSE" : 2,
@@ -38,6 +43,9 @@ REPORT_IDS = {
"SYS_CONTROL" : 4,
"GAMEPAD" : 5,
"DIGITIZER" : 6,
+ "XAC_COMPATIBLE_GAMEPAD" : 7,
+ # RAW must not have a report ID, so it can't be used with other devices.
+ "RAW" : 0,
}
# Byte count for each kind of report. Length does not include report ID in first byte.
@@ -48,6 +56,8 @@ REPORT_LENGTHS = {
"SYS_CONTROL" : 1,
"GAMEPAD" : 6,
"DIGITIZER" : 5,
+ "XAC_COMPATIBLE_GAMEPAD" : 3,
+ "RAW" : 64,
}
KEYBOARD_WITH_ID = hid.ReportDescriptor(
@@ -228,6 +238,54 @@ DIGITIZER_WITH_ID = hid.ReportDescriptor(
0xC0, # End Collection
]))
+XAC_COMPATIBLE_GAMEPAD_WITH_ID = hid.ReportDescriptor(
+ description="XAC",
+ report_descriptor=bytes([
+ # This descriptor mimics the simple joystick from PDP that the XBox likes
+ 0x05, 0x01, # Usage Page (Desktop),
+ 0x09, 0x05, # Usage (Gamepad),
+ 0xA1, 0x01, # Collection (Application),
+ 0x85, REPORT_IDS["XAC_COMPATIBLE_GAMEPAD"], # Report ID (n)
+ 0x15, 0x00, # Logical Minimum (0),
+ 0x25, 0x01, # Logical Maximum (1),
+ 0x35, 0x00, # Physical Minimum (0),
+ 0x45, 0x01, # Physical Maximum (1),
+ 0x75, 0x01, # Report Size (1),
+ 0x95, 0x08, # Report Count (8),
+ 0x05, 0x09, # Usage Page (Button),
+ 0x19, 0x01, # Usage Minimum (01h),
+ 0x29, 0x08, # Usage Maximum (08h),
+ 0x81, 0x02, # Input (Variable),
+ 0x05, 0x01, # Usage Page (Desktop),
+ 0x26, 0xFF, 0x00, # Logical Maximum (255),
+ 0x46, 0xFF, 0x00, # Physical Maximum (255),
+ 0x09, 0x30, # Usage (X),
+ 0x09, 0x31, # Usage (Y),
+ 0x75, 0x08, # Report Size (8),
+ 0x95, 0x02, # Report Count (2),
+ 0x81, 0x02, # Input (Variable),
+ 0xC0 # End Collection
+ ]))
+
+RAW = hid.ReportDescriptor(
+ description="RAW",
+ report_descriptor=bytes([
+ # Provide vendor-defined
+ 0x06, 0xAF, 0xFF, # Usage Page (Vendor 0xFFAF "Adafruit"),
+ 0x09, 0xAF, # Usage (AF),
+ 0xA1, 0x01, # Collection (Application),
+ 0x75, 0x08, # Report Size (8),
+ 0x15, 0x00, # Logical Minimum (0),
+ 0x26, 0xFF, 0x00 # Logical Maximum (255),
+ 0x95, 0x08, # Report Count (8),
+ 0x09, 0x01 # Usage(xxx)
+ 0x81, 0x02 # Input (Variable)
+ 0x95, 0x08, # Report Count (8),
+ 0x09, 0x02, # Usage(xxx)
+ 0x91, 0x02, # Input (Variable)
+ 0xC0 # End Collection
+ ]))
+
# Byte count for each kind of report. Length does not include report ID in first byte.
REPORT_DESCRIPTORS = {
"KEYBOARD" : KEYBOARD_WITH_ID,
@@ -236,4 +294,6 @@ REPORT_DESCRIPTORS = {
"SYS_CONTROL" : SYS_CONTROL_WITH_ID,
"GAMEPAD" : GAMEPAD_WITH_ID,
"DIGITIZER" : DIGITIZER_WITH_ID,
+ "XAC_COMPATIBLE_GAMEPAD" : XAC_COMPATIBLE_GAMEPAD_WITH_ID,
+ "RAW" : RAW_WITH_ID,
}