diff --git a/src/java/InputStickAPI/.classpath b/src/java/InputStickAPI/.classpath
new file mode 100644
index 00000000..7bc01d9a
--- /dev/null
+++ b/src/java/InputStickAPI/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/src/java/InputStickAPI/.project b/src/java/InputStickAPI/.project
new file mode 100644
index 00000000..860b70fe
--- /dev/null
+++ b/src/java/InputStickAPI/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>InputStickAPI</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/src/java/InputStickAPI/.settings/org.eclipse.jdt.core.prefs b/src/java/InputStickAPI/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..b080d2dd
--- /dev/null
+++ b/src/java/InputStickAPI/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/src/java/InputStickAPI/AndroidManifest.xml b/src/java/InputStickAPI/AndroidManifest.xml
new file mode 100644
index 00000000..0ee5fbb4
--- /dev/null
+++ b/src/java/InputStickAPI/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.inputstick.api"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="9"
+        android:targetSdkVersion="17" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+    </application>
+
+</manifest>
diff --git a/src/java/InputStickAPI/gen/com/inputstick/api/BuildConfig.java b/src/java/InputStickAPI/gen/com/inputstick/api/BuildConfig.java
new file mode 100644
index 00000000..29334b73
--- /dev/null
+++ b/src/java/InputStickAPI/gen/com/inputstick/api/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package com.inputstick.api;
+
+public final class BuildConfig {
+    public final static boolean DEBUG = true;
+}
\ No newline at end of file
diff --git a/src/java/InputStickAPI/gen/com/inputstick/api/R.java b/src/java/InputStickAPI/gen/com/inputstick/api/R.java
new file mode 100644
index 00000000..eeb47c67
--- /dev/null
+++ b/src/java/InputStickAPI/gen/com/inputstick/api/R.java
@@ -0,0 +1,47 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+
+package com.inputstick.api;
+
+public final class R {
+    public static final class attr {
+    }
+    public static final class drawable {
+        public static int ic_launcher=0x7f020000;
+    }
+    public static final class string {
+        public static int app_name=0x7f030000;
+    }
+    public static final class style {
+        /** 
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    
+
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        
+
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    
+ API 11 theme customizations can go here. 
+
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    
+ API 14 theme customizations can go here. 
+         */
+        public static int AppBaseTheme=0x7f040000;
+        /**  Application theme. 
+ All customizations that are NOT specific to a particular API-level can go here. 
+         */
+        public static int AppTheme=0x7f040001;
+    }
+}
diff --git a/src/java/InputStickAPI/libs/android-support-v4.jar b/src/java/InputStickAPI/libs/android-support-v4.jar
new file mode 100644
index 00000000..cf12d283
Binary files /dev/null and b/src/java/InputStickAPI/libs/android-support-v4.jar differ
diff --git a/src/java/InputStickAPI/proguard-project.txt b/src/java/InputStickAPI/proguard-project.txt
new file mode 100644
index 00000000..f2fe1559
--- /dev/null
+++ b/src/java/InputStickAPI/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/src/java/InputStickAPI/project.properties b/src/java/InputStickAPI/project.properties
new file mode 100644
index 00000000..91d2b024
--- /dev/null
+++ b/src/java/InputStickAPI/project.properties
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
+android.library=true
diff --git a/src/java/InputStickAPI/res/drawable-hdpi/ic_launcher.png b/src/java/InputStickAPI/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..96a442e5
Binary files /dev/null and b/src/java/InputStickAPI/res/drawable-hdpi/ic_launcher.png differ
diff --git a/src/java/InputStickAPI/res/drawable-mdpi/ic_launcher.png b/src/java/InputStickAPI/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..359047df
Binary files /dev/null and b/src/java/InputStickAPI/res/drawable-mdpi/ic_launcher.png differ
diff --git a/src/java/InputStickAPI/res/drawable-xhdpi/ic_launcher.png b/src/java/InputStickAPI/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..71c6d760
Binary files /dev/null and b/src/java/InputStickAPI/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/src/java/InputStickAPI/res/values-v11/styles.xml b/src/java/InputStickAPI/res/values-v11/styles.xml
new file mode 100644
index 00000000..3c02242a
--- /dev/null
+++ b/src/java/InputStickAPI/res/values-v11/styles.xml
@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/src/java/InputStickAPI/res/values-v14/styles.xml b/src/java/InputStickAPI/res/values-v14/styles.xml
new file mode 100644
index 00000000..a91fd037
--- /dev/null
+++ b/src/java/InputStickAPI/res/values-v14/styles.xml
@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/src/java/InputStickAPI/res/values/strings.xml b/src/java/InputStickAPI/res/values/strings.xml
new file mode 100644
index 00000000..bcb62752
--- /dev/null
+++ b/src/java/InputStickAPI/res/values/strings.xml
@@ -0,0 +1,5 @@
+<resources>
+
+    <string name="app_name">InputStickAPI</string>
+
+</resources>
diff --git a/src/java/InputStickAPI/res/values/styles.xml b/src/java/InputStickAPI/res/values/styles.xml
new file mode 100644
index 00000000..6ce89c7b
--- /dev/null
+++ b/src/java/InputStickAPI/res/values/styles.xml
@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/AES.java b/src/java/InputStickAPI/src/com/inputstick/api/AES.java
new file mode 100644
index 00000000..054dcb6b
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/AES.java
@@ -0,0 +1,52 @@
+package com.inputstick.api;
+
+import java.security.MessageDigest;
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+public class AES {
+	
+	private Cipher mCipherEncr;
+	private Cipher mCipherDecr;
+	private SecretKeySpec mKey;	
+	
+	public AES() {
+	}
+	
+	public static byte[] getMD5(String s) {
+		try {
+			MessageDigest md = MessageDigest.getInstance("MD5");
+			return md.digest(s.getBytes("UTF-8"));
+		} catch (Exception e) {
+			e.printStackTrace();
+		} 		
+		return null;
+	}
+	
+	public byte[] init(byte[] key) {
+		byte[] iv = null;
+		try {
+			mKey = new SecretKeySpec(key, "AES");		
+			mCipherEncr = Cipher.getInstance("AES/CBC/NoPadding");					
+			mCipherEncr.init(Cipher.ENCRYPT_MODE, mKey);
+			iv = mCipherEncr.getIV();
+			//System.out.println("AES IV: ");
+			Util.printHex(iv);
+			mCipherDecr = Cipher.getInstance("AES/CBC/NoPadding");
+			mCipherDecr.init(Cipher.DECRYPT_MODE, mKey, new IvParameterSpec(iv));
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return iv;
+	}		
+	
+	public byte[] encrypt(byte[] data) {
+		return mCipherEncr.update(data);
+	}
+	
+	public byte[] decrypt(byte[] data) {
+		return mCipherDecr.update(data);
+	}
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/BTConnectionManager.java b/src/java/InputStickAPI/src/com/inputstick/api/BTConnectionManager.java
new file mode 100644
index 00000000..4d853bec
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/BTConnectionManager.java
@@ -0,0 +1,168 @@
+package com.inputstick.api;
+
+import java.lang.ref.WeakReference;
+
+import android.app.Application;
+import android.os.Handler;
+import android.os.Message;
+
+import com.inputstick.api.bluetooth.BTService;
+import com.inputstick.init.InitManager;
+import com.inputstick.init.InitManagerListener;
+
+public class BTConnectionManager extends ConnectionManager implements InitManagerListener {
+	
+	//private static final String mTag = "BTConnectionManager";
+	
+	private String mMac;
+	private byte[] mKey;		
+	
+	private InitManager mInitManager;
+	private Application mApp;
+	private BTService mBTService;
+	private PacketManager mPacketManager;
+	//private PacketQueue mPacketQueue;
+	private final BTHandler mBTHandler = new BTHandler(this);				
+	
+	
+	
+    private static class BTHandler extends Handler {    	
+    	private final WeakReference<BTConnectionManager> ref; 
+
+    	BTHandler(BTConnectionManager manager) { 
+    		ref = new WeakReference<BTConnectionManager>(manager); 
+        }    	
+    	
+		@Override
+		public void handleMessage(Message msg) {
+			BTConnectionManager manager = ref.get();
+			switch (msg.what) {
+				case BTService.EVENT_DATA:
+					manager.onData((byte[])msg.obj);
+					break;			
+				case BTService.EVENT_CONNECTED:
+					manager.onConnected();
+					break;
+				case BTService.EVENT_CANCELLED:
+					manager.onDisconnected();
+					break;					
+				case BTService.EVENT_CONNECTION_FAILED:
+					manager.onFailure(1); 
+					break;
+				case BTService.EVENT_CONNECTION_LOST:
+					manager.onFailure(1); 
+					break;					
+				case BTService.EVENT_NO_BT_HW:
+					manager.onFailure(1); 
+					break;
+				case BTService.EVENT_INVALID_MAC:
+					manager.onFailure(1); 
+					break;
+				case BTService.EVENT_CMD_TIMEOUT:
+					manager.onFailure(1); 
+					break;
+				case BTService.EVENT_INTERVAL_TIMEOUT:
+					manager.onFailure(1); 
+					break;
+				case BTService.EVENT_TURN_ON_TIMEOUT:
+					manager.onFailure(1); 
+					break;					
+				case BTService.EVENT_OTHER_ERROR:
+					manager.onFailure(1); 
+					break;									
+			}
+		}
+    } 		
+    
+    private void onConnecting() {
+    	stateNotify(ConnectionManager.STATE_CONNECTING);
+    }
+	
+	private void onConnected() {		
+		stateNotify(ConnectionManager.STATE_CONNECTED);
+		mInitManager.onConnected();
+	}
+	
+	private void onDisconnected() {
+		stateNotify(ConnectionManager.STATE_DISCONNECTED);
+	}
+	
+	private void onFailure(int code) {
+		mErrorCode = code;
+		stateNotify(ConnectionManager.STATE_FAILURE);
+	}
+	
+	private void onData(byte[] rawData) {
+		byte[] data;
+		data = mPacketManager.bytesToPacket(rawData);
+		
+		if (data == null) {
+			//TODO
+			return;
+		}
+		
+		mInitManager.onData(data);
+		
+		//sendNext(); TODO
+		for (InputStickDataListener listener : mDataListeners) {
+			listener.onInputStickData(data);
+		}		
+	}	
+	
+	
+	public BTConnectionManager(InitManager initManager, Application app, String mac, byte[] key) {		
+		mInitManager = initManager;		
+		mMac = mac;		
+		mKey = key;
+		mApp = app;
+	}
+	
+	@Override
+	public void connect() {
+		connect(false, BTService.DEFAULT_CONNECT_TIMEOUT);
+	}
+
+	
+	public void connect(boolean reflection, int timeout) {
+		mErrorCode = ConnectionManager.ERROR_NONE;
+		if (mBTService == null) {
+			mBTService = new BTService(mApp, mBTHandler);
+			mPacketManager = new PacketManager(mBTService, mKey);
+			mInitManager.init(this, mPacketManager);
+		}
+		mBTService.setConnectTimeout(timeout);
+		mBTService.enableReflection(reflection);
+		mBTService.connect(mMac);
+		onConnecting();
+	}
+
+	@Override
+	public void disconnect() {
+		if (mBTService != null) {
+			mBTService.disconnect();
+		}
+	}
+	
+
+	@Override
+	public void sendPacket(Packet p) {
+		mPacketManager.sendPacket(p); //TODO tmp; zalozmy z beda same NO_RESP ???
+	}
+	
+
+	@Override
+	public void onInitReady() {
+		stateNotify(ConnectionManager.STATE_READY);
+	}
+
+	@Override
+	public void onInitNotReady() {
+		stateNotify(ConnectionManager.STATE_CONNECTED);
+	}
+
+	@Override
+	public void onInitFailure(int code) {
+		onFailure(code);
+	}	
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/ConnectionManager.java b/src/java/InputStickAPI/src/com/inputstick/api/ConnectionManager.java
new file mode 100644
index 00000000..d62cdcc4
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/ConnectionManager.java
@@ -0,0 +1,72 @@
+package com.inputstick.api;
+
+import java.util.Vector;
+
+public abstract class ConnectionManager {
+	
+	public static final int STATE_DISCONNECTED = 0;
+	public static final int STATE_FAILURE = 1;
+	public static final int STATE_CONNECTING = 2;
+	public static final int STATE_CONNECTED = 3;
+	public static final int STATE_READY = 4;
+	
+	
+	public static final int ERROR_NONE = 0;
+	
+	public static final int ERROR_UNSUPPORTED_FIRMWARE = 10;
+	public static final int ERROR_PASSWORD_PROTECTED = 11;
+	public static final int ERROR_INVALID_KEY = 12;
+	
+	
+	protected Vector<InputStickStateListener> mStateListeners = new Vector<InputStickStateListener>();
+	protected Vector<InputStickDataListener> mDataListeners = new Vector<InputStickDataListener>();
+	
+	protected int mState;
+	protected int mErrorCode;
+	
+	public abstract void connect();
+	public abstract void disconnect();
+	public abstract void sendPacket(Packet p);
+	
+	protected void stateNotify(int state) {
+		if (mState != state) {							
+			mState = state;
+			for (InputStickStateListener listener : mStateListeners) {
+				listener.onStateChanged(state);
+			}	
+		}
+	}    
+	
+	public int getState() {
+		return mState;
+	}
+	
+	public int getErrorCode() {
+		return mErrorCode;
+	}
+	
+	public void addStateListener(InputStickStateListener listener) {
+		if (listener != null) {
+			mStateListeners.add(listener);
+		}	
+	}
+	
+	public void removeStateListener(InputStickStateListener listener) {
+		if (listener != null) {
+			mStateListeners.remove(listener);
+		}	
+	}
+	
+	public void addDataListener(InputStickDataListener listener) {
+		if (listener != null) {
+			mDataListeners.add(listener);
+		}				
+	}
+	
+	public void removeDataListener(InputStickDataListener listener) {
+		if (listener != null) {
+			mDataListeners.remove(listener);
+		}			
+	}
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/HIDInfo.java b/src/java/InputStickAPI/src/com/inputstick/api/HIDInfo.java
new file mode 100644
index 00000000..6b8f6c4b
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/HIDInfo.java
@@ -0,0 +1,115 @@
+package com.inputstick.api;
+
+public class HIDInfo {
+	
+	private int state;
+	
+	private boolean numLock;
+	private boolean capsLock;
+	private boolean scrollLock;
+	
+	private boolean keyboardReportProtocol;
+	private boolean mouseReportProtocol;
+	
+	private boolean keyboardReady;
+	private boolean mouseReady;
+	private boolean consumerReady;
+	
+
+	public HIDInfo() {
+		keyboardReportProtocol = true;
+		mouseReportProtocol = true;
+	}
+	
+	public void update(byte[] data) {
+		state = data[1];
+		
+		int leds = data[2];
+		if ((leds & 0x01) != 0) {
+			numLock = true;
+		} else {
+			numLock = false;
+		}
+		if ((leds & 0x02) != 0) {
+			capsLock = true;
+		} else {
+			capsLock = false;
+		}
+		if ((leds & 0x04) != 0) {
+			scrollLock = true;
+		} else {
+			scrollLock = false;
+		}	
+		
+		if (data[3] == 0) {
+			keyboardReportProtocol = true;
+		} else {
+			keyboardReportProtocol = false;
+		}
+		
+		if (data[4] == 0) {
+			keyboardReady = false;
+		} else {
+			keyboardReady = true;
+		}
+		
+		if (data[5] == 0) {
+			mouseReportProtocol = true;
+		} else {
+			mouseReportProtocol = false;
+		}	
+		
+		if (data[6] == 0) {
+			mouseReady = false;
+		} else {
+			mouseReady = true;
+		}		
+		
+		if (data[7] == 0) {
+			consumerReady = false;
+		} else {
+			consumerReady = true;
+		}			
+	}
+	
+	public void setKeyboardBusy() {
+		keyboardReady = false;
+	}
+	
+	public int getState() {
+		return state;
+	}
+	
+	public boolean getNumLock() {
+		return numLock;
+	}
+	
+	public boolean getCapsLock() {
+		return capsLock;
+	}
+	
+	public boolean getScrollLock() {
+		return scrollLock;
+	}	
+	
+	public boolean isKeyboardReportProtocol() {
+		return keyboardReportProtocol;
+	}
+	
+	public boolean isMouseReportProtocol() {
+		return mouseReportProtocol;
+	}	
+	
+	public boolean isKeyboardReady() {
+		return keyboardReady;
+	}
+	
+	public boolean isMouseReady() {
+		return mouseReady;
+	}
+	
+	public boolean isConsumerReady() {
+		return consumerReady;
+	}	
+	
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/IPCConnectionManager.java b/src/java/InputStickAPI/src/com/inputstick/api/IPCConnectionManager.java
new file mode 100644
index 00000000..5548f6f5
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/IPCConnectionManager.java
@@ -0,0 +1,180 @@
+package com.inputstick.api;
+
+import java.lang.ref.WeakReference;
+
+import android.app.Application;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.RemoteException;
+
+public class IPCConnectionManager extends ConnectionManager {
+	
+	//private static final String mTag = "IPCConnectionManager";
+	
+	public static final int SERVICE_CMD_CONNECT = 1;
+	public static final int SERVICE_CMD_DISCONNECT = 2;
+	public static final int SERVICE_CMD_DATA = 3;
+	public static final int SERVICE_CMD_STATE = 4;
+	
+    Context mCtx;
+	Messenger mService = null;    
+	boolean mBound;
+	boolean initSent;
+    final Messenger mMessenger = new Messenger(new IncomingHandler(this)); 
+    
+    private static class IncomingHandler extends Handler {    	
+    	private final WeakReference<IPCConnectionManager> ref; 
+
+    	IncomingHandler(IPCConnectionManager manager) { 
+    		ref = new WeakReference<IPCConnectionManager>(manager); 
+        }    	
+    	
+        @Override
+        public void handleMessage(Message msg) {      	
+        	IPCConnectionManager manager = ref.get();
+        	
+        	switch (msg.what) {     	
+    		case SERVICE_CMD_DATA:
+            	byte[] data = null;        	
+            	Bundle b = msg.getData();
+            	if (b != null) {
+            		data = b.getByteArray("data");
+            		manager.onData(data);
+            	}             	
+    			break;
+    		case SERVICE_CMD_STATE:
+    			//System.out.println("CMD STATE: "+msg.arg1);
+    			manager.stateNotify(msg.arg1);
+    			break;             	
+        	}         	
+        }
+    }     
+    
+    private ServiceConnection mConnection = new ServiceConnection() {
+        public void onServiceConnected(ComponentName className, IBinder service) {
+        	//System.out.println("onServiceConnected!");
+            mService = new Messenger(service);
+            mBound = true;                  
+            sendMessage(SERVICE_CMD_CONNECT, 0, 0); 
+        }
+
+        public void onServiceDisconnected(ComponentName className) {
+            // unexpectedly disconnected from service
+        	//System.out.println("onService DISCONNECTED!");
+            mService = null;
+            mBound = false;
+            stateNotify(STATE_DISCONNECTED);
+        }
+    };  
+    //SERVICE=========================================================            
+
+	
+	
+	
+	
+	
+
+    
+    private void sendMessage(int what, int arg1, int arg2, Bundle b) {
+		Message msg;
+		try {
+			msg = Message.obtain(null, what, arg1, 0, null);
+			msg.replyTo = mMessenger;
+			msg.setData(b);				
+			mService.send(msg);
+		} catch (RemoteException e) {
+			e.printStackTrace();
+		}    	
+    }
+    
+    private void sendMessage(int what, int arg1, int arg2, byte[] data) {
+    	Bundle b;
+		b = new Bundle();
+		b.putByteArray("data", data);
+		sendMessage(what, arg1, arg2, b);
+    }    
+    
+    private void sendMessage(int what, int arg1, int arg2) {
+    	sendMessage(what, arg1, arg2, (Bundle)null);	
+    }  	
+	
+	
+	private void onData(byte[] data) {
+		for (InputStickDataListener listener : mDataListeners) {
+			listener.onInputStickData(data);
+		} 		
+	}    		
+	
+	
+	public IPCConnectionManager(Application app) {
+		mCtx = app.getApplicationContext();
+	}
+
+	@Override
+	public void connect() {
+		PackageManager pm = mCtx.getPackageManager();
+		boolean exists = true;
+		try {
+			pm.getPackageInfo("com.inputstick.apps.inputstickutility", PackageManager.GET_META_DATA);
+		} catch (NameNotFoundException e) {
+			exists = false;
+		}		
+		
+		if (exists) {
+			mErrorCode = ConnectionManager.ERROR_NONE;
+			Intent intent = new Intent();									
+			intent.setComponent(new ComponentName("com.inputstick.apps.inputstickutility","com.inputstick.apps.inputstickutility.service.InputStickService"));
+			mCtx.startService(intent);
+			mCtx.bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 
+	        if (mBound) {
+	        	//already bound?
+	        	//System.out.println("Service already Connected");
+	        	sendMessage(SERVICE_CMD_CONNECT, 0, 0); 
+	        } 
+		} else {
+			mErrorCode = 1; //TODO
+			stateNotify(STATE_FAILURE);
+		}
+	}
+
+	@Override
+	public void disconnect() {
+		if (mBound) {
+			//System.out.println("UNBIND");
+			sendMessage(SERVICE_CMD_DISCONNECT, 0, 0); 
+			Intent intent = new Intent();		   
+			intent.setComponent(new ComponentName("com.inputstick.apps.inputstickutility","com.inputstick.apps.inputstickutility.service.InputStickService"));	
+			mCtx.unbindService(mConnection);
+			mCtx.stopService(intent);
+			mBound = false;
+			//TODO stateNotify 
+			//service will pass notification message
+		} else {
+			//just set state, there is nothing else to do
+			stateNotify(STATE_DISCONNECTED);
+		}
+	}
+	
+	@Override
+	public void sendPacket(Packet p) {
+		if (mState == ConnectionManager.STATE_READY) {			
+			if (p.getRespond()) {
+				sendMessage(IPCConnectionManager.SERVICE_CMD_DATA, 1, 0, p.getBytes());
+			} else {
+				sendMessage(IPCConnectionManager.SERVICE_CMD_DATA, 0, 0, p.getBytes());
+			}
+		}
+	}
+
+
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/InputStickDataListener.java b/src/java/InputStickAPI/src/com/inputstick/api/InputStickDataListener.java
new file mode 100644
index 00000000..1496db85
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/InputStickDataListener.java
@@ -0,0 +1,7 @@
+package com.inputstick.api;
+
+public interface InputStickDataListener {
+
+	public void onInputStickData(byte[] data);
+	
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/InputStickKeyboardListener.java b/src/java/InputStickAPI/src/com/inputstick/api/InputStickKeyboardListener.java
new file mode 100644
index 00000000..c0508417
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/InputStickKeyboardListener.java
@@ -0,0 +1,7 @@
+package com.inputstick.api;
+
+public interface InputStickKeyboardListener {
+	
+	public void onLEDsChanged(boolean numLock, boolean capsLock, boolean scrollLock);
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/InputStickStateListener.java b/src/java/InputStickAPI/src/com/inputstick/api/InputStickStateListener.java
new file mode 100644
index 00000000..16a7df8e
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/InputStickStateListener.java
@@ -0,0 +1,7 @@
+package com.inputstick.api;
+
+public interface InputStickStateListener {
+	
+	public void onStateChanged(int state); 
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/Packet.java b/src/java/InputStickAPI/src/com/inputstick/api/Packet.java
new file mode 100644
index 00000000..27e0ac93
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/Packet.java
@@ -0,0 +1,122 @@
+package com.inputstick.api;
+
+public class Packet {
+	
+	public static final byte NONE =						0x00;
+	
+	public static final byte START_TAG = 				0x55;
+	public static final byte FLAG_RESPOND = 			(byte)0x80;
+	public static final byte FLAG_ENCRYPTED = 			0x40;
+	
+	public static final int MAX_SUBPACKETS = 			17;	
+	public static final int MAX_LENGTH = 				MAX_SUBPACKETS * 16;
+	
+	public static final byte CMD_IDENTIFY =		 		0x01;
+	public static final byte CMD_LED =				 	0x02;
+	public static final byte CMD_RUN_BL =		 		0x03;
+	public static final byte CMD_RUN_FW =		 		0x04;
+	public static final byte CMD_GET_INFO =		 		0x05;
+	public static final byte CMD_BL_ERASE =		 		0x06;
+	public static final byte CMD_ADD_DATA =		 		0x07;
+	public static final byte CMD_BL_WRITE =		 		0x08;
+	
+	public static final byte CMD_FW_INFO =		 		0x10;
+	public static final byte CMD_INIT =			 		0x11;
+	
+	
+	public static final byte CMD_HID_STATUS_REPORT = 	0x20;
+	public static final byte CMD_HID_DATA_KEYB = 		0x21;
+	public static final byte CMD_HID_DATA_CONSUMER =	0x22;
+	public static final byte CMD_HID_DATA_MOUSE = 		0x23;
+	//out	
+	public static final byte CMD_HID_STATUS =			0x2F;
+	
+	
+	
+	public static final byte CMD_DUMMY =	 			(byte)0xFF;
+	
+	
+	public static final byte RESP_OK =					0x01;
+	
+	
+	public static final byte[] RAW_OLD_BOOTLOADER = new byte[] {START_TAG, (byte)0x00, (byte)0x02, (byte)0x83, (byte)0x00, (byte)0xDA};			
+	public static final byte[] RAW_DELAY_1_MS = new byte[] {0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01}; 
+	
+	private byte[] mData;
+	private int mPos;
+	private boolean mRespond;
+	
+	//do not modify
+	public Packet(boolean respond, byte[] data) {
+		mRespond = respond;
+		mData = data;
+		mPos = data.length;		
+	}
+	
+	public Packet(boolean respond, byte cmd, byte param, byte[] data) {
+		mRespond = respond;
+		mData = new byte[MAX_LENGTH];
+		mData[0] = cmd;
+		mData[1] = param;
+		mPos = 2;		
+		if (data != null) {
+			addBytes(data);
+		}		
+	}
+	
+	public Packet(boolean respond, byte cmd, byte param) {
+		this(respond, cmd, param, null);
+	}	
+	
+	public Packet(boolean respond, byte cmd) {
+		mRespond = respond;
+		mData = new byte[MAX_LENGTH];
+		mData[0] = cmd;
+		mPos = 1;
+	}	
+	
+	public void modifyByte(int pos, byte b) {
+		mData[pos] = b;
+	}
+	
+	public void addBytes(byte[] data) {
+		//TODO check null pointer / available size (MAX_PAYLOAD - mPos) 
+		System.arraycopy(data, 0, mData, mPos, data.length);
+		mPos += data.length;		
+	}
+	
+	public void addByte(byte b) {
+		mData[mPos++] = b;
+	}
+	
+	public void addInt16(int val) {
+		mData[mPos + 0] = Util.getMSB(val);
+		mData[mPos + 1] = Util.getLSB(val);
+		mPos += 2;
+	}
+	
+	public void addInt32(long val) {
+		mData[mPos + 3] = (byte)val;
+		val >>= 8;
+		mData[mPos + 2] = (byte)val;
+		val >>= 8;
+		mData[mPos + 1] = (byte)val;
+		val >>= 8;
+		mData[mPos + 0] = (byte)val;
+		val >>= 8;	
+		mPos += 4;
+	}	
+	
+	
+	public byte[] getBytes() {
+		byte[] result;		
+		result = new byte[mPos];
+		System.arraycopy(mData, 0, result, 0, mPos);
+		return result;
+	}
+	
+	public boolean getRespond() {
+		return mRespond;
+	}
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/PacketManager.java b/src/java/InputStickAPI/src/com/inputstick/api/PacketManager.java
new file mode 100644
index 00000000..78ae191f
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/PacketManager.java
@@ -0,0 +1,169 @@
+package com.inputstick.api;
+
+import java.util.Arrays;
+import java.util.Random;
+import java.util.zip.CRC32;
+
+import com.inputstick.api.bluetooth.BTService;
+
+public class PacketManager {
+	
+	public static final int MAX_PAYLAOD = 64;
+	public static final int HEADER_OFFSET = 2;
+	public static final int CRC_OFFSET = 4;
+	public static final int PACKET_SIZE = 16;
+	
+	private final BTService mBTService;
+	private final AES mAes;
+	private final byte[] mKey;
+	private byte[] cmpData;
+	private final CRC32 mCrc;	
+	private boolean mEncryption;
+	
+	public PacketManager(BTService btService, byte[] key) {
+		mBTService = btService;
+		mCrc = new CRC32();
+		mAes = new AES();
+		mKey = key;
+		mEncryption = false;
+	}
+	
+	public boolean setEncryption(byte[] cmp, boolean encryptOut) {
+		byte[] cmpDec = mAes.decrypt(cmp);					
+		if (Arrays.equals(cmpDec, cmpData)) {
+			mEncryption = encryptOut;
+			return true;
+		} else {
+			mEncryption = false;
+			return false;
+		}
+	}
+	
+	public Packet encPacket(boolean enable) {
+		Random r = new Random();         
+		Packet p = new Packet(true, Packet.CMD_INIT);
+		if (enable) {
+			p.addByte((byte)1);
+		} else {
+			p.addByte((byte)0);
+		}	
+		
+		byte[] iv = mAes.init(mKey);		
+		p.addBytes(iv);
+		
+		Util.printHex(iv, "IV: ");
+		
+		byte[] initData = new byte[16];
+		r.nextBytes(initData);		
+		mCrc.reset();
+		mCrc.update(initData, 4, 12); //only 12 bytes!
+		long crcValue = mCrc.getValue();
+		initData[3] = (byte)crcValue;
+		crcValue >>= 8;
+		initData[2] = (byte)crcValue;
+		crcValue >>= 8;
+		initData[1] = (byte)crcValue;
+		crcValue >>= 8;
+		initData[0] = (byte)crcValue;		
+		initData = mAes.encrypt(initData);
+		p.addBytes(initData);				
+		
+		//Util.printHex(initData, "InitData: ");
+		
+		cmpData = new byte[16];
+		r.nextBytes(cmpData);
+		p.addBytes(cmpData);
+		
+		//Util.printHex(cmpData, "CmpData: ");		
+		return p;
+	}
+	
+	
+	
+	public byte[] bytesToPacket(byte[] data) {
+		byte[] payload;		
+		//boolean decrypt = false;
+		long crcValue, crcCompare;
+		
+		payload = Arrays.copyOfRange(data, 2, data.length); //remove TAG, info
+		if ((data[1] & Packet.FLAG_ENCRYPTED) != 0) {
+			Util.log("DECRYPT");
+			payload = mAes.decrypt(payload);
+		}
+		
+		Util.printHex(payload, "DATA IN: ");
+	
+		//check CRC		
+		crcCompare = Util.getLong(payload[0], payload[1], payload[2], payload[3]);
+		mCrc.reset();
+		mCrc.update(payload, CRC_OFFSET, payload.length - CRC_OFFSET);
+		crcValue = mCrc.getValue();
+		//System.out.println("CMP: " + crcCompare + " VAL: " + crcValue); 				
+		
+		if (crcValue == crcCompare) {
+			payload = Arrays.copyOfRange(payload, 4, payload.length); //remove CRC
+			return payload;
+		} else {
+			return null; //TODO
+		}		
+		
+	}
+	
+	public void sendRAW(byte[] data) {
+		mBTService.write(data);
+	}
+	
+	public void sendPacket(Packet p) {
+		sendPacket(p, mEncryption);
+	}
+	
+	public void sendPacket(Packet p, boolean encrypt) {
+		byte[] result, header, data;
+		int length;
+		int packets;
+		long crcValue;		
+		
+		//if data > MAX_PAYLAOD -> error
+		
+		data = p.getBytes();
+		
+		length = data.length + CRC_OFFSET; //include 4bytes for CRC32		
+		packets = ((length - 1) >> 4) + 1; //how many 16 bytes data sub-packets are necessary		
+
+		result = new byte[packets * PACKET_SIZE];
+		System.arraycopy(data, 0, result, CRC_OFFSET, data.length);
+				
+		//add CRC32
+		mCrc.reset();
+		mCrc.update(result, CRC_OFFSET, result.length - CRC_OFFSET);		
+		crcValue = mCrc.getValue();
+		Util.log("CRC: "+crcValue);
+		result[3] = (byte)crcValue;
+	    crcValue >>= 8;
+	    result[2] = (byte)crcValue;
+		crcValue >>= 8;
+		result[1] = (byte)crcValue;
+		crcValue >>= 8;
+		result[0] = (byte)crcValue;			
+		
+		//Util.printHex(result);
+		
+		if (encrypt) {
+			result = mAes.encrypt(result);
+			//Util.printHex(result);			
+		}
+		
+		header = new byte[2];
+		header[0] = Packet.START_TAG;
+		header[1] = (byte)packets;
+		if (encrypt) {
+			header[1] |= Packet.FLAG_ENCRYPTED;
+		}
+		if (p.getRespond()) {
+			header[1] |= Packet.FLAG_RESPOND;
+		}
+		mBTService.write(header);
+		mBTService.write(result);	
+	}
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/Util.java b/src/java/InputStickAPI/src/com/inputstick/api/Util.java
new file mode 100644
index 00000000..112e3312
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/Util.java
@@ -0,0 +1,83 @@
+package com.inputstick.api;
+
+
+public abstract class Util {
+	
+	private static final boolean debug = false;
+	
+	public static void log(String msg) {
+		if (debug) {
+			System.out.println("LOG: " + msg);
+		}
+	}
+	
+	public static void printHex(byte[] toPrint, String info) {
+		if (debug) {
+			System.out.println(info);
+			printHex(toPrint);
+		}
+	}
+
+
+	public static void printHex(byte[] toPrint) {
+		if (debug) {
+			int cnt = 0;
+			String s;
+			byte b;
+	        for (int i = 0; i < toPrint.length; i++) {
+	        	b = toPrint[i];    	
+	        	if ((b < 10) && (b >= 0)) {
+	        		s = Integer.toHexString((int)b);
+	        		s = "0" + s;
+	        	} else {
+		        	s = Integer.toHexString((int)b);
+		        	if (s.length() > 2) {
+		        		s = s.substring(s.length() - 2);
+		        	}
+	        	}        	        	
+	        	s = s.toUpperCase();
+	        	System.out.print("0x" + s + " ");
+	        	cnt++;
+	        	if (cnt == 8) {
+	        		System.out.println("");
+	        		cnt = 0;
+	        	}
+	        }
+	        System.out.println("\n#####");	
+		}
+	}
+	
+	
+    public static byte getLSB(int n) {
+        return (byte)(n & 0x00FF);
+    }
+    
+    public static byte getMSB(int n) {
+        return (byte)((n & 0xFF00) >> 8);
+    }   
+    
+    public static int getInt(byte b) {
+    	int bInt = b & 0xFF;
+    	return bInt;
+    }
+    
+    public static int getInt(byte msb, byte lsb) {
+    	int msbInt = msb & 0xFF;
+    	int lsbInt = lsb & 0xFF;
+    	return (msbInt << 8) + lsbInt;    	
+    } 	
+	
+	public static long getLong(byte b0, byte b1, byte b2, byte b3) {
+		long result;		
+		result = (b0) & 0xFF;
+		result <<= 8;
+		result += (b1) & 0xFF;
+		result <<= 8;
+		result += (b2) & 0xFF;
+		result <<= 8;
+		result += (b3) & 0xFF;				
+		return result;
+	}
+	
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickConsumer.java b/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickConsumer.java
new file mode 100644
index 00000000..edb3b287
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickConsumer.java
@@ -0,0 +1,40 @@
+package com.inputstick.api.basic;
+
+import com.inputstick.api.hid.ConsumerReport;
+import com.inputstick.api.hid.HIDTransaction;
+
+public class InputStickConsumer {
+	
+	//CONSUMER PAGE
+	public static final int VOL_UP = 0x00E9;
+	public static final int VOL_DOWN = 0x00EA;
+	public static final int VOL_MUTE = 0x00E2;
+	public static final int TRACK_NEXT = 0x00B5;
+	public static final int TRACK_PREV = 0x00B6;
+	public static final int STOP = 0x00B7;
+	public static final int PLAY_PAUSE = 0x00CD;
+	
+	public static final int LAUNCH_BROWSER = 0x0196;
+	public static final int LAUNCH_EMAIL = 0x018A;
+	public static final int LAUNCH_CALC = 0x0192;
+	
+	//SYSTEM CONTROL
+	public static final int POWER_DOWN = 0x81;
+	public static final int SLEEP = 0x82;
+	public static final int WAKEUP = 0x83;		
+	
+	private InputStickConsumer() {
+		
+	}
+	
+	/*public static void systemAction(int action) {
+	}*/	
+	
+	public static void consumerAction(int action) {
+		HIDTransaction t = new HIDTransaction();
+		t.addReport(new ConsumerReport(action));
+		t.addReport(new ConsumerReport());
+		InputStickHID.addConsumerTransaction(t);		
+	}
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickHID.java b/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickHID.java
new file mode 100644
index 00000000..cf9adafa
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickHID.java
@@ -0,0 +1,152 @@
+package com.inputstick.api.basic;
+
+import java.util.Vector;
+
+import android.app.Application;
+
+import com.inputstick.api.BTConnectionManager;
+import com.inputstick.api.ConnectionManager;
+import com.inputstick.api.HIDInfo;
+import com.inputstick.api.IPCConnectionManager;
+import com.inputstick.api.InputStickDataListener;
+import com.inputstick.api.InputStickStateListener;
+import com.inputstick.api.Packet;
+import com.inputstick.api.hid.HIDTransaction;
+import com.inputstick.api.hid.HIDTransactionQueue;
+import com.inputstick.init.InitManager;
+
+public class InputStickHID implements InputStickStateListener, InputStickDataListener  {
+	
+	//private static final String mTag = "InputStickBasic";		
+	
+	private static ConnectionManager mConnectionManager;
+	
+	private static Vector<InputStickStateListener> mStateListeners = new Vector<InputStickStateListener>();
+	
+	private static InputStickHID instance = new InputStickHID();
+	private static HIDInfo mHIDInfo = new HIDInfo();
+	
+	private static HIDTransactionQueue keyboardQueue;
+	private static HIDTransactionQueue mouseQueue;
+	private static HIDTransactionQueue consumerQueue;
+	
+	private InputStickHID() {
+	}
+	
+	public static InputStickHID getInstance() {
+		return instance;
+	}
+	
+	private static void init() {
+		keyboardQueue = new HIDTransactionQueue(HIDTransactionQueue.KEYBOARD, mConnectionManager);
+		mouseQueue = new HIDTransactionQueue(HIDTransactionQueue.MOUSE, mConnectionManager);
+		consumerQueue = new HIDTransactionQueue(HIDTransactionQueue.CONSUMER, mConnectionManager);		
+		
+		mConnectionManager.addStateListener(instance);
+		mConnectionManager.addDataListener(instance);
+		mConnectionManager.connect();		
+	}
+	
+	//direct Bluetooth connection, custom InitManager
+	public static void connect(Application app, String mac, byte[] key, InitManager initManager) {
+		mConnectionManager = new BTConnectionManager(initManager, app, mac, key);		
+		init();
+	}	
+	
+	//direct Bluetooth connection
+	public static void connect(Application app, String mac, byte[] key) {
+		//mConnectionManager = new BTConnectionManager(new BasicInitManager(key), app, mac, reflections, key);
+		//mConnectionManager = new BTConnectionManager(new BasicInitManager(key), app, mac, key);
+		mConnectionManager = new BTConnectionManager(new InitManager(key), app, mac, key);
+		init();
+	}
+	
+	//use background service & DeviceManager
+	public static void connect(Application app) {
+		mConnectionManager = new IPCConnectionManager(app);
+		init();
+	}			
+	
+	public static void disconnect() { 
+		//TODO check state?
+		mConnectionManager.disconnect();
+	}
+	
+	public static int getState() {
+		if (mConnectionManager != null) {
+			return mConnectionManager.getState();
+		} else {
+			return ConnectionManager.STATE_DISCONNECTED;
+		}
+	}
+	
+	public static boolean isReady() {
+		if (getState() == ConnectionManager.STATE_READY) {
+			return true;
+		} else {
+			return false;
+		}
+	}
+	
+	public static void addStateListener(InputStickStateListener listener) {
+		if (listener != null) {
+			mStateListeners.add(listener);
+		}
+	}
+	
+	public static void removeStateListener(InputStickStateListener listener) {
+		if (listener != null) {
+			mStateListeners.remove(listener);
+		}
+	}
+
+	public static void addKeyboardTransaction(HIDTransaction transaction) {
+		keyboardQueue.addTransaction(transaction);
+	}
+	
+	public static void addMouseTransaction(HIDTransaction transaction) {
+		mouseQueue.addTransaction(transaction);
+	}
+	
+	public static void addConsumerTransaction(HIDTransaction transaction) {
+		consumerQueue.addTransaction(transaction);
+	}
+	
+	public static boolean sendPacket(Packet p) {
+		if (mConnectionManager != null) {
+			mConnectionManager.sendPacket(p);
+			return true;
+		} else {
+			return false;
+		}
+	}				
+	
+	@Override
+	public void onStateChanged(int state) {
+		for (InputStickStateListener listener : mStateListeners) {
+			listener.onStateChanged(state);
+		}		
+	}
+
+	@Override
+	public void onInputStickData(byte[] data) {
+		if (data[0] == Packet.CMD_HID_STATUS) {
+			mHIDInfo.update(data);
+
+			if (mHIDInfo.isKeyboardReady()) {
+				keyboardQueue.deviceReady();
+			}
+			if (mHIDInfo.isMouseReady()) {
+				mouseQueue.deviceReady();
+			}
+			if (mHIDInfo.isConsumerReady()) {
+				consumerQueue.deviceReady();
+			}			
+			
+			InputStickKeyboard.setLEDs(mHIDInfo.getNumLock(), mHIDInfo.getCapsLock(), mHIDInfo.getScrollLock());			
+		}
+	}	
+	
+	
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickKeyboard.java b/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickKeyboard.java
new file mode 100644
index 00000000..3c902203
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickKeyboard.java
@@ -0,0 +1,118 @@
+package com.inputstick.api.basic;
+
+import java.util.Vector;
+
+import com.inputstick.api.InputStickKeyboardListener;
+import com.inputstick.api.hid.HIDKeycodes;
+import com.inputstick.api.hid.HIDTransaction;
+import com.inputstick.api.hid.KeyboardReport;
+
+public class InputStickKeyboard {
+	
+	//private static final String mTag = "InputStickKeyboard";
+	
+	private static final byte NONE = (byte)0;
+	
+	private static boolean mReportProtocol;		
+	private static boolean mNumLock;
+	private static boolean mCapsLock;
+	private static boolean mScrollLock;
+	
+	private static Vector<InputStickKeyboardListener> mKeyboardListeners = new Vector<InputStickKeyboardListener>();
+	
+	private InputStickKeyboard() {
+	}
+	
+	public static void addKeyboardListener(InputStickKeyboardListener listener) {
+		if (listener != null) {
+			mKeyboardListeners.add(listener);
+		}
+	}
+	
+	public static void removeKeyboardListener(InputStickKeyboardListener listener) {
+		if (listener != null) {
+			mKeyboardListeners.remove(listener);
+		}
+	}		
+	
+	protected void setReportProtocol(boolean reportProtocol) {
+		mReportProtocol = reportProtocol;				
+	}
+	
+	public boolean isReportProtocol() {
+		return mReportProtocol;
+	}
+	
+	protected static void setLEDs(boolean numLock, boolean capsLock, boolean scrollLock) {
+		mNumLock = numLock;
+		mCapsLock = capsLock;
+		mScrollLock = scrollLock;
+		
+		for (InputStickKeyboardListener listener : mKeyboardListeners) {
+			listener.onLEDsChanged(mNumLock, mCapsLock, mScrollLock);
+		}			
+	}
+	
+	public static boolean isNumLock() {
+		return mNumLock;
+	}
+	
+	public static boolean isCapsLock() {
+		return mCapsLock;
+	}
+	
+	public static boolean isScrollLock() {
+		return mScrollLock;
+	}
+	
+	public static void toggleNumLock() {
+		pressAndRelease(NONE, HIDKeycodes.KEY_NUM_LOCK);
+	}
+	
+	public static void toggleCapsLock() {
+		pressAndRelease(NONE, HIDKeycodes.KEY_CAPS_LOCK);
+	}
+	
+	public static void toggleScrollLock() {
+		pressAndRelease(NONE, HIDKeycodes.KEY_SCROLL_LOCK);
+	}
+	
+	public static void pressAndRelease(byte modifier, byte key) {
+		HIDTransaction t = new HIDTransaction();
+		t.addReport(new KeyboardReport(modifier, NONE));
+		t.addReport(new KeyboardReport(modifier, key));
+		t.addReport(new KeyboardReport(NONE, NONE));
+		InputStickHID.addKeyboardTransaction(t);
+	}	
+		
+	public static void typeASCII(String toType) {
+		int keyCode;
+		int index;
+		for (int i = 0; i < toType.length(); i++) {
+			index = toType.charAt(i);
+			if (index > 127) {
+				index = 127;
+			}
+			keyCode = HIDKeycodes.getKeyCode(index);
+			if (keyCode > 128) {
+				keyCode -= 128;
+				pressAndRelease(HIDKeycodes.SHIFT_LEFT, (byte)keyCode);
+			} else {
+				pressAndRelease(NONE, (byte)keyCode);
+			}
+		}
+	}		
+	
+	public static void customReport(byte modifier, byte key0, byte key1, byte key2, byte key3, byte key4, byte key5) {
+		HIDTransaction t = new HIDTransaction();
+		t.addReport(new KeyboardReport(modifier, key0, key1, key2, key3, key4, key5));
+		InputStickHID.addKeyboardTransaction(t);
+	}
+	
+	/*public static void customReport(byte[] report) {
+		HIDTransaction t = new HIDTransaction();
+		t.addReport(report);
+		InputStickHID.addKeyboardTransaction(t);	
+	}*/
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickMouse.java b/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickMouse.java
new file mode 100644
index 00000000..a5db55f2
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/basic/InputStickMouse.java
@@ -0,0 +1,57 @@
+package com.inputstick.api.basic;
+
+import com.inputstick.api.hid.HIDTransaction;
+import com.inputstick.api.hid.MouseReport;
+
+public class InputStickMouse {
+	
+	private static final byte NONE = 0x00;
+
+	public static final byte BUTTON_NONE = 0x00;
+	public static final byte BUTTON_LEFT = 0x01;
+	public static final byte BUTTON_RIGHT = 0x02;
+	public static final byte BUTTON_MIDDLE = 0x04;
+	
+	private static boolean mReportProtocol;
+	
+	private InputStickMouse() {
+		
+	}
+	
+	protected void setReportProtocol(boolean reportProtocol) {
+		mReportProtocol = reportProtocol;				
+	}
+	
+	public boolean isReportProtocol() {
+		return mReportProtocol;
+	}		
+	
+	public static void click(byte button, int n) {
+		HIDTransaction t = new HIDTransaction();
+		t.addReport(new MouseReport()); //release
+		for (int i = 0; i < n; i++) {								
+			t.addReport(new MouseReport(button, NONE, NONE, NONE)); //press
+			t.addReport(new MouseReport()); //release			
+		}
+		InputStickHID.addMouseTransaction(t);	
+	}
+	
+	public static void move(byte x, byte y) {
+		HIDTransaction t = new HIDTransaction();
+		t.addReport(new MouseReport(NONE, x, y, NONE));
+		InputStickHID.addMouseTransaction(t);	
+	}
+	
+	public static void scroll(byte wheel) {
+		HIDTransaction t = new HIDTransaction();
+		t.addReport(new MouseReport(NONE, NONE, NONE, wheel));
+		InputStickHID.addMouseTransaction(t);		
+	}	
+	
+	public static void customReport(byte buttons, byte x, byte y, byte wheel) {
+		HIDTransaction t = new HIDTransaction();
+		t.addReport(new MouseReport(buttons, x, y, wheel));
+		InputStickHID.addMouseTransaction(t);		
+	}		
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/bluetooth/BTService.java b/src/java/InputStickAPI/src/com/inputstick/api/bluetooth/BTService.java
new file mode 100644
index 00000000..fd0098ac
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/bluetooth/BTService.java
@@ -0,0 +1,404 @@
+package com.inputstick.api.bluetooth;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Method;
+import java.util.UUID;
+
+import android.app.Application;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothSocket;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Message;
+
+import com.inputstick.api.Packet;
+import com.inputstick.api.Util;
+
+public class BTService {
+	
+	public static final int DEFAULT_CONNECT_TIMEOUT = 30000;
+	
+	public static final int EVENT_NONE = 0;
+	public static final int EVENT_DATA = 1;
+	public static final int EVENT_CONNECTED = 2;
+	public static final int EVENT_CANCELLED = 3;
+	public static final int EVENT_CONNECTION_FAILED = 4;
+	public static final int EVENT_CONNECTION_LOST = 5;
+	public static final int EVENT_NO_BT_HW = 6;
+	public static final int EVENT_INVALID_MAC = 7;
+	//TODO:
+	public static final int EVENT_CMD_TIMEOUT = 8;
+	public static final int EVENT_INTERVAL_TIMEOUT = 9;
+	public static final int EVENT_TURN_ON_TIMEOUT = 10;
+	public static final int EVENT_OTHER_ERROR = 11;
+	
+	
+       
+    private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); //SPP
+    
+    //private final String dTag = "BTService";
+    
+    
+    private final BluetoothAdapter mAdapter;
+    private final Handler mHandler;
+    private ConnectThread mConnectThread;
+    private ConnectedThread mConnectedThread;
+    private int mLastEvent;
+    
+    private String mMac;
+    private boolean mReflection;
+    private final Application mApp;
+    private final Context mCtx;    
+    
+    private boolean mUseReflection;
+    private int mConnectTimeout;    
+    
+    private boolean turnBluetoothOn;
+    private boolean receiverRegistered;
+    private long timeout;
+    private int retryCnt;    
+    
+    private boolean disconnecting;
+    private boolean connected;
+  
+    
+	private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+		@Override
+		public void onReceive(Context context, Intent intent) {
+			final String action = intent.getAction();
+			System.out.println("ACTION: "+action);
+			if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
+				final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
+				if ((state == BluetoothAdapter.STATE_ON)  && (turnBluetoothOn)) {					
+					turnBluetoothOn = false;					
+					doConnect(false);
+				}
+			}
+		}
+	};    
+    
+    
+    
+    
+    public BTService(Application app, Handler handler) {
+        mAdapter = BluetoothAdapter.getDefaultAdapter();
+        mLastEvent = EVENT_NONE;
+        mHandler = handler;
+        mApp = app;
+        mCtx = app.getApplicationContext();
+        mConnectTimeout = DEFAULT_CONNECT_TIMEOUT; //30s - default value
+    }    
+    
+    public void setConnectTimeout(int timeout) {
+    	mConnectTimeout = timeout;
+    }
+    
+    public void enableReflection(boolean enabled) {
+    	mUseReflection = enabled;
+    }
+	
+    private synchronized void event(int event) {
+    	Util.log("event() " + mLastEvent + " -> " + event);
+        mLastEvent = event;
+        
+        Message msg = Message.obtain(null, mLastEvent, 0, 0);
+        mHandler.sendMessage(msg);        
+    }        
+    
+    public synchronized int getLastEvent() {
+        return mLastEvent;
+    }    
+    
+    
+    
+    private void enableBluetooth() {
+    	if (mApp != null) {
+	    	turnBluetoothOn = true;
+	    	if ( !receiverRegistered) {
+	    		IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
+	    		mCtx.registerReceiver(mReceiver, filter);
+	    		receiverRegistered = true;
+	    	}
+	        
+	    	Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+	    	enableBtIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+	    	mApp.startActivity(enableBtIntent);	    	
+    	}
+    }    
+    
+    private void doConnect(boolean reconnecting) {
+    	if (reconnecting) {
+    		retryCnt++;
+    	} else {	
+    		retryCnt = 0;
+			timeout = System.currentTimeMillis() + mConnectTimeout;
+    	}
+        
+        if (mConnectThread != null) {
+        	mConnectThread.cancel();
+        	mConnectThread = null;
+        }        
+        if (mConnectedThread != null) {
+        	mConnectedThread.cancel(); 
+        	mConnectedThread = null;
+        }
+        
+        mConnectThread = new ConnectThread(mAdapter.getRemoteDevice(mMac), mReflection);
+        mConnectThread.start();        
+    }
+    
+    
+    public synchronized void connect(String mac) {
+    	Util.log("connect to: " + mac + " REFLECTION: " + mUseReflection);
+		disconnecting = false;
+		connected = false;
+		mMac = mac;
+		
+		if (BluetoothAdapter.checkBluetoothAddress(mac)) {
+			BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+			if (mBluetoothAdapter == null) {
+				event(EVENT_NO_BT_HW);
+			} else {
+				if (mBluetoothAdapter.isEnabled()) {					
+					doConnect(false);
+				} else {					
+					enableBluetooth();
+				}
+			}
+		} else {
+			event(EVENT_INVALID_MAC);
+		}
+    }    
+    
+    public synchronized void disconnect() {
+    	Util.log("disconnect");
+        disconnecting = true;
+        cancelThreads();            
+        event(EVENT_CANCELLED);
+    }
+
+
+    public synchronized void write(byte[] out) {    	
+        // Create temporary object
+    	/*
+        ConnectedThread r;
+        // Synchronize a copy of the ConnectedThread
+        synchronized (this) {            
+            r = mConnectedThread;            
+        }
+        // Perform the write unsynchronized
+        if (connected) {
+        	r.write(out);  	
+        }*/
+        if (connected) {
+        	mConnectedThread.write(out);  	
+        }    	
+    }          
+    
+    
+    private synchronized void cancelThreads() {
+        if (mConnectThread != null) {
+        	mConnectThread.cancel(); 
+        	mConnectThread = null;
+        }
+        if (mConnectedThread != null) {
+        	mConnectedThread.cancel(); 
+        	mConnectedThread = null;
+        }    	
+    }
+    
+    private synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
+        timeout = 0;
+        cancelThreads();        
+        if (receiverRegistered) {
+        	mCtx.unregisterReceiver(mReceiver);
+        	receiverRegistered = false;
+        }
+
+        // Start the thread to manage the connection and perform transmissions
+        mConnectedThread = new ConnectedThread(socket);
+        mConnectedThread.start();
+
+        connected = true;
+        event(EVENT_CONNECTED);
+    }    
+    
+    
+    private void connectionFailed() {    	
+    	connected = false;
+    	if (disconnecting) {
+    		disconnecting = false;
+    	} else {	
+	    	if ((timeout > 0) && (System.currentTimeMillis() < timeout)) {
+	    		Util.log("RETRY: "+retryCnt + " time left: " + (timeout - System.currentTimeMillis()));    		
+	    		doConnect(true);
+	    	} else {    	
+	    		event(EVENT_CONNECTION_FAILED);
+	    	}     
+    	}
+    }    
+    
+    private void connectionLost() { 
+    	connected = false;
+    	if (disconnecting) {
+    		disconnecting = false;
+    	} else {
+    		event(EVENT_CONNECTION_LOST);
+    	}
+    }    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    private class ConnectThread extends Thread {
+    	
+        private final BluetoothSocket mmSocket;
+        private final BluetoothDevice mmDevice;
+
+        public ConnectThread(BluetoothDevice device, boolean useReflection) {
+            mmDevice = device;
+            BluetoothSocket tmp = null;
+
+            try {    
+            	if (useReflection) {
+            		Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
+                    tmp = (BluetoothSocket) m.invoke(device, 1);            		
+            	} else {
+            		tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
+            	}
+                
+            } catch (IOException e) {
+                Util.log("Socket create() failed");
+            } catch (Exception e) {
+            	Util.log("Socket create() REFLECTION failed");
+				e.printStackTrace();
+			} 
+            mmSocket = tmp;
+        }
+
+        public void run() {
+        	Util.log("BEGIN mConnectThread");
+            
+            mAdapter.cancelDiscovery(); //else it will slow down connection
+
+            try {
+                mmSocket.connect();
+            } catch (IOException e) {
+                try {
+                    mmSocket.close();
+                } catch (IOException e2) {
+                	Util.log("unable to close() socket during connection failure");
+                }
+                connectionFailed();
+                return;
+            }
+
+            // Reset the ConnectThread
+            synchronized (BTService.this) {
+                mConnectThread = null;
+            }
+
+            connected(mmSocket, mmDevice);
+        }
+
+        public void cancel() {
+            try {
+                mmSocket.close();
+            } catch (IOException e) {
+            	Util.log("close() of connect socket failed");
+            }
+        }
+    }
+
+
+
+    private class ConnectedThread extends Thread {
+    	
+        private final BluetoothSocket mmSocket;
+        private final InputStream mmInStream;
+        private final OutputStream mmOutStream;
+
+        public ConnectedThread(BluetoothSocket socket) {
+        	Util.log("create ConnectedThread");
+            mmSocket = socket;
+            InputStream tmpIn = null;
+            OutputStream tmpOut = null;
+
+            try {
+                tmpIn = socket.getInputStream();
+                tmpOut = socket.getOutputStream();
+            } catch (IOException e) {
+            	Util.log("temp sockets not created");
+            }
+           
+            mmInStream = tmpIn;
+            mmOutStream = tmpOut;
+        }
+
+        public void run() {
+        	Util.log("BEGIN mConnectedThread");           
+            byte[] buffer = null;    
+            int rxTmp;
+            int lengthByte;
+            int length;            
+            while (true) {
+                try {
+                	rxTmp = mmInStream.read();
+                	if (rxTmp == Packet.START_TAG) {
+	                	lengthByte = mmInStream.read();
+	                	length = lengthByte;
+						length &= 0x3F;
+						length *= 16;					
+						buffer = new byte[length + 2];
+						buffer[0] = Packet.START_TAG;
+						buffer[1] = (byte)lengthByte;
+						for (int i = 2; i < length + 2; i++) {
+							buffer[i] = (byte)mmInStream.read();
+						}				
+						mHandler.obtainMessage(EVENT_DATA, 0, 0, buffer).sendToTarget();             
+                	} else {
+                		System.out.println("RX: " + rxTmp);
+                		//possible WDG reset															     
+                	}
+                } catch (IOException e) {
+                    connectionLost();
+                    break;
+                }
+            }
+        }
+
+        public void write(byte[] buffer) {      	
+            try {
+                mmOutStream.write(buffer);
+                mmOutStream.flush();
+            } catch (IOException e) {
+            	Util.log("Exception during write");
+            }
+        }          
+
+        public void cancel() {
+            try {
+                mmSocket.close();
+            } catch (IOException e) {
+            	Util.log("close() of connect socket failed");
+            }
+        }
+    }            
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/hid/ConsumerReport.java b/src/java/InputStickAPI/src/com/inputstick/api/hid/ConsumerReport.java
new file mode 100644
index 00000000..859da27e
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/hid/ConsumerReport.java
@@ -0,0 +1,30 @@
+package com.inputstick.api.hid;
+
+import com.inputstick.api.Util;
+
+public class ConsumerReport extends HIDReport {
+	
+	public static final int SIZE = 3;
+	
+	private byte[] data;
+	
+	public ConsumerReport(int usage) {
+		data = new byte[SIZE];
+		data[0] = 1;
+		data[1] = Util.getLSB(usage);
+		data[2] = Util.getMSB(usage);		
+	}
+	
+	public ConsumerReport() {
+		this(0);
+	}
+	
+	public byte[] getBytes() {
+		return data;
+	}
+	
+	public int getBytesCount() {
+		return SIZE;
+	}	
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDKeycodes.java b/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDKeycodes.java
new file mode 100644
index 00000000..3528bdbd
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDKeycodes.java
@@ -0,0 +1,272 @@
+package com.inputstick.api.hid;
+
+public class HIDKeycodes {
+	
+	public static final byte NONE = 0x00;
+	
+	public static final byte CTRL_LEFT = 0x01;
+	public static final byte SHIFT_LEFT = 0x02;
+	public static final byte ALT_LEFT = 0x04;
+	public static final byte GUI_LEFT = 0x08;
+	public static final byte CTRL_RIGHT = 0x10;
+	public static final byte SHIFT_RIGHT = 0x20;
+	public static final byte ALT_RIGHT = 0x40;
+	public static final byte GUI_RIGHT = (byte)0x80;	
+	
+	public static final byte KEY_ENTER = 0x28;
+	public static final byte KEY_ESCAPE = 0x29;
+	public static final byte KEY_BACKSPACE = 0x2A;
+	public static final byte KEY_TAB = 0x2B;
+	public static final byte KEY_SPACEBAR = 0x2C;
+		
+	public static final byte KEY_CAPS_LOCK = 0x39;
+	
+	
+	public static final byte KEY_1 = 0x1E;
+	public static final byte KEY_2 = 0x1F;
+	public static final byte KEY_3 = 0x20;
+	public static final byte KEY_4 = 0x21;
+	public static final byte KEY_5 = 0x22;
+	public static final byte KEY_6 = 0x23;
+	public static final byte KEY_7 = 0x24;
+	public static final byte KEY_8 = 0x25;
+	public static final byte KEY_9 = 0x26;
+	public static final byte KEY_0 = 0x27;
+	
+	public static final byte KEY_F1 = 0x3A;
+	public static final byte KEY_F2 = 0x3B;
+	public static final byte KEY_F3 = 0x3C;
+	public static final byte KEY_F4 = 0x3D;
+	public static final byte KEY_F5 = 0x3E;
+	public static final byte KEY_F6 = 0x3F;
+	public static final byte KEY_F7 = 0x40;
+	public static final byte KEY_F8 = 0x41;
+	public static final byte KEY_F9 = 0x42;
+	public static final byte KEY_F10 = 0x43;
+	public static final byte KEY_F11 = 0x44;
+	public static final byte KEY_F12 = 0x45;		
+	
+	public static final byte KEY_PRINT_SCREEN = 0x46;
+	public static final byte KEY_SCROLL_LOCK = 0x47;
+	public static final byte KEY_PASUE = 0x48;
+	public static final byte KEY_INSERT = 0x49;
+	public static final byte KEY_HOME = 0x4A;
+	public static final byte KEY_PAGE_UP = 0x4B;
+	public static final byte KEY_DELETE = 0x4C;
+	public static final byte KEY_END = 0x4D;
+	public static final byte KEY_PAGE_DOWN = 0x4E;
+	
+	public static final byte KEY_ARROW_RIGHT = 0x4F;
+	public static final byte KEY_ARROW_LEFT = 0x50;
+	public static final byte KEY_ARROW_DOWN = 0x51;
+	public static final byte KEY_ARROW_UP = 0x52;		
+	
+	public static final byte KEY_NUM_LOCK = 0x53;	
+	public static final byte KEY_NUM_BACKSLASH = 	0x54;
+	public static final byte KEY_NUM_STAR = 		0x55;
+	public static final byte KEY_NUM_MINUS = 		0x56;
+	public static final byte KEY_NUM_PLUS = 		0x57;	
+	public static final byte KEY_NUM_ENTER = 		0x58;	
+	public static final byte KEY_NUM_1 = 			0x59;
+	public static final byte KEY_NUM_2 = 			0x5A;
+	public static final byte KEY_NUM_3 = 			0x5B;
+	public static final byte KEY_NUM_4 = 			0x5C;
+	public static final byte KEY_NUM_5 = 			0x5D;
+	public static final byte KEY_NUM_6 = 			0x5E;
+	public static final byte KEY_NUM_7 = 			0x5F;
+	public static final byte KEY_NUM_8 = 			0x60;
+	public static final byte KEY_NUM_9 = 			0x61;
+	public static final byte KEY_NUM_0 = 			0x62;		
+	public static final byte KEY_NUM_DOT = 			0x63;
+	
+	public static final byte KEY_A = 				0x04;
+	public static final byte KEY_B = 				0x05;
+	public static final byte KEY_C = 				0x06;
+	public static final byte KEY_D = 				0x07;
+	public static final byte KEY_E = 				0x08;
+	public static final byte KEY_F = 				0x09;
+	public static final byte KEY_G = 				0x0A;
+	public static final byte KEY_H = 				0x0B;
+	public static final byte KEY_I = 				0x0C;
+	public static final byte KEY_J = 				0x0D;
+	public static final byte KEY_K = 				0x0E;
+	public static final byte KEY_L = 				0x0F;
+	public static final byte KEY_M = 				0x10;
+	public static final byte KEY_N = 				0x11;
+	public static final byte KEY_O = 				0x12;
+	public static final byte KEY_P = 				0x13;
+	public static final byte KEY_Q = 				0x14;
+	public static final byte KEY_R = 				0x15;
+	public static final byte KEY_S = 				0x16;
+	public static final byte KEY_T = 				0x17;
+	public static final byte KEY_U = 				0x18;	
+	public static final byte KEY_V = 				0x19;
+	public static final byte KEY_W = 				0x1A;
+	public static final byte KEY_X = 				0x1B;
+	public static final byte KEY_Y = 				0x1C;
+	public static final byte KEY_Z = 				0x1D;
+	
+
+	
+	public static final byte KEY_MINUS = 			0x2D;
+	public static final byte KEY_EQUALS = 			0x2E;	
+	public static final byte KEY_LEFT_BRACKET = 	0x2F;
+	public static final byte KEY_RIGHT_BRACKET = 	0x30;
+	public static final byte KEY_BACKSLASH =		0x31;
+	//public static final byte KEY_GRAVE = 			0x32;
+	public static final byte KEY_SEMICOLON = 		0x33;
+	public static final byte KEY_APOSTROPHE = 		0x34;
+	public static final byte KEY_GRAVE = 			0x35;
+	public static final byte KEY_COMA = 			0x36;
+	public static final byte KEY_DOT = 				0x37;	
+	public static final byte KEY_SLASH = 			0x38;
+
+	
+	public static final byte KEY_APPLICATION = 		0x65;	
+	
+	
+	
+    public static final int[] ASCIItoHID = {
+        0, //000
+        0, //001
+        0, //002
+        0, //003
+        0, //004
+        0, //005
+        0, //006
+        0, //007
+        0, //008
+        0, //009
+        0, //010
+        0, //011
+        0, //012
+        0, //013
+        0, //014
+        0, //015
+        0, //016
+        0, //017
+        0, //018
+        0, //019
+        0, //020
+        0, //021
+        0, //022
+        0, //023
+        0, //024
+        0, //025
+        0, //026
+        0, //027
+        0, //028
+        0, //029
+        0, //030
+        0, //031
+        44, //032 space
+        128 + 30, //033 ! [SHIFT]
+        128 + 52, //034 " [SHIFT]
+        128 + 32, //035 # [SHIFT]
+        128 + 33, //036 $ [SHIFT]
+        128 + 34, //037 % [SHIFT]
+        128 + 36, //038 & [SHIFT]
+        52, //039 '
+        128 + 38, //040 ( [SHIFT]
+        128 + 39, //041 ) [SHIFT]
+        128 + 37, //042 * [SHIFT]
+        128 + 46, //043 + [SHIFT]
+        54, //044 ,
+        45, //045 - (-)
+        55, //046 . (.)
+        56, //047 /
+        39, //048 0
+        30, //049 1
+        31, //050 2
+        32, //051 3
+        33, //052 4
+        34, //053 5
+        35, //054 6
+        36, //055 7
+        37, //056 8
+        38, //057 9
+        128 + 51, //058 : [SHIFT]
+        51, //059 ;
+        128 + 54, //060 < [SHIFT]
+        46, //061 =
+        128 + 55, //062 > [SHIFT]
+        128 + 56, //063 ? [SHIFT]
+        128 + 31, //064 @ [SHIFT]
+        128 + 4, //065 A [SHIFT]
+        128 + 5, //066 B [SHIFT]
+        128 + 6, //067 C [SHIFT]
+        128 + 7, //068 D [SHIFT]
+        128 + 8, //069 E [SHIFT]
+        128 + 9, //070 F [SHIFT]
+        128 + 10, //071 G [SHIFT]
+        128 + 11, //072 H [SHIFT]
+        128 + 12, //073 I [SHIFT]
+        128 + 13, //074 J [SHIFT]
+        128 + 14, //075 K [SHIFT]
+        128 + 15, //076 L [SHIFT]
+        128 + 16, //077 M [SHIFT]
+        128 + 17, //078 N [SHIFT]
+        128 + 18, //079 O [SHIFT]
+        128 + 19, //080 P [SHIFT]
+        128 + 20, //081 Q [SHIFT]
+        128 + 21, //082 R [SHIFT]
+        128 + 22, //083 S [SHIFT]
+        128 + 23, //084 T [SHIFT]
+        128 + 24, //085 U [SHIFT]
+        128 + 25, //086 V [SHIFT]
+        128 + 26, //087 W [SHIFT]
+        128 + 27, //088 X [SHIFT]
+        128 + 28, //089 Y [SHIFT]
+        128 + 29, //090 Z [SHIFT]
+        47, //091 [
+        49, /*092 \   */
+        48, //093 ]
+        128 + 35, //094 ^ [SHIFT]
+        128 + 45, //095 _ [SHIFT] (underscore)
+        128 + 53, //096 ` [SHIFT] (grave accent)
+        4, //097 a
+        5, //098 b
+        6, //099 c
+        7, //100 d
+        8, //101 e
+        9, //102 f
+        10, //103 g
+        11, //104 h
+        12, //105 i
+        13, //106 j
+        14, //107 k
+        15, //108 l
+        16, //109 m
+        17, //110 n
+        18, //111 o
+        19, //112 p
+        20, //113 q
+        21, //114 r
+        22, //115 s
+        23, //116 t
+        24, //117 u
+        25, //118 v
+        26, //119 w
+        27, //120 x
+        28, //121 y
+        29, //122 z
+        128 + 47, //123 { [SHIFT]
+        128 + 49, //124 | [SHIFT]
+        128 + 48, //125 } [SHIFT]
+        128 + 53, //126 ~ [SHIFT]
+        0       //127 just in case...
+    };	
+    
+    
+	public static byte getKeyCode(char c) {
+		return (byte)ASCIItoHID[c]; //TODO range
+	}
+	
+	public static int getKeyCode(int c) {
+		return ASCIItoHID[c]; //TODO range
+	}    
+    
+    
+    
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDReport.java b/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDReport.java
new file mode 100644
index 00000000..28cce791
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDReport.java
@@ -0,0 +1,8 @@
+package com.inputstick.api.hid;
+
+public abstract class HIDReport {
+
+	public abstract byte[] getBytes();
+	public abstract int getBytesCount();
+	
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDTransaction.java b/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDTransaction.java
new file mode 100644
index 00000000..3dd06973
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDTransaction.java
@@ -0,0 +1,56 @@
+package com.inputstick.api.hid;
+
+import java.util.Vector;
+
+public class HIDTransaction {
+
+	private int mID;
+	private Vector<HIDReport> reports;
+	
+	public HIDTransaction() {
+		reports = new Vector<HIDReport>();
+	}
+	
+	public void addReport(HIDReport report) {
+		reports.add(report);
+	}
+	
+	public int getReportsCount() {
+		return reports.size();
+	}
+	
+	public void setID(int id) {
+		mID = id;
+	}
+	
+	public int getID() {
+		return mID;
+	}
+	
+	public boolean hasNext() {
+		return !reports.isEmpty();
+	}
+	
+	public byte[] getNextReport() {
+		byte[] report;
+		report = reports.elementAt(0).getBytes();
+		reports.removeElementAt(0);
+		return report;
+	}
+	
+	public HIDTransaction split(int n) {
+		HIDTransaction result = new HIDTransaction();
+		HIDReport report;
+		if (n <= reports.size()) {
+			while(n > 0) {
+				report = reports.firstElement();
+				reports.remove(0);
+				result.addReport(report);
+				n--;
+			}		
+		}
+		
+		return result;
+	}
+	
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDTransactionQueue.java b/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDTransactionQueue.java
new file mode 100644
index 00000000..64b174ee
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/hid/HIDTransactionQueue.java
@@ -0,0 +1,111 @@
+package com.inputstick.api.hid;
+
+import java.util.Vector;
+import com.inputstick.api.ConnectionManager;
+import com.inputstick.api.Packet;
+
+public class HIDTransactionQueue {
+	
+	public static final int KEYBOARD = 1;
+	public static final int MOUSE = 2;
+	public static final int CONSUMER = 3;
+	
+	private static final int BUFFER_SIZE = 32;
+
+	private final Vector<HIDTransaction> queue;
+	private final ConnectionManager mConnectionManager;
+	private final byte cmd;
+	private boolean ready;
+	
+	
+	private long lastTime;
+	private int lastReports;
+	
+	
+	public HIDTransactionQueue(int type, ConnectionManager connectionManager) {
+		queue = new Vector<HIDTransaction>();
+		mConnectionManager = connectionManager;
+		ready = false;
+		switch (type) {
+			case KEYBOARD:
+				cmd = Packet.CMD_HID_DATA_KEYB;
+				break;
+			case MOUSE:
+				cmd = Packet.CMD_HID_DATA_MOUSE;
+				break;
+			case CONSUMER:
+				cmd = Packet.CMD_HID_DATA_CONSUMER;
+				break;
+			default:
+				cmd = Packet.CMD_DUMMY;
+		}
+	}
+	
+	private void sendNext() {
+		HIDTransaction transaction;
+		byte reports = 0;
+		ready = false;
+		Packet p = new Packet(false, cmd, reports);
+		
+		//assume there is at least 1 element in queue		
+		transaction = queue.firstElement();
+		if (transaction.getReportsCount() > BUFFER_SIZE) {
+			//transaction too big! split
+			transaction = transaction.split(BUFFER_SIZE);			
+		} else {
+			queue.removeElementAt(0);						
+		}
+				
+		while (transaction.hasNext()) {
+			p.addBytes(transaction.getNextReport());
+			reports++;
+		}		
+		//TODO add next transactions if possible
+		
+		while(true) {
+			if (queue.isEmpty()) {
+				break;
+			}
+			
+			transaction = queue.firstElement();			
+			if (reports + transaction.getReportsCount() < BUFFER_SIZE) {
+				queue.removeElementAt(0);	
+				while (transaction.hasNext()) {
+					p.addBytes(transaction.getNextReport());
+					reports++;
+				}				
+			} else {
+				break;
+			}
+		}
+		
+		
+		p.modifyByte(1, reports); //set reports count
+		mConnectionManager.sendPacket(p);	
+		
+		lastReports = reports;
+		lastTime = System.currentTimeMillis();
+	}
+	
+	public void addTransaction(HIDTransaction transaction) {
+		if (queue.isEmpty()) {
+			if (System.currentTimeMillis() > lastTime + (lastReports * 8 * 2/*just to be safe*/)) {
+				ready = true;
+			}
+		}		
+		
+		queue.add(transaction);						
+		if (ready) {
+			sendNext();
+		} 		
+	}
+	
+	public void deviceReady() {
+		if (!queue.isEmpty()) {
+			sendNext();
+		} else {
+			ready = true;
+		}
+	}			
+	
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/hid/KeyboardReport.java b/src/java/InputStickAPI/src/com/inputstick/api/hid/KeyboardReport.java
new file mode 100644
index 00000000..7ece9b62
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/hid/KeyboardReport.java
@@ -0,0 +1,36 @@
+package com.inputstick.api.hid;
+
+public class KeyboardReport extends HIDReport {
+	
+	public static final int SIZE = 8;
+	
+	private byte[] data;
+
+	public KeyboardReport(byte modifier, byte key0, byte key1, byte key2, byte key3, byte key4, byte key5) {
+		data = new byte[SIZE];
+		data[0] = modifier;
+		data[2] = key0;
+		data[3] = key1;
+		data[4] = key2;
+		data[5] = key3;
+		data[6] = key4;
+		data[7] = key5;
+	}
+	
+	public KeyboardReport() {
+		this((byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0);
+	}
+	
+	public KeyboardReport(byte modifier, byte key) {
+		this(modifier, key, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0);
+	}
+	
+	public byte[] getBytes() {
+		return data;
+	}
+	
+	public int getBytesCount() {
+		return SIZE;
+	}
+	
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/hid/MouseReport.java b/src/java/InputStickAPI/src/com/inputstick/api/hid/MouseReport.java
new file mode 100644
index 00000000..8454513e
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/hid/MouseReport.java
@@ -0,0 +1,29 @@
+package com.inputstick.api.hid;
+
+public class MouseReport extends HIDReport {
+	
+	public static final int SIZE = 4;
+	
+	private byte[] data;
+
+	public MouseReport(byte buttons, byte x, byte y, byte wheel) {
+		data = new byte[SIZE];
+		data[0] = buttons;
+		data[1] = x;
+		data[2] = y;
+		data[3] = wheel;
+	}
+	
+	public MouseReport() {
+		this((byte)0, (byte)0, (byte)0, (byte)0);
+	}	
+	
+	public byte[] getBytes() {
+		return data;
+	}
+	
+	public int getBytesCount() {
+		return SIZE;
+	}	
+	
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/layout/GermanLayout.java b/src/java/InputStickAPI/src/com/inputstick/api/layout/GermanLayout.java
new file mode 100644
index 00000000..b5c56677
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/layout/GermanLayout.java
@@ -0,0 +1,142 @@
+package com.inputstick.api.layout;
+
+public class GermanLayout extends KeyboardLayout {
+	
+	public static final String LOCALE_NAME = "de-DE";
+	
+	public static final int LUT[][] = {
+		/*	0	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	1	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	2	*/	{	0	,	(int)'1'	,	0x21	,	-1	,	-1	,	-1	}	,
+		/*	3	*/	{	0	,	(int)'2'	,	0x22	,	-1	,	0x00b2	,	0x00b2	}	,
+		/*	4	*/	{	0	,	(int)'3'	,	0x00a7	,	-1	,	0x00b3	,	0x00b3	}	,
+		/*	5	*/	{	0	,	(int)'4'	,	0x24	,	-1	,	-1	,	-1	}	,
+		/*	6	*/	{	0	,	(int)'5'	,	0x25	,	-1	,	-1	,	-1	}	,
+		/*	7	*/	{	0	,	(int)'6'	,	0x26	,	-1	,	-1	,	-1	}	,
+		/*	8	*/	{	0	,	(int)'7'	,	0x002f	,	-1	,	0x007b	,	0x007b	}	,
+		/*	9	*/	{	0	,	(int)'8'	,	0x28	,	-1	,	0x005b	,	0x005b	}	,
+		/*	0a	*/	{	0	,	(int)'9'	,	0x29	,	-1	,	0x005d	,	0x005d	}	,
+		/*	0b	*/	{	0	,	(int)'0'	,	0x003d	,	-1	,	0x007d	,	0x007d	}	,
+		/*	0c	*/	{	0	,	0x00df	,	0x003f	,	-1	,	0x005c	,	0x005c	}	,
+		/*	0d	*/	{	0	,	0x00b4	,	0x0060	,	-1	,	-1	,	-1	}	,
+		/*	0e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	0f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		
+		
+		/*	10	*/	{	1	,	(int)'q'	,	(int)'Q'	,	-1	,	0x40	,	0x40	}	,
+		/*	11	*/	{	1	,	(int)'w'	,	(int)'W'	,	-1	,	-1	,	-1	}	,
+		/*	12	*/	{	1	,	(int)'e'	,	(int)'E'	,	-1	,	0x20ac	,	-1	}	,
+		/*	13	*/	{	1	,	(int)'r'	,	(int)'R'	,	-1	,	-1	,	-1	}	,
+		/*	14	*/	{	1	,	(int)'t'	,	(int)'T'	,	-1	,	-1	,	-1	}	,
+		/*	15	*/	{	1	,	(int)'z'	,	(int)'Z'	,	-1	,	-1	,	-1	}	,
+		/*	16	*/	{	1	,	(int)'u'	,	(int)'U'	,	-1	,	-1	,	-1	}	,
+		/*	17	*/	{	1	,	(int)'i'	,	(int)'I'	,	-1	,	-1	,	-1	}	,
+		/*	18	*/	{	1	,	(int)'o'	,	(int)'O'	,	-1	,	-1	,	-1	}	,
+		/*	19	*/	{	1	,	(int)'p'	,	(int)'P'	,	-1	,	-1	,	-1	}	,
+		/*	1a	*/	{	1	,	0x00fc	,	0x00dc	,	0x001b	,	-1	,	-1	}	,
+		/*	1b	*/	{	0	,	0x002b	,	0x002a	,	0x001d	,	0x007e	,	0x007e	}	,
+		/*	1c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	1d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	1e	*/	{	1	,	(int)'a'	,	(int)'A'	,	-1	,	-1	,	-1	}	,
+		/*	1f	*/	{	1	,	(int)'s'	,	(int)'S'	,	-1	,	-1	,	-1	}	,
+		
+		/*	20	*/	{	1	,	(int)'d'	,	(int)'D'	,	-1	,	-1	,	-1	}	,
+		/*	21	*/	{	1	,	(int)'f'	,	(int)'F'	,	-1	,	-1	,	-1	}	,
+		/*	22	*/	{	1	,	(int)'g'	,	(int)'G'	,	-1	,	-1	,	-1	}	,
+		/*	23	*/	{	1	,	(int)'h'	,	(int)'H'	,	-1	,	-1	,	-1	}	,
+		/*	24	*/	{	1	,	(int)'j'	,	(int)'J'	,	-1	,	-1	,	-1	}	,
+		/*	25	*/	{	1	,	(int)'k'	,	(int)'K'	,	-1	,	-1	,	-1	}	,
+		/*	26	*/	{	1	,	(int)'l'	,	(int)'L'	,	-1	,	-1	,	-1	}	,
+		/*	27	*/	{	1	,	0x00f6	,	0x00d6	,	-1	,	-1	,	-1	}	,
+		/*	28	*/	{	1	,	0x00e4	,	0x00c4	,	-1	,	-1	,	-1	}	,
+		/*	29	*/	{	0	,	0x005e	,	0x00b0	,	-1	,	-1	,	-1	}	,
+		/*	2a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	2b	*/	{	0	,	0x23	,	0x27	,	0x001c	,	-1	,	-1	}	,
+		/*	2c	*/	{	1	,	(int)'y'	,	(int)'Y'	,	-1	,	-1	,	-1	}	,
+		/*	2d	*/	{	1	,	(int)'x'	,	(int)'X'	,	-1	,	-1	,	-1	}	,
+		/*	2e	*/	{	1	,	(int)'c'	,	(int)'C'	,	-1	,	-1	,	-1	}	,
+		/*	2f	*/	{	1	,	(int)'v'	,	(int)'V'	,	-1	,	-1	,	-1	}	,
+		
+		/*	30	*/	{	1	,	(int)'b'	,	(int)'B'	,	-1	,	-1	,	-1	}	,
+		/*	31	*/	{	1	,	(int)'n'	,	(int)'N'	,	-1	,	-1	,	-1	}	,
+		/*	32	*/	{	1	,	(int)'m'	,	(int)'M'	,	-1	,	0x00b5	,	0x00b5	}	,
+		/*	33	*/	{	0	,	0x002c	,	0x003b	,	-1	,	-1	,	-1	}	,
+		/*	34	*/	{	0	,	0x002e	,	0x003a	,	-1	,	-1	,	-1	}	,
+		/*	35	*/	{	0	,	0x002d	,	0x005f	,	-1	,	-1	,	-1	}	,
+		/*	36	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	37	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	38	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	39	*/	{	0	,	0x20	,	0x20	,	0x20	,	-1	,	-1	}	,
+		/*	3a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		
+		/*	40	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	41	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	42	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	43	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	44	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	45	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	46	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	47	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+		/*	48	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	49	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		
+		/*	50	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	51	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+		/*	52	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	53	*/	{	0	,	0x002c	,	0x002c	,	-1	,	-1	,	-1	}	,
+		/*	54	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	55	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	56	*/	{	0	,	0x003c	,	0x003e	,	-1	,	0x007c	,	0x007c	}	,
+		/*	57	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+		/*	58	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	59	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,		
+		
+	};
+	
+	private static GermanLayout instance = new GermanLayout();
+	
+	private GermanLayout() {
+	}
+	
+	public static GermanLayout getInstance() {
+		return instance;
+	}	
+	
+	@Override
+	public int[][] getLUT() {
+		return LUT;
+	}
+
+	@Override
+	public void type(String text) {
+		super.type(LUT, text);
+	}	
+	
+	@Override
+	public char getChar(int scanCode, boolean capsLock, boolean shift, boolean altGr) {
+		return super.getChar(LUT, scanCode, capsLock, shift, altGr);
+	}	
+	
+	@Override
+	public String getLocaleName() {		
+		return LOCALE_NAME;
+	}			
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/layout/KeyboardLayout.java b/src/java/InputStickAPI/src/com/inputstick/api/layout/KeyboardLayout.java
new file mode 100644
index 00000000..20cbd121
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/layout/KeyboardLayout.java
@@ -0,0 +1,269 @@
+package com.inputstick.api.layout;
+
+import com.inputstick.api.ConnectionManager;
+import com.inputstick.api.basic.InputStickHID;
+import com.inputstick.api.hid.HIDKeycodes;
+import com.inputstick.api.hid.HIDTransaction;
+import com.inputstick.api.hid.KeyboardReport;
+
+public abstract class KeyboardLayout {
+	
+	public static final byte[] scanCodeToHID = {
+		/* 0x00 */ 0,
+		/* 0x01 */ HIDKeycodes.KEY_ESCAPE,
+		/* 0x02 */ HIDKeycodes.KEY_1,
+		/* 0x03 */ HIDKeycodes.KEY_2,
+		/* 0x04 */ HIDKeycodes.KEY_3,
+		/* 0x05 */ HIDKeycodes.KEY_4,
+		/* 0x06 */ HIDKeycodes.KEY_5,
+		/* 0x07 */ HIDKeycodes.KEY_6,
+		/* 0x08 */ HIDKeycodes.KEY_7,
+		/* 0x09 */ HIDKeycodes.KEY_8,
+		/* 0x0a */ HIDKeycodes.KEY_9,
+		/* 0x0b */ HIDKeycodes.KEY_0,
+		/* 0x0c */ HIDKeycodes.KEY_MINUS,
+		/* 0x0d */ HIDKeycodes.KEY_EQUALS,
+		/* 0x0e */ HIDKeycodes.KEY_BACKSPACE,
+		/* 0x0f */ HIDKeycodes.KEY_TAB,
+			
+		
+		/* 0x10 */ HIDKeycodes.KEY_Q,
+		/* 0x11 */ HIDKeycodes.KEY_W,
+		/* 0x12 */ HIDKeycodes.KEY_E,
+		/* 0x13 */ HIDKeycodes.KEY_R,
+		/* 0x14 */ HIDKeycodes.KEY_T,
+		/* 0x15 */ HIDKeycodes.KEY_Y,
+		/* 0x16 */ HIDKeycodes.KEY_U,
+		/* 0x17 */ HIDKeycodes.KEY_I,
+		/* 0x18 */ HIDKeycodes.KEY_O,
+		/* 0x19 */ HIDKeycodes.KEY_P,
+		/* 0x1a */ HIDKeycodes.KEY_LEFT_BRACKET,
+		/* 0x1b */ HIDKeycodes.KEY_RIGHT_BRACKET,
+		/* 0x1c */ HIDKeycodes.KEY_ENTER,
+		/* 0x1d */ 0, //RL CTRL
+		/* 0x1e */ HIDKeycodes.KEY_A,
+		/* 0x1f */ HIDKeycodes.KEY_S,	
+		
+		/* 0x20 */ HIDKeycodes.KEY_D,
+		/* 0x21 */ HIDKeycodes.KEY_F,
+		/* 0x22 */ HIDKeycodes.KEY_G,
+		/* 0x23 */ HIDKeycodes.KEY_H,
+		/* 0x24 */ HIDKeycodes.KEY_J,
+		/* 0x25 */ HIDKeycodes.KEY_K,
+		/* 0x26 */ HIDKeycodes.KEY_L,
+		/* 0x27 */ HIDKeycodes.KEY_SEMICOLON,
+		/* 0x28 */ HIDKeycodes.KEY_APOSTROPHE,
+		/* 0x29 */ HIDKeycodes.KEY_GRAVE,
+		/* 0x2a */ 0, //L SHIFT
+		/* 0x2b */ HIDKeycodes.KEY_BACKSLASH,
+		/* 0x2c */ HIDKeycodes.KEY_Z,
+		/* 0x2d */ HIDKeycodes.KEY_X,
+		/* 0x2e */ HIDKeycodes.KEY_C,
+		/* 0x2f */ HIDKeycodes.KEY_V,		
+		
+		/* 0x30 */ HIDKeycodes.KEY_B,
+		/* 0x31 */ HIDKeycodes.KEY_N,
+		/* 0x32 */ HIDKeycodes.KEY_M,
+		/* 0x33 */ HIDKeycodes.KEY_COMA,
+		/* 0x34 */ HIDKeycodes.KEY_DOT,
+		/* 0x35 */ HIDKeycodes.KEY_SLASH,
+		/* 0x36 */ 0, //R SHIFT
+		/* 0x37 */ HIDKeycodes.KEY_PRINT_SCREEN,
+		/* 0x38 */ 0, //RL ALT
+		/* 0x39 */ HIDKeycodes.KEY_SPACEBAR,
+		/* 0x3a */ HIDKeycodes.KEY_CAPS_LOCK,
+		/* 0x3b */ HIDKeycodes.KEY_F1,
+		/* 0x3c */ HIDKeycodes.KEY_F2,
+		/* 0x3d */ HIDKeycodes.KEY_F3,
+		/* 0x3e */ HIDKeycodes.KEY_F4,
+		/* 0x3f */ HIDKeycodes.KEY_F5,
+		
+		/* 0x40 */ HIDKeycodes.KEY_F6,
+		/* 0x41 */ HIDKeycodes.KEY_F7,
+		/* 0x42 */ HIDKeycodes.KEY_F8,
+		/* 0x43 */ HIDKeycodes.KEY_F9,
+		/* 0x44 */ HIDKeycodes.KEY_F10,
+		/* 0x45 */ HIDKeycodes.KEY_NUM_LOCK,
+		/* 0x46 */ HIDKeycodes.KEY_SCROLL_LOCK,
+		/* 0x47 */ HIDKeycodes.KEY_HOME,
+		/* 0x48 */ HIDKeycodes.KEY_ARROW_UP,
+		/* 0x49 */ HIDKeycodes.KEY_PAGE_UP,
+		/* 0x4a */ 0, //-
+		/* 0x4b */ HIDKeycodes.KEY_ARROW_LEFT,
+		/* 0x4c */ 0, //CENTER
+		/* 0x4d */ HIDKeycodes.KEY_ARROW_RIGHT,
+		/* 0x4e */ 0, //+
+		/* 0x4f */ HIDKeycodes.KEY_END,
+		
+		/* 0x50 */ HIDKeycodes.KEY_ARROW_DOWN,
+		/* 0x51 */ HIDKeycodes.KEY_PAGE_DOWN,
+		/* 0x52 */ HIDKeycodes.KEY_INSERT,
+		/* 0x53 */ HIDKeycodes.KEY_DELETE,
+		/* 0x54 */ 0,
+		/* 0x55 */ 0,
+		/* 0x56 */ 0,
+		/* 0x57 */ HIDKeycodes.KEY_F11,
+		/* 0x58 */ HIDKeycodes.KEY_F12,
+		/* 0x59 */ 0,
+		/* 0x5a */ 0,
+		/* 0x5b */ 0,
+		/* 0x5c */ 0,
+		/* 0x5d */ 0,
+		/* 0x5e */ 0,
+		/* 0x5f */ 0,		
+		
+	};	
+	
+	public static final int LAYOUT_CODE = 0;
+	
+	public abstract int[][] getLUT();
+	public abstract String getLocaleName();
+	public abstract void type(String text);
+	public abstract char getChar(int scanCode, boolean capsLock, boolean shift, boolean altGr);
+	
+	public void type(int[][] lut, String text) {
+		if (InputStickHID.getState() == ConnectionManager.STATE_READY) {			
+			char[] chars = text.toCharArray();
+			HIDTransaction t;
+			for (char c : chars) {
+				t = getHIDTransaction(lut, c);
+				if (t != null) {
+					InputStickHID.addKeyboardTransaction(t);
+				}
+			}
+		}
+	}	
+	
+	public static int hidToScanCode(byte key) {
+		for (int scanCode = 0; scanCode < 80; scanCode++) {
+			if (scanCodeToHID[scanCode] == key) {
+				return scanCode;
+			}
+		}
+		return -1;
+	}
+	
+	public static char getChar(int[][] lut, int scanCode, boolean capsLock, boolean shift, boolean altGr) {
+		if ((scanCode > 80) || (scanCode < 0)) {
+			return (char)0;
+		}
+		
+		int index = 1;
+		
+		if ((capsLock) && (lut[scanCode][0] > 0)) {
+			//capslock is on and it affects current key						
+			if (lut[scanCode][0] == 1) {
+				if (shift) {
+					index = 1; //caps + shift = default
+				} else {
+					index = 2; //shift
+				}
+			} else {
+				// >1
+				if (shift) {
+					if (altGr) {
+						index = 4; //caps + shift + alt = alt
+					} else {					
+						index = 1; //caps + shift = default
+					}
+				} else {
+					if (altGr) {
+						index = 5; //caps + alt = shift + alt
+					} else {
+						index = 2; //caps = shift
+					}
+				}					
+			}
+		} else {				
+			if (shift) {
+				index = 2;
+			}		
+			if (altGr) {
+				if (shift) {
+					index = 5;
+				} else {
+					index = 4;
+				}
+			} 
+		}
+		
+		if (lut[scanCode][index] == -1) {
+			index = 1;
+		} 
+		return (char)lut[scanCode][index];		
+	}
+	
+	public static int getScanCode(int[][] lut, char c) {		
+		for (int scanCode = 0; scanCode < 80; scanCode++) {
+			if (lut[scanCode][0] == -1) {
+				continue;
+			} else {
+				for (int i = 1; i < 6; i++) {
+					if (lut[scanCode][i] == (int)c) {
+						return scanCode;
+					}
+				}
+			}
+		}
+		return -1;
+	}
+	
+	public static byte getKey(int scanCode) {	
+		return scanCodeToHID[scanCode];
+	}
+	
+	public static byte getModifiers(int[][] lut, int scanCode, char c) {
+		if (lut[scanCode][1] == (int)c) {
+			return 0;
+		}
+		if (lut[scanCode][2] == (int)c) {
+			return HIDKeycodes.SHIFT_LEFT;
+		}
+		if (lut[scanCode][3] == (int)c) {
+			return HIDKeycodes.CTRL_LEFT;
+		}
+		if (lut[scanCode][4] == (int)c) {
+			return HIDKeycodes.ALT_RIGHT;
+		}
+		if (lut[scanCode][5] == (int)c) {
+			return HIDKeycodes.SHIFT_LEFT | HIDKeycodes.ALT_RIGHT;
+		}
+		
+		return 0;
+	}
+	
+	
+	public static HIDTransaction getHIDTransaction(int[][] lut, char c) {
+		byte modifiers, key;
+		int scanCode;
+		
+		HIDTransaction t = new HIDTransaction();		
+		scanCode = getScanCode(lut, c);
+		if (scanCode > 0) {
+			key = getKey(scanCode);
+			modifiers = getModifiers(lut, scanCode, c);
+			
+			t.addReport(new KeyboardReport(modifiers, (byte)0));
+			t.addReport(new KeyboardReport(modifiers, key));
+			t.addReport(new KeyboardReport());
+		}
+		return t;
+	}		
+	
+	public static KeyboardLayout getLayout(String locale) {
+		if (locale != null) {
+			if (locale.equals(UnitedStatesLayout.getInstance().getLocaleName())) {
+				return UnitedStatesLayout.getInstance();
+			} else if (locale.equals(PolishLayout.getInstance().getLocaleName())) {
+				return PolishLayout.getInstance();
+			} else if (locale.equals(RussianLayout.getInstance().getLocaleName())) {
+				return RussianLayout.getInstance();
+			} else if (locale.equals(GermanLayout.getInstance().getLocaleName())) {
+				return GermanLayout.getInstance();
+			}
+		}
+
+		return UnitedStatesLayout.getInstance();
+	}
+	
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/layout/PolishLayout.java b/src/java/InputStickAPI/src/com/inputstick/api/layout/PolishLayout.java
new file mode 100644
index 00000000..e9a3ec4b
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/layout/PolishLayout.java
@@ -0,0 +1,144 @@
+package com.inputstick.api.layout;
+
+
+public class PolishLayout extends KeyboardLayout {
+	
+	public static final String LOCALE_NAME = "pl-PL";
+	
+	public static final int LUT[][] = {
+	/*	0	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	1	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	2	*/	{	0	,	(int)'1'	,	0x21	,	-1	,	-1	,	-1	}	,
+	/*	3	*/	{	0	,	(int)'2'	,	0x40	,	-1	,	-1	,	-1	}	,
+	/*	4	*/	{	0	,	(int)'3'	,	0x23	,	-1	,	-1	,	-1	}	,
+	/*	5	*/	{	0	,	(int)'4'	,	0x24	,	-1	,	-1	,	-1	}	,
+	/*	6	*/	{	0	,	(int)'5'	,	0x25	,	-1	,	-1	,	-1	}	,
+	/*	7	*/	{	0	,	(int)'6'	,	0x005e	,	-1	,	-1	,	-1	}	,
+	/*	8	*/	{	0	,	(int)'7'	,	0x26	,	-1	,	-1	,	-1	}	,
+	/*	9	*/	{	0	,	(int)'8'	,	0x002a	,	-1	,	-1	,	-1	}	,
+	/*	0a	*/	{	0	,	(int)'9'	,	0x28	,	-1	,	-1	,	-1	}	,
+	/*	0b	*/	{	0	,	(int)'0'	,	0x29	,	-1	,	-1	,	-1	}	,
+	/*	0c	*/	{	0	,	0x002d		,	0x005f	,	-1	,	-1	,	-1	}	,
+	/*	0d	*/	{	0	,	0x003d		,	0x002b	,	-1	,	-1	,	-1	}	,
+	/*	0e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	0f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	
+	/*	10	*/	{	1	,	(int)'q'	,	(int)'Q'	,	-1	,	-1	,	-1	}	,
+	/*	11	*/	{	1	,	(int)'w'	,	(int)'W'	,	-1	,	-1	,	-1	}	,
+	/*	12	*/	{	5	,	(int)'e'	,	(int)'E'	,	-1	,	0x119	,	0x118	}	,
+	/*	13	*/	{	1	,	(int)'r'	,	(int)'R'	,	-1	,	-1	,	-1	}	,
+	/*	14	*/	{	1	,	(int)'t'	,	(int)'T'	,	-1	,	-1	,	-1	}	,
+	/*	15	*/	{	1	,	(int)'y'	,	(int)'Y'	,	-1	,	-1	,	-1	}	,
+	/*	16	*/	{	1	,	(int)'u'	,	(int)'U'	,	-1	,	0x20ac	,	-1	}	,
+	/*	17	*/	{	1	,	(int)'i'	,	(int)'I'	,	-1	,	-1	,	-1	}	,
+	/*	18	*/	{	5	,	(int)'o'	,	(int)'O'	,	-1	,	0x00f3	,	0x00d3	}	,
+	/*	19	*/	{	1	,	(int)'p'	,	(int)'P'	,	-1	,	-1	,	-1	}	,
+	/*	1a	*/	{	0	,	0x005b	,	0x007b	,	0x001b	,	-1	,	-1	}	,
+	/*	1b	*/	{	0	,	0x005d	,	0x007d	,	0x001d	,	-1	,	-1	}	,
+	/*	1c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	1d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	1e	*/	{	5	,	(int)'a'	,	(int)'A'	,	-1	,	0x105	,	0x104	}	,
+	/*	1f	*/	{	5	,	(int)'s'	,	(int)'S'	,	-1	,	0x015b	,	0x015a	}	,
+	
+	/*	20	*/	{	1	,	(int)'d'	,	(int)'D'	,	-1	,	-1	,	-1	}	,
+	/*	21	*/	{	1	,	(int)'f'	,	(int)'F'	,	-1	,	-1	,	-1	}	,
+	/*	22	*/	{	1	,	(int)'g'	,	(int)'G'	,	-1	,	-1	,	-1	}	,
+	/*	23	*/	{	1	,	(int)'h'	,	(int)'H'	,	-1	,	-1	,	-1	}	,
+	/*	24	*/	{	1	,	(int)'j'	,	(int)'J'	,	-1	,	-1	,	-1	}	,
+	/*	25	*/	{	1	,	(int)'k'	,	(int)'K'	,	-1	,	-1	,	-1	}	,
+	/*	26	*/	{	5	,	(int)'l'	,	(int)'L'	,	-1	,	0x142	,	0x141	}	,
+	/*	27	*/	{	0	,	0x003b	,	0x003a	,	0x001d	,	-1	,	-1	}	,
+	/*	28	*/	{	0	,	0x27	,	0x22	,	-1	,	-1	,	-1	}	,
+	/*	29	*/	{	0	,	0x60	,	0x007e	,	-1	,	-1	,	-1	}	, //@
+	/*	2a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	2b	*/	{	0	,	0x005c	,	0x007c	,	0x001c	,	-1	,	-1	}	,
+	/*	2c	*/	{	5	,	(int)'z'	,	(int)'Z'	,	-1	,	0x017c	,	0x017b	}	,
+	/*	2d	*/	{	5	,	(int)'x'	,	(int)'X'	,	-1	,	0x017a	,	0x179	}	,
+	/*	2e	*/	{	5	,	(int)'c'	,	(int)'C'	,	-1	,	0x107	,	0x106	}	,
+	/*	2f	*/	{	1	,	(int)'v'	,	(int)'V'	,	-1	,	-1	,	-1	}	,
+	
+	/*	30	*/	{	1	,	(int)'b'	,	(int)'B'	,	-1	,	-1	,	-1	}	,
+	/*	31	*/	{	5	,	(int)'n'	,	(int)'N'	,	-1	,	0x144	,	0x143	}	,
+	/*	32	*/	{	1	,	(int)'m'	,	(int)'M'	,	-1	,	-1	,	-1	}	,
+	/*	33	*/	{	0	,	0x002c	,	0x003c	,	-1	,	-1	,	-1	}	,
+	/*	34	*/	{	0	,	0x002e	,	0x003e	,	-1	,	-1	,	-1	}	,
+	/*	35	*/	{	0	,	0x002f	,	0x003f	,	-1	,	-1	,	-1	}	,
+	/*	36	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	37	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	38	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	39	*/	{	0	,	0x20	,	0x20	,	0x20	,	-1	,	-1	}	,
+	/*	3a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	
+	/*	40	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	41	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	42	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	43	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	44	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	45	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	46	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	47	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+	/*	48	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	49	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+	
+	/*	50	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	51	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	52	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+	/*	53	*/	{	0	,	0x002c	,	0x002c		,	-1	,	-1	,	-1	}	,
+	/*	54	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	55	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+	/*	56	*/	{	0	,	0x005c	,	0x007c		,	0x001c	,	-1	,	-1	}	,
+	/*	57	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+	/*	58	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	59	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,		
+	
+		
+	};
+	
+	private static PolishLayout instance = new PolishLayout();
+	
+	private PolishLayout() {
+	}
+	
+	public static PolishLayout getInstance() {
+		return instance;
+	}	
+
+	@Override
+	public int[][] getLUT() {
+		return LUT;
+	}
+
+	@Override
+	public void type(String text) {
+		super.type(LUT, text);
+	}
+
+	@Override
+	public char getChar(int scanCode, boolean capsLock, boolean shift, boolean altGr) {
+		return super.getChar(LUT, scanCode, capsLock, shift, altGr);
+	}
+
+	@Override
+	public String getLocaleName() {		
+		return LOCALE_NAME;
+	}	
+	
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/layout/RussianLayout.java b/src/java/InputStickAPI/src/com/inputstick/api/layout/RussianLayout.java
new file mode 100644
index 00000000..0000d097
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/layout/RussianLayout.java
@@ -0,0 +1,144 @@
+package com.inputstick.api.layout;
+
+public class RussianLayout extends KeyboardLayout {
+	
+	public static final String LOCALE_NAME = "ru-RU";
+	
+	public static final int LUT[][] = {
+	/*	0	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	1	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	2	*/	{	0	,	(int)'1'	,	0x21	,	-1	,	-1	,	-1	}	,
+	/*	3	*/	{	0	,	(int)'2'	,	0x22	,	-1	,	-1	,	-1	}	,
+	/*	4	*/	{	0	,	(int)'3'	,	0x2116	,	-1	,	-1	,	-1	}	,
+	/*	5	*/	{	0	,	(int)'4'	,	0x003b	,	-1	,	-1	,	-1	}	,
+	/*	6	*/	{	0	,	(int)'5'	,	0x25	,	-1	,	-1	,	-1	}	,
+	/*	7	*/	{	0	,	(int)'6'	,	0x003a	,	-1	,	-1	,	-1	}	,
+	/*	8	*/	{	0	,	(int)'7'	,	0x003f	,	-1	,	-1	,	-1	}	,
+	/*	9	*/	{	0	,	(int)'8'	,	0x002a	,	-1	,	-1	,	-1	}	,
+	/*	0a	*/	{	0	,	(int)'9'	,	0x28	,	-1	,	-1	,	-1	}	,
+	/*	0b	*/	{	0	,	(int)'0'	,	0x29	,	-1	,	-1	,	-1	}	,
+	/*	0c	*/	{	0	,	0x002d	,	0x005f	,	-1	,	-1	,	-1	}	,
+	/*	0d	*/	{	0	,	0x003d	,	0x002b	,	-1	,	-1	,	-1	}	,
+	/*	0e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	0f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	
+	/*	10	*/	{	1	,	0x439	,	0x419	,	-1	,	-1	,	-1	}	,
+	/*	11	*/	{	1	,	0x446	,	0x426	,	-1	,	-1	,	-1	}	,
+	/*	12	*/	{	1	,	0x443	,	0x423	,	-1	,	-1	,	-1	}	,
+	/*	13	*/	{	1	,	0x043a	,	0x041a	,	-1	,	-1	,	-1	}	,
+	/*	14	*/	{	1	,	0x435	,	0x415	,	-1	,	-1	,	-1	}	,
+	/*	15	*/	{	1	,	0x043d	,	0x041d	,	-1	,	-1	,	-1	}	,
+	/*	16	*/	{	1	,	0x433	,	0x413	,	-1	,	-1	,	-1	}	,
+	/*	17	*/	{	1	,	0x448	,	0x428	,	-1	,	-1	,	-1	}	,
+	/*	18	*/	{	1	,	0x449	,	0x429	,	-1	,	-1	,	-1	}	,
+	/*	19	*/	{	1	,	0x437	,	0x417	,	-1	,	-1	,	-1	}	,
+	/*	1a	*/	{	1	,	0x445	,	0x425	,	-1	,	-1	,	-1	}	,
+	/*	1b	*/	{	1	,	0x044a	,	0x042a	,	-1	,	-1	,	-1	}	,
+	/*	1c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	1d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	1e	*/	{	1	,	0x444	,	0x424	,	-1	,	-1	,	-1	}	,
+	/*	1f	*/	{	1	,	0x044b	,	0x042b	,	-1	,	-1	,	-1	}	,
+	
+	
+	/*	20	*/	{	1	,	0x432	,	0x412	,	-1	,	-1	,	-1	}	,
+	/*	21	*/	{	1	,	0x430	,	0x410	,	-1	,	-1	,	-1	}	,
+	/*	22	*/	{	1	,	0x043f	,	0x041f	,	-1	,	-1	,	-1	}	,
+	/*	23	*/	{	1	,	0x440	,	0x420	,	-1	,	-1	,	-1	}	,
+	/*	24	*/	{	1	,	0x043e	,	0x041e	,	-1	,	-1	,	-1	}	,
+	/*	25	*/	{	1	,	0x043b	,	0x041b	,	-1	,	-1	,	-1	}	,
+	/*	26	*/	{	1	,	0x434	,	0x414	,	-1	,	-1	,	-1	}	,
+	/*	27	*/	{	1	,	0x436	,	0x416	,	-1	,	-1	,	-1	}	,
+	/*	28	*/	{	1	,	0x044d	,	0x042d	,	-1	,	-1	,	-1	}	,
+	/*	29	*/	{	1	,	0x451	,	0x401	,	-1	,	-1	,	-1	}	,
+	/*	2a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	2b	*/	{	0	,	0x005c	,	0x002f	,	0x001c	,	-1	,	-1	}	,
+	/*	2c	*/	{	1	,	0x044f	,	0x042f	,	-1	,	-1	,	-1	}	,
+	/*	2d	*/	{	1	,	0x447	,	0x427	,	-1	,	-1	,	-1	}	,
+	/*	2e	*/	{	1	,	0x441	,	0x421	,	-1	,	-1	,	-1	}	,
+	/*	2f	*/	{	1	,	0x043c	,	0x041c	,	-1	,	-1	,	-1	}	,
+	
+	
+	/*	30	*/	{	1	,	0x438	,	0x418	,	-1	,	-1	,	-1	}	,
+	/*	31	*/	{	1	,	0x442	,	0x422	,	-1	,	-1	,	-1	}	,
+	/*	32	*/	{	1	,	0x044c	,	0x042c	,	-1	,	-1	,	-1	}	,
+	/*	33	*/	{	1	,	0x431	,	0x411	,	-1	,	-1	,	-1	}	,
+	/*	34	*/	{	1	,	0x044e	,	0x042e	,	-1	,	-1	,	-1	}	,
+	/*	35	*/	{	0	,	0x002e	,	0x002c	,	-1	,	-1	,	-1	}	,
+	/*	36	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	37	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	38	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	39	*/	{	0	,	0x20	,	0x20	,	0x20	,	-1	,	-1	}	,
+	/*	3a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	3f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	
+	/*	40	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	41	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	42	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	43	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	44	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	45	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	46	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	47	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+	/*	48	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	49	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	4f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	
+	
+	/*	50	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	51	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+	/*	52	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	53	*/	{	0	,	0x002c	,	0x002c	,	-1	,	-1	,	-1	}	,
+	/*	54	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	55	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	56	*/	{	0	,	0x005c	,	0x002f	,	0x001c	,	-1	,	-1	}	,
+	/*	57	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+	/*	58	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	59	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+	/*	5f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,				
+		
+	};
+	
+	private static RussianLayout instance = new RussianLayout();
+	
+	private RussianLayout() {
+	}
+	
+	public static RussianLayout getInstance() {
+		return instance;
+	}	
+	
+	@Override
+	public int[][] getLUT() {
+		return LUT;
+	}
+
+	@Override
+	public void type(String text) {
+		super.type(LUT, text);
+	}	
+	
+	@Override
+	public char getChar(int scanCode, boolean capsLock, boolean shift, boolean altGr) {
+		return super.getChar(LUT, scanCode, capsLock, shift, altGr);
+	}	
+	
+	@Override
+	public String getLocaleName() {		
+		return LOCALE_NAME;
+	}		
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/api/layout/UnitedStatesLayout.java b/src/java/InputStickAPI/src/com/inputstick/api/layout/UnitedStatesLayout.java
new file mode 100644
index 00000000..7f16d907
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/api/layout/UnitedStatesLayout.java
@@ -0,0 +1,146 @@
+package com.inputstick.api.layout;
+
+public class UnitedStatesLayout extends KeyboardLayout {
+	
+	public static final String LOCALE_NAME = "en-US";
+	
+	public static final int LUT[][] = {
+		/*	0	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	1	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	2	*/	{	0	,	(int)'1'	,	0x21	,	-1	,	-1	,	-1	}	,
+		/*	3	*/	{	0	,	(int)'2'	,	0x40	,	-1	,	-1	,	-1	}	,
+		/*	4	*/	{	0	,	(int)'3'	,	0x23	,	-1	,	-1	,	-1	}	,
+		/*	5	*/	{	0	,	(int)'4'	,	0x24	,	-1	,	-1	,	-1	}	,
+		/*	6	*/	{	0	,	(int)'5'	,	0x25	,	-1	,	-1	,	-1	}	,
+		/*	7	*/	{	0	,	(int)'6'	,	0x005e	,	-1	,	-1	,	-1	}	,
+		/*	8	*/	{	0	,	(int)'7'	,	0x26	,	-1	,	-1	,	-1	}	,
+		/*	9	*/	{	0	,	(int)'8'	,	0x002a	,	-1	,	-1	,	-1	}	,
+		/*	0a	*/	{	0	,	(int)'9'	,	0x28	,	-1	,	-1	,	-1	}	,
+		/*	0b	*/	{	0	,	(int)'0'	,	0x29	,	-1	,	-1	,	-1	}	,
+		/*	0c	*/	{	0	,	0x002d	,	0x005f	,	-1	,	-1	,	-1	}	,
+		/*	0d	*/	{	0	,	0x003d	,	0x002b	,	-1	,	-1	,	-1	}	,
+		/*	0e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	0f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		
+		
+		/*	10	*/	{	1	,	(int)'q'	,	(int)'Q'	,	-1	,	-1	,	-1	}	,
+		/*	11	*/	{	1	,	(int)'w'	,	(int)'W'	,	-1	,	-1	,	-1	}	,
+		/*	12	*/	{	1	,	(int)'e'	,	(int)'E'	,	-1	,	-1	,	-1	}	,
+		/*	13	*/	{	1	,	(int)'r'	,	(int)'R'	,	-1	,	-1	,	-1	}	,
+		/*	14	*/	{	1	,	(int)'t'	,	(int)'T'	,	-1	,	-1	,	-1	}	,
+		/*	15	*/	{	1	,	(int)'y'	,	(int)'Y'	,	-1	,	-1	,	-1	}	,
+		/*	16	*/	{	1	,	(int)'u'	,	(int)'U'	,	-1	,	-1	,	-1	}	,
+		/*	17	*/	{	1	,	(int)'i'	,	(int)'I'	,	-1	,	-1	,	-1	}	,
+		/*	18	*/	{	1	,	(int)'o'	,	(int)'O'	,	-1	,	-1	,	-1	}	,
+		/*	19	*/	{	1	,	(int)'p'	,	(int)'P'	,	-1	,	-1	,	-1	}	,
+		/*	1a	*/	{	0	,	0x005b	,	0x007b	,	0x001b	,	-1	,	-1	}	,
+		/*	1b	*/	{	0	,	0x005d	,	0x007d	,	0x001d	,	-1	,	-1	}	,
+		/*	1c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	1d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	1e	*/	{	1	,	(int)'a'	,	(int)'A'	,	-1	,	-1	,	-1	}	,
+		/*	1f	*/	{	1	,	(int)'s'	,	(int)'S' ,	-1	,	-1	,	-1	}	,
+		
+		
+		/*	20	*/	{	1	,	(int)'d'	,	(int)'D'	,	-1	,	-1	,	-1	}	,
+		/*	21	*/	{	1	,	(int)'f'	,	(int)'F'	,	-1	,	-1	,	-1	}	,
+		/*	22	*/	{	1	,	(int)'g'	,	(int)'G'	,	-1	,	-1	,	-1	}	,
+		/*	23	*/	{	1	,	(int)'h'	,	(int)'H'	,	-1	,	-1	,	-1	}	,
+		/*	24	*/	{	1	,	(int)'j'	,	(int)'J'	,	-1	,	-1	,	-1	}	,
+		/*	25	*/	{	1	,	(int)'k'	,	(int)'K'	,	-1	,	-1	,	-1	}	,
+		/*	26	*/	{	1	,	(int)'l'	,	(int)'L'	,	-1	,	-1	,	-1	}	,
+		/*	27	*/	{	0	,	0x003b	,	0x003a	,	-1	,	-1	,	-1	}	,
+		/*	28	*/	{	0	,	0x27	,	0x22	,	-1	,	-1	,	-1	}	,
+		/*	29	*/	{	0	,	0x60	,	0x007e	,	-1	,	-1	,	-1	}	,
+		/*	2a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	2b	*/	{	0	,	0x005c	,	0x007c	,	0x001c	,	-1	,	-1	}	,
+		/*	2c	*/	{	1	,	(int)'z'	,	(int)'Z'	,	-1	,	-1	,	-1	}	,
+		/*	2d	*/	{	1	,	(int)'x'	,	(int)'X'	,	-1	,	-1	,	-1	}	,
+		/*	2e	*/	{	1	,	(int)'c'	,	(int)'C'	,	-1	,	-1	,	-1	}	,
+		/*	2f	*/	{	1	,	(int)'v'	,	(int)'V'	,	-1	,	-1	,	-1	}	,
+		
+		
+		/*	30	*/	{	1	,	(int)'b'	,	(int)'B'	,	-1	,	-1	,	-1	}	,
+		/*	31	*/	{	1	,	(int)'n'	,	(int)'N'	,	-1	,	-1	,	-1	}	,
+		/*	32	*/	{	1	,	(int)'m'	,	(int)'M'	,	-1	,	-1	,	-1	}	,
+		/*	33	*/	{	0	,	0x002c	,	0x003c	,	-1	,	-1	,	-1	}	,
+		/*	34	*/	{	0	,	0x002e	,	0x003e	,	-1	,	-1	,	-1	}	,
+		/*	35	*/	{	0	,	0x002f	,	0x003f	,	-1	,	-1	,	-1	}	,
+		/*	36	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	37	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	38	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,		
+		/*	39	*/	{	0	,	0x20	,	0x20	,	0x20	,	-1	,	-1	}	,
+		/*	3a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	3f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		
+		
+		/*	40	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	41	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	42	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	43	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	44	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	45	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	46	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	47	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+		/*	48	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	49	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	4f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,		
+		
+		
+		/*	50	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	51	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+		/*	52	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,		
+		/*	53	*/	{	0	,	0x002e	,	0x002e	,	-1	,	-1	,	-1	}	,
+		/*	54	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	55	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,		
+		/*	56	*/	{	0	,	0x005c	,	0x007c	,	0x001c	,	-1	,	-1	}	,
+		/*	57	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,	
+		/*	58	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	59	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5a	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5b	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5c	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5d	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5e	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,
+		/*	5f	*/	{	-1	,	0			,	0		,	0	,	0	,	0	}	,			
+		
+	};
+	
+	private static UnitedStatesLayout instance = new UnitedStatesLayout();
+	
+	private UnitedStatesLayout() {
+	}
+	
+	public static UnitedStatesLayout getInstance() {
+		return instance;
+	}	
+
+	@Override
+	public int[][] getLUT() {
+		return LUT;
+	}
+
+	@Override
+	public void type(String text) {
+		super.type(LUT, text);
+	}	
+	
+	@Override
+	public char getChar(int scanCode, boolean capsLock, boolean shift, boolean altGr) {
+		return super.getChar(LUT, scanCode, capsLock, shift, altGr);
+	}	
+	
+	@Override
+	public String getLocaleName() {		
+		return LOCALE_NAME;
+	}		
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/init/BasicInitManager.java b/src/java/InputStickAPI/src/com/inputstick/init/BasicInitManager.java
new file mode 100644
index 00000000..413da8e2
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/init/BasicInitManager.java
@@ -0,0 +1,61 @@
+package com.inputstick.init;
+
+import com.inputstick.api.Packet;
+
+
+public class BasicInitManager extends InitManager {
+	
+	private boolean initDone = false;	
+	
+	public BasicInitManager(byte[] key) {
+		super(key);
+	}
+	
+
+	@Override
+	public void onConnected() {		
+		/*Packet p = new Packet(false, Packet.RAW_OLD_BOOTLOADER); //compatibility
+		sendPacket(p);*/
+		
+		sendPacket(new Packet(true, Packet.CMD_RUN_FW));			
+	}
+	
+
+	@Override
+	public void onData(byte[] data) {
+		byte cmd = data[0];
+		byte respCode = data[1];
+		byte param = data[1];
+		
+		if (cmd == Packet.CMD_RUN_FW) {
+			sendPacket(new Packet(true, Packet.CMD_GET_INFO));
+		}
+		
+		if (cmd == Packet.CMD_GET_INFO) {
+			//store info
+			sendPacket(new Packet(true, Packet.CMD_INIT)); //TODO params!	
+		}
+		
+		if (cmd == Packet.CMD_INIT) {
+			if (respCode == Packet.RESP_OK) {						
+				initDone = true;
+				sendPacket(new Packet(false, Packet.CMD_HID_STATUS_REPORT));
+			} else {
+				mListener.onInitFailure(respCode);
+			}
+		}
+		
+		if (cmd == Packet.CMD_HID_STATUS) {
+			if (initDone) {
+				if (param == 0x05) {
+					mListener.onInitReady();
+				} else {
+					mListener.onInitNotReady();
+				}
+			}
+		}
+	}
+
+	
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/init/BootloaderInitManager.java b/src/java/InputStickAPI/src/com/inputstick/init/BootloaderInitManager.java
new file mode 100644
index 00000000..ea49b56d
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/init/BootloaderInitManager.java
@@ -0,0 +1,28 @@
+package com.inputstick.init;
+
+import com.inputstick.api.Packet;
+
+public class BootloaderInitManager extends InitManager {
+
+	public BootloaderInitManager(byte[] key) {
+		super(key);
+	}
+	
+	@Override
+	public void onConnected() {
+		//TODO key
+		sendPacket(new Packet(true, Packet.CMD_RUN_BL));			
+	}
+
+	@Override
+	public void onData(byte[] data) {
+		byte cmd = data[0];
+		//byte respCode = data[1];
+		//byte param = data[1];
+		
+		if (cmd == Packet.CMD_RUN_BL) {
+			mListener.onInitReady();
+		}
+	}
+
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/init/InitManager.java b/src/java/InputStickAPI/src/com/inputstick/init/InitManager.java
new file mode 100644
index 00000000..7d8907ab
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/init/InitManager.java
@@ -0,0 +1,33 @@
+package com.inputstick.init;
+
+import com.inputstick.api.Packet;
+import com.inputstick.api.PacketManager;
+
+public class InitManager {
+	
+	protected PacketManager mPacketManager;
+	protected InitManagerListener mListener;	
+	protected byte[] mKey;
+	
+	public InitManager(byte[] key) {
+		mKey = key;
+	}
+	
+	public void init(InitManagerListener listener, PacketManager packetManager) {
+		mListener = listener;
+		mPacketManager = packetManager;
+	}	
+	
+	public void onConnected() {
+		mListener.onInitReady();
+	}
+		
+	public void onData(byte[] data) {
+		
+	}
+	
+	public void sendPacket(Packet p) {
+		mPacketManager.sendPacket(p);
+	}
+	
+}
diff --git a/src/java/InputStickAPI/src/com/inputstick/init/InitManagerListener.java b/src/java/InputStickAPI/src/com/inputstick/init/InitManagerListener.java
new file mode 100644
index 00000000..fee3c21a
--- /dev/null
+++ b/src/java/InputStickAPI/src/com/inputstick/init/InitManagerListener.java
@@ -0,0 +1,9 @@
+package com.inputstick.init;
+
+public interface InitManagerListener {
+	
+	public void onInitReady();
+	public void onInitNotReady();
+	public void onInitFailure(int code);
+
+}
diff --git a/src/java/PluginA/.classpath b/src/java/PluginA/.classpath
new file mode 100644
index 00000000..51769745
--- /dev/null
+++ b/src/java/PluginA/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/src/java/PluginA/.project b/src/java/PluginA/.project
new file mode 100644
index 00000000..ad6a7b57
--- /dev/null
+++ b/src/java/PluginA/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>PluginA</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/src/java/PluginA/.settings/org.eclipse.jdt.core.prefs b/src/java/PluginA/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..b080d2dd
--- /dev/null
+++ b/src/java/PluginA/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/src/java/PluginA/AndroidManifest.xml b/src/java/PluginA/AndroidManifest.xml
new file mode 100644
index 00000000..b035a6b2
--- /dev/null
+++ b/src/java/PluginA/AndroidManifest.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="keepass2android.plugina"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="19" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="keepass2android.plugina.PlugInA"
+            android:label="@string/app_name" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        
+        <receiver android:name="PluginAAccessReceiver" android:exported="true">
+            <intent-filter>
+                <action android:name="keepass2android.ACTION_TRIGGER_REQUEST_ACCESS" />
+                <action android:name="keepass2android.ACTION_RECEIVE_ACCESS" />
+                <action android:name="keepass2android.ACTION_REVOKE_ACCESS" />
+                
+            </intent-filter>
+        </receiver>
+        
+        <receiver android:name="PluginAActionReceiver" android:exported="true">
+            <intent-filter>
+                <action android:name="keepass2android.ACTION_OPEN_ENTRY" />
+                <action android:name="keepass2android.ACTION_CLOSE_ENTRY_VIEW" />
+                <action android:name="keepass2android.ACTION_ENTRY_ACTION_SELECTED" />
+                
+                <action android:name="keepass2android.ACTION_LOCK_DATABASE" />
+                <action android:name="keepass2android.ACTION_UNLOCK_DATABASE" />
+                <action android:name="keepass2android.ACTION_CLOSE_DATABASE" />
+                <action android:name="keepass2android.ACTION_OPEN_DATABASE" />
+            </intent-filter>
+        </receiver>
+        
+            </application>
+
+</manifest>
diff --git a/src/java/PluginA/gen/keepass2android/plugina/BuildConfig.java b/src/java/PluginA/gen/keepass2android/plugina/BuildConfig.java
new file mode 100644
index 00000000..ce8a915a
--- /dev/null
+++ b/src/java/PluginA/gen/keepass2android/plugina/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package keepass2android.plugina;
+
+public final class BuildConfig {
+    public final static boolean DEBUG = true;
+}
\ No newline at end of file
diff --git a/src/java/PluginA/gen/keepass2android/plugina/R.java b/src/java/PluginA/gen/keepass2android/plugina/R.java
new file mode 100644
index 00000000..464b88df
--- /dev/null
+++ b/src/java/PluginA/gen/keepass2android/plugina/R.java
@@ -0,0 +1,91 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+
+package keepass2android.plugina;
+
+public final class R {
+    public static final class attr {
+    }
+    public static final class dimen {
+        /**  Default screen margins, per the Android Design guidelines. 
+
+         Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+    
+ Default screen margins, per the Android Design guidelines. 
+
+         Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+    
+         */
+        public static final int activity_horizontal_margin=0x7f040000;
+        public static final int activity_vertical_margin=0x7f040001;
+    }
+    public static final class drawable {
+        public static final int ic_launcher=0x7f020000;
+    }
+    public static final class id {
+        public static final int action_settings=0x7f080001;
+        public static final int container=0x7f080000;
+    }
+    public static final class layout {
+        public static final int activity_plug_in=0x7f030000;
+        public static final int fragment_plug_in=0x7f030001;
+    }
+    public static final class menu {
+        public static final int plug_in=0x7f070000;
+    }
+    public static final class string {
+        public static final int action_settings=0x7f050002;
+        public static final int app_name=0x7f050000;
+        public static final int hello_world=0x7f050001;
+        public static final int kp2aplugin_author=0x7f050005;
+        public static final int kp2aplugin_shortdesc=0x7f050004;
+        public static final int kp2aplugin_title=0x7f050003;
+    }
+    public static final class style {
+        /** 
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    
+
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        
+
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    
+ API 11 theme customizations can go here. 
+
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    
+ API 14 theme customizations can go here. 
+
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    
+
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        
+         */
+        public static final int AppBaseTheme=0x7f060000;
+        /**  Application theme. 
+ All customizations that are NOT specific to a particular API-level can go here. 
+ Application theme. 
+ All customizations that are NOT specific to a particular API-level can go here. 
+         */
+        public static final int AppTheme=0x7f060001;
+    }
+}
diff --git a/src/java/PluginA/gen/keepass2android/pluginsdk/R.java b/src/java/PluginA/gen/keepass2android/pluginsdk/R.java
new file mode 100644
index 00000000..446843e7
--- /dev/null
+++ b/src/java/PluginA/gen/keepass2android/pluginsdk/R.java
@@ -0,0 +1,24 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+package keepass2android.pluginsdk;
+
+public final class R {
+	public static final class dimen {
+		public static final int activity_horizontal_margin = 0x7f040000;
+		public static final int activity_vertical_margin = 0x7f040001;
+	}
+	public static final class drawable {
+		public static final int ic_launcher = 0x7f020000;
+	}
+	public static final class string {
+		public static final int app_name = 0x7f050000;
+	}
+	public static final class style {
+		public static final int AppBaseTheme = 0x7f060000;
+		public static final int AppTheme = 0x7f060001;
+	}
+}
diff --git a/src/java/PluginA/libs/android-support-v4.jar b/src/java/PluginA/libs/android-support-v4.jar
new file mode 100644
index 00000000..96644edb
Binary files /dev/null and b/src/java/PluginA/libs/android-support-v4.jar differ
diff --git a/src/java/PluginA/proguard-project.txt b/src/java/PluginA/proguard-project.txt
new file mode 100644
index 00000000..f2fe1559
--- /dev/null
+++ b/src/java/PluginA/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/src/java/PluginA/project.properties b/src/java/PluginA/project.properties
new file mode 100644
index 00000000..b983a093
--- /dev/null
+++ b/src/java/PluginA/project.properties
@@ -0,0 +1,15 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
+android.library.reference.1=../Keepass2AndroidPluginSDK
diff --git a/src/java/PluginA/res/drawable-xhdpi/ic_launcher.png b/src/java/PluginA/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..71c6d760
Binary files /dev/null and b/src/java/PluginA/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/src/java/PluginA/res/layout/activity_plug_in.xml b/src/java/PluginA/res/layout/activity_plug_in.xml
new file mode 100644
index 00000000..fe410d79
--- /dev/null
+++ b/src/java/PluginA/res/layout/activity_plug_in.xml
@@ -0,0 +1,8 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="keepass2android.plugina.PlugInA"
+    tools:ignore="MergeRootFrame" />
+
diff --git a/src/java/PluginA/res/layout/fragment_plug_in.xml b/src/java/PluginA/res/layout/fragment_plug_in.xml
new file mode 100644
index 00000000..24d1ed42
--- /dev/null
+++ b/src/java/PluginA/res/layout/fragment_plug_in.xml
@@ -0,0 +1,16 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context="keepass2android.plugina.PlugInA$PlaceholderFragment" >
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/hello_world" />
+
+</RelativeLayout>
diff --git a/src/java/PluginA/res/menu/plug_in.xml b/src/java/PluginA/res/menu/plug_in.xml
new file mode 100644
index 00000000..075e5c23
--- /dev/null
+++ b/src/java/PluginA/res/menu/plug_in.xml
@@ -0,0 +1,12 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:context="keepass2android.plugina.PlugInA" >
+
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:title="@string/action_settings"
+        android:showAsAction="never"/>
+
+</menu>
diff --git a/src/java/PluginA/res/values-w820dp/dimens.xml b/src/java/PluginA/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000..f3e70203
--- /dev/null
+++ b/src/java/PluginA/res/values-w820dp/dimens.xml
@@ -0,0 +1,10 @@
+<resources>
+
+    <!--
+         Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+    -->
+    <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
diff --git a/src/java/PluginA/res/values/dimens.xml b/src/java/PluginA/res/values/dimens.xml
new file mode 100644
index 00000000..55c1e590
--- /dev/null
+++ b/src/java/PluginA/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/src/java/PluginA/res/values/strings.xml b/src/java/PluginA/res/values/strings.xml
new file mode 100644
index 00000000..adc1ad3d
--- /dev/null
+++ b/src/java/PluginA/res/values/strings.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">PluginA</string>
+    <string name="hello_world">Hello world!</string>
+    <string name="action_settings">Settings</string>
+    <string name="kp2aplugin_title">The Great PluginA</string>
+    <string name="kp2aplugin_shortdesc">Test plugin to demonstrate how plugins work</string>
+    <string name="kp2aplugin_author">Philipp Crocoll</string>
+
+</resources>
diff --git a/src/java/PluginA/res/values/styles.xml b/src/java/PluginA/res/values/styles.xml
new file mode 100644
index 00000000..c0ebd3e9
--- /dev/null
+++ b/src/java/PluginA/res/values/styles.xml
@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
diff --git a/src/java/PluginA/src/keepass2android/plugina/EntryOpenedReceiver.java b/src/java/PluginA/src/keepass2android/plugina/EntryOpenedReceiver.java
new file mode 100644
index 00000000..aa191b2b
--- /dev/null
+++ b/src/java/PluginA/src/keepass2android/plugina/EntryOpenedReceiver.java
@@ -0,0 +1,20 @@
+package keepass2android.plugina;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+
+
+
+public class EntryOpenedReceiver extends BroadcastReceiver {
+	@Override
+	  public void onReceive(Context context, Intent intent) {
+	    Bundle extras = intent.getExtras();
+	    if (extras != null) {
+	      Log.w("PluginA", "received broadcast!");
+	      
+	    }
+	  }
+}
diff --git a/src/java/PluginA/src/keepass2android/plugina/PlugInA.java b/src/java/PluginA/src/keepass2android/plugina/PlugInA.java
new file mode 100644
index 00000000..63a68133
--- /dev/null
+++ b/src/java/PluginA/src/keepass2android/plugina/PlugInA.java
@@ -0,0 +1,62 @@
+package keepass2android.plugina;
+import android.app.Activity;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.os.Build;
+
+public class PlugInA extends Activity {
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_plug_in);
+
+		if (savedInstanceState == null) {
+			getFragmentManager().beginTransaction()
+					.add(R.id.container, new PlaceholderFragment()).commit();
+		}
+	}
+
+	@Override
+	public boolean onCreateOptionsMenu(Menu menu) {
+
+		// Inflate the menu; this adds items to the action bar if it is present.
+		getMenuInflater().inflate(R.menu.plug_in, menu);
+		return true;
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem item) {
+		// Handle action bar item clicks here. The action bar will
+		// automatically handle clicks on the Home/Up button, so long
+		// as you specify a parent activity in AndroidManifest.xml.
+		int id = item.getItemId();
+		if (id == R.id.action_settings) {
+			return true;
+		}
+		return super.onOptionsItemSelected(item);
+	}
+
+	/**
+	 * A placeholder fragment containing a simple view.
+	 */
+	public static class PlaceholderFragment extends Fragment {
+
+		public PlaceholderFragment() {
+		}
+
+		@Override
+		public View onCreateView(LayoutInflater inflater, ViewGroup container,
+				Bundle savedInstanceState) {
+			View rootView = inflater.inflate(R.layout.fragment_plug_in,
+					container, false);
+			return rootView;
+		}
+	}
+
+}
diff --git a/src/java/PluginA/src/keepass2android/plugina/PluginAAccessReceiver.java b/src/java/PluginA/src/keepass2android/plugina/PluginAAccessReceiver.java
new file mode 100644
index 00000000..4aa24be6
--- /dev/null
+++ b/src/java/PluginA/src/keepass2android/plugina/PluginAAccessReceiver.java
@@ -0,0 +1,20 @@
+package keepass2android.plugina;
+
+import java.util.ArrayList;
+
+import keepass2android.pluginsdk.Strings;
+
+public class PluginAAccessReceiver
+ extends keepass2android.pluginsdk.PluginAccessBroadcastReceiver
+{
+
+	@Override
+	public ArrayList<String> getScopes() {
+		ArrayList<String> scopes = new ArrayList<String>();
+		scopes.add(Strings.SCOPE_DATABASE_ACTIONS);
+		scopes.add(Strings.SCOPE_CURRENT_ENTRY);
+		return scopes;
+		
+	}
+
+}
diff --git a/src/java/PluginA/src/keepass2android/plugina/PluginAActionReceiver.java b/src/java/PluginA/src/keepass2android/plugina/PluginAActionReceiver.java
new file mode 100644
index 00000000..9b3b0ec4
--- /dev/null
+++ b/src/java/PluginA/src/keepass2android/plugina/PluginAActionReceiver.java
@@ -0,0 +1,56 @@
+package keepass2android.plugina;
+
+import keepass2android.pluginsdk.PluginAccessException;
+import keepass2android.pluginsdk.Strings;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.Toast;
+
+public class PluginAActionReceiver
+	extends keepass2android.pluginsdk.PluginActionBroadcastReceiver
+{
+
+	@Override
+	protected void actionSelected(ActionSelectedAction actionSelected) {
+		if (actionSelected.isEntryAction())
+		{
+			Toast.makeText(actionSelected.getContext(), "PluginA rocks!", Toast.LENGTH_SHORT).show();
+		}
+		else
+		{
+			String fieldId = actionSelected.getFieldId().substring(Strings.PREFIX_STRING.length());
+			//Toast.makeText(actionSelected.getContext(), actionSelected.getActionData().getString("text"), Toast.LENGTH_SHORT).show();
+			Toast.makeText(actionSelected.getContext(), actionSelected.getEntryFields().get(fieldId), Toast.LENGTH_SHORT).show();
+		}
+		
+	}
+
+	@Override
+	protected void openEntry(OpenEntryAction oe) {
+		
+		try {
+			
+			Bundle bField = new Bundle();
+			bField.putString("text", oe.getEntryFields().get("Password"));
+			oe.addEntryFieldAction("keepass2android.plugina.bla", Strings.PREFIX_STRING+"Password", "PluginA says hello", R.drawable.ic_launcher, bField);
+			oe.addEntryFieldAction("keepass2android.plugina.bla",Strings.PREFIX_STRING+"UserName", "Be nice!", R.drawable.ic_launcher, null);
+			
+			Bundle bEntry = new Bundle();
+			oe.addEntryAction("PluginA", R.drawable.ic_launcher, bEntry);
+			
+			oe.setEntryField("newFieldFromPluginA", "I love pluginA", false);
+			oe.setEntryField("SecretFieldFromPluginA", "I love pluginA uiadertn", true);
+			oe.setEntryField("UserName", "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 	Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 	Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. 	Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. 	Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. 	At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. 	Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. 	Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. 	Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. 	Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ", true);
+			
+		} catch (PluginAccessException e) {
+			e.printStackTrace();
+		}
+
+	}
+
+	@Override
+	protected void dbAction(DatabaseAction db) {
+		
+		Log.d("PluginA", db.getAction() + " in file " + db.getFileDisplayName() + " ("+db.getFilePath()+")");
+	}
+}
diff --git a/src/java/PluginInputStick/.classpath b/src/java/PluginInputStick/.classpath
new file mode 100644
index 00000000..7bc01d9a
--- /dev/null
+++ b/src/java/PluginInputStick/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
diff --git a/src/java/PluginInputStick/.project b/src/java/PluginInputStick/.project
new file mode 100644
index 00000000..cca1dea2
--- /dev/null
+++ b/src/java/PluginInputStick/.project
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>PluginInputStick</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
diff --git a/src/java/PluginInputStick/.settings/org.eclipse.jdt.core.prefs b/src/java/PluginInputStick/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 00000000..b080d2dd
--- /dev/null
+++ b/src/java/PluginInputStick/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,4 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.source=1.6
diff --git a/src/java/PluginInputStick/AndroidManifest.xml b/src/java/PluginInputStick/AndroidManifest.xml
new file mode 100644
index 00000000..a1f67439
--- /dev/null
+++ b/src/java/PluginInputStick/AndroidManifest.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="keepass2android.plugin.inputstick"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="14"
+        android:targetSdkVersion="19" />
+
+    <application
+        android:allowBackup="true"
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@style/AppTheme" >
+        <activity
+            android:name="keepass2android.plugin.inputstick.MainActivity"
+            android:label="@string/app_name" >
+            
+        </activity>
+
+        <receiver
+            android:name="keepass2android.plugin.inputstick.AccessReceiver"
+            android:exported="true" >
+            <intent-filter>
+                <action android:name="keepass2android.ACTION_TRIGGER_REQUEST_ACCESS" />
+                <action android:name="keepass2android.ACTION_RECEIVE_ACCESS" />
+                <action android:name="keepass2android.ACTION_REVOKE_ACCESS" />
+            </intent-filter>
+        </receiver>
+        <receiver
+            android:name="keepass2android.plugin.inputstick.ActionReceiver"
+            android:exported="true" >
+            <intent-filter>
+                <action android:name="keepass2android.ACTION_OPEN_ENTRY" />
+                <action android:name="keepass2android.ACTION_ENTRY_OUTPUT_MODIFIED" />
+                <action android:name="keepass2android.ACTION_ENTRY_ACTION_SELECTED" />
+                <action android:name="keepass2android.ACTION_CLOSE_ENTRY_VIEW" />
+            </intent-filter>
+        </receiver>
+
+        <service
+            android:name="keepass2android.plugin.inputstick.InputStickService"
+            android:enabled="true" >
+        </service>
+
+        <activity
+            android:name="keepass2android.plugin.inputstick.SettingsActivity"
+            android:label="@string/title_activity_settings" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
diff --git a/src/java/PluginInputStick/gen/com/inputstick/api/R.java b/src/java/PluginInputStick/gen/com/inputstick/api/R.java
new file mode 100644
index 00000000..f6c5a1d2
--- /dev/null
+++ b/src/java/PluginInputStick/gen/com/inputstick/api/R.java
@@ -0,0 +1,20 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+package com.inputstick.api;
+
+public final class R {
+	public static final class drawable {
+		public static final int ic_launcher = 0x7f020000;
+	}
+	public static final class string {
+		public static final int app_name = 0x7f060000;
+	}
+	public static final class style {
+		public static final int AppBaseTheme = 0x7f070000;
+		public static final int AppTheme = 0x7f070001;
+	}
+}
diff --git a/src/java/PluginInputStick/gen/keepass2android/plugin/inputstick/BuildConfig.java b/src/java/PluginInputStick/gen/keepass2android/plugin/inputstick/BuildConfig.java
new file mode 100644
index 00000000..0c6ce6d6
--- /dev/null
+++ b/src/java/PluginInputStick/gen/keepass2android/plugin/inputstick/BuildConfig.java
@@ -0,0 +1,6 @@
+/** Automatically generated file. DO NOT MODIFY */
+package keepass2android.plugin.inputstick;
+
+public final class BuildConfig {
+    public final static boolean DEBUG = true;
+}
\ No newline at end of file
diff --git a/src/java/PluginInputStick/gen/keepass2android/plugin/inputstick/R.java b/src/java/PluginInputStick/gen/keepass2android/plugin/inputstick/R.java
new file mode 100644
index 00000000..c085b820
--- /dev/null
+++ b/src/java/PluginInputStick/gen/keepass2android/plugin/inputstick/R.java
@@ -0,0 +1,141 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+
+package keepass2android.plugin.inputstick;
+
+public final class R {
+    public static final class array {
+        public static final int layout_names=0x7f080000;
+        public static final int layout_values=0x7f080001;
+    }
+    public static final class attr {
+    }
+    public static final class dimen {
+        /**  Default screen margins, per the Android Design guidelines. 
+
+         Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+    
+ Default screen margins, per the Android Design guidelines. 
+
+         Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+    
+         */
+        public static final int activity_horizontal_margin=0x7f050000;
+        public static final int activity_vertical_margin=0x7f050001;
+    }
+    public static final class drawable {
+        public static final int ic_launcher=0x7f020000;
+        public static final int ic_notification=0x7f020001;
+    }
+    public static final class id {
+        public static final int action_settings=0x7f0a0003;
+        public static final int button1=0x7f0a0001;
+        public static final int button2=0x7f0a0002;
+        public static final int container=0x7f0a0000;
+    }
+    public static final class layout {
+        public static final int activity_main=0x7f030000;
+        public static final int fragment_main=0x7f030001;
+    }
+    public static final class menu {
+        public static final int main=0x7f090000;
+    }
+    public static final class string {
+        public static final int action_input_stick=0x7f060005;
+        public static final int action_settings=0x7f060001;
+        public static final int action_type_enter=0x7f060007;
+        public static final int action_type_tab=0x7f060006;
+        public static final int app_name=0x7f060000;
+        /**  Strings related to Settings 
+         */
+        public static final int configure_plugin=0x7f060009;
+        public static final int kp2aplugin_author=0x7f060004;
+        public static final int kp2aplugin_shortdesc=0x7f060003;
+        public static final int kp2aplugin_title=0x7f060002;
+        public static final int layout_title=0x7f06000a;
+        public static final int title_activity_settings=0x7f060008;
+    }
+    public static final class style {
+        /** 
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    
+
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        
+
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    
+ API 11 theme customizations can go here. 
+
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    
+ API 14 theme customizations can go here. 
+
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    
+
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        
+
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    
+ API 11 theme customizations can go here. 
+
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    
+ API 14 theme customizations can go here. 
+
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    
+
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        
+
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    
+ API 11 theme customizations can go here. 
+
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    
+ API 14 theme customizations can go here. 
+         */
+        public static final int AppBaseTheme=0x7f070000;
+        /**  Application theme. 
+ All customizations that are NOT specific to a particular API-level can go here. 
+ Application theme. 
+ All customizations that are NOT specific to a particular API-level can go here. 
+ Application theme. 
+ All customizations that are NOT specific to a particular API-level can go here. 
+         */
+        public static final int AppTheme=0x7f070001;
+    }
+    public static final class xml {
+        public static final int pref_general=0x7f040000;
+    }
+}
diff --git a/src/java/PluginInputStick/gen/keepass2android/pluginsdk/R.java b/src/java/PluginInputStick/gen/keepass2android/pluginsdk/R.java
new file mode 100644
index 00000000..71bb12b1
--- /dev/null
+++ b/src/java/PluginInputStick/gen/keepass2android/pluginsdk/R.java
@@ -0,0 +1,24 @@
+/* AUTO-GENERATED FILE.  DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found.  It
+ * should not be modified by hand.
+ */
+package keepass2android.pluginsdk;
+
+public final class R {
+	public static final class dimen {
+		public static final int activity_horizontal_margin = 0x7f050000;
+		public static final int activity_vertical_margin = 0x7f050001;
+	}
+	public static final class drawable {
+		public static final int ic_launcher = 0x7f020000;
+	}
+	public static final class string {
+		public static final int app_name = 0x7f060000;
+	}
+	public static final class style {
+		public static final int AppBaseTheme = 0x7f070000;
+		public static final int AppTheme = 0x7f070001;
+	}
+}
diff --git a/src/java/PluginInputStick/ic_launcher-web.png b/src/java/PluginInputStick/ic_launcher-web.png
new file mode 100644
index 00000000..69fadd12
Binary files /dev/null and b/src/java/PluginInputStick/ic_launcher-web.png differ
diff --git a/src/java/PluginInputStick/proguard-project.txt b/src/java/PluginInputStick/proguard-project.txt
new file mode 100644
index 00000000..f2fe1559
--- /dev/null
+++ b/src/java/PluginInputStick/proguard-project.txt
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
diff --git a/src/java/PluginInputStick/project.properties b/src/java/PluginInputStick/project.properties
new file mode 100644
index 00000000..0206c251
--- /dev/null
+++ b/src/java/PluginInputStick/project.properties
@@ -0,0 +1,16 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
+android.library.reference.1=../InputStickAPI
+android.library.reference.2=../Keepass2AndroidPluginSDK
diff --git a/src/java/PluginInputStick/res/drawable-hdpi/ic_launcher.png b/src/java/PluginInputStick/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..8ad4ab43
Binary files /dev/null and b/src/java/PluginInputStick/res/drawable-hdpi/ic_launcher.png differ
diff --git a/src/java/PluginInputStick/res/drawable-hdpi/ic_notification.png b/src/java/PluginInputStick/res/drawable-hdpi/ic_notification.png
new file mode 100644
index 00000000..de6935b9
Binary files /dev/null and b/src/java/PluginInputStick/res/drawable-hdpi/ic_notification.png differ
diff --git a/src/java/PluginInputStick/res/drawable-mdpi/ic_launcher.png b/src/java/PluginInputStick/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..18a3f3fc
Binary files /dev/null and b/src/java/PluginInputStick/res/drawable-mdpi/ic_launcher.png differ
diff --git a/src/java/PluginInputStick/res/drawable-mdpi/ic_notification.png b/src/java/PluginInputStick/res/drawable-mdpi/ic_notification.png
new file mode 100644
index 00000000..2248b578
Binary files /dev/null and b/src/java/PluginInputStick/res/drawable-mdpi/ic_notification.png differ
diff --git a/src/java/PluginInputStick/res/drawable-xhdpi/ic_launcher.png b/src/java/PluginInputStick/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..f113b28e
Binary files /dev/null and b/src/java/PluginInputStick/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/src/java/PluginInputStick/res/drawable-xhdpi/ic_notification.png b/src/java/PluginInputStick/res/drawable-xhdpi/ic_notification.png
new file mode 100644
index 00000000..b8b47268
Binary files /dev/null and b/src/java/PluginInputStick/res/drawable-xhdpi/ic_notification.png differ
diff --git a/src/java/PluginInputStick/res/drawable-xxhdpi/ic_launcher.png b/src/java/PluginInputStick/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..dff13e63
Binary files /dev/null and b/src/java/PluginInputStick/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/src/java/PluginInputStick/res/drawable-xxhdpi/ic_notification.png b/src/java/PluginInputStick/res/drawable-xxhdpi/ic_notification.png
new file mode 100644
index 00000000..f609343a
Binary files /dev/null and b/src/java/PluginInputStick/res/drawable-xxhdpi/ic_notification.png differ
diff --git a/src/java/PluginInputStick/res/layout/activity_main.xml b/src/java/PluginInputStick/res/layout/activity_main.xml
new file mode 100644
index 00000000..2b60afd4
--- /dev/null
+++ b/src/java/PluginInputStick/res/layout/activity_main.xml
@@ -0,0 +1,12 @@
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="keepass2android.plugin.inputstick.MainActivity"
+    tools:ignore="MergeRootFrame" >
+
+    
+
+</FrameLayout>
+
diff --git a/src/java/PluginInputStick/res/layout/fragment_main.xml b/src/java/PluginInputStick/res/layout/fragment_main.xml
new file mode 100644
index 00000000..9714c703
--- /dev/null
+++ b/src/java/PluginInputStick/res/layout/fragment_main.xml
@@ -0,0 +1,29 @@
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingBottom="@dimen/activity_vertical_margin"
+    android:paddingLeft="@dimen/activity_horizontal_margin"
+    android:paddingRight="@dimen/activity_horizontal_margin"
+    android:paddingTop="@dimen/activity_vertical_margin"
+    tools:context="keepass2android.plugin.inputstick.MainActivity$PlaceholderFragment" >
+
+
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical" >
+        <Button
+        android:id="@+id/button1"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Button 1" />
+
+    <Button
+        android:id="@+id/button2"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="Button 2" />
+    </LinearLayout>
+</RelativeLayout>
diff --git a/src/java/PluginInputStick/res/menu/main.xml b/src/java/PluginInputStick/res/menu/main.xml
new file mode 100644
index 00000000..c329677e
--- /dev/null
+++ b/src/java/PluginInputStick/res/menu/main.xml
@@ -0,0 +1,11 @@
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:context="keepass2android.plugin.inputstick.MainActivity" >
+
+    <item
+        android:id="@+id/action_settings"
+        android:orderInCategory="100"
+        android:showAsAction="never"
+        android:title="@string/action_settings"/>
+
+</menu>
diff --git a/src/java/PluginInputStick/res/values-v11/styles.xml b/src/java/PluginInputStick/res/values-v11/styles.xml
new file mode 100644
index 00000000..3c02242a
--- /dev/null
+++ b/src/java/PluginInputStick/res/values-v11/styles.xml
@@ -0,0 +1,11 @@
+<resources>
+
+    <!--
+        Base application theme for API 11+. This theme completely replaces
+        AppBaseTheme from res/values/styles.xml on API 11+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+        <!-- API 11 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/src/java/PluginInputStick/res/values-v14/styles.xml b/src/java/PluginInputStick/res/values-v14/styles.xml
new file mode 100644
index 00000000..a91fd037
--- /dev/null
+++ b/src/java/PluginInputStick/res/values-v14/styles.xml
@@ -0,0 +1,12 @@
+<resources>
+
+    <!--
+        Base application theme for API 14+. This theme completely replaces
+        AppBaseTheme from BOTH res/values/styles.xml and
+        res/values-v11/styles.xml on API 14+ devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+        <!-- API 14 theme customizations can go here. -->
+    </style>
+
+</resources>
diff --git a/src/java/PluginInputStick/res/values-w820dp/dimens.xml b/src/java/PluginInputStick/res/values-w820dp/dimens.xml
new file mode 100644
index 00000000..f3e70203
--- /dev/null
+++ b/src/java/PluginInputStick/res/values-w820dp/dimens.xml
@@ -0,0 +1,10 @@
+<resources>
+
+    <!--
+         Example customization of dimensions originally defined in res/values/dimens.xml
+         (such as screen margins) for screens with more than 820dp of available width. This
+         would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+    -->
+    <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
diff --git a/src/java/PluginInputStick/res/values/dimens.xml b/src/java/PluginInputStick/res/values/dimens.xml
new file mode 100644
index 00000000..55c1e590
--- /dev/null
+++ b/src/java/PluginInputStick/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<resources>
+
+    <!-- Default screen margins, per the Android Design guidelines. -->
+    <dimen name="activity_horizontal_margin">16dp</dimen>
+    <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
diff --git a/src/java/PluginInputStick/res/values/strings.xml b/src/java/PluginInputStick/res/values/strings.xml
new file mode 100644
index 00000000..ba6f2769
--- /dev/null
+++ b/src/java/PluginInputStick/res/values/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+    <string name="app_name">InputStick Plugin for KP2A</string>
+    
+    <string name="action_settings">Settings</string>
+    
+    <string name="kp2aplugin_title">InputStick Plugin</string>
+    <string name="kp2aplugin_shortdesc">Allows to send text from KP2A via InputStick to your PC.</string>
+    <string name="kp2aplugin_author">Philipp Crocoll</string>
+    
+    <string name="action_input_stick">Type with InputStick</string>
+    <string name="action_type_tab">Type Tab with InputStick</string>
+    <string name="action_type_enter">Type Enter with InputStick</string>
+
+</resources>
diff --git a/src/java/PluginInputStick/res/values/strings_activity_settings.xml b/src/java/PluginInputStick/res/values/strings_activity_settings.xml
new file mode 100644
index 00000000..d3adfd6e
--- /dev/null
+++ b/src/java/PluginInputStick/res/values/strings_activity_settings.xml
@@ -0,0 +1,24 @@
+<resources>
+
+    <string name="title_activity_settings">KP2A InputStick Settings</string>
+
+    <!-- Strings related to Settings -->
+    <string name="configure_plugin">Configure as plugin</string>
+
+    <string name="layout_title">Host keyboard layout</string>
+    
+    <string-array name="layout_names">
+        <item>English (United States) - en-US</item>
+        <item>German - de-DE</item>
+        <item>Polish - pl-PL</item>
+        <item>Russian - ru-RU</item>
+    </string-array>
+    
+    <string-array name="layout_values">
+        <item>en-US</item>
+        <item>de-DE</item>
+        <item>pl-PL</item>
+        <item>ru-RU</item>
+    </string-array>
+
+</resources>
diff --git a/src/java/PluginInputStick/res/values/styles.xml b/src/java/PluginInputStick/res/values/styles.xml
new file mode 100644
index 00000000..6ce89c7b
--- /dev/null
+++ b/src/java/PluginInputStick/res/values/styles.xml
@@ -0,0 +1,20 @@
+<resources>
+
+    <!--
+        Base application theme, dependent on API level. This theme is replaced
+        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+    -->
+    <style name="AppBaseTheme" parent="android:Theme.Light">
+        <!--
+            Theme customizations available in newer API levels can go in
+            res/values-vXX/styles.xml, while customizations related to
+            backward-compatibility can go here.
+        -->
+    </style>
+
+    <!-- Application theme. -->
+    <style name="AppTheme" parent="AppBaseTheme">
+        <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+    </style>
+
+</resources>
diff --git a/src/java/PluginInputStick/res/xml/pref_general.xml b/src/java/PluginInputStick/res/xml/pref_general.xml
new file mode 100644
index 00000000..dfcb83c3
--- /dev/null
+++ b/src/java/PluginInputStick/res/xml/pref_general.xml
@@ -0,0 +1,24 @@
+<PreferenceScreen
+    android:key="general_pref"
+     xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <Preference
+        android:key="enable_plugin_pref"
+        android:title="@string/configure_plugin" />
+
+
+    <!--
+         NOTE: Hide buttons to simplify the UI. Users can touch outside the dialog to
+         dismiss it.
+    -->
+    <!-- NOTE: ListPreference's summary should be set to its value by the activity code. -->
+    <ListPreference
+        android:defaultValue="en-US"
+        android:entries="@array/layout_names"
+        android:entryValues="@array/layout_values"
+        android:key="kbd_layout"
+        android:negativeButtonText="@null"
+        android:positiveButtonText="@null"
+        android:title="@string/layout_title" />
+
+</PreferenceScreen>
diff --git a/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/AccessReceiver.java b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/AccessReceiver.java
new file mode 100644
index 00000000..831804cf
--- /dev/null
+++ b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/AccessReceiver.java
@@ -0,0 +1,16 @@
+package keepass2android.plugin.inputstick;
+
+import java.util.ArrayList;
+
+import keepass2android.pluginsdk.Strings;
+
+public class AccessReceiver extends keepass2android.pluginsdk.PluginAccessBroadcastReceiver {
+
+	@Override
+	public ArrayList<String> getScopes() {
+		ArrayList<String> scopes = new ArrayList<String>();
+		scopes.add(Strings.SCOPE_CURRENT_ENTRY);
+		return scopes;
+	}
+
+}
diff --git a/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/ActionReceiver.java b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/ActionReceiver.java
new file mode 100644
index 00000000..87448890
--- /dev/null
+++ b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/ActionReceiver.java
@@ -0,0 +1,78 @@
+package keepass2android.plugin.inputstick;
+
+import keepass2android.pluginsdk.PluginAccessException;
+import keepass2android.pluginsdk.Strings;
+
+import org.json.JSONObject;
+
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class ActionReceiver extends keepass2android.pluginsdk.PluginActionBroadcastReceiver {
+	private static final String EXTRA_TEXT = "text";
+
+	@Override
+	protected void openEntry(OpenEntryAction oe) {
+		try {
+			for (String field: oe.getEntryFields().keySet())
+			{
+				oe.addEntryFieldAction("keepass2android.plugin.inputstick.type", Strings.PREFIX_STRING+field, oe.getContext().getString(R.string.action_input_stick),
+					R.drawable.ic_launcher, null);
+			}
+			Bundle b1 = new Bundle();
+			b1.putString(EXTRA_TEXT, "\t");
+			oe.addEntryAction(oe.getContext().getString(R.string.action_type_tab), R.drawable.ic_launcher, b1);
+			Bundle b2 = new Bundle();
+			b2.putString(EXTRA_TEXT, "\n");
+			oe.addEntryAction(oe.getContext().getString(R.string.action_type_enter), R.drawable.ic_launcher, b2);
+		} catch (PluginAccessException e) {
+			e.printStackTrace();
+		}
+		typeText(oe.getContext(), "");
+	}
+	
+	@Override 
+	protected void closeEntryView(CloseEntryViewAction closeEntryView) 
+	{
+		Intent serviceIntent = new Intent(closeEntryView.getContext(), InputStickService.class);
+		serviceIntent.setAction(InputStickService.DISCONNECT);
+		closeEntryView.getContext().startService(serviceIntent);
+		
+	};
+	
+	@Override
+	protected void actionSelected(ActionSelectedAction actionSelected) {
+		if (actionSelected.isEntryAction())
+		{
+			typeText(actionSelected.getContext(), actionSelected.getActionData().getString(EXTRA_TEXT));
+		}
+		else
+		{
+			String fieldKey =actionSelected.getFieldId().substring(Strings.PREFIX_STRING.length());
+			String text = actionSelected.getEntryFields().get(fieldKey);
+			typeText(actionSelected.getContext(), text);
+		}
+	}
+
+	
+	private void typeText(Context ctx, String text) {
+		Intent serviceIntent = new Intent(ctx, InputStickService.class);
+		serviceIntent.setAction(InputStickService.TYPE);
+	
+		serviceIntent.putExtra(Intent.EXTRA_TEXT, text);
+		ctx.startService(serviceIntent);
+		
+	}
+
+	@Override
+	protected void entryOutputModified(EntryOutputModifiedAction eom) {
+		try {
+			eom.addEntryFieldAction("keepass2android.plugin.inputstick.type", eom.getModifiedFieldId(), eom.getContext().getString(R.string.action_input_stick),
+					R.drawable.ic_launcher, null);
+		} catch (PluginAccessException e) {
+			e.printStackTrace();
+		}
+	}
+
+}
diff --git a/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/InputStickService.java b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/InputStickService.java
new file mode 100644
index 00000000..cf70a8c1
--- /dev/null
+++ b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/InputStickService.java
@@ -0,0 +1,225 @@
+package keepass2android.plugin.inputstick;
+
+import java.util.ArrayList;
+
+import com.inputstick.api.ConnectionManager;
+import com.inputstick.api.InputStickStateListener;
+import com.inputstick.api.basic.InputStickHID;
+import com.inputstick.api.basic.InputStickKeyboard;
+import com.inputstick.api.hid.HIDKeycodes;
+import com.inputstick.api.layout.KeyboardLayout;
+
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.AsyncTask;
+import android.os.IBinder;
+import android.preference.PreferenceManager;
+import android.support.v4.app.NotificationCompat.Builder;
+import android.util.Log;
+import android.widget.Toast;
+
+public class InputStickService extends Service implements InputStickStateListener {
+
+	private static final String _TAG = "KP2AINPUTSTICK";
+	public static final String DISCONNECT = "disconnect";
+	private static final int NOTIFICATION_ID = 1;
+	public static final String TYPE = "type";
+	private static final String TYPE_QUEUE = "type_queue";
+	
+	@Override
+	public void onCreate() {
+		InputStickHID.addStateListener(this);
+		super.onCreate();
+	}
+	private ArrayList<String> stringsToType = new ArrayList<String>(); 
+
+	@Override
+	public int onStartCommand(Intent intent, int flags, int startId) {
+		
+		if (intent != null)
+			Log.d(_TAG, "starting with "+intent.getAction());
+		else
+			Log.d(_TAG, "starting with null intent");
+
+		if (DISCONNECT.equals(intent.getAction()))
+		{
+			Log.d(_TAG, "disconnecting");
+			try
+			{
+				InputStickHID.disconnect();	
+			}
+			catch (NullPointerException e)
+			{
+				Log.d(_TAG, "couldn't disconnect. Probably we never connected.");
+			}
+			
+			stopSelf();
+			return Service.START_NOT_STICKY;
+		}
+		showNotification();
+		
+		if (TYPE_QUEUE.equals(intent.getAction()))
+		{
+			typeQueue();
+		}
+		
+		if (TYPE.equals(intent.getAction()))
+		{
+			int state = InputStickHID.getState();
+			String stringToType = intent.getStringExtra(Intent.EXTRA_TEXT);
+			
+			switch (state) {
+				case ConnectionManager.STATE_CONNECTED:
+				case ConnectionManager.STATE_CONNECTING:
+				case ConnectionManager.STATE_READY:
+					typeString(stringToType);
+					break;
+				case ConnectionManager.STATE_DISCONNECTED:
+				case ConnectionManager.STATE_FAILURE:	
+					synchronized (stringsToType) {
+						stringsToType.add(stringToType);
+					}
+					Log.d(_TAG, "trigger connect");
+					InputStickHID.connect(getApplication());
+					
+					break;											
+			}	
+			
+		}
+		
+
+		return Service.START_NOT_STICKY;
+
+	}
+
+	private void typeString(String stringToType) {
+		Log.d(_TAG, "typing "+stringToType);
+		
+		if (stringToType.equals("\n"))
+		{
+			InputStickKeyboard.pressAndRelease(HIDKeycodes.NONE, HIDKeycodes.KEY_ENTER);
+			return;
+		}
+		if (stringToType.equals("\t"))
+		{
+			InputStickKeyboard.pressAndRelease(HIDKeycodes.NONE, HIDKeycodes.KEY_TAB);
+			return;
+		}
+		
+		KeyboardLayout layout = KeyboardLayout.getLayout(PreferenceManager.getDefaultSharedPreferences(this).getString("kbd_layout", "en-US"));
+		
+		//currently supported layouts: de-DE, en-US, pl-PL, ru-RU
+		layout.type(stringToType);
+		
+		
+		//InputStickKeyboard.typeASCII(stringToType);
+	}
+
+	private void typeQueue() {
+		synchronized (stringsToType) {
+			for (String t:stringsToType)
+			{
+				Log.d(_TAG, "typing (after callback) "+t);
+				typeString(t);	
+			}
+			stringsToType.clear();
+		}
+	}
+
+	private void showNotification() {
+		android.support.v4.app.NotificationCompat.Builder b = new Builder(this);
+		b.setSmallIcon(R.drawable.ic_notification);
+
+		b.setPriority(android.support.v4.app.NotificationCompat.PRIORITY_MIN);
+		b.setContentTitle("KP2A InputStick");
+		
+		int state = InputStickHID.getState();
+		
+		Intent disconnectIntent = new Intent(this, InputStickService.class);
+		disconnectIntent.setAction(DISCONNECT);
+		
+		switch (state) {
+			case ConnectionManager.STATE_CONNECTED:
+			case ConnectionManager.STATE_CONNECTING:
+				b.setContentText("connecting...");
+
+				b.addAction(android.R.drawable.ic_menu_close_clear_cancel, "disconnect", PendingIntent.getService(this, 1, disconnectIntent, 0));
+				
+				break;
+			case ConnectionManager.STATE_READY:
+				b.setContentText("InputStick connected.");
+
+				b.addAction(android.R.drawable.ic_menu_close_clear_cancel, "disconnect", PendingIntent.getService(this, 1, disconnectIntent, 0));
+				
+				break;
+			case ConnectionManager.STATE_DISCONNECTED:
+			case ConnectionManager.STATE_FAILURE:	
+				b.setContentText("InputStick failure");
+				
+				break;											
+		}	
+		startForeground(NOTIFICATION_ID, b.build());
+	}
+	
+	@Override
+	public IBinder onBind(Intent arg0) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	
+	@Override
+	public void onDestroy() {
+		InputStickHID.removeStateListener(this);
+		super.onDestroy();
+	}
+
+	@Override
+	public void onStateChanged(int state) {
+		showNotification();
+		Log.d(_TAG, "state changed: "+state);
+		switch (state) {
+			case ConnectionManager.STATE_READY:
+				
+				/*
+				Intent typeQueue = new Intent(this, InputStickService.class);
+				typeQueue.setAction(TYPE_QUEUE);
+				startService(typeQueue);
+					*/
+				new AsyncTask<Object, Object, Object>() {
+
+					@Override
+					protected Object doInBackground(Object... params) {
+						
+						try {
+							Thread.sleep(1000, 0);
+						} catch (InterruptedException e) {
+							// TODO Auto-generated catch block
+							e.printStackTrace();
+						}
+						typeQueue();
+						
+						return null;
+					}
+
+				};
+				typeQueue();
+				break;
+			case ConnectionManager.STATE_DISCONNECTED:
+				Log.d(_TAG, "stopping service. State = "+state);
+				stopSelf();
+				break;
+			case ConnectionManager.STATE_FAILURE:
+				Log.d(_TAG, "stopping service. State = "+state);
+				stopSelf();
+				Toast.makeText(this, "Failure connecting to InputStick! Do you have InputStickUtility installed?", Toast.LENGTH_LONG).show();
+				
+				break;		
+			default:
+				break;
+		}	
+		
+	}
+
+}
diff --git a/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/MainActivity.java b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/MainActivity.java
new file mode 100644
index 00000000..5ef48bc9
--- /dev/null
+++ b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/MainActivity.java
@@ -0,0 +1,100 @@
+package keepass2android.plugin.inputstick;
+
+import com.inputstick.api.ConnectionManager;
+import com.inputstick.api.basic.InputStickHID;
+import com.inputstick.api.basic.InputStickKeyboard;
+
+import android.app.Activity;
+import android.app.ActionBar;
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.os.Build;
+
+public class MainActivity extends Activity {
+
+	@Override
+	protected void onCreate(Bundle savedInstanceState) {
+		super.onCreate(savedInstanceState);
+		setContentView(R.layout.activity_main);
+
+		if (savedInstanceState == null) {
+			getFragmentManager().beginTransaction()
+					.add(R.id.container, new PlaceholderFragment()).commit();
+		}
+	}
+
+	@Override
+	public boolean onCreateOptionsMenu(Menu menu) {
+
+		// Inflate the menu; this adds items to the action bar if it is present.
+		getMenuInflater().inflate(R.menu.main, menu);
+		return true;
+	}
+
+	@Override
+	public boolean onOptionsItemSelected(MenuItem item) {
+		// Handle action bar item clicks here. The action bar will
+		// automatically handle clicks on the Home/Up button, so long
+		// as you specify a parent activity in AndroidManifest.xml.
+		int id = item.getItemId();
+		if (id == R.id.action_settings) {
+			return true;
+		}
+		return super.onOptionsItemSelected(item);
+	}
+
+	/**
+	 * A placeholder fragment containing a simple view.
+	 */
+	public static class PlaceholderFragment extends Fragment {
+
+		public PlaceholderFragment() {
+		}
+
+		@Override
+		public View onCreateView(LayoutInflater inflater, ViewGroup container,
+				Bundle savedInstanceState) {
+			View rootView = inflater.inflate(R.layout.fragment_main, container,
+					false);
+			View btn1 = rootView.findViewById(R.id.button1);
+			btn1.setOnClickListener(new View.OnClickListener() {
+				
+				@Override
+				public void onClick(View v) {
+					
+					String textToType = "some text to transfer";
+					triggerTypeService(textToType);
+					
+					
+				}
+
+				
+			});
+			
+			rootView.findViewById(R.id.button2).setOnClickListener(new View.OnClickListener() {
+				
+				@Override
+				public void onClick(View v) {
+					triggerTypeService("");
+					
+				}
+			});
+			
+			return rootView;
+		}
+		private void triggerTypeService(String textToType) {
+			Intent serviceIntent = new Intent(getActivity(), InputStickService.class);
+			serviceIntent.setAction(InputStickService.TYPE);
+		
+			serviceIntent.putExtra(Intent.EXTRA_TEXT, textToType);
+			getActivity().startService(serviceIntent);
+		}
+	}
+
+}
diff --git a/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/SettingsActivity.java b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/SettingsActivity.java
new file mode 100644
index 00000000..a7e8e278
--- /dev/null
+++ b/src/java/PluginInputStick/src/keepass2android/plugin/inputstick/SettingsActivity.java
@@ -0,0 +1,212 @@
+package keepass2android.plugin.inputstick;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.media.Ringtone;
+import android.media.RingtoneManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceActivity;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceManager;
+import android.preference.PreferenceScreen;
+import android.preference.RingtonePreference;
+import android.text.TextUtils;
+
+import java.util.List;
+
+import keepass2android.pluginsdk.AccessManager;
+import keepass2android.pluginsdk.Strings;
+
+/**
+ * A {@link PreferenceActivity} that presents a set of application settings. On
+ * handset devices, settings are presented as a single list. On tablets,
+ * settings are split by category, with category headers shown to the left of
+ * the list of settings.
+ * <p>
+ * See <a href="http://developer.android.com/design/patterns/settings.html">
+ * Android Design: Settings</a> for design guidelines and the <a
+ * href="http://developer.android.com/guide/topics/ui/settings.html">Settings
+ * API Guide</a> for more information on developing a Settings UI.
+ */
+public class SettingsActivity extends PreferenceActivity {
+	/**
+	 * Determines whether to always show the simplified settings UI, where
+	 * settings are presented in a single list. When false, settings are shown
+	 * as a master/detail two-pane view on tablets. When true, a single pane is
+	 * shown on tablets.
+	 */
+	private static final boolean ALWAYS_SIMPLE_PREFS = false;
+
+	@Override
+	protected void onPostCreate(Bundle savedInstanceState) {
+		super.onPostCreate(savedInstanceState);
+
+		setupSimplePreferencesScreen();
+	}
+
+	/**
+	 * Shows the simplified settings UI if the device configuration if the
+	 * device configuration dictates that a simplified, single-pane UI should be
+	 * shown.
+	 */
+	private void setupSimplePreferencesScreen() {
+		if (!isSimplePreferences(this)) {
+			return;
+		}
+
+		// In the simplified UI, fragments are not used at all and we instead
+		// use the older PreferenceActivity APIs.
+
+		// Add 'general' preferences.
+		addPreferencesFromResource(R.xml.pref_general);
+
+		bindPreferenceSummaryToValue(findPreference("kbd_layout"));
+		
+		Preference enablePref = findPreference("enable_plugin_pref");
+		
+		enablePref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+			
+			@Override
+			public boolean onPreferenceClick(Preference preference) {
+				try
+				{
+					Intent i = new Intent(Strings.ACTION_EDIT_PLUGIN_SETTINGS);
+					i.putExtra(Strings.EXTRA_PLUGIN_PACKAGE, SettingsActivity.this.getPackageName());
+					startActivityForResult(i, 123);
+				}
+				catch(Exception e)
+				{
+					e.printStackTrace();
+				}
+				return true;
+			}
+		});
+		
+	}
+	
+	@Override
+	protected void onResume() {
+		Preference enablePref = findPreference("enable_plugin_pref");
+		if (AccessManager.getAllHostPackages(SettingsActivity.this).isEmpty())
+		{
+			enablePref.setSummary("");
+		}
+		else
+		{
+			enablePref.setSummary("enabled.");
+		}
+		// TODO Auto-generated method stub
+		super.onResume();
+	}
+
+	/** {@inheritDoc} */
+	@Override
+	public boolean onIsMultiPane() {
+		return isXLargeTablet(this) && !isSimplePreferences(this);
+	}
+
+	/**
+	 * Helper method to determine if the device has an extra-large screen. For
+	 * example, 10" tablets are extra-large.
+	 */
+	private static boolean isXLargeTablet(Context context) {
+		return (context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_XLARGE;
+	}
+
+	/**
+	 * Determines whether the simplified settings UI should be shown. This is
+	 * true if this is forced via {@link #ALWAYS_SIMPLE_PREFS}, or the device
+	 * doesn't have newer APIs like {@link PreferenceFragment}, or the device
+	 * doesn't have an extra-large screen. In these cases, a single-pane
+	 * "simplified" settings UI should be shown.
+	 */
+	private static boolean isSimplePreferences(Context context) {
+		return ALWAYS_SIMPLE_PREFS
+				|| Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB
+				|| !isXLargeTablet(context);
+	}
+
+	
+
+	/**
+	 * A preference value change listener that updates the preference's summary
+	 * to reflect its new value.
+	 */
+	private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
+		@Override
+		public boolean onPreferenceChange(Preference preference, Object value) {
+			String stringValue = value.toString();
+
+			if (preference instanceof ListPreference) {
+				// For list preferences, look up the correct display value in
+				// the preference's 'entries' list.
+				ListPreference listPreference = (ListPreference) preference;
+				int index = listPreference.findIndexOfValue(stringValue);
+
+				// Set the summary to reflect the new value.
+				preference
+						.setSummary(index >= 0 ? listPreference.getEntries()[index]
+								: null);
+
+
+			} else {
+				// For all other preferences, set the summary to the value's
+				// simple string representation.
+				preference.setSummary(stringValue);
+			}
+			return true;
+		}
+	};
+
+	/**
+	 * Binds a preference's summary to its value. More specifically, when the
+	 * preference's value is changed, its summary (line of text below the
+	 * preference title) is updated to reflect the value. The summary is also
+	 * immediately updated upon calling this method. The exact display format is
+	 * dependent on the type of preference.
+	 * 
+	 * @see #sBindPreferenceSummaryToValueListener
+	 */
+	private static void bindPreferenceSummaryToValue(Preference preference) {
+		// Set the listener to watch for value changes.
+		preference
+				.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);
+
+		// Trigger the listener immediately with the preference's
+		// current value.
+		sBindPreferenceSummaryToValueListener.onPreferenceChange(
+				preference,
+				PreferenceManager.getDefaultSharedPreferences(
+						preference.getContext()).getString(preference.getKey(),
+						""));
+	}
+
+	/**
+	 * This fragment shows general preferences only. It is used when the
+	 * activity is showing a two-pane settings UI.
+	 */
+	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
+	public static class GeneralPreferenceFragment extends PreferenceFragment {
+		@Override
+		public void onCreate(Bundle savedInstanceState) {
+			super.onCreate(savedInstanceState);
+			addPreferencesFromResource(R.xml.pref_general);
+
+			// Bind the summaries of EditText/List/Dialog/Ringtone preferences
+			// to their values. When their values change, their summaries are
+			// updated to reflect the new value, per the Android Design
+			// guidelines.
+			//bindPreferenceSummaryToValue(findPreference("example_text"));
+			//bindPreferenceSummaryToValue(findPreference("example_list"));
+		}
+	}
+
+}
diff --git a/src/java/PluginQR/AndroidManifest.xml b/src/java/PluginQR/AndroidManifest.xml
index c60d1c0a..4fe916b2 100644
--- a/src/java/PluginQR/AndroidManifest.xml
+++ b/src/java/PluginQR/AndroidManifest.xml
@@ -21,7 +21,7 @@
 
     <application
         android:allowBackup="true"
-        android:icon="@drawable/qrcode"
+        android:icon="@drawable/ic_launcher"
         android:label="@string/app_name"
         android:theme="@style/AppTheme" >
         <activity
diff --git a/src/java/PluginQR/res/drawable-hdpi/ic_launcher.png b/src/java/PluginQR/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..fede9733
Binary files /dev/null and b/src/java/PluginQR/res/drawable-hdpi/ic_launcher.png differ
diff --git a/src/java/PluginQR/res/drawable-mdpi/ic_launcher.png b/src/java/PluginQR/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..3a1e5e02
Binary files /dev/null and b/src/java/PluginQR/res/drawable-mdpi/ic_launcher.png differ
diff --git a/src/java/PluginQR/res/drawable-xhdpi/ic_launcher.png b/src/java/PluginQR/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 00000000..672e9068
Binary files /dev/null and b/src/java/PluginQR/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/src/java/PluginQR/res/drawable-xxhdpi/ic_launcher.png b/src/java/PluginQR/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 00000000..f50f542d
Binary files /dev/null and b/src/java/PluginQR/res/drawable-xxhdpi/ic_launcher.png differ
diff --git a/src/java/PluginQR/res/values/stringsqr.xml b/src/java/PluginQR/res/values/stringsqr.xml
index 3a97cc89..c7d45231 100644
--- a/src/java/PluginQR/res/values/stringsqr.xml
+++ b/src/java/PluginQR/res/values/stringsqr.xml
@@ -7,7 +7,7 @@
     <string name="include_label">Include field label</string>
     <string name="all_fields">All fields</string>
     <string name="kp2aplugin_title">QR Plugin</string>
-    <string name="kp2aplugin_shortdesc">Displays password entries as QR code</string>
+    <string name="kp2aplugin_shortdesc">Displays password entries as QR code; can be used to scan QR codes which can then be added to Keepass2Android.</string>
     <string name="kp2aplugin_author">Philipp Crocoll</string>
     <string name="scan_qr">Scan QR code from other device</string>
     <string name="show_qr">Select entry to show as QR code</string>