NicoHood/HID

Keyboard not recognized at boot / BIOS

NicoHood opened this issue · 57 comments

The keyboard has to be a special boot keyboard with a standard descriptor. I heard it is possible with Teensy. More information can be found in the official USB docs.

http://www.usb.org/developers/hidpage/HID1_11.pdf
Seite 89 im PDF, 79 auf dem Blatt. Geht hier um Boot compatible HID devices.
Mit USB kann man ein Keyboard auf verschiedene Arten beschreiben. Standardmäßig 6 Modifier (strg, alt), 1 reserved und 6 keys. Das nutzt auch der Arduino. 

Auf seite 85/75 steht auch etwas feines. Das USB Gerät muss einen Boot Modus unterstützen, bzw sich als solches ausweisen.
Desweiteren steht hier, dass es mit dem Teensy wohl gehen sollte:
http://stackoverflow.com/questions/12682429/generic-keyboard-emulation-using-arduino-leonardo 

Hey Nico,

Have a look at Appendix E of the hid1_11 pdf you've linked to, there's an example:

The sample device is a low-speed 105-key keyboard with an integrated pointing
device. This device could be built using just one interface. However, two are used
in this example so the device can support the boot protocol. As a result there are
two Interface, Endpoint, HID and Report descriptors for this device.

Sure, if I ever have time to do that. I didnt even had time to review your PR. I just add issues if things like that come to my mind. I also did not translate my german notes I wrote someone as email.

As always: If you have a fix, open a PR.

Haha, stupid 24 hour days ;-)

I have to admit that I am working on the IRLremote instead :D totally worth it. Fixes will come, sooner or later.

bam80 commented

The feature would be very great!
Hope you will have time for this @NicoHood
Thanks for your work

Does the teensy work at boot? has anyone tested this? I dont know what is required for a boot keyboard. If the teensy works at boot we could try to search for the difference in the code and fix it.

The teensy keyboard is currently in the dev repo, but I dont think this works like this. I think the hid interface descriptor will be different then.

bam80 commented

In the Teensy USB Keyboard example it's clearly said:
"This code also supports the keyboard "boot protocol" ":
https://www.pjrc.com/teensy/usb_keyboard.html

I don't have Teensy to check it though

http://community.silabs.com/t5/8-bit-MCU/USB-HID-class-Difference-between-report-protocol-and-boot/td-p/78797

I do not think that this will work with our current setup. But it should be possible to implement this. It requires a single HID Interface with just a keyboard and with no report ID. This differs from the current implementation. It would require a new endpoint to be used and some API changes. Those changes are similar to what would be needed for raw HID + The interface descriptor mentioned in the link above.

http://www.avrfreaks.net/forum/avr-all-firmware-usb-and-pc-bootbios
https://github.com/PaulStoffregen/cores/blob/master/teensy3/usb_desc.c#L572-L574
www.usb.org/developers/hidpage/HID1_11.pdf
Page 59 and 62

Got it working under my Bios. Feel free to test it. You need to install the latest dev version of HID Project and the patched IDE with .alinkage. See the wiki on installing instructions.

Then you need to outcomment this line in HID-Project.h to enable the boot keyboard API. Working for improved keyboard and Teensy Keyboard as well.

Booting took a bit longer than normal for me.

The keyboard will not work under the OS currently, only via BIOS. With further work this can also be accomplished.

Fix commit:
0e29749

@bam80 @RingoM Now enabled by default! There were a few bugs that now should be removed. Booting is fast now and it automatically switched between boot protocol and normal protocol.

You can deactivate this function now, if it causes problems. This was only tested under linux with a newer bios(UEFI). It could be possible that it does not work with older BIOS, because I did not implement every required function. Thats enough at least for my bios. If it doesnt work for you, let me know and I will patch it. Unless it works, I wont add more "useless" code.

The mouse wont be supported here. You can only have Mouse OR Keyboard. Or you need a 2nd interface which I will not implement since no bios needs a mouse at all if you are serious.
Mouse is also supported, but deactivated by default. My Bios doesnt support a mouse, I need help here.

3ed2577

bam80 commented

Thank you @NicoHood, it's awesome!
I've got my Arduino UNO recently and just need to get used to it. Then I'll try your patches definitely and report if they work.
Thank you again and keep up such a good work!

@NicoHood please how do I add the boot USB protocol to the arduino ide from dev 2.4 I cannot find any.zip files and I'm kind of new to this thank you for your time and effort on this matter

It is enabled by default. Just install the library as described in the wiki and use the keyboard API.

(maybe in further versions it will be disabled again, I need to have a look at this once again. RawHID caused this some problems).

@NicoHood thank you for the reply I'm not sure where to find the library as I can't see a folder in 2.4 code do I download and install 2.2 then add files I have read the wiki and do not u derstand what to do sorry to pester you

https://github.com/NicoHood/HID/tree/dev_2_4
on the right side click download .zip file.

And then read the wiki on how to install this zip file. the wiki will link to the arduino page. basically you open the ide, search for libraries and select install via zip file. Or you put the file manually in your arduino/libraries folder.

https://github.com/NicoHood/HID/wiki/Installation

Thank you for your help I've now Dow loaded the .zip and will install when
I am home will the boot protocol work with keboardpress. Keyboardrelease
and lastly what library do I have to #include to have the boot keyboard
function work I am very gratefull for the help also do you know if this
library works on Mac bootscreen? EFI for example?
On 25 Sep 2015 14:20, "Nico" notifications@github.com wrote:

https://github.com/NicoHood/HID/tree/dev_2_4
on the right side click download .zip file.

And then read the wiki on how to install this zip file. the wiki will link
to the arduino page. basically you open the ide, search for libraries and
select install via zip file. Or you put the file manually in your
arduino/libraries folder.


Reply to this email directly or view it on GitHub
#34 (comment).

Just include HID-Project.h and you can use the Keyboard API. Try the examples.

This is not a support forum, sorry. If you have further technical questions/bugs please write it here. Otherwise contact me via PGP mail: www.nicohood.de for instructions.

Ok I will try this thank you very much for the help I will email you if I
need further help thanks again
On 25 Sep 2015 15:16, "Nico" notifications@github.com wrote:

Just include HID-Project.h and you can use the Keyboard API. Try the
examples.

This is not a support forum, sorry. If you have further technical
questions/bugs please write it here. Otherwise contact me via PGP mail:
www.nicohood.de for instructions.


Reply to this email directly or view it on GitHub
#34 (comment).

Ignore this...
screenshot from 2015-10-09 19 01 35

Current dev version requires this PR:
arduino/Arduino#3948

A real bootkeyboard is now implemented. Multireport Keyboard is still supported, but not as boot compatible. I wanted to a) keep it simple, and b) to the official specs. Everything else would just work half of the time.

Please test the BootKeyboard sketch. For me the Arduino detects the boot mode (led lights) but not when starting back the OS. Not sure if this is a feature/ intended of linux or just a lock of the HID implementation. Because the idle mode and getreport and getprotocol is not supported yet which normally is essential to work as bios. However it works more or less. No further testing has been done. I also dont need this feature myself so I dont really care much more if noone is willing to test.

Mouse needs further testing. At the moment it leaves out the wheel data in bios mode. However it does not recognize when it comes back to report mode (for keyboard at least). This means after a reboot the mouse (wheel) might not work at all.

bam80 commented

Hi Nico, you said:

it automatically switched between boot protocol and normal protocol

What did you mean here?
Is it mean that I can always use BootKeyboard class and it will switch internally between normal Keyboard and Bootkeyboard?

This was for the implementation before.

There is a variable called "protocol" in the BootKeyboard class. This indicated if the USB Keyboard is in bios mode or not. However it does currently not reset back to normal mode (currently). This is no problem now, because the report is always the same anyways. Before where i mashed up all other devices as well (consumer etc inside a multi report) this would have caused problems.

I think I need to reset the variable on reenumeration. Then people can detect when they are in bios mode or even if a pc reboots or so. However for the functionality NOW it doesnt matter anymore.

Clearer? Sorry if thats all mashed up. When the time is ready i try to make the wiki as clear as i can.

bam80 commented

Thank you but it isn't too clearer actually.
If "protocol" variable does currently not reset back to normal mode, how could I know then what class to use: BootKeyboard or Keyboard? As I understand I must choose the right one to make keyboard work in current environment.
Could you update BootKeyboard sketch so that is work both in bios mode and OS mode, or it's impossible with current implementation?

Keyboard has no bios compatiblity.

BootKeyboard has. Bootkeyboard detects when the usb host changes to bios/boot mode. However there is no actual difference in sending the reports to the host, so that information is useless somehow. However the proper implementation would be to know the state (bios or not) because the idea behind this is to implement a whole different device after bios finished (such as an nkro keyboard).

The current sketch works in both modes, it always acts the same. It detects if the host switches to bios mode but not back (at last for linux, linux seems to not send a signal). The detection can be made visible via the led. But as said it doesnt switch back. But its just a variable, the keyboard will continue to work anyways.

Maybe you should look at the bootkeyboard source if its still unclear. Hm...

This changes the protocol variable (which is almost useless but should indicate the device to change to pure bios mode if it uses other stuff in non bios mode). However this only works from report -> bios mode and not back (yet).

protocol = setup.wValueL;

bam80 commented

Ah, this is what I've asked before: if I could use BootKeyboard class all the way for now.
Just didn't catch it from your previous response, thank you.

Renewed the whole Keyboard API. I havent tested the delta between the new version but it should possibly be smaller. In any case its more clear now and should work better.

The main reason why I did this is that you cannot press all keys via write() before (like volume up/down). Instead of inputting a 2 byte value I just improved it the correct way.

AddKeycode etc is now just renamed, the option is still there.

Feedback appreciated. More Key definitions will follow. Consumer Keys and System key support will follow (yes for keyboard, in the same report). But only for linux, because windows sucks. Meaning you can integrate 3 device functions into a single device =) This is especially useful for u2 Uno devices combined with a raspi for example. But it also gives less API overhead for new devices and their descriptors.
1a676a2

Closing this, as it is implemented now. If it doesnt work, let me know.

Doesn't seem to be working for me. I think I need boot mode to work with a KVM I have. Testing the same code on a Windows 7 or Linux machine works, the same machine in BIOS or via KVM doesn't.
Here's the test code I was testing:

#include "HID-Project.h"

void setup() {
  // put your setup code here, to run once:
  delay(12000);
  BootKeyboard.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
  BootKeyboard.write(KEY_DOWN_ARROW);
  delay(1000);
  BootKeyboard.write(KEY_UP_ARROW);
  delay(1000);

}

I also tried BootKeyboard.press/release too but to no avail.

12 second delay? Is it not too long delay? Excuse my ignorance but why do
you need a so long pause? During that time the keyboard will be not
recognized and that could be the cause.
El dia 15/03/2016 4:22, "justinj0305" notifications@github.com va
escriure:

Doesn't seem to be working for me. I think I need boot mode to work with a
KVM I have. Testing the same code on a Windows 7 or Linux machine works,
the same machine in BIOS mode doesn't.
Here's the test code I was trying:
`
#include "HID-Project.h"

void setup() {
// put your setup code here, to run once:
delay(12000);
BootKeyboard.begin();
}

void loop() {
// put your main code here, to run repeatedly:
BootKeyboard.write(KEY_DOWN_ARROW);
delay(1000);
BootKeyboard.write(KEY_UP_ARROW);
delay(1000);

}'
I also tried BootKeyboard.press/release too but to no avail.


You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
#34 (comment)

It has a 12 second delay for 2 reasons:

  1. It gives me a good period of time before the sketch starts to reprogram the board in case something doesn't work as expected and tries to stop me reprogramming.
  2. Allows the PC connected to the KVM to start as there's a delay in my situation between the KVM powering on and the PC powering on of about 8 seconds.
    I am waiting for the 12 seconds each time and not being impatient to see if the sketch will work.

The delay does not cause any trouble. The HID device will enumerate instantly, actually on a leonardo the begin is not essentially required in all cases.

Bit i am not sure what this up and down should do. Does your bios support usb devices in general? I once had a user that was using a ps/2 keyboard. And usb devices in general did not work. Also does it work when the OS is bootet?

It happened to me to have problems with an usb keyboard when another ps/2
keyboard was connected at same time. Do you have other keyboard connected
to the computer?
El dia 15/03/2016 17:30, "Nico" notifications@github.com va escriure:

The delay does not cause any trouble. The HID device will enumerate
instantly, actually on a leonardo the begin is not essentially required in
all cases.

Bit i am not sure what this up and down should do. Does your bios support
usb devices in general? I once had a user that was using a ps/2 keyboard.
And usb devices in general did not work.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub:
#34 (comment)

The up and down is just a test in the PC BIOS I had sitting next to me so I could see if it was working without taking it to the KVM (Different location) each time. The PC only has USB ports on it and the USB keyboard attached works fine in BIOS and the sketch works fine when the PC has booted. The LED doesn't light in the BootKeyboard example sketch, so I'm wondering if it's not going into boot mode for some reason? I've tried it on 2 different PCs (In BIOS) as well as the KVM and have the same problem.

Can you please try to: plug in the arduino when the bios is loading. Like a normal boot, not a reboot. And then also test a reboot. Cause if the usb state is changing a lot (reboots) the arduino could possibly get confused and fail.

But actually I have no idea whats going on. I'd have to debug this and get such a PC/bios myself. And to be honest I currently have not the time to debug it. You may want to contact me on tox and kindly ask if i have time to help you in chat.

Hi,
I've just double checked it, running purely on the example BootKeyboard sketch (Just changing KEY_ENTER to '1' so I could see if it was typing) and when plugged in during BIOS, or when powering on from scratch or rebooting the LED does not light indicating it's in boot mode. Shorting Pin2>GND flashes the TX once (As per my previous sketches), does not send any keystrokes and does not attempt to send again. When plugging into a running machine the LED does not light (As expected) and shorting Pin2>GND enters a string of 1's. Is there any way to force the sketch into boot mode? I'm willing to help diagnose the issue (I have another micro to use when this one is in deployment), but in this circumstance I just need a quick fix and keeping the Arduino in boot mode should be that quick fix.

I dont think that this will change much. You can set it here:
https://github.com/NicoHood/HID/blob/master/src/SingleReport/BootKeyboard.cpp#L102

The definition is in the pluggable hid core (of the ide) i think. To really debug this we need to a) read the usb specs about boot compatible devices again (not all required functions are implemented). And b) we need to add debug output to see what is going on. What does the host request etc (with serial1). This is complex.

Well it does force it into boot mode (LED on) when connected to a running computer. The same computer in BIOS does not seem to be enumerating it as the LED fails to light.

you can add a blink without delay inside the loop for another led/pin.
If it does not blink then the sketch crashed. Or it hangs in an interrupt.
It would be nice to know what happens if you then boot the OS.

Also the bios could have problems with the 500ma spec. You might want to change that (somewhere in the arduino usb core, usbdesc.h i think).

As I said, contact me in tox for faster support (tomorrow again)

Added a blink code in and in BIOS the blinking continues so the sketch isn't crashing. The TX light still flashes once only after shorting and that's all.
I've added you to Tox but with timezone difference it might be a bit hard.

@NicoHood : I am not sure still you are in track of this issue. Hopefully you are. I am using learnado with HID-Project 2.4.4. I don't have any issues with either BIOS or OS.
My problem while emulating keyboard for booting to BIOS from scratch or after a reboot. Something similar as follows.

void setup() {
BootKeyboard.begin();
}

void loop() {

BootKeyboard.write(KeyboardKeycode(KEY_F2));
delay(200);
}
Initially I thought it would be the power problem in the USB port during the early boot. So I tried connecting an external power for my Learnado. Still it is not sending the F2 key strokes during the initial system boot. Any possible clues I can look into? Thanks

So you are saying that you can use left/right inside the bios to switch pages, but are unable to enter setup? Have you verified the f2 key works properly when inside the os?

I'd try to press and release the key with some delay in between each press.

Thanks for looking into this.

So you are saying that you can use left/right inside the bios to switch pages, but are unable to enter setup?

Yes. That is correct. (f3, F4 every keys are working inside BIOS)

Have you verified the f2 key works properly when inside the OS?

Yes. F2 is working. I have verified with a KB tester application.

Today I did some more experiment after I paused in the pre-boot screen. (Attached the screen).
I have configured a button in my sketch which when pressed will send back a serial data to serial1. When I read the serial data while in the pre-boot screen, I always get "NON_BOOT_PROTOCOL". Where as I get HID_BOOT_PROTOCOL after I boot to BIOS by pressing F2 with a REAL keyboard.

preboot_screen

void loop() {
int buttonState = digitalRead(buttonPin);
if (buttonState == HIGH)
{
if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL)
Serial1.write("HID_BOOT_PROTOCOL\n");
else
Serial1.write("NON_BOOT_PROTOCOL\n");
}

Thanks.

Does the keyboard work after you entered setup?
The bios possibly does not like your arduino.

Does the keyboard work after you entered setup?

I hope you mean setup(). - Yes F2 works in setup().

The bios possibly does not like your arduino.

My problem is ONLY with the pre-boot screen. I tried with a another arduino -learnado. Still no hope :(

I mean once it reaches BIOS it returns the protocol as HID_BOOT_PROTOCOL. But in the early/pre boot it is recognizing arduino as normal (HID_REPORT_PROTOCOL).

no i mean if you tried the arduino in the bios setup, after you pressed f2. Check if the arrow keys work etc. If not, I dont know whats the problem of your bios. I've tested the fujitsu laptop bios which is based on infineon. Which bios vendor is your bios from? American megatrends? phoenix? infineon? how old is your pc? are you booting with csm enabled or disabled?

I currently have no hardware to even retest on my own system, but it must be something in between bios and keyboard.

Sounds a lot like the issue I was having, I tried hours and hours to get it to work and couldn't. In the end I tried a teensy and it's built in keyboard function and it worked perfectly. I wish I had of tried it sooner!
From memory I had to downgrade the teensy keyboard library to the older version, I can't remember if that was for an additional function that was obsolete in the latest version or to do with the boot protocol mode being removed or changed in the latest version. So if you want to save yourself a heap of time, give a teensy a try.

Some old version - phoenix. I tried with few other machines too with infineon. Still i could see the issue.

I have another observation, hope it will narrow down to the possible root-cause.

a) If I boot my machine from a complete shutdown - F2 or any other keys are working in the PRE-BOOT screen.

b) But a reboot from OS/BIOS - The F2/any other keys are not working in PRE-BOOT screen.

So I believe the problem is with the reboot procedure. Appreciate if you can give me some clues or the area in the library I can have a try. Thanks

Another observation in LEDs

Booting from shutdown - Rx LED blinks twice
Booting from a reboot - Rx LED blinks only once

Thanks

Is it a cold or warm reboot? A cold reboot turns off usb power for a short time.
Its definitely and arduino bug, maybe the device does not reset properly. I currently have no idea how to fix it, I'd need to debug it. :/

Hallo NicoHood! I have pretty much the same problem, although it doesn't matter if I reboot cold/warm or from a complete shutdown (Stromlos). I have a couple of HP-Bios to set up (130 to be exact).

I tried it with your example code, since I just wanted to test possibilities... KEY_ENTER/_F10/_DOWN_ARROW are all not responding. TX blinks once when Pin 2 is shorted. Doesn't blink again when 2 is kept shorted. PinLED never turns on. Behavior in MacOS/Windows as programmed/expected. Any Ideas?

/*
  Copyright (c) 2014-2015 NicoHood
  See the readme for credit to other people.
  BootKeyboard example
  Shows that keyboard works even in bios.
  Led indicats if we are in bios.
  See HID Project documentation for more information.
  https://github.com/NicoHood/HID/wiki/Keyboard-API#boot-keyboard
*/

#include "HID-Project.h"

const int pinLed = LED_BUILTIN;
const int pinButton = 2;

void setup() {
  pinMode(pinLed, OUTPUT);
  pinMode(pinButton, INPUT_PULLUP);

  // Sends a clean report to the host. This is important on any Arduino type.
  BootKeyboard.begin();
}


void loop() {
  // Light led if keyboard uses the boot protocol (normally while in bios)
  // Keep in mind that on a 16u2 and Arduino Micro HIGH and LOW for TX/RX Leds are inverted.
  if (BootKeyboard.getProtocol() == HID_BOOT_PROTOCOL)
    digitalWrite(pinLed, HIGH);
  else
    digitalWrite(pinLed, LOW);

  // Trigger caps lock manually via button
  if (!digitalRead(pinButton)) {
    BootKeyboard.write(KEY_DOWN_ARROW);

    // Simple debounce
    delay(300);
  }
}

I never tried forcing it in HID_BOOT_PROTOCOL...

As an alternative you could try LUFA. I built an API around that, please checkout the example here:
https://github.com/NicoHood/avr/blob/master/lib/USB_KEYBOARD/examples/keyboard/keyboard.cpp

The code is provided "as is" I did not create any docs yet. Feel free to check it out, but you have to figure out how everything is done yourself.

hi BenediktRPI ! Reading about your post to use an arduino to set the Bios. Which arduino do you use ? Best regards. Wilbo

To everyone who still has problems with keyboard in bios:
Checkout this comment #305 (comment) where someone is happy to fix the issue, if he can get his hands on a not working device. Maybe someone of you can help here?

You can also try this:
#225 (comment)