Open bmosley opened 6 years ago
The HID keyboard currently presented by CircuitPython is not a boot device keyboard, with its own endpoint(s), which is what the Mac Open Firmware ("BIOS") and regular PC BIOSes expect. It's part of a composite HID device that includes mouse, multimedia keys, and a gamepad. This was to save endpoints for other purposes.
We've had one other person who wants a boot-compatible keyboard and we're thinking about that - we have to count up the available endpoints and what we want for the future (e.g. USB MIDI). Also, in the long run, we are thinking about how to provide user-configurable HID devices.
Thanks. I completely understand and figured that this wasn’t currently supported but thought filing a bug was the best way to ask/suggest implementation of the feature. Is there any roadmap for future HID support? And MIDI sounds quite awesome too :)
No specific timeline with dates, but your request is noted and it's a vote!
wonderful, thank you!
This is marked as closed - was it done? If the fix was the same that I used in the XBox stuff which requires a custom build, is there any example of making this work?
The fix requires a new descriptor and its own endpoint, at least. I'm not sure what else. Perhaps it could be added as a compile option for the descriptor generating Python script, and then later as a boot.py
. We can reopen this as long term.
I understand this not being in the core CP, but I do think it should remain open until there's some way to do it. I don't mind having to do a custom build (like we do for the XBox Adaptive Controller), but we have found lots of folks who really want to use devices through KVMs, and the composite devices don't work through them. Here's our current pressing issue: https://www.facebook.com/groups/ATMakers/permalink/815702142174560/
BTW, thanks Dan
Do you need a bootmode mouse HID capability too?
Um... I don't think so? I think the reason this is needed is that the KVM listens in on the keyboard commands and relays them. That lets it watch for trigger keystrokes ('scroll-scroll-enter') to jump between devices. We don't kneed the triggers, but the stupid KVM doesn't know what to do with composite devices. It might be that we just need a non-composite device w/no other profiles. Or only a single device (no serial/mass storage?)
I just know it is a known issue that "complicated" keyboards (even those with media keys) don't work.
Here is another vote for it :) By now i've tried arduino, vusb, teensy, and pico pi and only teensy seems to have a full featured keyboard that works in BIOS and KVM devices. @ATMakersBill The teensy itself is also a composite device, having keyboard, mouse, gamepad, serial and still works fine with a KVM. So my best guess is, that it only depends on a correct implementation of the boot keyboard. @dhalbert As far as i know, a boot keyboard needs its own descriptor and endpoint and on top of it, it has two additional functions which are described in the usb docs.
We are currently out of endpoints on most boards with 8 endpoints, having added a second CDC. If someone would like to contribute boot keyboard and mouse descriptors and compile flags, we'd be happy to include them. We would not turn them on normally, since they would remove having MIDI or the second CDC available by default.
This is another indicator for user-configurable USB and USB HID descriptors. However, we are pretty much out of space on the smallest builds, and don't have room to add the code for this. It would have to be on something other than the non-Express SAMD21's.
@dhalbert boot keyboard doesn't need to be on its own interface and/or take extra endpoint. It can be used with existing HID device. Basically the HID device has 2 mode (or protocol): boot mode, and report mode (default).
Most bios will always start with SET_PROTOCOL = BOOT upon enumeration. We only need to handle the callback, set the mode correctly then skip all other report except keyboard. I will update my hid_composite example in my repo so that you could have a clear example to follow in circuitpython later on. Will tag you on the modification later on, may try to submit PR myself as well. Though for the flash size, it may indeed increase a bit of space.
Aha, great, thanks! I will await your example. It would be more complicated to add a boot mouse, but at least having a keyboard will satisfy many needs.
each interface can only either support boot keyboard or mouse, to support both, we need an extra interface though.
But when in boot mode, you don't need MSC and CDC and MIDI, no?
But when in boot mode, you don't need MSC and CDC and MIDI, no?
Good point - it's more a question of having code space on the smallest builds to switch back and forth.
@hathach Are you sure about the not needed extra endpoint? I tried a few times getting this to work with the arduino environment and to have an idea where the issue is i used this tool https://www.thesycon.de/eng/usb_descriptordumper.shtml and a real keyboard always used an extra endpoint.
@dhalbert during my research i never found someone asking for a boot mouse. Most BIOSes are configured by keyboard and Hotkeys in KVMs are also done with a keyboard
I believe that BOOT mode is missing n-key rollover so we'll want to switch between the two if we can.
@bitboy85 can you post the descriptor of your real keyboard here along with its hid descriptor for the reference. If it is too long, you could move it to a gist and have a link here.
@hathach https://gist.github.com/bitboy85/543b34a9505280ead8103a4d4d9cab26 2 different keyboards, no mixed device.
I remember a doc that says, a boot keyboard endpoint requires a packet size of 8 byte.
As additional reference: https://www.usb.org/sites/default/files/hid1_11.pdf page 50-54: GET_PROTOCOL and SET_PROTOCOL request for boot device page 62: Keyboard implementation page 74: Boot keyboard requirements
thanks for the descriptor, and the reference. I just go through the hid 1.1 briefly again, and didn't see any requirement for boot protocol to has its own interface. The consumer keyboard has the luxury of additional endpoint to implement it in that way. Though we will see how this works out.
@obra may know what we need to be a boot keyboard too.
I also need a keyboard that works at boot time. I'm currently working on a software for a DIY split keyboard with each part having a Raspberry Pi Pico in it. All features I planned are now implemented and I will share the code on GitHub in the comming weeks. I just realized, that it does not work at boot time (at least not under macOS). I hope that this issue can be fixed, because otherwise building fully fledged custom keyboards is out of reach by using CircuitPython.
You want to have a look at the descriptors we use for https://github.com/keyboardio/KeyboardioHID The idea is that you should offer up both a Boot Protocol descriptor and a bitmap descriptor.
On Thu, Mar 11, 2021, at 1:18 AM, akaenner wrote:
I also need a keyboard that works at boot time. I'm currently working on a software for a DIY split keyboard with each part having a Raspberry Pi Pico in it. All features I planned are now implemented and I will share the code on GitHub in the comming weeks. I just realized, that it does not work at boot time (at least not under macOS). I hope that this issue can be fixed, because otherwise building fully fledged custom keyboards is out of reach by using CircuitPython.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/adafruit/circuitpython/issues/1136#issuecomment-796591688, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAALC2AOHJ7R2B6YSWKGPZ3TDCDGTANCNFSM4FQ4LPWA.
As it is possible to config USB devices on a custom build, any hints where to start when trying to implement this? https://learn.adafruit.com/building-circuitpython/customizing-usb-devices
I've read some docs about the requirement.
I am starting to implement dynamic control over USB and USB HID descriptors right now. I may not get to boot keyboard immediately, but it will be possible. So I would say not to start on it yourself right now, because the underlying code is going to change a lot in the near future.
All that we really need is a separate USB descriptor (separate endpoint) with an appropriate USB HID descriptor. Almost any commercial keyboard does this and we can vet our choices against the descriptors from such keyboards.
interested in the request. i have a macropad that works with circuitpython, which i would like to use to access to bios. here the thing https://learn.adafruit.com/itsybitsy-keybow-mechanical-keypad?view=all
I am not implementing boot keyboard in the first pass of dynamic USB descriptors, which I am working on right now. But internally the implementation is flexible enough to add later. Once I get the first version working it can be revisited.
I am adding the hid_boot_interface
example here if anyone is interested to test https://github.com/hathach/tinyusb/pull/1025 . I don't have any legacy bios PC to test with though. Therefore it may have an issue or two. For implementation it uses 1 interface for keyboard, and 1 for mouse. Per HID specs, device is default to report mode, Bios PC will send control request SET_PROTOCOL to change it to boot mode which cause this callback to invoked https://github.com/hathach/tinyusb/pull/1025/files#diff-197babc2310c6d123603f9f2df568b1c1f1857cee19037e747408f146a847d4fR170-R176
You could also use tud_hid_n_get_protocol()
to get the current mode and send construct the report accordingly.
report
mode: report is sent accordingly to descriptor like we are currently doing (can be composite)I am now working on this. I ran into an issue of BIOS's expecting the interface number to be 0 for the keyboard, and not handling non-zero values properly. See https://github.com/hathach/tinyusb/issues/1129. I can push the HID interface to position 0, but right now the Windows drivers package we have assumes the CDC is in position 0. I think I have a way of restructuring the drivers to handle that, though, by imitating what Windows 10 does for usbser.sys
. I'll test that it, which might considerably simplify the Windows 10 driver package as well.
I am now working on this. I ran into an issue of BIOS's expecting the interface number to be 0 for the keyboard, and not handling non-zero values properly. See hathach/tinyusb#1129. I can push the HID interface to position 0, but right now the Windows drivers package we have assumes the CDC is in position 0. I think I have a way of restructuring the drivers to handle that, though, by imitating what Windows 10 does for
usbser.sys
. I'll test that it, which might considerably simplify the Windows 7/8.1 driver package as well.
It turns out this does not work for Windows security policy reasons. See fuller writeups in https://github.com/adafruit/Adafruit_Windows_Drivers/issues/34 and https://github.com/hathach/tinyusb/issues/1129#issuecomment-940498866
I am going to put this on ice for now. As long as we continue to support Windows 7 and 8.1, we cannot move the Device Interface numbers around so that HID is Interface 0 instead of CDC. In the long run, it could be possible, but boot keyboard support may become less important. I have some BIOS examples that don't need boot keyboards anyway.
How difficult is it to create a branch of CircuitPython with the HID device at position 0?
I'm currently writing a documentation for my upcoming DIY keyboard. The firmware is based on CircuitPython and is much easier to use than others like QMK. Not being able to emulate a boot keyboard is of course a big show stopper. For example: under macOS you can not login without a boot keyboard if your hard disk is encrypted and most users encrypt their HD.
macOS may still work, I think the issue Dan mentioned above only happens with old PC bios ? And MAYBE we don't have to make HID as interface 0 in macOS bios
I can assure you that you cannot log into a Mac if the hard drive is encrypted because I sit in front of a Mac all day.
"The only wrinkle in a CircuitPython-based keyboard is not working well in boot phase: things like UEFI/BIOS settings, waking up from hybernation, or FileVault password typing in macOS. It is probably related to device enumeration: a CircuitPython board enumerates several USB virtual devices (storage, keyboard, mouse, serial) and UEFI expects keyboards to be keyboards only, or the keyboard should be the first enumeration."
Found here - scroll to the bottom: KMK87
These are exactly the same problems I currently have with my keyboard.
I can make HID always be interface #0 just by reordering some code. But it will cause problems on Windows 7 and 8.1, which expect CDC to be at interface #0.
I have a branch where I did this work. I can give you a test UF2. Tell me the board you need a build for. If you are used to building CircuitPython yourself, the branch is https://github.com/dhalbert/circuitpython/tree/hid-boot-protocol .
Then you'll try this: in boot.py
, turn off all other USB devices except HID. So something like:
# Normally, disable all devices except HID.
# But when booting, if a particular key is held down, don't hide CIRCUITPY and the REPL.
maintenance_mode = <some key pressed down>
if not maintenance_mode:
storage.disable_usb_drive()
usb_cdc.disable()
usb_midi.disable()
usb_hid.enable((your_keyboard_device,), boot_device=1 if not maintenance_mode else 0)
boot_device
is new in this branch. With the code above, and a build from the branch, HID should end up at interface #0, because no other devices will be put in the descriptor. The interface numbers are assigned sequentially in CircuitPython 7.0.0, so HID will be at #0. In 6.3.0 and earlier, they were given fixed assignments: CDC was always at #0, HID was at something else, etc.
(EDIT: boot_protocol
-> boot_device
)
How do you get a Mac into this boot state? I assume you hold down some keys when power-cycling. I would like to have another test besides an older BIOS or UEFI.
Thank you very much. I just managed to built your branch of CircuitPython. I will test it over the weekend.
With boot mode I simply mean: Boot the mac and try to login. A CircuitPython keyboard does not work at this point. It event does no work if the mac is in sleep mode and you try to wake it up with a CircuitPython keyboard. If you press a key in sleep mode, then the Mac does not wake up. But worse, the keyboard does not work after waking up. You then have to reconnect the keyboard or reset it. If you wake up the Mac and login by using a normal keyboard, the CircuitPython keyboard works.
Hi Dan,
I compiled your hid-boot-protocol branch and tested it with my keyboard but I'm sure I'm doing something wrong. Maybe you can help me. Here is the message in boot_out.txt:
Adafruit CircuitPython 5.0.0-alpha.0-11771-g13210d2cc-dirty on 2021-10-15; Raspberry Pi Pico with rp2040
Board ID:raspberry_pi_pico
boot.py output:
Traceback (most recent call last):
File "boot.py", line 41, in <module>
TypeError: extra keyword arguments given
Here is the code in line 41 in boot.py:
usb_hid.enable((usb_hid.Device.KEYBOARD,), boot_protocol=1 if not maintenance_mode else 0)
@akaenner Ah, sorry, I changed the name of the argument from boot_protocol
to boot_device
for clarity but didn't remember that. Use:
usb_hid.enable((usb_hid.Device.KEYBOARD,), boot_device=1 if not maintenance_mode else 0)
ok, here is the part of my boot.py which disables other devices and enables just the keyboard.
if not maintenance_mode:
storage.disable_usb_drive()
usb_cdc.disable()
usb_midi.disable()
usb_hid.enable((usb_hid.Device.KEYBOARD,), boot_device=1 if not maintenance_mode else 0)
The USB-Stick does not show up in the Finder and if I'm already logged in to the mac, the keyboard works. But the keyboard still does not work when I try to login on a mac with an encrypted HD.
Here is the output from lsusb -v (only the pico part)
Bus 020 Device 014: ID 239a:80f4
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x239a
idProduct 0x80f4
bcdDevice 1.00
iManufacturer 1 Raspberry Pi
iProduct 2 Pico
iSerial 3 E6609CB2D37A3F29
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 195
bNumInterfaces 5
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Association:
bLength 8
bDescriptorType 11
bFirstInterface 0
bInterfaceCount 2
bFunctionClass 2 Communications
bFunctionSubClass 2 Abstract (modem)
bFunctionProtocol 0 None
iFunction 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 2 Communications
bInterfaceSubClass 2 Abstract (modem)
bInterfaceProtocol 0 None
iInterface 4 CircuitPython CDC control
CDC Header:
bcdCDC 1.10
CDC Call Management:
bmCapabilities 0x01
call management
bDataInterface 1
CDC ACM:
bmCapabilities 0x02
line coding and serial state
CDC Union:
bMasterInterface 0
bSlaveInterface 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 16
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 10 CDC Data
bInterfaceSubClass 0 Unused
bInterfaceProtocol 0
iInterface 5 CircuitPython CDC data
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x02 EP 2 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 2
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 0 No Subclass
bInterfaceProtocol 0 None
iInterface 6 CircuitPython HID
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 156
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x83 EP 3 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 8
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 8
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 3
bAlternateSetting 0
bNumEndpoints 0
bInterfaceClass 1 Audio
bInterfaceSubClass 1 Control Device
bInterfaceProtocol 0
iInterface 8 CircuitPython Audio
AudioControl Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdADC 1.00
wTotalLength 9
bInCollection 1
baInterfaceNr( 0) 4
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 4
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 1 Audio
bInterfaceSubClass 3 MIDI Streaming
bInterfaceProtocol 0
iInterface 7 CircuitPython MIDI
MIDIStreaming Interface Descriptor:
bLength 7
bDescriptorType 36
bDescriptorSubtype 1 (HEADER)
bcdADC 1.00
wTotalLength 37
MIDIStreaming Interface Descriptor:
bLength 6
bDescriptorType 36
bDescriptorSubtype 2 (MIDI_IN_JACK)
bJackType 1 Embedded
bJackID 1
iJack 9 CircuitPython usb_midi.ports[0]
MIDIStreaming Interface Descriptor:
bLength 6
bDescriptorType 36
bDescriptorSubtype 2 (MIDI_IN_JACK)
bJackType 2 External
bJackID 2
iJack 0
MIDIStreaming Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (MIDI_OUT_JACK)
bJackType 1 Embedded
bJackID 3
bNrInputPins 1
baSourceID( 0) 2
BaSourcePin( 0) 1
iJack 10 CircuitPython usb_midi.ports[0]
MIDIStreaming Interface Descriptor:
bLength 9
bDescriptorType 36
bDescriptorSubtype 3 (MIDI_OUT_JACK)
bJackType 2 External
bJackID 4
bNrInputPins 1
baSourceID( 0) 1
BaSourcePin( 0) 1
iJack 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x04 EP 4 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
MIDIStreaming Endpoint Descriptor:
bLength 5
bDescriptorType 37
bDescriptorSubtype 1 (GENERAL)
bNumEmbMIDIJack 1
baAssocJackID( 0) 1
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x84 EP 4 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 0
MIDIStreaming Endpoint Descriptor:
bLength 5
bDescriptorType 37
bDescriptorSubtype 1 (GENERAL)
bNumEmbMIDIJack 1
baAssocJackID( 0) 3
Device Status: 0x0000
(Bus Powered)
MIDI should not be showing up; you are trying to turn it off in boot.py
. Check your boot_out.txt
to see if there are errors reported in boot.py
, or perhaps the "maintenance_mode" switch is being checked in a backwards way.
I forgot to import usb_cdc. Now the output from lsusb command for the Pico looks better:
Bus 020 Device 013: ID 239a:80f4
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 2.00
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 64
idVendor 0x239a
idProduct 0x80f4
bcdDevice 1.00
iManufacturer 1 Raspberry Pi
iProduct 2 Pico
iSerial 3 E6609CB2D37A3F29
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 41
bNumInterfaces 1
bConfigurationValue 1
iConfiguration 0
bmAttributes 0x80
(Bus Powered)
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 2
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 1 Keyboard
iInterface 4 CircuitPython HID
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.11
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 67
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 8
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x01 EP 1 OUT
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0040 1x 64 bytes
bInterval 8
Device Status: 0x0000
(Bus Powered)
Unfortunately, the keyboard still doesn't work with a Mac. I can not login to the desktop and it does not wake up from sleep. Here you can see the output from lsusb for my other keyboard (a TypeMatrix) which works fine. Maybe you can compare the two descriptions and maybe then you have an idea of what needs to be changed. For example: at the end of the TypeMatrix output there is the text "Remote Wakeup Enabled" which is not in the output for the Pico.
I am happy to test other versions if you like.
Bus 020 Device 007: ID 1e54:2030 TypeMatrix 2030 USB Keyboard
Device Descriptor:
bLength 18
bDescriptorType 1
bcdUSB 1.10
bDeviceClass 0 (Defined at Interface level)
bDeviceSubClass 0
bDeviceProtocol 0
bMaxPacketSize0 8
idVendor 0x1e54 TypeMatrix
idProduct 0x2030 2030 USB Keyboard
bcdDevice 1.50
iManufacturer 1 TypeMatrix.com
iProduct 2 USB Keyboard
iSerial 0
bNumConfigurations 1
Configuration Descriptor:
bLength 9
bDescriptorType 2
wTotalLength 59
bNumInterfaces 2
bConfigurationValue 1
iConfiguration 0
bmAttributes 0xa0
(Bus Powered)
Remote Wakeup
MaxPower 100mA
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 1 Keyboard
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 64
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 10
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 1
bAlternateSetting 0
bNumEndpoints 1
bInterfaceClass 3 Human Interface Device
bInterfaceSubClass 1 Boot Interface Subclass
bInterfaceProtocol 0 None
iInterface 0
HID Device Descriptor:
bLength 9
bDescriptorType 33
bcdHID 1.10
bCountryCode 0 Not supported
bNumDescriptors 1
bDescriptorType 34 Report
wDescriptorLength 94
Report Descriptors:
** UNAVAILABLE **
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 10
Device Status: 0x0002
(Bus Powered)
Remote Wakeup Enabled
The wakeup problem is different than boot keyboard, and I need to work on that separately. If you plug in the RP2040 when the password prompt appears, does it still not work?
My Macs are not set up for this disk encryption, but there may be other boot-time choices (option-shift-whatever, etc.) that I can use to test without having to set one up for encryption. Do you know of some boot-time entry screens similar to the password request?
If you plug in the RP2040 when the password prompt appears, does it still not work?
No, this also does not work.
Do you know of some boot-time entry screens similar to the password request?
I don"t know how to reproduce this behaviour without an encrypted HD. But you can encrypt your HD at any time. It just takes some time to finish. See System Preferences > Security & Privacy > File Vault
@akaenner I have a simpler test of this, which is to start the Mac while holding down the "D" key, to get it into diagnostics mode. Then it lists the available wifi networks (wait for the spinning to stop), and an external keyboard's up and down arrow keys can go up and down the list of networks.
The "D" key is for Intel Macs. For M1 ("Apple silicon"), you just keep holding down the power button to get into a startup menu. https://support.apple.com/en-us/HT202731
Anyway, what I see on an Intel MacBook is that a MacroPad set up for boot keyboard and sending up and down arrows does not work, but a vanilla Dell external keyboard does. So this gives me something to work toward.
I just wanted to tell that I'm also looking forward to a better HID support. I'm on Windows and often after booting I need to un- and re-plug my Raspberry Pi Pico based keyboard first. (No password or keypress required for booting into Windows desktop.)
Also, usage with the KVM switch is not robust (the KVM is built into my monitor). Thanks for your work on this issue.
So currently the default firmware has cdc hard coded to interface 0 because the windows driver is also hard coded to interface 0. Is this a requirement by windows or could it also use a hardcoded interface number 1? (having 0 as unused/reserved for boot keyboard).
What about making it the default firmware where the user can choose the interface number?
Fixing CDC to interface is a requirement due to the limitations of third-party drivers in Windows. A third-party cannot write a "class driver", which identifies the device by class and subclass. That is reserved for system-supplied drivers. I can only identify the device by PID/VID, and (optionally) interface number. If I scramble the interface numbers, then it can assign the wrong driver (e.g. MSC for CDC). I have also seen that at least some versions of Windows expected CDC on interface 0 always (incorrectly). In addition, at least some OS's expect the interface numbers to be sequential, so I assign them sequentially. And it would be a big bang to move CDC away from interface 0, and could cause trouble for current Windows users.
Windows driver assignments can get confused if the same device starts presenting different devices on varying interface numbers.
We don't need the Adafruit drivers package on Windows 10, because it has a built-in class driver for CDC. So if we stopped supporting Windows 7 and 8.1, the problem would go away.
Boot keyboard support on interface 0 is now merged into the main
branch on CircuitPython, and will be in CircuitPython 7.1.0. Right now the order of the interfaces is fixed, so we are just turning off enough to bring HID to the top as interface 0. Since most keyboard projects are standalone things, and you don't want CIRCUITPY and CDC to be present anyway, especially in the case of a boot keyboard, this didn't seem like a serious limitation.
The boot keyboard suipport works on a few PC BIOS's I tested it on. It does not work on Mac yet, so I am leaving this issue open. I don't understand why, and the errors appear to be below the level of the descriptors: I am seeing unusual USB transmissions, so the issue may be at the USB protocol level.
I started putting together a project with my Trinket M0 to use for switching boot volumes on macOS. My goal was to have it select a volume by keystrokes. However, it doesn't seem to be working.Working correctly in macOS once booted
Using the same code for HID keyboard: