Author Topic: reading keyboard LEDS  (Read 6486 times)

deepthought

  • Newbie
  • *
  • Posts: 1
reading keyboard LEDS
« on: September 16, 2014, 05:40:07 pm »
I've been trying to modify the digispark keyboard library to be able to read the state of the capslock/numlock/scrolllock LEDs
here is my code

Code: [Select]
//DigiKeyboard.h
/*
 * 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
uint8_t expectReport = 0;       

/* 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.
 */
char PROGMEM usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {
    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_ARROW_LEFT 0x50


class DigiKeyboardDevice : public Print {
 public:
uint8_t   LEDstate;   

uint8_t getleds()
{
return LEDstate;
}

  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();
  }
}
 
  void sendKeyStroke(byte keyStroke) {
    sendKeyStroke(keyStroke, 0);
  }

  void sendKeyStroke(byte keyStroke, byte modifiers) {
    while (!usbInterruptIsReady()) {
      // Note: We wait until we can send keystroke
      //       so we know the previous keystroke was
      //       sent.
    usbPoll();
    _delay_ms(5);
    }
   
    memset(reportBuffer, 0, sizeof(reportBuffer));

    reportBuffer[0] = modifiers;
    reportBuffer[1] = keyStroke;
   
    usbSetInterrupt(reportBuffer, sizeof(reportBuffer));

  while (!usbInterruptIsReady()) {
      // Note: We wait until we can send keystroke
      //       so we know the previous keystroke was
      //       sent.
    usbPoll();
    _delay_ms(5);
    }
     
    // This stops endlessly repeating keystrokes:
    memset(reportBuffer, 0, sizeof(reportBuffer));     
    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[2];    // 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 if (rq->bRequest == USBRQ_HID_SET_REPORT) {
            if (rq->wLength.word == 1) {
                // We expect one byte reports
                expectReport = 1;
                return 0xff; // Call usbFunctionWrite with data
            }
        }  else {
      /* no vendor specific requests implemented */
    }

    return 0;
  }

uint8_t usbFunctionWrite(uchar *data, uchar len) {
    if (expectReport && (len == 1)) {
        DigiKeyboard.LEDstate = data[0];
}
expectReport = 0;
    return 0x01;
}

#ifdef __cplusplus
} // extern "C"
#endif


#endif // __DigiKeyboard_h__

and my test sketch

Code: [Select]
#include<DigiKeyboard.h>
#include <TinyWireM.h>

 
#define disk1 0x50    //Address of 24LC256 eeprom chip
int returned = 0;
void setup(void)
{
}
 
void loop(){
  DigiKeyboard.sendKeyStroke(0);
  DigiKeyboard.println("hello");
DigiKeyboard.println(DigiKeyboard.getleds());
delay(2000);
}
 
void writeEEPROM(int deviceaddress, unsigned int eeaddress, byte data )
{
  TinyWireM.beginTransmission(deviceaddress);
  TinyWireM.send((int)(eeaddress & 0xFF)); // LSB
  TinyWireM.send(data);
  TinyWireM.endTransmission();
 
  delay(5);
}
 
byte readEEPROM(int deviceaddress, unsigned int eeaddress )
{
  byte rdata = 0xFF;
 
  TinyWireM.beginTransmission(deviceaddress);
  TinyWireM.send((int)(eeaddress & 0xFF)); // LSB
  TinyWireM.endTransmission();
 
  TinyWireM.requestFrom(deviceaddress,1);
 
 while (!TinyWireM.available()) {}
  rdata = TinyWireM.receive();
 
  return rdata;
}

for some reason the library is unable to type anything or read LED state.
Any ideas how I could get this to work?

collie147

  • Newbie
  • *
  • Posts: 3
Re: reading keyboard LEDS
« Reply #1 on: June 19, 2015, 05:00:53 am »
Did you ever get this to work??? I might be able to throw a few lines your way to see if it works. I havent tried with a digispark but I've gotten it to work elsewhere. 

stevelord

  • Newbie
  • *
  • Posts: 2
Re: reading keyboard LEDS
« Reply #2 on: November 03, 2015, 01:02:31 pm »
I don't see a getleds() method in your DigiKeyboard library - there isn't one.

As I understand it you may need to use a USB report to write your own, but I'm just starting out here - anyone got any ideas?

Akasurde

  • Newbie
  • *
  • Posts: 2
Re: reading keyboard LEDS
« Reply #3 on: September 18, 2016, 11:27:46 am »
I also facing same issue. After editing DigiKeyboard.h, it stops working. I am also looking at code https://github.com/adafruit/Adafruit-Trinket-USB/blob/master/TrinketKeyboard/TrinketKeyboardC.c