Deprecated: Function create_function() is deprecated in /home/bluekitc/public_html/ringwald.ch/electronics/pmwiki.php on line 456

Main.BluetoothKeyboard History

Show minor edits - Show changes to output

December 05, 2009, at 03:52 PM by 77.58.155.199 -
Deleted line 190:
Deleted lines 192-193:

[+Further Exploration+]
Added lines 195-196:
[+Further Exploration+]
\\
December 05, 2009, at 03:51 PM by 77.58.155.199 -
Changed lines 1-2 from:
[++User-space Java Bluetooth (JSR-82) Keyboard Driver++]
to:
[++User-Space Java Bluetooth (JSR-82) Keyboard Driver++]
December 05, 2009, at 03:51 PM by 77.58.155.199 -
Changed lines 13-17 from:
[+Further Exploration+]
\\
Build your own [[http://www.matias.ca/halfkeyboard/|HalfKeyboard (tm)]].

to:
Changed lines 192-198 from:
@]
to:
@]


[+Further Exploration+]
\\
\\
Build your own [[http://www.matias.ca/halfkeyboard/|HalfKeyboard (tm)]].
December 05, 2009, at 03:50 PM by 77.58.155.199 -
Changed lines 1-2 from:
[+User-space Java Bluetooth (JSR-82) Keyboard Driver+]
to:
[++User-space Java Bluetooth (JSR-82) Keyboard Driver++]
Changed lines 5-8 from:
[++Motivation++]

[++Requirements++]
to:
[+Motivation+]

[+Requirements+]
Changed lines 11-13 from:
[++Explanation++]

[++Further Exploration++]
to:
[+Explanation+]

[+Further Exploration+]
\\
Added line 17:
December 05, 2009, at 03:49 PM by 77.58.155.199 -
Added lines 1-15:
[+User-space Java Bluetooth (JSR-82) Keyboard Driver+]

... stay tuned!

[++Motivation++]

[++Requirements++]

* JSR-82 implementation, e.g., [[http://bluecove.org/|BlueCove]]

[++Explanation++]

[++Further Exploration++]
Build your own [[http://www.matias.ca/halfkeyboard/|HalfKeyboard (tm)]].

December 05, 2009, at 03:41 PM by 77.58.155.199 -
Changed line 164 from:
       KeyEvent.VK_TAB, ' ',                  /* 42 - 44 */
to:
       KeyEvent.VK_TAB, ' ',                           /* 42 - 44 */
December 05, 2009, at 03:41 PM by 77.58.155.199 -
Changed line 164 from:
       KeyEvent.VK_TAB, ' ',    /* 42 - 44 */
to:
       KeyEvent.VK_TAB, ' ',                   /* 42 - 44 */
December 05, 2009, at 03:40 PM by 77.58.155.199 -
Changed line 163 from:
       KeyEvent.VK_ENTER, 27, KeyEvent.VK_BACK_SPACE, /* 40 - 42 */
to:
       KeyEvent.VK_ENTER, 27, KeyEvent.VK_BACK_SPACE,   /* 40 - 42 */
December 05, 2009, at 03:40 PM by 77.58.155.199 -
Changed line 164 from:
       KeyEvent.VK_TAB, ' ', /* 42 - 44 */
to:
       KeyEvent.VK_TAB, ' ',   /* 42 - 44 */
Changed line 166 from:
       '.', '/', KeyEvent.VK_ENTER                       /* 55 - 57 */
to:
       '.', '/', KeyEvent.VK_ENTER                      /* 55 - 57 */
December 05, 2009, at 03:39 PM by 77.58.155.199 -
Changed lines 165-166 from:
       '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',' /* 45 - 54 */
        '.', '/', KeyEvent.VK_ENTER                           /* 55 - 57 */
to:
       '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',', /* 45 - 54 */
        '.', '/', KeyEvent.VK_ENTER                        /* 55 - 57 */
December 05, 2009, at 03:38 PM by 77.58.155.199 -
Changed line 165 from:
       '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',',    /* 45 - 54 */
to:
       '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',' /* 45 - 54 */
December 05, 2009, at 03:37 PM by 77.58.155.199 -
Changed lines 163-164 from:
       KeyEvent.VK_ENTER, 27, KeyEvent.VK_BACK_SPACE, KeyEvent.VK_TAB, ' ',
        /* 40 - 44 */
to:
       KeyEvent.VK_ENTER, 27, KeyEvent.VK_BACK_SPACE, /* 40 - 42 */
        KeyEvent.VK_TAB, ' ', /* 42 - 44 */
December 05, 2009, at 03:35 PM by 77.58.155.199 -
Changed lines 94-95 from:
                      boolean ctrl_pressed, boolean alt_pressed,
   
                  boolean command_pressed) throws AWTException {
to:
                   boolean ctrl_pressed, boolean alt_pressed,
                  boolean command_pressed) throws AWTException {
Changed lines 163-164 from:
       KeyEvent.VK_ENTER, 27, KeyEvent.VK_BACK_SPACE, KeyEvent.VK_TAB, ' ', /* 40 - 44 */
to:
       KeyEvent.VK_ENTER, 27, KeyEvent.VK_BACK_SPACE, KeyEvent.VK_TAB, ' ', 
     
/* 40 - 44 */
December 05, 2009, at 03:34 PM by 77.58.155.199 -
Changed lines 83-85 from:
           injectKey(new_key, shift_pressed,
                      ctrl_pressed, alt_pressed, command_pressed);
to:
           injectKey(new_key, shift_pressed, ctrl_pressed,
                      alt_pressed, command_pressed);
Changed lines 93-94 from:
   void injectKey(int new_key, boolean shift_pressed, boolean ctrl_pressed, boolean alt_pressed,
                  boolean command_pressed) throws AWTException {
to:
   void injectKey(int new_key, boolean shift_pressed,
                      boolean ctrl_pressed, boolean alt_pressed,
   
                  boolean command_pressed) throws AWTException {
December 05, 2009, at 03:32 PM by 77.58.155.199 -
Changed lines 93-94 from:
   void injectKey(int new_key, boolean shift_pressed, boolean ctrl_pressed,
            boolean alt_pressed, boolean command_pressed) throws AWTException {
to:
   void injectKey(int new_key, boolean shift_pressed, boolean ctrl_pressed, boolean alt_pressed,
                 boolean command_pressed) throws AWTException {
Changed lines 149-150 from:
   public static final int cursor_keys[] = { KeyEvent.VK_RIGHT, KeyEvent.VK_LEFT, KeyEvent.VK_DOWN, KeyEvent.VK_UP};
to:
   public static final int cursor_keys[] = {
                           KeyEvent.VK_RIGHT,
                            KeyEvent.VK_LEFT,
                            KeyEvent.VK_DOWN,
                            KeyEvent.VK_
UP 
                       
};
December 05, 2009, at 03:31 PM by 77.58.155.199 -
Changed lines 83-84 from:
           injectKey(new_key, shift_pressed, ctrl_pressed, alt_pressed, command_pressed);
to:
           injectKey(new_key, shift_pressed, 
                   
ctrl_pressed, alt_pressed, command_pressed);
December 05, 2009, at 03:30 PM by 77.58.155.199 -
Changed line 26 from:
             + kbAddr + ":13;authenticate=true;");
to:
                               + kbAddr + ":13;authenticate=true;");
Changed lines 43-44 from:
   void handlePacket(byte[] hidReport, int packetLen) throws IOException, AWTException {
to:
   void handlePacket(byte[] hidReport, int packetLen) throws
                                          IOException,
                                         
AWTException {
December 05, 2009, at 03:29 PM by 77.58.155.199 -
Changed line 15 from:
                                           IOException{
to:
                                           IOException {
Changed lines 25-26 from:
       L2CAPConnection con = (L2CAPConnection) Connector.open("btl2cap://" + kbAddr + ":13;authenticate=true;");
to:
       L2CAPConnection con = (L2CAPConnection) Connector.open("btl2cap://"
           
+ kbAddr + ":13;authenticate=true;");
December 05, 2009, at 03:29 PM by 77.58.155.199 -
Changed lines 12-15 from:
   public static void main(String[] args) throws AWTException, InterruptedException, IOException{
to:
   public static void main(String[] args) throws
                                          AWTException,
                                          InterruptedException,
                                         
IOException{
December 05, 2009, at 03:27 PM by 77.58.155.199 -
Changed lines 12-165 from:
public static void main(String[] args) throws
 
         AWTException,
          InterruptedException,
   
      IOException {
new BluetoothKeyboard().go();
}

void go() throws IOException, AWTException {

// allow connections to PSM below
0x1001
System.setProperty("bluecove.jsr82.psm_minimum_off", "true");

// connect
L2CAPConnection con = (L2CAPConnection) Connector.open("btl2cap://" + kbAddr + ":13;authenticate
=true;");
System
.out.println("Connected");

// process reports
byte hidReport[]
= new byte[255];
while (true){
// get packet from L2CAP connection
int packetLen = con
.receive(hidReport);

// dump report
dumpBuffer(hidReport, packetLen);

// process event
handlePacket(hidReport, packetLen);
}
}

void handlePacket(byte[] hidReport, int packetLen) throws IOException, AWTException {

// decode keys, only
process up to NUM_KEYS
int modifier =
hidReport[2];
int nrKeys
= packetLen - 4;
if (nrKeys > NUM_KEYS){
nrKeys = NUM_KEYS;
}

// modifier keys
boolean ctrl_pressed
    = (modifier & 0x11) != 0;
boolean shift_pressed
  = (modifier & 0x22) != 0;
boolean alt_pressed
    = (modifier & 0x44) != 0;
boolean command_pressed = (modifier & 0x88
) != 0;

// process events
for (int i=0; i< nrKeys; i++){
// find key in last state
int new_event = hidReport[4+i];
if (new_event == 0 || new_event == 44) continue;
for
(int j=0; j<NUM_KEYS; j++){
if (new_event == last_keyboard_state[j]){
new_event = 0;
break;
}
}
if (new_event == 0) continue;

// get from table
int new_key = 0;
if (new_event <= 57){
new_key = keytable_us_none[new_
event];
} else if (new_event >= 0x4f && new_event <= 0x52) {
new_key = cursor_keys[ new_event - 0x4f];
} else {
continue;
}

injectKey(new_key, shift_pressed, ctrl_pressed, alt_pressed, command_pressed);

}

// store keyboard state
System.arraycopy(hidReport, 4, last_keyboard_state
, 0, NUM_KEYS);
last_modifier = modifier;
}

void injectKey(int new_key, boolean shift_pressed, boolean ctrl_pressed,
boolean alt_pressed, boolean command_pressed) throws AWTException {

// create Robot instance if necessary
if (robot == null){
robot = new Robot()
;
}

// use upper case chars
char key = Character.toUpperCase((char) new_key)
;

// set up modifier keys
if (shift_pressed) {
robot.keyPress
(KeyEvent.VK_SHIFT);
}
if (ctrl_pressed) {
robot.keyPress(KeyEvent.VK_CONTROL);
}
if (alt_pressed) {
robot.keyPress(KeyEvent.VK_ALT);
}
if (command
_pressed){
robot.keyPress(KeyEvent.VK_META)
;
}

// inject single press
robot.keyPress(key);
robot.keyRelease(key);

// unset modifier keys
if (command_pressed){
robot.keyRelease(KeyEvent.VK_META);
}
if (alt_pressed) {
robot.keyRelease(KeyEvent.VK_ALT);
}
if (ctrl_pressed) {
robot.keyRelease(KeyEvent.VK_CONTROL);
}
if (shift_pressed) {
robot.keyRelease(KeyEvent.VK_SHIFT);
}
}

public void dumpBuffer(byte[] data, int len){
System.out.print("DATA: ");
for (int i=0;i<len;i++){
int value = data[i];
if (value<0){
value += 256;
}
System.out.print( Integer.toHexString(value) + " "
);
}
System.out.println();
}

public static final int cursor_keys[] = { KeyEvent.VK_RIGHT, KeyEvent.VK
_LEFT, KeyEvent.VK_DOWN, KeyEvent.VK_UP};

public static int keytable_us_none []
= {
0, 0, 0, 0, /* 0-3 */
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', /*  4 - 13 */
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', /* 14 - 23 */
'u', 'v', 'w', 'x', 'y', 'z',
                    /* 24 - 29 */
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', /* 30 - 39 */
KeyEvent.VK_ENTER, 27, KeyEvent.VK_BACK_SPACE, KeyEvent.VK_TAB, ' ', /* 40 - 44 */
'-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',',
      /* 45 - 54 */
'.', '/', KeyEvent.VK
_ENTER                           /* 55 - 57 */
};


public static final int NUM_KEYS = 5;
Robot robot;

byte last
_keyboard_state[] = new byte[NUM_KEYS];
int last_modifier = 0;

// address of your keyboard
public
static final String kbAddr = "001b63fa61c3";
to:
    public static void main(String[] args) throws AWTException, InterruptedException, IOException{
        new BluetoothKeyboard().go();
    }
   
   void go() throws IOException, AWTException {
       
   
    // allow connections to PSM below 0x1001
       System.setProperty("bluecove.jsr82.psm_minimum_off", "true");
     
       // connect
        L2CAPConnection con
= (L2CAPConnection) Connector.open("btl2cap://" + kbAddr + ":13;authenticate=true;");
     
  System.out.println("Connected");
       
   
   // process reports
 
     byte hidReport[] = new byte[255];
       while (true){
           // get packet from L2CAP connection
 
           int packetLen = con.receive(hidReport);

           // dump report
 
          dumpBuffer(hidReport, packetLen);
     
           // process event
          handlePacket(hidReport, packetLen);
       }
    }

    void handlePacket(byte[] hidReport, int packetLen) throws IOException, AWTException {

        // decode keys, only process up to NUM_KEYS
       int modifier = hidReport[2];
       int nrKeys = packetLen - 4;
        if (nrKeys > NUM_KEYS){
           nrKeys = NUM_KEYS;
        }
       
 
    // modifier keys
       boolean ctrl_pressed    = (modifier & 0x11) != 0;
       boolean shift_pressed  = (modifier & 0x22) != 0;
 
    boolean alt_pressed    = (modifier & 0x44) != 0;
 
      boolean command_pressed = (modifier & 0x88) != 0;
       
        // process events
        for (int i=0; i< nrKeys; i++){
           // find key in last state
            int new_event = hidReport[4+i];
            if (new_event == 0 || new_event == 44) continue;
            for (int j=0; j<NUM_KEYS; j++){
               if (new_event == last_keyboard_state[j]){
 
                   new_event = 0;
                    break;
                }
            }
            if (new_event == 0) continue;

            // get from table
            int new_key = 0;
            if (new_event <= 57){
                new_key = keytable_us_none[new_event];
            } else if (new_event >= 0x4f && new_event <= 0x52) {
                new_key = cursor_keys[ new_event - 0x4f];
            } else {
                continue;
            }

            injectKey(new_key, shift_pressed, ctrl_pressed, alt_pressed, command_pressed);

        }

        // store keyboard state
        System.arraycopy(hidReport, 4, last_keyboard_state, 0, NUM_KEYS);
        last_modifier = modifier;
    }

    void injectKey(int new_key, boolean shift_pressed, boolean ctrl_pressed,
            boolean alt_pressed, boolean command_pressed) throws AWTException {
       
        // create Robot instance if necessary
        if (robot == null){
            robot = new Robot();
        }
       
        // use upper case chars
        char key = Character.toUpperCase((char) new_key);
       
        // set up modifier keys
        if (shift_pressed) {
            robot.keyPress(KeyEvent.VK_SHIFT);
        }
        if (ctrl_pressed) {
            robot.keyPress(KeyEvent.VK_CONTROL);
        }
        if (alt_pressed) {
            robot.keyPress(KeyEvent.VK_ALT);
        }
        if (command_pressed){
            robot.keyPress(KeyEvent.VK_META);
        }
       
        // inject single press
        robot.keyPress(key);
        robot.keyRelease(key);
       
        // unset modifier keys
        if (command_pressed){
            robot.keyRelease(KeyEvent.VK_META);
        }
        if (alt_pressed) {
            robot.keyRelease(KeyEvent.VK_ALT);
        }
        if (ctrl_pressed) {
            robot.keyRelease(KeyEvent.VK_CONTROL);
        }
        if (shift_pressed) {
            robot.keyRelease(KeyEvent.VK_SHIFT);
        }
    }

    public void dumpBuffer(byte[] data, int len){
        System.out.print("DATA: ");
        for (int i=0;i<len;i++){
            int value = data[i];
            if (value<0){
                value += 256;
            }
            System.out.print( Integer.toHexString(value) + " ");
        }
        System.out.println();
    }

    public static final int cursor_keys[] = { KeyEvent.VK_RIGHT, KeyEvent.VK_LEFT, KeyEvent.VK_DOWN, KeyEvent.VK_UP};

    public static int keytable_us_none [] = {
        0, 0, 0, 0, /* 0-3 */
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', /*  4 - 13 */
        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', /* 14 - 23 */
        'u', 'v', 'w', 'x', 'y', 'z',                    /* 24 - 29 */
        '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', /* 30 - 39 */
        KeyEvent.VK_ENTER, 27, KeyEvent.VK_BACK_SPACE, KeyEvent.VK_TAB, ' ', /* 40 - 44 */
        '-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',',      /* 45 - 54 */
        '.', '/', KeyEvent.VK_ENTER                            /* 55 - 57 */
    };
   
    public static final int NUM_KEYS = 5;
    Robot robot;
   
    byte last_keyboard_state[] = new byte[NUM_KEYS];
    int last_modifier = 0;

    // address of your keyboard
   
public static final String kbAddr = "001b63fa61c3";
December 05, 2009, at 03:26 PM by 77.58.155.199 -
Changed lines 12-15 from:
public static void main(String[] args) throws AWTException, InterruptedException, IOException{
to:
public static void main(String[] args) throws
          AWTException,
          InterruptedException,
         
IOException {
December 05, 2009, at 03:24 PM by 77.58.155.199 -
Added lines 1-165:
[@
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import java.io.IOException;

import javax.bluetooth.L2CAPConnection;
import javax.microedition.io.Connector;

public class BluetoothKeyboard {

public static void main(String[] args) throws AWTException, InterruptedException, IOException{
new BluetoothKeyboard().go();
}

void go() throws IOException, AWTException {

// allow connections to PSM below 0x1001
System.setProperty("bluecove.jsr82.psm_minimum_off", "true");

// connect
L2CAPConnection con = (L2CAPConnection) Connector.open("btl2cap://" + kbAddr + ":13;authenticate=true;");
System.out.println("Connected");

// process reports
byte hidReport[] = new byte[255];
while (true){
// get packet from L2CAP connection
int packetLen = con.receive(hidReport);

// dump report
dumpBuffer(hidReport, packetLen);

// process event
handlePacket(hidReport, packetLen);
}
}

void handlePacket(byte[] hidReport, int packetLen) throws IOException, AWTException {

// decode keys, only process up to NUM_KEYS
int modifier = hidReport[2];
int nrKeys = packetLen - 4;
if (nrKeys > NUM_KEYS){
nrKeys = NUM_KEYS;
}

// modifier keys
boolean ctrl_pressed    = (modifier & 0x11) != 0;
boolean shift_pressed  = (modifier & 0x22) != 0;
boolean alt_pressed    = (modifier & 0x44) != 0;
boolean command_pressed = (modifier & 0x88) != 0;

// process events
for (int i=0; i< nrKeys; i++){
// find key in last state
int new_event = hidReport[4+i];
if (new_event == 0 || new_event == 44) continue;
for (int j=0; j<NUM_KEYS; j++){
if (new_event == last_keyboard_state[j]){
new_event = 0;
break;
}
}
if (new_event == 0) continue;

// get from table
int new_key = 0;
if (new_event <= 57){
new_key = keytable_us_none[new_event];
} else if (new_event >= 0x4f && new_event <= 0x52) {
new_key = cursor_keys[ new_event - 0x4f];
} else {
continue;
}

injectKey(new_key, shift_pressed, ctrl_pressed, alt_pressed, command_pressed);

}

// store keyboard state
System.arraycopy(hidReport, 4, last_keyboard_state, 0, NUM_KEYS);
last_modifier = modifier;
}

void injectKey(int new_key, boolean shift_pressed, boolean ctrl_pressed,
boolean alt_pressed, boolean command_pressed) throws AWTException {

// create Robot instance if necessary
if (robot == null){
robot = new Robot();
}

// use upper case chars
char key = Character.toUpperCase((char) new_key);

// set up modifier keys
if (shift_pressed) {
robot.keyPress(KeyEvent.VK_SHIFT);
}
if (ctrl_pressed) {
robot.keyPress(KeyEvent.VK_CONTROL);
}
if (alt_pressed) {
robot.keyPress(KeyEvent.VK_ALT);
}
if (command_pressed){
robot.keyPress(KeyEvent.VK_META);
}

// inject single press
robot.keyPress(key);
robot.keyRelease(key);

// unset modifier keys
if (command_pressed){
robot.keyRelease(KeyEvent.VK_META);
}
if (alt_pressed) {
robot.keyRelease(KeyEvent.VK_ALT);
}
if (ctrl_pressed) {
robot.keyRelease(KeyEvent.VK_CONTROL);
}
if (shift_pressed) {
robot.keyRelease(KeyEvent.VK_SHIFT);
}
}

public void dumpBuffer(byte[] data, int len){
System.out.print("DATA: ");
for (int i=0;i<len;i++){
int value = data[i];
if (value<0){
value += 256;
}
System.out.print( Integer.toHexString(value) + " ");
}
System.out.println();
}

public static final int cursor_keys[] = { KeyEvent.VK_RIGHT, KeyEvent.VK_LEFT, KeyEvent.VK_DOWN, KeyEvent.VK_UP};

public static int keytable_us_none [] = {
0, 0, 0, 0, /* 0-3 */
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', /*  4 - 13 */
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', /* 14 - 23 */
'u', 'v', 'w', 'x', 'y', 'z',                    /* 24 - 29 */
'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', /* 30 - 39 */
KeyEvent.VK_ENTER, 27, KeyEvent.VK_BACK_SPACE, KeyEvent.VK_TAB, ' ', /* 40 - 44 */
'-', '=', '[', ']', '\\', 0, ';', '\'', '`', ',',      /* 45 - 54 */
'.', '/', KeyEvent.VK_ENTER                            /* 55 - 57 */
};

public static final int NUM_KEYS = 5;
Robot robot;

byte last_keyboard_state[] = new byte[NUM_KEYS];
int last_modifier = 0;

// address of your keyboard
public static final String kbAddr = "001b63fa61c3";
}

@]