Android Open Source - BlueCtrl Hid Keyboard






From Project

Back to project page BlueCtrl.

License

The source code is released under:

GNU General Public License

If you think the Android project BlueCtrl listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2012//from  w  w w.ja  v  a2s.c o  m
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.ronsdev.bluectrl;

import org.ronsdev.bluectrl.daemon.DaemonService;

import android.content.Context;
import android.util.Log;

import java.util.ArrayList;

/**
 * Virtual Keyboard that sends HID Keyboard Reports to the application daemon.
 */
public class HidKeyboard {

    private static final String TAG = "HidKeyboard";
    private static final boolean V = false;


    /*
     * HID key codes
     *
     * For more information look at the "USB - HID Usage Tables" document under the
     * chapter "10 Keyboard/Keypad Page".
     */
    public static final int KEYCODE_A = 4;
    public static final int KEYCODE_B = 5;
    public static final int KEYCODE_C = 6;
    public static final int KEYCODE_D = 7;
    public static final int KEYCODE_E = 8;
    public static final int KEYCODE_F = 9;
    public static final int KEYCODE_G = 10;
    public static final int KEYCODE_H = 11;
    public static final int KEYCODE_I = 12;
    public static final int KEYCODE_J = 13;
    public static final int KEYCODE_K = 14;
    public static final int KEYCODE_L = 15;
    public static final int KEYCODE_M = 16;
    public static final int KEYCODE_N = 17;
    public static final int KEYCODE_O = 18;
    public static final int KEYCODE_P = 19;
    public static final int KEYCODE_Q = 20;
    public static final int KEYCODE_R = 21;
    public static final int KEYCODE_S = 22;
    public static final int KEYCODE_T = 23;
    public static final int KEYCODE_U = 24;
    public static final int KEYCODE_V = 25;
    public static final int KEYCODE_W = 26;
    public static final int KEYCODE_X = 27;
    public static final int KEYCODE_Y = 28;
    public static final int KEYCODE_Z = 29;
    public static final int KEYCODE_1 = 30;
    public static final int KEYCODE_2 = 31;
    public static final int KEYCODE_3 = 32;
    public static final int KEYCODE_4 = 33;
    public static final int KEYCODE_5 = 34;
    public static final int KEYCODE_6 = 35;
    public static final int KEYCODE_7 = 36;
    public static final int KEYCODE_8 = 37;
    public static final int KEYCODE_9 = 38;
    public static final int KEYCODE_0 = 39;
    public static final int KEYCODE_ENTER = 40;
    public static final int KEYCODE_ESCAPE = 41;
    public static final int KEYCODE_DEL = 42;
    public static final int KEYCODE_TAB = 43;
    public static final int KEYCODE_SPACE = 44;
    public static final int KEYCODE_MINUS = 45;
    public static final int KEYCODE_EQUAL = 46;
    public static final int KEYCODE_LEFT_BRACKET = 47;
    public static final int KEYCODE_RIGHT_BRACKET = 48;
    public static final int KEYCODE_BACKSLASH = 49;
    public static final int KEYCODE_NON_US_POUND = 50;
    public static final int KEYCODE_SEMICOLON = 51;
    public static final int KEYCODE_APOSTROPHE = 52;
    public static final int KEYCODE_TILDE = 53;
    public static final int KEYCODE_COMMA = 54;
    public static final int KEYCODE_PERIOD = 55;
    public static final int KEYCODE_SLASH = 56;
    public static final int KEYCODE_CAPS_LOCK = 57;
    public static final int KEYCODE_F1 = 58;
    public static final int KEYCODE_F2 = 59;
    public static final int KEYCODE_F3 = 60;
    public static final int KEYCODE_F4 = 61;
    public static final int KEYCODE_F5 = 62;
    public static final int KEYCODE_F6 = 63;
    public static final int KEYCODE_F7 = 64;
    public static final int KEYCODE_F8 = 65;
    public static final int KEYCODE_F9 = 66;
    public static final int KEYCODE_F10 = 67;
    public static final int KEYCODE_F11 = 68;
    public static final int KEYCODE_F12 = 69;
    public static final int KEYCODE_PRINT_SCREEN = 70;
    public static final int KEYCODE_SCROLL_LOCK = 71;
    public static final int KEYCODE_PAUSE = 72;
    public static final int KEYCODE_INSERT = 73;
    public static final int KEYCODE_HOME = 74;
    public static final int KEYCODE_PAGE_UP = 75;
    public static final int KEYCODE_FORWARD_DEL = 76;
    public static final int KEYCODE_END = 77;
    public static final int KEYCODE_PAGE_DOWN = 78;
    public static final int KEYCODE_RIGHT_ARROW = 79;
    public static final int KEYCODE_LEFT_ARROW = 80;
    public static final int KEYCODE_DOWN_ARROW = 81;
    public static final int KEYCODE_UP_ARROW = 82;
    public static final int KEYCODE_NUM_LOCK = 83;
    public static final int KEYCODE_NUMPAD_DIVIDE = 84;
    public static final int KEYCODE_NUMPAD_MULTIPLY = 85;
    public static final int KEYCODE_NUMPAD_SUBTRACT = 86;
    public static final int KEYCODE_NUMPAD_ADD = 87;
    public static final int KEYCODE_NUMPAD_ENTER = 88;
    public static final int KEYCODE_NUMPAD_1 = 89;
    public static final int KEYCODE_NUMPAD_2 = 90;
    public static final int KEYCODE_NUMPAD_3 = 91;
    public static final int KEYCODE_NUMPAD_4 = 92;
    public static final int KEYCODE_NUMPAD_5 = 93;
    public static final int KEYCODE_NUMPAD_6 = 94;
    public static final int KEYCODE_NUMPAD_7 = 95;
    public static final int KEYCODE_NUMPAD_8 = 96;
    public static final int KEYCODE_NUMPAD_9 = 97;
    public static final int KEYCODE_NUMPAD_0 = 98;
    public static final int KEYCODE_NUMPAD_DOT = 99;
    public static final int KEYCODE_NON_US_BACKSLASH = 100;
    public static final int KEYCODE_APPLICATION = 101;
    public static final int KEYCODE_NUMPAD_EQUALS = 103;
    public static final int KEYCODE_F13 = 104;
    public static final int KEYCODE_F14 = 105;
    public static final int KEYCODE_F15 = 106;
    public static final int KEYCODE_F16 = 107;
    public static final int KEYCODE_F17 = 108;
    public static final int KEYCODE_F18 = 109;
    public static final int KEYCODE_F19 = 110;
    public static final int KEYCODE_F20 = 111;
    public static final int KEYCODE_F21 = 112;
    public static final int KEYCODE_F22 = 113;
    public static final int KEYCODE_F23 = 114;
    public static final int KEYCODE_F24 = 115;
    public static final int KEYCODE_EXECUTE = 116;
    public static final int KEYCODE_HELP = 117;
    public static final int KEYCODE_MENU = 118;
    public static final int KEYCODE_SELECT = 119;
    public static final int KEYCODE_STOP = 120;
    public static final int KEYCODE_AGAIN = 121;
    public static final int KEYCODE_UNDO = 122;
    public static final int KEYCODE_CUT = 123;
    public static final int KEYCODE_COPY = 124;
    public static final int KEYCODE_PASTE = 125;
    public static final int KEYCODE_FIND = 126;
    public static final int KEYCODE_MUTE = 127;
    public static final int KEYCODE_VOLUME_UP = 128;
    public static final int KEYCODE_VOLUME_DOWN = 129;
    public static final int KEYCODE_NUMPAD_COMMA = 133;
    public static final int KEYCODE_SYSRQ = 154;
    public static final int KEYCODE_CLEAR = 156;
    public static final int KEYCODE_NUMPAD_LEFT_PAREN = 182;
    public static final int KEYCODE_NUMPAD_RIGHT_PAREN = 183;


    /** Indicates that the left Control modifier key is pressed. */
    public static final int MODIFIER_LEFT_CTRL = 0x01;

    /** Indicates that the left Shift modifier key is pressed. */
    public static final int MODIFIER_LEFT_SHIFT = 0x02;

    /** Indicates that the left Alt modifier key is pressed. */
    public static final int MODIFIER_LEFT_ALT = 0x04;

    /** Indicates that the left GUI modifier key is pressed. */
    public static final int MODIFIER_LEFT_GUI = 0x08;

    /** Indicates that the right Control modifier key is pressed. */
    public static final int MODIFIER_RIGHT_CTRL = 0x10;

    /** Indicates that the right Shift modifier key is pressed. */
    public static final int MODIFIER_RIGHT_SHIFT = 0x20;

    /** Indicates that the right Alt modifier key is pressed. */
    public static final int MODIFIER_RIGHT_ALT = 0x40;

    /** Indicates that the right GUI modifier key is pressed. */
    public static final int MODIFIER_RIGHT_GUI = 0x80;


    /** Indicates that the system key 'Power' is pressed. */
    public static final int SYSTEM_KEY_POWER = 0x01;

    /** Indicates that the system key 'Sleep' is pressed. */
    public static final int SYSTEM_KEY_SLEEP = 0x02;


    /** Indicates that the hardware key 'Eject' is pressed. */
    public static final int HARDWARE_KEY_EJECT = 0x08;


    /** Indicates that the media key 'Play/Pause' is pressed. */
    public static final int MEDIA_KEY_PLAY_PAUSE = 0x01;

    /** Indicates that the media key 'Forward' is pressed. */
    public static final int MEDIA_KEY_FORWARD = 0x02;

    /** Indicates that the media key 'Rewind' is pressed. */
    public static final int MEDIA_KEY_REWIND = 0x04;

    /** Indicates that the media key 'Scan Next Track' is pressed. */
    public static final int MEDIA_KEY_SCAN_NEXT_TRACK = 0x08;

    /** Indicates that the media key 'Scan Previous Track' is pressed. */
    public static final int MEDIA_KEY_SCAN_PREV_TRACK = 0x10;

    /** Indicates that the media key 'Mute' is pressed. */
    public static final int MEDIA_KEY_MUTE = 0x20;

    /** Indicates that the media key 'Volume Increment' is pressed. */
    public static final int MEDIA_KEY_VOLUME_INC = 0x40;

    /** Indicates that the media key 'Volume Decrement' is pressed. */
    public static final int MEDIA_KEY_VOLUME_DEC = 0x80;


    /** Indicates that the application control key 'Home' is pressed. */
    public static final int AC_KEY_HOME = 0x01;

    /** Indicates that the application control key 'Back' is pressed. */
    public static final int AC_KEY_BACK = 0x02;

    /** Indicates that the application control key 'Forward' is pressed. */
    public static final int AC_KEY_FORWARD = 0x04;


    private DaemonService mDaemon;

    private String mKeyMap = "";
    private CharKeyReportMap mCharKeyMap = null;

    private int mPressedModifier = 0;
    private int mPressedSystemKeys = 0;
    private int mPressedHardwareKeys = 0;
    private int mPressedMediaKeys = 0;
    private int mPressedAppCtrlKeys = 0;
    private IntArrayList mPressedKeys = new IntArrayList(6);


    public HidKeyboard(DaemonService daemon) {
        mDaemon = daemon;
    }


    private int[] getPressedKeysArray() {
        int result[] = new int[mPressedKeys.size()];
        for (int i=0; i < mPressedKeys.size(); i++) {
            result[i] = mPressedKeys.getValue(i);
        }
        return result;
    }

    public boolean isConnected() {
        return (mDaemon.isRunning() &&
                (mDaemon.getHidState() == DaemonService.HID_STATE_CONNECTED));
    }

    public String getKeyMap() {
        return mKeyMap;
    }
    public void setKeyMap(Context context, String keyMap) {
        if ((keyMap == null) || keyMap.isEmpty()) {
            mKeyMap = "";
            mCharKeyMap = null;
        } else if (!keyMap.equals(mKeyMap)) {
            mKeyMap = keyMap;
            mCharKeyMap = new CharKeyReportMap(keyMap, context.getAssets());
        }
    }

    public void pressModifierKey(int hidModifier) {
        final int newModifier = mPressedModifier | hidModifier;
        if (mPressedModifier != newModifier) {
            mPressedModifier = newModifier;

            mDaemon.sendKeyboardReport(mPressedModifier, getPressedKeysArray());

            if (V) Log.v(TAG, String.format("modifier key pressed (0x%h)", hidModifier));
        }
    }

    public void releaseModifierKey(int hidModifier) {
        final int newModifier = mPressedModifier & ~hidModifier;
        if (mPressedModifier != newModifier) {
            mPressedModifier = newModifier;

            mDaemon.sendKeyboardReport(mPressedModifier, getPressedKeysArray());

            if (V) Log.v(TAG, String.format("modifier key released (0x%h)", hidModifier));
        }
    }

    public void pressKey(int hidKeyCode) {
        if (!mPressedKeys.containsValue(hidKeyCode)) {
            mPressedKeys.addValue(hidKeyCode);

            mDaemon.sendKeyboardReport(mPressedModifier, getPressedKeysArray());

            if (V) Log.v(TAG, String.format("key pressed (%d)", hidKeyCode));
        }
    }

    public void releaseKey(int hidKeyCode) {
        if (mPressedKeys.containsValue(hidKeyCode)) {
            mPressedKeys.removeValue(hidKeyCode);

            mDaemon.sendKeyboardReport(mPressedModifier, getPressedKeysArray());

            if (V) Log.v(TAG, String.format("key released (%d)", hidKeyCode));
        }
    }

    public void pressSystemKey(int key) {
        final int newKeys = mPressedSystemKeys | key;
        if (mPressedSystemKeys != newKeys) {
            mPressedSystemKeys = newKeys;

            mDaemon.sendSystemKeyReport(mPressedSystemKeys);

            if (V) Log.v(TAG, String.format("system key pressed (0x%h)", key));
        }
    }

    public void releaseSystemKey(int key) {
        final int newKeys = mPressedSystemKeys & ~key;
        if (mPressedSystemKeys != newKeys) {
            mPressedSystemKeys = newKeys;

            mDaemon.sendSystemKeyReport(mPressedSystemKeys);

            if (V) Log.v(TAG, String.format("system key released (0x%h)", key));
        }
    }

    public void pressHardwareKey(int key) {
        final int newKeys = mPressedHardwareKeys | key;
        if (mPressedHardwareKeys != newKeys) {
            mPressedHardwareKeys = newKeys;

            mDaemon.sendHardwareKeyReport(mPressedHardwareKeys);

            if (V) Log.v(TAG, String.format("hardware key pressed (0x%h)", key));
        }
    }

    public void releaseHardwareKey(int key) {
        final int newKeys = mPressedHardwareKeys & ~key;
        if (mPressedHardwareKeys != newKeys) {
            mPressedHardwareKeys = newKeys;

            mDaemon.sendHardwareKeyReport(mPressedHardwareKeys);

            if (V) Log.v(TAG, String.format("hardware key released (0x%h)", key));
        }
    }

    public void pressMediaKey(int key) {
        final int newKeys = mPressedMediaKeys | key;
        if (mPressedMediaKeys != newKeys) {
            mPressedMediaKeys = newKeys;

            mDaemon.sendMediaKeyReport(mPressedMediaKeys);

            if (V) Log.v(TAG, String.format("media key pressed (0x%h)", key));
        }
    }

    public void releaseMediaKey(int key) {
        final int newKeys = mPressedMediaKeys & ~key;
        if (mPressedMediaKeys != newKeys) {
            mPressedMediaKeys = newKeys;

            mDaemon.sendMediaKeyReport(mPressedMediaKeys);

            if (V) Log.v(TAG, String.format("media key released (0x%h)", key));
        }
    }

    public void pressAppCtrlKey(int key) {
        final int newKeys = mPressedAppCtrlKeys | key;
        if (mPressedAppCtrlKeys != newKeys) {
            mPressedAppCtrlKeys = newKeys;

            mDaemon.sendAppCtrlKeyReport(mPressedAppCtrlKeys);

            if (V) Log.v(TAG, String.format("application control key pressed (0x%h)", key));
        }
    }

    public void releaseAppCtrlKey(int key) {
        final int newKeys = mPressedAppCtrlKeys & ~key;
        if (mPressedAppCtrlKeys != newKeys) {
            mPressedAppCtrlKeys = newKeys;

            mDaemon.sendAppCtrlKeyReport(mPressedAppCtrlKeys);

            if (V) Log.v(TAG, String.format("application control key released (0x%h)", key));
        }
    }

    /**
     * Presses the corresponding key for the specified character. Only simple characters that can
     * be produced with one key and one modifier key (in other words no dead keys) are supported.
     * Also the character must be specified in the current Keymap file.
     * @param key
     * The character of the key that should be pressed.
     * @return
     * Returns {@code false} if the character cannot be mapped to a key.
     */
    public boolean pressCharKey(char key) {
        if (mCharKeyMap == null) {
            return false;
        }

        CharKeyReportMap.KeyReportSequence keyReportSequence = mCharKeyMap.get(key);
        if ((keyReportSequence != null) && (keyReportSequence.size() == 1)) {
            final int hidModifier = keyReportSequence.get(0).getModifier();
            if (hidModifier != 0) {
                pressModifierKey(hidModifier);
            }

            final int hidKeyCode = keyReportSequence.get(0).getKeyCode();
            if (hidKeyCode != 0) {
                pressKey(hidKeyCode);
            }

            return true;
        }

        return false;
    }

    /**
     * Releases the corresponding key for the specified character. Only simple characters that can
     * be produced with one key and one modifier key (in other words no dead keys) are supported.
     * Also the character must be specified in the current Keymap file.
     * @param key
     * The character of the key that should be released.
     * @return
     * Returns {@code false} if the character cannot be mapped to a key.
     */
    public boolean releaseCharKey(char key) {
        if (mCharKeyMap == null) {
            return false;
        }

        CharKeyReportMap.KeyReportSequence keyReportSequence = mCharKeyMap.get(key);
        if ((keyReportSequence != null) && (keyReportSequence.size() == 1)) {
            final int hidKeyCode = keyReportSequence.get(0).getKeyCode();
            if (hidKeyCode != 0) {
                releaseKey(hidKeyCode);
            }

            final int hidModifier = keyReportSequence.get(0).getModifier();
            if (hidModifier != 0) {
                releaseModifierKey(hidModifier);
            }

            return true;
        }

        return false;
    }

    /** Types a complete text. */
    public void typeText(String text) {
        if (mCharKeyMap == null) {
            Log.w(TAG, "Keymap not set");
            return;
        }

        ArrayList<CharKeyReportMap.KeyReport> reportList = convertToKeyReports(text);

        if (reportList.size() < 1) {
            return;
        }

        int index = 0;
        CharKeyReportMap.KeyReport keyReport;
        CharKeyReportMap.KeyReport nextKeyReport = reportList.get(index);
        while (nextKeyReport != null) {
            keyReport = nextKeyReport;
            index++;
            nextKeyReport = (index < reportList.size()) ? reportList.get(index) : null;

            final int modifier = keyReport.getModifier();
            final int keyCode = keyReport.getKeyCode();

            pressModifierKey(modifier);
            pressKey(keyCode);
            releaseKey(keyCode);

            // If the next Modifier value equals the current value then don't reset the Modifier.
            // This saves two unnecessary HID Keyboard Reports.
            if ((nextKeyReport == null) || (nextKeyReport.getModifier() != modifier)) {
                releaseModifierKey(modifier);
            }
        }
    }

    /** Converts a text to a list of Keyboard Reports. */
    private ArrayList<CharKeyReportMap.KeyReport> convertToKeyReports(String text) {
        ArrayList<CharKeyReportMap.KeyReport> result = new ArrayList<CharKeyReportMap.KeyReport>();

        for (int i = 0; i < text.length(); i++) {
            final char character = text.charAt(i);

            CharKeyReportMap.KeyReportSequence keyReportSequence = mCharKeyMap.get(character);
            if (keyReportSequence != null) {
                result.addAll(keyReportSequence);
            } else {
                Log.w(TAG, String.format("unknown Keymap character '%c'", character));
            }
        }

        return result;
    }
}




Java Source Code List

org.ronsdev.bluectrl.ChangelogDialog.java
org.ronsdev.bluectrl.CharKeyReportMap.java
org.ronsdev.bluectrl.DeviceManager.java
org.ronsdev.bluectrl.DevicePreferenceActivity.java
org.ronsdev.bluectrl.DeviceSettings.java
org.ronsdev.bluectrl.HidKeyboard.java
org.ronsdev.bluectrl.HidMouse.java
org.ronsdev.bluectrl.IntArrayList.java
org.ronsdev.bluectrl.KeyEventFuture.java
org.ronsdev.bluectrl.MainActivity.java
org.ronsdev.bluectrl.OnMouseButtonClickListener.java
org.ronsdev.bluectrl.PairedDevice.java
org.ronsdev.bluectrl.PairingActivity.java
org.ronsdev.bluectrl.TouchpadActivity.java
org.ronsdev.bluectrl.TouchpadTutorialActivity.java
org.ronsdev.bluectrl.daemon.DaemonActivity.java
org.ronsdev.bluectrl.daemon.DaemonCallbackReceiver.java
org.ronsdev.bluectrl.daemon.DaemonListActivity.java
org.ronsdev.bluectrl.daemon.DaemonService.java
org.ronsdev.bluectrl.widget.ComposeTextLayout.java
org.ronsdev.bluectrl.widget.FloatSliderPreference.java
org.ronsdev.bluectrl.widget.KeyboardInputView.java
org.ronsdev.bluectrl.widget.MouseTouchListener.java
org.ronsdev.bluectrl.widget.OnKeyboardComposingTextListener.java
org.ronsdev.bluectrl.widget.OnScrollModeChangedListener.java
org.ronsdev.bluectrl.widget.OnSendComposeTextListener.java
org.ronsdev.bluectrl.widget.OnTouchpadGestureListener.java
org.ronsdev.bluectrl.widget.SummaryListPreference.java
org.ronsdev.bluectrl.widget.TouchpadViewGestureListener.java
org.ronsdev.bluectrl.widget.TouchpadView.java