1

I am using a custom version of the DigiKeyboard library, to use a Digispark as a keyboard in the BIOS. It works on most computers, but HP 730 Thin clients dont recognize it as a keyboard.

Below is the custom version. Any suggestions on how to fix this issue? Thank you in advance for any suggestions/help.

/*
 * Based on Obdev's AVRUSB code and under the same license.
 *
 * TODO: Make a proper file header. :-)
 * Modified for Digispark by Digistump
 */
#ifndef __DigiKeyboard_h__
#define __DigiKeyboard_h__
#include <Arduino.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <string.h>
#include "usbdrv.h"
#include "scancode-ascii-table.h"
// TODO: Work around Arduino 12 issues better.
//#include <WConstants.h>
//#undef int()
typedef uint8_t byte;
#define BUFFER_SIZE 2 // Minimum of 2: 1 for modifiers + 1 for keystroke 
static uchar idleRate; // in 4 ms units
/* Boot protocols have been added.
 * 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.
 */
const PROGMEM uchar usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = { /* USB report descriptor */
 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
 0x09, 0x06, // USAGE (Keyboard)
 0xa1, 0x01, // COLLECTION (Application)
 0x05, 0x07, // USAGE_PAGE (Keyboard)
 0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
 0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
 0x15, 0x00, // LOGICAL_MINIMUM (0)
 0x25, 0x01, // LOGICAL_MAXIMUM (1)
 0x75, 0x01, // REPORT_SIZE (1)
 0x95, 0x08, // REPORT_COUNT (8)
 0x81, 0x02, // INPUT (Data,Var,Abs)
 0x95, 0x01, // REPORT_COUNT (1)
 0x75, 0x08, // REPORT_SIZE (8)
 0x81, 0x03, // INPUT (Cnst,Var,Abs)
 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)
 0x95, 0x01, // REPORT_COUNT (1)
 0x75, 0x03, // REPORT_SIZE (3)
 0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
 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)
 0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
 0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
 0x81, 0x00, // INPUT (Data,Ary,Abs)
 0xc0 // END_COLLECTION
};
/* Keyboard usage values, see usb.org's HID-usage-tables document, chapter
 * 10 Keyboard/Keypad Page for more codes.
 */
#define MOD_CONTROL_LEFT (1<<0)
#define MOD_SHIFT_LEFT (1<<1)
#define MOD_ALT_LEFT (1<<2)
#define MOD_GUI_LEFT (1<<3)
#define MOD_CONTROL_RIGHT (1<<4)
#define MOD_SHIFT_RIGHT (1<<5)
#define MOD_ALT_RIGHT (1<<6)
#define MOD_GUI_RIGHT (1<<7)
#define KEY_A 4
#define KEY_B 5
#define KEY_C 6
#define KEY_D 7
#define KEY_E 8
#define KEY_F 9
#define KEY_G 10
#define KEY_H 11
#define KEY_I 12
#define KEY_J 13
#define KEY_K 14
#define KEY_L 15
#define KEY_M 16
#define KEY_N 17
#define KEY_O 18
#define KEY_P 19
#define KEY_Q 20
#define KEY_R 21
#define KEY_S 22
#define KEY_T 23
#define KEY_U 24
#define KEY_V 25
#define KEY_W 26
#define KEY_X 27
#define KEY_Y 28
#define KEY_Z 29
#define KEY_1 30
#define KEY_2 31
#define KEY_3 32
#define KEY_4 33
#define KEY_5 34
#define KEY_6 35
#define KEY_7 36
#define KEY_8 37
#define KEY_9 38
#define KEY_0 39
#define KEY_ENTER 40
#define KEY_SPACE 44
#define KEY_F1 58
#define KEY_F2 59
#define KEY_F3 60
#define KEY_F4 61
#define KEY_F5 62
#define KEY_F6 63
#define KEY_F7 64
#define KEY_F8 65
#define KEY_F9 66
#define KEY_F10 67
#define KEY_F11 68
#define KEY_F12 69
#define KEY_LEFT 0x50
#define KEY_RIGHT 0x4F
#define KEY_DOWN 0x51
#define KEY_UP 0x52
#define KEY_DEL 0x4C
#define KEY_TAB 0x2B
#define KEY_BACKSP 0x2A
#define KEY_TILDE 0x35
#define KEY_MINUS 0x2D
#define KEY_EQUAL 0x2E
#define KEY_L_BRACE 0x2F
#define KEY_R_BRACE 0x30
#define KEY_BACKSLASH 0x31
#define KEY_SEMICOLON 0x33
#define KEY_QUOTE 0x34
#define KEY_COMMA 0x36
#define KEY_PERIOD 0x37
#define KEY_SLASH 0x38
#define KEY_ESC 0x29
class DigiKeyboardDevice : public Print {
 public:
 DigiKeyboardDevice () {
 cli();
 usbDeviceDisconnect();
 _delay_ms(250);
 usbDeviceConnect();
 usbInit();
 
 sei();
 // TODO: Remove the next two lines once we fix
 // missing first keystroke bug properly.
 memset(reportBuffer, 0, sizeof(reportBuffer)); 
 usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
 }
 
 void update() {
 usbPoll();
 }
 
 // delay while updating until we are finished delaying
 void delay(long milli) {
 unsigned long last = millis();
 while (milli > 0) {
 unsigned long now = millis();
 milli -= now - last;
 last = now;
 update();
 }
 }
 
 //sendKeyStroke: sends a key press AND release
 void sendKeyStroke(byte keyStroke) {
 sendKeyStroke(keyStroke, 0);
 }
 //sendKeyStroke: sends a key press AND release with modifiers
 void sendKeyStroke(byte keyStroke, byte modifiers) {
 sendKeyPress(keyStroke, modifiers);
 delay(10);
 // This stops endlessly repeating keystrokes:
 sendKeyPress(0,0);
 }
 //sendKeyPress: sends a key press only - no release
 //to release the key, send again with keyPress=0
 void sendKeyPress(byte keyPress) {
 sendKeyPress(keyPress, 0);
 }
 //sendKeyPress: sends a key press only, with modifiers - no release
 //to release the key, send again with keyPress=0
 void sendKeyPress(byte keyPress, byte modifiers) {
 while (!usbInterruptIsReady()) {
 // Note: We wait until we can send keyPress
 // so we know the previous keyPress was
 // sent.
 usbPoll();
 _delay_ms(5);
 }
 
 memset(reportBuffer, 0, sizeof(reportBuffer));
 
 reportBuffer[0] = modifiers;
 reportBuffer[3] = keyPress;
 
 usbSetInterrupt(reportBuffer, sizeof(reportBuffer));
 }
 
 size_t write(uint8_t chr) {
 uint8_t data = pgm_read_byte_near(ascii_to_scan_code_table + (chr - 8));
 sendKeyStroke(data & 0b01111111, data >> 7 ? MOD_SHIFT_RIGHT : 0);
 return 1;
 }
 
 //private: TODO: Make friend?
 uchar reportBuffer[8]; // buffer for HID reports [ 1 modifier byte + (len-1) key strokes]
 using Print::write;
};
DigiKeyboardDevice DigiKeyboard = DigiKeyboardDevice();
#ifdef __cplusplus
extern "C"{
#endif 
 // USB_PUBLIC uchar usbFunctionSetup
 uchar usbFunctionSetup(uchar data[8]) {
 usbRequest_t *rq = (usbRequest_t *)((void *)data);
 usbMsgPtr = DigiKeyboard.reportBuffer; //
 if ((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS) {
 /* class request type */
 if (rq->bRequest == USBRQ_HID_GET_REPORT) {
 /* wValue: ReportType (highbyte), ReportID (lowbyte) */
 /* we only have one report type, so don't look at wValue */
 // TODO: Ensure it's okay not to return anything here? 
 return 0;
 } else if (rq->bRequest == USBRQ_HID_GET_IDLE) {
 //usbMsgPtr = &idleRate;
 //return 1;
 return 0;
 
 } else if (rq->bRequest == USBRQ_HID_SET_IDLE) {
 idleRate = rq->wValue.bytes[1];
 
 }
 } else {
 /* no vendor specific requests implemented */
 }
 
 return 0;
 }
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __DigiKeyboard_h__
jsotola
1,5342 gold badges12 silver badges20 bronze badges
asked Dec 13, 2023 at 18:22
4
  • 1
    Welcome to SE/Arduino! Please take the tour to learn how this site works, and read "How to Ask". Then come back and edit your question to clarify. -- Do you have access to a USB analyzer/sniffer? If so, please tap the USB connection and watch the enumeration process and what follows. -- Did you search for information of the HP's requirements for keyboards, what did you find, and why does it not help you? -- Do you have another USB keyboard that works? If so, you might want to connect it to a Linux computer and look into the system logs for difference between that and your DigiKeyboard. Commented Dec 13, 2023 at 18:35
  • Thank you for your response. In asking what I tried, you answered my question of what I can try. Didn't know USB analyzer/sniffers existed. And the idea of checking it against a known good keyboard in linux is great. Thank you for your help! Commented Dec 13, 2023 at 19:56
  • Thanks for the flowers! However, these are just the next steps without guarantee of progress, but might help to finally find the solution. If you do, please come back and write an actual answer, marking it (later) as accepted. Commented Dec 13, 2023 at 20:00
  • "a custom version of the DigiKeyboard library" is likely part of the problem based on what I see. But confirmation is in what I don't see. Where is the rest of the code? Commented Dec 13, 2023 at 20:45

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.