Go Down

Topic: Turning on/off keyboard leds (Read 1 time) previous topic - next topic

1212toba

Feb 14, 2015, 04:26 pm Last Edit: Feb 15, 2015, 09:04 pm by 1212toba
Hello,

I've took an Arduino UNO and a USB host shield and made a simple keyboard translator. I have attached it to a regular USB keyboard. All it does is that it translates some key presses to some other key presses. What I couldn't figure out is
how to send data from Arduino UNO to the keyboard to set the keyboard led status. Is it doable at all?

Kind Regards

BTW below is the program that is running on the board

Code: [Select]

#include <hidboot.h>
#include <usbhub.h>
#include <Usb.h>
#include <USBAPI.h>

#define CHECK_BIT(val, bit)   (((val) & (1 << (bit))) != 0)
#define SET_BIT(val, bit)     ((val) |= (1 << (bit)))
#define CLEAR_BIT(val, bit)   ((val) &= (uint8_t)~(1 << (bit)))
 
#define KEY_LEFT_CTRL 0x01
#define KEY_LEFT_SHIFT 0x02
#define KEY_LEFT_ALT    0x04
#define KEY_LEFT_GUI    0x08
#define KEY_RIGHT_CTRL 0x10
#define KEY_RIGHT_SHIFT 0x20
#define KEY_RIGHT_ALT   0x40
#define KEY_RIGHT_GUI   0x80

#define LEFT_CTRL     0
#define LEFT_SHIFT    1
#define LEFT_ALT      2
#define LEFT_GUI      3
#define RIGHT_CTRL    4
#define RIGHT_SHIFT   5
#define RIGHT_ALT     6
#define RIGHT_GUI     7

#define KEY_CAPSLOCK    57

uint8_t kbdbuf[8] = {0};
uint8_t real_keys[8] = {0};
uint8_t capslock_pressed = 0;
uint8_t in_selection = 0;
uint8_t prev_keys[3] = {0};

class KbdRptParser : public KeyboardReportParser
{
    protected:
        virtual void OnControlKeysChanged(uint8_t before, uint8_t after);
        virtual void OnKeyDown (uint8_t mod, uint8_t key);
        virtual void OnKeyUp (uint8_t mod, uint8_t key);
        virtual void OnKeyPressed(uint8_t key);
};

void sendBuf(uint8_t* buf) {
     if(in_selection) {
         SET_BIT(buf[0], LEFT_SHIFT);
     }
     //printState(buf);
     Serial.write(buf, 8 );
}

void add_prevkey(uint8_t key) {
    prev_keys[0] = prev_keys[1];
    prev_keys[1] = prev_keys[2];
    prev_keys[2] = key;   
}

void reset() {
    prev_keys[0] = {0};
    kbdbuf[8] = {0};
    real_keys[8] = {0};
    capslock_pressed = 0;
    in_selection = 0;
    sendBuf(kbdbuf);
}

void pressKey(uint8_t mod, uint8_t key) {
    uint8_t buf[8] = {mod, 0, key, 0, 0, 0, 0, 0};
    sendBuf(buf);
    buf[2] = 0;
    sendBuf(buf);
}

int find(uint8_t key, uint8_t* buf) {
    for(int i = 2; i < 8; i++) {
        if(buf[i] == key) {
            return i;
        }
    }
    return -1;
}

void clearKey(uint8_t key, uint8_t* buf) {
    int idx = find(key ,kbdbuf);
    if(idx > 0) {
        buf[idx] = 0;
    }
}

uint8_t setKey(uint8_t key, uint8_t* buf) {
    if(find(key, buf) > 0) {
        return -1;
    }
    else {
        uint8_t idx = find(0, buf);
        if(idx > 0) {
            buf[idx] = key;
            return idx;
        }
    }
    return -1;
}

void KbdRptParser::OnKeyDown(uint8_t mod, uint8_t key) {
    add_prevkey(key);
    if(prev_keys[0] == KEY_CAPSLOCK && prev_keys[1] == KEY_CAPSLOCK && prev_keys[2] == KEY_CAPSLOCK) {
        reset();
        return;
    }
   
    int firstEmptySlot = find(0 ,kbdbuf);
    if(firstEmptySlot < 0) {
        return;
    }
    kbdbuf[0] = mod;
    kbdbuf[firstEmptySlot] = key;
   
   if(key == KEY_CAPSLOCK && CHECK_BIT(mod, LEFT_SHIFT)) {
        CLEAR_BIT(mod, LEFT_SHIFT);
        sendBuf(kbdbuf);
        return;       
    }
   
   if(key == KEY_CAPSLOCK) {
        capslock_pressed = 1;
        // A caps-lock-ot eltuntetjuk, annak nem szabad megjelennie.
        clearKey(KEY_CAPSLOCK ,kbdbuf);
        return;
    }
   
   if(capslock_pressed) {
        if(key == 72) { //Pause/break
            reset();
            return;
        }
       
        uint8_t fake_key = 0;
        clearKey(key ,kbdbuf);
        kbdbuf[0] = 0;
       
        if(key == 13) { //j
            in_selection = !in_selection;
            return;
        }
        else if(key == 15) { //l
            pressKey(0, 47); //HOME
            in_selection = !in_selection;
            pressKey(0, 81); //DOWN
            return;
        }
        else if(key == 23) { //t - cut
            in_selection = 0;
            SET_BIT(kbdbuf[0], LEFT_CTRL);
            fake_key = 27; //x
            //return;
        }
        else if(key == 28) { //y - copy
            in_selection = 0;
            SET_BIT(kbdbuf[0], LEFT_CTRL);
            fake_key = 6; //c
            //return;
        }
        else if(key == 24) { //u - paste
            in_selection = 0;
            SET_BIT(kbdbuf[0], LEFT_CTRL);
            fake_key = 25; //v       
        }
        else if(key == 22) { //left
            fake_key = 80;
        }
        else if(key == 7) { //right
            fake_key = 79;     
        }
        else if(key == 8) { //up
            fake_key = 82;
        }
        else if(key == 27) { //down
            fake_key = 81;
        }
        else if(key == 21) { //pgup
            fake_key = 75;
        }
        else if(key == 6) { //pgdn
            fake_key = 78;
        }
        else if(key == 5) { //home
            fake_key = 74;       
        }
        else if(key == 17) { //end
            fake_key = 77;       
        }
        else if(key == 11) { //bs
            fake_key = 42;       
        }
        else if(key == 10) { //del
            fake_key = 76;       
        }
        else if(key == 18) { //o - undo
            in_selection = 0;
            SET_BIT(kbdbuf[0], LEFT_CTRL);
            fake_key = 29; //z
        }
        else if(key == 19) { //p - redo
            in_selection = 0;
            SET_BIT(kbdbuf[0], LEFT_CTRL);
            fake_key = 28; //y
        }

        if(fake_key != 0) {
          uint8_t idx = setKey(fake_key, kbdbuf);
          if(idx > 0) {
              real_keys[idx] = key;
          }
        }
    }
    sendBuf(kbdbuf); 
}

void KbdRptParser::OnKeyUp(uint8_t mod, uint8_t key) {
    uint8_t idx = find(key, real_keys);
    if(idx > 0) {
        real_keys[idx] = 0;
        kbdbuf[idx] = 0;
    }
    clearKey(key, kbdbuf);
       
    if(capslock_pressed && key == KEY_CAPSLOCK) {
        capslock_pressed = 0;
        return;
    }
    sendBuf(kbdbuf);
//    kbdbuf[0] = mod; ?
}

void printState(uint8_t* buf) {
    Serial.print(buf[0]);Serial.print("|");Serial.print(buf[2]);Serial.print(" ");
    Serial.print(buf[3]);Serial.print(" ");Serial.print(buf[4]);Serial.print(" ");
    Serial.print(buf[5]);Serial.print(" ");Serial.print(buf[6]);Serial.print(" ");
    Serial.print(buf[7]);Serial.println("");
}

void KbdRptParser::OnKeyPressed(uint8_t key) {};

void KbdRptParser::OnControlKeysChanged(uint8_t before, uint8_t after) {
    kbdbuf[0] = after; 
}

USB     Usb;
HIDBoot<HID_PROTOCOL_KEYBOARD>    HidKeyboard(&Usb);

//uint32_t next_time;

KbdRptParser Prs;             

void setup()
{
    Serial.begin( 9600 );
    //while (!Serial); // Wait for serial port to connect - used on Leonardo, Teensy and other boards with built-in USB CDC serial connection
    //Serial.println("StaasAwgFDASDFGEDAaart");

    if (Usb.Init() == -1) Serial.println("OSC did not start.");

  delay( 200 );


  //next_time = millis() + 5000;
//    HidComposite.SetReportParser(0, (HIDReportParser*)&Prs);
    HidKeyboard.SetReportParser(0, (HIDReportParser*)&Prs);
}

void loop() {
    Usb.Task();
}

weedpharma

#1
Feb 15, 2015, 06:28 am Last Edit: Feb 15, 2015, 06:29 am by weedpharma
Please put your code in its own window as seen in other posts. This can be done by placing     [code] and [/code]         around the code. This makes it easier for others to read.

Weedpharma

KenF

There seems to be a decent example of the process On THIS page

It seems the magic is done with setReport.

1212toba

I looked at the page, and found that line with setReport

Code: [Select]

        rcode = Usb.setReport( KBD_ADDR, 0, 1, KBD_IF, 0x02, 0, &leds );


but when I tried to do something similar in my code I got an error message


error: 'class USB' has no member named 'setReport'


It looks like this setReport function is not defined.

Go Up