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

Main.BluetoothKeyboard History

Hide minor edits - Show changes to markup


Deprecated: Function create_function() is deprecated in /home/bluekitc/public_html/ringwald.ch/electronics/pmwiki.php on line 456
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 HalfKeyboard (tm).

to:
Changed lines 192-198 from:

@]

to:

@]

Further Exploration

Build your own 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., BlueCove

Explanation

Further Exploration Build your own 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";
}