Author Topic: Digispark as HID Keyboard on preboot doesnt work  (Read 16767 times)

Julian

  • Newbie
  • *
  • Posts: 7
Digispark as HID Keyboard on preboot doesnt work
« on: September 17, 2013, 01:56:26 am »

Hi all,


I'm trying to use a Digiskpark as a keyboard (code below). It works like a champ when a OS is loaded but does not work on preboot (UEFI apps, BIOS, grub menu, etc). If DigiKeyboard library is based on a partial port of VUSB proyect, is it possible that extending the lib would give full support on preboot?  Any hint?


Thanks,


Julian




Code: [Select]
#include "DigiKeyboard.h"




// Delay between keystrokes
#define KEYSTROKE_DELAY 1000


// Blinking control
int iterationCounter = 0;
#define BLINK_RATE 2


void setup() {
 
  // initialize the digital pin as an output.
  pinMode(0, OUTPUT); //LED on Model B
  pinMode(1, OUTPUT); //LED on Model A     
 
  // don't need to set anything up to use DigiKeyboard
}


void loop() {
 
  DigiKeyboard.update();


  if (iterationCounter % BLINK_RATE == 0)
      turnLedOn ();


  // this is generally not necessary but with some older systems it seems to
  // prevent missing the first character after a delay:
  DigiKeyboard.sendKeyStroke(0);


  // It's better to use DigiKeyboard.delay() over the regular Arduino delay()
  // if doing keyboard stuff because it keeps talking to the computer to make
  // sure the computer knows the keyboard is alive and connected
  DigiKeyboard.delay(KEYSTROKE_DELAY);


 
  // UP
  DigiKeyboard.sendKeyStroke(KEY_ARROW_UP);
  DigiKeyboard.delay(KEYSTROKE_DELAY); 
 
  // DOWN
  DigiKeyboard.sendKeyStroke(KEY_ARROW_DOWN);
  DigiKeyboard.delay(KEYSTROKE_DELAY);   
 


  if (iterationCounter % BLINK_RATE == 0)
      turnLedOff (); 
 
  iterationCounter++;
}


void turnLedOn ()
{
    digitalWrite(0, HIGH);   // turn the LED on (HIGH is the voltage level)
    digitalWrite(1, HIGH);
}


void turnLedOff ()
{
    digitalWrite(0, LOW);    // turn the LED off by making the voltage LOW
    digitalWrite(1, LOW);
}



« Last Edit: September 17, 2013, 02:25:11 am by Julian »

gogol

  • Sr. Member
  • ****
  • Posts: 398
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #1 on: September 18, 2013, 01:08:14 am »
I think, that this is also hardware related.
My workstation for example accepts during preboot only one USB keyboard.
First I would check to replace the working keyboard with the digisparc during preboot.  And I would connect the digisparc on the very same USB port.

What happens in that case?

regards

  gogol

digistump

  • Administrator
  • Hero Member
  • *****
  • Posts: 1465
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #2 on: September 18, 2013, 10:29:53 pm »
It is very likely related to the start routine of the USB code - which is based on v-usb - a search for similar issues with v-usb might turn up some good hints...

Julian

  • Newbie
  • *
  • Posts: 7
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #3 on: September 19, 2013, 02:16:11 am »

Thank you for your responses!
According to the HID spec I need add the boot protocol:
Quote
Appendix B: Boot Interface
Descriptors
The HID Subclass 1 defines two descriptors for Boot Devices. Devices may
append additional data to these boot reports, but the first 8 bytes of keyboard
reports and the first 3 bytes of mouse reports must conform to the format defined
by the Boot Report descriptor in order for the data to be correctly interpreted by
the BIOS. The report may not exceed 8 bytes in length. The BIOS will ignore any
extensions to reports. These descriptors describe reports that the BIOS expects to
see. However, since the BIOS does not actually read the Report descriptors, these
descriptors do not have to be hard-coded into the device if an alternative report
descriptor is provided. Instead, descriptors that describe the device reports in a
USB-aware operating system should be included (these may or may not be the
same). When the HID class driver is loaded, it will issue a Change Protocol,
changing from the boot protocol to the report protocol after reading the boot
interface’s Report descriptor.
In the DigisparkKeyboard header I see:
Code: [Select]
/* We use a simplifed keyboard report descriptor which does not support the
 * boot protocol. We don't allow setting status LEDs and but we do allow
 * simultaneous key presses.
 * The report descriptor has been created with usb.org's "HID Descriptor Tool"
 * which can be downloaded from http://www.usb.org/developers/hidpage/.
 * Redundant entries (such as LOGICAL_MINIMUM and USAGE_PAGE) have been omitted
 * for the second INPUT item.
 */


So I'm going to see if I can make it work!


Regards,


Julian

digistump

  • Administrator
  • Hero Member
  • *****
  • Posts: 1465
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #4 on: September 19, 2013, 10:57:40 am »
Please let us know if you make some progress on it!

Julian

  • Newbie
  • *
  • Posts: 7
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #5 on: September 23, 2013, 06:41:59 am »

Hi again,


Turns out that no great changes needed:


1. Mark device as boot device in configuration descriptor:


      #define USB_CFG_DEVICE_CLASS        0     /* set to 0 if deferred to interface */
      #define USB_CFG_DEVICE_SUBCLASS     0
      /* See USB specification if you want to conform to an existing device class.
       * Class 0xff is "vendor specific".
       */
      #define USB_CFG_INTERFACE_CLASS     3   /* define class here if not at device level */
      #define USB_CFG_INTERFACE_SUBCLASS  1
      #define USB_CFG_INTERFACE_PROTOCOL  1


2. Use a HID report descriptor indicating boot support (see http://www.usb.org/developers/devclass_docs/HID1_11.pdf , Appendix B: Boot Interface
Descriptors) (Update USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH to the new size, mine is 63 bytes):


   PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
      0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
      0x09, 0x06,                    // USAGE (Keyboard)
      0xa1, 0x01,                    // COLLECTION (Application)
      0x75, 0x01,                    //   REPORT_SIZE (1)
      0x95, 0x08,                    //   REPORT_COUNT (8)
      0x05, 0x07,                    //   USAGE_PAGE (Keyboard)(Key Codes)
      0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)(224)
      0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)(231)
      0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
      0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
      0x81, 0x02,                    //   INPUT (Data,Var,Abs) ; Modifier byte
      0x95, 0x01,                    //   REPORT_COUNT (1)
      0x75, 0x08,                    //   REPORT_SIZE (8)
      0x81, 0x03,                    //   INPUT (Cnst,Var,Abs) ; Reserved byte
      0x95, 0x05,                    //   REPORT_COUNT (5)
      0x75, 0x01,                    //   REPORT_SIZE (1)
      0x05, 0x08,                    //   USAGE_PAGE (LEDs)
      0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
      0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
      0x91, 0x02,                    //   OUTPUT (Data,Var,Abs) ; LED report
      0x95, 0x01,                    //   REPORT_COUNT (1)
      0x75, 0x03,                    //   REPORT_SIZE (3)
      0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs) ; LED report padding
      0x95, 0x06,                    //   REPORT_COUNT (6)
      0x75, 0x08,                    //   REPORT_SIZE (8)
      0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
      0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
      0x05, 0x07,                    //   USAGE_PAGE (Keyboard)(Key Codes)
      0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))(0)
      0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)(101)
      0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
      0xc0                           // END_COLLECTION
   };
   
3. Fill a report structure for boot protocol. Send it when needed. Up to 6 at the same time. For example
 
   typedef struct {
         uint8_t modifier;
         uint8_t reserved;
         uint8_t keycode[6];
   } keyboard_report_t;




Almost all work done here: http://codeandlife.com/2012/06/18/usb-hid-keyboard-with-v-usb/


Regards,
 
Julián

MichaelMeissner

  • Full Member
  • ***
  • Posts: 166
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #6 on: September 23, 2013, 09:14:53 am »
Just a note, when posting code, enclose the code with [ code ] and [ /code ] (without the spaces) tags, so that you don't get random smiley faces in the output, and the browsers can scroll on the longer segments.  A simple way to do this is to add the code, mark the region with your mouse, and hit the '#'  square in the buttons above the text box.

Cyberwizzard

  • Newbie
  • *
  • Posts: 5
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #7 on: January 11, 2014, 03:45:06 pm »
Julian, does your virtual keyboard work on pre-boot, over system restarts and after stand-by?

As far as I understand, supporting boot protocol should provide me with exactly these features but so far I need to remove and re-insert the Digispark every time the system reboots or otherwise powers down.

I also implemented "set protocol" and "get protocol" which seems to be a feature that the host likes to use and is required for proper functionality without HID drivers but this made no difference (afaik).

joakim

  • Newbie
  • *
  • Posts: 4
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #8 on: August 10, 2014, 03:18:52 am »
Terribly sorry to bring up an old post, but has anyone had any success when it comes to running the HID pre-boot?

Cyberwizzard

  • Newbie
  • *
  • Posts: 5
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #9 on: January 08, 2015, 05:00:13 am »
So far I have not been able to get USB HID to work on power-on or over reboots.

Even worse, some of my systems hang on boot as the USB controller gets confused by the Digispark and the USB subsystem hangs indefinitely.

If somebody knows how to make the USB support work so I do not have to unplug my Digisparks on every boot that would be great...

whocares1

  • Newbie
  • *
  • Posts: 4
Re: Digispark as HID Keyboard on preboot doesnt work
« Reply #10 on: June 02, 2018, 10:54:54 am »

Hi again,


Turns out that no great changes needed:


1. Mark device as boot device in configuration descriptor:


      #define USB_CFG_DEVICE_CLASS        0     /* set to 0 if deferred to interface */
      #define USB_CFG_DEVICE_SUBCLASS     0
      /* See USB specification if you want to conform to an existing device class.
       * Class 0xff is "vendor specific".
       */
      #define USB_CFG_INTERFACE_CLASS     3   /* define class here if not at device level */
      #define USB_CFG_INTERFACE_SUBCLASS  1
      #define USB_CFG_INTERFACE_PROTOCOL  1


2. Use a HID report descriptor indicating boot support (see http://www.usb.org/developers/devclass_docs/HID1_11.pdf , Appendix B: Boot Interface
Descriptors) (Update USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH to the new size, mine is 63 bytes):


   PROGMEM char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
      0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
      0x09, 0x06,                    // USAGE (Keyboard)
      0xa1, 0x01,                    // COLLECTION (Application)
      0x75, 0x01,                    //   REPORT_SIZE (1)
      0x95, 0x08,                    //   REPORT_COUNT (8)
      0x05, 0x07,                    //   USAGE_PAGE (Keyboard)(Key Codes)
      0x19, 0xe0,                    //   USAGE_MINIMUM (Keyboard LeftControl)(224)
      0x29, 0xe7,                    //   USAGE_MAXIMUM (Keyboard Right GUI)(231)
      0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
      0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
      0x81, 0x02,                    //   INPUT (Data,Var,Abs) ; Modifier byte
      0x95, 0x01,                    //   REPORT_COUNT (1)
      0x75, 0x08,                    //   REPORT_SIZE (8)
      0x81, 0x03,                    //   INPUT (Cnst,Var,Abs) ; Reserved byte
      0x95, 0x05,                    //   REPORT_COUNT (5)
      0x75, 0x01,                    //   REPORT_SIZE (1)
      0x05, 0x08,                    //   USAGE_PAGE (LEDs)
      0x19, 0x01,                    //   USAGE_MINIMUM (Num Lock)
      0x29, 0x05,                    //   USAGE_MAXIMUM (Kana)
      0x91, 0x02,                    //   OUTPUT (Data,Var,Abs) ; LED report
      0x95, 0x01,                    //   REPORT_COUNT (1)
      0x75, 0x03,                    //   REPORT_SIZE (3)
      0x91, 0x03,                    //   OUTPUT (Cnst,Var,Abs) ; LED report padding
      0x95, 0x06,                    //   REPORT_COUNT (6)
      0x75, 0x08,                    //   REPORT_SIZE (8)
      0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
      0x25, 0x65,                    //   LOGICAL_MAXIMUM (101)
      0x05, 0x07,                    //   USAGE_PAGE (Keyboard)(Key Codes)
      0x19, 0x00,                    //   USAGE_MINIMUM (Reserved (no event indicated))(0)
      0x29, 0x65,                    //   USAGE_MAXIMUM (Keyboard Application)(101)
      0x81, 0x00,                    //   INPUT (Data,Ary,Abs)
      0xc0                           // END_COLLECTION
   };
   
3. Fill a report structure for boot protocol. Send it when needed. Up to 6 at the same time. For example
 
   typedef struct {
         uint8_t modifier;
         uint8_t reserved;
         uint8_t keycode[6];
   } keyboard_report_t;




Almost all work done here: http://codeandlife.com/2012/06/18/usb-hid-keyboard-with-v-usb/


Regards,
 
Julián
Could you consider posting your sources coz nobody else got this working even after reading the v usb thing