Saturday 13 July 2013

Standard devices: overview

Here is a short overview of classes that can be directly used in Android applications to emulate most common USB devices: keyboard, mouse, gamepad, consumer control:

USBDevice
Base class for any USB device that is emulated using InputStick.

Public methods:

void connect();
Description: initiates connection to InputStick device.

void disconnect();.
Description: terminates connection.

int getState();
Description: returns current connection state:
STATE_NONE - not connected.
STATE_CONNECTING - InputStickUtility is trying to connect to InputStick device.
STATE_CONNECTED - Bluetooth connection has been established.
STATE_READY - USB host has successfully enumerated InputStick device.

void registerListener(USBDeviceListener listener);
Description: registers new listener, which will be notified when connection state changes or when USB host sends data.

void unregisterListener(USBDeviceListener listener);
Description: removes listener, it will no longer receive notifications.

void setContext(Context context);
Description: sets context. Must be called before initiating connection!

 
USBDeviceListener
Interface that must be implemented by a class that wants to be able to receive callbacks when connections state changes or data form USB host is received.

Public methods:

void onUSBData(int endpoint, byte[] data);
Description: called when data form USB host has been received on given endpoint.

void onStateChanged(int state);.
Description: called when connection state changes.

 
USBKeyobard
Generic USB keyboard. It is assumed that USB host uses EN-US keyboard layout (or compatible, example: Polish Programmers).

Public methods:

void type(String text);
Description: types content of text. All non-ASCII characters will be ignored.

void typeUnicodeWindows(String text);
Description: types content of text using Alt Codes. This should allow to type all ASCII characters correctly, regardless of keyboard layout.  All non-ASCII characters will be ignored. Windows only!

void typeUnicodeLinux(String text);
Description: types content of text using hex code. This should allow to type all ASCII characters correctly, regardless of keyboard layout.  All non-ASCII characters will be ignored. Linux only!

void pressAndRelease(byte modifier, byte key);.
Description: first presses modifier keys (Ctrl, Alt, Shift, GUI), then presses key, finally releases all keys.
Modifiers:
ALT_LEFT - left Alt key.
CTRL_LEFT - left Ctrl key.
(...)
Keys:
KEY_A - key "a".
(...)

void delayKeyboard(int duration);
Description: waits at least duration milliseconds (not guaranteed to be precise, may be a few milliseconds longer) before sending next keyboard reports.

void sendKeyboardReport(byte modifier, byte key0, byte key1, byte key2, byte key3, byte key4, byte key5);
Description: sends custom USB keyboard report containing data specified by parameters. Does not change state of the object!

void setNumLock(boolean enable);
Description: sets state of NumLock (disabled/enabled).

void setCapsLock(boolean enable);
Description: sets state of CapsLock (disabled/enabled).

void setScrollLock(boolean enable);
Description: sets state of ScrollLock (disabled/enabled).

boolean isNumLock();
Description: returns state of NumLock.

boolean isCapsLock();
Description: returns state of CapsLock.

boolean isScrollLock();
Description: returns state of ScrollLock.

int getKeyboardProtocol();
Description: returns value of protocol set by USB host.
PROTOCOL_BOOT - for simplified boot protocol.
PROTOCOL_REPORT  - for report protocol.

 
USBMouse
Generic USB mouse: three buttons and vertical scroll wheel (scroll is not available when BOOT protocol is used).

Public methods:

void move(int x, int y);
Description: moves mouse pointer by x and y.

void scroll(int scroll);
Description: moves scroll wheel by scroll. Works only if USB host has set protocol to report protocol.

void click(int button, int duration);.
Description: presses button and releases after duration milliseconds.
BUTTON_LEFT - left mouse button.
BUTTON_RIGHT - right mouse button.
BUTTON_MIDDLE - middle mouse button (scroll wheel).

void setButton(int button, boolean state);.
Description: sets state for given mouse button, which is persisted and affects further calls to move, scroll and click methods.

boolean getButton(int button);.
Description: returns state of mouse button.

void releaseAllButtons();.
Description: releases all mouse buttons.

void delayMouse(int duration);
Description: waits at least duration milliseconds (not guaranteed to be precise, may be a few milliseconds longer) before sending next mouse reports.

void sendMouseReport(byte buttons, byte x, byte y, byte scroll);
Description: sends custom USB mouse report containing data specified by parameters. If protocol is set to BOOT, value of scroll will be ignored. Does not change state of the object!

int getMouseProtocol();
Description: returns value of protocol set by USB host.
PROTOCOL_BOOT - for simplified boot protocol.
PROTOCOL_REPORT  - for report protocol.

 
USBConsumerControl
Input device that allows to control media playback, system volume, power state, launch applications (browser, e-mail client etc.). Keep in mind that some actions are not supported by all operating systems or results of given action may be different, depending on OS.

Public methods:

void consumerReport(int code);
Description: sends consumer control report containing specified code.
VOL_UP - increase system volume.
VOL_DOWN - decrease system volume.
VOL_MUTE - mute/unmute.
(...)

void systemReport(int code);
Description: sends system report containing specified code.
POWER_DOWN - power down system.
SLEEP - put system to stand-by.
(...)

void delayConsumer(int duration);
Description: waits at least duration milliseconds (not guaranteed to be precise, may be a few milliseconds longer) before sending next consumer control reports.
 

USBGamepad
Generic USB gamepad: 16 buttons and 4 axes (X,Y,Z,rZ).

Public methods:

void setXAxis(int value);
Description: sets value of X axis, which is persisted and affects further calls to sendGamepadReport method.

void setYAxis(int value);
Description: sets value of Y axis, which is persisted and affects further calls to sendGamepadReport method.

void setZAxis(int value);
Description: sets value of Z axis, which is persisted and affects further calls to sendGamepadReport method.

void setRZAxis(int value);
Description: sets value of rZ axis, which is persisted and affects further calls to sendGamepadReport method.

void resetAxes();.
Description: sets all axes to 0. Affects further calls to sendGamepadReport method.

void setButton(int button, boolean state);.
Description: sets state for given gamepad button (1-16), which is persisted and affects further calls to sendGamepadReport method.

boolean getButton(int button);.
Description: returns state of gamepad button (1-16).

void releaseAllButtons();.
Description: releases all gamepad buttons. Affects further calls to sendGamepadReport method.

void delayGamepad(int duration);
Description: waits at least duration milliseconds (not guaranteed to be precise, may be a few milliseconds longer) before sending next gamepad reports.

void sendGamepadReport();
Description: sends USB gamepad report, which is based on current state of the object (buttons, axes).

void sendGamepadReport(byte buttons1, byte buttons2, byte x, byte y, byte z, byte rz);
Description: sends custom USB gamepad report containing data specified by parameters. Does not change state of the object!


USBKeyobardMouse
Composite USB device composed of three interfaces: USB keyboard, USB Mouse and USB ConsumerControl.

Public methods: same as in USBKeyboard, USBMouse and USBConsumerControl.


In most cases using these classes should be easy and produce expected results. However we should not make any assumptions about USB host: hardware (PC or maybe a game console), operating system, keyboard layout and screen resolution. With USB mouse, solution is quiet simple: simple sensitivity setting. In case of USB keyboard it is more complicated, since there are dozens of keyboard layouts. I came up with an idea, to enter characters using Unicode, but unfortunately this is OS-dependent (Alt+ numeric keypad digits on Windows).

2 comments:

  1. Would there be any support for pushing files through Bluetooth to the USB? I know that it might have to be remounted as Mass Storage(but I'm no dev; I don't know what I'm talking about!). That said, there would have to be either 1.Big Temporary Storage or 2.Permanent Storage...

    I'm only suggesting these as I really want your project to go well!

    ~xJokerzz

    ReplyDelete
    Replies
    1. In theory it should be possible to use Mass Storage Device class, but there are some problems with that:
      1) internal "storage" is almost entirely occupied by bootloader & firmware, so there is something like just a few KB left.
      2) Bluetooth connection between Android device and InputStick allows to send 10 KBps. After taking into account protocol overhead and latency you probably will end up with something like 5 KBps.

      So the question is if using InputStick as a flash drive with such low transfer rate has any sense at all. Maybe in some cases, like transferring really small text files, configuration files, generally anything that has really small size. So, MSD class at this moment has very low priority for me, maybe some time later I will try to implement this (probably just for fun, but who knows, maybe there is some useful use case for that). At this moment I want to focus mainly on Human Interface Device class. I hope I will be able to implement emulation of Sony Sixaxis controller soon.

      Delete