package andraus.bluetoothhidemu.sock.payload;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import andraus.bluetoothhidemu.util.DoLog;
import android.view.KeyEvent;
/**
* Regular keyboard payload.
*/
public class HidKeyboardPayload extends HidPayload {
private static final String TAG = HidPayload.TAG;
private static final int SIZE = 10;
private static final int MODF_NULL = 0x00;
private static final int MODF_SHIFT = 0x02;
private static final int REPORT_ID_KEYBOARD = 0x01;
// Static map for keys
private static final Map<Character, HidKeyPair> CHAR_HID_MAP;
static {
Map<Character, HidKeyPair>charHidMap = new HashMap<Character, HidKeyPair>();
charHidMap.put(Character.valueOf(Character.MIN_VALUE), new HidKeyPair(0x00, MODF_NULL));
charHidMap.put('a', new HidKeyPair(0x04, MODF_NULL));
charHidMap.put('b', new HidKeyPair(0x05, MODF_NULL));
charHidMap.put('c', new HidKeyPair(0x06, MODF_NULL));
charHidMap.put('d', new HidKeyPair(0x07, MODF_NULL));
charHidMap.put('e', new HidKeyPair(0x08, MODF_NULL));
charHidMap.put('f', new HidKeyPair(0x09, MODF_NULL));
charHidMap.put('g', new HidKeyPair(0x0a, MODF_NULL));
charHidMap.put('h', new HidKeyPair(0x0b, MODF_NULL));
charHidMap.put('i', new HidKeyPair(0x0c, MODF_NULL));
charHidMap.put('j', new HidKeyPair(0x0d, MODF_NULL));
charHidMap.put('k', new HidKeyPair(0x0e, MODF_NULL));
charHidMap.put('l', new HidKeyPair(0x0f, MODF_NULL));
charHidMap.put('m', new HidKeyPair(0x10, MODF_NULL));
charHidMap.put('n', new HidKeyPair(0x11, MODF_NULL));
charHidMap.put('o', new HidKeyPair(0x12, MODF_NULL));
charHidMap.put('p', new HidKeyPair(0x13, MODF_NULL));
charHidMap.put('q', new HidKeyPair(0x14, MODF_NULL));
charHidMap.put('r', new HidKeyPair(0x15, MODF_NULL));
charHidMap.put('s', new HidKeyPair(0x16, MODF_NULL));
charHidMap.put('t', new HidKeyPair(0x17, MODF_NULL));
charHidMap.put('u', new HidKeyPair(0x18, MODF_NULL));
charHidMap.put('v', new HidKeyPair(0x19, MODF_NULL));
charHidMap.put('w', new HidKeyPair(0x1a, MODF_NULL));
charHidMap.put('x', new HidKeyPair(0x1b, MODF_NULL));
charHidMap.put('y', new HidKeyPair(0x1c, MODF_NULL));
charHidMap.put('z', new HidKeyPair(0x1d, MODF_NULL));
charHidMap.put('1', new HidKeyPair(0x1e, MODF_NULL));
charHidMap.put('!', new HidKeyPair(0x1e, MODF_SHIFT));
charHidMap.put('2', new HidKeyPair(0x1f, MODF_NULL));
charHidMap.put('@', new HidKeyPair(0x1f, MODF_SHIFT));
charHidMap.put('3', new HidKeyPair(0x20, MODF_NULL));
charHidMap.put('#', new HidKeyPair(0x20, MODF_SHIFT));
charHidMap.put('4', new HidKeyPair(0x21, MODF_NULL));
charHidMap.put('$', new HidKeyPair(0x21, MODF_SHIFT));
charHidMap.put('5', new HidKeyPair(0x22, MODF_NULL));
charHidMap.put('%', new HidKeyPair(0x22, MODF_SHIFT));
charHidMap.put('6', new HidKeyPair(0x23, MODF_NULL));
charHidMap.put('^', new HidKeyPair(0x23, MODF_SHIFT));
charHidMap.put('7', new HidKeyPair(0x24, MODF_NULL));
charHidMap.put('&', new HidKeyPair(0x24, MODF_SHIFT));
charHidMap.put('8', new HidKeyPair(0x25, MODF_NULL));
charHidMap.put('*', new HidKeyPair(0x25, MODF_SHIFT));
charHidMap.put('9', new HidKeyPair(0x26, MODF_NULL));
charHidMap.put('(', new HidKeyPair(0x26, MODF_SHIFT));
charHidMap.put('0', new HidKeyPair(0x27, MODF_NULL));
charHidMap.put(')', new HidKeyPair(0x27, MODF_SHIFT));
charHidMap.put(HidKeyPair.ENTER, new HidKeyPair(0x28, MODF_NULL));
charHidMap.put(HidKeyPair.DEL, new HidKeyPair(0x2a, MODF_NULL));
charHidMap.put(' ', new HidKeyPair(0x2c, MODF_NULL));
charHidMap.put('-', new HidKeyPair(0x2d, MODF_NULL));
charHidMap.put('_', new HidKeyPair(0x2d, MODF_SHIFT));
charHidMap.put('=', new HidKeyPair(0x2e, MODF_NULL));
charHidMap.put('+', new HidKeyPair(0x2e, MODF_SHIFT));
charHidMap.put('[', new HidKeyPair(0x2f, MODF_NULL));
charHidMap.put('{', new HidKeyPair(0x2f, MODF_SHIFT));
charHidMap.put(']', new HidKeyPair(0x30, MODF_NULL));
charHidMap.put('}', new HidKeyPair(0x30, MODF_SHIFT));
charHidMap.put(HidKeyPair.INV_BACKSLASH, new HidKeyPair(0x31, MODF_NULL));
charHidMap.put('|', new HidKeyPair(0x31, MODF_SHIFT));
charHidMap.put(';', new HidKeyPair(0x33, MODF_NULL));
charHidMap.put(':', new HidKeyPair(0x33, MODF_SHIFT));
charHidMap.put(HidKeyPair.QUOTE, new HidKeyPair(0x34, MODF_NULL));
charHidMap.put(HidKeyPair.DB_QUOTE, new HidKeyPair(0x34, MODF_SHIFT));
charHidMap.put('`', new HidKeyPair(0x35, MODF_NULL));
charHidMap.put('~', new HidKeyPair(0x35, MODF_SHIFT));
charHidMap.put(',', new HidKeyPair(0x36, MODF_NULL));
charHidMap.put('<', new HidKeyPair(0x36, MODF_SHIFT));
charHidMap.put('.', new HidKeyPair(0x37, MODF_NULL));
charHidMap.put('>', new HidKeyPair(0x37, MODF_SHIFT));
charHidMap.put('/', new HidKeyPair(0x38, MODF_NULL));
charHidMap.put('?', new HidKeyPair(0x38, MODF_SHIFT));
CHAR_HID_MAP = Collections.unmodifiableMap(charHidMap);
}
private static final Map<Integer, HidKeyPair> KEYCODE_HID_MAP;
static {
Map<Integer, HidKeyPair>keyCodeHidMap = new HashMap<Integer, HidKeyPair>();
keyCodeHidMap.put(Integer.valueOf(0), new HidKeyPair(0x00, MODF_NULL));
keyCodeHidMap.put(Integer.valueOf(KeyEvent.KEYCODE_DPAD_RIGHT), new HidKeyPair(0x4f, MODF_NULL));
keyCodeHidMap.put(Integer.valueOf(KeyEvent.KEYCODE_DPAD_LEFT), new HidKeyPair(0x50, MODF_NULL));
keyCodeHidMap.put(Integer.valueOf(KeyEvent.KEYCODE_DPAD_UP), new HidKeyPair(0x52, MODF_NULL));
keyCodeHidMap.put(Integer.valueOf(KeyEvent.KEYCODE_DPAD_DOWN), new HidKeyPair(0x51, MODF_NULL));
keyCodeHidMap.put(Integer.valueOf(KeyEvent.KEYCODE_ENTER), new HidKeyPair(0x28, MODF_NULL));
keyCodeHidMap.put(Integer.valueOf(KeyEvent.KEYCODE_BACK), new HidKeyPair(0x29, MODF_NULL));
keyCodeHidMap.put(Integer.valueOf(KeyEvent.KEYCODE_VOLUME_UP), new HidKeyPair(0x80, MODF_NULL));
keyCodeHidMap.put(Integer.valueOf(KeyEvent.KEYCODE_VOLUME_DOWN), new HidKeyPair(0x81, MODF_NULL));
KEYCODE_HID_MAP = Collections.unmodifiableMap(keyCodeHidMap);
}
/**
*
* @param size
*/
public HidKeyboardPayload() {
super(SIZE);
mPayload[0] = (byte)0xa1;
mPayload[1] = (byte)REPORT_ID_KEYBOARD; // report_id (keyboard)
mPayload[2] = (byte)0x00; // modifier
mPayload[3] = (byte)0x00; // reserved
mPayload[4] = (byte)0x00; // keycode
mPayload[5] = (byte)0x00; // keycode
mPayload[6] = (byte)0x00; // keycode
mPayload[7] = (byte)0x00; // keycode
mPayload[8] = (byte)0x00; // keycode
mPayload[9] = (byte)0x00; // keycode
}
/**
*
* @param value
*/
public void setModifier(int value) {
setByte(2, value);
}
/**
*
* @param value
*/
public void setKeycode(int value) {
setByte(4, value);
}
/**
*
*/
public void resetBytes() {
setModifier(0x00);
setKeycode(0x00);
}
/**
* Assemble a HID payload byte array for specified character
* @param keyCode - Android framework keycode
*
*/
public void assemblePayload(char character) {
resetBytes();
// logic to handle uppercase letters. this avoids duplicating entries in CHAR_HID_MAP for uppercase letters.
int overrideModifier = -1;
if (Character.isUpperCase(character)) {
character = Character.toLowerCase(character);
overrideModifier = MODF_SHIFT;
}
HidKeyPair hidByteSet = CHAR_HID_MAP.get(Character.valueOf(character));
if (overrideModifier > 0) {
hidByteSet = new HidKeyPair(hidByteSet.getCode(), overrideModifier);
}
if (hidByteSet == null) {
DoLog.w(TAG, "No hid code found for character = " + character);
} else {
setModifier(hidByteSet.getMod());
setKeycode(hidByteSet.getCode());
}
}
/**
* Assemble a HID payload byte array for specified keyCode (see KeyEvent)
* @param keyCode
*/
public void assemblePayload(int keyCode) {
resetBytes();
HidKeyPair hidByteSet = KEYCODE_HID_MAP.get(Integer.valueOf(keyCode));
if (hidByteSet == null) {
DoLog.w(TAG, "Nod hid code found for keyCode = " + keyCode);
} else {
setModifier(hidByteSet.getMod());
setKeycode(hidByteSet.getCode());
}
}
}