Merge remote-tracking branch 'upstream/master' into stm32-ci-workflow
This commit is contained in:
commit
96d1711296
|
@ -20,6 +20,9 @@ ifeq ($(CHIP_FAMILY),samd21)
|
|||
CIRCUITPY_AUDIOMIXER = 0
|
||||
CIRCUITPY_FREQUENCYIO = 0
|
||||
CIRCUITPY_TOUCHIO_USE_NATIVE = 1
|
||||
|
||||
# SAMD21 needs separate endpoint pairs for MSC BULK IN and BULK OUT, otherwise it's erratic.
|
||||
USB_MSC_NUM_ENDPOINT_PAIRS = 2
|
||||
endif
|
||||
|
||||
# Put samd51-only choices here.
|
||||
|
|
|
@ -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() ) {
|
||||
|
|
|
@ -24,131 +24,4 @@
|
|||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
#include "genhdr/autogen_usb_descriptor.h"
|
||||
#include "shared-module/usb_hid/Device.h"
|
||||
#include "shared-bindings/usb_hid/Device.h"
|
||||
#include "tusb.h"
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_KEYBOARD
|
||||
static uint8_t keyboard_report_buffer[USB_HID_REPORT_LENGTH_KEYBOARD];
|
||||
#endif
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_MOUSE
|
||||
static uint8_t mouse_report_buffer[USB_HID_REPORT_LENGTH_MOUSE];
|
||||
#endif
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_CONSUMER
|
||||
static uint8_t consumer_report_buffer[USB_HID_REPORT_LENGTH_CONSUMER];
|
||||
#endif
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_SYS_CONTROL
|
||||
static uint8_t sys_control_report_buffer[USB_HID_REPORT_LENGTH_SYS_CONTROL];
|
||||
#endif
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_GAMEPAD
|
||||
static uint8_t gamepad_report_buffer[USB_HID_REPORT_LENGTH_GAMEPAD];
|
||||
#endif
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_DIGITIZER
|
||||
static uint8_t digitizer_report_buffer[USB_HID_REPORT_LENGTH_DIGITIZER];
|
||||
#endif
|
||||
|
||||
usb_hid_device_obj_t usb_hid_devices[] = {
|
||||
#ifdef USB_HID_REPORT_ID_KEYBOARD
|
||||
{
|
||||
.base = { .type = &usb_hid_device_type } ,
|
||||
.report_buffer = keyboard_report_buffer ,
|
||||
.report_id = USB_HID_REPORT_ID_KEYBOARD ,
|
||||
.report_length = USB_HID_REPORT_LENGTH_KEYBOARD ,
|
||||
.usage_page = HID_USAGE_PAGE_DESKTOP ,
|
||||
.usage = HID_USAGE_DESKTOP_KEYBOARD ,
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_MOUSE
|
||||
{
|
||||
.base = { .type = &usb_hid_device_type } ,
|
||||
.report_buffer = mouse_report_buffer ,
|
||||
.report_id = USB_HID_REPORT_ID_MOUSE ,
|
||||
.report_length = USB_HID_REPORT_LENGTH_MOUSE ,
|
||||
.usage_page = HID_USAGE_PAGE_DESKTOP ,
|
||||
.usage = HID_USAGE_DESKTOP_MOUSE ,
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_CONSUMER
|
||||
{
|
||||
.base = { .type = &usb_hid_device_type } ,
|
||||
.report_buffer = consumer_report_buffer ,
|
||||
.report_id = USB_HID_REPORT_ID_CONSUMER ,
|
||||
.report_length = USB_HID_REPORT_LENGTH_CONSUMER ,
|
||||
.usage_page = HID_USAGE_PAGE_CONSUMER ,
|
||||
.usage = HID_USAGE_CONSUMER_CONTROL ,
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_SYS_CONTROL
|
||||
{
|
||||
.base = { .type = &usb_hid_device_type } ,
|
||||
.report_buffer = sys_control_report_buffer ,
|
||||
.report_id = USB_HID_REPORT_ID_SYS_CONTROL ,
|
||||
.report_length = USB_HID_REPORT_LENGTH_SYS_CONTROL ,
|
||||
.usage_page = HID_USAGE_PAGE_DESKTOP ,
|
||||
.usage = HID_USAGE_DESKTOP_SYSTEM_CONTROL ,
|
||||
},
|
||||
#endif
|
||||
|
||||
#ifdef USB_HID_REPORT_ID_GAMEPAD
|
||||
{
|
||||
.base = { .type = &usb_hid_device_type } ,
|
||||
.report_buffer = gamepad_report_buffer ,
|
||||
.report_id = USB_HID_REPORT_ID_GAMEPAD ,
|
||||
.report_length = USB_HID_REPORT_LENGTH_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 } ,
|
||||
.report_buffer = digitizer_report_buffer ,
|
||||
.report_id = USB_HID_REPORT_ID_DIGITIZER ,
|
||||
.report_length = USB_HID_REPORT_LENGTH_DIGITIZER ,
|
||||
.usage_page = 0x0D ,
|
||||
.usage = 0x02 ,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
mp_obj_tuple_t common_hal_usb_hid_devices = {
|
||||
.base = {
|
||||
.type = &mp_type_tuple,
|
||||
},
|
||||
.len = USB_HID_NUM_DEVICES,
|
||||
.items = {
|
||||
#if USB_HID_NUM_DEVICES >= 1
|
||||
(mp_obj_t) &usb_hid_devices[0],
|
||||
#endif
|
||||
#if USB_HID_NUM_DEVICES >= 2
|
||||
(mp_obj_t) &usb_hid_devices[1],
|
||||
#endif
|
||||
#if USB_HID_NUM_DEVICES >= 3
|
||||
(mp_obj_t) &usb_hid_devices[2],
|
||||
#endif
|
||||
#if USB_HID_NUM_DEVICES >= 4
|
||||
(mp_obj_t) &usb_hid_devices[3],
|
||||
#endif
|
||||
#if USB_HID_NUM_DEVICES >= 5
|
||||
(mp_obj_t) &usb_hid_devices[4],
|
||||
#endif
|
||||
#if USB_HID_NUM_DEVICES >= 6
|
||||
(mp_obj_t) &usb_hid_devices[5],
|
||||
#endif
|
||||
}
|
||||
};
|
||||
// Nothing needed here. Tables of HID devices are generated in autogen_usb_descriptor.c at compile-time.
|
||||
|
|
|
@ -86,6 +86,19 @@ 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
|
||||
|
||||
# SAMD21 needs separate endpoint pairs for MSC BULK IN and BULK OUT, otherwise it's erratic.
|
||||
ifndef USB_MSC_NUM_ENDPOINT_PAIRS
|
||||
USB_MSC_NUM_ENDPOINT_PAIRS = 1
|
||||
endif
|
||||
|
||||
SUPERVISOR_O = $(addprefix $(BUILD)/, $(SRC_SUPERVISOR:.c=.o)) $(BUILD)/autogen_display_resources.o
|
||||
|
||||
$(BUILD)/supervisor/shared/translate.o: $(HEADER_BUILD)/qstrdefs.generated.h
|
||||
|
@ -103,6 +116,9 @@ 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)\
|
||||
--msc_num_endpoint_pairs $(USB_MSC_NUM_ENDPOINT_PAIRS)\
|
||||
--output_c_file $(BUILD)/autogen_usb_descriptor.c\
|
||||
--output_h_file $(BUILD)/genhdr/autogen_usb_descriptor.h
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ def get_current_info():
|
|||
current_info[info["id"]] = info
|
||||
return git_info, current_info
|
||||
|
||||
def create_pr(changes, updated, git_info):
|
||||
def create_pr(changes, updated, git_info, user):
|
||||
commit_sha, original_blob_sha = git_info
|
||||
branch_name = "new_release_" + changes["new_release"]
|
||||
|
||||
|
@ -139,7 +139,7 @@ def create_pr(changes, updated, git_info):
|
|||
languages = ""
|
||||
if changes["new_languages"]:
|
||||
languages = "New languages:\n* " + "\n* ".join(changes["new_languages"])
|
||||
message = "Automated website update for release {} by AdaBot.\n\n{}\n\n{}\n".format(
|
||||
message = "Automated website update for release {} by Blinka.\n\n{}\n\n{}\n".format(
|
||||
changes["new_release"],
|
||||
boards,
|
||||
languages
|
||||
|
@ -149,7 +149,7 @@ def create_pr(changes, updated, git_info):
|
|||
"ref": "refs/heads/" + branch_name,
|
||||
"sha": commit_sha
|
||||
}
|
||||
response = github.post("/repos/adafruit-adabot/circuitpython-org/git/refs", json=create_branch)
|
||||
response = github.post("/repos/{}/circuitpython-org/git/refs".format(user), json=create_branch)
|
||||
if not response.ok and response.json()["message"] != "Reference already exists":
|
||||
print("unable to create branch")
|
||||
print(response.text)
|
||||
|
@ -162,14 +162,14 @@ def create_pr(changes, updated, git_info):
|
|||
"branch": branch_name
|
||||
}
|
||||
|
||||
response = github.put("/repos/adafruit-adabot/circuitpython-org/contents/_data/files.json", json=update_file)
|
||||
response = github.put("/repos/{}/circuitpython-org/contents/_data/files.json".format(user), json=update_file)
|
||||
if not response.ok:
|
||||
print("unable to post new file")
|
||||
print(response.text)
|
||||
return
|
||||
pr_info = {
|
||||
"title": pr_title,
|
||||
"head": "adafruit-adabot:" + branch_name,
|
||||
"head": user + ":" + branch_name,
|
||||
"base": "master",
|
||||
"body": message,
|
||||
"maintainer_can_modify": True
|
||||
|
@ -199,9 +199,12 @@ def update_downloads(boards, release):
|
|||
def print_active_user():
|
||||
response = github.get("/user")
|
||||
if response.ok:
|
||||
print("Logged in as {}".format(response.json()["login"]))
|
||||
user = response.json()["login"]
|
||||
print("Logged in as {}".format(user))
|
||||
return user
|
||||
else:
|
||||
print("Not logged in")
|
||||
return None
|
||||
|
||||
def generate_download_info():
|
||||
boards = {}
|
||||
|
@ -215,7 +218,7 @@ def generate_download_info():
|
|||
"new_languages": []
|
||||
}
|
||||
|
||||
print_active_user()
|
||||
user = print_active_user()
|
||||
|
||||
sha, this_version = get_version_info()
|
||||
|
||||
|
@ -272,8 +275,8 @@ def generate_download_info():
|
|||
|
||||
changes["new_languages"] = set(languages) - previous_languages
|
||||
|
||||
if changes["new_release"]:
|
||||
create_pr(changes, current_info, git_info)
|
||||
if changes["new_release"] and user:
|
||||
create_pr(changes, current_info, git_info, user)
|
||||
else:
|
||||
print("No new release to update")
|
||||
|
||||
|
|
|
@ -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,RAW'
|
||||
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,29 @@ 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: tuple(l.split(',')), default=DEFAULT_DEVICES,
|
||||
help='devices to include in descriptor (AUDIO includes MIDI support)')
|
||||
parser.add_argument('--hid_devices', type=lambda l: tuple(l.split(',')), default=DEFAULT_HID_DEVICES,
|
||||
help='HID devices to include in HID report descriptor')
|
||||
parser.add_argument('--msc_num_endpoint_pairs', type=int, default=1,
|
||||
help='Use 1 or 2 endpoint pairs for MSC (1 bidirectional, or 1 input + 1 output (required by SAMD21))')
|
||||
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(frozenset(args.devices) - ALL_DEVICES_SET)
|
||||
if unknown_devices:
|
||||
raise ValueError("Unknown device(s)", unknown_devices)
|
||||
|
||||
unknown_hid_devices = list(frozenset(args.hid_devices) - ALL_HID_DEVICES_SET)
|
||||
if unknown_hid_devices:
|
||||
raise ValueError("Unknown HID devices(s)", unknown_hid_devices)
|
||||
|
||||
if args.msc_num_endpoint_pairs not in (1, 2):
|
||||
raise ValueError("--msc_num_endpoint_pairs must be 1 or 2")
|
||||
|
||||
|
||||
class StringIndex:
|
||||
"""Assign a monotonically increasing index to each unique string. Start with 0."""
|
||||
string_to_index = {}
|
||||
|
@ -131,25 +158,36 @@ msc_interfaces = [
|
|||
bInterval=0),
|
||||
standard.EndpointDescriptor(
|
||||
description="MSC out",
|
||||
bEndpointAddress=0x1 | standard.EndpointDescriptor.DIRECTION_OUT,
|
||||
# SAMD21 needs to use a separate pair of endpoints for MSC.
|
||||
bEndpointAddress=((0x1 if args.msc_num_endpoint_pairs == 2 else 0x0) |
|
||||
standard.EndpointDescriptor.DIRECTION_OUT),
|
||||
bmAttributes=standard.EndpointDescriptor.TYPE_BULK,
|
||||
bInterval=0)
|
||||
]
|
||||
)
|
||||
]
|
||||
|
||||
# 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")
|
||||
# When there's only one hid_device, it shouldn't have a report id.
|
||||
# Otherwise, report ids are assigned sequentially:
|
||||
# args.hid_devices[0] has report_id 1
|
||||
# args.hid_devices[1] has report_id 2
|
||||
# etc.
|
||||
|
||||
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_lengths_dict = { name: hid_report_descriptors.REPORT_LENGTHS[name] for name in hid_devices }
|
||||
hid_max_report_length = max(hid_report_lengths_dict.values())
|
||||
if len(args.hid_devices) == 1:
|
||||
name = args.hid_devices[0]
|
||||
combined_hid_report_descriptor = hid.ReportDescriptor(
|
||||
description=name,
|
||||
report_descriptor=bytes(hid_report_descriptors.REPORT_DESCRIPTOR_FUNCTIONS[name](0)))
|
||||
else:
|
||||
report_id = 1
|
||||
concatenated_descriptors = bytearray()
|
||||
for name in args.hid_devices:
|
||||
concatenated_descriptors.extend(
|
||||
bytes(hid_report_descriptors.REPORT_DESCRIPTOR_FUNCTIONS[name](report_id)))
|
||||
report_id += 1
|
||||
combined_hid_report_descriptor = hid.ReportDescriptor(
|
||||
description="MULTIDEVICE",
|
||||
report_descriptor=bytes(concatenated_descriptors))
|
||||
|
||||
# ASF4 expects keyboard and generic devices to have both in and out endpoints,
|
||||
# and will fail (possibly silently) if both are not supplied.
|
||||
|
@ -271,19 +309,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",
|
||||
|
@ -302,6 +348,8 @@ h_file = args.output_h_file
|
|||
c_file.write("""\
|
||||
#include <stdint.h>
|
||||
|
||||
#include "py/objtuple.h"
|
||||
#include "shared-bindings/usb_hid/Device.h"
|
||||
#include "{H_FILE_NAME}"
|
||||
|
||||
""".format(H_FILE_NAME=h_file.name))
|
||||
|
@ -420,7 +468,9 @@ const uint8_t usb_desc_cfg[{configuration_length}];
|
|||
uint16_t usb_serial_number[{serial_number_length}];
|
||||
uint16_t const * const string_desc_arr [{string_descriptor_length}];
|
||||
|
||||
const uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}];
|
||||
const uint8_t hid_report_descriptor[{hid_report_descriptor_length}];
|
||||
|
||||
#define USB_HID_NUM_DEVICES {hid_num_devices}
|
||||
|
||||
// Vendor name included in Inquiry response, max 8 bytes
|
||||
#define CFG_TUD_MSC_VENDOR "{msc_vendor}"
|
||||
|
@ -434,36 +484,11 @@ const uint8_t hid_report_descriptor[{HID_REPORT_DESCRIPTOR_LENGTH}];
|
|||
configuration_length=descriptor_length,
|
||||
max_configuration_length=max(hid_descriptor_length, descriptor_length),
|
||||
string_descriptor_length=len(pointers_to_strings),
|
||||
HID_REPORT_DESCRIPTOR_LENGTH=len(bytes(combined_hid_report_descriptor)),
|
||||
hid_report_descriptor_length=len(bytes(combined_hid_report_descriptor)),
|
||||
hid_num_devices=len(args.hid_devices),
|
||||
msc_vendor=args.manufacturer[:8],
|
||||
msc_product=args.product[:16]))
|
||||
|
||||
# #define the report ID's used in the combined HID descriptor
|
||||
for name, id in hid_report_ids_dict.items():
|
||||
h_file.write("""\
|
||||
#define USB_HID_REPORT_ID_{name} {id}
|
||||
""".format(name=name,
|
||||
id=id))
|
||||
|
||||
h_file.write("\n")
|
||||
|
||||
# #define the report sizes used in the combined HID descriptor
|
||||
for name, length in hid_report_lengths_dict.items():
|
||||
h_file.write("""\
|
||||
#define USB_HID_REPORT_LENGTH_{name} {length}
|
||||
""".format(name=name,
|
||||
length=length))
|
||||
|
||||
h_file.write("\n")
|
||||
|
||||
h_file.write("""\
|
||||
#define USB_HID_NUM_DEVICES {num_devices}
|
||||
#define USB_HID_MAX_REPORT_LENGTH {max_length}
|
||||
""".format(num_devices=len(hid_report_lengths_dict),
|
||||
max_length=hid_max_report_length))
|
||||
|
||||
|
||||
|
||||
# Write out the report descriptor and info
|
||||
c_file.write("""\
|
||||
const uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{
|
||||
|
@ -471,7 +496,55 @@ const uint8_t hid_report_descriptor[{HID_DESCRIPTOR_LENGTH}] = {{
|
|||
|
||||
for b in bytes(combined_hid_report_descriptor):
|
||||
c_file.write("0x{:02x}, ".format(b))
|
||||
c_file.write("""\
|
||||
};
|
||||
|
||||
""")
|
||||
|
||||
# Write out USB HID report buffer definitions.
|
||||
for report_id, name in enumerate(args.hid_devices, start=1):
|
||||
c_file.write("""\
|
||||
static uint8_t {name}_report_buffer[{report_length}];
|
||||
""".format(name=name.lower(), report_length=hid_report_descriptors.HID_DEVICE_DATA[name].report_length))
|
||||
|
||||
# Write out table of device objects.
|
||||
c_file.write("""
|
||||
usb_hid_device_obj_t usb_hid_devices[] = {
|
||||
""");
|
||||
for report_id, name in enumerate(args.hid_devices, start=1):
|
||||
device_data = hid_report_descriptors.HID_DEVICE_DATA[name]
|
||||
c_file.write("""\
|
||||
{{
|
||||
.base = {{ .type = &usb_hid_device_type }},
|
||||
.report_buffer = {name}_report_buffer,
|
||||
.report_id = {report_id:},
|
||||
.report_length = {report_length},
|
||||
.usage_page = {usage_page:#04x},
|
||||
.usage = {usage:#04x},
|
||||
}},
|
||||
""".format(name=name.lower(), report_id=report_id,
|
||||
report_length=device_data.report_length,
|
||||
usage_page=device_data.usage_page,
|
||||
usage=device_data.usage))
|
||||
c_file.write("""\
|
||||
};
|
||||
""")
|
||||
|
||||
# Write out tuple of device objects.
|
||||
c_file.write("""
|
||||
mp_obj_tuple_t common_hal_usb_hid_devices = {{
|
||||
.base = {{
|
||||
.type = &mp_type_tuple,
|
||||
}},
|
||||
.len = {num_devices},
|
||||
.items = {{
|
||||
""".format(num_devices=len(args.hid_devices)))
|
||||
for idx in range(len(args.hid_devices)):
|
||||
c_file.write("""\
|
||||
(mp_obj_t) &usb_hid_devices[{idx}],
|
||||
""".format(idx=idx))
|
||||
c_file.write("""\
|
||||
},
|
||||
};
|
||||
""")
|
||||
|
||||
|
|
|
@ -29,211 +29,284 @@ HID specific descriptors
|
|||
* Author(s): Dan Halbert
|
||||
"""
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
from adafruit_usb_descriptor import hid
|
||||
|
||||
REPORT_IDS = {
|
||||
"KEYBOARD" : 1,
|
||||
"MOUSE" : 2,
|
||||
"CONSUMER" : 3,
|
||||
"SYS_CONTROL" : 4,
|
||||
"GAMEPAD" : 5,
|
||||
"DIGITIZER" : 6,
|
||||
# Information about each kind of device
|
||||
# report_length does not include report ID in first byte, if present when sent.
|
||||
DeviceData = namedtuple('DeviceData', ('report_length', 'usage_page', 'usage'))
|
||||
HID_DEVICE_DATA = {
|
||||
"KEYBOARD" : DeviceData(report_length=8, usage_page=0x01, usage=0x06), # Generic Desktop, Keyboard
|
||||
"MOUSE" : DeviceData(report_length=4, usage_page=0x01, usage=0x02), # Generic Desktop, Mouse
|
||||
"CONSUMER" : DeviceData(report_length=2, usage_page=0x0C, usage=0x01), # Consumer, Consumer Control
|
||||
"SYS_CONTROL" : DeviceData(report_length=1, usage_page=0x01, usage=0x80), # Generic Desktop, Sys Control
|
||||
"GAMEPAD" : DeviceData(report_length=6, usage_page=0x01, usage=0x05), # Generic Desktop, Game Pad
|
||||
"DIGITIZER" : DeviceData(report_length=5, usage_page=0x0D, usage=0x02), # Digitizers, Pen
|
||||
"XAC_COMPATIBLE_GAMEPAD" : DeviceData(report_length=3, usage_page=0x01, usage=0x05), # Generic Desktop, Game Pad
|
||||
"RAW" : DeviceData(report_length=64, usage_page=0xFFAF, usage=0xAF), # Vendor 0xFFAF "Adafruit", 0xAF
|
||||
}
|
||||
|
||||
# Byte count for each kind of report. Length does not include report ID in first byte.
|
||||
REPORT_LENGTHS = {
|
||||
"KEYBOARD" : 8,
|
||||
"MOUSE" : 4,
|
||||
"CONSUMER" : 2,
|
||||
"SYS_CONTROL" : 1,
|
||||
"GAMEPAD" : 6,
|
||||
"DIGITIZER" : 5,
|
||||
}
|
||||
def keyboard_hid_descriptor(report_id):
|
||||
data = HID_DEVICE_DATA["KEYBOARD"]
|
||||
return hid.ReportDescriptor(
|
||||
description="KEYBOARD",
|
||||
report_descriptor=bytes(
|
||||
# Regular keyboard
|
||||
(0x05, data.usage_page, # Usage Page (Generic Desktop)
|
||||
0x09, data.usage, # Usage (Keyboard)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
) +
|
||||
((0x85, report_id) if report_id != 0 else ()) +
|
||||
(0x05, 0x07, # Usage Page (Keyboard)
|
||||
0x19, 224, # Usage Minimum (224)
|
||||
0x29, 231, # Usage Maximum (231)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x95, 0x08, # Report Count (8)
|
||||
0x81, 0x02, # Input (Data, Variable, Absolute)
|
||||
0x81, 0x01, # Input (Constant)
|
||||
0x19, 0x00, # Usage Minimum (0)
|
||||
0x29, 101, # Usage Maximum (101)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 101, # Logical Maximum (101)
|
||||
0x75, 0x08, # Report Size (8)
|
||||
0x95, 0x06, # Report Count (6)
|
||||
0x81, 0x00, # Input (Data, Array)
|
||||
0x05, 0x08, # Usage Page (LED)
|
||||
0x19, 0x01, # Usage Minimum (1)
|
||||
0x29, 0x05, # Usage Maximum (5)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x95, 0x05, # Report Count (5)
|
||||
0x91, 0x02, # Output (Data, Variable, Absolute)
|
||||
0x95, 0x03, # Report Count (3)
|
||||
0x91, 0x01, # Output (Constant)
|
||||
0xC0, # End Collection
|
||||
)))
|
||||
|
||||
KEYBOARD_WITH_ID = hid.ReportDescriptor(
|
||||
description="KEYBOARD",
|
||||
report_descriptor=bytes([
|
||||
# Regular keyboard
|
||||
0x05, 0x01, # Usage Page (Generic Desktop)
|
||||
0x09, 0x06, # Usage (Keyboard)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
0x85, REPORT_IDS["KEYBOARD"], # Report ID (1)
|
||||
0x05, 0x07, # Usage Page (Keyboard)
|
||||
0x19, 224, # Usage Minimum (224)
|
||||
0x29, 231, # Usage Maximum (231)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x95, 0x08, # Report Count (8)
|
||||
0x81, 0x02, # Input (Data, Variable, Absolute)
|
||||
0x81, 0x01, # Input (Constant)
|
||||
0x19, 0x00, # Usage Minimum (0)
|
||||
0x29, 101, # Usage Maximum (101)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 101, # Logical Maximum (101)
|
||||
0x75, 0x08, # Report Size (8)
|
||||
0x95, 0x06, # Report Count (6)
|
||||
0x81, 0x00, # Input (Data, Array)
|
||||
0x05, 0x08, # Usage Page (LED)
|
||||
0x19, 0x01, # Usage Minimum (1)
|
||||
0x29, 0x05, # Usage Maximum (5)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x95, 0x05, # Report Count (5)
|
||||
0x91, 0x02, # Output (Data, Variable, Absolute)
|
||||
0x95, 0x03, # Report Count (3)
|
||||
0x91, 0x01, # Output (Constant)
|
||||
0xC0, # End Collection
|
||||
]))
|
||||
def mouse_hid_descriptor(report_id):
|
||||
data = HID_DEVICE_DATA["MOUSE"]
|
||||
return hid.ReportDescriptor(
|
||||
description="MOUSE",
|
||||
report_descriptor=bytes(
|
||||
# Regular mouse
|
||||
(0x05, data.usage_page, # Usage Page (Generic Desktop)
|
||||
0x09, data.usage, # Usage (Mouse)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
0x09, 0x01, # Usage (Pointer)
|
||||
0xA1, 0x00, # Collection (Physical)
|
||||
) +
|
||||
((0x85, report_id) if report_id != 0 else ()) +
|
||||
(0x05, 0x09, # Usage Page (Button)
|
||||
0x19, 0x01, # Usage Minimum (0x01)
|
||||
0x29, 0x05, # Usage Maximum (0x05)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x95, 0x05, # Report Count (5)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x95, 0x01, # Report Count (1)
|
||||
0x75, 0x03, # Report Size (3)
|
||||
0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x30, # Usage (X)
|
||||
0x09, 0x31, # Usage (Y)
|
||||
0x15, 0x81, # Logical Minimum (-127)
|
||||
0x25, 0x7F, # Logical Maximum (127)
|
||||
0x75, 0x08, # Report Size (8)
|
||||
0x95, 0x02, # Report Count (2)
|
||||
0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x09, 0x38, # Usage (Wheel)
|
||||
0x15, 0x81, # Logical Minimum (-127)
|
||||
0x25, 0x7F, # Logical Maximum (127)
|
||||
0x75, 0x08, # Report Size (8)
|
||||
0x95, 0x01, # Report Count (1)
|
||||
0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, # End Collection
|
||||
0xC0, # End Collection
|
||||
)))
|
||||
|
||||
MOUSE_WITH_ID = hid.ReportDescriptor(
|
||||
description="MOUSE",
|
||||
report_descriptor=bytes([
|
||||
# Regular mouse
|
||||
0x05, 0x01, # Usage Page (Generic Desktop)
|
||||
0x09, 0x02, # Usage (Mouse)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
0x09, 0x01, # Usage (Pointer)
|
||||
0xA1, 0x00, # Collection (Physical)
|
||||
0x85, REPORT_IDS["MOUSE"], # Report ID (n)
|
||||
0x05, 0x09, # Usage Page (Button)
|
||||
0x19, 0x01, # Usage Minimum (0x01)
|
||||
0x29, 0x05, # Usage Maximum (0x05)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x95, 0x05, # Report Count (5)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x95, 0x01, # Report Count (1)
|
||||
0x75, 0x03, # Report Size (3)
|
||||
0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x30, # Usage (X)
|
||||
0x09, 0x31, # Usage (Y)
|
||||
0x15, 0x81, # Logical Minimum (-127)
|
||||
0x25, 0x7F, # Logical Maximum (127)
|
||||
0x75, 0x08, # Report Size (8)
|
||||
0x95, 0x02, # Report Count (2)
|
||||
0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x09, 0x38, # Usage (Wheel)
|
||||
0x15, 0x81, # Logical Minimum (-127)
|
||||
0x25, 0x7F, # Logical Maximum (127)
|
||||
0x75, 0x08, # Report Size (8)
|
||||
0x95, 0x01, # Report Count (1)
|
||||
0x81, 0x06, # Input (Data,Var,Rel,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, # End Collection
|
||||
0xC0, # End Collection
|
||||
]))
|
||||
def consumer_hid_descriptor(report_id):
|
||||
data = HID_DEVICE_DATA["CONSUMER"]
|
||||
return hid.ReportDescriptor(
|
||||
description="CONSUMER",
|
||||
report_descriptor=bytes(
|
||||
# Consumer ("multimedia") keys
|
||||
(0x05, data.usage_page, # Usage Page (Consumer)
|
||||
0x09, data.usage, # Usage (Consumer Control)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
) +
|
||||
((0x85, report_id) if report_id != 0 else ()) +
|
||||
(0x75, 0x10, # Report Size (16)
|
||||
0x95, 0x01, # Report Count (1)
|
||||
0x15, 0x01, # Logical Minimum (1)
|
||||
0x26, 0x8C, 0x02, # Logical Maximum (652)
|
||||
0x19, 0x01, # Usage Minimum (Consumer Control)
|
||||
0x2A, 0x8C, 0x02, # Usage Maximum (AC Send)
|
||||
0x81, 0x00, # Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, # End Collection
|
||||
)))
|
||||
|
||||
CONSUMER_WITH_ID = hid.ReportDescriptor(
|
||||
description="CONSUMER",
|
||||
report_descriptor=bytes([
|
||||
# Consumer ("multimedia") keys
|
||||
0x05, 0x0C, # Usage Page (Consumer)
|
||||
0x09, 0x01, # Usage (Consumer Control)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
0x85, REPORT_IDS["CONSUMER"], # Report ID (n)
|
||||
0x75, 0x10, # Report Size (16)
|
||||
0x95, 0x01, # Report Count (1)
|
||||
0x15, 0x01, # Logical Minimum (1)
|
||||
0x26, 0x8C, 0x02, # Logical Maximum (652)
|
||||
0x19, 0x01, # Usage Minimum (Consumer Control)
|
||||
0x2A, 0x8C, 0x02, # Usage Maximum (AC Send)
|
||||
0x81, 0x00, # Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, # End Collection
|
||||
]))
|
||||
def sys_control_hid_descriptor(report_id):
|
||||
data = HID_DEVICE_DATA["SYS_CONTROL"]
|
||||
return hid.ReportDescriptor(
|
||||
description="SYS_CONTROL",
|
||||
report_descriptor=bytes(
|
||||
# Power controls
|
||||
(0x05, data.usage_page, # Usage Page (Generic Desktop Ctrls)
|
||||
0x09, data.usage, # Usage (Sys Control)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
) +
|
||||
((0x85, report_id) if report_id != 0 else ()) +
|
||||
(0x75, 0x02, # Report Size (2)
|
||||
0x95, 0x01, # Report Count (1)
|
||||
0x15, 0x01, # Logical Minimum (1)
|
||||
0x25, 0x03, # Logical Maximum (3)
|
||||
0x09, 0x82, # Usage (Sys Sleep)
|
||||
0x09, 0x81, # Usage (Sys Power Down)
|
||||
0x09, 0x83, # Usage (Sys Wake Up)
|
||||
0x81, 0x60, # Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State)
|
||||
0x75, 0x06, # Report Size (6)
|
||||
0x81, 0x03, # Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, # End Collection
|
||||
)))
|
||||
|
||||
SYS_CONTROL_WITH_ID = hid.ReportDescriptor(
|
||||
description="SYS_CONTROL",
|
||||
report_descriptor=bytes([
|
||||
# Power controls
|
||||
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x80, # Usage (Sys Control)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
0x85, REPORT_IDS["SYS_CONTROL"], # Report ID (n)
|
||||
0x75, 0x02, # Report Size (2)
|
||||
0x95, 0x01, # Report Count (1)
|
||||
0x15, 0x01, # Logical Minimum (1)
|
||||
0x25, 0x03, # Logical Maximum (3)
|
||||
0x09, 0x82, # Usage (Sys Sleep)
|
||||
0x09, 0x81, # Usage (Sys Power Down)
|
||||
0x09, 0x83, # Usage (Sys Wake Up)
|
||||
0x81, 0x60, # Input (Data,Array,Abs,No Wrap,Linear,No Preferred State,Null State)
|
||||
0x75, 0x06, # Report Size (6)
|
||||
0x81, 0x03, # Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, # End Collection
|
||||
]))
|
||||
def gamepad_hid_descriptor(report_id):
|
||||
data = HID_DEVICE_DATA["GAMEPAD"]
|
||||
return hid.ReportDescriptor(
|
||||
description="GAMEPAD",
|
||||
report_descriptor=bytes(
|
||||
# Gamepad with 16 buttons and two joysticks
|
||||
(0x05, data.usage_page, # Usage Page (Generic Desktop Ctrls)
|
||||
0x09, data.usage, # Usage (Game Pad)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
) +
|
||||
((0x85, report_id) if report_id != 0 else ()) +
|
||||
(0x05, 0x09, # Usage Page (Button)
|
||||
0x19, 0x01, # Usage Minimum (Button 1)
|
||||
0x29, 0x10, # Usage Maximum (Button 16)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x95, 0x10, # Report Count (16)
|
||||
0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
|
||||
0x15, 0x81, # Logical Minimum (-127)
|
||||
0x25, 0x7F, # Logical Maximum (127)
|
||||
0x09, 0x30, # Usage (X)
|
||||
0x09, 0x31, # Usage (Y)
|
||||
0x09, 0x32, # Usage (Z)
|
||||
0x09, 0x35, # Usage (Rz)
|
||||
0x75, 0x08, # Report Size (8)
|
||||
0x95, 0x04, # Report Count (4)
|
||||
0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, # End Collection
|
||||
)))
|
||||
|
||||
GAMEPAD_WITH_ID = hid.ReportDescriptor(
|
||||
description="GAMEPAD",
|
||||
report_descriptor=bytes([
|
||||
# Gamepad with 16 buttons and two joysticks
|
||||
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
|
||||
0x09, 0x05, # Usage (Game Pad)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
0x85, REPORT_IDS["GAMEPAD"], # Report ID (n)
|
||||
0x05, 0x09, # Usage Page (Button)
|
||||
0x19, 0x01, # Usage Minimum (Button 1)
|
||||
0x29, 0x10, # Usage Maximum (Button 16)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x95, 0x10, # Report Count (16)
|
||||
0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
|
||||
0x15, 0x81, # Logical Minimum (-127)
|
||||
0x25, 0x7F, # Logical Maximum (127)
|
||||
0x09, 0x30, # Usage (X)
|
||||
0x09, 0x31, # Usage (Y)
|
||||
0x09, 0x32, # Usage (Z)
|
||||
0x09, 0x35, # Usage (Rz)
|
||||
0x75, 0x08, # Report Size (8)
|
||||
0x95, 0x04, # Report Count (4)
|
||||
0x81, 0x02, # Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0xC0, # End Collection
|
||||
]))
|
||||
def digitizer_hid_descriptor(report_id):
|
||||
data = HID_DEVICE_DATA["DIGITIZER"]
|
||||
return hid.ReportDescriptor(
|
||||
description="DIGITIZER",
|
||||
report_descriptor=bytes(
|
||||
# Digitizer (used as an absolute pointer)
|
||||
(0x05, data.usage_page, # Usage Page (Digitizers)
|
||||
0x09, data.usage, # Usage (Pen)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
) +
|
||||
((0x85, report_id) if report_id != 0 else ()) +
|
||||
(0x09, 0x01, # Usage (Stylus)
|
||||
0xA1, 0x00, # Collection (Physical)
|
||||
0x09, 0x32, # Usage (In-Range)
|
||||
0x09, 0x42, # Usage (Tip Switch)
|
||||
0x09, 0x44, # Usage (Barrel Switch)
|
||||
0x09, 0x45, # Usage (Eraser Switch)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x95, 0x04, # Report Count (4)
|
||||
0x81, 0x02, # Input (Data,Var,Abs)
|
||||
0x75, 0x04, # Report Size (4) -- Filler
|
||||
0x95, 0x01, # Report Count (1) -- Filler
|
||||
0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x26, 0xff, 0x7f, # Logical Maximum (32767)
|
||||
0x09, 0x30, # Usage (X)
|
||||
0x09, 0x31, # Usage (Y)
|
||||
0x75, 0x10, # Report Size (16)
|
||||
0x95, 0x02, # Report Count (2)
|
||||
0x81, 0x02, # Input (Data,Var,Abs)
|
||||
0xC0, # End Collection
|
||||
0xC0, # End Collection
|
||||
)))
|
||||
|
||||
DIGITIZER_WITH_ID = hid.ReportDescriptor(
|
||||
description="DIGITIZER",
|
||||
report_descriptor=bytes([
|
||||
# Digitizer (used as an absolute pointer)
|
||||
0x05, 0x0D, # Usage Page (Digitizers)
|
||||
0x09, 0x02, # Usage (Pen)
|
||||
0xA1, 0x01, # Collection (Application)
|
||||
0x85, REPORT_IDS["DIGITIZER"], # Report ID (n)
|
||||
0x09, 0x01, # Usage (Stylus)
|
||||
0xA1, 0x00, # Collection (Physical)
|
||||
0x09, 0x32, # Usage (In-Range)
|
||||
0x09, 0x42, # Usage (Tip Switch)
|
||||
0x09, 0x44, # Usage (Barrel Switch)
|
||||
0x09, 0x45, # Usage (Eraser Switch)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x25, 0x01, # Logical Maximum (1)
|
||||
0x75, 0x01, # Report Size (1)
|
||||
0x95, 0x04, # Report Count (4)
|
||||
0x81, 0x02, # Input (Data,Var,Abs)
|
||||
0x75, 0x04, # Report Size (4) -- Filler
|
||||
0x95, 0x01, # Report Count (1) -- Filler
|
||||
0x81, 0x01, # Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position)
|
||||
0x05, 0x01, # Usage Page (Generic Desktop Ctrls)
|
||||
0x15, 0x00, # Logical Minimum (0)
|
||||
0x26, 0xff, 0x7f, # Logical Maximum (32767)
|
||||
0x09, 0x30, # Usage (X)
|
||||
0x09, 0x31, # Usage (Y)
|
||||
0x75, 0x10, # Report Size (16)
|
||||
0x95, 0x02, # Report Count (2)
|
||||
0x81, 0x02, # Input (Data,Var,Abs)
|
||||
0xC0, # End Collection
|
||||
0xC0, # End Collection
|
||||
]))
|
||||
def xac_compatible_gamepad_hid_descriptor(report_id):
|
||||
data = HID_DEVICE_DATA["XAC_COMPATIBLE_GAMEPAD"]
|
||||
return hid.ReportDescriptor(
|
||||
description="XAC",
|
||||
report_descriptor=bytes(
|
||||
# This descriptor mimics the simple joystick from PDP that the XBox likes
|
||||
(0x05, data.usage_page, # Usage Page (Desktop),
|
||||
0x09, data.usage, # Usage (Gamepad),
|
||||
0xA1, 0x01, # Collection (Application),
|
||||
) +
|
||||
((0x85, report_id) if report_id != 0 else ()) +
|
||||
(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
|
||||
)))
|
||||
|
||||
# Byte count for each kind of report. Length does not include report ID in first byte.
|
||||
REPORT_DESCRIPTORS = {
|
||||
"KEYBOARD" : KEYBOARD_WITH_ID,
|
||||
"MOUSE" : MOUSE_WITH_ID,
|
||||
"CONSUMER" : CONSUMER_WITH_ID,
|
||||
"SYS_CONTROL" : SYS_CONTROL_WITH_ID,
|
||||
"GAMEPAD" : GAMEPAD_WITH_ID,
|
||||
"DIGITIZER" : DIGITIZER_WITH_ID,
|
||||
}
|
||||
def raw_hid_descriptor(report_id):
|
||||
if report_id != 0:
|
||||
raise ValueError("raw hid must not have a report id")
|
||||
data = HID_DEVICE_DATA["RAW"]
|
||||
return hid.ReportDescriptor(
|
||||
description="RAW",
|
||||
report_descriptor=bytes(
|
||||
# Provide vendor-defined
|
||||
# This is a two-byte page value.
|
||||
(0x06, data.usage_page & 0xff, (data.usage_page >> 8) & 0xff, # Usage Page (Vendor 0xFFAF "Adafruit"),
|
||||
0x09, data.usage, # 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
|
||||
)))
|
||||
|
||||
# Function to call for each kind of HID descriptor.
|
||||
REPORT_DESCRIPTOR_FUNCTIONS = {
|
||||
"KEYBOARD" : keyboard_hid_descriptor,
|
||||
"MOUSE" : mouse_hid_descriptor,
|
||||
"CONSUMER" : consumer_hid_descriptor,
|
||||
"SYS_CONTROL" : sys_control_hid_descriptor,
|
||||
"GAMEPAD" : gamepad_hid_descriptor,
|
||||
"DIGITIZER" : digitizer_hid_descriptor,
|
||||
"XAC_COMPATIBLE_GAMEPAD" : xac_compatible_gamepad_hid_descriptor,
|
||||
"RAW" : raw_hid_descriptor,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue