Tuesday 31 December 2013

Pre-orders

PRE-ORDER


I've just started InputStick campaign on Indiegogo. All the details are on the campaign page, so there is no point in duplicating this here. As I've already mentioned in my previous post, this is more of a pre-orders than crowdfunding, what basically means that you'll get InputStick regardless of whether funding goal is reached or not. Since most of the development is already done, the funding goal is set relatively low. During first few days there won't be much promotion going on, but I'll definitely put a lot of effort into this during January 2014.

Why pre-order? All pre-orders get free international shipment (well, to be more precise it's already included in the price), also you'll be sure to receive InputStick from the very first production run. At this moment I can't guarantee anything about how many units will be available after the pre-orders are over and when next batch will be manufactured. Last but not least, number of pre-ordered units will allow me to estimate how many people are actually interested in this project and as a result I may put additional resources into applications development (UI, custom icons, additional functionality, possible new apps).

I'd really appreciate if you could share campaign URL: http://igg.me/at/inputstick with anyone who might be potentially interested in InputStick. Thanks! :)

Monday 23 December 2013

Almost there

It's been over a month since my last post here. During that time I've been mostly busy with getting InputStick ready for a CE certification process. Making a working prototype is one thing, turning it into commercially available product that's a whole other story. It turned out that my latest PCB revision failed at some tests (ESD), but after some modifications it looks like this shouldn't be a problem anymore. At this point I think that I've managed to deal with most critical things and I'm finally ready to start taking pre-orders, without risking a possibility of a massive delay.


Campaign will go live in next few days (most probably on December 27th) and will last till February 2nd 2014. Since I'm able to finish InputStick development with my own funds, this is more of a pre-order that a crowdfunding campaign. The difference is that InputStick will go into production whether or not funding goal is reached. As you'll probably notice, estimated delivery date is set to March 2014, which is more than two months form now. Why so late? Well, main reason for this is certification process, which will require a lot of paperwork and many things will depend more on availability of my test lab than on me. I will also need some time for manufacturing (up to two weeks) and finally one-two weeks for delivery. In the meantime I will have a lot of time to work on improving API and Android apps.

Wednesday 13 November 2013

Video presentation

Here's an InputStick video presentation:


Please, let me know what do you think about the video? Does it miss anything important? Is something not clear or needs more attention? I'll really appreciate any comments and suggestions. Some changes will definitely be necessary, since I have finally received new enclosures with InputStick logo on it. Because shipment was delayed a bit, I have started making video with what I had available at the time. Anyway, here you can see how final version of InputStick looks like. There will be two versions available: black and white.



Tuesday 15 October 2013

New PCB and enclosure

Some time ago, I've decided to switch to a different type of enclosure. Here is the result:




Old InputStick vs new one:




Changes than can be noticed by end user:
  • Cap "locks" in opened/closed positions.
  • Takes less space in "opened" position.
  • Weight reduced to 8g (from 15g).
  • Dimensions: 57.5mm x 19.5mm x 9.5mm (vs 56.5mm x 19.5mm x 10.5mm).
There are also some changes that were made to make InputStick easier to manufacture:
  • More space inside enclosure allowed to improve PCB layout. Now it is easier to attach debugger/programmer.
  • Pushing back Bluetooth module by 1mm allowed to use SMT USB connector. Also, now there are proper slots for mounting it.
  • Some minor layout changes.
So far everything looks good. I'm not 100% sure about the colour yet. It may remain black and white or it will be entirely black or white. Of course final version will also include logo.
 
BTW: I've also received an estimate for contract manufacturing, however there are still some details to discuss.

Wednesday 9 October 2013

System keyboard input for RemoteController

While waiting for new PCBs to arrive, I did some improvements to RemoteController app. Now it is possible to choose between using my custom keyboard (which needs some customization options):
 
My custom keyboard.
 
and Android system keyboard:
 
Horizontal orientation, "SwiftKey Keyboard".

At first I didn't want to use Android keyboards, since I assumed that no keyboard offers all additional "PC" keys. Looks like I should have done some more research on this. Thanks to Max for letting me know about "Hacker's Keyboard", which has all necessary keys:

Vertical orientation, "Hacker's Keyboard".

Hacker's Keyboard also introduces additional keys known from PC keyboards.

A few words about keyboard-related API in Android:
  • Android 2.3 does not support "Ctrl" key.
  • There is no way to check what keyboard layout is currently in use.
  • Multi-character input like swype or dictionary predictions is not supported in this case.
  • Detecting if soft keyboard is visible is kind of a hack (checking difference in size of root view).
As a result of that, I had to add separate toggle buttons for modifier keys. It also looks like it will be necessary to add option to manually select keyboard layout used by USB host. It is not possible to get this kind of information form the host and it turns out that even if I wanted to assume that it is identical to the one used by soft keyboard, there is also no way to check what layout it actually is. There is a small problem related to arrow keys: depending on which UI element has the focus, they may work as indented or switch between tabs. Besides that, everything works just fine :)
 


Thursday 3 October 2013

TrueCrypt Widget

Some time ago I've shown you Password Manager application. This post is also related to passwords. I've created a very simple widget that uses InputStick to type my TrueCrypt password for encrypted system partition. The most important fact is that now all it takes to type the password is just a single click.

Here's a quick comparison of steps required to type the password:

Password Manager:
  1. Run application.
  2. Type master password.
  3. Connect to InputStick (although auto connect feature will be added).
  4. Click on "TrueCrypt" item.
  5. Select  "Password" entry.
  6. Press "Type" button.

Widget:
  1. Click on the widget.

In both cases it is assumed that there is only one InputStick paired with the phone, otherwise you have to manually select InputStick device (unless DeviceManager is set to always connect to "Default" device). Also, I assume that Bluetooth radio is already on, if not you will be asked if you want to enable it.

But what about security? Is it safe this way? Well, in this case I think that it is:
  • TrueCrypt is used to protect data in case my laptop gets lost or stolen.
  • If I loose both my laptop and phone, it is still protected by relatively complex pattern lock.
  • Even if phone is unlocked the only (simple) way to get the password is to type it with InputStick, there is no "show plaintext" option.
  • Data stored on system partition is not something that can be remotely accessed, unlike, for example: email account.
So the only scenario in which my data can be compromised is when I loose all three devices: laptop, phone, InputStick and somehow phone remains unlocked. In my opinion: highly unlikely. However, for anything that can be remotely accessed I will still use Password Manager.

Here you can see the widget conveniently placed on my homescreen:

TrueCrypt Widget placed on homescreen.

After clicking on it, it hides icon and shows progress bar. When everything is done, it returns to initial state.

TrueCrypt Widget at work :)

And here's a short video showing how this actually works:



Also, if anyone is interested, take a look at the source code. Most part of the widget is based on this tutorial.

Main widget class: MyWidget.java:


Background service, which is actually doing all the work: WidgetService.java

Wednesday 2 October 2013

Some videos ...and AES encryption

Let's start with some videos:

Pairing InputStick with Android phone and InputStick Device Manager (Utility) application. As you can see takes about one minute.




USB Remote app in action.




USB Gamepad. Works with Linux (Ubuntu) out of the box. No need to configure anything. Game: TuxRacer.




USB Presentation Remote:




and finally, USB BarcodeScanner.



AES Encryption.

Recently I've been working on implementing AES-128 encryption in order to additionally secure communication with InputStick. Since one of use cases is using InputStick with Password Manager this is rather important, although InputStick is already using secured Bluetooth connection. 
At this moment AES encryption works on both ends: InputStick background service and device's firmware. There are still some performance issues, however some optimisation should solve this. Anyway, I was able to achieve about 30KBps data encryption/decryption rate @ 48 MHz MCU clock speed.
Since adding encryption will require firmware upgrade, I won't be including it in API for some time, until it is 100% tested.

Thursday 12 September 2013

Project update

Here's a brief list of things that I've done recently:


InputStick background service:
  • fixed some issues that caused the service to crash.
  • service now makes several attempts to establish a Bluetooth connection.
  • added support for resuming session.

DeviceManager (app): 
  • verifying device before adding to database.
  • notifications in status bar.
  • sub-menu instead of context menu in DeviceList.
  • application asks user to enable Bluetooth only when this is necessary
  • added "Test" functionality, which configures InputStick as a USB keyboard, logs communication and allows to send test report back to me (via email).

Main activity


No more context menu.


API:
  • added support for resuming session. 
  • added request callbacks.

So now each subclass of USBDevice can override following methods:

public void resetState();
Resets state of USBDevice, called after device state has been set to "Configured" by USB host, or when previous session has been resumed.

public void incomingData(int endp, byte[] data);
Called when new report is received form USB host.

public void incomingResumeData(int endp, byte[] data);
Called when session is resumed. Sends all reports stored in buffer for given endpoint. This allows to get most recent state of the device, which could have changed when application was not connected to InputStick However, each time there is no more free space in buffer, oldest reports are removed. Is this a problem? Well, that depends on a particular USB device. In case of USB keyboard, we are interested only in most recent state of Num/Caps/Scroll lock, so we don't care about previous reports.

public void incomingRequest(int requestNo, DeviceInfo info);
Called when host sends USB request. requestNo indicates which request has been received (this depends on order in which requests has been added), info allows to get data from setup packet (bmRequestType, bRequest, wValue, wIndex, wLength and some additional info).

public void incomingResumeRequest(int requestNo, DeviceInfo info);
This works similar to  incomingResumeData. And again, in case of USB mouse we are interested only in most recent value of report protocol set by USB host. In case of generic USB keyboard, report and boot protocols are exactly the same.


Hardware:

I thing about using slightly different model of enclosure. This one has a little bit more space inside, what will allow to improve PCB design (easier to assemble, better access to programmer/debugger pins). Also, it is made entirely from plastic, so InputStick weights 50% less than before. At this moment I'm almost done with redesigning PCB layout, so new PCBs should arrive next week.



Wednesday 21 August 2013

Samples and API: getting started

Several people have already received their samples. I've got more requests about samples, so I think about going for a short pick-and-place assembly run. Hand-soldering is OK for 1-2 prototypes, otherwise it just takes way too much time. Currently I'm waiting to get quotes.

Here's a simple "getting started" guide:

Device Manager (InputStickUtility):

To use InputStick you have to install DeviceManager app on your Android phone.

Installation:
  • Make sure that "allow installation of non-market applications" is checked in your devices settings.
  • Copy DeviceManager.apk to your device and install it.

Pairing with InputStick:
  • Plug InputStick into any USB port in order to power it up.
  • Run DeviceManager, if Bluetooth is disabled it will ask you to enable it. 
  • Manage devices -> Add device -> Discover device -> Select device form the list -> Add device.
  • By default it will be named "Dev-00" and set as "Home", however application will ask you if you want to edit this.
Settings:

Dialog settings:
  • Always ask: each time you will be asked to manually select InputStick device that you want to connect to. Use this if you want to be sure that no application will be able to connect to InputStick without you knowing.
  • Ask when more than 1 [Default]: you will be asked to select device only when more than one InputStick is paired with your phone. Otherwise it will connect automatically.
  • Never ask: you won't be bothered with dialog. If there is more than one device paired, it will attempt to connect to the one marked as "Default device".
Toast settings:
  • Show all - show all toasts, useful mainly in my case.
  • Show important - show only important toasts, useful for application developers.
  • Show none [Default] : DeviceManager won't be displaying any Toast messages.
Status Bar Notifications:
  • Enabled - notification will be displayed when InputStick device is in use.
  • Disabled - no notifications will be displayed.

Demo apps:

Use Connect/Disconnect button, exact behaviour depends on configuration of DeviceManager.  If it is the first time that you are using your InputStick device you will be asked to enter PIN code (1234), unless you have already paired it manually.

BUG: if attempt to establish Bluetooth connection fails (InputStick not plugged in, out of range etc), pressing "Connect" again will do nothing. You have to kill the app and try again. Next API release will solve this issue.

Depending on USB host, OS, and settings it may take some time to detect new hardware and install drivers.  During this period you won't be able to use application, even though it may appear to be ready. Next time, this should be much faster (OS will recognize the device using PID/VID pair).


API & Demos:

Import InputStickLibrary project into Eclipse:

  • File -> Import -> Existing projects into workspace -> browse -> select InputStickLibrary directory -> check "Copy into workspace" -> Finish

Depending on your ADT version you may get some error messages, in such case go to:
  • Project Properties -> Android -> Select build target -> OK
  • Android Tools -> Fix project properties
This should fix all error messages. Do the same for demo projects.

Starting new project:

  • Create new Android project. Choose minimum SDK > 2.3. 
  • Project Properties -> Android -> Add -> Select InputStickLibrary -> OK

Using API in your project:

Let's take "HelloInputStick" project as an example. This simple app uses USBKeyboard class to type:

Hello world!
XyZ

This version is a little bit different from the one posted some time ago. Comments should explain everything. (GitHub)



For other device classes see: this post

Friday 2 August 2013

Project update

TL;DR

Current project status:
  • Bootloader: finished.
  • Firmware: works :) (can be upgraded via Bluetooth if necessary).
  • API: works, but needs some improvements.
  • Applications: no changes here, first I have to finish dealing with the API.
 New features:
  • Storing device configuration in flash memory.
  • Storing USB reports in flash memory.
  • OnDisconnect event.
  • Resuming USB session.
 Upcoming features (rather low priority):
  • AES128 encryption.
  • data compression.
Production & availability:
  • I should have some samples available next week (hopefully on Monday).
  • Indiegogo campaign as a form of pre-order?
  • EMC testing (this and all CE related stuff will be covered someday in a separate post).

OK, now if anyone is interested in details:

Storing device configuration in flash memory:
First, I want to remind you how InputStick behaved some time ago:
  1. Plug InputStick into USB port.
  2. Run Android application.
  3. Connect to InputStick.
  4. Configuration data is uploaded.
  5. System enumerates InputStick as some sort of USB device (depending on the configuration).
  6. Do stuff.
  7. Disconnect.
Now, some real-life testing revealed following problem:
Device enumeration (step 5) requires some time. Usually it takes, just a few hundreds milliseconds, so you won't even notice any delay, but in some scenarios this can take even several seconds. Example: Windows recognises new device, but even though it is a standard HID keyboard it attempts to search for a driver using Windows Update, what may take some time in case of slow Internet connection. At this moment user has already started Android application, so he/she has to wait for
enumeration process to finish. And most of us don't like to wait... If you once again take a look at steps 1 - 7, you will see that this would be less inconvenient if InputStick was able to start enumeration earlier, preferable right after plugging into USB port. So I came up with following solution: user can store device configuration in microcontrollers flash memory (using DeviceManager app), so it can begin enumeration immediately. In such case, it should be ready to go, even before user runs application. Of course this is optional, so if you are going to use InputStick with single PC, there is no need to do that, however it may be really helpful if you often use different PCs (at work? at school/university?).


Storing USB reports in flash memory:
Now, if you can store device configuration in flash, why not add some USB reports? This allows to execute some actions, without having to use Android application. Example:

Device configuration: generic USB keyboard
USB reports: TrueCrypt password followed by "Enter" key.
 
so as a result such configuration turns InputStick into keyboard that automatically types my  system partition passwords and allows Windows to boot. What if, at a given moment I don't want it to type my password? For that purpose I've decided to add timeout feature: wait, let's say 10 seconds for incoming connection, if nothing connects during that period, put reports into queue. The question, if storing system partition password this way is a good idea is another thing, this is just an example. Just like in previous case, this is purely optional, I just think that in some cases such feature might be useful.

OnDisconnect event:
Imagine following scenario: user uses RemoteController application, and presses "Enter" key. This sends two USB reports: press Enter key, release enter key. Now, what happens is smartphone crashes or battery runs out after first report (press) is sent, but before second one (release)? It will result in Enter key being constantly pressed. And you really don't want that to happen, especially if you deal with money. This can be partially solved using InputStick API: send such reports only in one transaction, so either both are received or none. But if we want to allow application to press key and hold it for some indefinite period of time, then if something unexpected happens, it will stay like that forever (or at least until InputStick is removed from USB port).
If connection is unexpectedly lost it would be ideal to send USB report which releases all keys. So here's another new feature: you can upload few USB reports which will be put into queue in case if connection is unexpectedly lost. Usually it will be something like releasing all keys, buttons, setting axes to 0 (gamepad) etc. but you can get more creative here, for example: send Win+L combination to lock PC (Windows) if a smartphone gets out of InputStick range.

Resuming USB session:
New firmware allows to resume session, so the device does not need to go through enumeration process again. In case of most HID devices, you can simply disconnect and leave it enumerated, then connect again after some time and resume activity. When session is resumed, InputStick API asks the device to send all latest output reports and information about processed USB requests. This allows to get latest state of the device. Example: USB keyboard class will get information about state of NumLock, CapsLock and ScrollLock LEDs (most recent OUT report) as well as selected protocol (most recent SetProtocol request). In case of devices like simple mouse (without scroll), this step can be skipped, since there is nothing that influences such device.

AES128 encryption:
Although Bluetooth connection is already encrypted, I decided to make some minor changes in communication protocol, which will allow to implement additional layer of encryption later on. So at this moment it is just an idea.

Data compression:
In case of some USB reports, like for example keyboard, there are many bytes which are mostly zeros, so even very simple compression method will allow to reduce payload size by >50%. Because data throughput is heavily limited, this may be a good idea, but just like in previous case, at this moment I'm not going to implement this feature yet.

Samples:
I hope to have several samples available on Monday. Since firmware and applications are still in beta, I think that samples are mainly for Android developers. Without fully functional apps InputStick will be of little to no use for other people.

Indiegogo:
So, I think about (finally) starting Indiegogo campaign this month. My first attempt at making a promotional video wasn't too impressive, so I need to give it (at least) one more try. Also, I have to carefully consider all factors, like components prices at different quantities, taxes, shipment rates and so on.

EMC testing:
Recently I've been able to make some quick EMC tests. It looks like current version of InputStick should be able to pass all tests required for CE certification.
 

Saturday 27 July 2013

New enclosures

On Thursday I've received enclosures with custom logo. Looks exactly as expected:


There is only one problem: even though all enclosures of this kind looks exactly the same on the outside, on the inside all (that I have) are different (other two are from disassembled USB flash drives).


First one from the left is the one that I've ordered. Now, if you take a look at the latest PCB revision:


it obviously won't fit in there, since it was designed basing on the first enclosure form the right (blue one). Fortunately it's not a big deal. For now, I will just remove parts of the enclosure marked by red arrows, so as a result I will get something similar to the enclosure in the middle. Next PCB revision will obviously be redesigned to fit, without having to cut out anything.

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).

Friday 12 July 2013

Enclosure with custom logo

I know that this probably doesn't look too impressive, but for now it should do:

I'm about to order several such enclosures. Hope I will get them soon :)

Monday 8 July 2013

InputStick API

Many Android applications can benefit form using InputStick: remote controllers, password managers, barcode scanners and many more. My main goal was to design API in such a way, that using InputStick in existing applications will be fast and easy.

InputStick API is divided into two layers: API classes and Utility application consisting of  background service and user interface. This separates interface which represents USB device form the whole mechanism that uses InputStick to emulate it. InputStick API uses inter-process communication to exchange data with background service.


This allowed to achieve following goals:
  • using InputStick in Android applications is very easy.
  • user application does not need Bluetooth permissions.
  • most of InputStick-related user interactions are handled by InputStickUtility, which always provides user with the same interface.
  • maintaining compatibility of applications using older API version with possible newer firmware/protocol.
  • increased data security.
  • protecting hardware form being simultaneously accessed by more than one application.
Are there any drawbacks? Inter-process communication introduces additional latency, still it is less than a millisecond on most mid-end and high-end devices. Of course it also consumes some additional system resources, but that is a small price to pay for all the advantages.


InputStick API classes.

InputStick API is a set of Java classes that are directly used in application. API takes care of communicating with background service. In case if InputStickUtility is not installed, it will ask user to download the application form Google Play (at this moment it is not yet released). Most applications will use one of following standard device classes:
  • USB Keyboard
  • USB Mouse
  • USB Gamepad
  • USB Keyboard & USB Mouse & USB Consumer Control
where all it takes is to call methods corresponding to desired behaviour of the device (press key, move cursor, click, etc). Application should also handle callbacks generated when there is a change of connection state or when USB data is received (example: change of keyboard LEDs: NumLock, CapsLock, ScrollLock). Developer can focus on implementing additional functionality, while everything USB-related is taken care of by the API.

If you would like to emulate non-standard USB device, API provides a set of classes that allows you to use Java to create:
  • USB Descriptors (to define device capabilities)
  • USB Requests (define how to respond to specific type of USB host request)
  • Endpoint Configuration, Data Buffers Configuration etc.
This allows to emulate almost any kind of USB HID (Human Interface Device) hardware, but keep in mind that there are some limitations (more on that at the end).


InputStickUtility.

InputStickUtility is an Android application that is required to be installed on any Android device that will be used with InputStick. Utility application provides user interface that takes care of:
  • pairing with InputStick devices.
  • selecting appropriate InputStick device at a given moment.
  • displaying notifications.
  • handling connection errors.
  • performing firmware upgrade.
User benefits form the fact that all InputStick related activities are always performed in exactly the same manner, regardless of what application wants to use InputStick, while application developers do not have to include additional user interface elements. The other task of Utility application is handled by background service. It acts as a proxy between users application and InputStick hardware. This allows to protect InputStick hardware form simultaneous access form two applications and does not allow user applications to modify internal firmware. Since all traffic goes through the service, it can maintain compatibility with applications compiled using previous API versions, in case if new communication protocol is introduced in the future. Last but not least, user application is simpler since it does not have to manage Bluetooth connection and everything related to that (enabling Bluetooth radio, dealing with unexpected situation like loosing connection, etc.).


Limitations.

InputStick can be recognised by USB host as any (full speed) USB device, depending on provided USB descriptors. However that does not mean that you can actually make it work. There are three main limiting factors:

Bluetooth: InputStcik communicates with Android device using Bluetooth link. This limits maximum data throughput to 12.5 KBps, what results in approximately 10 KBps for user data, after taking into account overhead introduced by transport protocol. It also introduces several milliseconds of latency.

USB: interrupt transfer type, used in HID devices, allows to set minimal polling interval to 1 millisecond, what limits maximal number of reports per second to 1000.

API: InputStick API allows to emulate most of Human Interface Devices and many other kinds of USB devices, however it may not be possible to emulate some types of devices which express non-standard behaviour.

To sum up: InputStick should allow to emulate most of Human Interface Devices, where 10 KBps throughput is in most cases enough to provide data even for 1000 reports every second. It should be also possible to implement mass storage device, however 5 KBps transfer rate (additional overhead and latency must be taken into account) makes it rather impractical. Finally, 10 KBps is simply not enough for audio class.

 
Example.

Here is a simple example of how to use InputStick API in Android application. Application emulates USB keyboard and when user presses a button, it types "Hello world!". Let's start with a source code:


Here is what we get:

Main Activity.
 
InputStickUtility takes care of asking user to select InputStick device to use.


Just a few more seconds...

Connected!

InputStick is detected as a generic USB keyboard.


This is a result of pressing "Say Hello" button.

As you can see, it was enough to add several lines of code to allow Android application to use InputStick to emulate USB keyboard.

I hope that this more or less explains how InputStick API is designed. There is still some work to be done, but I estimate that I should be able to release it by the end of this month.

Tuesday 2 July 2013

InputStick and PlayStation 3

Just a quick post related to PlayStation 3. PS3 supports many different kinds of USB devices, but I'm mainly interested in the following: keyboard, mouse and gamepad. Unfortunately there are some limitations: you can't use keyboard or mouse to play games, also generic HID gamepad is supported only by some titles (for example: Dirt Showdown).

What I've been able to confirm is that my implementation of:
  • USB Keyboard: works
  • USB Mouse: works
  • USB Consumer Control: does not work :(
  • USB Keyboard & Mouse: works
  • USB Gamepad: works (as a generic HID gamepad, only with some games)

I guess that next step is to implement emulation of original PS3 controller. I've done a little bit of research and I think that I should be able to do this, using InputStick, although it's a bit tricky, since PS3 controller is not a typical HID device and it uses some custom protocol. For now, there are more important things that have to be done, but I will for sure come back to this subject later.
 
I'm aware of the fact that there are already apps like Blueputdroid that allow to control PS3 via Bluetooth, however your phone must be rooted, also it is not compatible with all phones. With InputStick this is not an issue anymore.



 

Friday 28 June 2013

Password Manager

Like many of us, I have a lot of online accounts: email, banks, forums, online stores, games etc. It would be ideal if I could use different password for each account. It would be also nice to use long and complex passwords, just in case. Also, sometimes you can't or simply don't want to use your email address as a user name and have to think of something else (and remember it!). Finally there is a case where you simply have to use user name and password specified by somebody else. I guess that it is not possible for most of us to remember so many user name and password sets. There is also another problem with long and complex passwords: it takes a while to type them, especially if you want to be extra careful not to make any typing mistakes.
To solve these problems we can use some kind of password manager application. I won't be getting into details here, because there are so many different solutions. Instead, I will just make a list of features that my ideal password manager application should have.

1) I want to be able to access my data at any moment.
2) I don't want to store my accounts data online.
3) I don't want to enter passwords manually, password manager should do that for me.
4) I want to be able to use my password manager on any machine/operating system.
5) There are some cases when I can't/don't want to install any software on a machine I use at given moment.

...so as a result:

1) Account data should be accessible form my smartphone, because I usually have it with me.
2) Data should be stored locally (of course with possibility to make a backup).
3) Password manager must have some way of controlling or accessing a machine that I use at the moment.
4) It must support many different operating systems.
5) Password manager should be able to input data using the same way as a user does.

InputStick allows to solve many password related problem by allowing to type passwords for you (also user name, direct URL to login page etc). What is most important is the fact that as a generic USB keyboard it will work with any USB host/operating system and does not require any additional software or drivers. Also no Internet connection is required since everything is stored locally, on your Android device.

Now let's take a look at my implementation. At this moment application is still in very early phase, but it already provides most important functionality: storing account data, displaying it or using InputStick to type it for you. Let's start with a video:


Login Screen
I guess it is pretty much obvious that any password manager should have master password to protect stored data. Since application is still in development, at this moment master password is set to null.


Main Activity (Item List)
Here you can select item from the list, add new item or connect to/disconnect InputStick.


Item details.
Here you can see list of elements associated with an item. At this time list of possible elements include: element name, URL, user name and password. There are also additional buttons that allow you to easily navigate between text fields (using Tab and Shift+Tab combinations) and press Enter key.


Element action.
For each element you can choose to display its value, type using InputStick or copy to clipboard.


Edit item
This activity allows to add or edit an item. You can specify value for each of elements: item name, URL, user name, password, item type. You can also check the checkbox to automatically include Enter after typing password.


Settings

If you mostly use "Type" action, you can check "Connect automatically" option so you don't have to manually initiate connection to InputStcik. Application can also detect state of Caps Lock and basing on that choose to type in upper/lower case.

So as you can see at this time application provides only basic functionality, still I think that it is a great demo showing one of many possible usages for InputStick.

Wednesday 26 June 2013

InputStick webpage. Also new webcam.

During last few days I've spent some time working on InputStick webpage. It's not 100% done yet, but I think that I've managed to put there most important information related to InputStick project. Check it out: inputstick.com

Also, today I've finally received my new Logitech C920 webcam, so expect some new posts with 1080p movies, maybe even tomorrow :) I've been waiting with posting some material untill I'll be able to record high quality movies.

Tuesday 14 May 2013

Fast Keyboard

After making some improvements (mainly related to USB reports buffering) it is time to test InputStick performance. In order to do that, I've modified USBKeyboard class by changing endpoint polling interval form 32ms to 1ms. In theory this should allow to send up to 1000 reports per second and as a result type 1000 characters (under some conditions).

First, take a look at this video:


So here's what happens:
  1. application sends Alt+Insert combination, what starts music playback in Winamp
  2. application types 10000 characters
  3. application sends Alt+Home, what pauses playback. At this time Winamp shows 13 seconds elapsed
Now some simple math: 10000 characters in approximately 13 seconds gives 770 characters per second = 46200 characters per minute. Pretty fast and pretty close to 1000 characters per seconds what is highest possible value. I guess that after some further improvements I should be able to reach that value.

Are there any applications for that? At this rate, typing all four digit PIN codes, each followed by "Enter" key (50000 characters) will take approximately 65 seconds. In some real world scenario it probably will be necessary to add some delay between consecutive attempts, and deal with "Wrong Password" messages (for example: press "Enter" to try again). Also, there is an assumption that target will allow for infinite (OK, 10000 will also do) number of attempts.

Finally, some remarks. As you can see the test has been performed on Windows and I'm not sure how different systems may behave. It may be necessary to send additional USB report after each character ("release" key), or separate "Shift+Key" report into two reports: "Shift" and "Shift+Key". This may reduce final performance by two or three times, but still, even 15000 characters per minute is really fast, see: World Records in Typing.

Sunday 12 May 2013

USB Remote Control

Recently I've added support for USB composite devices, what allows InputStick to have several USB interfaces at the same time. This is extremely useful in applications like remote control, where we need mouse and keyboard interfaces working at the same time. I will leave implementation details for other post, which will cover recent improvements in InputStick firmware and Android library. Here I want to focus on Remote Control application. First let's take a look at how opetaing system sees such device:




As you can see there are three interfaces: mouse (USB endpoint 1), keyboard (USB endpoint 2) and input device consisting of consumer control device (system volume and playback control) and power control (USB endpoint 3). Each interface has already been covered in my previous posts. Now let's take a look at Remote Control application (which originally was supposed to be Remote Keyboard application):




I should spend some more time working on the layout, but for now its just a proof of concept. Here you can see it in action:



Just like I've mentioned in the video, there is no need to install any additional software on controlled device. As a physical device it will also work with any modern operating system (Windows, Linux, Mac OS, Android etc) and it doesn't require installing additional drivers, since it uses standard USB HID (Human Interface Device) class. So just like in the video, all it takes is to plug InputStick into USB port and run Remote Control application on your smartphone.


Thursday 9 May 2013

USB Numeric Keypad

Before starting with USB Remote Control application, which combines: keyboard, mouse and consumer control interfaces (more on that soon), I wanted to practise some layout design. That's why I did Numeric Keypad app. I guess that there is not much to say about this app... it allows you to use your smartphone or tablet as a wireless USB numeric keypad and well... that's all.

NumLock is on.
NumLock is off.

Wednesday 1 May 2013

USB Gamepad

Another thing that I have recently implemented is a USBGamepad class. It's very similar to other previously described HID devices. Let's take a look at report descriptor:
 

 
As you can see, my gamepad implementation supports up to 16 buttons and 4 axes. First byte of USB report is always set to 1 (report ID), next two bytes are an array containing data about state of buttons, followed by 4 bytes, one for each axis. Endpoint 1 has polling interval set to 8 ms in order to reduce latency, what is very important in case of a gamepad device. There are following methods offered by this class:
 

 
In order to demonstrate USBGamepad class in action I have prepared simple GamepadDemo app. As you can see there are 8 buttons (multi-touch is supported). Data for X and Y axes is gathered from accelerometer, Z and rX axes are not used. Application sends data every 25 ms, but I guess any interval greater than 8 ms (endpoint polling interval) should be ok.
 
GamepadDemo app.


Devices and Printers

On the screen above you can see that Windows sees InputStick as a USB game controller device. I didn't check this class on any other operating system beside Windows, but if a physical gamepad is supported, then InputStick will also work.

Here's a video of me playing GRID with my phone as a controller (it's a bit difficult to steer when you have camera between yourself and phone) :