class library to access fischertechnik interfaces via USB

Dependencies:   FatFileSystem mbed myBlueUSB neigbourhood rfcomm sdp

Files at this revision

API Documentation at this revision

Comitter:
networker
Date:
Wed Jun 15 19:12:25 2011 +0000
Child:
1:4676e8b9b357
Commit message:
initial version
; Bluetooth support incomplete

Changed in this revision

AvailableMemory.cpp Show annotated file Show diff for this revision Revisions of this file
AvailableMemory.h Show annotated file Show diff for this revision Revisions of this file
FATFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
ROBO_TX_FW.h Show annotated file Show diff for this revision Revisions of this file
ROBO_TX_FW_1_24.h Show annotated file Show diff for this revision Revisions of this file
fifo.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ROBO_TX_FW_1_24.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ft.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ftErrCode.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlib.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclass.cpp Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclass.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclasscom.cpp Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclasscom.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclassdev.cpp Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclassdev.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclasstxc.cpp Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclasstxc.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclasstxcbt.cpp Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclasstxcbt.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclassusb.cpp Show annotated file Show diff for this revision Revisions of this file
ftlib/ftlibclassusb.h Show annotated file Show diff for this revision Revisions of this file
ftlib/ftusb.cpp Show annotated file Show diff for this revision Revisions of this file
ftlib/ftusb.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.lib Show annotated file Show diff for this revision Revisions of this file
message.h Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/HCITransportUSB.h Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/L2CAP.cpp Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/Socket.cpp Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/Socket.h Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/Utils.cpp Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/Utils.h Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/hci.cpp Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/hci.h Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/hci_private.h Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/rfcomm/RFCOMM.cpp Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/rfcomm/RFCOMM.h Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/sdp/sdp.cpp Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/sdp/sdp.h Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/sdp/sdp_data.cpp Show annotated file Show diff for this revision Revisions of this file
myBlueUSB/sdp/sdp_data.h Show annotated file Show diff for this revision Revisions of this file
myUSBHost/AutoEvents.cpp Show annotated file Show diff for this revision Revisions of this file
myUSBHost/MassStorage.cpp Show annotated file Show diff for this revision Revisions of this file
myUSBHost/USBHost.cpp Show annotated file Show diff for this revision Revisions of this file
myUSBHost/USBHost.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AvailableMemory.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,34 @@
+#include "AvailableMemory.h"
+#include <stdlib.h>
+
+namespace segundo {
+namespace Utilities {
+
+int AvailableMemory(int resolution, int maximum, bool disableInterrupts) {
+
+    if (resolution < 1) resolution = 1;
+    if (maximum < 0) maximum = 0;
+
+    int low = 0;
+    int high = maximum + 1;
+
+    if (disableInterrupts) __disable_irq();
+
+    while (high - low > resolution) {
+        int mid = (low + high) / 2;
+        void* p = malloc(mid);
+        if (p == NULL) {
+            high = mid;
+        } else {
+            free(p);
+            low = mid;
+        }
+    }
+
+    if (disableInterrupts) __enable_irq();
+
+    return low;
+}
+
+} // namespace Utilities
+} // namespace segundo
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AvailableMemory.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,46 @@
+/** @file
+ * Return the memory available for a malloc call.
+ */
+#ifndef SEGUNDO_UTILITIES_AVAILABLEMEMORY_H
+#define SEGUNDO_UTILITIES_AVAILABLEMEMORY_H
+
+/**
+ * Segundo Equipo
+ */
+namespace segundo {
+/**
+ * A collection of utilities
+ */
+namespace Utilities {
+
+/** Return the memory available for a malloc call.
+ * This is done by a binary search approach
+ * calling malloc/free starting with a maximum.
+ *
+ * Example:
+ * @code
+ * #include <stdio.h>
+ * #include "AvailableMemory.h"
+ *
+ * int main() {
+ *
+ *     printf("Available memory (bytes to nearest 256) : %d\n", AvailableMemory());
+ *     printf("Available memory (exact bytes) : %d\n", AvailableMemory(1));
+ *
+ * }
+ * @endcode
+ * @param resolution Resolution in number of bytes,
+ * 1 will return the exact value,
+ * default will return the available memory to the nearest 256 bytes
+ * @param maximum Maximum amount of memory to check, default is 32K (0x8000)
+ * @param disableInterrupts Disable interrupts whilst checking, default is true
+ * @return Available memory in bytes accurate to within resolution
+ */
+int AvailableMemory(int resolution = 256, int maximum = 0x8000, bool disableInterrupts = true);
+
+} // namespace Utilities
+} // namespace segundo
+
+using namespace segundo::Utilities;
+
+#endif // SEGUNDO_UTILITIES_AVAILABLEMEMORY_H
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FATFileSystem.lib	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.co.uk/projects/libraries/svn/FATFileSystem/trunk@19
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ROBO_TX_FW.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,356 @@
+//=============================================================================
+//              |  
+// Headerfile   |  robo_tx_fw.h
+//              |  
+// Description  |  Header file with definition of the software interface
+//              |  to the ROBO TX Controller firmware.
+//              |  Can be used for building C-programs which can run
+//              |  under control of the ROBO TX Controller firmware in
+//              |  download (local) mode or for building PC-programs which
+//              |  can communicate with the ROBO TX Controller firmware in
+//              |  online mode.
+//              |
+//-----------------------------------------------------------------------------
+// Disclaimer - Exclusion of Liability
+//
+// This software is distributed in the hope that it will be useful,but WITHOUT 
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+// FITNESS FOR A PARTICULAR PURPOSE. It can be used an modified by anyone
+// free of any license obligations or authoring rights.
+//=============================================================================
+
+#ifndef __ROBO_TX_FW_H__
+#define __ROBO_TX_FW_H__
+
+
+#define N_CNT               4           //  number of counters
+#define N_PWM_CHAN          8           //  number of PWM channels
+#define N_MOTOR             4           //  number of motors
+#define N_UNI               8           //  number of universal inputs
+
+// 5kOhm Range
+#define R_MIN               10          //  [Ohm]
+#define R_MAX               4999        //  [Ohm]
+#define R_OVR               5000        //  [Ohm] overload
+
+// 10V Range
+#define U_MIN               0           //  [mV]
+#define U_MAX               9999        //  [mV]
+#define U_OVR               10000       //  [mV] overload
+
+// Ultrasonic Sensor Range
+#define ULTRASONIC_MIN      2           //  [cm]
+#define ULTRASONIC_MAX      1023        //  [cm]
+#define ULTRASONIC_OVR      1024        //  [cm] overload
+#define NO_ULTRASONIC       4096        //  not present
+
+// Length of strings
+#define DEV_NAME_LEN        16          // "ROBO TX-xxxxxxxx"
+#define BLUETOOTH_ADDR_LEN  17          // "xx:xx:xx:xx:xx:xx"
+#define DISPL_MSG_LEN_MAX   64          // max length of a pop-up display message
+
+
+// Identifiers of the Transfer Area parts
+enum ta_id_e
+{
+    TA_LOCAL = 0,           // Local part of Transfer Area. Corresponds to the device on which  
+                            // program is currently running in download (local) mode or to the
+                            // remotely controlled device (seen from controlled device not from
+                            // controlling device) in online mode.
+    TA_EXT_1,               // Extension 1 part of Transfer Area
+    TA_EXT_2,               // Extension 2 part of Transfer Area
+    TA_EXT_3,               // Extension 3 part of Transfer Area
+    TA_EXT_4,               // Extension 4 part of Transfer Area
+    TA_EXT_5,               // Extension 5 part of Transfer Area
+    TA_EXT_6,               // Extension 6 part of Transfer Area
+    TA_EXT_7,               // Extension 7 part of Transfer Area
+    TA_EXT_8,               // Extension 8 part of Transfer Area
+    TA_N_PARTS              // Number of Transfer Area parts
+};
+
+#define N_EXT_DEV           (TA_N_PARTS - 1)    // Number of extension devices = 8
+
+
+// Device functioning modes
+enum dev_mode_e
+{
+    DEV_MODE_LOCAL = 0,
+    DEV_MODE_ONLINE,
+    DEV_MODE_INVALID
+};
+
+
+// State of connection to an extension device
+enum ext_dev_connect_state_e
+{
+    EXT_DEV_OFFLINE = 0,
+    EXT_DEV_ONLINE,
+    EXT_DEV_INVALID
+};
+
+
+// Modes of universal inputs
+enum input_mode_e
+{
+    MODE_U = 0,
+    MODE_R = 1,
+    MODE_ULTRASONIC = 3,
+    MODE_INVALID
+};
+
+
+// Program states
+enum pgm_state_e
+{
+    PGM_STATE_INVALID = 0,
+    PGM_STATE_RUN,
+    PGM_STATE_STOP
+};
+
+
+// Timer units for GetSystemTime hook function
+enum TimerUnit
+{
+    TIMER_UNIT_INVALID        = 0,
+    TIMER_UNIT_SECONDS        = 2,
+    TIMER_UNIT_MILLISECONDS   = 3,
+    TIMER_UNIT_MICROSECONDS   = 4
+};
+
+
+//=============================================================================
+//  Structures for Transfer Area (TA)
+//=============================================================================
+
+
+// Program information, 8 bytes
+typedef struct
+{
+    char          * name;   // name of a program with a full path, for example, "/ramdisk/Program_1"
+    UINT8           state;  // enum pgm_state_e
+    char            reserved[3];
+} PGM_INFO;
+
+
+// Display message, 68 bytes. Used to show pop-up message box on the boards display
+typedef struct
+{
+    unsigned char   id; // should be increased by 1 each time a new pop-up message is to be shown
+    char            text[DISPL_MSG_LEN_MAX + 1];
+    char            reserved[2];
+} DISPLAY_MSG;
+
+
+// Display frame, 8 bytes. Used to refresh boards display with a bitmap image frame
+typedef struct
+{
+    unsigned char * frame;  // contents of a frame as a 128x64 pixels bitmap
+    UINT16          id;     // should be increased by 1 each time a new display frame is to be shown
+    BOOL16          is_pgm_master_of_display;   // ++ if program wants to have control over display,
+                                                // i.e. image frame is displayed over firmware menus;
+                                                // -- if program wants to return control over display
+                                                // to the firmware menus
+} DISPLAY_FRAME;
+
+
+// Version structure definition, 4 bytes
+typedef union
+{
+    unsigned long abcd;
+    struct
+    {
+        unsigned char   a;
+        unsigned char   b;
+        unsigned char   c;
+        unsigned char   d;
+    } part;
+} FT_VER;
+
+
+// Versions of hardware and firmware components, 16 bytes
+typedef struct
+{
+    FT_VER          hardware;   // version of hardware (hardware.part.a = 'A' or 'B' or 'C')
+    FT_VER          firmware;   // version of firmware ("V %d.%02d", firmware.part.c, firmware.part.d)
+    FT_VER          ta;         // version of transfer area ("V %d.%02d", ta.part.c, ta.part.d)
+    char            reserved[4];
+} FT_VERSION;
+
+
+// Info structure, 64 bytes
+typedef struct
+{
+    char            device_name[DEV_NAME_LEN + 1];
+    char            bt_addr[BLUETOOTH_ADDR_LEN + 1];
+    char            reserved;
+    unsigned long   ta_start_addr;
+    unsigned long   pgm_area_start_addr;
+    unsigned long   pgm_area_size;
+    FT_VERSION      version;
+} TA_INFO;
+
+
+// State structure, 36 bytes
+typedef struct
+{
+    // Used by local program
+    BOOL8           pgm_initialized;
+    char            reserved_1[7];
+
+    // Public state info
+    BOOL8           dev_mode;   // enum dev_mode_e
+    UCHAR8          id;         // Should be increased by 1 each time something (except id fields)
+                                // is changed in this state structure
+    UCHAR8          info_id;    // Should be increased by 1 each time something is changed in info structure
+    UCHAR8          config_id;  // Should be increased by 1 each time something is changed in config structure
+    BOOL8           ext_dev_connect_state[N_EXT_DEV];    // enum ext_dev_connect_state_e
+    char            reserved_2[8];
+    PGM_INFO        local_pgm;  // Corresponds to the program currently being in the program memory
+} TA_STATE;
+
+
+// Universal inputs configuration, 4 bytes
+typedef struct
+{
+    UINT8           mode;       // enum input_mode_e
+    BOOL8           digital;    // FALSE = analog input, TRUE = digital input
+    unsigned char   reserved[2];
+} UNI_CONFIG;
+
+
+// Counter inputs configuration, 4 bytes
+typedef struct
+{
+    UINT8           mode;       // enum input_mode_e
+    unsigned char   reserved[3];
+} CNT_CONFIG;
+
+
+// Config structure, 88 bytes
+typedef struct
+{
+    UINT8           pgm_state_req;  // enum pgm_state_e
+    char            reserved_1[3];
+    BOOL8           motor[N_MOTOR];
+    UNI_CONFIG      uni[N_UNI];
+    CNT_CONFIG      cnt[N_CNT];
+    char            reserved_2[32];
+} TA_CONFIG;
+
+
+// Input structure, 40 bytes
+typedef struct
+{
+    INT16           uni[N_UNI];
+    INT16           cnt_in[N_CNT];
+    INT16           counter[N_CNT];
+    // Number of milliseconds during which the left display button is being kept pressed
+    INT16           display_button_left;
+    // Number of milliseconds during which the right display button is being kept pressed
+    INT16           display_button_right;
+    // Set to 1 by motor control if target position is reached
+    INT16           motor_pos_reached[N_MOTOR];
+} TA_INPUT;
+
+
+// Output structure, 36 bytes
+typedef struct
+{
+    // Counter reset requests
+    BOOL8           cnt_reset[N_CNT];
+    // If not 0, synchronize this channel with the given channel (1:channel 0, ...)
+    UINT8           master[N_MOTOR];
+    // Selected motor PWM values
+    INT16           duty[N_PWM_CHAN];
+    // Selected distane (counter value) at which motor shall stop
+    UINT16          distance[N_MOTOR];
+    char            reserved[4];
+} TA_OUTPUT;
+
+
+// Display structure, 76 bytes
+typedef struct
+{
+    DISPLAY_MSG     display_msg;
+    DISPLAY_FRAME   display_frame;
+} TA_DISPLAY;
+
+
+// Change structure (only for ftMscLib), 8 bytes
+typedef struct
+{
+    char            reserved_1[2];
+    UINT8           ChangeStatus;
+    UINT8           ChangeUni;
+    UINT8           ChangeCntIn;
+    UINT8           ChangeCounter;
+    char            reserved_2[2];
+} TA_CHANGE;
+
+
+// 16-bit timers, 12 bytes
+typedef struct
+{
+    UINT16          Timer1ms;
+    UINT16          Timer10ms;
+    UINT16          Timer100ms;
+    UINT16          Timer1s;
+    UINT16          Timer10s;
+    UINT16          Timer1min;
+} TA_TIMER;
+
+
+// Hook table with pointers to the firmware functions,
+// that can be called by local program, 4 bytes
+typedef struct
+{
+    INT32   (*IsRunAllowed) (void);
+    UINT32  (*GetSystemTime)(enum TimerUnit unit);
+} TA_HOOK_TABLE;
+
+
+
+// ============================================================================
+//  Transfer Area (TA) of ROBO TX Controller (one part of TA_N_PARTS)
+// ============================================================================
+#define RESERVED_1_SIZE  4
+#define RESERVED_2_SIZE  28
+#define RESERVED_3_SIZE \
+    (512 - ( \
+    sizeof(TA_INFO)         + \
+    sizeof(TA_STATE)        + \
+    sizeof(TA_CONFIG)       + \
+    sizeof(TA_INPUT)        + \
+    sizeof(TA_OUTPUT)       + \
+    sizeof(TA_DISPLAY)      + \
+    RESERVED_1_SIZE         + \
+    sizeof(TA_CHANGE)       + \
+    sizeof(TA_TIMER)        + \
+    RESERVED_2_SIZE         + \
+    sizeof(TA_HOOK_TABLE)     \
+    ))
+
+
+typedef struct
+{
+    TA_INFO             info;           // info structure
+    TA_STATE            state;          // state structure
+    TA_CONFIG           config;         // config structure   
+    TA_INPUT            input;          // input structure
+    TA_OUTPUT           output;         // output structure
+    TA_DISPLAY          display;        // display structure
+
+    char                reserved_1[RESERVED_1_SIZE];
+
+    TA_CHANGE           change;         // change structure
+    TA_TIMER            timer;          // 16-bit timers
+
+    char                reserved_2[RESERVED_2_SIZE];
+
+    TA_HOOK_TABLE       hook_table;     // hook table with functions pointers
+
+    char                reserved_3[RESERVED_3_SIZE];
+} TA;
+
+
+#endif // __ROBO_TX_FW_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ROBO_TX_FW_1_24.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,387 @@
+//=============================================================================
+//              |
+// Headerfile   |  robo_tx_fw.h
+//              |
+// Description  |  Header file with definition of the software interface
+//              |  to the ROBO TX Controller firmware.
+//              |  Can be used for building C-programs which can run
+//              |  under control of the ROBO TX Controller firmware in
+//              |  download (local) mode or for building PC-programs which
+//              |  can communicate with the ROBO TX Controller firmware in
+//              |  online mode.
+//              |
+//-----------------------------------------------------------------------------
+// Disclaimer - Exclusion of Liability
+//
+// This software is distributed in the hope that it will be useful,but WITHOUT 
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+// FITNESS FOR A PARTICULAR PURPOSE. It can be used an modified by anyone
+// free of any license obligations or authoring rights.
+//=============================================================================
+
+#ifndef __ROBO_TX_FW_H__
+#define __ROBO_TX_FW_H__
+#define FW_1_24    //my own adaptations to comply with FW version 1.24
+
+#define N_CNT               4           //  number of counters
+#define N_PWM_CHAN          8           //  number of PWM channels
+#define N_MOTOR             4           //  number of motors
+#define N_UNI               8           //  number of universal inputs
+
+// 5kOhm Range
+#define R_MIN               10          //  [Ohm]
+#define R_MAX               4999        //  [Ohm]
+#define R_OVR               5000        //  [Ohm] overload
+
+// 10V Range
+#define U_MIN               0           //  [mV]
+#define U_MAX               9999        //  [mV]
+#define U_OVR               10000       //  [mV] overload
+
+// Ultrasonic Sensor Range
+#define ULTRASONIC_MIN      2           //  [cm]
+#define ULTRASONIC_MAX      1023        //  [cm]
+#define ULTRASONIC_OVR      1024        //  [cm] overload
+#define NO_ULTRASONIC       4096        //  not present
+
+// Length of strings
+#define DEV_NAME_LEN        16          // "ROBO TX-xxxxxxxx"
+#define BLUETOOTH_ADDR_LEN  17          // "xx:xx:xx:xx:xx:xx"
+#define DISPL_MSG_LEN_MAX   64          // max length of a pop-up display message
+
+
+// Identifiers of the Transfer Area parts
+enum ta_id_e
+{
+    TA_LOCAL = 0,           // Local part of Transfer Area. Corresponds to the device on which  
+                            // program is currently running in download (local) mode or to the
+                            // remotely controlled device (seen from controlled device not from
+                            // controlling device) in online mode.
+    TA_EXT_1,               // Extension 1 part of Transfer Area
+    TA_EXT_2,               // Extension 2 part of Transfer Area
+    TA_EXT_3,               // Extension 3 part of Transfer Area
+    TA_EXT_4,               // Extension 4 part of Transfer Area
+    TA_EXT_5,               // Extension 5 part of Transfer Area
+    TA_EXT_6,               // Extension 6 part of Transfer Area
+    TA_EXT_7,               // Extension 7 part of Transfer Area
+    TA_EXT_8,               // Extension 8 part of Transfer Area
+    TA_N_PARTS              // Number of Transfer Area parts
+};
+
+#define N_EXT_DEV           (TA_N_PARTS - 1)    // Number of extension devices = 8
+
+
+// Device functioning modes
+enum dev_mode_e
+{
+    DEV_MODE_LOCAL = 0,
+    DEV_MODE_ONLINE,
+    DEV_MODE_INVALID
+};
+
+
+// State of connection to an extension device
+enum ext_dev_connect_state_e
+{
+    EXT_DEV_OFFLINE = 0,
+    EXT_DEV_ONLINE,
+    EXT_DEV_INVALID
+};
+
+
+// Modes of universal inputs
+enum input_mode_e
+{
+    MODE_U = 0,
+    MODE_R = 1,
+    MODE_ULTRASONIC = 3,
+    MODE_INVALID
+};
+
+
+// Program states
+enum pgm_state_e
+{
+    PGM_STATE_INVALID = 0,
+    PGM_STATE_RUN,
+    PGM_STATE_STOP
+};
+
+
+// Timer units for GetSystemTime hook function
+enum TimerUnit
+{
+    TIMER_UNIT_INVALID        = 0,
+    TIMER_UNIT_SECONDS        = 2,
+    TIMER_UNIT_MILLISECONDS   = 3,
+    TIMER_UNIT_MICROSECONDS   = 4
+};
+
+
+//=============================================================================
+//  Structures for Transfer Area (TA)
+//=============================================================================
+
+typedef char    BD_ADDR[6]; //leftmost byte in lowest address
+
+// Program information, 8 bytes
+typedef struct
+{
+    char          * name;   // name of a program with a full path, for example, "/ramdisk/Program_1"
+    UINT8           state;  // enum pgm_state_e
+    char            reserved[3];
+} PGM_INFO;
+
+
+// Display message, 68 bytes. Used to show pop-up message box on the boards display
+typedef struct
+{
+    unsigned char   id; // should be increased by 1 each time a new pop-up message is to be shown
+    char            text[DISPL_MSG_LEN_MAX + 1];
+    char            reserved[2];
+} DISPLAY_MSG;
+
+
+// Display frame, 8 bytes. Used to refresh boards display with a bitmap image frame
+typedef struct
+{
+    unsigned char * frame;  // contents of a frame as a 128x64 pixels bitmap
+    UINT16          id;     // should be increased by 1 each time a new display frame is to be shown
+    BOOL16          is_pgm_master_of_display;   // ++ if program wants to have control over display,
+                                                // i.e. image frame is displayed over firmware menus;
+                                                // -- if program wants to return control over display
+                                                // to the firmware menus
+} DISPLAY_FRAME;
+
+
+// Version structure definition, 4 bytes
+typedef union
+{
+    unsigned long abcd;
+    struct
+    {
+        unsigned char   a;
+        unsigned char   b;
+        unsigned char   c;
+        unsigned char   d;
+    } part;
+} FT_VER;
+
+
+// Versions of hardware and firmware components, 16 bytes
+typedef struct//verified
+{
+    FT_VER          hardware;   // version of hardware (hardware.part.a = 'A' or 'B' or 'C')
+    FT_VER          firmware;   // version of firmware ("V %d.%02d", firmware.part.c, firmware.part.d) firmware.part.b = DLL version
+    FT_VER          ta;         // version of transfer area ("V %d.%02d", ta.part.c, ta.part.d)
+    char            reserved[4];
+} FT_VERSION;
+
+
+// Info structure, 64 bytes
+typedef struct //verified
+{
+    char            device_name[DEV_NAME_LEN + 1];
+    char            bt_addr[BLUETOOTH_ADDR_LEN + 1];
+    char            reserved;
+    unsigned long   ta_start_addr;
+    unsigned long   pgm_area_start_addr;
+    unsigned long   pgm_area_size;
+    FT_VERSION      version;
+} TA_INFO;
+
+
+// State structure, 36 bytes
+//changed in 1.24 to 24 bytes
+typedef struct
+{
+    // Used by local program
+//    BOOL8           pgm_initialized;
+//    char            reserved_1[7];
+
+    // Public state info
+//    BOOL8           dev_mode;   // enum dev_mode_e
+//    UCHAR8          id;         // Should be increased by 1 each time something (except id fields)
+                                // is changed in this state structure
+//    UCHAR8          info_id;    // Should be increased by 1 each time something is changed in info structure
+//    UCHAR8          config_id;  // Should be increased by 1 each time something is changed in config structure
+    BOOL8           ext_dev_connect_state[N_EXT_DEV];    // enum ext_dev_connect_state_e //verified
+    char            reserved_2[8];
+    PGM_INFO        local_pgm;  // Corresponds to the program currently being in the program memory
+} TA_STATE;
+
+
+// Universal inputs configuration, 4 bytes
+//changed in 1.24 to 1 byte
+typedef struct //verified
+{
+    UINT8           mode;       // enum input_mode_e, for digital inputs msb=1, for analog msb=0
+//    BOOL8           digital;    // FALSE = analog input, TRUE = digital input
+//    unsigned char   reserved[2];
+} UNI_CONFIG;
+
+
+// Counter inputs configuration, 4 bytes
+//changed in 1.24 to 1 byte
+typedef struct
+{
+    UINT8           mode;       // enum input_mode_e
+//    unsigned char   reserved[3];
+} CNT_CONFIG;
+
+
+// Config structure, 88 bytes
+//changed in 1.24 to 48 bytes
+typedef struct
+{
+    //UINT8           pgm_state_req;  // enum pgm_state_e
+    //char            reserved_1[3];
+    BOOL8           motor[N_MOTOR];//verified
+    UNI_CONFIG      uni[N_UNI];//verified
+    CNT_CONFIG      cnt[N_CNT];//verfied 1=normal, 0=inverted
+    char            reserved_2[32];
+} TA_CONFIG;
+
+
+// Input structure, 40 bytes (wrong! 44 bytes)
+//changed in 1.24 to 48 bytes
+typedef struct
+{
+    INT16           uni[N_UNI];//verified
+    BOOL8           cnt_in[N_CNT];//was INT16
+    INT16           counter[N_CNT];//verified
+    // Number of milliseconds during which the left display button is being kept pressed
+    INT16           display_button_left;//verified
+    // Number of milliseconds during which the right display button is being kept pressed
+    INT16           display_button_right;//verified
+    char            unknown[8];//new in 1.24
+    // Set to 1 by motor control if target position is reached
+    INT16           motor_pos_reached[N_MOTOR];//verified
+} TA_INPUT;
+
+
+// Output structure, 36 bytes
+//changed in 1.24 to 44 bytes, don't know what changed, 4 bytes added before duty. 4 after
+typedef struct
+{
+    // Counter reset requests
+    INT16           cnt_reset[N_CNT];//was BOOL8
+    // If not 0, synchronize this channel with the given channel (1:channel 0, ...)
+    UINT8           master[N_MOTOR];
+    // Selected motor PWM values
+    INT16           duty[N_PWM_CHAN];//verified
+    // Selected distane (counter value) at which motor shall stop
+    UINT16          distance[N_MOTOR];//verified
+    UINT16            reserved[4];//was char
+} TA_OUTPUT;
+
+
+// Display structure, 76 bytes
+typedef struct
+{
+    DISPLAY_MSG     display_msg;
+    DISPLAY_FRAME   display_frame;
+} TA_DISPLAY;
+
+//new in 1.24 message structure, 24 bytes
+typedef struct
+{
+    UINT16            index;
+    UINT16            status;
+    UINT16            length;
+    UINT8            hwid;
+    UINT8            subid;
+    UINT16            cmd;
+    UINT16            val;
+    UINT16            unknown2[6];//possibly another message or room for larger messages
+} TA_MESSAGE;
+
+//new in 1.24 message structure, 32 bytes, note: this struct is not preceded by a transferarea-ID
+typedef struct
+{
+    UINT16            result; //??? 1 for the first (empty) result, 2 for each real result, 5 for the last (empty) result.
+    BD_ADDR            bd_addr;
+    UINT16            unknown;
+    char            device_name[DEV_NAME_LEN + 1];
+    char            pad[1];
+    UINT32            unknown2;
+} TA_INQUIRY;
+
+// Change structure (only for ftMscLib), 8 bytes
+typedef struct
+{
+    char            reserved_1[2];
+    UINT8           ChangeStatus;
+    UINT8           ChangeUni;
+    UINT8           ChangeCntIn;
+    UINT8           ChangeCounter;
+    char            reserved_2[2];
+} TA_CHANGE;
+
+
+// 16-bit timers, 12 bytes
+typedef struct
+{
+    UINT16          Timer1ms;
+    UINT16          Timer10ms;
+    UINT16          Timer100ms;
+    UINT16          Timer1s;
+    UINT16          Timer10s;
+    UINT16          Timer1min;
+} TA_TIMER;
+
+
+// Hook table with pointers to the firmware functions,
+// that can be called by local program, 4 bytes
+typedef struct
+{
+    INT32   (*IsRunAllowed) (void);
+    UINT32  (*GetSystemTime)(enum TimerUnit unit);
+} TA_HOOK_TABLE;
+
+
+
+// ============================================================================
+//  Transfer Area (TA) of ROBO TX Controller (one part of TA_N_PARTS)
+// ============================================================================
+#define RESERVED_1_SIZE  4
+#define RESERVED_2_SIZE  28
+#define RESERVED_3_SIZE \
+    (512 - ( \
+    sizeof(TA_INFO)         + \
+    sizeof(TA_STATE)        + \
+    sizeof(TA_CONFIG)       + \
+    sizeof(TA_INPUT)        + \
+    sizeof(TA_OUTPUT)       + \
+    sizeof(TA_DISPLAY)      + \
+    RESERVED_1_SIZE         + \
+    sizeof(TA_CHANGE)       + \
+    sizeof(TA_TIMER)        + \
+    RESERVED_2_SIZE         + \
+    sizeof(TA_HOOK_TABLE)     \
+    ))
+
+
+typedef struct
+{
+    TA_INFO             info;           // info structure
+    TA_STATE            state;          // state structure
+    TA_CONFIG           config;         // config structure   
+    TA_INPUT            input;          // input structure
+    TA_OUTPUT           output;         // output structure
+    TA_DISPLAY          display;        // display structure
+
+    char                reserved_1[RESERVED_1_SIZE];
+
+    TA_CHANGE           change;         // change structure
+    TA_TIMER            timer;          // 16-bit timers
+
+    char                reserved_2[RESERVED_2_SIZE];
+
+    TA_HOOK_TABLE       hook_table;     // hook table with functions pointers
+
+    char                reserved_3[RESERVED_3_SIZE];
+} TA;
+
+
+#endif // __ROBO_TX_FW_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fifo.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,61 @@
+#ifndef FIFO_H
+#define FIFO_H
+
+class fifo {
+    char *buf;
+    int size, in, out, free;
+//    fifo() {}
+public:
+    fifo(int sz = 127):size(sz), in(0), out(0), free(sz) {
+        buf = new char[sz];
+    }
+    ~fifo() {
+        delete[] buf;
+    }
+
+    void put(char c) {
+        if (free) {
+            buf[in++] = c;
+            if (in==size) in = 0;
+            free--;
+        } else
+            printf("fifo full\n");
+    }
+
+    int get() {
+        if (free == size)
+            return -1;
+        free++;
+        int c = buf[out++];
+        if (out == size) out = 0;
+        return c;
+    }
+    int gets(char *line, int len) {
+       int i = out, n = size-free, l = 0;
+       while (n>0 && buf[i] != '\n' && l<len-1) {
+         if (buf[i] != '\r')
+           line[l++] = buf[i++];
+         else
+           i++; //skip the \r
+         if (i==size) i = 0;
+         n--;
+       }
+       if (n==0) //buf does not contain EOLN
+         return -1;
+       if (buf[i] == '\n') {
+         line[l] = '\0';
+         out = i+1;
+         if (out==size) out = 0;
+         free = size - n + 1;
+         return 0; //success
+       } else //line too short
+         return -2;
+    }
+    void flush() {
+      free = size;
+      in = 0;
+      out = 0;
+    }
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ROBO_TX_FW_1_24.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,387 @@
+//=============================================================================
+//              |
+// Headerfile   |  robo_tx_fw.h
+//              |
+// Description  |  Header file with definition of the software interface
+//              |  to the ROBO TX Controller firmware.
+//              |  Can be used for building C-programs which can run
+//              |  under control of the ROBO TX Controller firmware in
+//              |  download (local) mode or for building PC-programs which
+//              |  can communicate with the ROBO TX Controller firmware in
+//              |  online mode.
+//              |
+//-----------------------------------------------------------------------------
+// Disclaimer - Exclusion of Liability
+//
+// This software is distributed in the hope that it will be useful,but WITHOUT 
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+// FITNESS FOR A PARTICULAR PURPOSE. It can be used an modified by anyone
+// free of any license obligations or authoring rights.
+//=============================================================================
+
+#ifndef __ROBO_TX_FW_H__
+#define __ROBO_TX_FW_H__
+#define FW_1_24    //my own adaptations to comply with FW version 1.24
+
+#define N_CNT               4           //  number of counters
+#define N_PWM_CHAN          8           //  number of PWM channels
+#define N_MOTOR             4           //  number of motors
+#define N_UNI               8           //  number of universal inputs
+
+// 5kOhm Range
+#define R_MIN               10          //  [Ohm]
+#define R_MAX               4999        //  [Ohm]
+#define R_OVR               5000        //  [Ohm] overload
+
+// 10V Range
+#define U_MIN               0           //  [mV]
+#define U_MAX               9999        //  [mV]
+#define U_OVR               10000       //  [mV] overload
+
+// Ultrasonic Sensor Range
+#define ULTRASONIC_MIN      2           //  [cm]
+#define ULTRASONIC_MAX      1023        //  [cm]
+#define ULTRASONIC_OVR      1024        //  [cm] overload
+#define NO_ULTRASONIC       4096        //  not present
+
+// Length of strings
+#define DEV_NAME_LEN        16          // "ROBO TX-xxxxxxxx"
+#define BLUETOOTH_ADDR_LEN  17          // "xx:xx:xx:xx:xx:xx"
+#define DISPL_MSG_LEN_MAX   64          // max length of a pop-up display message
+
+
+// Identifiers of the Transfer Area parts
+enum ta_id_e
+{
+    TA_LOCAL = 0,           // Local part of Transfer Area. Corresponds to the device on which  
+                            // program is currently running in download (local) mode or to the
+                            // remotely controlled device (seen from controlled device not from
+                            // controlling device) in online mode.
+    TA_EXT_1,               // Extension 1 part of Transfer Area
+    TA_EXT_2,               // Extension 2 part of Transfer Area
+    TA_EXT_3,               // Extension 3 part of Transfer Area
+    TA_EXT_4,               // Extension 4 part of Transfer Area
+    TA_EXT_5,               // Extension 5 part of Transfer Area
+    TA_EXT_6,               // Extension 6 part of Transfer Area
+    TA_EXT_7,               // Extension 7 part of Transfer Area
+    TA_EXT_8,               // Extension 8 part of Transfer Area
+    TA_N_PARTS              // Number of Transfer Area parts
+};
+
+#define N_EXT_DEV           (TA_N_PARTS - 1)    // Number of extension devices = 8
+
+
+// Device functioning modes
+enum dev_mode_e
+{
+    DEV_MODE_LOCAL = 0,
+    DEV_MODE_ONLINE,
+    DEV_MODE_INVALID
+};
+
+
+// State of connection to an extension device
+enum ext_dev_connect_state_e
+{
+    EXT_DEV_OFFLINE = 0,
+    EXT_DEV_ONLINE,
+    EXT_DEV_INVALID
+};
+
+
+// Modes of universal inputs
+enum input_mode_e
+{
+    MODE_U = 0,
+    MODE_R = 1,
+    MODE_ULTRASONIC = 3,
+    MODE_INVALID
+};
+
+
+// Program states
+enum pgm_state_e
+{
+    PGM_STATE_INVALID = 0,
+    PGM_STATE_RUN,
+    PGM_STATE_STOP
+};
+
+
+// Timer units for GetSystemTime hook function
+enum TimerUnit
+{
+    TIMER_UNIT_INVALID        = 0,
+    TIMER_UNIT_SECONDS        = 2,
+    TIMER_UNIT_MILLISECONDS   = 3,
+    TIMER_UNIT_MICROSECONDS   = 4
+};
+
+
+//=============================================================================
+//  Structures for Transfer Area (TA)
+//=============================================================================
+
+typedef char    BT_ADDR[6]; //leftmost byte in lowest address
+
+// Program information, 8 bytes
+typedef struct
+{
+    char          * name;   // name of a program with a full path, for example, "/ramdisk/Program_1"
+    UINT8           state;  // enum pgm_state_e
+    char            reserved[3];
+} PGM_INFO;
+
+
+// Display message, 68 bytes. Used to show pop-up message box on the boards display
+typedef struct
+{
+    unsigned char   id; // should be increased by 1 each time a new pop-up message is to be shown
+    char            text[DISPL_MSG_LEN_MAX + 1];
+    char            reserved[2];
+} DISPLAY_MSG;
+
+
+// Display frame, 8 bytes. Used to refresh boards display with a bitmap image frame
+typedef struct
+{
+    unsigned char * frame;  // contents of a frame as a 128x64 pixels bitmap
+    UINT16          id;     // should be increased by 1 each time a new display frame is to be shown
+    BOOL16          is_pgm_master_of_display;   // ++ if program wants to have control over display,
+                                                // i.e. image frame is displayed over firmware menus;
+                                                // -- if program wants to return control over display
+                                                // to the firmware menus
+} DISPLAY_FRAME;
+
+
+// Version structure definition, 4 bytes
+typedef union
+{
+    unsigned long abcd;
+    struct
+    {
+        unsigned char   a;
+        unsigned char   b;
+        unsigned char   c;
+        unsigned char   d;
+    } part;
+} FT_VER;
+
+
+// Versions of hardware and firmware components, 16 bytes
+typedef struct//verified
+{
+    FT_VER          hardware;   // version of hardware (hardware.part.a = 'A' or 'B' or 'C')
+    FT_VER          firmware;   // version of firmware ("V %d.%02d", firmware.part.c, firmware.part.d) firmware.part.b = DLL version
+    FT_VER          ta;         // version of transfer area ("V %d.%02d", ta.part.c, ta.part.d)
+    char            reserved[4];
+} FT_VERSION;
+
+
+// Info structure, 64 bytes
+typedef struct //verified
+{
+    char            device_name[DEV_NAME_LEN + 1];
+    char            bt_addr[BLUETOOTH_ADDR_LEN + 1];
+    char            reserved;
+    unsigned long   ta_start_addr;
+    unsigned long   pgm_area_start_addr;
+    unsigned long   pgm_area_size;
+    FT_VERSION      version;
+} TA_INFO;
+
+
+// State structure, 36 bytes
+//changed in 1.24 to 24 bytes
+typedef struct
+{
+    // Used by local program
+//    BOOL8           pgm_initialized;
+//    char            reserved_1[7];
+
+    // Public state info
+//    BOOL8           dev_mode;   // enum dev_mode_e
+//    UCHAR8          id;         // Should be increased by 1 each time something (except id fields)
+                                // is changed in this state structure
+//    UCHAR8          info_id;    // Should be increased by 1 each time something is changed in info structure
+//    UCHAR8          config_id;  // Should be increased by 1 each time something is changed in config structure
+    BOOL8           ext_dev_connect_state[N_EXT_DEV];    // enum ext_dev_connect_state_e //verified
+    char            reserved_2[8];
+    PGM_INFO        local_pgm;  // Corresponds to the program currently being in the program memory
+} TA_STATE;
+
+
+// Universal inputs configuration, 4 bytes
+//changed in 1.24 to 1 byte
+typedef struct //verified
+{
+    UINT8           mode;       // enum input_mode_e, for digital inputs msb=1, for analog msb=0
+//    BOOL8           digital;    // FALSE = analog input, TRUE = digital input
+//    unsigned char   reserved[2];
+} UNI_CONFIG;
+
+
+// Counter inputs configuration, 4 bytes
+//changed in 1.24 to 1 byte
+typedef struct
+{
+    UINT8           mode;       // enum input_mode_e
+//    unsigned char   reserved[3];
+} CNT_CONFIG;
+
+
+// Config structure, 88 bytes
+//changed in 1.24 to 48 bytes
+typedef struct
+{
+    //UINT8           pgm_state_req;  // enum pgm_state_e
+    //char            reserved_1[3];
+    BOOL8           motor[N_MOTOR];//verified
+    UNI_CONFIG      uni[N_UNI];//verified
+    CNT_CONFIG      cnt[N_CNT];//verfied 1=normal, 0=inverted
+    char            reserved_2[32];
+} TA_CONFIG;
+
+
+// Input structure, 40 bytes (wrong! 44 bytes)
+//changed in 1.24 to 48 bytes
+typedef struct
+{
+    INT16           uni[N_UNI];//verified
+    BOOL8           cnt_in[N_CNT];//was INT16
+    INT16           counter[N_CNT];//verified
+    // Number of milliseconds during which the left display button is being kept pressed
+    INT16           display_button_left;//verified
+    // Number of milliseconds during which the right display button is being kept pressed
+    INT16           display_button_right;//verified
+    char            unknown[8];//new in 1.24
+    // Set to 1 by motor control if target position is reached
+    INT16           motor_pos_reached[N_MOTOR];//verified
+} TA_INPUT;
+
+
+// Output structure, 36 bytes
+//changed in 1.24 to 44 bytes, don't know what changed, 4 bytes added before duty. 4 after
+typedef struct
+{
+    // Counter reset requests
+    INT16           cnt_reset[N_CNT];//was BOOL8
+    // If not 0, synchronize this channel with the given channel (1:channel 0, ...)
+    UINT8           master[N_MOTOR];
+    // Selected motor PWM values
+    INT16           duty[N_PWM_CHAN];//verified
+    // Selected distane (counter value) at which motor shall stop
+    UINT16          distance[N_MOTOR];//verified
+    UINT16            reserved[4];//was char
+} TA_OUTPUT;
+
+
+// Display structure, 76 bytes
+typedef struct
+{
+    DISPLAY_MSG     display_msg;
+    DISPLAY_FRAME   display_frame;
+} TA_DISPLAY;
+
+//new in 1.24 message structure, 24 bytes
+typedef struct
+{
+    UINT16            index;
+    UINT16            status;
+    UINT16            length;
+    UINT8            hwid;
+    UINT8            subid;
+    UINT16            cmd;
+    UINT16            val;
+    UINT16            unknown2[6];//possibly another message or room for larger messages
+} TA_MESSAGE;
+
+//new in 1.24 message structure, 32 bytes, note: this struct is not preceded by a transferarea-ID
+typedef struct
+{
+    UINT16            result; //??? 1 for the first (empty) result, 2 for each real result, 5 for the last (empty) result.
+    BT_ADDR            bd_addr;
+    UINT16            unknown;
+    char            device_name[DEV_NAME_LEN + 1];
+    char            pad[1];
+    UINT32            unknown2;
+} TA_INQUIRY;
+
+// Change structure (only for ftMscLib), 8 bytes
+typedef struct
+{
+    char            reserved_1[2];
+    UINT8           ChangeStatus;
+    UINT8           ChangeUni;
+    UINT8           ChangeCntIn;
+    UINT8           ChangeCounter;
+    char            reserved_2[2];
+} TA_CHANGE;
+
+
+// 16-bit timers, 12 bytes
+typedef struct
+{
+    UINT16          Timer1ms;
+    UINT16          Timer10ms;
+    UINT16          Timer100ms;
+    UINT16          Timer1s;
+    UINT16          Timer10s;
+    UINT16          Timer1min;
+} TA_TIMER;
+
+
+// Hook table with pointers to the firmware functions,
+// that can be called by local program, 4 bytes
+typedef struct
+{
+    INT32   (*IsRunAllowed) (void);
+    UINT32  (*GetSystemTime)(enum TimerUnit unit);
+} TA_HOOK_TABLE;
+
+
+
+// ============================================================================
+//  Transfer Area (TA) of ROBO TX Controller (one part of TA_N_PARTS)
+// ============================================================================
+#define RESERVED_1_SIZE  4
+#define RESERVED_2_SIZE  28
+#define RESERVED_3_SIZE \
+    (512 - ( \
+    sizeof(TA_INFO)         + \
+    sizeof(TA_STATE)        + \
+    sizeof(TA_CONFIG)       + \
+    sizeof(TA_INPUT)        + \
+    sizeof(TA_OUTPUT)       + \
+    sizeof(TA_DISPLAY)      + \
+    RESERVED_1_SIZE         + \
+    sizeof(TA_CHANGE)       + \
+    sizeof(TA_TIMER)        + \
+    RESERVED_2_SIZE         + \
+    sizeof(TA_HOOK_TABLE)     \
+    ))
+
+
+typedef struct
+{
+    TA_INFO             info;           // info structure
+    TA_STATE            state;          // state structure
+    TA_CONFIG           config;         // config structure   
+    TA_INPUT            input;          // input structure
+    TA_OUTPUT           output;         // output structure
+    TA_DISPLAY          display;        // display structure
+
+    char                reserved_1[RESERVED_1_SIZE];
+
+    TA_CHANGE           change;         // change structure
+    TA_TIMER            timer;          // 16-bit timers
+
+    char                reserved_2[RESERVED_2_SIZE];
+
+    TA_HOOK_TABLE       hook_table;     // hook table with functions pointers
+
+    char                reserved_3[RESERVED_3_SIZE];
+} TA;
+
+
+#endif // __ROBO_TX_FW_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ft.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,31 @@
+#ifndef FT_H
+#define FT_H
+
+typedef unsigned char   BYTE;
+typedef unsigned short  USHORT;
+typedef unsigned int    DWORD;
+
+#pragma pack( push, 1 )
+typedef union {
+    BYTE    aucMsg[6];
+    struct {
+        BYTE    ucHwId;
+        BYTE    ucSubId;
+        union {
+            struct {
+                BYTE    ucB0;
+                BYTE    ucB1;
+                BYTE    ucB2;
+                BYTE    ucB3;
+            };
+            struct {
+                USHORT  uiMsgId;
+                USHORT  uiMsg;
+            } ;
+            DWORD   dw;
+        } ;
+    } ;
+} SMESSAGE;
+#pragma pack( pop )
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftErrCode.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,87 @@
+//=============================================================================
+//              |
+// Headerfile   |  ftErrCode.h
+//              |
+// Description  |  Definition of error codes
+//              |
+//-----------------------------------------------------------------------------
+// Disclaimer - Exclusion of Liability
+//
+// This software is distributed in the hope that it will be useful,but WITHOUT 
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
+// FITNESS FOR A PARTICULAR PURPOSE. It can be used an modified by anyone
+// free of any license obligations or authoring rights.
+//=============================================================================
+
+#ifndef __FTERRCODE_H__
+#define __FTERRCODE_H__
+
+//---   FTLIB Error Codes
+
+#define FTLIB_ERR_SUCCESS                   0x00000000L
+#define FTLIB_ERR_NO_MEMORY                 0xE0000100L
+
+#define FTLIB_ERR_FAILED                    0xE0001000L
+#define FTLIB_ERR_TIMEOUT                   0xE000100CL
+#define FTLIB_ERR_INVALID_PARAM             0xE0001018L
+
+#define FTLIB_ERR_SOME_DEVICES_ARE_OPEN     0xE0001101L
+#define FTLIB_ERR_DEVICE_IS_OPEN            0xE0001102L
+#define FTLIB_ERR_DEVICE_NOT_OPEN           0xE0001103L
+#define FTLIB_ERR_NO_SUCH_DEVICE_INSTANCE   0xE0001104L
+
+#define FTLIB_ERR_UNKNOWN_DEVICE_HANDLE     0xE0001283L
+#define FTLIB_ERR_LIB_IS_INITIALIZED        0xE0001286L
+#define FTLIB_ERR_LIB_IS_NOT_INITIALIZED    0xE0001287L
+#define FTLIB_ERR_THREAD_NOT_STARTABLE      0xE00012A0L
+#define FTLIB_ERR_THREAD_IS_RUNNING         0xE00012A5L
+#define FTLIB_ERR_THREAD_NOT_RUNNING        0xE00012A6L
+#define FTLIB_ERR_THREAD_SYNCHRONIZED       0xE00012AFL
+
+#define FTLIB_ERR_TIMEOUT_TA                0xE00012B0L
+#define FTLIB_ERR_CREATE_EVENT              0xE00012B1L
+#define FTLIB_ERR_CREATE_MM_TIMER           0xE00012B2L
+
+#define FTLIB_ERR_UPLOAD_FILE_NOT_OPEN      0xE0001400L
+#define FTLIB_ERR_UPLOAD_FILE_READ_ERR      0xE0001401L
+#define FTLIB_ERR_UPLOAD_INVALID_FSIZE      0xE0001402L
+#define FTLIB_ERR_UPLOAD_START              0xE0001403L
+#define FTLIB_ERR_UPLOAD_CANCELED           0xE0001404L
+#define FTLIB_ERR_UPLOAD_FAILED             0xE0001405L
+#define FTLIB_ERR_UPLOAD_TIMEOUT            0xE0001406L
+#define FTLIB_ERR_UPLOAD_ACK                0xE0001407L
+#define FTLIB_ERR_UPLOAD_NAK                0xE0001408L
+#define FTLIB_ERR_UPLOAD_DONE               0xE0001409L
+#define    FTLIB_ERR_UPLOAD_FLASHWRITE         0xE000140AL
+#define FTLIB_ERR_REM_CMD_FAILED            0xE000140BL
+#define FTLIB_ERR_REM_CMD_NOT_SUPPORTED     0xE000140CL
+#define FTLIB_ERR_FWUPD_GET_FILES           0xE000140DL
+#define FTLIB_ERR_FWUPD_NO_FILES            0xE000140EL
+
+#define FTLIB_ERR_ACCESS_DENIED             0xE0001905L
+#define FTLIB_ERR_OPEN_COM                  0xE0001906L
+#define FTLIB_ERR_INIT_COM                  0xE0001908L
+#define FTLIB_ERR_INIT_COM_TIMEOUT          0xE0001909L
+
+#define FTLIB_ERR_WRONG_HOSTNAME_LEN        0xE0002000L
+
+#define FTLIB_FWUPD_UPLOAD_START            0xE0003000L
+#define FTLIB_FWUPD_UPLOAD_DONE             0xE0003001L
+#define FTLIB_FWUPD_TIMEOUT                 0xE0003002L
+#define FTLIB_FWUPD_FLUSH_DISK              0xE0003003L
+#define FTLIB_FWUPD_CLEAN_DISK              0xE0003004L
+#define FTLIB_FWUPD_ERR_FILE_READ           0xE0003005L
+#define FTLIB_FWUPD_UPLOAD_FAILED           0xE0003006L
+#define FTLIB_FWUPD_STARTING                0xE0003007L
+#define FTLIB_FWUPD_FINISHED                0xE0003008L
+#define FTLIB_FWUPD_REM_COMMAND             0xE0003009L
+#define FTLIB_FWUPD_REM_TIMEOUT             0xE000300AL
+#define FTLIB_FWUPD_REM_FAILED              0xE000300BL
+#define FTLIB_FWUPD_IZ_STEPS                0xE000300CL
+#define FTLIB_FWUPD_STEP                    0xE000300DL
+
+
+#define FTLIB_ERR_UNKNOWN                   0xEFFFFFFFL
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlib.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,1213 @@
+/** @file */
+/*******************************************************************************  
+ *  (c) by Knobloch GmbH
+ *         Weedgasse 14
+ *         D-55234 Erbes-B&#65533;im                                    
+ *
+ *  Header:         FtLib.h          Headerfile for fischertechnik USB-Library
+ *
+ *  Version:        0.60
+ *  Date:           10. May 2006
+ *
+ *  Revision:
+ *  0.60:   10. May 2006
+ *          New Name: GetAnzFtUsbDevice()    --> GetNumFtUsbDevice()
+ *                    ClearFtMessagePuffer() --> ClearFtMessageBuffer()
+ ********************************************************************************/
+
+
+#ifndef _FT_LIBRARY_H_
+#define _FT_LIBRARY_H_
+
+/** \cond doxygen ignore start */
+#define DWORD unsigned
+#define BYTE unsigned char
+#define USHORT unsigned short int
+#define UINT unsigned int
+#define UCHAR unsigned char
+
+#define HANDLE int
+#define HWND int
+#define __stdcall 
+#define LPCSTR char *
+#define LPVOID void *
+/** \endcond doxygen ignore end */
+
+struct _ftdev;
+
+/// \brief Communication Area for ft-Device
+typedef struct _FT_TRANSFER_AREA
+{
+    /// \brief Digital Inputs Main Module
+    /// Base+0x00: | E8 | E7 | E6 | E5 | E4 | E3 | E2 | E1 |
+    unsigned char E_Main;
+
+    /// \brief Digital Inputs Extension Modules 1
+    /// Base+0x01: | E16| E15| E14| E13| E12| E11| E10| E9 |
+    unsigned char E_Sub1;
+    /// \brief Digital Inputs Extension Modules 2
+    /// Base+0x02: | E24| E23| E22| E21| E20| E19| E18| E17|
+    unsigned char E_Sub2;
+    /// \brief Digital Inputs Extension Modules 3
+    /// Base+0x03: | E32| E31| E30| E29| E28| E27| E26| E25|
+    unsigned char E_Sub3;
+
+    /// \brief Reserved
+    /// Base+0x04..0x0B
+    unsigned char rsvd1[8];
+
+    /// \brief Abstandsensoren (1=detektiert)
+    /// Base+0x0C: |  0 |  0 |  0 |  0 |  0 |  0 | D2 | D1 |
+    unsigned char Distance;
+
+    /// \brief Base+0x0D: reserved
+    unsigned char rsvd2;
+
+    /// \brief IR-Receiver input code 
+    ///
+    /// Base+0x0E: | 0 | 0 | 0 | C | T | T | T | T
+    /// C = Code: 0 = Code 1 active, 1 = Code 2 active
+    /// TTTT = Keycode 0..11
+    /// Arangement of keys on Transmitter
+    ///   1        8
+    ///   2     7
+    ///   3          10
+    ///   4      9
+    ///   5        11
+    ///   6
+    /// Taste 1 = M3 right
+    /// Taste 2 = M3 left
+    /// Taste 3 = Speed. M1
+    /// Taste 4 = Speed. M2
+    /// Taste 5 = Speed. M3
+    /// Taste 6 = Code 2
+    /// Taste 7 = M1 backward
+    /// Taste 8 = M1 forward
+    /// Taste 9 = M2 left
+    /// Taste 10 = M2 right
+    /// Taste 11 = Code 1
+    unsigned char IRKeys;
+
+    /// \brief Base+0x0F: | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
+    unsigned char res_1;
+
+    /// \brief Analoginput of main module
+    ///
+    /// 8x 16 Bit, Range 0..1023, L:H Format (intel) )
+    /// Base+0x10..0x11: AX (Master Modul)
+    unsigned short AX;
+    /// \brief Analoginput of main module
+    ///
+    /// 8x 16 Bit, Range 0..1023, L:H Format (intel) )
+    /// Base+0x12..0x13: AY (Master Modul)
+    unsigned short AY;
+    /// \brief Analoginput of main module
+    ///
+    /// 8x 16 Bit, Range 0..1023, L:H Format (intel) )
+    /// Base+0x14..0x15: A1 (Master Modul)
+    unsigned short A1;
+    /// \brief Analoginput of main module
+    ///
+    /// 8x 16 Bit, Range 0..1023, L:H Format (intel) )
+    /// Base+0x16..0x17: A2 (Master Modul)
+    unsigned short A2;
+    /// \brief Analoginput of main module
+    ///
+    /// 8x 16 Bit, Range 0..1023, L:H Format (intel) )
+    /// Base+0x18..0x19: AZ (Master Modul, vom SLAVE-Modul-BUS)
+    unsigned short AZ;
+    /// \brief Analoginput of main module
+    ///
+    /// 8x 16 Bit, Range 0..1023, L:H Format (intel) )
+    /// Base+0x1A..0x1B: AV (Versorgungsspannung Master Modul)
+    unsigned short AV;
+    /// \brief Analoginput of main module
+    ///
+    /// 8x 16 Bit, Range 0..1023, L:H Format (intel) )
+    /// Base+0x1C..0x1D: D1 (Abstandssensor 1)
+    unsigned short D1;
+    /// \brief Analoginput of main module
+    ///
+    /// 8x 16 Bit, Range 0..1023, L:H Format (intel) )
+    /// Base+0x1E..0x1F: D2 (Abstandssensor 2)
+    unsigned short D2;
+
+    /// \brief Analoginput of slave module 1
+    ///
+    /// Base+0x20..0x21: AX (Slave 1 Modul)
+    unsigned short AXS1;
+    /// \brief Analoginput of slave module 1
+    ///
+    /// Base+0x22..0x23: AX (Slave 2 Modul)
+    unsigned short AXS2;
+    /// \brief Analoginput of slave module 1
+    ///
+    /// Base+0x24..0x25: AX (Slave 3 Modul)
+    unsigned short AXS3;
+
+    /// \brief Detection limit for distance sensor 1 ( to generate digital from analog input )
+    ///
+    /// Base+0x26..0x27: DS1
+    unsigned short DS1;
+    /// \brief Detection limit for distance sensor 2 ( to generate digital from analog input )
+    ///
+    /// Base+0x28..0x29: DS2
+    unsigned short DS2;
+
+    /// \brief Reserved
+    /// Base+0x2A..0x2B
+    unsigned short ZE;
+
+    /// \brief Reserved
+    /// Base+0x2C..0x2F
+    unsigned char rsvd3[4];
+
+    /// \brief 16-Bit Timer
+    ///
+    /// Base+0x30..0x31: Timer 1ms Inkrement
+    unsigned short Timer1ms;
+    /// \brief 16-Bit Timer
+    ///
+    /// Base+0x32..0x33: Timer 10ms Inkrement
+    unsigned short Timer10ms;
+    /// \brief 16-Bit Timer
+    ///
+    /// Base+0x34..0x35: Timer 100ms Inkrement
+    unsigned short Timer100ms;
+    /// \brief 16-Bit Timer
+    ///
+    /// Base+0x36..0x37: Timer 1s Inkrement
+    unsigned short Timer1s;
+    /// \brief 16-Bit Timer
+    ///
+    /// Base+0x38..0x39: Timer 10s Inkrement
+    unsigned short Timer10s;
+    /// \brief 16-Bit Timer
+    ///
+    /// Base+0x3A..0x3B: Timer 1min Inkrement
+    unsigned short Timer1min;
+
+    /// \brief Reserved
+    /// Base+0x3C..0x3D
+    unsigned short res_bF;
+    /// \brief Reserved
+    /// Base+0x3E
+    unsigned char res_bT;
+
+    /// \brief Reserved
+    /// Base+0x3F
+    unsigned char rsvd4[1];
+
+    /// \brief Outputs of the main module ( polarity )
+    ///
+    /// Base+0x40: |M4B |M4A |M3B |M3A |M2B |M2A |M1B |M1A |
+    unsigned char M_Main;
+    /// \brief Outputs of extension module 1
+    ///
+    /// Base+0x41: |M8B |M8A |M7B |M7A |M6B |M6A |M5B |M5A |
+    unsigned char M_Sub1;
+    /// \brief Outputs of extension module 2
+    ///
+    /// Base+0x42: |M12B|M12A|M11B|M11A|M10B|M10A|M9B |M9A |
+    unsigned char M_Sub2;
+    /// \brief Outputs of extension module 3
+    ///
+    /// Base+0x43: |M16B|M16A|M15B|M15A|M14B|M14A|M13B|M13A|
+    unsigned char M_Sub3;
+
+    /// \brief Reserved
+    /// Base+0x44..0x47
+    unsigned char rsvd5[4];
+
+    ///\brief Outputs of the main module ( energy saver mode )
+    ///
+    /// 1 = energy saver mode, 0 = operational, PowerUp = 1
+    /// Base+0x48: | 0  | 0  | 0  | 0  | M4 | M3 | M2 | M1 |
+    unsigned char MES_Main;
+    /// \brief Outputs of extension module 1 ( energy saver mode )
+    ///
+    /// Base+0x49: | 0  | 0  | 0  | 0  | M8 | M7 | M6 | M5 |
+    unsigned char MES_Sub1;
+    /// \brief Outputs of extension module 2 ( energy saver mode )
+    ///
+    /// Base+0x4A: | 0  | 0  | 0  | 0  | M12| M11| M10| M9 |
+    unsigned char MES_Sub2;
+    /// \brief Outputs of extension module 3 ( energy saver mode )
+    ///
+    /// Base+0x4B: | 0  | 0  | 0  | 0  | M16| M15| M14| M13|
+    unsigned char MES_Sub3;
+
+    /// \brief Reserved
+    /// Base+0x4C
+    unsigned char rsvd6[1];
+
+    /// \brief Reserved
+    /// Base+0x4D:
+    unsigned char reserved_l1;
+    /// \brief Reserved
+    /// Base+0x4E: 
+    unsigned char reserved_l2;
+    /// \brief Reserved
+    /// Base+0x4F: 
+    unsigned char reserved_l3;
+
+    /// \brief Outputs of the main module (PWM values, range =0..7)
+    ///
+    /// Base+0x50: M1A
+    /// Base+0x51: M1B
+    /// Base+0x52: M2A
+    /// Base+0x53: M2B
+    /// Base+0x54: M3A
+    /// Base+0x55: M3B
+    /// Base+0x56: M4A
+    /// Base+0x57: M4B
+    unsigned char MPWM_Main[8];
+
+    /// \brief Outputs of slave module 1 (PWM values, range =0..7)
+    ///
+    /// Base+0x58: M5A
+    /// Base+0x59: M5B
+    /// Base+0x5A: M6A
+    /// Base+0x5B: M6B
+    /// Base+0x5C: M7A
+    /// Base+0x5D: M7B
+    /// Base+0x5E: M8A
+    /// Base+0x5F: M8B
+    unsigned char MPWM_Sub1[8];
+
+    /// \brief Outputs of slave module 2 (PWM values, range =0..7)
+    ///
+    /// Base+0x60: M9A
+    /// Base+0x61: M9B
+    /// Base+0x62: M10A
+    /// Base+0x63: M10B
+    /// Base+0x64: M11A
+    /// Base+0x65: M11B
+    /// Base+0x66: M12A
+    /// Base+0x67: M12B
+    unsigned char MPWM_Sub2[8];
+
+    /// \brief Outputs of slave module 3 (PWM values, range =0..7)
+    ///
+    /// Base+0x68: M13A
+    /// Base+0x69: M13B
+    /// Base+0x6A: M14A
+    /// Base+0x6B: M14B
+    /// Base+0x6C: M15A
+    /// Base+0x6D: M15B
+    /// Base+0x6E: M16A
+    /// Base+0x6F: M16B
+    unsigned char MPWM_Sub3[8];
+
+    /// \brief Reserved
+    /// Base+0x70..0x8F
+    unsigned char rsvd7[32];
+
+
+    /// \brief Analoginput of slave module 1 (Update-Time: 20ms)
+    ///
+    /// Base+0x90..0x91: A1 (Slave 1 Modul)
+    unsigned short A1S1;
+    /// \brief Analoginput of slave module 2 (Update-Time: 20ms)
+    ///
+    /// Base+0x92..0x93: A1 (Slave 2 Modul)
+    unsigned short A1S2;
+    /// \brief Analoginput of slave module 3 (Update-Time: 20ms)
+    ///
+    /// Base+0x94..0x95: A1 (Slave 3 Modul)
+    unsigned short A1S3;
+
+    /// \brief Analoginput of slave modules 1 (Update-Time: 20ms)
+    ///
+    /// Base+0x96..0x97: AV (Slave 1 Modul)
+    unsigned short AVS1;
+    /// \brief Analoginput of slave modules 2 (Update-Time: 20ms)
+    ///
+    /// Base+0x98..0x99: AV (Slave 2 Modul)
+    unsigned short AVS2;
+    /// \brief Analoginput of slave modules 3 (Update-Time: 20ms)
+    ///
+    /// Base+0x9A..0x9B: AV (Slave 3 Modul)
+    unsigned short AVS3;
+
+    /// \brief Reserved
+    /// Base+0x9C..0x9F
+    unsigned char rsvd8[4];
+
+    /// \brief Reserved
+    /// Base+0xA0..0xA1: AX (Interface) Resistor-Value (0..5662 Ohm)
+    unsigned short AX_R;
+
+    /// \brief Base+0xA2..0xA3: AY (Interface) Resistor-Value (0..5662 Ohm)
+    unsigned short AY_R;
+
+    /// \brief Base+0xA4..0xA5: AX (Slave 1 Modul) Resistor-Value (0..5662 Ohm)
+    unsigned short AXS1_R;
+
+    /// \brief Base+0xA6..0xA7: AX (Slave 2 Modul) Resistor-Value (0..5662 Ohm)
+    unsigned short AXS2_R;
+
+    /// \brief Base+0xA8..0xA9: AX (Slave 3 Modul) Resistor-Value (0..5662 Ohm)
+    unsigned short AXS3_R;
+
+    /// \brief Reserved
+    /// Base+0xAA..0xDF
+    unsigned char rsvd10[54];
+
+    /// \brief Operation mode 
+    /// Base+0xE0: 0x00=online, 0x01=binary download
+    unsigned char Mode;
+
+    /// \brief Output PWM update (0x01=always, 0x02=once)
+    /// Base+0xE1: | 0  | 0  | 0  | 0  | 0  | 0  |ONCE|ALWA|
+    unsigned char MPWM_Update;
+
+    /// \brief Base+0xE2
+    ///
+    /// 0 = Transfer Area closed
+    /// 1 = Transfer Area is working (Library Thread is running)
+    unsigned char TransferAktiv;
+
+    /// \brief Reserved
+    /// Base+0xE3..0xE5
+    unsigned char rsvd11[3];
+
+    /// \brief I/O Extension modules connected
+    ///
+    /// Base+0xE6: | 0  | 0  | 0  | 0  | 0  | S2 | S1 | S0 |
+    /// S2..S0 = Number of connected I/O Extension Modules
+    unsigned char BusModules;
+
+    /// \brief Slot 1 connected extension module type
+    /// Base+0xE7: ?
+    unsigned char SlotModule1;
+
+    /// \brief Slot 2 connected extension module type
+    /// Base+0xE8: ?
+    unsigned char SlotModule2;
+
+    /// \brief Reserved
+    /// Base+0xE9..0xEF
+    unsigned char rsvd12[7];
+
+
+    /// \brief Change Bytes
+    ///
+    /// 1 = EG (Master or Slave 1..3) have changed
+    /// The Application must read and change this byte to "0"
+    /// Base+0xF0: 
+    unsigned char ChangeEg;
+
+    /// \brief 1 = Analog Inputs (Master AX, AY, A1, A2, AV, AZ or Extension 1..3 AX,AY,AV) 
+    ///
+    /// or RfPower, RfError have changed
+    /// The Application must read and change this byte to "0"
+    /// Base+0xF1: 
+    unsigned char ChangeAn;
+
+    /// \brief 1 = Infrared Input (Robo-IF) or RfStatus have changed
+    ///
+    /// The Application must read and change this byte to "0"
+    /// Base+0xF2: 
+    unsigned char ChangeIr;
+
+
+    /// \brief Reserved
+    /// Base+0xF3..0xFF
+    unsigned char rsvd13[13];
+
+
+    /// \brief Digital inputs as 16 bit values
+    ///
+    /// Base+0x100..0x101  Input 1 (Master-Modul)
+    /// Base+0x102..0x103  Input 2 (Master-Modul)
+    /// Base+0x104..0x105  Input 3 (Master-Modul)
+    /// Base+0x106..0x107  Input 4 (Master-Modul)
+    /// Base+0x108..0x109  Input 5 (Master-Modul)
+    /// Base+0x10A..0x10B  Input 6 (Master-Modul)
+    /// Base+0x10C..0x10D  Input 7 (Master-Modul)
+    /// Base+0x10E..0x10F  Input 8 (Master-Modul)
+    unsigned short E16_Main[8];
+    /// \brief Digital inputs as 16 bit values
+    ///
+    /// Base+0x110..0x111  Input 9 (Slave1-Modul)
+    /// Base+0x112..0x113  Input 10 (Slave1-Modul)
+    /// Base+0x114..0x115  Input 11 (Slave1-Modul)
+    /// Base+0x116..0x117  Input 12 (Slave1-Modul)
+    /// Base+0x118..0x119  Input 13 (Slave1-Modul)
+    /// Base+0x11A..0x11B  Input 14 (Slave1-Modul)
+    /// Base+0x11C..0x11D  Input 15 (Slave1-Modul)
+    /// Base+0x11E..0x11F  Input 16 (Slave1-Modul)
+    unsigned short E16_Sub1[8];
+    /// \brief Digital inputs as 16 bit values
+    ///
+    /// Base+0x120..0x121  Input 17 (Slave2-Modul)
+    /// Base+0x122..0x123  Input 18 (Slave2-Modul)
+    /// Base+0x124..0x125  Input 19 (Slave2-Modul)
+    /// Base+0x126..0x127  Input 20 (Slave2-Modul)
+    /// Base+0x128..0x129  Input 21 (Slave2-Modul)
+    /// Base+0x12A..0x12B  Input 22 (Slave2-Modul)
+    /// Base+0x12C..0x12D  Input 23 (Slave2-Modul)
+    /// Base+0x12E..0x12F  Input 24 (Slave2-Modul)
+    unsigned short E16_Sub2[8];
+    /// \brief Digital inputs as 16 bit values
+    ///
+    /// Base+0x130..0x131  Input 25 (Slave3-Modul)
+    /// Base+0x132..0x133  Input 26 (Slave3-Modul)
+    /// Base+0x134..0x135  Input 27 (Slave3-Modul)
+    /// Base+0x136..0x137  Input 28 (Slave3-Modul)
+    /// Base+0x138..0x139  Input 29 (Slave3-Modul)
+    /// Base+0x13A..0x13B  Input 30 (Slave3-Modul)
+    /// Base+0x13C..0x13D  Input 31 (Slave3-Modul)
+    /// Base+0x13E..0x13F  Input 32 (Slave3-Modul)
+    unsigned short E16_Sub3[8];
+    /// \brief Distance sensors D1 & D2 (Master Modul)
+    ///
+    /// Base+0x140..0x141  Distance sensor D1 (Master-Modul)
+    /// Base+0x142..0x143  Distance sensor D2 (Master-Modul)
+    unsigned short Distance16[2];
+
+    /// \brief Reserved
+    /// Base+0x144..0x14F
+    unsigned char rsvd14[12];
+ 
+    /// \brief IR-Keys as 16 bit values (independent of code)
+    ///
+    /// Base+0x150..0x151  IR Taste  1 (M3R)
+    /// Base+0x152..0x153  IR Taste  2 (M3L)
+    /// Base+0x154..0x155  IR Taste  3 (M1)
+    /// Base+0x156..0x157  IR Taste  4 (M2)
+    /// Base+0x158..0x159  IR Taste  5 (M3)
+    /// Base+0x15A..0x15B  IR Taste  6 (Code2)
+    /// Base+0x15C..0x15D  IR Taste  7 (M1BW)
+    /// Base+0x15E..0x15F  IR Taste  8 (M1FW)
+    /// Base+0x160..0x161  IR Taste  9 (M2L)
+    /// Base+0x162..0x163  IR Taste 10 (M2R)
+    /// Base+0x164..0x165  IR Taste 11 (Code1)
+    unsigned short IRKeys16[11];
+    /// \brief Reserved
+    /// Base+0x166..0x16F
+    unsigned char rsvd15[10];
+
+    /// \brief IR-Keys as 16 bit values (code 1)
+    ///
+    /// Base+0x170..0x171  IR Taste  1 (M3R)    Code1
+    /// Base+0x172..0x173  IR Taste  2 (M3L)    Code1
+    /// Base+0x174..0x175  IR Taste  3 (M1)     Code1
+    /// Base+0x176..0x177  IR Taste  4 (M2)     Code1
+    /// Base+0x178..0x179  IR Taste  5 (M3)     Code1
+    /// Base+0x17A..0x17B  always 0
+    /// Base+0x17C..0x17D  IR Taste  7 (M1BW)   Code1
+    /// Base+0x17E..0x17F  IR Taste  8 (M1FW)   Code1
+    /// Base+0x180..0x181  IR Taste  9 (M2L)    Code1
+    /// Base+0x182..0x183  IR Taste 10 (M2R)    Code1
+    /// Base+0x184..0x185  IR Taste 11 (Code1)  Code1 
+    unsigned short IRKeys16Code1[11];
+
+    /// \brief Reserved
+    ///
+    /// Base+0x186..0x18F
+    unsigned char rsvd16[10];
+ 
+    /// \brief IR-Keys as 16 bit values (code 1)
+    ///
+    /// Base+0x190..0x191  IR Taste  1 (M3R)    Code2
+    /// Base+0x192..0x193  IR Taste  2 (M3L)    Code2
+    /// Base+0x194..0x195  IR Taste  3 (M1)     Code2
+    /// Base+0x196..0x197  IR Taste  4 (M2)     Code2
+    /// Base+0x198..0x199  IR Taste  5 (M3)     Code2
+    /// Base+0x19A..0x19B  IR Taste  6 (Code2)  Code2 
+    /// Base+0x19C..0x19D  IR Taste  7 (M1BW)   Code2
+    /// Base+0x19E..0x19F  IR Taste  8 (M1FW)   Code2
+    /// Base+0x1A0..0x1A1  IR Taste  9 (M2LE)   Code2
+    /// Base+0x1A2..0x1A3  IR Taste 10 (M2RI)   Code2
+    /// Base+0x1A4..0x1A5  always 0
+    unsigned short IRKeys16Code2[11];
+
+    /// \brief Reserved
+    ///
+    /// Base+0x1A6..0x1AF
+    unsigned char rsvd17[10];
+    
+    /// \brief 1 = RfError (0x1B4..0x1B5) is > 25. We think, Rf connection (only Onlinemodus) is lost 
+    ///
+    /// Base+0x1B0..0x1B1
+    unsigned short RfStatus;
+
+    /// \brief Signal Power of the RF Signal entering the RF input (only Onlinemodus, 7 bit, 0..127)  
+    ///
+    /// Base+0x1B2..0x1B3
+    unsigned short RfPower;
+
+    /// \brief Rf-Error Count (0..250)  
+    ///
+    /// Base+0x1B4..0x1B5
+    unsigned short RfError;
+
+    /// \brief Number of Messages inside the Buffer
+    ///
+    /// Base+0x1B6..0x1B7
+    unsigned short MsgNumInBuffer;
+
+    /// \brief Number of Interface-RF-Modul if installed or "-1" if not installed
+    ///
+    /// Base+0x1B8..0x1B9
+    unsigned short RfModulNr;
+
+    /// \brief Reserved
+    /// Base+0x1BA..0x1BB
+    unsigned char rsvd19[2];
+
+    /// \brief Reserved for Internal Use
+    /// Base+0x1BC..0x1BF
+    DWORD dwTC;
+
+    /// \brief Reserved
+    /// Base+0x1C0..0x1FF
+    unsigned char rsvd20[64];
+
+} FT_TRANSFER_AREA;
+/** \fn typedef FT_TRANSFER_AREA
+ *  Type definition for the transfer area.
+ */
+
+struct ft_handle_devices;//forward declaration
+typedef struct ft_handle_devices *FT_HANDLE;
+
+/** \cond doxygen ignore start */
+
+bool test_and_set(int& s);
+void increment(int& s);
+
+FT_HANDLE OpenFtCommDevice(char *sDevice, long int dwTyp, long int dwZyklus);
+int GetFtStatus(FT_HANDLE hFt, int *num);
+DWORD GetFtDeviceTypeString(FT_HANDLE hft, char *dest, int len);
+char *GetLibVersionStrg();
+long int SetRFMode(FT_HANDLE hFt, long int frequency, long int callSign);
+long int GetRFMode(FT_HANDLE hFt, long int *frequency, long int *callSign);
+long int SetRealSerial(FT_HANDLE hFt, unsigned char bOn);
+char IsFtInterfaceConnected(FT_HANDLE hFt);
+
+                                                // Numbers from GetFtDeviceTyp()
+#define     NO_FT_DEVICE                0       // No ft Device connected
+#define     FT_AUTO_TYPE                1       // Search for Device
+#define     FT_INTELLIGENT_IF           10      // FT-Intelligent Interface connect (serial)
+#define     FT_INTELLIGENT_IF_SLAVE     20      // FT-Intelligent Interface with Extension connect (serial)
+#define     FT_ROBO_IF_IIM              50      // FT-Robo Interface with Intelligent-Interface-Modus connect (serial)
+#define     FT_ROBO_IF_USB              60      // FT-Robo Interface connect with USB-Port
+#define     FT_ROBO_IF_COM              70      // FT-Robo Interface connect with COM- (serial-) Port
+#define     FT_ROBO_IF_OVER_RF          80      // FT-Robo Interface connect over RF-Data-Link
+#define     FT_ROBO_IO_EXTENSION        90      // FT-Robo I/O-Extension
+#define     FT_ROBO_RF_DATA_LINK        110     // FT-Robo RF Data Link
+#define     FT_MAX_TYP_NUMBER           999     // Max Typ Number
+
+
+#define     FT_ANALOG_CYCLE             5       // Standard: 5*Read Digital Inputs, then EX, EY
+                                                // Only for old Intelligent Interface { for OpenFtCommDevice() }
+
+
+#define     PORT_NONE                   0
+#define     PORT_COM                    1       // Standard: COM1
+#define     PORT_COM1                   1
+#define     PORT_COM2                   2
+#define     PORT_COM3                   3
+#define     PORT_COM4                   4
+#define     PORT_USB                    50
+
+                                                // Moduletypes for Robo Interface
+#define     MODULE_NOT_INSTALLED        0       // Not installed
+#define     MODULE_RF1                  1       // RF Data Link Module is installed
+
+
+#define     LEN_STRG1                   30      // Length of SN / FW Strings
+#define     LEN_STRG2                   255     // Length of Name-Strigs
+#define     ANZ_DISTANCE_TYPES          2       // Number of supported Distance-Modes
+#define     LEN_DIST_TYPE_NAMES         30      // Lenght of Mode-Names
+#define     LEN_DIST_VAR_NAMES          20      // Lenght of Variable-Names
+#define     NAME_LEN                    85      // Lenght of Prog-Names
+
+
+#define     MEM_FLASH1                  0       // Use Memory FLASH-1 Block
+#define     MEM_FLASH2                  1       // Use Memory FLASH-2 Block
+#define     MEM_RAM                     2       // Use Memory RAM Block
+#define     MEM_NO_ACCESS               -1      // No Memory Select (for SetFtProgramActiv() )
+#define     DOWNLOAD_PROG_NAMELEN       80      // Max. 80 characters/bytes for the programname
+
+                                                // Values for "dwParameter" from DownloadFtProgram() 
+#define     PROG_TYP_NORMAL             1       // Program can bei Start with Software and Switch
+#define     PROG_TYP_AUTOSTART          2       // Program is startable at Power-On
+
+
+                                                // COM-Modes for SetFtDeviceCommMode()
+#define     IF_COM_ONLINE               1       // Online Mode
+#define     IF_COM_MESSAGE              3       // Messagemode
+#define     IF_COM_DATA                 4       // Datatransfer
+#define     IF_COM_PARAMETER            5       // Get Mode
+
+
+                                                // Message-System
+#define     MSG_HWID_SELF               0       // Message for himself
+#define     MSG_HWID_SER                1       // Message for the Robo-Interface serial port
+#define     MSG_HWID_RF                 2       // Message for other Interfaces (over RF)
+#define     MSG_HWID_RF_SELF            3       // Message for other Interfaces (over RF) and for himself (back over RF)
+
+#define     MSG_BUFF_SER                1       // SER-Messagebuffer (for ClearRfMessage() )
+#define     MSG_BUFF_RF                 2       // RF-Messagebuffer (for ClearRfMessage() )
+#define     MSG_BUFF_SELF               4       // SELF-Messagebuffer (for ClearRfMessage() )
+
+#define     MSG_SEND_NORMAL             0       // Message send "normal"
+#define     MSG_SEND_OTHER_THAN_LAST    1       // Message send "if not the same as the last message"
+#define     MSG_SEND_IF_NOT_PRESENT     2       // Message send "if not present in the send buffer"
+
+
+
+                                                // Interface Distancesensor-Inputs Type
+#define     IF_DS_INPUT_VOLTAGE         0       // Voltage
+#define     IF_DS_INPUT_DISTANCE        1       // Distance
+#define     IF_DS_INPUT_TOL_STD         20      // Toleranz (Standard)
+#define     IF_DS_INPUT_REP_STD         3       // Repeat (Standard)
+
+
+#ifndef FT_H
+    #pragma pack( push, 1 )
+    typedef union
+    {
+        BYTE    aucMsg[6];
+
+        struct 
+        {
+            BYTE    ucHwId;       
+            BYTE    ucSubId;       
+            BYTE    ucB0;
+            BYTE    ucB1;
+            BYTE    ucB2;
+            BYTE    ucB3;
+        } B;
+
+        struct 
+        {
+            BYTE    ucHwId;       
+            BYTE    ucSubId;       
+            USHORT  uiMsgId;        
+            USHORT  uiMsg;
+        } W;
+
+        struct 
+        {
+            BYTE    ucHwId;       
+            BYTE    ucSubId;       
+            DWORD   dw;
+        } L;
+    } SMESSAGE;
+    #pragma pack( pop )
+#endif
+
+    //typedef void * FT_HANDLE;
+    typedef void (*DATA_UPDATE_CALLBACK)(void* Context);
+    typedef void (*MSG_UPDATE_CALLBACK)(SMESSAGE *);
+
+
+
+    // Important: 
+    // Initialise all unused Variables in this Structure with "NULL"
+    //
+    // Every Time the driver reads new information from the Device
+    // the Library checks this structure 
+    typedef struct _NOTIFICATION_EVENTS 
+    {
+        // Callback-Procedure
+        DATA_UPDATE_CALLBACK NotificationCallback;  // Pointer to the Callback-Procedure
+        void* Context;                              // Pointer to the Context for the Callback-Procedure
+
+        // for SetEvent()
+        HANDLE hEvent;
+
+        // for posting a Message (PostMessage() with wParam & lParam = 0)
+        HWND    WindowsHandle;                      // handle to the destination window
+        DWORD   Message;                            // message ID
+
+
+        // Callback-Procedure for Messaging
+        MSG_UPDATE_CALLBACK     CallbackMessage;    // Pointer to the Callback-Procedure for Receiving Messages
+
+    } 
+    NOTIFICATION_EVENTS;
+
+
+
+
+    typedef struct _FT_SERIAL_NUMBER
+    {
+        DWORD   dwSn;                   // actually Serial Number at Power On
+        DWORD   dwSn1;                  // Serial Number-1
+        DWORD   dwSn2;                  // Serial Number-2
+        DWORD   dwSnAktiv;              // Serial Number Activ (1/2) for next Power On
+    } FT_SERIAL_NUMBER;
+
+
+
+    typedef struct _FT_DISTANCE         // Robo Interface Distance Sensor
+    {
+        unsigned char   aDistModeNames[LEN_DIST_TYPE_NAMES];    // RO   Names for the Modes  
+
+        DWORD           dwEnableDisVal1;                        // RO   1=Ask for Distance Value 1
+        unsigned char   aDisVal1Name[LEN_DIST_VAR_NAMES];       // RO   Value 1 Name
+        DWORD           dwDisVal1;                              // RW   Value 1
+
+        DWORD           dwEnableDisVal2;                        // RO   1=Ask for Distance Value 2
+        unsigned char   aDisVal2Name[LEN_DIST_VAR_NAMES];       // RO   Value 2 Name
+        DWORD           dwDisVal2;                              // RW   Value 2
+
+        DWORD           dwEnableDisVal3;                        // RO   1=Ask for Distance Value 3
+        unsigned char   aDisVal3Name[LEN_DIST_VAR_NAMES];       // RO   Value 3 Name
+        DWORD           dwDisVal3;                              // RW   Value 3
+
+        DWORD           dwEnableDisVal4;                        // RO   1=Ask for Distance Value 4
+        unsigned char   aDisVal4Name[LEN_DIST_VAR_NAMES];       // RO   Value 4 Name
+        DWORD           dwDisVal4;                              // RW   Value 4
+
+        DWORD           dwEnableDisVal5;                        // RO   1=Ask for Distance Value 5
+        unsigned char   aDisVal5Name[LEN_DIST_VAR_NAMES];       // RO   Value 5 Name
+        DWORD           dwDisVal5;                              // RW   Value 5
+
+        DWORD           dwEnableDisVal6;                        // RO   1=Ask for Distance Value 6
+        unsigned char   aDisVal6Name[LEN_DIST_VAR_NAMES];       // RO   Value 6 Name
+        DWORD           dwDisVal6;                              // RW   Value 6
+
+        DWORD           dwEnableDisVal7;                        // RO   1=Ask for Distance Value 7
+        unsigned char   aDisVal7Name[LEN_DIST_VAR_NAMES];       // RO   Value 7 Name
+        DWORD           dwDisVal7;                              // RW   Value 7
+
+        DWORD           dwEnableDisVal8;                        // RO   1=Ask for Distance Value 8
+        unsigned char   aDisVal8Name[LEN_DIST_VAR_NAMES];       // RO   Value 8 Name
+        DWORD           dwDisVal8;                              // RW   Value 8
+    } FT_DISTANCE;
+
+
+
+    typedef union _FT_SETTING
+    {
+        struct                              // RO = Read Only, RW = Read / Write
+        {
+            DWORD   dwIfTyp;                // RO   Type of connected Device
+                                            //      possible Values:       
+                                            //          NO_FT_DEVICE            no answer from the Device - is it gone ?
+                                            //          FT_INTELLIGENT_IF       FT-Intelligent Interface connect (serial)
+                                            //          FT_ROBO_IF_IIM          FT-Robo Interface with Intelligent-Interface-Modus connect (serial)
+                                            //          FT_ROBO_IF_USB          FT-Robo Interface connect with USB-Port
+                                            //          FT_ROBO_IF_COM          FT-Robo Interface connect with COM- (serial-) Port
+                                            //          FT_ROBO_IO_EXTENSION    FT-Robo I/O-Extension
+                                            //          FT_ROBO_RF_DATA_LINK    FT-Robo RF Data Link
+                                            //             FT_ROBO_IF_OVER_RF   FT-Robo Interface connect over RF-Data-Link
+
+                                            // Serial numbers section
+            DWORD   dwSn;                   // RO   actually Serial Number at Power On
+            DWORD   dwSn1;                  // RW   Serial Number-1             (only FT-Robo Products)
+            DWORD   dwSn2;                  // RO   Serial Number-2             (only FT-Robo Products)
+            DWORD   dwSnAktiv;              // RW   Set Serial Number Activ (1/2) for next Power On
+
+            DWORD   dwFw;                       // RO   Is Firmware Version for this product (only FT-Robo Products)
+
+            unsigned char aSnStrg[LEN_STRG1];   // RO   String with Serialnumber    (only FT-Robo Products)
+            unsigned char aSn1Strg[LEN_STRG1];  // RO   String with Serialnumber1   (only FT-Robo Products)
+            unsigned char aSn2Strg[LEN_STRG1];  // RO   String with Serialnumber2   (only FT-Robo Products)
+            unsigned char aFwStrg[LEN_STRG1];   // RO   String with Firmware        (only FT-Robo Products)
+            unsigned char aSNaStrg[LEN_STRG2];  // RO   String with Short-Name      (only FT-Robo Products)
+            unsigned char aLNaStrg[LEN_STRG2];  // RO   String with Long-Name       (only FT-Robo Products)
+
+            DWORD   dwFwRoboIfVerAtLibIsMade;   // RO   Robo-If Firmware Version as this Lib is made
+            DWORD   dwFwIoExtVerAtLibIsMade;    // RO   IO-Extension Firmware Version as this Lib is made
+            DWORD   dwFwRfDataVerAtLibIsMade;   // RO   RF-DataLink Firmware Version as this Lib is made
+            unsigned char aFwRoboIfVerAtLibIsMadeStrg[LEN_STRG1];   // RO   String with Robo-If Firmware Version as this Lib is made
+            unsigned char aFwIoExtVerAtLibIsMadeStrg[LEN_STRG1];    // RO   String with IO-Extension Firmware Version as this Lib is made
+            unsigned char aFwRfDataVerAtLibIsMadeStrg[LEN_STRG1];   // RO   String with Rf-Data-Link Firmware Version as this Lib is made
+                                            
+            DWORD   dwReserved;                 // Reserved for later use 
+
+
+                                                // Output Section
+            DWORD   dwOutputAutoOff[4];         // RW   M1=[0]...M4=[3] Energy saver: 
+                                                //      "1" = "Power Off" motor driver when both outputs logical "0" (reduces Energy)
+                                                //      "0" = do not automatically disable the motor driver
+            DWORD   dwOutputPwmType;            // RW   PWM-Type (Today only "0" supported)
+
+
+                                                // Robo Interface Distance Sensor
+            DWORD   dwAnzDistanceModes;         // RO   Number of supported Distance Modes (Array Entries)
+            DWORD   dwDistanceMode;             // RW   Type and Mode for Distance-Sensor (Index-Number in the range 0...ANZ_DISTANCE_TYPES)
+            FT_DISTANCE     sDistance[ANZ_DISTANCE_TYPES];  // RW   Values for setting
+                        
+
+                                                        // Robo Interface Memory Section
+            DWORD           dwProg[3];                  // RO   1=Program is saved in the Memory block; [0]=Flash-1 [1]=Flash-2 [2]=Ram
+            unsigned char   aProgNames[3][NAME_LEN];    // RO   [0]=Flash-1 Prog Name; [1]=Flash-2 Prog Name; [2]=Ram Prog-Name
+            DWORD           dwF1AutoStart;              // RO   1=Autostart Flash-1 programm, 0=no autostart
+
+
+                                                // Robo Interface Module Section
+            DWORD           dwMod1Typ;          // RO   Type of left Module (only Robo-If)
+            DWORD           dwMod2Typ;          // RO   Type of right Module (only Robo-If)
+                                                //      possible Values:       
+                                                //          MODULE_NOT_INSTALLED    No Module is installed
+                                                //          MODULE_RF1              RF Data Link is installed
+
+            unsigned char   aMod1Strg[LEN_STRG1];   // RO   String with Module-1 Name   (only FT-Robo Products)
+            unsigned char   aMod2Strg[LEN_STRG1];   // RO   String with Module-2 Name   (only FT-Robo Products)
+
+
+                                                // Robo Interface & RF Data Link Section
+            DWORD   dwRfOn;                     // RW   0=disable RF  1=Enable RF
+            DWORD   dwRfChannel;                // RW   Channel-Number (2..80) for RF-Communication 
+            DWORD   dwRfSubChannel;             // RW   Sub-Channel of Device for the specified Channel (1..3)
+            DWORD   dwRfMessage;                // RW   0=Disable Message-Router Function 1=Enable Message-Rounter Function
+            DWORD   dwRfWrite;                  // W    0=write values permanent (FLASH); 1=write values temporary (RAM) 
+            DWORD   dwRfFw;                     // RO   Firmwareversion of RF-Module
+            unsigned char aRfFwStrg[LEN_STRG1]; // RO   String with Firmware of RF-Module 
+
+                                                // Information for the PC-RF Module
+            DWORD   dwRfStopTransferOnError;    // RW   1=Stop the RF-Transfer Thread on bad RF Connection
+
+                                                // Information for the Interface RF-Module
+            DWORD   dwRfMotorOffOnError;        // RW   1=Motor Off on bad RF Connection
+        } sIf;
+    } FT_SETTING;
+
+
+                                                // ****** Function Prototypes  ******
+    DWORD __stdcall     GetLibVersion(void);
+    DWORD __stdcall     InitFtLib(void);
+    DWORD __stdcall     CloseFtLib(void);
+    DWORD __stdcall     IsFtLibInit(void);
+    DWORD __stdcall     InitFtUsbDeviceList(void);
+    UINT  __stdcall     GetNumFtUsbDevice(void);
+    FT_HANDLE __stdcall GetFtUsbDeviceHandle(UCHAR ucDevNr);
+    FT_HANDLE __stdcall GetFtUsbDeviceHandleSerialNr(DWORD dwSN, DWORD dwTyp);
+    DWORD __stdcall     OpenFtUsbDevice(FT_HANDLE hFt);
+    //FT_HANDLE __stdcall OpenFtCommDevice(DWORD dwPort, DWORD dwTyp, DWORD dwZyklus, DWORD *pdwError);
+    DWORD __stdcall     SetFtDeviceCommMode (FT_HANDLE hFt, DWORD dwMode, DWORD dwParameter, USHORT *puiValue);
+    DWORD __stdcall     CloseAllFtDevices(void);
+    DWORD __stdcall     CloseFtDevice(FT_HANDLE hFt);
+    DWORD __stdcall     GetFtDeviceTyp(FT_HANDLE hFt);
+    LPCSTR __stdcall    GetFtSerialNrStrg(FT_HANDLE hFt);
+    DWORD  __stdcall    GetFtSerialNr(FT_HANDLE hFt);
+    LPCSTR __stdcall    GetFtFirmwareStrg(FT_HANDLE hFt);
+    DWORD __stdcall     GetFtFirmware(FT_HANDLE hFt);
+    LPCSTR __stdcall    GetFtManufacturerStrg(FT_HANDLE hFt);
+    LPCSTR __stdcall    GetFtShortNameStrg(FT_HANDLE hFt);
+    LPCSTR __stdcall    GetFtLongNameStrg(FT_HANDLE hFt);
+    LPCSTR __stdcall    GetFtLibErrorString(DWORD dwErrorCode, DWORD dwTyp);
+    DWORD __stdcall     GetFtDeviceSetting(FT_HANDLE hFt, FT_SETTING *pSet);
+    DWORD __stdcall     SetFtDeviceSetting(FT_HANDLE hFt, FT_SETTING *pSet);
+    DWORD __stdcall     SetFtDistanceSensorMode(FT_HANDLE hFt, DWORD dwMode, DWORD dwTol1, DWORD dwTol2, 
+                                                DWORD dwSchwell1, DWORD dwSchwell2, DWORD dwRepeat1, DWORD dwRepeat2);
+
+
+    DWORD __stdcall     StartFtTransferArea(FT_HANDLE hFt, NOTIFICATION_EVENTS* sNEvent );
+    DWORD __stdcall     StartFtTransferAreaWithCommunication(FT_HANDLE hFt, NOTIFICATION_EVENTS* sNEvent );
+    DWORD __stdcall     StopFtTransferArea(FT_HANDLE hFt);
+    FT_TRANSFER_AREA* __stdcall GetFtTransferAreaAddress(FT_HANDLE hFt);
+    DWORD __stdcall     IsFtTransferActiv(FT_HANDLE hFt);
+    DWORD __stdcall     ResetFtTransfer (FT_HANDLE hFt);
+
+    
+    DWORD __stdcall     GetFtMemoryLayout(FT_HANDLE hFt, BYTE * pbArray, DWORD dwSize);
+    DWORD __stdcall     DownloadFtProgram(FT_HANDLE hFt, DWORD dwMemBlock, BYTE* pbArray, DWORD dwSize, DWORD dwParameter, BYTE *pbName, DWORD dwNameLen);
+    DWORD __stdcall     StartFtProgram(FT_HANDLE hFt, DWORD dwMemBlock);
+    DWORD __stdcall     StopFtProgram(FT_HANDLE hFt);
+    DWORD __stdcall     DeleteFtProgram(FT_HANDLE hFt, DWORD dwMemBlock);
+    DWORD __stdcall     SetFtProgramActiv(FT_HANDLE hFt, DWORD dwMemBlock);
+    DWORD __stdcall     GetFtProgramName(FT_HANDLE hFt, DWORD dwMemBlock, DWORD dwSize, LPVOID pName);
+    DWORD __stdcall     WriteFtMemoryData(FT_HANDLE hFt, DWORD dwData, DWORD dwAddress);
+    DWORD __stdcall     GetFtMemoryData(FT_HANDLE hFt, BYTE * pbArray, DWORD dwSize, DWORD dwAddress);
+
+
+    DWORD __stdcall     SendFtMessage(FT_HANDLE hFt, BYTE bHwId, BYTE bSubId, DWORD dwMessage, DWORD dwWaitTime, DWORD dwOption); 
+    DWORD __stdcall     ClearFtMessageBuffer(FT_HANDLE hFt);
+
+
+
+
+//
+// FTLIB Error Codes
+//
+    #define FTLIB_ERR_SUCCESS                              0x00000000L  
+    #define FTLIB_ERR_CRC                                  0xE0000001L  
+    #define FTLIB_ERR_BTSTUFF                              0xE0000002L  
+    #define FTLIB_ERR_DATA_TOGGLE_MISMATCH                 0xE0000003L  
+    #define FTLIB_ERR_STALL_PID                            0xE0000004L  
+    #define FTLIB_ERR_DEV_NOT_RESPONDING                   0xE0000005L  
+    #define FTLIB_ERR_PID_CHECK_FAILURE                    0xE0000006L  
+    #define FTLIB_ERR_UNEXPECTED_PID                       0xE0000007L  
+    #define FTLIB_ERR_DATA_OVERRUN                         0xE0000008L  
+    #define FTLIB_ERR_DATA_UNDERRUN                        0xE0000009L  
+    #define FTLIB_ERR_RESERVED1                            0xE000000AL  
+    #define FTLIB_ERR_RESERVED2                            0xE000000BL  
+    #define FTLIB_ERR_BUFFER_OVERRUN                       0xE000000CL  
+    #define FTLIB_ERR_BUFFER_UNDERRUN                      0xE000000DL  
+    #define FTLIB_ERR_NOT_ACCESSED                         0xE000000FL  
+    #define FTLIB_ERR_FIFO                                 0xE0000010L  
+    #define FTLIB_ERR_XACT_ERROR                           0xE0000011L  
+    #define FTLIB_ERR_BABBLE_DETECTED                      0xE0000012L  
+    #define FTLIB_ERR_DATA_BUFFER_ERROR                    0xE0000013L  
+                                                    
+    #define FTLIB_ERR_ENDPOINT_HALTED                      0xE0000030L  
+    #define FTLIB_ERR_NO_MEMORY                            0xE0000100L  
+    #define FTLIB_ERR_INVALID_URB_FUNCTION                 0xE0000200L  
+    #define FTLIB_ERR_INVALID_PARAMETER                    0xE0000300L  
+    #define FTLIB_ERR_ERROR_BUSY                           0xE0000400L  
+    #define FTLIB_ERR_INVALID_PIPE_HANDLE                  0xE0000600L  
+    #define FTLIB_ERR_NO_BANDWIDTH                         0xE0000700L  
+    #define FTLIB_ERR_INTERNAL_HC_ERROR                    0xE0000800L  
+    #define FTLIB_ERR_ERROR_SHORT_TRANSFER                 0xE0000900L  
+    #define FTLIB_ERR_BAD_START_FRAME                      0xE0000A00L  
+    #define FTLIB_ERR_ISOCH_REQUEST_FAILED                 0xE0000B00L  
+    #define FTLIB_ERR_FRAME_CONTROL_OWNED                  0xE0000C00L  
+    #define FTLIB_ERR_FRAME_CONTROL_NOT_OWNED              0xE0000D00L  
+    #define FTLIB_ERR_NOT_SUPPORTED                        0xE0000E00L  
+    #define FTLIB_ERR_INVALID_CONFIGURATION_DESCRIPTOR     0xE0000F00L  
+
+    #define FTLIB_ERR_INSUFFICIENT_RESOURCES               0xE8001000L  
+    #define FTLIB_ERR_SET_CONFIG_FAILED                    0xE0002000L  
+    #define FTLIB_ERR_USBD_BUFFER_TOO_SMALL                0xE0003000L  
+    #define FTLIB_ERR_USBD_INTERFACE_NOT_FOUND             0xE0004000L  
+    #define FTLIB_ERR_INVALID_PIPE_FLAGS                   0xE0005000L  
+    #define FTLIB_ERR_USBD_TIMEOUT                         0xE0006000L  
+    #define FTLIB_ERR_DEVICE_GONE                          0xE0007000L  
+    #define FTLIB_ERR_STATUS_NOT_MAPPED                    0xE0008000L  
+
+    #define FTLIB_ERR_CANCELED                             0xE0010000L  
+    #define FTLIB_ERR_ISO_NOT_ACCESSED_BY_HW               0xE0020000L  
+    #define FTLIB_ERR_ISO_TD_ERROR                         0xE0030000L  
+    #define FTLIB_ERR_ISO_NA_LATE_USBPORT                  0xE0040000L  
+    #define FTLIB_ERR_ISO_NOT_ACCESSED_LATE                0xE0050000L  
+                                                    
+    #define FTLIB_ERR_FAILED                               0xE0001000L  
+    #define FTLIB_ERR_INVALID_INBUFFER                     0xE0001001L  
+    #define FTLIB_ERR_INVALID_OUTBUFFER                    0xE0001002L  
+    #define FTLIB_ERR_OUT_OF_MEMORY                        0xE0001003L  
+    #define FTLIB_ERR_PENDING_REQUESTS                     0xE0001004L  
+    #define FTLIB_ERR_ALREADY_CONFIGURED                   0xE0001005L  
+    #define FTLIB_ERR_NOT_CONFIGURED                       0xE0001006L  
+    #define FTLIB_ERR_OPEN_PIPES                           0xE0001007L  
+    #define FTLIB_ERR_ALREADY_BOUND                        0xE0001008L  
+    #define FTLIB_ERR_NOT_BOUND                            0xE0001009L  
+    #define FTLIB_ERR_DEVICE_NOT_PRESENT                   0xE000100AL  
+    #define FTLIB_ERR_CONTROL_NOT_SUPPORTED                0xE000100BL  
+    #define FTLIB_ERR_TIMEOUT                              0xE000100CL  
+    #define FTLIB_ERR_INVALID_RECIPIENT                    0xE000100DL  
+    #define FTLIB_ERR_INVALID_TYPE                         0xE000100EL  
+    #define FTLIB_ERR_INVALID_IOCTL                        0xE000100FL  
+    #define FTLIB_ERR_INVALID_DIRECTION                    0xE0001010L  
+    #define FTLIB_ERR_TOO_MUCH_ISO_PACKETS                 0xE0001011L  
+    #define FTLIB_ERR_POOL_EMPTY                           0xE0001012L  
+    #define FTLIB_ERR_PIPE_NOT_FOUND                       0xE0001013L  
+    #define FTLIB_ERR_INVALID_ISO_PACKET                   0xE0001014L  
+    #define FTLIB_ERR_OUT_OF_ADDRESS_SPACE                 0xE0001015L  
+    #define FTLIB_ERR_INTERFACE_NOT_FOUND                  0xE0001016L  
+    #define FTLIB_ERR_INVALID_DEVICE_STATE                 0xE0001017L  
+    #define FTLIB_ERR_INVALID_PARAM                        0xE0001018L  
+    #define FTLIB_ERR_INVALID_POWER_STATE                  0xE000101AL  
+    #define FTLIB_ERR_POWER_DOWN                           0xE000101BL  
+    #define FTLIB_ERR_VERSION_MISMATCH                     0xE000101CL  
+    #define FTLIB_ERR_SET_CONFIGURATION_FAILED             0xE000101DL  
+
+    #define FTLIB_ERR_VID_RESTRICTION                      0xE0001080L  
+    #define FTLIB_ERR_ISO_RESTRICTION                      0xE0001081L  
+    #define FTLIB_ERR_BULK_RESTRICTION                     0xE0001082L  
+    #define FTLIB_ERR_EP0_RESTRICTION                      0xE0001083L  
+    #define FTLIB_ERR_PIPE_RESTRICTION                     0xE0001084L  
+    #define FTLIB_ERR_PIPE_SIZE_RESTRICTION                0xE0001085L  
+    #define FTLIB_ERR_CONTROL_RESTRICTION                  0xE0001086L  
+    #define FTLIB_ERR_INTERRUPT_RESTRICTION                0xE0001087L  
+                                                    
+    #define FTLIB_ERR_DEVICE_NOT_FOUND                     0xE0001100L
+    #define FTLIB_ERR_SOME_DEVICES_ARE_OPEN                0xE0001101L
+    #define FTLIB_ERR_DEVICE_IS_OPEN                       0xE0001102L
+    #define FTLIB_ERR_DEVICE_NOT_OPEN                      0xE0001103L
+    #define FTLIB_ERR_NO_SUCH_DEVICE_INSTANCE              0xE0001104L
+    #define FTLIB_ERR_INVALID_FUNCTION_PARAM               0xE0001105L
+    #define FTLIB_ERR_DESTROY_DEVICE_LIST                  0xE0001106L
+    #define FTLIB_ERR_USB_NOT_SUPPORTET_FROM_OS            0xE0001107L
+    #define FTLIB_ERR_CLOSE_DEVICE                         0xE0001108L
+
+    #define FTLIB_ERR_DEVICE_NOT_SUPPORTET                 0xE0001281L  
+    #define FTLIB_ERR_WRONG_DEVICE_NUMBER                  0xE0001282L  
+    #define FTLIB_ERR_UNKNOWN_DEVICE_HANDLE                0xE0001283L  
+    #define FTLIB_ERR_WRONG_USB_HANDLE                     0xE0001284L  
+    #define FTLIB_ERR_WRONG_PATHNAME                       0xE0001285L  
+    #define FTLIB_ERR_LIB_IS_INITIALIZED                   0xE0001286L  
+    #define FTLIB_ERR_LIB_IS_NOT_INITIALIZED               0xE0001287L  
+    #define FTLIB_ERR_SERIAL_NR_UNKNOWN                    0xE0001288L  
+    #define FTLIB_ERR_POWER_TOO_LOW                        0xE0001289L  
+    #define FTLIB_ERR_WRONG_RETURN_VALUE                   0xE000128AL  
+    #define FTLIB_ERR_USB_SUPPORT_IS_NOT_INITIALIZED       0xE000128BL  
+
+    #define FTLIB_ERR_USB_MUT0                             0xE0001290L  
+    #define FTLIB_ERR_USB_MUT1                             0xE0001291L  
+    #define FTLIB_ERR_USB_MUT2                             0xE0001292L  
+    #define FTLIB_ERR_USB_MUT3                             0xE0001293L 
+    #define FTLIB_ERR_USB_DEVICE_IS_IN_USE                 0xE0001295L
+
+    #define FTLIB_ERR_THREAD_NOT_STARTABLE                 0xE00012A0L  
+    #define FTLIB_ERR_THREAD_NOT_STARTABLE_X1              0xE00012A1L  
+    #define FTLIB_ERR_THREAD_NOT_STARTABLE_X2              0xE00012A2L  
+    #define FTLIB_ERR_THREAD_NOT_STARTABLE_X3              0xE00012A3L  
+    #define FTLIB_ERR_OTHER_THREAD_FOR_SAME_DEVICE_IS_RUN  0xE00012A4L  
+    #define FTLIB_ERR_THREAD_IS_RUNNING                    0xE00012A5L  
+    #define FTLIB_ERR_THREAD_NOT_RUNNING                   0xE00012A6L  
+    #define FTLIB_ERR_THREAD_X1                            0xE00012A7L  
+    #define FTLIB_ERR_THREAD_X2                            0xE00012A8L  
+    #define FTLIB_ERR_THREAD_WRITE_USB                     0xE00012A9L  
+    #define FTLIB_ERR_THREAD_READ_USB                      0xE00012AAL  
+    #define FTLIB_ERR_THREAD_IS_NORMAL_STOPPED             0xE00012ABL  
+    #define FTLIB_ERR_THREAD_WAIT_TIMEOUT                  0xE00012ACL  
+    #define FTLIB_ERR_THREAD_WRITE_COM                     0xE00012ADL  
+    #define FTLIB_ERR_THREAD_READ_COM                      0xE00012AEL   
+
+    #define FTLIB_ERR_DOWNLOAD                             0xE00012C0L  
+    #define FTLIB_ERR_DOWNLOAD_WRONG_PARAMETER             0xE00012C1L  
+    #define FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK             0xE00012C2L  
+    #define FTLIB_ERR_DOWNLOAD_DATA_SIZE_IS_NULL           0xE00012C3L  
+    #define FTLIB_ERR_DOWNLOAD_DATA_SIZE_TOO_BIG           0xE00012C4L  
+    #define FTLIB_ERR_DOWNLOAD_DATA_SIZE                   0xE00012C5L  
+    #define FTLIB_ERR_DOWNLOAD_ERASE                       0xE00012C6L  
+    #define FTLIB_ERR_DOWNLOAD_F5                          0xE00012C7L  
+    #define FTLIB_ERR_DOWNLOAD_PROG_SNF1                   0xE00012C8L  
+    #define FTLIB_ERR_DOWNLOAD_PROG_SNF2                   0xE00012C9L  
+    #define FTLIB_ERR_DOWNLOAD_BLOCK                       0xE00012CAL  
+    #define FTLIB_ERR_DOWNLOAD_BLOCK_NR                    0xE00012CBL  
+    #define FTLIB_ERR_DOWNLOAD_CRC                         0xE00012CDL  
+
+    #define FTLIB_ERR_IF_NO_PROGRAM                        0xE00012E0L  
+    #define FTLIB_ERR_IF_PROGRAM_IS_RUNNING                0xE00012E1L  
+    #define FTLIB_ERR_IF_NO_PROGRAM_IS_RUNNING             0xE00012E2L  
+    #define FTLIB_ERR_IF_WRONG_PROG_NUMBER                 0xE00012E3L  
+    #define FTLIB_ERR_IF_BUFFER_TOO_SMALL                  0xE00012E4L  
+    #define FTLIB_ERR_IF_MEM_ADDRESS                       0xE00012E5L  
+    #define FTLIB_ERR_IF_MEM_VERIFY                        0xE00012E6L  
+    #define FTLIB_ERR_IF_NOT_SUPPORTET_MODUS               0xE00012E7L  
+    #define FTLIB_ERR_IF_FUNCTION_NOT_SUPPORT              0xE00012E8L
+    #define FTLIB_ERR_FUNCTION_OVER_RF_NOT_ALLOWED         0xE00012E9L
+
+
+    #define FTLIB_INFO_PROGRAM_0_IS_RUNNING                0xE0001600L  
+    #define FTLIB_INFO_PROGRAM_1_IS_RUNNING                0xE0001601L  
+    #define FTLIB_INFO_PROGRAM_2_IS_RUNNING                0xE0001602L  
+    #define FTLIB_INFO_ONLINE_MODUS                        0xE0001620L  
+
+    #define FTLIB_FIRMWARE_UPDATE_FILE_WRONG_0             0xE0001800L  
+    #define FTLIB_FIRMWARE_UPDATE_CRC                      0xE0001801L  
+    #define FTLIB_FIRMWARE_UPDATE_FILE_OLD                 0xE0001802L
+    #define FTLIB_FIRMWARE_UPDATE_FILE_WRONG_1             0xE0001803L
+
+
+    #define FTLIB_ERR_PORT_NUMBER                          0xE0001900L  
+    #define FTLIB_ERR_WRONG_PORT                           0xE0001901L  
+    #define FTLIB_ERR_PORT_NUMBER_IS_NULL                  0xE0001902L  
+    #define FTLIB_ERR_TYP                                  0xE0001903L  
+    #define FTLIB_ERR_PORT_NOT_FOUND                       0xE0001904L  
+    #define FTLIB_ERR_ACCESS_DENIED                        0xE0001905L  
+    #define FTLIB_ERR_OPEN_COM                             0xE0001906L  
+    #define FTLIB_ERR_CLOSE_COM                            0xE0001907L  
+    #define FTLIB_ERR_INIT_COM                             0xE0001908L  
+    #define FTLIB_ERR_INIT_COM_TIMEOUT                     0xE0001909L  
+    #define FTLIB_ERR_WRITE_COM                            0xE000190AL  
+    #define FTLIB_ERR_READ_COM                             0xE000190BL  
+    #define FTLIB_ERR_READ_COM_NUMBER                      0xE000190CL  
+    #define FTLIB_ERR_READ_COM_NOTHING                     0xE000190DL  
+
+    #define FTLIB_ERR_RF_NOT_INSTALLED                     0xE0001A00L
+    #define FTLIB_ERR_RF_WRONG_CHANNEL                     0xE0001A01L
+    #define FTLIB_ERR_RF_WRONG_SUB_CHANNEL                 0xE0001A02L
+    #define FTLIB_ERR_RF_NO_CONNECTION                     0xE0001A03L
+    #define FTLIB_ERR_RF_NO_CONNECTION_A                   0xE0001A04L
+    #define FTLIB_ERR_RF_NO_CONNECTION_B                   0xE0001A05L
+    #define FTLIB_ERR_RF_NO_CONNECTION_C                   0xE0001A06L
+    #define FTLIB_ERR_RF_TIMEOUT_1                         0xE0001A08L
+    #define FTLIB_ERR_RF_TIMEOUT_2                         0xE0001A09L
+    #define FTLIB_ERR_RF_FW_OLD1                           0xE0001A0AL
+    #define FTLIB_ERR_RF_INTERNAL_1                        0xE0001A0DL
+    #define FTLIB_ERR_RF_NO_INTERFACE_MODULE_FOUND         0xE0001A0EL
+
+    #define FTLIB_ERR_DLL_NOT_LOADABLE                     0xE0001B00L 
+    #define FTLIB_ERR_DLL_FUNCTION_ERROR                   0xE0001B01L 
+
+    #define FTLIB_ERR_MSG_HWID_WRONG                       0xE0001C00L 
+    #define FTLIB_ERR_MSG_BUFFER_FULL_TIMEOUT              0xE0001C01L
+
+    #define FTLIB_ERR_UNKNOWN_OPTION_VALUE                 0xE0001D00L
+
+    #define FTLIB_ERR_INTERFACE_00                         0xE0001F00L  
+    #define FTLIB_ERR_INTERFACE_01                         0xE0001F01L  
+    #define FTLIB_ERR_INTERFACE_02                         0xE0001F02L  
+    #define FTLIB_ERR_INTERFACE_03                         0xE0001F03L  
+    #define FTLIB_ERR_INTERFACE_04                         0xE0001F04L  
+    #define FTLIB_ERR_INTERFACE_05                         0xE0001F05L  
+    #define FTLIB_ERR_INTERFACE_06                         0xE0001F06L  
+    #define FTLIB_ERR_INTERFACE_07                         0xE0001F07L  
+    #define FTLIB_ERR_INTERFACE_08                         0xE0001F08L  
+    #define FTLIB_ERR_INTERFACE_09                         0xE0001F09L  
+    #define FTLIB_ERR_INTERFACE_0A                         0xE0001F0AL  
+    #define FTLIB_ERR_INTERFACE_0B                         0xE0001F0BL  
+    #define FTLIB_ERR_INTERFACE_0C                         0xE0001F0CL  
+    #define FTLIB_ERR_INTERFACE_0D                         0xE0001F0DL  
+    #define FTLIB_ERR_INTERFACE_0E                         0xE0001F0EL  
+    #define FTLIB_ERR_INTERFACE_0F                         0xE0001F0FL  
+
+    #define FTLIB_ERR_INTERFACE_D0                         0xE0001FD0L  
+    #define FTLIB_ERR_INTERFACE_D1                         0xE0001FD1L  
+    #define FTLIB_ERR_INTERFACE_D2                         0xE0001FD2L  
+    #define FTLIB_ERR_INTERFACE_D3                         0xE0001FD3L  
+    #define FTLIB_ERR_INTERFACE_D4                         0xE0001FD4L  
+    #define FTLIB_ERR_INTERFACE_D5                         0xE0001FD5L  
+    #define FTLIB_ERR_INTERFACE_D6                         0xE0001FD6L  
+    #define FTLIB_ERR_INTERFACE_D7                         0xE0001FD7L  
+    #define FTLIB_ERR_INTERFACE_D8                         0xE0001FD8L  
+    #define FTLIB_ERR_INTERFACE_D9                         0xE0001FD9L  
+    #define FTLIB_ERR_INTERFACE_DA                         0xE0001FDAL  
+    #define FTLIB_ERR_INTERFACE_DB                         0xE0001FDBL  
+    #define FTLIB_ERR_INTERFACE_DC                         0xE0001FDCL  
+    #define FTLIB_ERR_INTERFACE_DD                         0xE0001FDDL  
+    #define FTLIB_ERR_INTERFACE_DE                         0xE0001FDEL  
+    #define FTLIB_ERR_INTERFACE_DF                         0xE0001FDFL  
+
+    #define FTLIB_ERR_INTERFACE_E0                         0xE0001FE0L  
+    #define FTLIB_ERR_INTERFACE_E1                         0xE0001FE1L  
+    #define FTLIB_ERR_INTERFACE_E2                         0xE0001FE2L  
+    #define FTLIB_ERR_INTERFACE_E3                         0xE0001FE3L  
+    #define FTLIB_ERR_INTERFACE_E4                         0xE0001FE4L  
+    #define FTLIB_ERR_INTERFACE_E5                         0xE0001FE5L  
+    #define FTLIB_ERR_INTERFACE_E6                         0xE0001FE6L  
+    #define FTLIB_ERR_INTERFACE_E7                         0xE0001FE7L  
+    #define FTLIB_ERR_INTERFACE_E8                         0xE0001FE8L  
+    #define FTLIB_ERR_INTERFACE_E9                         0xE0001FE9L  
+    #define FTLIB_ERR_INTERFACE_EA                         0xE0001FEAL  
+    #define FTLIB_ERR_INTERFACE_EB                         0xE0001FEBL  
+    #define FTLIB_ERR_INTERFACE_EC                         0xE0001FECL  
+    #define FTLIB_ERR_INTERFACE_ED                         0xE0001FEDL  
+    #define FTLIB_ERR_INTERFACE_EE                         0xE0001FEEL  
+    #define FTLIB_ERR_INTERFACE_EF                         0xE0001FEFL  
+
+    #define FTLIB_ERR_INTERFACE_F0                         0xE0001FF0L  
+    #define FTLIB_ERR_INTERFACE_F1                         0xE0001FF1L  
+    #define FTLIB_ERR_INTERFACE_F2                         0xE0001FF2L  
+    #define FTLIB_ERR_INTERFACE_F3                         0xE0001FF3L  
+    #define FTLIB_ERR_INTERFACE_F4                         0xE0001FF4L  
+    #define FTLIB_ERR_INTERFACE_F5                         0xE0001FF5L  
+    #define FTLIB_ERR_INTERFACE_F6                         0xE0001FF6L  
+    #define FTLIB_ERR_INTERFACE_F7                         0xE0001FF7L  
+    #define FTLIB_ERR_INTERFACE_F8                         0xE0001FF8L  
+    #define FTLIB_ERR_INTERFACE_F9                         0xE0001FF9L  
+    #define FTLIB_ERR_INTERFACE_FA                         0xE0001FFAL  
+    #define FTLIB_ERR_INTERFACE_FB                         0xE0001FFBL  
+    #define FTLIB_ERR_INTERFACE_FC                         0xE0001FFCL  
+    #define FTLIB_ERR_INTERFACE_FD                         0xE0001FFDL  
+    #define FTLIB_ERR_INTERFACE_FE                         0xE0001FFEL  
+    #define FTLIB_ERR_INTERFACE_FF                         0xE0001FFFL  
+
+/** \endcond doxygen ignore end */
+
+#endif
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclass.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,105 @@
+#include "mbed.h"
+#include "ftlib.h"
+#include "ftlibclass.h"
+#include "ftlibclasscom.h"
+#include "ftlibclassusb.h"
+
+
+
+ftlib* ftlib::lib = 0;
+
+unsigned ftlib::InitFtLib() {
+    lib = new ftlib;
+    return FTLIB_ERR_SUCCESS;
+}
+
+void ftlib::onTick() {
+    ftusbdev::onTick();
+    ftcommdev::onTick();
+}
+
+void ftlib::poll() {
+    ftusbdev::poll();    //this function should be called repetetively from the main event loop
+    ftcommdev::poll();
+}
+
+unsigned ftlib::CloseFtLib() {
+    delete lib;
+    lib = 0;
+    return FTLIB_ERR_SUCCESS;
+}
+
+unsigned ftlib::IsFtLibInit() {
+    return lib ? FTLIB_ERR_LIB_IS_INITIALIZED : FTLIB_ERR_LIB_IS_NOT_INITIALIZED;
+}
+
+unsigned ftlib::CloseAllFtDevices() {
+    ftusbdev::CloseAllFtDevices();
+    ftcommdev::CloseAllFtDevices();
+    return FTLIB_ERR_SUCCESS;
+}
+
+int ftlib::FtproductIDToInterfaceID(int iProductID) {
+    switch (iProductID) {
+        case ROBO_IF_PRODUCT_ID:
+            return FT_ROBO_IF_USB;
+        case EXT_IF_PRODUCT_ID:
+            return FT_ROBO_IO_EXTENSION;
+        case RF_DATA_LINK_PRODUCT_ID:
+            return FT_ROBO_RF_DATA_LINK;
+    }
+
+    return 0;
+}
+
+char * ftlib::GetFtLibErrorString(unsigned dwErrorCode, unsigned dwTyp) {
+    char *buffer = new char[128];
+
+    switch (dwErrorCode) {
+        case FTLIB_ERR_IF_NO_PROGRAM:
+            if (dwTyp) strncpy(buffer, "There is no program stored to work with", 128);
+            else strncpy(buffer, "FTLIB_ERR_IF_NO_PROGRAM", 128);
+            break;
+        case FTLIB_ERR_SUCCESS:
+            if (dwTyp) strncpy(buffer, "Everything is fine", 128);
+            else strncpy(buffer, "FTLIB_ERR_SUCCESS", 128);
+            break;
+        case FTLIB_ERR_THREAD_IS_RUNNING:
+            if (dwTyp) strncpy(buffer, "Thread has been started successfully", 128);
+            else strncpy(buffer, "FTLIB_ERR_THREAD_IS_RUNNING", 128);
+            break;
+        case FTLIB_ERR_DOWNLOAD:
+            if (dwTyp) strncpy(buffer, "Failed to upload the program", 128);
+            else strncpy(buffer, "FTLIB_ERR_DOWNLOAD", 128);
+            break;
+        case FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK:
+            if (dwTyp) strncpy(buffer, "Bad target to upload the program to", 128);
+            else strncpy(buffer, "FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK", 128);
+            break;
+        case FTLIB_ERR_INVALID_PARAM:
+            if (dwTyp) strncpy(buffer, "A parameter specified has a wrong value", 128);
+            else strncpy(buffer, "FTLIB_ERR_INVALID_PARAM", 128);
+            break;
+        case FTLIB_ERR_LIB_IS_INITIALIZED:
+            if (dwTyp) strncpy(buffer, "This library has been initialized", 128);
+            else strncpy(buffer, "FTLIB_ERR_LIB_IS_INITIALIZED", 128);
+            break;
+        case FTLIB_ERR_NOT_SUPPORTED:
+            if (dwTyp) strncpy(buffer, "The requested action is not supported", 128);
+            else strncpy(buffer, "FTLIB_ERR_NOT_SUPPORTED", 128);
+            break;
+        case FTLIB_ERR_PORT_NUMBER_IS_NULL:
+            if (dwTyp) strncpy(buffer, "No handle given", 128);
+            else strncpy(buffer, "FTLIB_ERR_PORT_NUMBER_IS_NULL", 128);
+            break;
+        case FTLIB_ERR_THREAD_NOT_RUNNING:
+            if (dwTyp) strncpy(buffer, "Unable to start the thread", 128);
+            else strncpy(buffer, "FTLIB_ERR_THREAD_NOT_RUNNING", 128);
+            break;
+        default:
+            strncpy(buffer, "Unknown", 128);
+    }
+
+    return buffer;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclass.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,40 @@
+#ifndef FTLIBCLASS_H
+#define FTLIBCLASS_H
+
+#include "mbed.h"
+
+#define LIBFT_VERSION_MAJOR 1
+#define LIBFT_VERSION_MINOR 0
+#define LIBFT_VERSION_PATCH 0
+
+#define INTERFACE_QUERY_TIME 10000 // &#65533;s == 5ms
+
+
+class ftusbdev;
+class ftcommdev;
+
+class ftlib {
+    friend ftusbdev;
+    friend ftcommdev;
+    static ftlib* lib;
+    Ticker tick;//the ticker indicates the moments that transfers should be conducted
+    void onTick();
+    ftlib() {
+        tick.attach_us(this, &ftlib::onTick, INTERFACE_QUERY_TIME);
+    }
+    ~ftlib() {
+        tick.detach();
+    }
+    static int FtproductIDToInterfaceID(int iProductID);
+public:
+    static void poll();
+//public API: These functions match those of the original ftlib
+    static unsigned GetLibVersion();
+    static unsigned InitFtLib();
+    static unsigned CloseFtLib();
+    static unsigned IsFtLibInit();
+    static char* GetFtLibErrorString(unsigned dwErrorCode, unsigned dwTyp);
+    static unsigned CloseAllFtDevices() ;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclasscom.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,456 @@
+#include "mbed.h"
+#include "ftlibclasscom.h"
+vector<ftcommdev*> ftcommdev::devs;
+
+ftcommdev::ftcommdev(Serial *s, unsigned t, unsigned c): ftdev(t, 0) {
+    device = s;
+    port = 0;
+    FT_TRANSFER_AREA *area = new FT_TRANSFER_AREA;
+    memset(area, 0, sizeof(struct _FT_TRANSFER_AREA));
+    area->TransferAktiv = 0;
+    //query_time = INTERFACE_QUERY_TIME_SERIAL;
+    area->RfModulNr = -1;
+    if (t == FT_INTELLIGENT_IF)
+        area->BusModules = 1;
+    else if (t == FT_INTELLIGENT_IF_SLAVE)
+        area->BusModules = 2;
+    ta = area;
+}
+
+//blocking
+int ftcommdev::read(Serial *stream, unsigned char *buf, int n, int timeout_ms) {
+    Timer t;
+    t.start();
+    int i = 0;
+    while (t.read_ms() < timeout_ms && i < n) {
+        if (stream->readable())
+            buf[i++] = stream->getc();
+    }
+    return i;
+}
+
+int ftcommdev::write(Serial *d, unsigned char *ptr, int n, int timeout_ms) {
+    Timer t;
+    t.start();
+    int i = 0;
+    while (t.read_ms() < timeout_ms && i < n) {
+        if (d->writeable())
+            d->putc(ptr[i++]);
+    }
+    return i;
+}
+
+//non-blocking
+int ftcommdev::write() {
+    windex = 0;
+    writeByte(); //write the first byte, callback will take care of the rest
+    return num_write;
+}
+void ftcommdev::writeByte() {
+    if (windex < num_write) {
+        device->putc(out[windex++]);
+        if (windex == num_write)
+            rindex = 0;
+    }
+}
+void ftcommdev::readByte() {
+    if (rindex < num_read) {
+        in[rindex++] = device->getc();
+        if (rindex == num_read) {
+            FtThreadEnd();
+        }
+    }
+}
+
+ftcommdev* ftcommdev::OpenFtCommDevice(unsigned sDevice, unsigned dwTyp, unsigned dwZyklus, unsigned *pdwError) {//makes a (blocking) comm request to the interface
+    Serial *dev = 0;
+    switch (sDevice) {
+        case 1:
+            dev = new Serial(p9, p10);
+            break;
+        case 2:
+            dev = new Serial(p13, p14);
+            break;
+        case 3:
+            dev = new Serial(p28, p27);
+            break;
+//      default:  dev = new Serial(p9, p10); break;
+        default:
+//            dev = &viaUsb;
+            break;
+    }
+    ftcommdev* com = OpenFtCommDevice(dev, dwTyp, dwZyklus, pdwError);
+    if (com) {
+        com->port = sDevice;
+        printf("opening of COM%d OK\n", sDevice);
+    }
+    return com;
+}
+
+ftcommdev* ftcommdev::OpenFtCommDevice(Serial *dev, unsigned dwTyp, unsigned dwZyklus, unsigned *pdwError) {//makes a (blocking) comm request to the interface
+    unsigned char in[5];
+    unsigned char on[] = " ft-Robo-ON-V1";
+    on[0] = 0xA1;
+    ftcommdev* ret = 0;
+    if (dwTyp != FT_ROBO_IF_COM) {
+        ret = new ftcommdevii(dev, dwTyp, dwZyklus);
+        dev->baud(BAUDRATE_II);
+    } else {// dwTyp == FT_ROBO_IF_COM
+        ret = new ftcommdev(dev, dwTyp, dwZyklus);
+        dev->baud(BAUDRATE_RI);
+    }
+    printf("about to send '%s'\n", on);
+    if (dwTyp == FT_ROBO_IF_COM) {
+        int sent = write(dev, on, strlen((const char*)on), 100/*ms*/);
+//        int sent = dev->printf("%s", on);
+        printf("sent %d bytes to COM\n", sent);
+        if (sent == strlen((const char*)on)) {
+            if (read(dev, in, 5, 1000/*ms*/) == 5) {              //   if (dev->scanf("%5c", in) == 1) { does not work, could have to do with NUL chars or needs a lookahead char
+                printf("%02X: interface version: %d.%d.%d.%d\n", in[0], in[4], in[3], in[2], in[1]);
+                ret->fw = *(unsigned*)(in+1);
+                if ((in[0] ^ on[0]) ==  0x0FFU) {
+                    printf("opening of %s OK\n", "UNKNOWN");
+                } else {
+                    printf("return code is %02X but should be %02X\n", in[0], ~on[0]&0xFF);
+                    delete ret;
+                    return NULL;
+                }
+            } else {
+                printf("read did not return 5\n");
+                delete ret;
+                return NULL;
+            }
+        } else {
+            printf("only %d chars were sent i.o %d\n", sent, strlen((const char*)on));
+            delete ret;
+            return NULL;
+        }
+    }
+    devs.push_back(ret);
+    return ret;
+}
+
+unsigned ftcommdev::CloseFtDevice() {//sends a comm request
+    unsigned char off = 0xA2;
+    unsigned char in[1];
+
+    while (ta->TransferAktiv != 0) {
+        fprintf(stderr, "Transfer ta still active\n");
+        sleep(1);
+    }
+
+    if (type == FT_ROBO_IF_COM) {
+        if (write(device, &off, 1, 500) != 1 || read(device, in, 1, 1000) != 1 || (in[0]^off != 0xFF)) {
+            fprintf(stderr, "CloseFtDevice: Error communicating with serial\n");
+        }
+    }
+    for (vector<ftcommdev*>::iterator it = devs.begin(); it < devs.end(); it++)
+        if (*it == this) {
+            devs.erase(it);
+            delete this;
+            return 0;
+        }
+    return 0;
+}
+
+unsigned ftcommdev::GetFtSerialNr() {
+    int ret;
+    unsigned char buffer[35] = { 0 };
+    if (sn > 0)
+        return sn;
+    switch (type) {
+        case FT_INTELLIGENT_IF:
+        case FT_INTELLIGENT_IF_SLAVE:
+            return 0;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xf0;
+            buffer[1] = 0x02;
+            ret = write(device, buffer, 2, 500);
+            if (ret != 2) {
+                fprintf(stderr, "Error writing msg 0xF0 0x02\n");
+                return 0;
+            }
+            ret = read(device, buffer, 5, 1000);
+            if (ret != 5) {
+                fprintf(stderr, "Error reading msg 0xF0 0x02\n");
+                return 0;
+            }
+            //sn = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000;
+            sn = *(unsigned*)(buffer+1);
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+    return sn;
+}
+
+char * ftcommdev::GetFtLongNameStrg() {
+    switch (type) {
+        case FT_INTELLIGENT_IF:
+            return strdup("Intelligent Interface");
+        case FT_INTELLIGENT_IF_SLAVE:
+            return strdup("Intelligent Interface with Slave");
+        case FT_ROBO_IF_IIM:
+            return strdup("Robo Interface in Intelligent Interface mode");
+        case FT_ROBO_IF_COM:
+            return strdup("Robo Interface on Com");
+        default:
+            return strdup("Unknown interface type");
+    }
+}
+
+char * ftcommdev::GetFtShortNameStrg() {
+    switch (type) {
+        case FT_INTELLIGENT_IF:
+            return strdup("IIF");
+        case FT_INTELLIGENT_IF_SLAVE:
+            return strdup("IIF w/Slave");
+        case FT_ROBO_IF_IIM:
+            return strdup("RI_IIM");
+        case FT_ROBO_IF_COM:
+            return strdup("RICom");
+        default:
+            return strdup("Unknown");
+    }
+}
+
+void ftcommdev::poll() {
+    for (int i = 0; i < devs.size(); i++) {
+        if (devs[i]->triggered) {
+            if (devs[i]->guardedFtThreadBegin())
+                devs[i]->triggered = 0;
+        }
+    }
+}
+
+void ftcommdev::FtThreadInit() {//setup buffers for this type of interface
+    device->attach(this, &ftcommdev::writeByte, Serial::TxIrq);
+    device->attach(this, &ftcommdev::readByte, Serial::RxIrq);
+    ftdev::FtThreadInit();
+    out[0] = 0xf2;
+    num_write = 17;
+    num_read = 21;
+}
+
+//here the real data exchange starts
+void ftcommdev::FtThreadBegin() {//called every 10ms to issue a request, should be non-blocking
+    if (!test_and_set()) {//return when transferarea is in use
+        busy = false; //release the mutex, otherwise the thread effectively stops
+        return;//return because there is no point in sending a nonsense request, alternatively the lock can be ignored in which case the data may be inconsistent
+    }
+    out[1] = ta->M_Main;
+    out[2] = (ta->MPWM_Main[0] & 0x7) | (ta->MPWM_Main[1]<<3 & 0x38) | (ta->MPWM_Main[2]<<6 & 0xC0);
+    out[3] = (ta->MPWM_Main[2] & 0x1) | (ta->MPWM_Main[3]<<1 & 0xE) | (ta->MPWM_Main[4]<<4 & 0x70) | (ta->MPWM_Main[5]<<7 & 0x80);
+    out[4] = (ta->MPWM_Main[5] & 0x3) | (ta->MPWM_Main[6]<<2 & 0x1C) | (ta->MPWM_Main[7]<<5 & 0xE0);
+    out[5] = ta->M_Sub1;
+    out[6] = (ta->MPWM_Sub1[0] & 0x7) | (ta->MPWM_Sub1[1]<<3 & 0x38) | (ta->MPWM_Sub1[2]<<6 & 0xC0);
+    out[7] = (ta->MPWM_Sub1[2] & 0x1) | (ta->MPWM_Sub1[3]<<1 & 0xE) | (ta->MPWM_Sub1[4]<<4 & 0x70) | (ta->MPWM_Sub1[5]<<7 & 0x80);
+    out[8] = (ta->MPWM_Sub1[5] & 0x3) | (ta->MPWM_Sub1[6]<<2 & 0x1C) | (ta->MPWM_Sub1[7]<<5 & 0xE0);
+    out[9] = ta->M_Sub2;
+    out[10] = (ta->MPWM_Sub2[0] & 0x7) | (ta->MPWM_Sub2[1]<<3 & 0x38) | (ta->MPWM_Sub2[2]<<6 & 0xC0);
+    out[11] = (ta->MPWM_Sub2[2] & 0x1) | (ta->MPWM_Sub2[3]<<1 & 0xE) | (ta->MPWM_Sub2[4]<<4 & 0x70) | (ta->MPWM_Sub2[5]<<7 & 0x80);
+    out[12] = (ta->MPWM_Sub2[5] & 0x3) | (ta->MPWM_Sub2[6]<<2 & 0x1C) | (ta->MPWM_Sub2[7]<<5 & 0xE0);
+    out[13] = ta->M_Sub3;
+    out[14] = (ta->MPWM_Sub3[0] & 0x7) | (ta->MPWM_Sub3[1]<<3 & 0x38) | (ta->MPWM_Sub3[2]<<6 & 0xC0);
+    out[15] = (ta->MPWM_Sub3[2] & 0x1) | (ta->MPWM_Sub3[3]<<1 & 0xE) | (ta->MPWM_Sub3[4]<<4 & 0x70) | (ta->MPWM_Sub3[5]<<7 & 0x80);
+    out[16] = (ta->MPWM_Sub3[5] & 0x3) | (ta->MPWM_Sub3[6]<<2 & 0x1C) | (ta->MPWM_Sub3[7]<<5 & 0xE0);
+    out[17]    = 0;
+    out[18]    = 0;
+    out[19]    = 0;
+    out[20]    = 0;
+    out[21]    = 0;
+    out[22]    = 0;
+    out[23]    = 0;
+    out[24]    = 0;
+    out[25]    = 0;
+    out[26]    = 0;
+    out[27]    = 0;
+    out[28]    = 0;
+    out[29]    = 0;
+    out[30]    = 0;
+    out[31]    = 0;
+
+    increment();//release the lock on shared memeory
+    write();
+}
+#if 0
+void ftcommdev::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete
+    if (!test_and_set()) {//skip when busy
+        busy = false;
+        return;
+    }
+    ta->ChangeEg = ta->E_Main != in[0] || ta->E_Sub1 != in[1] || ta->E_Sub2 != in[2] || ta->E_Sub3 != in[3];
+    ta->E_Main = in[0];
+    ta->E_Sub1 = in[1];
+    ta->E_Sub2 = in[2];
+    ta->E_Sub3 = in[3];
+    ta->ChangeAn = 1; //assume that analog always changes (noise)
+    ta->AX = in[4];
+    ta->AY = in[5];
+    ta->A1 = in[6];
+    ta->A2 = in[7];
+    ta->AX |= (in[8] & 0x3) << 8;
+    ta->AY |= (in[8] & 0xC) << 6;
+    ta->A1 |= (in[8] & 0x30) << 4;
+    ta->A2 |= (in[8] & 0xC0) << 2;
+    ta->AZ = in[9];
+    ta->D1 = in[10];
+    ta->D2 = in[11];
+    ta->AV = in[12];
+    ta->AZ |= (in[13] & 0x3) << 8;
+    ta->D1 |= (in[13] & 0xC) << 6;
+    ta->D2 |= (in[13] & 0x30) << 4;
+    ta->AV |= (in[13] & 0xC0) << 2;
+    if (ta->IRKeys != in[14])
+        ta->ChangeIr = 1;
+    ta->IRKeys = in[14];
+    ta->BusModules = in[15];
+    // 16
+    ta->AXS1 = in[17];
+    ta->AXS2 = in[18];
+    ta->AXS3 = in[19];
+    ta->AXS1 |= (in[20] & 0x3) << 8;
+    ta->AXS2 |= (in[20] & 0xC) << 6;
+    ta->AXS3 |= (in[20] & 0x30) << 4;
+    // 21
+    ta->AVS1 = in[22];
+    ta->AVS2 = in[23];
+    ta->AVS3 = in[24];
+    ta->AVS1 |= (in[25] & 0x3) << 8;
+    ta->AVS2 |= (in[25] & 0xC) << 6;
+    ta->AVS3 |= (in[25] & 0x30) << 4;
+    // 26...42
+    increment();
+    interface_connected = 1;
+    if (ne.NotificationCallback) {
+        (*ne.NotificationCallback)(ne.Context);
+    }
+    busy = false;
+}
+#endif
+
+void ftcommdev::FtThreadFinish() {//called by StopFtTransferArea
+    device->attach(0,Serial::RxIrq);
+    device->attach(0,Serial::TxIrq);
+    ftdev::FtThreadFinish();
+}
+
+void ftcommdevii::FtThreadBegin() {//called every 10ms to issue a request, should be non-blocking
+    if (!test_and_set()) {//return when transferarea is in use
+        busy = false; //release the mutex, otherwise the thread effectively stops
+        return;//return because there is no point in sending a nonsense request, alternatively the lock can be ignored in which case the data may be inconsistent
+    }
+    out[1] = ta->M_Main;
+    out[2] = ta->M_Sub1;
+
+    // For the II we need to simulate different speeds here
+    for (int iCurMotor = 0; iCurMotor < 7; iCurMotor++) {
+        if (ta->MPWM_Main[iCurMotor] < ii_speed) out[1] &= ~(1 << iCurMotor);
+        if (ta->MPWM_Sub1[iCurMotor] < ii_speed) out[2] &= ~(1 << iCurMotor);
+    }
+    ii_speed++;
+    if (ii_speed > 7) ii_speed = 0;
+
+    num_write=2;
+    switch (cycle) {
+        case 0:
+            num_read=3;
+            out[0] = 0xc5;
+            break;
+        case 1:
+            num_read=3;
+            out[0] = 0xc9;
+            break;
+        default:
+            num_read=1;
+            out[0] = 0xc1;
+            break;
+    }
+    if (type == FT_INTELLIGENT_IF_SLAVE) {
+        num_write++;
+        num_read++;
+        out[0]++;
+    }
+    if (cycle++ > analogcycle) cycle=0;
+    increment();//release the lock on shared memeory
+    write();
+}
+
+void ftcommdevii::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete
+    if (!test_and_set()) {//skip when busy
+        busy = false;
+        return;
+    }
+    ta->ChangeEg = ta->E_Main != in[0];
+    ta->E_Main = in[0];
+    ta->BusModules = type==FT_INTELLIGENT_IF_SLAVE;
+    switch (out[0]) {
+        case 0xc1:
+            break;
+        case 0xc5:
+            ta->AX = in[1] | (8<<in[2]);
+            break;
+        case 0xc9:
+            ta->AY = in[1] | (8<<in[2]);
+            break;
+        case 0xc2:
+            ta->ChangeEg = ta->ChangeEg || ta->E_Sub1 != in[1];
+            ta->E_Sub1 = in[1];
+            break;
+        case 0xc6:
+            ta->ChangeEg = ta->ChangeEg || ta->E_Sub1 != in[1];
+            ta->E_Sub1 = in[1];
+            ta->AX = in[2] | (8<<in[3]);
+            break;
+        case 0xca:
+            ta->ChangeEg = ta->ChangeEg || ta->E_Sub1 != in[1];
+            ta->E_Sub1 = in[1];
+            ta->AY = in[2] | (8<<in[3]);
+            break;
+    }
+    increment();
+    interface_connected = 1;
+    if (ne.NotificationCallback) {
+        (*ne.NotificationCallback)(ne.Context);
+    }
+    busy = false;
+}
+
+unsigned ftcommdev::SetFtDistanceSensorMode(unsigned dwMode, unsigned dwTol1, unsigned dwTol2, unsigned dwLevel1, unsigned dwLevel2, unsigned dwRepeat1, unsigned dwRepeat2) {
+    unsigned char buffer[11];
+ 
+    if (type != FT_ROBO_IF_COM)
+        return FTLIB_ERR_NOT_SUPPORTED;
+
+    buffer[0] = 0xf1;
+    buffer[1] = 0x01;
+    buffer[2] = dwMode;
+    buffer[3] = dwTol1;
+    buffer[4] = dwTol2;
+    buffer[5] = dwLevel1;
+    buffer[6] = dwLevel1>>8;
+    buffer[7] = dwLevel2;
+    buffer[8] = dwLevel2>>8;
+    buffer[9] = dwRepeat1;
+    buffer[10] = dwRepeat2;
+
+    if ((write(device, buffer, 11, 500)) != 11 || (read(device, buffer, 1, 500)) != 1 || buffer[0] != 0x01) {
+        fprintf(stderr, "SetFtDistanceSensorMode: Error communicating with serial\n");
+        return buffer[0];
+    }
+    usleep(100000); // wait before continue, else it doesn't always work
+    return FTLIB_ERR_SUCCESS;
+}
+
+unsigned ftcommdev::pgm_message(unsigned code, unsigned dwMemBlock) {
+    unsigned char buffer[2];
+    if (type != FT_ROBO_IF_COM) return FTLIB_ERR_NOT_SUPPORTED;
+    buffer[0] = code;
+    buffer[1] = dwMemBlock;
+    if ((write(device, buffer, 2, 500)) != 2 || (read(device, buffer, 1, 500)) != 1) {
+        return FTLIB_ERR_IF_NO_PROGRAM;
+    }
+    if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+    else return FTLIB_ERR_IF_NO_PROGRAM;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclasscom.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,82 @@
+#ifndef FTLIBCLASSCOM_H
+#define FTLIBCLASSCOM_H
+
+#include "ftlibclassdev.h"
+#include <vector>
+
+#define BAUDRATE_II 9600
+#define BAUDRATE_RI 38400
+
+#define usleep(x)    wait_us(x)
+#define sleep(x)    wait(x)
+
+class ftlib;
+
+class ftcommdev: public ftdev { //for serial devices (Robo over Com), IIF devices are derived from this
+    friend ftlib;
+    virtual unsigned pgm_message(unsigned code, unsigned dwMemBlock);
+protected:
+    static vector<ftcommdev*> devs;
+    Serial *device;
+    unsigned port;
+    int windex, rindex;
+    ftcommdev() {}
+    ftcommdev(Serial *s, unsigned t, unsigned c);
+    static int write(Serial *d, unsigned char *ptr, int n, int timeout_ms);
+    static int read(Serial *stream, unsigned char *buf, int n, int timeout_ms);
+    int write();
+    void writeByte();
+    void readByte();
+    static void onTick() {
+        for (int i = 0; i < devs.size(); i++) devs[i]->trigger();
+    }
+    static void CloseAllFtDevices() {
+        for (int i = 0; i < devs.size(); i++) devs[i]->CloseFtDevice();
+    }
+    virtual void FtThreadInit();
+    virtual void FtThreadBegin();
+//    virtual void FtThreadEnd();
+    virtual void FtThreadFinish();
+public:
+    virtual ~ftcommdev() {
+        if (port>0) delete device;
+    }
+    static void poll();
+//public API: These functions match those of the original ftlib
+    static ftcommdev* OpenFtCommDevice(unsigned dwPort, unsigned dwTyp, unsigned dwZyklus, unsigned *pdwError);
+    static ftcommdev* OpenFtCommDevice(Serial *port, unsigned dwTyp, unsigned dwZyklus, unsigned *pdwError);
+    virtual unsigned      CloseFtDevice();
+    virtual unsigned      GetFtSerialNr();
+    virtual char*     GetFtManufacturerStrg() {
+        return strdup("Knobloch GMBH");
+    }
+    virtual char*     GetFtShortNameStrg();
+    virtual char*     GetFtLongNameStrg();
+    virtual unsigned  SetFtDistanceSensorMode(unsigned dwMode, unsigned dwTol1, unsigned dwTol2,
+            unsigned dwSchwell1, unsigned dwSchwell2, unsigned dwRepeat1, unsigned dwRepeat2);
+    /*
+    virtual unsigned      GetFtDeviceSetting(FT_SETTING *pSet);
+    virtual unsigned      SetFtDeviceSetting(FT_SETTING *pSet);
+    */
+    virtual unsigned StartFtProgram(unsigned dwMemBlock) {
+        return pgm_message(0xf4, dwMemBlock);
+    }
+    virtual unsigned StopFtProgram() {
+        return pgm_message(0xf8, 0);
+    }
+};
+
+class ftcommdevii: public ftcommdev {//specialisation of intelligent interface like devices
+    friend ftcommdev;
+    int analogcycle, cycle;
+    int ii_speed;
+    ftcommdevii() {}
+    ftcommdevii(Serial *s, unsigned t, unsigned c):ftcommdev(s, t, c), analogcycle(c) {
+        cycle = 0;
+        ii_speed = 0;
+    }
+    virtual void FtThreadBegin();
+    virtual void FtThreadEnd();
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclassdev.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,229 @@
+#include "mbed.h"
+#include "USBHost.h"
+#include "ftlibclassdev.h"
+
+#define usleep(x)    wait_us(x)
+#define sleep(x)    wait(x)
+
+//incorrect: should clear outputs when thread is NOT running
+unsigned ftdev::ResetFtTransfer() {
+    if (ta) {
+        ta->M_Main = 0;
+        ta->M_Sub1 = 0;
+        ta->M_Sub2 = 0;
+        ta->M_Sub3 = 0;
+        return FTLIB_ERR_SUCCESS;
+    }
+    return FTLIB_ERR_DEVICE_NOT_OPEN;
+}
+
+unsigned ftdev::IsFtTransferActiv() {
+    if (transferAktiv > 0)
+        return FTLIB_ERR_THREAD_IS_RUNNING;
+    return FTLIB_ERR_THREAD_NOT_RUNNING;
+}
+
+//not sure about this conversion
+char * ftdev::GetFtFirmwareStrg() {
+    unsigned ifw = GetFtFirmware();
+    char *s = new char[16];
+    int byte1 = ifw & 0xff;
+    int byte2 = (ifw & 0xff00) >> 8;
+    int byte3 = (ifw & 0xff0000) >> 16;
+    int byte4 = (ifw & 0xff000000) >> 24;
+    snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1);
+    return s;
+}
+
+//not sure about this conversion
+char * ftdev::GetFtSerialNrStrg() {
+    DWORD ifw = GetFtSerialNr();
+    char *s = new char[16];
+    int byte1, byte2, byte3, byte4;
+    byte1 = ifw % 100;
+    ifw /= 100;
+    byte2 = ifw % 100;
+    ifw /= 100;
+    byte3 = ifw % 100;
+    ifw /= 100;
+    byte4 = ifw % 100;
+    ifw /= 100;
+    snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1);
+    return s;
+}
+
+unsigned ftdev::StartFtTransferArea(NOTIFICATION_EVENTS* ev) {
+    int err = IsFtTransferActiv();
+    if (err == FTLIB_ERR_THREAD_IS_RUNNING)
+        return err;
+    if (ta==0)
+        return FTLIB_ERR_DEVICE_NOT_OPEN;
+    if (ev)
+        ne = *ev; //copy the entire struct
+    else
+        memset(&ne, 0, sizeof(NOTIFICATION_EVENTS));
+    FtThreadInit();//setup buffers and serial handlers
+    transferAktiv = FTX1RUN;
+    return FTLIB_ERR_SUCCESS;
+}
+
+unsigned ftdev::StartFtTransferAreaWithCommunication(NOTIFICATION_EVENTS* ev) {
+    if (type == FT_INTELLIGENT_IF || type == FT_INTELLIGENT_IF_SLAVE || type == FT_ROBO_IF_IIM)
+        return FTLIB_ERR_NOT_SUPPORTED;
+    if (messages == 0)
+        messages = new msgbuffer<SMESSAGE, 10>;
+    int ret = StartFtTransferArea(ev);
+    if (ret) {
+        delete messages;
+        messages = 0;
+    }
+    return ret;
+}
+
+unsigned ftdev::StopFtTransferArea() {
+    while (!guardedStop()) {
+        USBLoop();//otherwise this loop gets stuck
+        printf("waiting for thread to finish\r");
+    }
+    FtThreadFinish();
+    if (messages) {
+        delete messages;
+        messages = 0;
+    }
+    busy = false;
+    printf("\nthread stopped\n");
+    return FTLIB_ERR_SUCCESS;
+}
+
+bool ftdev::guardedFtThreadBegin() {//called every 10ms by the main loop to issue a request, should be non-blocking, guarded by busy flag to avoid multiple pending requests
+  // printf("busy:%d-%d ", busy, triggered);
+    __disable_irq();
+    if (busy) {
+        if (triggered > 100) { //interface has not responded within 100 slots or response was missed
+            printf("Missed reply??? releasing busy\n");
+            busy = false; //release the busy flag to reenable the request-reply process
+        }
+        __enable_irq();
+        return false; //skip the timeslot when previous was not yet handled
+    }
+    busy = true;
+    printf("trig=%d\n", triggered);
+    __enable_irq();
+    FtThreadBegin();//here the request is sent to the interface
+    return true;
+}
+
+bool ftdev::guardedStop() {//called every 10ms by the main loop to issue a request, should be non-blocking, guarded by busy flag to avoid multiple pending requests
+    __disable_irq();
+    if (busy) {
+        if (triggered > 100) { //interface has not responded within 10 slots or response was missed
+            printf("busy ");
+        }
+        __enable_irq();
+        return false; //skip the timeslot when previous was not yet handled
+    }
+    busy = true;
+    __enable_irq();
+    triggered = 0;
+    transferAktiv = FTX1STOP;
+    return true;
+}
+
+bool ftdev::test_and_set() {
+    bool tmp;
+    __disable_irq();
+    if (tmp = (lock>0))
+        lock--;
+    __enable_irq();
+    return tmp;
+}
+
+void ftdev::increment() {
+    __disable_irq();
+    lock++;
+    __enable_irq();
+}
+
+void ftdev::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete
+    if (!test_and_set()) {//skip when busy
+        busy = false;
+        printf("ftdev::FtThreadEnd: release busy\n");
+        return;
+    }
+    ta->ChangeEg = ta->E_Main != in[0] || ta->E_Sub1 != in[1] || ta->E_Sub2 != in[2] || ta->E_Sub3 != in[3];
+    ta->E_Main = in[0];
+    ta->E_Sub1 = in[1];
+    ta->E_Sub2 = in[2];
+    ta->E_Sub3 = in[3];
+    ta->ChangeAn = 1; //assume that analog always changes (noise)
+    ta->AX = in[4];
+    ta->AY = in[5];
+    ta->A1 = in[6];
+    ta->A2 = in[7];
+    ta->AX |= (in[8] & 0x3) << 8;
+    ta->AY |= (in[8] & 0xC) << 6;
+    ta->A1 |= (in[8] & 0x30) << 4;
+    ta->A2 |= (in[8] & 0xC0) << 2;
+    ta->AZ = in[9];
+    ta->D1 = in[10];
+    ta->D2 = in[11];
+    ta->AV = in[12];
+    ta->AZ |= (in[13] & 0x3) << 8;
+    ta->D1 |= (in[13] & 0xC) << 6;
+    ta->D2 |= (in[13] & 0x30) << 4;
+    ta->AV |= (in[13] & 0xC0) << 2;
+    if (ta->IRKeys != in[14])
+        ta->ChangeIr = 1;
+    ta->IRKeys = in[14];
+    ta->BusModules = in[15];
+    // 16
+    ta->AXS1 = in[17];
+    ta->AXS2 = in[18];
+    ta->AXS3 = in[19];
+    ta->AXS1 |= (in[20] & 0x3) << 8;
+    ta->AXS2 |= (in[20] & 0xC) << 6;
+    ta->AXS3 |= (in[20] & 0x30) << 4;
+    // 21
+    ta->AVS1 = in[22];
+    ta->AVS2 = in[23];
+    ta->AVS3 = in[24];
+    ta->AVS1 |= (in[25] & 0x3) << 8;
+    ta->AVS2 |= (in[25] & 0xC) << 6;
+    ta->AVS3 |= (in[25] & 0x30) << 4;
+    // 26...42
+    ta->AV *= 3;
+    ta->AVS1 *= 3;
+    ta->AVS2 *= 3;
+    ta->AVS3 *= 3;
+    //message processing
+    if (messages && ne.CallbackMessage) { //just to check if communication was enabled
+        if (in[28])
+            ne.CallbackMessage((SMESSAGE*)(in+29));
+        if (in[35])
+            ne.CallbackMessage((SMESSAGE*)(in+36));
+    }
+    increment();
+    interface_connected = 1;
+    if (ne.NotificationCallback) {
+        (*ne.NotificationCallback)(ne.Context);
+    }
+    busy = false;
+        printf("ftdev::FtThreadEnd: release busy at exit\n");
+}
+
+unsigned ftdev::SendFtMessage(unsigned char bHwId, unsigned char bSubId, unsigned dwMessage, unsigned dwWaitTime, unsigned dwOption) {
+    SMESSAGE m;
+    m.L.ucHwId = bHwId;
+    m.L.ucSubId = bSubId;
+    m.L.dw = dwMessage;
+    //waittime ignored
+    if (messages)
+        return messages->push(m, dwOption) < 0 ? FTLIB_ERR_MSG_BUFFER_FULL_TIMEOUT : 0;
+    return FTLIB_ERR_MSG_HWID_WRONG; //not the correct error code
+}
+
+unsigned ftdev::ClearFtMessageBuffer() {
+    if (messages)
+        messages->clear();
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclassdev.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,148 @@
+#ifndef FTLIBCLASSDEV_H
+#define FTLIBCLASSDEV_H
+
+#include "ftlib.h"
+#include "message.h"
+
+#define ABF_IF_COMPLETE_NUM_WRITE 32
+#define ABF_IF_COMPLETE_NUM_READ 42
+
+/*****************************************************************************************
+  The interfaces use a combination of synchronous (blocking) and asynchronous (non-blocking)
+  I/O. For serial I/O it is essential that non-blocking I/O is used otherwise the entire 
+  transfer timeslot would be consumed with busy waiting. For USB this constraint is less
+  severe but I nevertheless used non-blocking I/O also for USB in the transfer thread (which
+  is not a real thread). Outside the transfer thread, I/O can be synchronous which I indeed
+  used because it is easier to write and easier to understand.
+  The timing of the transfer thread is determined by a Ticker interrupt. But in order not
+  to occupy the interrupt system for too long, it just increments a counter in every
+  interface object. The main event loop polls this counter, initiates a transfer and resets
+  it. Starting a thread works by calling FtThreadInit (which does some initialisation) and
+  setting transferAktiv to FTX1RUN. The poll routine will then call guardedFtThreadBegin
+  which in turn will call FtThreadBegin provided the previous run of the thread has ended.
+  The thead is protected by a busy flag which is set in guardedFtThreadBegin and released
+  in FtThreadEnd, as long as busy is active a new thread should not be begun (enforced by
+  guardedFtThreadBegin). FtThreadBegin copies the transferArea (TA) to a buffer and calls
+  the send routine which (being non-blocking) returns immediately. When the send completes
+  a callback (interrupt) occurs which initiates the corresponding read (request-reply model).
+  When the read finished another callback (interrupt) occurs which invokes FtThreadEnd.
+  FtThreadEnd may call notification routines which will all like FtThreadEnd but unlike
+  FtThreadBegin run in interrupt context. Both FtThreadBegin and FtThreadEnd operate on
+  the TA which is shared between the application and the transfer thread. As this transfer-
+  thread is not a real thread synchronisation is not strictly neccesary because FtThreadBegin
+  runs in the background (like the application) and FtThreadEnd+callback run as interrupt
+  and cannot be interrupted by the background. Still a semaphore 'lock' is in place to
+  protect the TA from simultaneous access. When the area is locked, the transfer is simply
+  skipped. A user application cal call test_and_set() which returns falls when the area is
+  locked and true when it is free. After using the TA the user must then call increment()
+  to release the lock on the TA. At the moment the onlu use-case is to provide a consistent
+  set of motor-settings to the TX which will be communicated in the same packet.
+*****************************************************************************************/
+
+inline char* strdup(const char *s) {
+    char *d = new char[strlen(s)+1];
+    strcpy(d, s);
+    return d;
+}
+
+class ftdev {
+protected:
+    FT_TRANSFER_AREA* ta;
+    NOTIFICATION_EVENTS ne;
+    msgbuffer<SMESSAGE, 10> *messages;
+    int type, sn;
+    unsigned fw;
+    unsigned char out[ABF_IF_COMPLETE_NUM_WRITE]; //these buffers have maximum size, alternatively each subclass could have its own properly sized buffer
+    unsigned char in[ABF_IF_COMPLETE_NUM_READ];
+    int num_write, num_read;
+    enum _ta_state {FTX1STOP, FTX1RUN, FTX1SYNC} transferAktiv;
+    volatile int lock; //semaphore to control concurrent access to transferarea, FtThreadEnd is called in interrupt context
+    volatile bool busy; //semaphore to prevent a transfer from being started while another is still in progress
+    volatile bool interface_connected;
+    volatile int triggered;//when >0 indicates that the next transfer should take place
+    ftdev() {} //private default, construction takes place through subclasses
+    ftdev(int t, int s): type(t), sn(s) {
+        ta = 0;
+        fw = 0;
+        triggered = 0;
+        busy = false;
+        lock = 1;
+        interface_connected = false;
+        messages = 0;
+        transferAktiv = FTX1STOP;
+    }
+    void trigger() {
+        if (transferAktiv != FTX1STOP) triggered++;    //called by onTick
+    }
+    bool guardedFtThreadBegin(); //called by 'poll'
+    bool guardedStop();
+    virtual void FtThreadInit() { busy = false; if (ta) ta->TransferAktiv = true;} //called by StartFtTransferArea
+    virtual void FtThreadBegin() = 0; //called by 'guardedFtThreadBegin'
+    virtual void FtThreadEnd();   //called by interrupt when transfer completes
+    virtual void FtThreadFinish() { if(ta) ta->TransferAktiv = false;} //called by StopFtTransferArea
+    bool test_and_set(); //'lock' semphore
+    void increment(); //'lock' semphore
+    virtual unsigned pgm_message(unsigned code, unsigned dwMemBlock) = 0;
+public:
+    virtual ~ftdev() {
+        delete ta;
+        delete messages;
+    }
+//public API: These functions match those of the original ftlib
+    virtual unsigned  CloseFtDevice() = 0;
+    virtual unsigned  GetFtDeviceTyp() {
+        return type;
+    }
+    virtual char*     GetFtSerialNrStrg();
+    virtual unsigned  GetFtSerialNr() {
+        return sn;
+    }
+    virtual char*     GetFtFirmwareStrg();
+    virtual unsigned  GetFtFirmware() {
+        return fw;
+    }
+    virtual char*     GetFtManufacturerStrg() = 0;
+    virtual char*     GetFtShortNameStrg() = 0;
+    virtual char*     GetFtLongNameStrg() = 0;
+    /*
+    virtual unsigned      GetFtDeviceSetting(FT_SETTING *pSet);
+    virtual unsigned      SetFtDeviceSetting(FT_SETTING *pSet);
+    */
+    virtual unsigned      SetFtDistanceSensorMode(unsigned dwMode, unsigned dwTol1, unsigned dwTol2,
+            unsigned dwSchwell1, unsigned dwSchwell2, unsigned dwRepeat1, unsigned dwRepeat2) {
+        return FTLIB_ERR_NOT_SUPPORTED;
+    }
+    virtual unsigned      StartFtTransferArea(NOTIFICATION_EVENTS* sNEvent = 0);
+    virtual unsigned      StartFtTransferAreaWithCommunication(NOTIFICATION_EVENTS* sNEvent = 0);
+    virtual unsigned      StopFtTransferArea();
+    virtual FT_TRANSFER_AREA*     GetFtTransferAreaAddress() {
+        return ta;
+    }
+    virtual unsigned      IsFtTransferActiv();
+    unsigned      ResetFtTransfer ();
+    unsigned      SendFtMessage(unsigned char bHwId, unsigned char bSubId, unsigned dwMessage, unsigned dwWaitTime, unsigned dwOption);
+    unsigned      ClearFtMessageBuffer();
+    virtual unsigned StartFtProgram(unsigned dwMemBlock) {
+        return FTLIB_ERR_NOT_SUPPORTED;
+    }
+    virtual unsigned StopFtProgram() {
+        return FTLIB_ERR_NOT_SUPPORTED;
+    }
+    unsigned DeleteFtProgram(unsigned dwMemBlock) {
+        return pgm_message(0xf5, dwMemBlock);
+    }
+    unsigned SetFtProgramActiv(unsigned dwMemBlock) {
+        return pgm_message(0xf9, dwMemBlock);
+    }
+};
+
+
+/* still to be implemented
+    unsigned GetFtMemoryLayout(unsigned char * pbArray, unsigned dwSize);
+    unsigned DownloadFtProgram(unsigned dwMemBlock, unsigned char* pbArray, unsigned dwSize, unsigned dwParameter, unsigned char *pbName, unsigned dwNameLen);
+    unsigned GetFtProgramName(unsigned dwMemBlock, unsigned dwSize, char* pName);
+    unsigned WriteFtMemoryData(unsigned dwData, unsigned dwAddress);
+    unsigned GetFtMemoryData(unsigned char * pbArray, unsigned dwSize, unsigned dwAddress);
+*/
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclasstxc.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,501 @@
+#include "mbed.h"
+#include "USBHost.h"
+#include "ftlibclasstxc.h"
+#include "ftErrCode.h"
+
+ftusbdevtx::ftusbdevtx(): ftusbdev(0, FT_TXC, 0) {
+    sid = 0;
+    tid = 0;
+    active = 0;
+    transferAktiv = FTX1STOP;
+    cbRoboExtState = 0;
+    for (int i = TA_LOCAL; i <  TA_N_PARTS; i++)  ta[i] = 0;
+}
+
+ftusbdevtx::ftusbdevtx(int d): ftusbdev(d, FT_TXC, 0) {
+    sid = 0;
+    tid = 0;
+    active = 0;
+    transferAktiv = FTX1STOP;
+    cbRoboExtState = 0;
+    for (int i = TA_LOCAL; i <  TA_N_PARTS; i++)  ta[i] = 0;
+    set_baudrate(38400);
+    send_msg(1); //ping
+    GetFtSerialNr();
+}
+
+void ftusbdevtx::getSlaveInfo() {
+    send_msg(7, 1); //get state for master
+    for (int i = 1; i <= N_EXT_DEV; i++)
+        if (ta[0]->state.ext_dev_connect_state[i-1]) {
+            if (ta[i] == 0) { //new slave
+                ta[i] = new TA;
+                memset(ta[i], 0, sizeof(TA));
+                active |= 1<<i;
+                send_msg(6, 1<<i); //get info for slave;
+                printf("New Extension %d = %s\n", i, ta[i]->info.device_name);
+                if (cbRoboExtState) cbRoboExtState(i, 1);
+            }
+        } else {
+            if (ta[i]) {
+                delete ta[i];
+                ta[i] = 0;
+                active &= ~(1<<i);
+                printf("Extension %d went offline\n", i);
+                if (cbRoboExtState) cbRoboExtState(i, 0);
+            }
+        }
+//    send_msg(6, active & ~1); //get info for slaves;
+}
+
+unsigned ftusbdevtx::OpenFtUsbDevice() {
+    ta[0] = new TA;
+    memset(ta[0], 0, sizeof(TA));
+    active = 1;
+    send_msg(6, 1); //get info for master
+    printf("Master=%s\n", ta[0]->info.device_name);
+    getSlaveInfo(); /*
+    send_msg(7, 1); //get state for master
+    for (int i = 0; i < N_EXT_DEV; i++)
+        if (ta[0]->state.ext_dev_connect_state[i]) {
+            ta[i+1] = new TA;
+            memset(ta[i+1], 0, sizeof(TA));
+            active |= 1<<(i+1);
+            send_msg(6, 1<<(i+1)); //get info for slave;
+            printf("Extension %d = %s\n", i+1, ta[i+1]->info.device_name);
+        }*/
+//    send_msg(6, active & ~1); //get info for slaves;
+    return 0;
+}
+
+unsigned ftusbdevtx::CloseFtDevice() {
+    if (ta[0]==0)
+        return FTLIB_ERR_DEVICE_NOT_OPEN;
+    while (transferAktiv != FTX1STOP) {
+        fprintf(stderr, "Transfer ta still active\n");
+        wait(1);
+    }
+    for (int i = 0; i < N_EXT_DEV; i++)
+        if (ta[i]!=0) {
+            delete ta[i];
+            ta[i] = 0;
+        }
+    return 0;
+}
+
+unsigned ftusbdevtx::IsFtTransferActiv() {
+    if (ta[0] == 0)
+        return FTLIB_ERR_DEVICE_NOT_OPEN;//or just say not running
+    if (transferAktiv == FTX1RUN)
+        return FTLIB_ERR_THREAD_IS_RUNNING;
+    if (transferAktiv == FTX1STOP)
+        return FTLIB_ERR_THREAD_NOT_RUNNING;
+    return FTLIB_ERR_THREAD_SYNCHRONIZED;
+}
+
+
+unsigned ftusbdevtx::set_baudrate(unsigned br) {
+    unsigned char buffer[7] = {0x00, 0x96, 0x00, 0x00, 0, 0, 8};
+    *(unsigned*)buffer = br;
+    int ret = USBControlTransfer(device, 0x21, 0x20, 0, 0, buffer, 7);
+    if (ret != 7)
+        printf("error setting Baudrate: %d\n", ret);
+    ret = USBControlTransfer(device, 0xa1, 0x21, 0, 0, buffer, 7);
+    if (ret == 7)
+        printf("baudrate=%d, format=%d, parity=%d, bits=%d\n", *(int*)buffer, buffer[4], buffer[5], buffer[6]);
+    else
+        printf("error getting Baudrate: %d\n", ret);
+    return *(unsigned*)buffer;
+}
+
+unsigned ftusbdevtx::GetFtSerialNr() {
+    if (sn) return sn;
+    unsigned char req_sn[] = "\x0dget_ser_num\x0d";
+    char ser[80];
+    memset(ser, 0, sizeof(ser));
+    int ret=write_data(req_sn, sizeof(req_sn)-1);
+    if (ret != sizeof(req_sn)-1)
+        printf("bulk write error: %d\n", ret);
+    ret=read_data((unsigned char*)ser, sizeof(ser));
+    if (ret < 0)
+        printf("bulk read error: %d\n", ret);
+    char s1[41],s3[31];
+    unsigned num=0;
+    int n = sscanf(ser,"\x0d\x0a%40[^\n\r]%u\x0d\x0a%30[^\n\r]", s1, &num, s3);
+    if (n==3) {
+        sn = num;
+        printf("%010u  %s\n",  num, s3);
+    } else
+        printf("could not parse serial number [%s]\n", ser);
+    return sn;
+}
+
+char* ftusbdevtx::GetFtLongNameStrg() {
+    unsigned char req_sn[] = "\x0dget_ser_num\x0d";
+    char ser[80];
+    memset(ser, 0, sizeof(ser));
+    int ret=write_data(req_sn, sizeof(req_sn)-1);
+    if (ret != sizeof(req_sn)-1)
+        printf("bulk write error: %d\n", ret);
+    ret=read_data((unsigned char*)ser, sizeof(ser));
+    if (ret < 0)
+        printf("bulk read error: %d\n", ret);
+    char s1[41],s3[31]="";
+    unsigned num=0;
+    int n = sscanf(ser,"\x0d\x0a%40[^\n\r]%u\x0d\x0a%30[^\n\r]", s1, &num, s3);
+    return strdup(s3);
+}
+
+TA*  ftusbdevtx::GetFtTransferAreaAddress(int i) {
+    if (i < N_EXT_DEV)
+        if (ta[i])
+            return ta[i];
+        else
+            printf("TX%d is not open\n", i);
+    else
+        printf("Index out of range (%d)\n", i);
+    return 0;
+}
+
+unsigned ftusbdevtx::StartFtTransferArea(NOTIFICATION_EVENTS* ev) {
+    int err = IsFtTransferActiv();
+    if (err == FTLIB_ERR_THREAD_IS_RUNNING)
+        return err;
+    if (active==0)
+        return FTLIB_ERR_DEVICE_NOT_OPEN;
+    if (ev)
+        ne = *ev; //copy the entire struct
+    else
+        memset(&ne, 0, sizeof(NOTIFICATION_EVENTS));
+    FtThreadInit(); //sets busy to false
+    transferAktiv = FTX1RUN;//indicate that thread is running
+    return FTLIB_ERR_SUCCESS;
+}
+
+void ftusbdevtx::FtThreadBegin() {
+    if (!test_and_set()) {//return when transferarea is in use
+        busy = false; //release the mutex, otherwise the thread effectively stops
+        printf("TA busy: skip begin slot\n");
+        return;//return because there is no point in sending a nonsense request, alternatively the lock can be ignored in which case the data may be inconsistent
+    }
+    transferAktiv = FTX1SYNC;//indicate that TA is being updated (like busy)
+    send_msg(2, active, false);
+    increment();
+}
+
+void ftusbdevtx::FtThreadEnd() {
+    if (!test_and_set()) {//skip when busy
+        busy = false;
+        printf("TA busy: skip end slot\n");
+        return;
+    }
+    rec_msg(); //parse the message
+    increment(); //release the TA mutex
+    if (ne.NotificationCallback) {
+        ne.NotificationCallback(ne.Context);
+    }
+    if (tid%100 == 0) { //about every 1 seconds
+        //getSlaveInfo(); //synchronous! TODO: change to non-blocking
+    }
+    transferAktiv = FTX1RUN;//TA update complete
+    busy = false;  //ready for the next tick
+//    printf("Busy released\n");
+}
+
+UINT16 ftusbdevtx::checksum(unsigned char *p, unsigned n) {
+    UINT16 sum = 0;
+    do {
+        sum -= *p++;
+    } while (--n);
+    return (sum<<8)|(sum>>8);
+}
+
+void ftusbdevtx::dump_buffer(int size) {
+    if (buffer==0) {
+        printf("No buffer\n");
+        return;
+    }
+    for (int i = 0; i < size; i++) {
+        printf("%02X ", buffer[i]);
+        if (i%16 == 15) printf("\n");
+    }
+    printf("----------------------\n");
+}
+
+unsigned ftusbdevtx::send_msg(unsigned cmd, unsigned set, bool sync) {
+    const unsigned sizes[] = {0, 0, //cmd 1
+                              sizeof(TA_OUTPUT)+sizeof(UINT32), //cmd 2
+                              0, //unknown
+                              0, //unknown
+                              sizeof(TA_CONFIG)+sizeof(UINT32), //cmd 5
+                              sizeof(UINT32), //cmd 6
+                              sizeof(UINT32), //cmd 7
+                              sizeof(DISPLAY_MSG)+sizeof(UINT32), //cmd 8
+                              DEV_NAME_LEN + 1+3 + sizeof(UINT32) //cmd 9
+                             };
+    int ret = 0;
+    int n = 0;
+    for (int i = TA_LOCAL; i < TA_N_PARTS; i++) {
+        if (set & (1<<i)) {
+            n++;
+        }
+    }
+    unsigned size = 0;
+    if (cmd < sizeof(sizes)/sizeof(unsigned))
+        size = sizes[cmd];
+    unsigned payload_size = n*size;
+    num_read = sizeof(header)+sizeof(trailer);
+    unsigned total_size = sizeof(header)+payload_size+sizeof(trailer);
+    buffer = new unsigned char[total_size]; //size must be known in advance
+
+    unsigned net_size = total_size-sizeof(UINT32)-sizeof(trailer);//exclude start,len,crc,etx
+    header *hdr = (header*)buffer;
+    hdr->start = 0x5502;
+    hdr->bytesH = net_size>>8;
+    hdr->bytesL = net_size&0xff;
+    hdr->body.snd = 2;
+    hdr->body.rec = 1;
+    hdr->body.trans = ++tid;
+    hdr->body.session = sid;
+    hdr->body.cmd = cmd;
+    hdr->body.structs = n;
+    unsigned char* payload = buffer+sizeof(header);
+    for (int i = TA_LOCAL; i < TA_N_PARTS; i++) {
+        if (ta[i]==0 || !(set & (1<<i))) {
+            if (set & (1<<i)) printf("TX %d is not open yet!\n", i);
+            continue;
+        }
+        unsigned *id = (unsigned*)payload;
+        *id = i;
+        payload = (unsigned char*)(id+1);
+        num_read += sizeof(UINT32);
+        switch (cmd) {
+            case 1:
+                break;
+            case 2:
+                memcpy(payload, &ta[i]->output, sizeof(TA_OUTPUT));
+                payload += sizeof(TA_OUTPUT);
+                num_read += sizeof(TA_INPUT);
+                break;
+            case 5:
+                memcpy(payload, &ta[i]->config, sizeof(TA_CONFIG));
+                payload += sizeof(TA_OUTPUT);
+                break;
+            case 6:
+                num_read += sizeof(TA_INFO);
+                break;
+            case 7:
+                num_read += sizeof(TA_STATE);
+                break;
+            case 8:
+                memcpy(payload, &ta[i]->display.display_msg, sizeof(DISPLAY_MSG));
+                payload += sizeof(DISPLAY_MSG);
+                break;
+            case 9:
+                memcpy(payload, ta[i]->info.device_name, DEV_NAME_LEN + 1+3);
+                payload += sizeof(DEV_NAME_LEN + 1+3);
+                break;
+            default:
+                printf("Unknown message type %d\n", cmd);
+                break;
+        }
+    }
+    trailer *trl = (trailer*)payload;
+    trl->chksum = checksum(buffer+2, net_size+2);
+    trl->etx = '\x03';
+    num_read--;
+    //dump_buffer(total_size);
+    //printf("Expecting %d bytes for transaction %d\n", num_read, tid);
+    if (sync) {
+        ret = write_data(buffer, total_size-1);//send 1 less because trailer is 1 too long due to alignment
+        delete[] buffer;
+        if (ret < 0)
+            printf("synchronous send_message failed (%d)\n", ret);
+        else {
+            buffer = new unsigned char[num_read];
+            ret = read_data(buffer, num_read);
+            if (ret < 0) {
+                printf("synchronous read failed (%d)\n", ret);
+                delete[] buffer;
+            } else {
+                //dump_buffer(num_read);
+                rec_msg();
+            }
+        }
+    } else
+        write_data(buffer, total_size-1, &ftusbdevtx::write_finished_cb, this);
+    return ret;
+}
+#if 0
+unsigned ftusbdevtx::rec_msg() {
+    header *hdr = (header*)buffer;
+    //dump_buffer(num_read);
+    if (hdr->start != 0x5502) printf("Invalid packet\n");
+    unsigned net_size = (hdr->bytesH<<8) + hdr->bytesL;
+    if (net_size+7 != num_read) printf("message has %d bytes, was expecting %d bytes\n", net_size+7, num_read);
+    //printf("message %d from %d\n", hdr->cmd, hdr->snd);
+    if (hdr->rec != 2) printf("Wrong destination (%d)\n", hdr->rec);
+    if (hdr->trans != tid) printf("Response to request %d, expected %d\n", hdr->trans, tid);
+    if (hdr->session != sid) {
+        printf("Session number has changed from %d to %d\n", sid, hdr->session);
+        sid = hdr->session;
+        tid = 1; //restart transaction sequence
+    }
+    unsigned cmd = hdr->cmd - 100;
+    unsigned n = hdr->structs;
+    unsigned char* payload = buffer+sizeof(header);
+    trailer *trl = (trailer*)(buffer+net_size+4);
+    for (int i = 0; i < n && payload < (unsigned char*)trl; i++) {
+        unsigned *id = (unsigned*)payload;
+        if (*id >= TA_N_PARTS) {
+            printf("Illegal extension nr %d\n", *id);
+            continue;
+        }
+        if (ta[*id]==0) {
+            printf("Message for new device %d\n", *id);
+            continue;//skip the copy to avoid assignment to null ta but the payload pointer is not advanced! stopping further copying
+        }
+        payload = (unsigned char*)(id+1);
+        switch (cmd) {
+            case 1:
+                break;
+            case 2:
+                memcpy(&ta[*id]->input, payload, sizeof(TA_INPUT));
+                payload += sizeof(TA_INPUT);
+                break;
+            case 5:
+                break;
+            case 6:
+                memcpy(&ta[*id]->info, payload, sizeof(TA_INFO));
+                payload += sizeof(TA_INFO);
+                break;
+            case 7:
+                memcpy(&ta[*id]->state, payload, sizeof(TA_STATE));
+                payload += sizeof(TA_STATE);
+                break;
+            case 8:
+                break;
+            case 9:
+                break;
+            default:
+                printf("Unknown message type %d\n", cmd);
+                break;
+        }
+    }
+    if (payload != (unsigned char*)trl) printf("expected %d sections with in total %d bytes; got %d bytes\n", n, payload-buffer-sizeof(header), net_size-sizeof(header));
+    if (trl->chksum != checksum(buffer+2, net_size+2)) printf("Checksum error\n");
+    if (trl->etx != '\x03') printf("Expected ETX(03), got %02X\n", trl->etx);
+    delete[] buffer;
+    return 0;
+}
+#else
+unsigned ftusbdevtx::rec_msg() {
+    header *hdr = (header*)buffer;
+    //dump_buffer(num_read);
+    if (hdr->start != 0x5502) printf("Invalid packet\n");
+    unsigned net_size = (hdr->bytesH<<8) + hdr->bytesL;
+    if (net_size+7 != num_read) printf("message has %d bytes, was expecting %d bytes\n", net_size+7, num_read);
+    rec_msg2(&hdr->body, net_size);
+    trailer *trl = (trailer*)(buffer+net_size+4);
+    if (trl->chksum != checksum(buffer+2, net_size+2)) printf("Checksum error\n");
+    if (trl->etx != '\x03') printf("Expected ETX(03), got %02X\n", trl->etx);
+    delete[] buffer;
+    return 0;
+}
+
+unsigned ftusbdevtx::rec_msg2(headerbody *hdr, unsigned net_size) {
+    //printf("message %d from %d\n", hdr->cmd, hdr->snd);
+    if (hdr->rec != 2) printf("Wrong destination (%d)\n", hdr->rec);
+    if (hdr->trans != tid) printf("Response to request %d, expected %d\n", hdr->trans, tid);
+    if (hdr->session != sid) {
+        printf("Session number has changed from %d to %d\n", sid, hdr->session);
+        sid = hdr->session;
+        tid = 1; //restart transaction sequence
+    }
+    unsigned cmd = hdr->cmd - 100;
+    unsigned n = hdr->structs;
+    if (n==0)
+        printf("Got reply to cmd %d\n", cmd);
+    unsigned char* payload = (unsigned char *)(hdr+1);
+    unsigned char* trl = (unsigned char*)hdr+net_size;
+    for (int i = 0; i < n && payload < trl; i++) {
+        unsigned *id = (unsigned*)payload;
+        if (*id >= TA_N_PARTS) {
+            printf("Illegal extension nr %d\n", *id);
+            continue;
+        }
+        if (ta[*id]==0) {
+            printf("Message for new device %d\n", *id);
+            continue;//skip the copy to avoid assignment to null ta but the payload pointer is not advanced! stopping further copying
+        }
+        payload = (unsigned char*)(id+1);
+        switch (cmd) {
+            case 1:
+                break;
+            case 2:
+                memcpy(&ta[*id]->input, payload, sizeof(TA_INPUT));
+                payload += sizeof(TA_INPUT);
+                break;
+            case 5:
+                break;
+            case 6:
+                memcpy(&ta[*id]->info, payload, sizeof(TA_INFO));
+                payload += sizeof(TA_INFO);
+                break;
+            case 7:
+                memcpy(&ta[*id]->state, payload, sizeof(TA_STATE));
+                payload += sizeof(TA_STATE);
+                if (*id == 0)
+                    for (int i = 1; i <= N_EXT_DEV; i++)
+                        if (ta[0]->state.ext_dev_connect_state[i-1]) {
+                            if (!(active & (1<<i))) { //new slave
+                                active |= 1<<i;
+                                if (ta[i] == 0) { //new slave
+                                    ta[i] = new TA;
+                                    memset(ta[i], 0, sizeof(TA));
+                                }
+                                send_msg(6, 1<<i, false); //get info for slave;
+                                printf("New Extension %d = %s\n", i, ta[i]->info.device_name);
+                                if (cbRoboExtState) cbRoboExtState(i, 1);
+                            }
+                        } else {
+                            if (active & (1<<i)) {
+                                active &= ~(1<<i);
+                                printf("Extension %d went offline\n", i);
+                                if (cbRoboExtState) cbRoboExtState(i, 0);
+                            }
+                        }
+
+                break;
+            case 8:
+                break;
+            case 9:
+                break;
+            default:
+                printf("Unknown message type %d\n", cmd);
+                break;
+        }
+    }
+    if (payload != trl)
+        printf("expected %d sections with in total %d bytes; got %d bytes\n", n, payload-(unsigned char*)(hdr+1), net_size-sizeof(headerbody));
+    return cmd;
+}
+#endif
+void ftusbdevtx::read_finished_cb(int device, int endpoint, int status, u8* data, int len, void* userData) {
+//end of reply transfer
+//printf("read_finished_cb: %d bytes\n", len);
+    ftusbdevtx *fth = (ftusbdevtx*)userData;
+    if (fth->transferAktiv == FTX1SYNC)
+        fth->FtThreadEnd();
+    else
+        fth->rec_msg();
+}
+
+void ftusbdevtx::write_finished_cb(int device, int endpoint, int status, u8* data, int len, void* userData) { //end of request transfer, issue, reply transfer
+    ftusbdevtx *fth = (ftusbdevtx*)userData;
+//printf("write_finished_cb: wrote %d bytes, reading %d bytes\n", len, fth->num_read);
+    delete[] fth->buffer;
+    fth->buffer = new unsigned char[fth->num_read];
+    USBInterruptTransfer(fth->device, 0x82, fth->buffer, fth->num_read, read_finished_cb, fth);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclasstxc.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,279 @@
+#ifndef FTLIBCLASSTXC_H
+#define FTLIBCLASSTXC_H
+#include "ftlibclassusb.h"
+#include <string.h>
+#include "fifo.h"
+#define FT_TXC  300
+
+
+typedef unsigned char UINT8;
+typedef unsigned char BOOL8;
+typedef unsigned char UCHAR8;
+typedef unsigned short  UINT16;
+typedef short  INT16;
+typedef unsigned short  BOOL16;
+typedef int INT32;
+typedef unsigned UINT32;
+
+//#include "ROBO_TX_FW.h" //"../PC_programming_RoboTXC_V1-2_11_Dec_2009/PC_Programming_RoboTXC/Demo_Static_Lib_C/Inc/"
+#include "ROBO_TX_FW_1_24.h" //"../PC_programming_RoboTXC/PC_Programming_RoboTXC/Demo_Static_Lib_C/Inc/"
+typedef     struct {
+    UINT32 snd, rec;
+    UINT16 trans, session;
+    UINT32 cmd, structs;
+    } headerbody;
+    
+typedef struct {
+    UINT16 start;
+    union { //the message format is HL, the native format is LH, receiver routine swaps HL to LH, send routine writes as HL UINT16 bytes;
+        struct {
+            UINT8 bytesH, bytesL;
+        }/*anonymous*/; //as_bytes;
+        UINT16 bytes;
+    };//winavr allows anonymous structs and unions
+ headerbody body;
+//    UINT32 ta_id;//ta_id is normally not considered part of the header but part of the payload, it is repeated for each struct
+} header;
+
+
+typedef struct {
+    UINT16    chksum;
+    UCHAR8    etx;
+} trailer;
+
+class ftusbdevtx: public ftusbdev {
+    friend ftusbdev;
+protected:
+    typedef TA *pTA;
+    pTA ta[TA_N_PARTS];
+    unsigned short tid, sid;
+    unsigned char *buffer;
+    fifo console;
+    unsigned active;
+    unsigned short checksum(unsigned char *p, unsigned n);
+    void getSlaveInfo();
+    void (*cbRoboExtState)(unsigned, unsigned);
+    ftusbdevtx();
+    ftusbdevtx(int d);
+    virtual void FtThreadInit() {
+        busy = false;
+    }
+    virtual void FtThreadBegin() ;
+    virtual void FtThreadEnd() ;
+    virtual unsigned set_baudrate(unsigned br);
+    void dump_buffer(int);
+    //unsigned set_name(unsigned index, char *name) { return send_msg(9, 1<<index, name);}
+    unsigned send_msg(unsigned cmd, unsigned set=0, bool sync = true);
+    unsigned rec_msg();
+    unsigned rec_msg2(headerbody *hdr, unsigned net_size);
+    static void read_finished_cb(int device, int endpoint, int status, unsigned char* data, int len, void* userData);
+    static void write_finished_cb(int device, int endpoint, int status, unsigned char* data, int len, void* userData);
+    virtual int read_data(unsigned char *data, int size, USBCallback callback = 0, void* userData = 0) { return USBBulkTransfer(device, 0x82, data, size, callback, userData);}
+    virtual int write_data(unsigned char *data, int size, USBCallback callback = 0, void* userData = 0) { return USBBulkTransfer(device, 0x03, data, size, callback, userData);}
+public:
+    virtual ~ftusbdevtx() {
+        for (int i = 0; i < TA_N_PARTS; i++) if (ta[i]) {
+                delete ta[i];
+                ta[i]=0;
+            }
+    }
+//public API: These functions match those of the original ftlib
+    virtual unsigned OpenFtUsbDevice(); //ftxOpenComDevice, we regard a TXC as a USB device
+    virtual unsigned CloseFtDevice(); //ftxCloseDevice, ftxCloseAllDevices (ftlibclass)
+    virtual unsigned IsFtTransferActiv();
+    virtual unsigned GetFtFirmware() {
+        if (ta[0]) return ta[0]->info.version.firmware.abcd;
+        return 0;
+    }
+    virtual unsigned GetFtSerialNr();
+    virtual char*    GetFtManufacturerStrg() { //ftxGetManufacturerStrg
+        return strdup("MSC Vertriebs GmbH");
+    }
+    virtual char*     GetFtShortNameStrg() {//ftxGetShortNameStrg
+        return strdup("ROBO TX Controller");;
+    }
+    virtual char*     GetFtLongNameStrg();//ftxGetLongNameStrg
+    virtual FT_TRANSFER_AREA*     GetFtTransferAreaAddress() {
+#ifdef COMPATIBILITY
+        if (ftdev::ta==0) ftdev::ta = new FT_TRANSFER_AREA;
+#else
+        printf("TXC does not support Robo TA\n");    //or create a compatible copy
+#endif
+        return ftdev::ta;
+    }
+    TA*  GetFtTransferAreaAddress(int i) ;
+    virtual unsigned      StartFtTransferArea(NOTIFICATION_EVENTS* sNEvent );
+    virtual unsigned      StartFtTransferAreaWithCommunication(NOTIFICATION_EVENTS* sNEvent ) {
+        return FTLIB_ERR_NOT_SUPPORTED;
+    }
+//FtRemoteCmd
+    void SetCBRoboExtState(void(*f)(unsigned, unsigned)) {
+        cbRoboExtState = f;
+    }
+    unsigned GetRoboTxDevName(int dev, char *strbuf, int len) {
+        if (ta[dev]==0) return 0;
+        strncpy(strbuf, ta[dev]->info.device_name, len);
+        return strlen(strbuf);
+    }
+    unsigned SetRoboTxDevName(int dev, char *strbuf) {
+        if (ta[dev]==0) return FTLIB_ERR_DEVICE_NOT_OPEN;
+        strncpy(ta[dev]->info.device_name, strbuf, 17);
+        send_msg(9, 1<<dev);
+        return FTLIB_ERR_SUCCESS;
+    }
+    unsigned GetRoboTxBtAddr(int dev, char *strbuf, int len) {
+        if (ta[dev]==0) return 0;
+        strncpy(strbuf, ta[dev]->info.bt_addr, len);
+        return strlen(strbuf);
+    }
+    unsigned GetFirmware(int dev) {
+        if (ta[dev]==0) return 0;
+        return ta[dev]->info.version.firmware.abcd;
+    }
+    //unsigned GetRoboTxFwStr(char *strbuf, int len) { return sprintf(strbuf, "%010d", 123456789);}
+    unsigned GetRoboTxHwStr(int dev, char *strbuf, int len) {
+        if (ta[dev]==0) return 0;
+        if (len>0) {
+            *strbuf = ta[dev]->info.version.hardware.part.a;
+            return 1;
+        } else return 0;
+    }
+    unsigned GetRoboTxDllStr(int dev, char *strbuf, int len) {
+        const char *dll = dev==0 ? "2" : "0";//seems to be '2' for master and '0' for slaves, source unknown
+        strcpy(strbuf, dll);
+        return strlen(dll);
+    }
+    unsigned SetOutCounterReset(int dev, unsigned cnt) {
+        if (ta[dev]==0) return FTLIB_ERR_DEVICE_NOT_OPEN;
+        if (cnt >= N_CNT) return -1;
+        ta[dev]->output.cnt_reset[cnt] = true;
+        return FTLIB_ERR_SUCCESS;
+    }
+    unsigned SetOutMotorValues(int dev, unsigned mId, float speed) {
+        int dutyp = 0, dutym = 0;
+        if (ta[dev]==0) return FTLIB_ERR_DEVICE_NOT_OPEN;
+        if (mId >= N_MOTOR) return -1;
+        if (speed >= 1) dutyp = 512;
+        else if (speed >= 0) dutyp = 512*speed;
+        else if (speed <= -1) dutym = 512;
+        else dutym = 512*speed;
+        ta[dev]->output.duty[mId<<1] = dutym;
+        ta[dev]->output.duty[(mId<<1)+1] = dutyp;
+        return FTLIB_ERR_SUCCESS;
+    }
+    unsigned SetOutPwmValues(int dev, unsigned mId, float speed) {
+        int duty = 0;
+        if (ta[dev]==0) return FTLIB_ERR_DEVICE_NOT_OPEN;
+        if (mId >= N_PWM_CHAN) return -1;
+        if (speed >= 1) duty = 512;
+        else if (speed >= 0) duty = 512*speed;
+        ta[dev]->output.duty[mId] = duty;
+        return FTLIB_ERR_SUCCESS;
+    }
+    //SetFtUniConfig
+    //SetFtCntConfig
+    //SetMotorExConfig
+    //StopMotorExConfig
+    //ResetMotorExConfig
+    //SetCBMotorExReached
+    //GetInIOValue
+    //GetInCounterValue
+    //GetInDisplayButtonValue
+    //SetRoboTxMessage
+};
+
+#endif
+
+#if 0
+class ta_txc: private TA {
+public:
+    unsigned GetRoboTxDevName(char *strbuf, int len) {
+        strncpy(strbuf, info.device_name, len);
+        return strlen(info.device_name);
+    }
+    unsigned SetRoboTxDevName(char *strbuf);
+    unsigned GetRoboTxBtAddr(char *strbuf, int len) {
+        strncpy(strbuf, info.bt_addr, len);
+        return strlen(info.bt_addr);
+    }
+    unsigned GetRoboTxFwVal(unsigned *buf) {
+        *buf = info.version.firmware.abcd;
+        return 0;
+    }
+    //unsigned GetRoboTxFwStr(char *strbuf, int len) { return sprintf(strbuf, "%010d", 123456789);}
+    unsigned GetRoboTxHwStr(char *strbuf, int len) {
+        if (len>0) {
+            *strbuf = info.version.hardware.part.a;
+            return 1;
+        } else return 0;
+    }
+    unsigned GetRoboTxDllStr(char *strbuf, int len) {
+        char *dll ="0";
+        strcpy(strbuf, dll);
+        return strlen(dll);
+    }
+    //SetOutCounterReset
+    //SetOutMotorValues
+    //SetOutPwmValues
+    //SetFtUniConfig
+    //SetFtCntConfig
+    //SetMotorExConfig
+    //StopMotorExConfig
+    //ResetMotorExConfig
+    //SetCBMotorExReached
+    //GetInIOValue
+    //GetInCounterValue
+    //GetInDisplayButtonValue
+    //SetRoboTxMessage
+};
+
+class ftusbdevtx;
+class ftdevtxslave {
+    ftusbdevtx *mstr;
+    int dev;
+//protected:
+    ftdevtxslave() {}
+    ftdevtxslave(int d);
+    //unsigned set_name(unsigned index, char *name) { return send_msg(9, 1<<index, name);}
+public:
+    virtual ~ftdevtxslave() { }
+//public API: These functions match those of the original ftlib
+    virtual unsigned GetFtFirmware() {
+        if (ta[0]) return ta[0]->info.version.firmware.abcd;
+        return 0;
+    }
+    virtual unsigned GetFtSerialNr();
+    virtual char*    GetFtManufacturerStrg() { //ftxGetManufacturerStrg
+        return strdup("MSC Vertriebs GmbH");
+    }
+    virtual char*     GetFtShortNameStrg() {//ftxGetShortNameStrg
+        return GetFtLongNameStrg();
+    }
+    virtual char*     GetFtLongNameStrg();//ftxGetLongNameStrg
+    virtual FT_TRANSFER_AREA*     GetFtTransferAreaAddress() {
+#ifdef COMPATIBILITY
+        if (ftdev::ta==0) ftdev::ta = new FT_TRANSFER_AREA;
+#else
+        printf("TXC does not support Robo TA\n");    //or create a compatible copy
+#endif
+        return ftdev::ta;
+    }
+    TA*  GetFtTransferAreaAddress(int i) ;
+    //SetOutCounterReset
+    unsigned SetOutMotorValues(int mId, float speed) {
+        return mstr->SetOutMotorValues(dev, mId, speed);
+    }
+    //SetOutPwmValues
+    //SetFtUniConfig
+    //SetFtCntConfig
+    //SetMotorExConfig
+    //StopMotorExConfig
+    //ResetMotorExConfig
+    //SetCBMotorExReached
+    //GetInIOValue
+    //GetInCounterValue
+    //GetInDisplayButtonValue
+    //SetRoboTxMessage
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclasstxcbt.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,474 @@
+#include "mbed.h"
+#include "USBHost.h"
+#include "ftlibclasstxcbt.h"
+#include "ftErrCode.h"
+#include "Utils.h"
+
+ftusbdevtxbt::ftusbdevtxbt(BTDevice *bd): ftusbdevtx() {
+    init = idle;
+    message_pending = 0;
+    parseState = 0;
+    if (bd) {
+        memcpy((char*)&btaddr, (char*)bd->GetAddress(), sizeof(BD_ADDR));
+        name = bd->_name;
+    }
+    set_baudrate(38400);//no effect
+    //further com not possible because device is not open
+//    send_msg(1); //ping
+//    GetFtSerialNr();
+}
+
+unsigned ftusbdevtxbt::InitFtUsbDeviceList() {
+    ftusbdev::InitFtUsbDeviceList();
+    BTDevice* btdevs[8];
+    int count = Bluetooth.GetDevices(btdevs,8);
+    for (int i = 0; i < count; i++)
+        //if (memcmp(devs[i]->_info.dev_class, FtDevClass, 3)==0)
+    {
+        devs.push_back(new ftusbdevtxbt(btdevs[i]));
+        printf("%d: %s\n", i, btdevs[i]->_name);
+    }
+    return 0;
+}
+
+int ftusbdevtxbt::read_data(unsigned char *data, int size, USBCallback callback, void* userData) {
+    return 0;
+}
+
+int ftusbdevtxbt::write_data(unsigned char *data, int size, USBCallback callback, void* userData) {
+    return Socket_Send(device, data, size);
+}
+
+unsigned ftusbdevtxbt::GetFtSerialNr() {
+    return sn;
+}
+
+void ftusbdevtxbt::parse (const unsigned char *buf, unsigned len) {
+    unsigned i = 0;
+    //printf("start parse, state = %d, len = %d\n", parseState, len);
+    while (i < len) {
+        char c = buf[i++];
+        switch (parseState) {
+            case 0: //ascii state
+                if (c==2)
+                    parseState = 1;
+                else {
+                    putc(c, stdout);
+                    console.put(c);
+                }
+                break;
+            case 1:
+                if (c==0x55)
+                    parseState = 2;
+                else {
+                    parseState = 0;
+                    printf("expected 0x55 in X1 header, found %02X\n", c);
+                }
+                break;
+            case 2:
+                X1_len = c<<8;
+                X1_crc = c;
+                parseState= 3;
+                break;
+            case 3:
+                X1_len += c;
+                X1_crc += c;
+                parseState= 4;
+                X1_pkt = new unsigned char[X1_len];
+                //printf("net length = %d\n", X1_len);
+                X1_pos = 0;
+                break;
+            case 4:
+                if  (X1_pos < X1_len) {
+                    X1_pkt[X1_pos++] = c;
+                    X1_crc += c;
+                } else { //c is first checksum byte (MSB!)
+                    parseState = 6;
+                    X1_crc += c<<8;
+                }
+                break;
+            case 5:
+                //X1_crc = c<<8;
+                X1_crc += c;
+                parseState= 6;
+                break;
+            case 6:
+                X1_crc += c;
+                parseState= 7;
+                break;
+            case 7:
+                if (c == 3 && X1_crc == 0) {
+                    //printHex(X1_pkt, X1_len);
+                  if (transferAktiv == FTX1SYNC)
+                    FtThreadEnd();
+                  else
+                    X1_cmd = rec_msg2((headerbody*)X1_pkt, X1_len);
+                  delete[] X1_pkt;
+                } else
+                    printf("framing or checksum error, end char = %02X, sum=%04X\n", c, X1_crc);
+
+                parseState = 0;
+                break;
+        }
+    }
+    //printf("Leaving parse, state = %d, i = %d (last char = %02X)\n", parseState, i, buf[i-1]);
+}
+
+void ftusbdevtxbt::receive(int socket, SocketState state, const u8* data, int len) {
+    //printf("ftusbdevtxbt::receive was called: socket %d, state=%d, length=%d\n", socket, state, len);
+    static const unsigned char req[] = "\xdget_ser_num\xd";
+    char line[80];
+    if (len==0) {
+        switch (state) {
+            case SocketState_Opening:
+                break;
+            case SocketState_Open:
+                console.flush();
+                send_msg(1, 0, false); //ping
+                init = ping;
+                break;
+            case SocketState_Closing:
+            case SocketState_Closed:
+                return;
+        }
+    } else {
+        //printHex(data, len);
+        parse(data, len);
+        switch (init) {
+            case idle:
+                break;
+            case ping:
+                if (X1_cmd == 1) {
+                    printf("sending sernum request \n%s\n", req);
+                    Socket_Send(socket, req, strlen((char*)req));
+                    init = serial;
+                }
+                break;
+            case serial:
+                while (console.gets(line, 80)==0) {
+                    printf("Line=%s\n", line);
+                    if (sscanf(line, "%d", &sn) == 1) {
+                        printf("Got S/N=%d\n", sn);
+                        send_msg(6, 1, false); //get INFO for master
+                        init = info;
+                    }
+                }
+                break;
+            case info:
+                if (X1_cmd == 6) {
+                    printf("Master=%s\n", ta[0]->info.device_name);
+                    send_msg(7, 1, false); //get state for master
+                    init = slaves;
+                }
+                break;
+            case slaves:
+                if (X1_cmd == 7) {/*
+                    for (int i = 1; i <= N_EXT_DEV; i++)
+                        if (ta[0]->state.ext_dev_connect_state[i-1]) {
+                            if (ta[i] == 0) { //new slave
+                                ta[i] = new TA;
+                                memset(ta[i], 0, sizeof(TA));
+                                active |= 1<<i;
+                                printf("New Extension %d = %s\n", i, ta[i]->info.device_name);
+                                if (cbRoboExtState) cbRoboExtState(i, 1);
+                            }
+                        } else {
+                            if (ta[i]) {//should not happen during initialisation
+                                delete ta[i];
+                                ta[i] = 0;
+                                active &= ~(1<<i);
+                                printf("Extension %d went offline\n", i);
+                                if (cbRoboExtState) cbRoboExtState(i, 0);
+                            }
+                        }
+                    if (active != 1) {
+                        send_msg(6, active & ~1, false); //get info for slaves;
+                        init = slaves_info;
+                    } else*/
+                        init = ready;
+                }
+                break;
+            case slaves_info:
+                if (X1_cmd == 6) {
+                    init = ready;
+                }
+                break;
+            case ready://normal message processing
+                break;
+        }
+    }
+}
+
+unsigned ftusbdevtxbt::OpenFtUsbDevice() {
+    ta[0] = new TA;
+    memset(ta[0], 0, sizeof(TA));
+    active = 1;
+    L2CAPAddr s;
+    s.bdaddr = btaddr;
+    s.psm = 1;//abuse the psm for the channelID
+    device = Socket_Open(SOCKET_RFCOM, &s.hdr, recv, this);//Open the serial connection via RFCOMM
+    if (device<=0) {
+        printf("Opening of RFCOMM socket for ftdevice failed (%d)\n", device);
+        delete ta[0];
+        ta[0] = 0;
+        return FTLIB_ERR_FAILED;
+    }
+    return 0;
+}
+
+unsigned ftusbdevtxbt::CloseFtDevice() {
+    if (ta[0]==0)
+        return FTLIB_ERR_DEVICE_NOT_OPEN;
+    while (transferAktiv != FTX1STOP) {
+        fprintf(stderr, "Transfer ta still active\n");
+        wait(1);
+    }
+    for (int i = 0; i < N_EXT_DEV; i++)
+        if (ta[i]!=0) {
+            delete ta[i];
+            ta[i] = 0;
+        }
+    init = idle;
+    unsigned retval = Socket_Close(device);
+    if (retval) {
+      printf("Socket_Close(%d) returned %d\n", device, retval);
+      return FTLIB_ERR_FAILED; //or whatever
+    }
+    return 0;
+}
+
+
+
+void ftusbdevtxbt::FtThreadBegin() {
+    if (init != ready) {//still initialising
+      busy = false;
+      return;
+    }
+    ftusbdevtx::FtThreadBegin();
+}
+
+void ftusbdevtxbt::FtThreadEnd() {
+    if (!test_and_set()) {//skip when busy
+        busy = false;
+        printf("TA busy: skip end slot\n");
+        return;
+    }
+    X1_cmd = rec_msg2((headerbody*)X1_pkt, X1_len); //parse the message
+    increment(); //release the TA mutex
+    if (ne.NotificationCallback) {
+        ne.NotificationCallback(ne.Context);
+    }
+    transferAktiv = FTX1RUN;//TA update complete
+    if (tid%100 == 0) { //about every 1 seconds
+//        getSlaveInfo(); //synchronous! TODO: change to non-blocking
+    }
+    busy = false;  //ready for the next tick
+//    printf("Busy released\n");
+}
+#if 0
+
+UINT16 ftusbdevtxbt::checksum(unsigned char *p, unsigned n) {
+    UINT16 sum = 0;
+    do {
+        sum -= *p++;
+    } while (--n);
+    return (sum<<8)|(sum>>8);
+}
+
+void ftusbdevtxbt::dump_buffer(int size) {
+    if (buffer==0) {
+        printf("No buffer\n");
+        return;
+    }
+    for (int i = 0; i < size; i++) {
+        printf("%02X ", buffer[i]);
+        if (i%16 == 15) printf("\n");
+    }
+    printf("----------------------\n");
+}
+
+unsigned ftusbdevtxbt::send_msg(unsigned cmd, unsigned set, bool sync) {
+    const unsigned sizes[] = {0, 0, //cmd 1
+                              sizeof(TA_OUTPUT)+sizeof(UINT32), //cmd 2
+                              0, //unknown
+                              0, //unknown
+                              sizeof(TA_CONFIG)+sizeof(UINT32), //cmd 5
+                              sizeof(UINT32), //cmd 6
+                              sizeof(UINT32), //cmd 7
+                              sizeof(DISPLAY_MSG)+sizeof(UINT32), //cmd 8
+                              DEV_NAME_LEN + 1+3 + sizeof(UINT32) //cmd 9
+                             };
+    int ret = 0;
+    int n = 0;
+    for (int i = TA_LOCAL; i < TA_N_PARTS; i++) {
+        if (set & (1<<i)) {
+            n++;
+        }
+    }
+    unsigned size = 0;
+    if (cmd < sizeof(sizes)/sizeof(unsigned))
+        size = sizes[cmd];
+    unsigned payload_size = n*size;
+    num_read = sizeof(header)+sizeof(trailer);
+    unsigned total_size = sizeof(header)+payload_size+sizeof(trailer);
+    buffer = new unsigned char[total_size]; //size must be known in advance
+
+    unsigned net_size = total_size-sizeof(UINT32)-sizeof(trailer);//exclude start,len,crc,etx
+    header *hdr = (header*)buffer;
+    hdr->start = 0x5502;
+    hdr->bytesH = net_size>>8;
+    hdr->bytesL = net_size&0xff;
+    hdr->snd = 2;
+    hdr->rec = 1;
+    hdr->trans = ++tid;
+    hdr->session = sid;
+    hdr->cmd = cmd;
+    hdr->structs = n;
+    unsigned char* payload = buffer+sizeof(header);
+    for (int i = TA_LOCAL; i < TA_N_PARTS; i++) {
+        if (ta[i]==0 || !(set & (1<<i))) {
+            if (set & (1<<i)) printf("TX %d is not open yet!\n", i);
+            continue;
+        }
+        unsigned *id = (unsigned*)payload;
+        *id = i;
+        payload = (unsigned char*)(id+1);
+        num_read += sizeof(UINT32);
+        switch (cmd) {
+            case 1:
+                break;
+            case 2:
+                memcpy(payload, &ta[i]->output, sizeof(TA_OUTPUT));
+                payload += sizeof(TA_OUTPUT);
+                num_read += sizeof(TA_INPUT);
+                break;
+            case 5:
+                memcpy(payload, &ta[i]->config, sizeof(TA_CONFIG));
+                payload += sizeof(TA_OUTPUT);
+                break;
+            case 6:
+                num_read += sizeof(TA_INFO);
+                break;
+            case 7:
+                num_read += sizeof(TA_STATE);
+                break;
+            case 8:
+                memcpy(payload, &ta[i]->display.display_msg, sizeof(DISPLAY_MSG));
+                payload += sizeof(DISPLAY_MSG);
+                break;
+            case 9:
+                memcpy(payload, ta[i]->info.device_name, DEV_NAME_LEN + 1+3);
+                payload += sizeof(DEV_NAME_LEN + 1+3);
+                break;
+            default:
+                printf("Unknown message type %d\n", cmd);
+                break;
+        }
+    }
+    trailer *trl = (trailer*)payload;
+    trl->chksum = checksum(buffer+2, net_size+2);
+    trl->etx = '\x03';
+    num_read--;
+    //dump_buffer(total_size);
+    //printf("Expecting %d bytes for transaction %d\n", num_read, tid);
+    if (sync) {
+        ret = USBBulkTransfer(device, 3, buffer, total_size-1);//send 1 less because trailer is 1 too long due to alignment
+        delete[] buffer;
+        if (ret < 0)
+            printf("synchronous send_message failed (%d)\n", ret);
+        else {
+            buffer = new unsigned char[num_read];
+            ret = USBInterruptTransfer(device, 0x82, buffer, num_read);
+            if (ret < 0) {
+                printf("synchronous read failed (%d)\n", ret);
+                delete[] buffer;
+            } else {
+                //dump_buffer(num_read);
+                rec_msg();
+            }
+        }
+    } else
+        USBBulkTransfer(device, 3, buffer, total_size-1, &ftusbdevtxbt::write_finished_cb, this);
+    return ret;
+}
+
+unsigned ftusbdevtxbt::rec_msg() {
+    header *hdr = (header*)buffer;
+    //dump_buffer(num_read);
+    if (hdr->start != 0x5502) printf("Invalid packet\n");
+    unsigned net_size = (hdr->bytesH<<8) + hdr->bytesL;
+    if (net_size+7 != num_read) printf("message has %d bytes, was expecting %d bytes\n", net_size+7, num_read);
+    //printf("message %d from %d\n", hdr->cmd, hdr->snd);
+    if (hdr->rec != 2) printf("Wrong destination (%d)\n", hdr->rec);
+    if (hdr->trans != tid) printf("Response to request %d, expected %d\n", hdr->trans, tid);
+    if (hdr->session != sid) {
+        printf("Session number has changed from %d to %d\n", sid, hdr->session);
+        sid = hdr->session;
+        tid = 1; //restart transaction sequence
+    }
+    unsigned cmd = hdr->cmd - 100;
+    unsigned n = hdr->structs;
+    unsigned char* payload = buffer+sizeof(header);
+    trailer *trl = (trailer*)(buffer+net_size+4);
+    for (int i = 0; i < n && payload < (unsigned char*)trl; i++) {
+        unsigned *id = (unsigned*)payload;
+        if (*id >= TA_N_PARTS) {
+            printf("Illegal extension nr %d\n", *id);
+            continue;
+        }
+        if (ta[*id]==0) {
+            printf("Message for new device %d\n", *id);
+            continue;//skip the copy to avoid assignment to null ta but the payload pointer is not advanced! stopping further copying
+        }
+        payload = (unsigned char*)(id+1);
+        switch (cmd) {
+            case 1:
+                break;
+            case 2:
+                memcpy(&ta[*id]->input, payload, sizeof(TA_INPUT));
+                payload += sizeof(TA_INPUT);
+                break;
+            case 5:
+                break;
+            case 6:
+                memcpy(&ta[*id]->info, payload, sizeof(TA_INFO));
+                payload += sizeof(TA_INFO);
+                break;
+            case 7:
+                memcpy(&ta[*id]->state, payload, sizeof(TA_STATE));
+                payload += sizeof(TA_STATE);
+                break;
+            case 8:
+                break;
+            case 9:
+                break;
+            default:
+                printf("Unknown message type %d\n", cmd);
+                break;
+        }
+    }
+    if (payload != (unsigned char*)trl) printf("expected %d sections with in total %d bytes; got %d bytes\n", n, payload-buffer-sizeof(header), net_size-sizeof(header));
+    if (trl->chksum != checksum(buffer+2, net_size+2)) printf("Checksum error\n");
+    if (trl->etx != '\x03') printf("Expected ETX(03), got %02X\n", trl->etx);
+    delete[] buffer;
+    return 0;
+}
+
+void ftusbdevtxbt::read_finished_cb(int device, int endpoint, int status, u8* data, int len, void* userData) {
+//end of reply transfer
+//printf("read_finished_cb: %d bytes\n", len);
+    ftusbdevtx *fth = (ftusbdevtx*)userData;
+    if (fth->transferAktiv == FTX1SYNC)
+        fth->FtThreadEnd();
+    else
+        fth->rec_msg();
+}
+
+void ftusbdevtxbt::write_finished_cb(int device, int endpoint, int status, u8* data, int len, void* userData) { //end of request transfer, issue, reply transfer
+    ftusbdevtx *fth = (ftusbdevtx*)userData;
+//printf("write_finished_cb: wrote %d bytes, reading %d bytes\n", len, fth->num_read);
+    delete[] fth->buffer;
+    fth->buffer = new unsigned char[fth->num_read];
+    USBInterruptTransfer(fth->device, 0x82, fth->buffer, fth->num_read, read_finished_cb, fth);
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclasstxcbt.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,57 @@
+#ifndef FTLIBCLASSTXCBT_H
+#define FTLIBCLASSTXCBT_H
+#include "ftlibclasstxc.h"
+#include "ftusb.h"
+//#include <string.h>
+//#define FT_TXC  300
+
+//#include "ROBO_TX_FW.h" //"../PC_programming_RoboTXC_V1-2_11_Dec_2009/PC_Programming_RoboTXC/Demo_Static_Lib_C/Inc/"
+#include "ROBO_TX_FW_1_24.h" //"../PC_programming_RoboTXC/PC_Programming_RoboTXC/Demo_Static_Lib_C/Inc/"
+
+class ftusbdevtxbt: public ftusbdevtx {
+    friend ftusbdev;
+    BD_ADDR btaddr;
+    char *name;
+    enum { idle, ping, serial, info, slaves, slaves_info, ready} init;
+    int message_pending;
+    int parseState;
+    unsigned short X1_crc, X1_len, X1_pos, X1_cmd;
+    unsigned char *X1_pkt;
+    //ftusbdevtxbt() {}
+    ftusbdevtxbt(BTDevice *bd);
+    //virtual void FtThreadInit() ;
+    virtual void FtThreadBegin() ;
+    virtual void FtThreadEnd() ;
+    //unsigned set_baudrate(unsigned br);
+    //unsigned send_msg(unsigned cmd, unsigned set=0, bool sync = true);
+    //unsigned rec_msg();
+    //static void read_finished_cb(int device, int endpoint, int status, unsigned char* data, int len, void* userData);
+    //static void write_finished_cb(int device, int endpoint, int status, unsigned char* data, int len, void* userData);
+    virtual int read_data(unsigned char *data, int size, USBCallback callback = 0, void* userData = 0);// { return USBBulkTransfer(device, 0x82, data, size, callback, userData);}
+    virtual int write_data(unsigned char *data, int size, USBCallback callback = 0, void* userData = 0);// { return USBBulkTransfer(device, 0x03, data, size, callback, userData);}
+    static void recv(int socket, SocketState state, const u8* data, int len, void* userData) {
+        if (userData) ((ftusbdevtxbt*)userData)->receive(socket, state, data, len);
+    }
+    void receive(int socket, SocketState state, const u8* data, int len);// {printf("ftdev::receive was called: socket %d, state=%d, length=%d\n", socket, state, len);}
+    void parse (const unsigned char *buf, unsigned len);
+public:
+    //virtual ~ftusbdevtxbt() ;
+//public API: These functions match those of the original ftlib
+    virtual unsigned set_baudrate(unsigned br) {
+        return 0;
+    }
+    static unsigned InitFtUsbDeviceList();//overrides ftusbdev (also adds BT devices)
+    virtual unsigned OpenFtUsbDevice(); //ftxOpenComDevice, we regard a TXC as a USB device
+    virtual unsigned CloseFtDevice(); //ftxCloseDevice, ftxCloseAllDevices (ftlibclass)
+    //virtual unsigned IsFtTransferActiv();
+    //virtual unsigned GetFtFirmware() ;
+    virtual unsigned GetFtSerialNr();
+    virtual char*     GetFtLongNameStrg() {
+        return strdup(name);
+    }
+    //TA*  GetFtTransferAreaAddress(int i) ;
+    //virtual unsigned      StartFtTransferArea(NOTIFICATION_EVENTS* sNEvent );
+};
+ 
+#endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclassusb.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,454 @@
+#include "mbed.h"
+#include "ftusb.h"
+#include "ftlibclass.h"
+#include "ftlibclassusb.h"
+#include "ftlibclasstxc.h"
+
+#ifdef USE_DOWNLOAD
+#include "crc.h"
+#endif
+
+#define VERSION_MAJOR LIBFT_VERSION_MAJOR
+#define VERSION_MINOR LIBFT_VERSION_MINOR
+#define VERSION_PATCH LIBFT_VERSION_PATCH
+#define ABF_IF_COMPLETE 0x8b // 0xf2
+#define INTERFACE_QUERY_TIME_SERIAL 10000
+#define FT_ENDPOINT_INTERRUPT_IN 0x81
+#define FT_ENDPOINT_INTERRUPT_OUT 0x1
+#define FT_ENDPOINT_BULK_IN 0x82
+#define FT_ENDPOINT_BULK_OUT 0x2
+#define FT_RF_ENDPOINT_INTERRUPT_IN 0x82
+#define FT_RF_ENDPOINT_INTERRUPT_OUT 0x2
+#define FT_USB_TIMEOUT 1000
+#define FT_USB_TIMEOUT_LONG 10000
+#define PROGRAM_UPLOAD_PACKET_SIZE 128
+
+#define GET_MAN     1
+#define GET_LONG    2
+#define GET_SN      3
+#define GET_FW      4
+#define GET_SHORT   5
+
+#define usleep(x)    wait_us(x)
+#define sleep(x)    wait(x)
+
+vector<ftusbdev*> ftusbdev::devs;
+
+int ftusbdev::GetNumFtDevicesFromRF(int device) {
+    unsigned iNum = 0;
+    int ret;
+    unsigned char buffer[35] = { 0 };
+    for (int i=1; i<9; i++) {
+        ret = USBControlTransfer(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, 0, 0);
+        if (ret < 0) {
+            fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
+            return ret;
+        } else if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device
+            iNum++;
+            unsigned snr = *(unsigned*)(buffer+3); //buffer[3] + buffer[4]*100 + buffer[5]*10000 + buffer[6]*1000000;
+            ftusbdev *d = new ftusbdev(device, FT_ROBO_IF_OVER_RF, snr, i);
+            d->fw = *(unsigned*)(buffer+20);
+            devs.push_back(d);//use datalink as type and assume little endianness
+        }
+    }
+    return iNum;
+}
+
+unsigned ftusbdev::InitFtUsbDeviceList() {
+    char buffer[128];
+    devs.clear();
+    for (vector<_ftdev>::iterator i = ::devs.begin(); i < ::devs.end(); i++) {
+        unsigned sn = 0;
+        if (i->product == 0x1000) { //TXC
+            devs.push_back(new ftusbdevtx(i->device));
+            continue;
+        }
+        if (GetString(i->device, GET_SN, buffer, 18) >= 0) {
+            sn = atoi(buffer);
+        } else {
+            printf("device %d did not respond\n", i->device);
+            continue;
+        }
+        if (i->product == RF_DATA_LINK_PRODUCT_ID) {//robo over RF
+            ftusbdev *dl = new ftusbdev(i->device, ftlib::FtproductIDToInterfaceID(i->product), sn, 0); //the RF call ID of the link is 0 but this is useless
+            devs.push_back(dl);
+            int pos = devs.size(); //position of first appended RF interface
+            int n = GetNumFtDevicesFromRF(i->device);
+            if (n > 0) {
+                dl->rf = devs[pos]->rf; //use the rf of the first child
+            }
+        } else {
+            if (i->product == EXT_IF_PRODUCT_ID)
+                devs.push_back(new ftusbdevext(i->device, ftlib::FtproductIDToInterfaceID(i->product), sn));
+            else
+                devs.push_back(new ftusbdev(i->device, ftlib::FtproductIDToInterfaceID(i->product), sn));
+        }
+    }
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+ftusbdev* ftusbdev::GetFtUsbDeviceHandle(unsigned  Num) {
+    if (Num < devs.size()) {
+        return devs[Num];
+    }
+    return 0;
+}
+
+ftusbdev* ftusbdev::GetFtUsbDeviceHandleSerialNr(unsigned dwSN, unsigned dwTyp) {
+    for (int i = 0; i < devs.size(); i++)
+        if (devs[i]->sn == dwSN) {
+            if (dwTyp == 0 || dwTyp == devs[i]->type)
+                return GetFtUsbDeviceHandle(i);
+        }
+    fprintf(stderr, "GetFtUsbDeviceSerialNr(%d, %d) not found\n", dwSN, dwTyp);
+    return 0;
+}
+
+unsigned ftusbdev::OpenFtUsbDevice() {
+    FT_TRANSFER_AREA *area = new FT_TRANSFER_AREA;
+    memset(area, 0, sizeof(struct _FT_TRANSFER_AREA));
+    area->RfModulNr = rf;
+    area->TransferAktiv = 0;
+    ta = area;
+    return 0;
+}
+
+unsigned ftusbdev::CloseFtDevice() {
+    if (ta==0)
+      return FTLIB_ERR_DEVICE_NOT_OPEN;
+    while (ta->TransferAktiv != 0) {
+        fprintf(stderr, "Transfer ta still active\n");
+        sleep(1);
+    }
+    delete ta;
+    ta = 0;
+    return 0;
+}
+
+unsigned ftusbdev::GetFtFirmware() {
+    int ret;
+    unsigned char buffer[35] = { 0 };
+    if (fw > 0)
+        return fw;
+    switch (type) {
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_IO_EXTENSION:
+        case FT_ROBO_RF_DATA_LINK:
+            ret = USBControlTransfer(device, 0xc0, 0xf0, 0x1, 0, buffer, 5);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
+                return 0;
+            }
+            fw = buffer[1] | buffer[2]<<8 | buffer[3]<<16 | buffer[4]<<24;
+            break;
+        case FT_ROBO_IF_OVER_RF:
+            ret = USBControlTransfer(device, 0xc0, 0x52, rf<<8 | 0x05, 0, buffer, 35);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
+                return 0;
+            }
+            if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device
+                fw = buffer[23]<<24 | buffer[22]<<16 | buffer[21]<<8 | buffer[20];
+            }
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+    return fw;
+}
+
+char * ftusbdev::GetFtLongNameStrg() {
+    const int sz = 128;
+    char *buffer = new char[sz];
+    buffer[0] = '\0';
+
+    switch (type) {
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_RF_DATA_LINK:
+        case FT_ROBO_IO_EXTENSION:
+            GetString(device, GET_LONG, buffer, sz);
+            break;
+        case FT_ROBO_IF_OVER_RF:
+            sprintf(buffer, " Robo Interface (RF:%d)", rf);
+            break;
+    }
+    return buffer;
+}
+
+char * ftusbdev::GetFtShortNameStrg() {
+    const int sz = 128;
+    char *buffer = new char[sz];
+    buffer[0] = '\0';
+
+    switch (type) {
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_RF_DATA_LINK:
+        case FT_ROBO_IO_EXTENSION:
+            GetString(device, GET_SHORT, buffer, sz);
+            break;
+        case FT_ROBO_IF_OVER_RF:
+            sprintf(buffer, " (RF:%d)", rf);
+            break;
+    }
+    return buffer;
+}
+
+char * ftusbdev::GetFtManufacturerStrg() {
+    const int sz = 128;
+    char *buffer = new char[sz];
+    buffer[0] = '\0';
+    GetString(device, GET_MAN, buffer, sz);
+    return buffer;
+}
+
+void ftusbdev::poll() {
+    for (int i = 0; i < devs.size(); i++) {
+        if (devs[i]->triggered) {
+            if (devs[i]->guardedFtThreadBegin())
+                devs[i]->triggered = 0;
+        }
+    }
+    //USBLoop();
+}
+
+void ftusbdev::FtThreadInit() {//setup buffers for this type of interface
+    num_write = ABF_IF_COMPLETE_NUM_WRITE;
+    num_read = ABF_IF_COMPLETE_NUM_READ;
+    out[0] = ABF_IF_COMPLETE;
+    ftdev::FtThreadInit();
+    unsigned ret;
+    switch (type) {
+        case FT_ROBO_IF_OVER_RF:
+        case FT_ROBO_RF_DATA_LINK:
+            usb_endpoint_write = FT_RF_ENDPOINT_INTERRUPT_OUT;
+            usb_endpoint_read = FT_RF_ENDPOINT_INTERRUPT_IN;
+            ret = USBControlTransfer(device, 0xc0, 0xfb, rf << 8 | 0x02, 0x1, in, 2, 0, 0);
+            if (ret != 2) {
+                fprintf(stderr, "%d FtThread: Error initiating RF Module!\n");
+                //ta->TransferAktiv = 0;
+            }
+            break;
+        default: //FT_ROBO_USB
+            usb_endpoint_write = FT_ENDPOINT_INTERRUPT_OUT;
+            usb_endpoint_read = FT_ENDPOINT_INTERRUPT_IN;
+            break;
+    }
+}
+
+void ftusbdev::read_finished_cb(int device, int endpoint, int status, u8* data, int len, void* userData) {
+//end of reply transfer
+    ftusbdev *fth = (ftusbdev*)userData;
+    fth->FtThreadEnd();
+}
+
+void ftusbdev::write_finished_cb(int device, int endpoint, int status, u8* data, int len, void* userData) { //end of request transfer, issue, reply transfer
+    ftusbdev *fth = (ftusbdev*)userData;
+    USBInterruptTransfer(fth->device, fth->usb_endpoint_read, fth->in, fth->num_read, read_finished_cb, fth);
+}
+
+//here the real data exchange starts
+void ftusbdev::FtThreadBegin() {//called every 10ms to issue a request, should be non-blocking
+    if (!test_and_set()) {//return when transferarea is in use
+        busy = false; //release the mutex, otherwise the thread effectively stops
+        return;//return because there is no point in sending a nonsense request, alternatively the lock can be ignored in which case the data may be inconsistent
+    }
+//putc('(', stderr);
+    out[1] = ta->M_Main;
+    out[2] = (ta->MPWM_Main[0] & 0x7) | (ta->MPWM_Main[1]<<3 & 0x38) | (ta->MPWM_Main[2]<<6 & 0xC0);
+    out[3] = (ta->MPWM_Main[2] & 0x1) | (ta->MPWM_Main[3]<<1 & 0xE) | (ta->MPWM_Main[4]<<4 & 0x70) | (ta->MPWM_Main[5]<<7 & 0x80);
+    out[4] = (ta->MPWM_Main[5] & 0x3) | (ta->MPWM_Main[6]<<2 & 0x1C) | (ta->MPWM_Main[7]<<5 & 0xE0);
+    out[5] = ta->M_Sub1;
+    out[6] = (ta->MPWM_Sub1[0] & 0x7) | (ta->MPWM_Sub1[1]<<3 & 0x38) | (ta->MPWM_Sub1[2]<<6 & 0xC0);
+    out[7] = (ta->MPWM_Sub1[2] & 0x1) | (ta->MPWM_Sub1[3]<<1 & 0xE) | (ta->MPWM_Sub1[4]<<4 & 0x70) | (ta->MPWM_Sub1[5]<<7 & 0x80);
+    out[8] = (ta->MPWM_Sub1[5] & 0x3) | (ta->MPWM_Sub1[6]<<2 & 0x1C) | (ta->MPWM_Sub1[7]<<5 & 0xE0);
+    out[9] = ta->M_Sub2;
+    out[10] = (ta->MPWM_Sub2[0] & 0x7) | (ta->MPWM_Sub2[1]<<3 & 0x38) | (ta->MPWM_Sub2[2]<<6 & 0xC0);
+    out[11] = (ta->MPWM_Sub2[2] & 0x1) | (ta->MPWM_Sub2[3]<<1 & 0xE) | (ta->MPWM_Sub2[4]<<4 & 0x70) | (ta->MPWM_Sub2[5]<<7 & 0x80);
+    out[12] = (ta->MPWM_Sub2[5] & 0x3) | (ta->MPWM_Sub2[6]<<2 & 0x1C) | (ta->MPWM_Sub2[7]<<5 & 0xE0);
+    out[13] = ta->M_Sub3;
+    out[14] = (ta->MPWM_Sub3[0] & 0x7) | (ta->MPWM_Sub3[1]<<3 & 0x38) | (ta->MPWM_Sub3[2]<<6 & 0xC0);
+    out[15] = (ta->MPWM_Sub3[2] & 0x1) | (ta->MPWM_Sub3[3]<<1 & 0xE) | (ta->MPWM_Sub3[4]<<4 & 0x70) | (ta->MPWM_Sub3[5]<<7 & 0x80);
+    out[16] = (ta->MPWM_Sub3[5] & 0x3) | (ta->MPWM_Sub3[6]<<2 & 0x1C) | (ta->MPWM_Sub3[7]<<5 & 0xE0);
+    out[17]    = 0;
+    if (messages && messages->nrOfMessages()>0) {
+        out[18]    = 0;
+        *(SMESSAGE*)(out+19) = messages->pop();
+    } else {
+        memset(out+18, 0, 7);
+    }
+    if (messages && messages->nrOfMessages()>0) {
+        out[25]    = 0;
+        *(SMESSAGE*)(out+26) = messages->pop();
+    } else {
+        memset(out+25, 0, 7);
+    }
+    increment();//release the lock on shared memeory
+    USBInterruptTransfer(device, usb_endpoint_write, out, num_write, write_finished_cb, this); //return immediately and call the callback when finished
+}
+#if 0 //use the parent version
+void ftusbdev::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete
+    if (!test_and_set()) {//skip when busy
+        busy = false;
+        return;
+    }
+    ta->ChangeEg = ta->E_Main != in[0] || ta->E_Sub1 != in[1] || ta->E_Sub2 != in[2] || ta->E_Sub3 != in[3];
+    ta->E_Main = in[0];
+    ta->E_Sub1 = in[1];
+    ta->E_Sub2 = in[2];
+    ta->E_Sub3 = in[3];
+    ta->ChangeAn = 1; //assume that analog always changes (noise)
+    ta->AX = in[4];
+    ta->AY = in[5];
+    ta->A1 = in[6];
+    ta->A2 = in[7];
+    ta->AX |= (in[8] & 0x3) << 8;
+    ta->AY |= (in[8] & 0xC) << 6;
+    ta->A1 |= (in[8] & 0x30) << 4;
+    ta->A2 |= (in[8] & 0xC0) << 2;
+    ta->AZ = in[9];
+    ta->D1 = in[10];
+    ta->D2 = in[11];
+    ta->AV = in[12];
+    ta->AZ |= (in[13] & 0x3) << 8;
+    ta->D1 |= (in[13] & 0xC) << 6;
+    ta->D2 |= (in[13] & 0x30) << 4;
+    ta->AV |= (in[13] & 0xC0) << 2;
+    if (ta->IRKeys != in[14])
+        ta->ChangeIr = 1;
+    ta->IRKeys = in[14];
+    ta->BusModules = in[15];
+    // 16
+    ta->AXS1 = in[17];
+    ta->AXS2 = in[18];
+    ta->AXS3 = in[19];
+    ta->AXS1 |= (in[20] & 0x3) << 8;
+    ta->AXS2 |= (in[20] & 0xC) << 6;
+    ta->AXS3 |= (in[20] & 0x30) << 4;
+    // 21
+    ta->AVS1 = in[22];
+    ta->AVS2 = in[23];
+    ta->AVS3 = in[24];
+    ta->AVS1 |= (in[25] & 0x3) << 8;
+    ta->AVS2 |= (in[25] & 0xC) << 6;
+    ta->AVS3 |= (in[25] & 0x30) << 4;
+    // 26...42
+    ta->AV *= 3;
+    ta->AVS1 *= 3;
+    ta->AVS2 *= 3;
+    ta->AVS3 *= 3;
+    //message processing
+    if (messages && ne.CallbackMessage) { //just to check if communication was enabled
+        if (in[28])
+            ne.CallbackMessage((SMESSAGE*)(in+29));
+        if (in[35])
+            ne.CallbackMessage((SMESSAGE*)(in+36));
+    }
+    increment();
+    interface_connected = 1;
+    if (ne.NotificationCallback) {
+        (*ne.NotificationCallback)(ne.Context);
+    }
+    busy = false;
+}
+#endif
+
+void ftusbdev::FtThreadFinish() {//called by StopFtTransferArea
+    if (type == FT_ROBO_IF_OVER_RF || type == FT_ROBO_RF_DATA_LINK) {
+        int ret = USBControlTransfer(device, 0xc0, 0x21, rf << 8, 0, in, 1);
+        if (ret != 1 || in[0] != 0xd7) {
+            fprintf(stderr, "Error uninitiating RF Module!\n");
+        }
+    }
+    ftdev::FtThreadFinish();
+}
+
+unsigned ftusbdev::SetFtDeviceCommMode (unsigned dwMode, unsigned dwParameter, unsigned short *puiValue) {
+    unsigned char buf[3];
+    unsigned  ret = USBControlTransfer(device, 0xc0, 0xf0, 0x0040, dwMode|(dwParameter<<8), buf, 3);
+    if (puiValue && dwMode == IF_COM_PARAMETER)
+        *puiValue = buf[1];
+    return ret;
+}
+
+void ftusbdevext::FtThreadInit() {//setup buffers for this type of interface
+    usb_endpoint_write = FT_ENDPOINT_INTERRUPT_OUT;
+    usb_endpoint_read = FT_ENDPOINT_INTERRUPT_IN;
+    ftdev::FtThreadInit();
+    out[0] = 0xf2;
+    num_write = 6;
+    num_read = 6;
+}
+
+void ftusbdevext::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete
+    if (!test_and_set()) {//skip when busy
+        busy = false;
+        return;
+    }
+    ta->ChangeEg = ta->E_Main != in[0];
+    ta->E_Main = in[0];
+    ta->ChangeAn = 1; //assume that analog always changes (noise)
+    ta->AX = in[1];
+    ta->A1 = in[2];
+    ta->AV = in[3];
+    ta->AX |= (in[4] & 0x3) << 8;
+    ta->A1 |= (in[4] & 0xC) << 6;
+    ta->AV |= (in[4] & 0x30) << 4;
+    ta->AV *= 3;
+    increment();
+    interface_connected = 1;
+//printf("%02X) ", ta->E_Main);
+    if (ne.NotificationCallback) {
+//        printf("%02X\r", transfer_area.E_Main);
+        (*ne.NotificationCallback)(ne.Context);
+    }
+    busy = false;
+}
+
+unsigned ftusbdev::SetFtDistanceSensorMode(unsigned dwMode, unsigned dwTol1, unsigned dwTol2, unsigned dwLevel1, unsigned dwLevel2, unsigned dwRepeat1, unsigned dwRepeat2) {
+    int ret;
+    unsigned char buffer[] =  {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 34
+
+    buffer[1] = dwTol1;
+    buffer[2] = dwTol2;
+    buffer[3] = dwLevel1;
+    buffer[4] = dwLevel1>>8;
+    buffer[5] = dwLevel2;
+    buffer[6] = dwLevel2>>8;
+    buffer[7] = dwRepeat1;
+    buffer[8] = dwRepeat2;
+
+    switch (type) {
+        case FT_ROBO_IF_USB:
+            ret = USBControlTransfer(device, 0x40, 0xf1, 0x1, dwMode, buffer+1, 8);
+            if (ret != 8) {
+                fprintf(stderr, "Error sending control msg 0x40 0xf1\n");
+                return ret;
+            }
+            break;
+        case FT_ROBO_RF_DATA_LINK:
+        case FT_ROBO_IF_OVER_RF:
+            ret = USBControlTransfer(device, 0x40, 0x53, rf<<8 | 0x01, 0, buffer, 34);
+            if (ret != 34) {
+                fprintf(stderr, "Error sending control msg 0x40 0x53\n");
+                return ret;
+            }
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+    usleep(100000); // wait before continue, else it doesn't always work
+    return FTLIB_ERR_SUCCESS;
+}
+
+unsigned ftusbdev::pgm_message(unsigned code, unsigned dwMemBlock) {
+    unsigned char buffer[2];
+    if (type != FT_ROBO_IF_USB) return FTLIB_ERR_NOT_SUPPORTED;
+    int ret = USBControlTransfer(device, 0xc0, code, dwMemBlock, 0, buffer, 1);
+    if (ret < 0) {
+        fprintf(stderr, "Error sending control msg 0xC0 %02X\n", code);
+        return ret;
+    }
+    if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+    else return FTLIB_ERR_IF_NO_PROGRAM;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftlibclassusb.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,78 @@
+#ifndef FTLIBCLASSUSB_H
+#define FTLIBCLASSUSB_H
+
+#include <vector>
+#include "ftlibclassdev.h"
+
+#define FT_VENDOR_ID 0x146a
+#define ROBO_IF_PRODUCT_ID 0x1
+#define EXT_IF_PRODUCT_ID 0x2
+#define RF_DATA_LINK_PRODUCT_ID 0x3
+/*
+#define usleep(x)    wait_us(x)
+#define sleep(x)    wait(x)
+*/
+class ftlib;
+
+class ftusbdev: public ftdev {
+    friend ftlib;
+    virtual unsigned pgm_message(unsigned code, unsigned dwMemBlock);
+protected:
+    static vector<ftusbdev*> devs;
+    int device; //usb device nr
+    int rf; //rf call nr
+    int usb_endpoint_read, usb_endpoint_write;
+    ftusbdev() {}
+    ftusbdev(int d, int t, int s = 0, int r = -1): ftdev(t, s), device(d), rf(r) {}
+    static int GetNumFtDevicesFromRF(int device);
+    static void onTick() {
+        for (int i = 0; i < devs.size(); i++) devs[i]->trigger();
+    }
+    static void CloseAllFtDevices() {
+        for (int i = 0; i < devs.size(); i++) devs[i]->CloseFtDevice();
+    }
+    static void read_finished_cb(int device, int endpoint, int status, unsigned char* data, int len, void* userData);
+    static void write_finished_cb(int device, int endpoint, int status, unsigned char* data, int len, void* userData);
+    virtual void FtThreadInit();
+    virtual void FtThreadBegin();
+//    virtual void FtThreadEnd();
+    virtual void FtThreadFinish();
+public:
+    static void poll();
+//public API: These functions match those of the original ftlib
+    static unsigned InitFtUsbDeviceList();
+    static unsigned GetNumFtUsbDevice() {
+        return devs.size();
+    }
+    virtual unsigned OpenFtUsbDevice();
+    static ftusbdev* GetFtUsbDeviceHandle(unsigned DevNr);
+    static ftusbdev* GetFtUsbDeviceHandleSerialNr(unsigned dwSN, unsigned dwTyp);
+    unsigned      SetFtDeviceCommMode (unsigned dwMode, unsigned dwParameter, unsigned short *puiValue);
+    virtual unsigned      CloseFtDevice();
+    virtual unsigned      GetFtFirmware();
+    virtual char*     GetFtManufacturerStrg();
+    virtual char*     GetFtShortNameStrg();
+    virtual char*     GetFtLongNameStrg();
+    virtual unsigned      SetFtDistanceSensorMode(unsigned dwMode, unsigned dwTol1, unsigned dwTol2,
+            unsigned dwSchwell1, unsigned dwSchwell2, unsigned dwRepeat1, unsigned dwRepeat2);
+    /*
+    virtual unsigned      GetFtDeviceSetting(FT_SETTING *pSet);
+    virtual unsigned      SetFtDeviceSetting(FT_SETTING *pSet);
+    */
+    virtual unsigned StartFtProgram(unsigned dwMemBlock) {
+        return pgm_message(0x12, dwMemBlock);
+    }
+    virtual unsigned StopFtProgram() {
+        return pgm_message(0x13, 0);
+    }
+};
+
+class ftusbdevext: public ftusbdev {
+    friend ftusbdev;
+    ftusbdevext() {}
+    ftusbdevext(int d, int t, int s): ftusbdev(d, t, s) {}
+    virtual void FtThreadInit();
+    virtual void FtThreadEnd();
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftusb.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,177 @@
+#include "mbed.h"
+#include "USBHost.h"
+#include "ftusb.h"
+#include <vector>
+#include "HCITransportUSB.h"
+#include "Socket.h"
+#include "RFCOMM.h"
+#include "sdp.h"
+
+//  these should be placed in the DMA SRAM
+typedef struct {
+    u8 _hciBuffer[MAX_HCL_SIZE];
+    u8 _aclBuffer[MAX_ACL_SIZE];
+} SRAMPlacement;
+
+const char FtDevClass[3] = {0x00, 0x1F, 0x82 };
+const char SerDevClass[3] = {4, 1, 0x00};
+
+HCITransportUSB _HCITransportUSB;  //use USB as the transport to the radio
+BTApp Bluetooth;
+vector<_ftdev> devs;
+
+void OnLoadFtDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc) {
+    for (int i = 0; i < devs.size(); i++)
+        if (devs[i].device == device) {
+            printf("device %d was already in the list\n", device);
+            return;
+        }
+    switch (deviceDesc->idProduct) {
+        case 1:
+            devs.push_back(*new _ftdev(device, deviceDesc->idProduct, deviceDesc->iSerialNumber));
+            printf("RoboInterface\n");
+            break;
+        case 2:
+            devs.push_back(*new _ftdev(device, deviceDesc->idProduct, deviceDesc->iSerialNumber));
+            printf("RoboExtension\n");
+            break;
+        case 3:
+            devs.push_back(*new _ftdev(device, deviceDesc->idProduct, deviceDesc->iSerialNumber, 0));
+            printf("Robo RF Interface\n");
+            break;
+        case 4:
+            printf("Sound\n");
+            break;
+        case 4096:
+            devs.push_back(*new _ftdev(device, deviceDesc->idProduct, deviceDesc->iSerialNumber));
+            printf("TX Controller\n");
+            break;
+        default:
+            printf("fischertechnik product %d\n", deviceDesc->idProduct);
+            break;
+    }
+}
+
+
+int OnBluetoothInsert(int device) {//install the HCI and start discovery, user callbacks are made to HciCalback
+    printf("Bluetooth inserted of %d\n",device);
+    u32 sramLen;
+    u8* sram =  USBGetBuffer(&sramLen);
+    sram = (u8*)(((u32)sram + 1023) & ~1023);
+    SRAMPlacement* s = (SRAMPlacement*)sram;
+    _HCITransportUSB.Open(device,s->_hciBuffer,s->_aclBuffer);//setup buffers for USB host, incoming data goes first to HCIRecv and ACLRecv
+    RegisterSocketHandler(SOCKET_L2CAP,&Bluetooth); //register the application::hci as handler for L2CAP events
+    RegisterSocketHandler(SOCKET_RFCOM, &rfcomm_manager);//set the RFCOMMManager as the RFCOM socket handler
+    if (RegisterSocketHandler(SOCKET_SDP, &SDP))
+        printf("Could not register SDP socket type\n");
+    Bluetooth.Open(&_HCITransportUSB);//the callback is virtual, calls BTApp::Callback
+    Bluetooth.Inquiry();//start discovery of BT devices phase 0
+    return 0;
+}
+
+void printf(const BD_ADDR* addr) {
+    const u8* a = addr->addr;
+    printf("%02X:%02X:%02X:%02X:%02X:%02X",a[5],a[4],a[3],a[2],a[1],a[0]);
+}
+
+//  We have connected to a device
+void BTApp::ConnectionComplete(connection_info* info) {
+    printf("ConnectionComplete ");
+    BD_ADDR* a = &info->bdaddr;
+    printf(a);
+    printf("\n");
+    RemoteNameRequest(a);
+    for (i++; i < count; i++) {//find the next ft device to open
+        //printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
+        if (devs[i]->_handle == 0 && memcmp(devs[i]->_info.dev_class, FtDevClass, 3)==0) {//or some other way to connect to RFCOMM devices
+            BD_ADDR* bd = &devs[i]->_info.bdaddr;
+            printf("Connecting to ");
+            printf(bd);
+            printf("\n");
+            pending++;
+            CreateConnection(bd); //some low level connect, just let it happen for now (sets pin, mtu etc.)
+            printf("connection cmd was sent\n");
+            return;
+        }
+    }
+}
+
+void BTApp::ConnectDevices() {
+    count = GetDevices(devs,8);//get pointers to all bluetooth devices
+    pending = 0;
+    for (i = 0; i < count; i++) {//find first ft device (when filter works, all devices are ft devices)
+        //printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
+        if (devs[i]->_handle == 0 && memcmp(devs[i]->_info.dev_class, FtDevClass, 3)==0) {//or some other way to connect to RFCOMM devices
+            BD_ADDR* bd = &devs[i]->_info.bdaddr;
+            printf("Connecting to ");
+            printf(bd);
+            printf("\n");
+            pending++;
+            CreateConnection(bd); //some low level connect, just let it happen for now (sets pin, mtu etc.)
+            printf("connection cmd was sent\n");
+            return;
+        }
+    }
+}
+
+void BTApp::Callback(HCI_CALLBACK_EVENT evt, const u8* data, int len) {//these events are forwarded (in)directly from HCIRecv
+    unsigned char pin[] = "1234";
+    u8 filter[] = {0x00, 0x1F, 0x82, 0xFF, 0xFF, 0xFF };
+    printf("\x1b[%dm", 33);
+    switch (evt) {
+        case CALLBACK_READY:
+            printf("CALLBACK_READY\n");
+            printf("my address = ");
+            printf((BD_ADDR*)data);
+            SetEventFilter(1, 1, filter);
+            Inquiry();//start the second phase of the discovery
+            break;
+
+        case CALLBACK_INQUIRY_RESULT: //optionally build the list of FT devices here
+            printf("CALLBACK_INQUIRY_RESULT ");
+            printf((BD_ADDR*)data);
+            printf("\n");//data points to inquiry_info struct
+            break;
+
+        case CALLBACK_INQUIRY_DONE:
+            printf("CALLBACK_INQUIRY_DONE\n");
+            ConnectDevices();
+            break;
+
+        case CALLBACK_REMOTE_NAME: {
+            BD_ADDR* addr = (BD_ADDR*)data;
+            const char* name = (const char*)(data + 6);
+            printf(addr);
+            printf(" = % s\n",name);
+            pending--;
+        }
+        break;
+
+        case CALLBACK_CONNECTION_COMPLETE: {
+            connection_info *ci = (connection_info*)data;
+            if (ci->status>0) {
+                printf("Connection failed, status=0x%02X\n", ci->status);
+                break;
+            }
+            ConnectionComplete(ci);
+            /*
+            printf("Going to open sdp socket\n");
+            L2CAPAddr addr;
+            memcpy(&addr.bdaddr, &ci->bdaddr, 6);
+            int s = SDP.Open(&addr.hdr);
+            */
+        }
+        break;
+        case CALLBACK_PIN_REQ:
+            printf("Enter PIN for ");
+            printf((BD_ADDR*)data);
+            printf(" :  submitting %s\n", pin);
+            PinCodeReply(data, pin);
+            break;
+        default:
+            printf("Unhandled HCI Callback %d\n", evt);
+    };
+    printf("\x1b[%dm", 0);
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ftlib/ftusb.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,37 @@
+#ifndef FTUSB_H
+#define FTUSB_H
+#include "USBHost.h"
+#include <vector>
+#include "hci.h"
+
+struct _ftdev {
+    int device;
+    int product;
+    int serial;
+    int rf;
+    _ftdev(int d, int p, int s, int r=-1): device(d), product(p), serial(s), rf(r) {}
+};
+
+extern vector<_ftdev> devs;
+/*
+unsigned InitFtUsbList (void);
+_ftdev& GetFtUsbDevice(int n);
+_ftdev* GetFtUsbDevicePtr(int n);
+int GetUsbDeviceSerialNr(unsigned s, unsigned t=0);
+unsigned int GetNthFtDeviceFromRF(int Num, int iRf);
+*/
+void OnLoadFtDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc);
+int OnBluetoothInsert(int device);
+
+
+class BTApp : public HCI {
+    BTDevice* devs[8];
+    int count, i, pending;
+public:
+    void ConnectionComplete(connection_info* info) ;
+    void ConnectDevices();
+    virtual void Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
+};
+
+extern BTApp Bluetooth;
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,190 @@
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "mbed.h"
+#include "USBHost.h"
+#include "Utils.h"
+#include "ftlibclass.h"
+#include "ftlibclassusb.h"
+#include "ftlibclasstxc.h"
+#include "ftlibclasstxcbt.h"
+
+Serial pc(USBTX, USBRX);
+
+FT_TRANSFER_AREA *ta = 0;
+TA *tax = 0;
+NOTIFICATION_EVENTS ne;
+
+int main() {
+    pc.baud(460800);
+    printf("USBShell\nNow get a bunch of usb things and plug them in\n");
+    USBInit();
+    int state = 0;
+    Timer time;
+    time.start();
+    int n, r0, r1, r2, r3=0;
+//    ftusbdev* h = 0;
+    ftusbdevtxbt* h = 0;
+    printf("Start enumeration\n");
+    for (;;) {
+        switch (state) {
+            case 0: //enumeration, allow 3 seconds
+                if (time.read() >= 20) {
+                    state = 1;
+                    printf("Start initialisation\n");
+                }
+                break;
+            case 1: //init program
+                r0 = ftlib::InitFtLib();
+                printf("InitFtLib() returns %d\n", r0);
+                r1 = ftusbdevtxbt::InitFtUsbDeviceList();
+                printf("InitFtUsbDeviceList() returns %d\n", r1);
+                n = ftusbdev::GetNumFtUsbDevice();
+                printf("GetNumFtUsbDevice() returns %d\n", n);
+                for (int i = 0; i < n; i++) {
+                    ftdev* h = ftusbdev::GetFtUsbDeviceHandle(i);
+                    printf("handle = %p\n", h);
+                    unsigned sn = h->GetFtSerialNr();
+                    printf("S/N=%d\n", sn);
+                    char *name = h->GetFtLongNameStrg();
+                    printf("%d: %s SN=%08d\n", i, name, sn);
+                    delete[] name;
+                    //USBLoop();
+                }
+                h = dynamic_cast<ftusbdevtxbt*>(ftusbdev::GetFtUsbDeviceHandle(0));
+                if (h==0) {
+                    printf("Cast failed\n");
+                    state = 4;
+                    break;
+                }
+                r2 = h->OpenFtUsbDevice();
+                printf("OpenFtUsbDevice() returns %08x\n", r2);
+//                ta = h->GetFtTransferAreaAddress();
+                tax = h->GetFtTransferAreaAddress(0);
+                r3 = h->StartFtTransferArea(&ne);
+                if (r3) {
+                    printf("Could not start thread %08X\n", r3);
+                    state = 3;
+                    break;
+                }
+                state = 2;
+                printf("Start main loop\n");
+                break;
+            case 2: //main loop
+                ftlib::poll();
+                /*                if (ta->ChangeEg) {
+                                    printf("%02X %d %d %d\n", ta->E_Main, ta->AX, ta->A1, ta->AV);
+                                    ta->ChangeEg = 0;
+                                }*/
+                //printf("%02X %d %d %d\r", tax->input.uni[0],tax->input.uni[1],tax->input.uni[2],tax->input.uni[3]);
+                if (time.read() >= 30) {
+                    state = 3;
+                    printf("\nEnd of main loop\n");
+                }
+                break;
+            case 3: //finalizing
+                h->StopFtTransferArea();
+                h->CloseFtDevice();
+                ftlib::CloseFtLib();
+                state = 4;
+                break;
+            case 4:
+                break;
+            default:
+                return 0;
+        }
+        USBLoop();
+    }
+}
+
+int OnDiskInsert(int device) {
+    return 0;
+}
+
+
+#if 0
+#include "FATFileSystem.h"
+
+int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize);
+int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize);
+int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize);
+
+class USBFileSystem : public FATFileSystem {
+    int _device;
+    u32 _blockSize;
+    u32 _blockCount;
+
+public:
+    USBFileSystem() : FATFileSystem("usb"),_device(0),_blockSize(0),_blockCount(0) {
+    }
+
+    void SetDevice(int device) {
+        _device = device;
+    }
+
+    virtual int disk_initialize() {
+        return MassStorage_ReadCapacity(_device,&_blockCount,&_blockSize);
+    }
+
+    virtual int disk_write(const char *buffer, int block_number) {
+        return MassStorage_Write(_device,block_number,1,(u8*)buffer,_blockSize);
+    }
+
+    virtual int disk_read(char *buffer, int block_number) {
+        return MassStorage_Read(_device,block_number,1,(u8*)buffer,_blockSize);
+    }
+
+    virtual int disk_sectors() {
+        return _blockCount;
+    }
+};
+
+
+void DumpFS(int depth, int count) {
+    DIR *d = opendir("/usb");
+    if (!d) {
+        printf("USB file system borked\n");
+        return;
+    }
+
+    printf("\nDumping root dir\n");
+    struct dirent *p;
+    while ((p = readdir(d))) {
+        int len = sizeof( dirent);
+        printf("%s %d\n", p->d_name, len);
+    }
+    closedir(d);
+}
+
+int OnDiskInsert(int device) {
+    USBFileSystem fs;
+    fs.SetDevice(device);
+    DumpFS(0,0);
+    return 0;
+}
+
+/*
+    Simple test shell to exercise mouse,keyboard,mass storage and hubs.
+    Add 2 15k pulldown resistors between D+/D- and ground, attach a usb socket and have at it.
+*/
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.lib	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/projects/libraries/svn/mbed/trunk@28
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/message.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,61 @@
+#ifndef MESSAGE_H
+#define MESSAGE_H
+
+template <class T, int N> class msgbuffer {
+    T buffer[N];
+    int in, out, n;
+public:
+    int push(T msg, int mode = 0);
+    int nrOfMessages() {
+        return n;
+    }
+    T pop();
+    msgbuffer() {
+        in = 0;
+        out = 0;
+        n = 0;
+    }
+    void clear() {
+        in = 0;
+        out = 0;
+        n = 0;
+    }
+};
+
+template <class T> bool operator==(T a, T b) {
+    return memcmp(&a, &b, sizeof(T))==0;
+}
+
+template <class T, int N> int msgbuffer<T, N> ::push(T msg, int mode) {
+    if (n>=N) return -1; //buffer full
+    switch (mode) {
+        case 2:
+            for (int i = 0, j = out; i < n; i++, j++) {
+                if (j >= N) j = 0;
+                if (buffer[j] == msg)
+                    return 0;
+            }
+            goto insert;
+        case 1:
+            if (buffer[in] == msg)
+                return 0;
+            goto insert;
+        case 0:
+insert:
+            in++;
+            if (in >= N) in = 0;
+            buffer[in] = msg;
+            n++;
+            return 0;
+    }
+    return -2; //illegal option
+}
+
+template <class T, int N> T msgbuffer<T, N> ::pop() {
+    T tmp = buffer[out++];
+    if (out >= N)
+        out = 0;
+    return tmp;
+}
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/HCITransportUSB.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,67 @@
+#ifndef HCITRANSPORTUSB_H
+#define HCITRANSPORTUSB_H
+#define MAX_HCL_SIZE 260
+#define MAX_ACL_SIZE 400
+#include "USBHost.h"
+#include "hci.h"
+#include "Utils.h"
+
+//extern int bulk;
+
+class HCITransportUSB : public HCITransport {
+    int _device;
+    u8* _hciBuffer;
+    u8* _aclBuffer;
+
+public:
+    void Open(int device, u8* hciBuffer, u8* aclBuffer) {
+        _device = device;
+        _hciBuffer = hciBuffer;
+        _aclBuffer = aclBuffer;
+        USBInterruptTransfer(_device,0x81,_hciBuffer,MAX_HCL_SIZE,HciCallback,this);
+        USBBulkTransfer(_device,0x82,_aclBuffer,MAX_ACL_SIZE,AclCallback,this);
+    }
+
+    static void HciCallback(int device, int endpoint, int status, u8* data, int len, void* userData) {
+        HCI* t = ((HCITransportUSB*)userData)->_target; //printf("HCI: %d bytes avail\n", len);
+        if (t){
+        //printfBytes("HCICallback:", data, min(len,16));
+            t->HCIRecv(data,len);
+            }
+        USBInterruptTransfer(device,0x81,data,MAX_HCL_SIZE,HciCallback,userData);
+    }
+
+    static void AclCallback(int device, int endpoint, int status, u8* data, int len, void* userData) {
+        HCI* t = ((HCITransportUSB*)userData)->_target; //printf("ACL: %d bytes avail\n", len);
+        if (t){
+        //printfBytes("ACLCallback:", data, min(len,16));
+            t->ACLRecv(data,len);
+            }
+            //printf("ACL Read pending..\n");
+        USBBulkTransfer(device,0x82,data,MAX_ACL_SIZE,AclCallback,userData);
+    }
+
+    virtual void HCISend(const u8* data, int len) {
+        //printfBytes("HCISend:", data, min(len,16));
+        USBControlTransfer(_device,REQUEST_TYPE_CLASS, 0, 0, 0,(u8*)data,len);
+    }
+
+    virtual int ACLSend(const u8* data, int len) { //printf("send %d bytes to usb\n", len);
+        if (len > _acl_mtu) {
+            printf("Max outgoing packet(%d) size exceeded, segmenting necessary, pktlen = %d\n", _acl_mtu, len);
+            return 0;
+        }
+#ifdef HOST_CONTR_FLOW
+/*        if (data_credits == 0)
+          printf("Waiting for ACL buffers...\n");*/
+        while (data_credits < 1) {
+            USBLoop();
+        }
+        data_credits--;
+#endif
+        //printfBytes("ACLSend:", data, min(len,16));
+        return USBBulkTransfer(_device,0x02,(u8*)data,len);
+    }
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/L2CAP.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,585 @@
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Utils.h"
+#include "hci.h"
+#include "HCITransportUSB.h"
+#include "sdp.h"
+#include "RFCOMM.h"
+
+#define L2CAP_COMMAND_REJ       0x01
+#define L2CAP_CONN_REQ          0x02
+#define L2CAP_CONN_RSP          0x03
+#define L2CAP_CONF_REQ          0x04
+#define L2CAP_CONF_RSP          0x05
+#define L2CAP_DISCONN_REQ       0x06
+#define L2CAP_DISCONN_RSP       0x07
+#define L2CAP_ECHO_REQ          0x08
+#define L2CAP_ECHO_RSP          0x09
+#define L2CAP_INFO_REQ          0x0a
+#define L2CAP_INFO_RSP          0x0b
+
+#define TXID    (++_txid?_txid:1)
+//template <class T> T min(T a, T b) { return a<b ? a : b;}
+
+/* L2CAP command codes */
+const char* L2CAP_ComandCodeStr(int c) {
+    switch (c) {
+        case L2CAP_COMMAND_REJ:
+            return "L2CAP_COMMAND_REJ";
+        case L2CAP_CONN_REQ:
+            return "L2CAP_CONN_REQ";
+        case L2CAP_CONN_RSP:
+            return "L2CAP_CONN_RSP";
+        case L2CAP_CONF_REQ:
+            return "L2CAP_CONF_REQ";
+        case L2CAP_CONF_RSP:
+            return "L2CAP_CONF_RSP";
+        case L2CAP_DISCONN_REQ:
+            return "L2CAP_DISCONN_REQ";
+        case L2CAP_DISCONN_RSP:
+            return "L2CAP_DISCONN_RSP";
+        case L2CAP_ECHO_REQ:
+            return "L2CAP_ECHO_REQ";
+        case L2CAP_ECHO_RSP:
+            return "L2CAP_ECHO_RSP";
+        case L2CAP_INFO_REQ:
+            return "L2CAP_INFO_REQ";
+        case L2CAP_INFO_RSP:
+            return "L2CAP_INFO_RSP";
+    }
+    return "unknown";
+}
+
+#define OFFSET  8 //means the buffer also has space for the l2cap/hci headers and need not be allocated and copied
+//#define OFFSET  0 //means the buffer only has space for the payload which need to be copied
+#if OFFSET == 0
+#define L2CAPBUFSIZE    128
+#else
+#define L2CAPBUFSIZE    0
+#endif
+
+typedef struct {
+    u16    handle;
+    u16    length;            // total
+    u16    l2capLength;    // length -4
+    u16    cid;            // Signaling packet CID = 1
+    u8  data[L2CAPBUFSIZE];       // Largest thing to send!!! todo
+} L2CAPData;
+
+//
+void BTDevice::Init() {
+    memset(&_info,0,sizeof(inquiry_info));
+    _handle = 0;
+    _name[0] = 0;
+    _state = 0;
+    _txid = 1;
+    //cntr_cred = 1;
+}
+
+// virtual SocketHandler
+int BTDevice::Open(SocketInternal* sock, SocketAddrHdr* addr) {
+    L2CAPSocket* s = (L2CAPSocket*)sock;
+    L2CAPAddr* a = (L2CAPAddr*)addr;
+    s->scid = 0x40 + sock->ID-1;   // are these reserved?
+    s->dcid = 0;
+    Connect(s->scid,a->psm);
+    sock->State = SocketState_L2CAP_WaitConnectRsp;
+    contState = 0;
+    return sock->ID;
+}
+
+// virtual SocketHandler
+int BTDevice::Accept(SocketInternal* sock, int scid, int rxid) {
+    L2CAPSocket* s = (L2CAPSocket*)sock;
+    s->scid = 0x40 + sock->ID-1;   // are these reserved?
+    s->dcid = scid;
+    u16 p[4];
+    p[0] = s->scid;
+    p[1] = scid;
+    p[2] = 0; //success
+    p[3] = 0; //no further information
+    Send(L2CAP_CONN_RSP,rxid,p,4);
+    printf("send conn_rsp with dcid=%#x and scid=%#x\n", p[0],p[1]);
+    sock->State = SocketState_L2CAP_Config_wait;
+    contState = 0;
+    return sock->ID;
+}
+
+// virtual SocketHandler, called from HCI which is ABOVE L2CAP
+int BTDevice::Send(SocketInternal* sock, const u8* data, int len) {
+    L2CAPSocket* s = (L2CAPSocket*)sock;
+#if OFFSET == 8  //sizeof L2CAPData header
+    L2CAPData &d = *const_cast<L2CAPData*>((L2CAPData*)data);
+#else
+    L2CAPData d;
+#endif
+    if (len > peer_mtu) {//mtu concerns the l2cap mtu, because we use basic mode we cannot segment
+        printf("MTU (%d) for outgoing packet (%d) exceeded\n", peer_mtu, len);
+        return 0;
+    }
+    d.handle = _handle | 0x2000;
+    d.length = 4 + len - OFFSET;
+    d.l2capLength = len - OFFSET;
+    d.cid = s->dcid;
+    //printf("cid=%d: ", d.cid);
+    //printfBytes("sending: ", data, len);
+#if OFFSET == 0
+    if (len > L2CAPBUFSIZE)
+        return -1;
+    memcpy(d.data,data,len);
+    return Send((u8*)&d,len+8);
+#else
+    return Send(data, len);
+#endif
+}
+
+// virtual SocketHandler
+int BTDevice::Close(SocketInternal* sock) {
+    printf("L2CAP close %d\n",sock->ID);
+    sock->State = SocketState_L2CAP_WaitDisconnect;
+    L2CAPSocket* s = (L2CAPSocket*)sock;
+    return Disconnect(s->scid,s->dcid);
+}
+
+L2CAPSocket* BTDevice::SCIDToSocket(int scid) {
+    return (L2CAPSocket*)GetSocketInternal(scid-0x40+1);
+}
+
+int BTDevice::Send(const u8* data, int len) {//printfBytes("Transport : ", data, len);
+#ifdef HOST_CONTR_FLOW
+    pkts_sent++;
+#endif
+    _transport->ACLSend(data,len);
+    return 0;
+}
+
+void BTDevice::repeat_cmd() {
+    printf("Cmd on handle %#x timed out, resending txid=%d\n", _handle, last_req.id);
+//  Send ((u8*)&last_req, last_req.length+4);//danger! interrupt context, Send is not reentrant
+    //optionally set new larger timeout
+}
+
+int BTDevice::Send(u8 c, u8 id, u16* params, int count) {
+    L2CAPCmd cmd;
+    cmd.handle = _handle | 0x2000;
+    cmd.length = 8 + count*2;
+
+    cmd.l2capLength = cmd.length-4;
+    cmd.cid = 1;    // Signaling packet
+
+    cmd.cmd = c;
+    cmd.id = id;
+    cmd.cmdLength = count*2;
+    for (int i = 0; i < count; i++)
+        cmd.params[i] = params[i];
+    if ((c & 1) == 0) { //this is a request
+        last_req = cmd;
+        rtx.attach(this, &BTDevice::repeat_cmd, 30.0);
+        //printf("Starting timeout for %#x, txid=%d\n", _handle, id);
+    }
+    return Send((u8*)&cmd,cmd.length+4);
+}
+
+int BTDevice::Connect(int scid, int psm) {
+    u16 p[2];
+    p[0] = psm;
+    p[1] = scid;
+    return Send(L2CAP_CONN_REQ,TXID,p,2);
+}
+
+int BTDevice::Disconnect(int scid, int dcid) {
+    u16 p[2];
+    p[0] = dcid;
+    p[1] = scid;
+    return Send(L2CAP_DISCONN_REQ,TXID,p,2);
+}
+
+int BTDevice::ConfigureRequest(int dcid) {
+    u16 p[4];
+    p[0] = dcid;
+    p[1] = 0;
+    p[2] = 0x0201;  // Options
+    p[3] = min(0x02A0, MAX_ACL_SIZE);  // my receiving MTU 672
+    return Send(L2CAP_CONF_REQ,TXID,p,4);
+}
+
+int BTDevice::CommandReject(u16 reason, u16 data0, u16 data1) {
+    u16 p[3];
+    p[0] = reason;
+    p[1] = data0;
+    p[2] = data1;
+    int parlen = 2;
+    switch(reason){
+      case 0: //command not understood
+         break;
+      case 1: //MTU exceeded
+         parlen = 4; //return actual mtu in data
+         break;
+      case 2: //invalid CID
+         parlen = 6; //return local, remote cid
+         break;
+    }
+    return Send(L2CAP_COMMAND_REJ,TXID,p,parlen);
+}
+
+int BTDevice::ConfigureResponse(u8 rxid, int dcid) {
+    u16 p[3];
+    p[0] = dcid; //source cid
+    p[1] = 0;    //flags  (no continuation)
+    p[2] = 0;    //result (success)
+    return Send(L2CAP_CONF_RSP,rxid,p,3);
+}
+
+int BTDevice::DisconnectResponse(u8 rxid, int scid, int dcid) {
+    u16 p[2];
+    p[0] = dcid;
+    p[1] = scid;
+    return Send(L2CAP_DISCONN_RSP,rxid,p,2);
+}
+
+void server(int socket, SocketState state, const u8* data, int len, void* userData) {
+    // printfBytes("Server: ", data, len);
+    if (state==SocketState_Open && len>0)
+        SDP.SDPServer(socket, state, data, len, userData);
+}
+
+void serserver(int socket, SocketState state, const u8* data, int len, void* userData) {
+    printfBytes("serserver: ", data, len);
+    SocketHandler *h = (SocketHandler*)userData;
+    printf("userData refers to %s, state = %d\n", h->Name(), state);
+    if (state==SocketState_Open) {
+        if (len == 0) { //assume that the socket has just been opened and bind it to a new rfcomm server entity
+            printf("Calling RFCOMMManager::BindSocket\n");
+            rfcomm_manager.BindSocket(socket);
+        } else {
+            printf("Calling RFCOMMManager::SerServer\n");
+            rfcomm_manager.SerServer(socket, state, data, len, userData);
+        }
+    } else if (state==SocketState_L2CAP_WaitDisconnect) {
+            printf("Calling RFCOMMManager::SerServer\n");
+            rfcomm_manager.SerServer(socket, state, data, len, userData);
+        }
+}
+
+//code8, tid8, lengthData16
+//   0,    1,     2, 3
+void BTDevice::Control(const u8* data, int len) { //control channel receive
+    printf("\x1B[%dm", 31);
+    int cc = data[0];//command code
+    if (cc & 1) { //it is a response or a reject
+        rtx.detach(); //kill the timeout
+        //printf("timeout cancelled for handle %#x, txid=%d\n", _handle, data[1]);
+    }
+    printf(L2CAP_ComandCodeStr(cc));
+    switch (cc) {
+        case L2CAP_COMMAND_REJ://bad command, eg. MTU, check (reason)
+            printf(" rejection reason=%d\n", LE16(data+4));
+            break;
+        case L2CAP_CONN_REQ://incoming connection request, not expected but should reply with proper rejection (or accept)
+            //when a connection is accepted a new socket must be opened
+            printf(" Remote side requested a connection\n");
+            {
+                int scid = LE16(data+6);
+                int psm = LE16(data+4);
+                int rxid = data[1];
+                u16 p[4];
+                p[0] = 0; //no dcid
+                p[1] = scid;
+                p[3] = 0; //no further information
+                printf(" scid=%d, psm=%d\n", scid, psm);
+                int s = 0;
+                switch (psm) {
+                    case L2CAP_PSM_SDP:
+                        s = Socket_Accept(SOCKET_SDP, scid, rxid, server, this);//allocate an sdp socket but use it as L2CAP
+                        break;
+                    case L2CAP_PSM_RFCOMM: //SOCKET_RFCOM;
+#if 0
+                        s = Socket_Accept(SOCKET_RFCOM, scid, rxid, serserver, this);//allocate an rfcomm socket
+                        //using L2CAP i.o. RFCOM makes little difference in processing but it also changes the handler to HCI i.o. RFCOMMManager
+#else
+//an RFCOMM requests comes in from a known (this) device
+//the channel is not yet known
+                        s = rfcomm_manager.FindSocket(this);//this should return 0 otherwise the remote device was asking a second rfcomm on the same device
+                        if (s==0) {
+                            printf("No connection to this device yet, allocate L2CAP Socket and accept\n");
+                            //accept the connection, even though there may be no listener???
+                            //have no choice because w/o acceptance no rfcomm req.
+                            s = Socket_Accept(SOCKET_L2CAP, scid, rxid, serserver, this);//allocate an l2cap socket
+                            //get a new l2cap socket, call HCI::Accept (fill in btdevice internals), then call BTDevice::Accept (send accept message)
+                            //serserver is called on state changes (SocketInternal::SetState) and on received packets from the peer device to the new l2cap handle
+                            //after sending the accept message, the devices will execute the normal l2cap connection state-machine
+                            //ending in a call to SetState(Open) which will invoke 'serserver' for the first time
+//or something like:
+//                            s = Socket_Create(SOCKET_L2CAP, serserver, this);//allocate an l2cap socket
+//                            Accept(GetSocketInternal(s), scid, rxid);//send accept response, this would bypass HCI::Accept()
+                        } else {
+                            printf("Already had an L2CAP connection on socket %d\n", s);
+                        }
+#endif
+                        break;
+                    default:
+                        printf("PSM %d not supported\n", psm);
+                }
+                switch (s) {
+                    case 0:
+                        printf("Not a valid socket\n");
+                        break;
+                    case ERR_SOCKET_TYPE_NOT_FOUND:
+                        p[2] = 2; //psm not supported
+                        Send(L2CAP_CONN_RSP,rxid,p,4);
+                        break;
+                    case ERR_SOCKET_NONE_LEFT:
+                        p[2] = 4; //no resources available
+                        Send(L2CAP_CONN_RSP,rxid,p,4);
+                        break;
+                }
+            }
+            break;
+            // Response to our initial connect from Remote
+        case L2CAP_CONN_RSP: {
+            int dcid = LE16(data+4);
+            int scid = LE16(data+6);
+            L2CAPSocket* s = SCIDToSocket(scid);
+            int result = LE16(data+8);
+            printf(" Result=%d, Status = %d\n", result, LE16(data+10));
+            if (s->si.State != SocketState_L2CAP_WaitConnectRsp) {
+                printf("Unexpected event ignored\n");
+                break;
+            }
+            if (result == 0) {
+                if (s) {
+                    s->si.State = SocketState_L2CAP_Config_wait;
+                    s->dcid = dcid;
+                    ConfigureRequest(dcid);
+                    s->si.State = SocketState_L2CAP_Config_wait_reqrsp;
+                    printf("Sent ConfigureRequest, state=WAIT_CONFIG_REQ_RSP\n");
+                }
+            } else if (result == 1) {//pending, stay in the present state
+            } else {
+                s->si.SetState(SocketState_Closed);
+                printf("Connect failed\n");
+            }
+        }
+        break;
+
+        case L2CAP_CONF_RSP: {
+            int result = LE16(data+8);
+            printf("Result=%d, datalen=%d, %smore conf to follow\n", result, LE16(data+2), LE16(data+6)?"":"No ");
+            //should parse the config
+            printfBytes("CONF RSP:", data, LE16(data+2)+4);
+            int scid = LE16(data+4);
+            SocketInternal* s = (SocketInternal*)SCIDToSocket(scid);
+            if (s == 0) break;
+            if (s->State != SocketState_L2CAP_Config_wait_reqrsp && s->State != SocketState_L2CAP_Config_wait_rsp) {
+                printf("Unexpected event ignored\n");
+                break;
+            }
+            if (result == 0) { //configuration acceptable
+                if (s->State == SocketState_L2CAP_Config_wait_reqrsp) {
+                    s->State = SocketState_L2CAP_Config_wait_req;
+                    printf("State=WAIT_CONFIG_REQ\n");
+                } else {
+                    ConfigureResponse(data[1],((L2CAPSocket*)s)->dcid);//data[1]==txid
+                    printf("Sent ConfigureResponse, state=Open\n");
+                    s->SetState(SocketState_Open);
+                }
+            } else {
+                printf("Renegotiate configuration\n");
+            }
+        }
+        break;
+
+        case L2CAP_CONF_REQ: {
+            int len = LE16(data+2);
+            int scid = LE16(data+4);//flags (data[6] LSB is continuation flag, data[10],[11] are the MTU
+            int flags = LE16(data+6);
+            if (flags)
+                printf("Warning! Continuation flag in L2CAP configuration not supported\n");
+            L2CAPSocket* s = SCIDToSocket(scid);
+            printfBytes("CONF REQ: ", data, LE16(data+2)+4);//data+8 contains option type 1-4 1=MTU, 2=flush timeout, 3=QoS, 4=FCM
+            if (s == 0) break;
+            if (s->si.State == SocketState_Closed ||
+                    s->si.State == SocketState_L2CAP_WaitConnectRsp ||
+                    s->si.State == SocketState_L2CAP_WaitDisconnect) {
+                //Send Reject command
+                printf("Connection should be rejected\n");
+                break;
+            }
+            if (len > 4)
+                switch (data[8]) {
+                    case 1:
+                        peer_mtu = LE16(data+10);
+                        printf("Peer L2CAP MTU = %d bytes\n", peer_mtu);
+                        break;
+                    default:
+                        printf("Unsupported configuration option %d, value = %#X\n", data[8], LE16(data+10));
+                        break;
+                }
+            if (1 /* options acceptable */) {
+                printf("Sending ConfigureResponse, old state=%d ", s->si.State);
+                ConfigureResponse(data[1],s->dcid);//data[1]==txid, success
+                switch (s->si.State) {
+                    case SocketState_L2CAP_Config_wait:
+                        s->si.State = SocketState_L2CAP_Config_wait_send;
+                        ConfigureRequest(s->dcid);
+                        s->si.State = SocketState_L2CAP_Config_wait_rsp;
+                        break;
+                    case SocketState_L2CAP_Config_wait_req:
+                        ((SocketInternal*)s)->SetState(SocketState_Open);
+                        break;
+                    case SocketState_L2CAP_Config_wait_rsp:
+                        break;
+                    case SocketState_L2CAP_Config_wait_reqrsp:
+                        s->si.State = SocketState_L2CAP_Config_wait_rsp;
+                        break;
+                }
+                printf("new state=%d\n", s->si.State);
+            } else { //options not acceptable
+                printf("Configure failure should be indicated\n");
+                ConfigureResponse(data[1],s->dcid);//indicates success but should indicate fail
+            }
+        }
+        break;
+        case L2CAP_DISCONN_REQ:  {
+            int dcid = LE16(data+4);
+            int scid = LE16(data+6);
+            L2CAPSocket* s = SCIDToSocket(dcid);
+            if (s){
+                s->si.SetState(SocketState_Closed);
+                DisconnectResponse(data[1], scid, dcid);
+            } else {
+                printf("request to disconnect cid %d fails, no such cid\n", dcid);
+                CommandReject(0, dcid, scid);
+            }
+        }
+        break;
+        case L2CAP_DISCONN_RSP: {
+            int scid = LE16(data+6);
+            L2CAPSocket* s = SCIDToSocket(scid);
+            if (s->si.State == SocketState_L2CAP_WaitDisconnect)
+                s->si.SetState(SocketState_Closed);
+        }
+        break;
+        default:
+            printf("Unsupported L2CAP message %d\n", cc);
+    }
+    printf("\x1b[0m");
+}
+
+void BTDevice::ACLFwd(const u8* data, int len) {
+    if (l2cap_sock == 1)
+        Control(data, len);
+    else {
+        SocketInternal* s = (SocketInternal*)SCIDToSocket(l2cap_sock);//in fact cid in the l2cap header
+        if (s)
+            s->Recv(data,len);//forward to the sockethandler for the type
+        else
+            printf("Bad event cid %d\n",l2cap_sock);
+    }
+}
+//sometimes acl packets are segmented, in that case the l2cap payload length does not correspond to the acl pkt length
+//and the l2cap packet length. L2CAP works in basic mode and cannot be segmented hence the l2cap pkt size corresponds to
+//the acl pkt size
+int BTDevice::ACLRecv(const u8* data, int acllen) {
+    //printfBytes("L2CP",data,acllen);
+    //cntr_cred--;
+    u16 handle = LE16(data);
+    if ((handle&0x0fff) !=  _handle) {
+        printf("unexpected handle %#x, this _handle=%#x\n", handle, _handle);
+        return 1;
+    }
+    //below is the ACL packet recombination engine
+    char pb = (handle>>12) & 3;
+    if (pb == 2)
+        segments = 1;
+    else
+        segments++;
+    int p = 4; //start of l2cap packet
+    int len = LE16(data+2); //length of l2cap pkt
+    while (p < acllen)
+        switch (contState) {
+            case 0://allow even for fragmented length field
+                plen = data[p++];//payload length lsb
+                contState = 1;
+                break;
+            case 1:
+                plen += data[p++]<<8; //payload length msb
+                if (pb == 2 && plen == acllen-8) {//normal case, l2cap pkt is contained completely in this hci pkt
+                    l2cap_sock = data[p] + (data[p+1]<<8);
+                    contState = 0;
+                    ACLFwd(data+8, plen); //forward the packet in its original buffer
+                    return segments; //all data was dealt with
+                } else { //packet is segmented
+                    //printf("ACL packet is segmented\n");
+                    contState = 2;
+                    contBuf = new unsigned char[plen];//allocate recombination buffer
+                    contPos = 0;
+                }
+                break;
+            case 2:
+                l2cap_sock = data[p++];
+                contState = 3;
+                break;
+            case 3:
+                l2cap_sock += data[p++]<<8;
+                contState = 4;
+                break;
+            case 4: //data, recombine segmented ACL (not l2cap!) frames
+                if (contPos < plen) {//buffer not yet full
+                    int datalen = acllen - p; //data in this incoming pkt
+                    int remcap = plen - contPos; //remaining capacity in the recombination buffer
+                    if (datalen <= remcap) {
+                        memcpy(contBuf+contPos, data+p, datalen);
+                        contPos += datalen;
+                        p = acllen;//end of data, stop the while loop
+                        if (contPos == plen) {//buffer is full now
+                            //printfBytes("Recombined packet is:", contBuf, plen);
+                            ACLFwd(contBuf, plen); //forward the recombination buffer
+                            delete[] contBuf;//and free the buffer
+                            contState = 0;
+                            return segments;
+                        }//else stay in this state to wait for the rest
+                    } else {//data contains (part of) next packet, never seen this happen
+                        memcpy(contBuf+contPos, data+p, plen-contPos);//this packet is complete
+                        p += plen-contPos;
+                        printfBytes("Recombined packet is:", contBuf, plen);
+                        printfBytes("Next packet starts with:", data+p, acllen-p);
+                        ACLFwd(contBuf, plen); //forward the recombination buffer
+                        delete[] contBuf;//and free the buffer
+                        contState = 0; //continue with the next packet
+                    }
+                } else {
+                    printf("Cannot append to buffer (size=%d, pos=%d, datalen = %d)\n", plen, contPos, len-p);
+                    contState = 0;
+                    return segments;//flushed
+                }
+                break;
+        }//switch (and while)
+    return 0;//the buffers are not processed yet
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/Socket.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,227 @@
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Utils.h"
+#include "Socket.h"
+
+#define MAX_SOCKET_HANDLERS 4
+#define MAX_SOCKETS 16
+
+class SocketInternalPad
+{
+    public:
+    SocketInternal si;
+    u8  pad[8];
+};
+
+class SocketManager
+{
+    SocketHandler*  _handlers[MAX_SOCKET_HANDLERS];
+    SocketInternalPad  _sockets[MAX_SOCKETS];
+
+    public:
+    SocketManager()
+    {
+        memset(_handlers,0,sizeof(_handlers));
+        memset(_sockets,0,sizeof(_sockets));
+    }
+
+    SocketHandler* GetHandler(int type)
+    {
+        if (type < 1 || type > MAX_SOCKET_HANDLERS)
+            return 0;
+        return _handlers[type - 1];
+    }
+
+    SocketInternal* GetInternal(int s)
+    {
+        if (s < 1 || s > MAX_SOCKETS)
+            return 0;
+        return &_sockets[s - 1].si;
+    }
+
+    int RegisterSocketHandler(int type, SocketHandler* handler)
+    {
+       if (type < 1 || type > MAX_SOCKET_HANDLERS)
+            return ERR_SOCKET_TYPE_NOT_FOUND;
+        _handlers[type - 1] = handler;
+        return 0;
+    }
+
+    int Create(int type, SocketCallback callback, void* userData)
+    {
+        SocketHandler* h = GetHandler(type);
+        if (!h)
+            return ERR_SOCKET_TYPE_NOT_FOUND;
+        
+        for (int i = 0; i < MAX_SOCKETS; i++)
+        {
+            SocketInternal* si = (SocketInternal*)(_sockets+i);
+            if (si->ID == 0)
+            {
+                si->ID = i+1;
+                si->Type = type;
+                si->Callback = callback;
+                si->userData = userData;
+                printf("Creating socket %d for type %d, invoking 'Open' on %p (=%s)\n", si->ID, type, h, h->Name());
+                return h->Create(si);
+            }
+        }
+        return ERR_SOCKET_NONE_LEFT;
+    }
+
+    int Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData)
+    {
+        SocketHandler* h = GetHandler(type);
+        if (!h)
+            return ERR_SOCKET_TYPE_NOT_FOUND;
+        
+        for (int i = 0; i < MAX_SOCKETS; i++)
+        {
+            SocketInternal* si = (SocketInternal*)(_sockets+i);
+            if (si->ID == 0)
+            {
+                si->ID = i+1;
+                si->Type = type;
+                si->Callback = callback;
+                si->userData = userData;
+                printf("Opening socket %d for type %d, invoking 'Open' on %p (=%s)\n", si->ID, type, h, h->Name());
+                return h->Open(si,addr);
+            }
+        }
+        return ERR_SOCKET_NONE_LEFT;
+    }
+
+    int Listen(int type, int channel, SocketCallback callback, void* userData)
+    {
+        SocketHandler* h = GetHandler(type);
+        if (!h)
+            return ERR_SOCKET_TYPE_NOT_FOUND;
+        
+        for (int i = 0; i < MAX_SOCKETS; i++)
+        {
+            SocketInternal* si = (SocketInternal*)(_sockets+i);
+            if (si->ID == 0)
+            {
+                si->ID = i+1;
+                si->Type = type;
+                si->Callback = callback;
+                si->userData = userData;
+                printf("Passively opening socket %d for type %d, invoking 'Listen' on %p (=%s)\n", si->ID, type, h, h->Name());
+                int sn = h->Listen(si, channel);
+                if (sn < 0)
+                  si->ID = 0;//free the socket when error
+                return sn;
+            }
+        }
+        return ERR_SOCKET_NONE_LEFT;
+    }
+
+    int Accept(int type, int scid, int rxid, SocketCallback callback, void* userData)
+    {
+        SocketHandler* h = GetHandler(type);
+        if (!h)
+            return ERR_SOCKET_TYPE_NOT_FOUND;
+        
+        for (int i = 0; i < MAX_SOCKETS; i++)
+        {
+            SocketInternal* si = (SocketInternal*)(_sockets+i);
+            if (si->ID == 0)
+            {
+                si->ID = i+1;
+                si->Type = type;
+                si->Callback = callback;
+                si->userData = userData;
+                printf("Accepting socket %d for type %d, invoking 'Accept' on %p (=%s)\n", si->ID, type, h, h->Name());
+                return h->Accept(si, scid, rxid);
+            }
+        }
+        return ERR_SOCKET_NONE_LEFT;
+    }
+
+    int Send(int socket, const u8* data, int len)
+    {
+        SocketInternal* si = GetInternal(socket);
+        if (!si || si->ID != socket)
+            return ERR_SOCKET_NOT_FOUND;
+           // printf("sending %d bytes to socket %d (ID=%d)\n", len, socket, si->ID);
+        return GetHandler(si->Type)->Send(si,data,len);
+    }
+
+    int Close(int socket)
+    {
+        SocketInternal* si = GetInternal(socket);
+        if (!si || si->ID != socket){
+            printf("Close: socket %d not found\n", socket);
+            return ERR_SOCKET_NOT_FOUND;
+        }
+        printf("Close: socket %d (type=%d)\n", socket, si->Type);
+        si->SetState(SocketState_Closing);
+        int retval = GetHandler(si->Type)->Close(si);
+        //si->SetState(Socket_Closed);
+        //si->ID = 0;
+        return retval;
+    }
+};
+
+SocketManager gSocketManager;
+
+int Socket_Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData)
+{
+    return gSocketManager.Open(type,addr,callback,userData);
+}
+
+int Socket_Listen(int type, int channel, SocketCallback callback, void* userData)  // Open a socket for listening
+{
+    return gSocketManager.Listen(type,channel,callback,userData);
+}
+
+int Socket_Accept(int type, int scid, int rxid, SocketCallback callback, void* userData)  // Open a socket for an incoming connection
+{
+    return gSocketManager.Accept(type,scid,rxid,callback,userData);
+}
+
+int Socket_Send(int socket, const u8* data, int len)
+{
+    return gSocketManager.Send(socket,data,len);
+}
+
+int Socket_Close(int socket)
+{
+    return gSocketManager.Close(socket);
+}
+
+int RegisterSocketHandler(int type, SocketHandler* handler)
+{
+    return gSocketManager.RegisterSocketHandler(type,handler);
+}
+
+SocketInternal* GetSocketInternal(int socket)
+{
+    return gSocketManager.GetInternal(socket);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/Socket.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,119 @@
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef SOCKET_H_INCLUDED
+#define SOCKET_H_INCLUDED
+
+#define SOCKET_HCI      1
+#define SOCKET_L2CAP    2
+#define SOCKET_RFCOM    3
+#define SOCKET_SDP      4
+
+typedef struct
+{
+    u8  AddressSpecific[0]; // BDADDR,psm etc
+} SocketAddrHdr;
+
+enum SocketState
+{
+    SocketState_Unknown,
+    SocketState_Opening,
+    SocketState_Open,
+    SocketState_Closing,
+    SocketState_Closed,
+    SocketState_Listen,
+    SocketState_Accepting,
+    SocketState_L2CAP_WaitConnect = 8,
+    SocketState_L2CAP_WaitConnectRsp,
+    SocketState_L2CAP_WaitDisconnect,
+    SocketState_L2CAP_Config_wait = 16,
+    SocketState_L2CAP_Config_wait_send,
+    SocketState_L2CAP_Config_wait_req,
+    SocketState_L2CAP_Config_wait_rsp,
+    SocketState_L2CAP_Config_wait_reqrsp  
+};
+
+typedef void (*SocketCallback)(int socket, SocketState state, const u8* data, int len, void* userData);
+
+int Socket_Create(int type, SocketCallback callback, void* userData);   // Allocate a socket
+int Socket_Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData);   // Open a socket
+int Socket_Listen(int type, int channel, SocketCallback callback, void* userData);   // Open a socket passive
+int Socket_Accept(int type, int scid, int rxid, SocketCallback callback, void* userData);   // Open a socket for an incoming connection
+int Socket_Send(int socket, const u8* data, int len);
+int Socket_State(int socket);
+int Socket_Close(int socket);
+
+//===========================================================================
+//===========================================================================
+//  Don't need to look at or use anything below this line:
+//  Internal representation of socket
+
+class SocketHandler;
+class SocketInternal
+{
+    public:
+
+    u8 ID;
+    u8 State;
+    u8 Type;
+    u8 B0;
+    SocketCallback Callback;
+    void* userData;
+    u8  Data[0];    // Extra socket data starts here
+
+    void Recv(const u8* data, int len)
+    {
+        Callback(ID,(SocketState)State,data,len,userData);
+    }
+
+    void SetState(SocketState state)
+    {
+        State = state;
+        Callback(ID,(SocketState)State,0,0,userData);
+        if (state == SocketState_Closed) {
+          printf("Socket %d has been freed\n", ID);
+          ID = 0;
+        }
+    }
+};
+
+class SocketHandler
+{
+    public:
+    virtual int Create(SocketInternal* sock) { printf("SocketHandler::Create: not implemented for %s\n", Name()); return sock->ID;}
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) = 0;
+    virtual int Send(SocketInternal* sock, const u8* data, int len) = 0;
+    virtual int Close(SocketInternal* sock) = 0;
+    virtual int Listen(SocketInternal* sock, int channel) { printf("SocketHandler::Listen: not implemented for %s\n", Name());return 0;}    
+    virtual int Accept(SocketInternal* sock, int scid, int rxid) { printf("SocketHandler::Accept: not implemented for %s\n", Name());return 0;}
+    virtual char* Name() { return "Base_SocketHandler";}
+};
+
+int RegisterSocketHandler(int type, SocketHandler* handler);
+SocketInternal* GetSocketInternal(int socket);
+
+#define ERR_SOCKET_TYPE_NOT_FOUND -200
+#define ERR_SOCKET_NOT_FOUND -201
+#define ERR_SOCKET_NONE_LEFT -202
+#define ERR_SOCKET_CANT_LISTEN -203
+
+#endif // SOCKET_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/Utils.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,49 @@
+
+
+#include "mbed.h"
+#include "Utils.h"
+
+void printfBytes(const char* s, const u8* data, int len)
+{
+    printf("%s %d:",s,len);
+    if (len > 256)
+        len = 256;
+    while (len-- > 0)
+        printf(" %02X",*data++);
+    printf("\n");
+}
+
+void printHexLine(const u8* d, int addr, int len)
+{
+    printf("%04X ",addr);
+    int i;
+    for (i = 0; i < len; i++)
+        printf("%02X ",d[i]);
+    for (;i < 16; i++)
+        printf("   ");
+    char s[16+1];
+    memset(s,0,sizeof(s));
+    for (i = 0; i < len; i++)
+    {
+        int c = d[i];
+        if (c < 0x20 || c > 0x7E)
+            c = '.';
+        s[i] = c;
+    }
+    printf("%s\n",s);
+}
+
+void printHex(const u8* d, int len)
+{
+    int addr = 0;
+    while (len)
+    {
+        int count = len;
+        if (count > 16)
+            count = 16;
+        printHexLine(d+addr,addr,count);
+        addr += 16;
+        len -= count;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/Utils.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,42 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+
+void DelayMS(int ms);
+
+void printfBytes(const char* label,const u8* data, int len);
+void printHex(const u8* d, int len);
+//void printf(const BD_ADDR* addr);
+
+#ifndef min
+#define min(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+inline int LE16(const u8* d)
+{
+    return d[0] | (d[1] << 8);
+}
+
+inline u32 BE32(const u8* d)
+{
+    return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
+}
+
+inline void BE32(u32 n, u8* d)
+{
+    d[0] = (u8)(n >> 24);
+    d[1] = (u8)(n >> 16);
+    d[2] = (u8)(n >> 8);
+    d[3] = (u8)n;
+}
+
+inline void BE16(u32 n, u8* d)
+{
+    d[0] = (u8)(n >> 8);
+    d[1] = (u8)n;
+}
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/hci.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,572 @@
+
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "Utils.h"
+#include "hci.h"
+#include "hci_private.h"
+#include "USBHost.h" //for USBLoop
+#include "HCITransportUSB.h" //for ACL/HCL buffer size
+
+enum hci_callback_evt {
+    NONE,
+    CONNECT,
+    DISCONECT,
+    INQUIRYRESULT
+};
+
+#define MAX_BLUETOOTH_ADAPTERS 1
+
+static const u8 local_name[] = "MBED";
+
+
+int  HCI::Open(HCITransport* transport, HCICallback callback) {
+    _transport = transport;
+    _transport->Set(this);
+    _callback = callback;
+    _state = 0;
+    for (int i = 0; i < MAX_BTDEVICES; i++) {
+        _devices[i].Init();
+        _devices[i]._transport = transport;
+    }
+#ifdef COMMAND_FLOW
+    cmd_credits = 1;
+#endif
+    return SendCmd(HCI_OP_RESET);
+}
+
+void printf(const BD_ADDR* addr);
+
+BTDevice* HCI::Find(const BD_ADDR* addr) {
+    for (int i = 0; i < MAX_BTDEVICES; i++)
+        if (_devices[i]._state != 0 && memcmp(addr,&_devices[i]._info.bdaddr,6) == 0)
+            return &_devices[i];
+    return 0;
+}
+
+BTDevice* HCI::Find(int handle) {
+    for (int i = 0; i < MAX_BTDEVICES; i++)
+        if (_devices[i]._state != 0 && handle == _devices[i]._handle)
+            return &_devices[i];
+    return 0;
+}
+
+//reports that some commands are still in progress
+bool HCI::Busy() {
+    return (_state & (MASK_INQUIRY | MASK_REMOTE_NAME | MASK_CREATE_CONNECTION)) != 0;
+}
+
+int HCI::Inquiry(int duration) {
+    _state |= MASK_INQUIRY;
+    u8 buf[5];
+    buf[0] = 0x33;//LAP=0x9e8b33
+    buf[1] = 0x8B;
+    buf[2] = 0x9E;
+    buf[3] = duration;
+    buf[4] = 5;  // 5 results
+    SendCmd(HCI_OP_INQUIRY,buf,sizeof(buf));
+    return 0;
+}
+
+int HCI::SetEventFilter(u8 filterType, u8 filterConditionType, u8* condition) {
+    int len = 2;
+    u8 buf[8];
+    buf[0] = filterType;
+    buf[1] = filterConditionType;
+    switch (filterConditionType) {
+        case 0://all devices
+            if (filterType==2) { //connection setup
+                buf[2] = condition[0];
+                len++;
+            }
+            break;
+        case 1: //filter by class
+        case 2: //filter by BDADDR
+            memcpy(buf+2, condition, 6);
+            len += 6;
+            break;
+        default:
+            printf("Unknown filter condition type %d, filter type=%d\n", filterConditionType, filterType);
+    }
+    SendCmd(HCI_OP_SET_EVENT_FLT, buf, len);
+    return 0;
+}
+
+int HCI::SendCmd(int cmd, const u8* params, int len) {
+    u8 b[256];
+    b[0] = cmd;
+    b[1] = (cmd >> 8);
+    b[2] = len;
+    if (params)
+        memcpy(b+3,params,len);
+#ifdef COMMAND_FLOW
+    //printf("%d cmd_credits\n", cmd_credits);
+    while (cmd_credits == 0) {//blocks when command credits run out
+        USBLoop();
+        putc('_', stdout);
+    }
+#endif
+    _transport->HCISend(b,len+3);
+    return 0;
+}
+
+void HCI::OnCommandComplete(int cmd, const u8* data, int len) {//data is exclusive the status byte
+    //printf("%04X %s",cmd,CmdStr(cmd));
+    if (len < 0)
+        return;
+    //printfBytes(" complete",data,len/*min(16,len)*/);
+
+    switch (cmd) {
+        case 0: //NOP
+            printf("Received NOP command (for cmd_credits)\n");
+            break;
+            //  Init phase 0
+        case HCI_OP_RESET:  // Reset done, init chain to HCI_OP_READ_LOCAL_NAME
+            SendCmd(HCI_OP_READ_BUFFER_SIZE);
+            _state |= MASK_RESET;
+            break;
+
+            //  Init phase 1
+        case HCI_OP_READ_BUFFER_SIZE:
+            _acl_mtu = LE16(data);
+            _sco_mtu = data[2];
+            _acl_max_pkt = LE16(data+3);
+            _sco_max_pkt = LE16(data+5);
+            printf("acl_mtu=%d, acl_max_pkt=%d\n", _acl_mtu, _acl_max_pkt);
+#ifdef HOST_CONTR_FLOW
+            _transport->data_credits = _acl_max_pkt;
+            _transport->_acl_mtu = _acl_mtu;
+#endif
+            SendCmd(HCI_OP_READ_BD_ADDR);
+            _state |= MASK_READ_BUFFER_SIZE;
+            break;
+
+            //  Init phase 2
+        case HCI_OP_READ_BD_ADDR:
+            _localAddr = *((BD_ADDR*)data); // Local Address
+            _state |= MASK_READ_BD_ADDR;
+            _state |= MASK_INITED;
+            {
+#ifdef CONTR_HOST_FLOW
+                unsigned char param[7];
+                param[0] = (u8)(MAX_ACL_SIZE-8);
+                param[1] = (u8)((MAX_ACL_SIZE-8)>>8);
+                param[2] = 0;//MAX_HCL_SIZE-8;
+                param[3] = 10;
+                param[4] = 0; //1 ACL buffer
+                param[5] = 0;
+                param[6] = 0; //0 Synchronous buffers
+                SendCmd(HCI_OP_HOST_BUFFER_SIZE, param, 7);
+                const unsigned char flow = 1;//ACL on, Synchonous off
+                SendCmd(HCI_OP_CONTR_TO_HOST_FLOW, &flow, 1);
+#endif
+                const unsigned char scan_enable = 3;
+                SendCmd(HCI_OP_WRITE_SCAN_ENABLE, &scan_enable, 1);
+                SendCmd(HCI_OP_WRITE_LOCAL_NAME, local_name, 248);
+            }
+            Callback(CALLBACK_READY,data,6);
+            break;
+
+            // 0CXX
+        case HCI_OP_READ_LOCAL_NAME:
+        case HCI_OP_LINK_KEY_NEG_REPLY:
+        case HCI_OP_WRITE_SCAN_ENABLE:
+        case HCI_OP_WRITE_LOCAL_NAME:
+            break;
+#ifdef CONTR_HOST_FLOW
+        case HCI_OP_CONTR_TO_HOST_FLOW:
+        case HCI_OP_HOST_BUFFER_SIZE:
+            break;
+        case HCI_OP_NUM_COMP_PKTS:
+            printf("Host number of Completed Packets: Invalid HCI Command Parameter\n");
+            break;
+#endif
+        case HCI_OP_READ_LOCAL_VERSION:
+            // params
+            //SendCmd(HCI_OP_READ_LOCAL_NAME);
+            break;
+
+        case HCI_OP_READ_LOCAL_COMMANDS:
+            break;
+
+        case HCI_OP_READ_LOCAL_FEATURES:
+            //SendCmd(HCI_OP_READ_LOCAL_VERSION);
+            break;
+
+        case HCI_OP_READ_LOCAL_EXT_FEATURES:
+            break;
+
+        case HCI_OP_PIN_CODE_REPLY:
+            printf("Got pin reply\n");
+            break;
+
+        default:
+            printf("Unrecognized Command Completion %04X\n",cmd);
+            break;
+    }
+}
+
+void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len) {
+    if (_callback) _callback(this,c,data,len);
+//    (this->*_callback)(c, data, len);
+}
+
+int HCI::RemoteNameRequest(const BD_ADDR* addr) {
+    _state |= MASK_REMOTE_NAME;
+    u8 buf[6+4];
+    memset(buf,0,sizeof(buf));
+    memcpy(buf,addr,6);
+    //buf[7] = 1;
+    return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf));
+}
+
+int HCI::RemoteNameRequest(inquiry_info *ii) {
+    _state |= MASK_REMOTE_NAME;
+    u8 buf[6+4];
+    //memset(buf,0,sizeof(buf));
+    memcpy(buf,&ii->bdaddr,6);
+    buf[6] = ii->pscan_rep_mode;
+    buf[7] = 0;
+    *(unsigned short*)(buf+8) = 0;
+    return SendCmd(HCI_OP_REMOTE_NAME_REQ,buf,sizeof(buf));
+}
+
+int HCI::CreateConnection(const BD_ADDR* remoteAddr) {
+    _state |= MASK_CREATE_CONNECTION;
+    u8 buf[6+7];
+    memset(buf,0,sizeof(buf));
+    memcpy(buf,remoteAddr,6);
+    buf[6] = 0x18;  // DM1,DH1
+    buf[7] = 0xCC;  // DM3, DH3, DM5, DH5
+    buf[8] = 1;     // Page Repetition R1
+    return SendCmd(HCI_OP_CREATE_CONN,buf,sizeof(buf));
+}
+
+int HCI::Disconnect(const BD_ADDR* bdaddr) {
+    BTDevice* d = Find(bdaddr);
+    if (!d)
+        return ERR_HCI_DEVICE_NOT_FOUND;
+    int handle = d->_handle;
+    printf("Disconnect from %d\n",handle);
+    _state |= MASK_CREATE_CONNECTION;
+    u8 buf[3];
+    buf[0] = handle;
+    buf[1] = (handle >> 8);
+    buf[2] = 0x13;
+    return SendCmd(HCI_OP_DISCONNECT,buf,sizeof(buf));
+}
+
+void HCI::DisconnectComplete(int handle) {
+    BTDevice* d = Find(handle);
+    if (!d)
+        return;
+    d->_handle = 0;
+}
+
+int HCI::DisconnectAll() {
+    BTDevice* devs[8];
+    int count = GetDevices(devs,8);
+    for (int i = 0; i < count; i++)
+        Disconnect(&devs[i]->_info.bdaddr);
+    return 0;
+}
+
+int HCI::PinCodeReply(const u8* data, const u8* pin) {
+    u8 b[6+1+16];
+    memset(b,0,sizeof(b));
+    memcpy(b,data,6);
+    b[6] = 4;
+    memcpy(b+7, pin, 4);
+    return SendCmd(HCI_OP_PIN_CODE_REPLY,b,sizeof(b));
+}
+
+void HCI::InquiryResult(const inquiry_info* info) {
+    BTDevice* bt = Find(&info->bdaddr);
+    if (!bt) {  // new device
+        for (int i = 0; i < MAX_BTDEVICES; i++) {
+            if (_devices[i]._state == 0) {
+                bt = _devices + i;
+                bt->_state = 1;
+                break;
+            }
+        }
+        if (!bt) {
+            printf("HCI::InquiryResult too many devices\n");
+            return; // Too many devices!
+        }
+    }
+
+    bt->_info = *info;
+}
+
+int HCI::GetDevices(BTDevice** devices, int maxDevices) {
+    int j = 0;
+    for (int i = 0; i < MAX_BTDEVICES; i++) {
+        if (_devices[i]._state != 0) {
+            devices[j++] = _devices + i;
+            if (j == maxDevices)
+                break;
+        }
+    }
+    return j;
+}
+
+void HCI::RemoteName(const BD_ADDR* addr, const char* name) {
+    BTDevice* d = Find(addr);
+    if (d) {
+        strncpy(d->_name,name,sizeof(d->_name)-1);
+        d->_name[sizeof(d->_name)-1] = 0;
+    }
+}
+
+void HCI::ConnectComplete(const connection_info* info) {
+    BTDevice* d = Find(&info->bdaddr);
+    if (!d) {
+        printf("BT Device not known!?! ");
+        printf(&info->bdaddr);
+        printf("\n");
+        return;
+    }
+    if (info->status == 0) {
+        d->_handle = info->handle;
+#ifdef HOST_CONTR_FLOW
+        d->pkts_sent = 0;
+#endif
+        printf("Connected on %04X\n",info->handle);
+    } else
+        printf("Connection failed with %d\n",info->status);
+}
+
+void HCI::Accept_Connection(const BD_ADDR* addr, bool slave) {
+    unsigned char b[7];
+    memcpy(b, addr, 6);
+    b[6] = slave;
+    BTDevice* bt = Find(addr);
+    if (!bt) {
+        printf("Received connection request from undiscovered device\n");
+        for (int i = 0; i < MAX_BTDEVICES; i++) {
+            if (_devices[i]._state == 0) {
+                bt = _devices + i;
+                bt->_state = 1;
+                memcpy(&(bt->_info.bdaddr), addr, 6);//rest of inquiry info unknown!!!
+                break;
+            }
+        }
+        if (!bt) {
+            printf("HCI::InquiryResult too many devices\n");
+            return; // Too many devices!
+        }
+    }
+    SendCmd(HCI_OP_ACCEPT_CONN_REQ, b , 7);
+}
+
+void HCI::HCIRecv(const u8* data, int len) {//[0]=event, [1]=parlen, [2...]=pars
+    //printfBytes(EvtStr(data[0]),data,min(len,16));
+    switch (data[0]) {
+        case HCI_EV_INQUIRY_COMPLETE:
+            printfBytes("Inquiry Complete",data,data[1]);
+            _state &= ~MASK_INQUIRY;
+            Callback(CALLBACK_INQUIRY_DONE,0,0);
+            break;
+
+        case HCI_EV_INQUIRY_RESULT: {
+            const u8* end = data[1] + data + 2;
+            data += 3;
+            while (data < end) {
+                inquiry_info align;
+                memcpy(&align,data,sizeof(inquiry_info));
+                InquiryResult(&align);
+                Callback(CALLBACK_INQUIRY_RESULT,(u8*)&align,sizeof(inquiry_info));
+                data += 14;
+            }
+        }
+        break;
+
+        case HCI_EV_CONN_COMPLETE:
+            _state &= ~MASK_CREATE_CONNECTION;
+            {
+                connection_info align;
+                memcpy(&align,data+2,sizeof(connection_info));
+                ConnectComplete(&align);
+                Callback(CALLBACK_CONNECTION_COMPLETE,(u8*)&align,sizeof(connection_info));
+            }
+            break;
+
+        case HCI_EV_CONN_REQUEST:
+            printf("Got Connection request \n");
+            Callback(CALLBACK_CONNECTION_REQUEST, data+2, data[1]);
+            Accept_Connection((BD_ADDR*)(data+2));
+            break;
+
+        case HCI_EV_DISCONN_COMPLETE:
+            DisconnectComplete(LE16(data+3));
+            break;
+
+        case HCI_EV_REMOTE_NAME: {
+            BD_ADDR* addr = (BD_ADDR*)(data+3);
+            const char* name = (const char*)(data + 9);
+            RemoteName(addr,name);
+        }
+        Callback(CALLBACK_REMOTE_NAME,data+3,LE16(data+1));    // addr is in here too
+        _state &= ~MASK_REMOTE_NAME;
+        break;
+
+        case HCI_EV_CMD_STATUS: {
+            const char* errs = HCIErrStr(data[2]);
+            printf("Status %s %s %d cmd pkts\n",CmdStr(LE16(data+4)),errs, data[3]);
+#ifdef COMMAND_FLOW
+            cmd_credits = data[3];
+#endif
+        }
+        Callback(CALLBACK_CMD_STATUS, data+2, 4);
+        break;
+
+        case HCI_EV_CMD_COMPLETE://[2]=cmd-pkts, [3-4]=cmd, [5...]=pars
+            if (data[5]) { //[5]=usually status
+                printf("HCIRecv error status: %s\n", HCIErrStr(data[5]));
+            }
+            OnCommandComplete(data[3] | (data[4] << 8), data+6, data[1]-4);
+#ifdef COMMAND_FLOW
+            cmd_credits = data[2];
+#endif
+            break;
+
+        case HCI_EV_PIN_CODE_REQ:
+            Callback(CALLBACK_PIN_REQ, data+2, 6);
+            //PinCodeReply(data+2);
+            break;
+
+        case HCI_EV_LINK_KEY_REQ:
+            SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6);
+            break;
+#ifdef HOST_CONTR_FLOW
+        case HCI_EV_NUM_COMP_PKTS:
+            for (int k = 0; k < data[2]; k++) {//data[2] and 'c' are usually 1
+                u16 h = LE16(data+3+2*k);
+                u16 c = LE16(data+5+2*k);
+                BTDevice *d = Find(h);
+                if (!d)
+                    continue;//skip no existing devices
+                if (d->pkts_sent >= c) {
+                    d->pkts_sent -= c;
+                    _transport->data_credits += c;
+                } else
+                    d->pkts_sent = 0;
+                //printf("%d Outstanding pkts for handle %03X (total credits=%d)\n", d->pkts_sent, h, _transport->data_credits);
+            }
+            break;
+#endif
+        case HCI_EV_LINK_KEY_NOTIFY:
+        case HCI_EV_ENCRYPT_CHANGE:
+            //for(int k=0; k<1000000;k++) USBLoop();
+            break;
+
+        default:
+            printfBytes("HCIRecv:",data,data[1]+2);
+            break;
+    }
+}
+
+int HCI::Open(SocketInternal* sock, SocketAddrHdr* addr) {
+    L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
+    L2CAPAddr* l2capaddr = (L2CAPAddr*)addr;
+    BTDevice* bt = Find(&l2capaddr->bdaddr);
+    if (!bt) {
+        printf("Can't open l2cap %d on ",l2capaddr->psm);
+        printf(&l2capaddr->bdaddr);
+        printf("\n");
+        return ERR_HCI_DEVICE_NOT_FOUND;
+    }
+    l2capsock->btdevice = bt;
+    return bt->Open(sock,addr);
+}
+
+int HCI::Accept(SocketInternal* sock, int scid, int rxid) {
+    L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
+    BTDevice* bt = (BTDevice*)sock->userData;
+    if (!bt) {
+        printf("Can't accept l2cap on socket %d\n", sock->ID);
+        return ERR_HCI_DEVICE_NOT_FOUND;
+    }
+    l2capsock->btdevice = bt;
+    return bt->Accept(sock, scid, rxid);
+}
+
+int HCI::Send(SocketInternal* sock, const u8* data, int len) {//check here for appropriate buffersize on the device
+    /* these checks are HCI functions but this 'Send' does not catch all ACL traffic, so it is better done in L2CAP or transport
+    //assume acl packet
+    //FIXME: treatment of OFFSET is dubious, OFFSET is not defined?!
+    #if OFFSET==8 //sizeof ACL/L2CAP is include in data/len
+        if (len > _acl_mtu)
+    #else //OFFSET==0, data is bare application frame
+        if (len+8 > _acl_mtu)
+    #endif
+        { printf("Max outgoing packet(%d) size exceeded, segmenting necessary, pktlen = %d\n", _acl_mtu, len);
+        }
+        if (data_credits == 0) {
+            printf("Out of ACL data credits\n");
+            return 0;
+        }
+        data_credits--;
+    */
+    L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
+    return l2capsock->btdevice->Send(sock,data,len);    // Pointless double dispatch
+}
+
+int HCI::Close(SocketInternal* sock) {
+    L2CAPSocket* l2capsock = (L2CAPSocket*)sock;
+    return l2capsock->btdevice->Close(sock);    // Pointless double dispatch
+}
+
+void HCI::Compl_pkts(int handle, u8 p) {
+    u8 b[8] = {(u8)HCI_OP_NUM_COMP_PKTS, HCI_OP_NUM_COMP_PKTS >> 8, 5, 1, 0, 0, 1, 0};
+    b[4] = handle;
+    b[5] = (handle&0x0f00)>>8;
+    b[6] = p;//only one packet
+    _transport->HCISend(b, 8);//directly call the transport layer to prevent the command flow control from interfering
+}
+
+void HCI::ACLRecv(const u8* data, int len) {
+    int handle = LE16(data);
+    BTDevice* d = Find(handle & 0x0FFF);
+    int bufs = 1;
+    if (!d) {
+        printfBytes("unk. dest. HCI:ACLRecv ", data, len);
+    } else
+        bufs = d->ACLRecv(data,len);
+    //controller to host flow control
+#ifdef CONTR_HOST_FLOW
+//the ACLRecv function returned so we assume that the buffer is free, and tell this to the controller
+    if (bufs) {
+        Compl_pkts(handle, bufs);//this packet is completed
+        printf("%d ACL buffers completed\n", bufs);
+    }
+#endif
+}
+
+//===================================================================
+//===================================================================
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/hci.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,288 @@
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef HCI_H_INCLUDED
+#define HCI_H_INCLUDED
+
+//#define CONTR_HOST_FLOW     //Controller to Host flow control
+#define HOST_CONTR_FLOW     //Host to Controller flow control
+#define COMMAND_FLOW        //Command flow control
+
+#include "mbed.h"
+#include "Socket.h"
+
+#pragma pack(1)
+
+#define ERR_HCI_DEVICE_NOT_FOUND -300
+
+class HCI;
+class HCITransport;
+class BTDevice;
+
+enum StateMask {
+    MASK_RESET = 1,
+    MASK_READ_BUFFER_SIZE = 2,
+    MASK_READ_BD_ADDR = 4,
+    MASK_INITED = 8,
+    MASK_INQUIRY = 16,
+    MASK_REMOTE_NAME = 32,
+    MASK_CREATE_CONNECTION = 64
+};
+
+typedef struct
+{
+    u8  addr[6];
+} BD_ADDR;
+
+typedef struct
+{
+    BD_ADDR bdaddr;
+    u8  pscan_rep_mode;
+    u8  pscan_period_mode;
+    u8  pscan_mode;
+    u8  dev_class[3];
+    u16 clock_offset;
+} inquiry_info;
+
+typedef struct
+{
+    u8  status;
+    u16 handle;
+    BD_ADDR bdaddr;
+    u8  link_type;
+    u8  encr_mode;
+} connection_info;
+
+//  Address struct for creating L2CAP sockets
+typedef struct {
+    SocketAddrHdr hdr;
+    BD_ADDR bdaddr;
+    u16 psm;
+} L2CAPAddr;
+
+typedef struct {
+    u16    handle;
+    u16    length;            // total
+    u16    l2capLength;    // length -4
+    u16    cid;            // Signaling packet CID = 1
+
+    // Payload
+    u8    cmd;            //
+    u8    id;
+    u16    cmdLength;        // total-8
+    u16 params[4];      // Params
+} L2CAPCmd;
+
+#pragma pack(4)
+
+class BTDevice;
+
+typedef struct
+{
+    public:
+    SocketInternal si;
+    BTDevice* btdevice;
+    u16 scid;
+    u16 dcid;
+} L2CAPSocket;
+
+#define MAX_HCL_NAME_LENGTH 20  // TODO - BTDevice wants to be a multiple of 4
+
+//  BTDevice encapsulates individual device state
+//  It provides L2CAP layer sockets
+
+class BTDevice : public SocketHandler
+{
+    public:
+    HCITransport* _transport;
+    inquiry_info  _info;
+    u16 _handle;     // acl connection handle
+    u8  _state;      // connection state
+    u8  _txid;
+    u16 peer_mtu;
+#ifdef HOST_CONTR_FLOW
+    u8 pkts_sent;   //host to controller flow control
+#endif
+//u8 cntr_cred;
+u8 segments;
+    char   _name[MAX_HCL_NAME_LENGTH];
+
+    void Init();
+
+    BD_ADDR* GetAddress() { return &_info.bdaddr; }
+
+    //  Called from HCI
+    int ACLRecv(const u8* data, int len);
+    void ACLFwd(const u8* data, int len);
+
+    // SocketHandler
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
+    virtual int Accept(SocketInternal* sock, int scid, int rxid);
+    virtual int Send(SocketInternal* sock, const u8* data, int len);
+    virtual int Close(SocketInternal* sock);
+    virtual char* Name() { return "BTDevice SocketHandler";}
+
+private:
+    int l2cap_sock, plen, contPos, contState;
+    unsigned char *contBuf;
+    Timeout rtx;
+    L2CAPCmd last_req;
+    void repeat_cmd();
+    
+    L2CAPSocket* SCIDToSocket(int scid);
+    int Send(const u8* data, int len);
+    int Send(u8 c, u8 id, u16* params, int count);
+    int Connect(int scid, int psm);
+    int Disconnect(int scid, int dcid);
+    int ConfigureRequest(int dcid);
+    int CommandReject(u16 reason=0, u16 data0=0, u16 data1=0);
+    int ConfigureResponse(u8 rxid, int dcid);
+    int DisconnectResponse(u8 rxid, int scid, int dcid);
+    void Control(const u8* data, int len);
+};
+
+enum HCI_CALLBACK_EVENT
+{
+    CALLBACK_NONE,
+    CALLBACK_READY,
+    CALLBACK_INQUIRY_RESULT,
+    CALLBACK_INQUIRY_DONE,
+    CALLBACK_REMOTE_NAME,
+    CALLBACK_CONNECTION_COMPLETE,
+    CALLBACK_CONNECTION_FAILED,
+    CALLBACK_PIN_REQ,
+    CALLBACK_CMD_STATUS,
+    CALLBACK_CONNECTION_REQUEST
+};
+
+//  L2CAP Protocol/Service Multiplexor (PSM) values
+
+#define L2CAP_PSM_ANY                   0x0000  /* Any/Invalid PSM */
+#define L2CAP_PSM_SDP                   0x0001  /* Service Discovery Protocol */
+#define L2CAP_PSM_RFCOMM                0x0003  /* RFCOMM protocol */
+#define L2CAP_PSM_TCP                   0x0005  /* Telephony Control Protocol */
+#define L2CAP_PSM_TCS                   0x0007  /* TCS cordless */
+#define L2CAP_PSM_BNEP                  0x000f  /* Bluetooth Network Encapsulation Protocol*/
+#define L2CAP_PSM_HID_CNTL              0x0011  /* HID Control */
+#define L2CAP_PSM_HID_INTR              0x0013  /* HID Interrupt */
+#define L2CAP_PSM_ESDP                  0x0015  /* Extended Service Discovery Profile */
+#define L2CAP_PSM_AVCTP                 0x0017  /* Audio/Visual Control Transport Protocol */
+#define L2CAP_PSM_AVDTP                 0x0019  /* Audio/Visual Distribution */
+
+//  Callback from inquiry
+typedef int (*HCICallback)(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len);
+//typedef int (HCI::*HCICallback)(HCI_CALLBACK_EVENT evt, const u8* data, int len);
+
+#define MAX_BTDEVICES 8
+
+class HCITransport;
+class HCI : public SocketHandler
+{
+    HCITransport* _transport;
+    HCICallback _callback;
+    BD_ADDR  _localAddr;
+
+    BTDevice _devices[MAX_BTDEVICES];
+    int _deviceCount;
+
+    int _acl_mtu;
+    int _acl_max_pkt;
+    int _sco_mtu;
+    int _sco_max_pkt;
+
+    int _state;
+#ifdef COMMAND_FLOW
+    char cmd_credits;//command flow control
+#endif
+//, data_credits;//host to controller flow control is per handle, hence is handled in BTDevice
+    public:
+
+    //  Open a local adapter
+    int Open(HCITransport* transport, HCICallback callback=0);
+
+    //  Return list of discovered addreses
+    int GetDevices(BTDevice** devices, int maxDevices);
+
+    //  Lookup a device by address or handle
+    BTDevice* Find(const BD_ADDR* addr);
+    BTDevice* Find(int handle);
+
+    //  Disconnect from a remote device
+    int Disconnect(const BD_ADDR* addr);
+    int DisconnectAll();
+
+    //  see what devies are in the system
+    int Inquiry(int duration = 10);
+
+    int SetEventFilter(u8 filterType, u8 filterConditionType, u8* condition);
+    //  get a name, delivered in callback
+    int RemoteNameRequest(const BD_ADDR* addr);
+    int RemoteNameRequest(inquiry_info* ii);
+
+    //  Connect to a remote device
+    int CreateConnection(const BD_ADDR* remoteAddr);
+
+    bool Busy();
+    int State() { return _state;}
+
+    //  called from transport
+    void HCIRecv(const u8* data, int len);
+
+    //  called from transport
+    void ACLRecv(const u8* data, int len);
+
+    //  SocketHandler methods for maintaining L2CAP sockets
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
+    virtual int Accept(SocketInternal* sock, int scid, int rxid);
+    virtual int Send(SocketInternal* sock, const u8* data, int len);
+    virtual int Close(SocketInternal* sock);
+    virtual char* Name() { return "HCI SocketHandler";}
+
+private:
+    void    InquiryResult(const inquiry_info* info);
+    void    RemoteName(const BD_ADDR* addr, const char* name);
+    void    ConnectComplete(const connection_info* info);
+    void    DisconnectComplete(int handle);
+    int     SendCmd(int cmd, const u8* params = 0, int len = 0);
+    void    OnCommandComplete(int cmd, const u8* data, int len);
+    virtual void    Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
+    void Compl_pkts(int handle, u8 p = 1);
+protected:
+    int     PinCodeReply(const u8* data, const u8* pin = "0000");
+    void    Accept_Connection(const BD_ADDR* addr, bool slave=true);
+};
+
+class HCITransport
+{
+protected:
+    HCI* _target;
+public:
+#ifdef HOST_CONTR_FLOW
+    u8 data_credits;
+#endif
+    u16 _acl_mtu;
+    void Set(HCI* target) { _target = target; };
+    virtual void HCISend(const u8* data, int len) = 0;
+    virtual int ACLSend(const u8* data, int len) = 0;
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/hci_private.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,325 @@
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef HCI_PRIVATE_H_INCLUDED
+#define HCI_PRIVATE_H_INCLUDED
+
+#define HCI_OP_INQUIRY                0x0401
+#define HCI_OP_INQUIRY_CANCEL        0x0402
+#define HCI_OP_EXIT_PERIODIC_INQ    0x0404
+#define HCI_OP_CREATE_CONN            0x0405
+#define HCI_OP_DISCONNECT            0x0406
+#define HCI_OP_ADD_SCO                0x0407
+#define HCI_OP_CREATE_CONN_CANCEL    0x0408
+#define HCI_OP_ACCEPT_CONN_REQ        0x0409
+#define HCI_OP_REJECT_CONN_REQ        0x040a
+#define HCI_OP_LINK_KEY_REPLY        0x040b
+#define HCI_OP_LINK_KEY_NEG_REPLY    0x040c
+#define HCI_OP_PIN_CODE_REPLY        0x040d
+#define HCI_OP_PIN_CODE_NEG_REPLY    0x040e
+#define HCI_OP_CHANGE_CONN_PTYPE    0x040f
+#define HCI_OP_AUTH_REQUESTED        0x0411
+#define HCI_OP_SET_CONN_ENCRYPT        0x0413
+#define HCI_OP_CHANGE_CONN_LINK_KEY    0x0415
+#define HCI_OP_REMOTE_NAME_REQ        0x0419
+#define HCI_OP_REMOTE_NAME_REQ_CANCEL    0x041a
+#define HCI_OP_READ_REMOTE_FEATURES    0x041b
+#define HCI_OP_READ_REMOTE_EXT_FEATURES    0x041c
+#define HCI_OP_READ_REMOTE_VERSION    0x041d
+#define HCI_OP_SETUP_SYNC_CONN        0x0428
+#define HCI_OP_ACCEPT_SYNC_CONN_REQ    0x0429
+#define HCI_OP_REJECT_SYNC_CONN_REQ    0x042a
+
+#define HCI_OP_SNIFF_MODE            0x0803
+#define HCI_OP_EXIT_SNIFF_MODE        0x0804
+#define HCI_OP_ROLE_DISCOVERY        0x0809
+#define HCI_OP_SWITCH_ROLE            0x080b
+#define HCI_OP_READ_LINK_POLICY        0x080c
+#define HCI_OP_WRITE_LINK_POLICY    0x080d
+#define HCI_OP_READ_DEF_LINK_POLICY    0x080e
+#define HCI_OP_WRITE_DEF_LINK_POLICY    0x080f
+#define HCI_OP_SNIFF_SUBRATE        0x0811
+
+
+#define HCI_OP_SET_EVENT_MASK        0x0c01
+#define HCI_OP_RESET                0x0c03
+#define HCI_OP_SET_EVENT_FLT        0x0c05
+#define HCI_OP_WRITE_LOCAL_NAME        0x0c13
+#define HCI_OP_READ_LOCAL_NAME        0x0c14
+#define HCI_OP_WRITE_CA_TIMEOUT        0x0c16
+#define HCI_OP_WRITE_PG_TIMEOUT        0x0c18
+#define HCI_OP_WRITE_SCAN_ENABLE     0x0c1a
+#define HCI_OP_READ_AUTH_ENABLE        0x0c1f
+#define HCI_OP_WRITE_AUTH_ENABLE    0x0c20
+#define HCI_OP_READ_ENCRYPT_MODE    0x0c21
+#define HCI_OP_WRITE_ENCRYPT_MODE    0x0c22
+    #define ENCRYPT_DISABLED    0x00
+    #define ENCRYPT_P2P        0x01
+    #define ENCRYPT_BOTH        0x02
+#define HCI_OP_READ_CLASS_OF_DEV    0x0c23
+#define HCI_OP_WRITE_CLASS_OF_DEV    0x0c24
+#define HCI_OP_READ_VOICE_SETTING    0x0c25
+#define HCI_OP_WRITE_VOICE_SETTING    0x0c26
+#define HCI_OP_CONTR_TO_HOST_FLOW        0x0c31
+#define HCI_OP_HOST_BUFFER_SIZE        0x0c33
+#define HCI_OP_NUM_COMP_PKTS        0x0c35
+#define HCI_OP_READ_SSP_MODE        0x0c55
+#define HCI_OP_WRITE_SSP_MODE        0x0c56
+
+#define HCI_OP_READ_LOCAL_VERSION    0x1001
+#define HCI_OP_READ_LOCAL_COMMANDS    0x1002
+#define HCI_OP_READ_LOCAL_FEATURES    0x1003
+#define HCI_OP_READ_LOCAL_EXT_FEATURES    0x1004
+#define HCI_OP_READ_BUFFER_SIZE        0x1005
+#define HCI_OP_READ_BD_ADDR            0x1009
+
+//  events
+#define HCI_EV_INQUIRY_COMPLETE        0x01
+#define HCI_EV_INQUIRY_RESULT        0x02
+#define HCI_EV_CONN_COMPLETE        0x03
+#define HCI_EV_CONN_REQUEST            0x04
+#define HCI_EV_DISCONN_COMPLETE        0x05
+#define HCI_EV_AUTH_COMPLETE        0x06
+#define HCI_EV_REMOTE_NAME            0x07
+#define HCI_EV_ENCRYPT_CHANGE        0x08
+#define HCI_EV_CHANGE_LINK_KEY_COMPLETE    0x09
+#define HCI_EV_REMOTE_FEATURES        0x0b
+#define HCI_EV_REMOTE_VERSION        0x0c
+#define HCI_EV_QOS_SETUP_COMPLETE    0x0d
+#define HCI_EV_CMD_COMPLETE            0x0e
+#define HCI_EV_CMD_STATUS            0x0f
+#define HCI_EV_ROLE_CHANGE            0x12
+#define HCI_EV_NUM_COMP_PKTS        0x13
+#define HCI_EV_MODE_CHANGE            0x14
+#define HCI_EV_PIN_CODE_REQ            0x16
+#define HCI_EV_LINK_KEY_REQ            0x17
+#define HCI_EV_LINK_KEY_NOTIFY        0x18
+#define HCI_EV_CLOCK_OFFSET            0x1c
+#define HCI_EV_PKT_TYPE_CHANGE        0x1d
+#define HCI_EV_PSCAN_REP_MODE        0x20
+#define HCI_EV_INQUIRY_RESULT_WITH_RSSI    0x22
+#define HCI_EV_REMOTE_EXT_FEATURES    0x23
+#define HCI_EV_SYNC_CONN_COMPLETE    0x2c
+#define HCI_EV_SYNC_CONN_CHANGED    0x2d
+#define HCI_EV_SNIFF_SUBRATE        0x2e
+#define HCI_EV_EXTENDED_INQUIRY_RESULT    0x2f
+#define HCI_EV_IO_CAPA_REQUEST        0x31
+#define HCI_EV_SIMPLE_PAIR_COMPLETE    0x36
+#define HCI_EV_REMOTE_HOST_FEATURES    0x3d
+
+/* Possible error codes */
+#define HCI_UNKNOWN_HCI_COMMAND 0x01
+#define HCI_NO_CONNECTION 0x02
+#define HCI_HW_FAILURE 0x03
+#define HCI_PAGE_TIMEOUT 0x04
+#define HCI_AUTHENTICATION_FAILURE 0x05
+#define HCI_KEY_MISSING 0x06
+#define HCI_MEMORY_FULL 0x07
+#define HCI_CONN_TIMEOUT 0x08
+#define HCI_MAX_NUMBER_OF_CONNECTIONS 0x09
+#define HCI_MAX_NUMBER_OF_SCO_CONNECTIONS_TO_DEVICE 0x0A
+#define HCI_ACL_CONNECTION_EXISTS 0x0B
+#define HCI_COMMAND_DISSALLOWED 0x0C
+#define HCI_HOST_REJECTED_DUE_TO_LIMITED_RESOURCES 0x0D
+#define HCI_HOST_REJECTED_DUE_TO_SECURITY_REASONS 0x0E
+#define HCI_HOST_REJECTED_DUE_TO_REMOTE_DEVICE_ONLY_PERSONAL_SERVICE 0x0F
+#define HCI_HOST_TIMEOUT 0x10
+#define HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE 0x11
+#define HCI_INVALID_HCI_COMMAND_PARAMETERS 0x12
+#define HCI_OTHER_END_TERMINATED_CONN_USER_ENDED 0x13
+#define HCI_OTHER_END_TERMINATED_CONN_LOW_RESOURCES 0x14
+#define HCI_OTHER_END_TERMINATED_CONN_ABOUT_TO_POWER_OFF 0x15
+#define HCI_CONN_TERMINATED_BY_LOCAL_HOST 0x16
+#define HCI_REPETED_ATTEMPTS 0x17
+#define HCI_PAIRING_NOT_ALLOWED 0x18
+#define HCI_UNKNOWN_LMP_PDU 0x19
+#define HCI_UNSUPPORTED_REMOTE_FEATURE 0x1A
+#define HCI_SCO_OFFSET_REJECTED 0x1B
+#define HCI_SCO_INTERVAL_REJECTED 0x1C
+#define HCI_SCO_AIR_MODE_REJECTED 0x1D
+#define HCI_INVALID_LMP_PARAMETERS 0x1E
+#define HCI_UNSPECIFIED_ERROR 0x1F
+#define HCI_UNSUPPORTED_LMP_PARAMETER_VALUE 0x20
+#define HCI_ROLE_CHANGE_NOT_ALLOWED 0x21
+#define HCI_LMP_RESPONSE_TIMEOUT 0x22
+#define HCI_LMP_ERROR_TRANSACTION_COLLISION 0x23
+#define HCI_LMP_PDU_NOT_ALLOWED 0x24
+#define HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE 0x25
+#define HCI_UNIT_KEY_USED 0x26
+#define HCI_QOS_NOT_SUPPORTED 0x27
+#define HCI_INSTANT_PASSED 0x28
+#define HCI_PAIRING_UNIT_KEY_NOT_SUPPORTED 0x29
+
+const char* EvtStr(int evt)
+{
+    switch (evt)
+    {
+        case HCI_EV_INQUIRY_COMPLETE:    return "HCI_EV_INQUIRY_COMPLETE";
+        case HCI_EV_INQUIRY_RESULT:    return "HCI_EV_INQUIRY_RESULT";
+        case HCI_EV_CONN_COMPLETE:    return "HCI_EV_CONN_COMPLETE";
+        case HCI_EV_CONN_REQUEST:    return "HCI_EV_CONN_REQUEST";
+        case HCI_EV_DISCONN_COMPLETE:    return "HCI_EV_DISCONN_COMPLETE";
+        case HCI_EV_AUTH_COMPLETE:    return "HCI_EV_AUTH_COMPLETE";
+        case HCI_EV_REMOTE_NAME:    return "HCI_EV_REMOTE_NAME";
+        case HCI_EV_ENCRYPT_CHANGE:    return "HCI_EV_ENCRYPT_CHANGE";
+        case HCI_EV_CHANGE_LINK_KEY_COMPLETE    :    return "HCI_EV_CHANGE_LINK_KEY_COMPLETE";
+        case HCI_EV_REMOTE_FEATURES:    return "HCI_EV_REMOTE_FEATURES";
+        case HCI_EV_REMOTE_VERSION:    return "HCI_EV_REMOTE_VERSION";
+        case HCI_EV_QOS_SETUP_COMPLETE    :    return "HCI_EV_QOS_SETUP_COMPLETE";
+        case HCI_EV_CMD_COMPLETE:    return "HCI_EV_CMD_COMPLETE";
+        case HCI_EV_CMD_STATUS:    return "HCI_EV_CMD_STATUS";
+        case HCI_EV_ROLE_CHANGE:    return "HCI_EV_ROLE_CHANGE";
+        case HCI_EV_NUM_COMP_PKTS:    return "HCI_EV_NUM_COMP_PKTS";
+        case HCI_EV_MODE_CHANGE:    return "HCI_EV_MODE_CHANGE";
+        case HCI_EV_PIN_CODE_REQ:    return "HCI_EV_PIN_CODE_REQ";
+        case HCI_EV_LINK_KEY_REQ:    return "HCI_EV_LINK_KEY_REQ";
+        case HCI_EV_LINK_KEY_NOTIFY:    return "HCI_EV_LINK_KEY_NOTIFY";
+        case HCI_EV_CLOCK_OFFSET:    return "HCI_EV_CLOCK_OFFSET";
+        case HCI_EV_PKT_TYPE_CHANGE:    return "HCI_EV_PKT_TYPE_CHANGE";
+        case HCI_EV_PSCAN_REP_MODE:    return "HCI_EV_PSCAN_REP_MODE";
+        case HCI_EV_INQUIRY_RESULT_WITH_RSSI    :    return "HCI_EV_INQUIRY_RESULT_WITH_RSSI";
+        case HCI_EV_REMOTE_EXT_FEATURES:    return "HCI_EV_REMOTE_EXT_FEATURES";
+        case HCI_EV_SYNC_CONN_COMPLETE:    return "HCI_EV_SYNC_CONN_COMPLETE";
+        case HCI_EV_SYNC_CONN_CHANGED:    return "HCI_EV_SYNC_CONN_CHANGED";
+        case HCI_EV_SNIFF_SUBRATE:    return "HCI_EV_SNIFF_SUBRATE";
+        case HCI_EV_EXTENDED_INQUIRY_RESULT:    return "HCI_EV_EXTENDED_INQUIRY_RESULT";
+        case HCI_EV_IO_CAPA_REQUEST:    return "HCI_EV_IO_CAPA_REQUEST";
+        case HCI_EV_SIMPLE_PAIR_COMPLETE:    return "HCI_EV_SIMPLE_PAIR_COMPLETE";
+        case HCI_EV_REMOTE_HOST_FEATURES:    return "HCI_EV_REMOTE_HOST_FEATURES";
+    }
+    return "Unknown Event";
+}
+
+const char* CmdStr(int cmd)
+{
+    switch (cmd)
+    {
+        // 0x04XX
+        case HCI_OP_INQUIRY:    return "HCI_OP_INQUIRY";
+        case HCI_OP_INQUIRY_CANCEL:    return "HCI_OP_INQUIRY_CANCEL";
+        case HCI_OP_EXIT_PERIODIC_INQ:    return "HCI_OP_EXIT_PERIODIC_INQ";
+        case HCI_OP_CREATE_CONN:    return "HCI_OP_CREATE_CONN";
+        case HCI_OP_DISCONNECT:    return "HCI_OP_DISCONNECT";
+        case HCI_OP_ADD_SCO:    return "HCI_OP_ADD_SCO";
+        case HCI_OP_CREATE_CONN_CANCEL:    return "HCI_OP_CREATE_CONN_CANCEL";
+        case HCI_OP_ACCEPT_CONN_REQ:    return "HCI_OP_ACCEPT_CONN_REQ";
+        case HCI_OP_REJECT_CONN_REQ:    return "HCI_OP_REJECT_CONN_REQ";
+        case HCI_OP_LINK_KEY_REPLY:    return "HCI_OP_LINK_KEY_REPLY";
+        case HCI_OP_LINK_KEY_NEG_REPLY:    return "HCI_OP_LINK_KEY_NEG_REPLY";
+        case HCI_OP_PIN_CODE_REPLY:    return "HCI_OP_PIN_CODE_REPLY";
+        case HCI_OP_PIN_CODE_NEG_REPLY:    return "HCI_OP_PIN_CODE_NEG_REPLY";
+        case HCI_OP_CHANGE_CONN_PTYPE:    return "HCI_OP_CHANGE_CONN_PTYPE";
+        case HCI_OP_AUTH_REQUESTED:    return "HCI_OP_AUTH_REQUESTED";
+        case HCI_OP_SET_CONN_ENCRYPT:    return "HCI_OP_SET_CONN_ENCRYPT";
+        case HCI_OP_CHANGE_CONN_LINK_KEY:    return "HCI_OP_CHANGE_CONN_LINK_KEY";
+        case HCI_OP_REMOTE_NAME_REQ:    return "HCI_OP_REMOTE_NAME_REQ";
+        case HCI_OP_REMOTE_NAME_REQ_CANCEL:    return "HCI_OP_REMOTE_NAME_REQ_CANCEL";
+        case HCI_OP_READ_REMOTE_FEATURES:    return "HCI_OP_READ_REMOTE_FEATURES";
+        case HCI_OP_READ_REMOTE_EXT_FEATURES:    return "HCI_OP_READ_REMOTE_EXT_FEATURES";
+        case HCI_OP_READ_REMOTE_VERSION:    return "HCI_OP_READ_REMOTE_VERSION";
+        case HCI_OP_SETUP_SYNC_CONN:    return "HCI_OP_SETUP_SYNC_CONN";
+        case HCI_OP_ACCEPT_SYNC_CONN_REQ:    return "HCI_OP_ACCEPT_SYNC_CONN_REQ";
+        case HCI_OP_REJECT_SYNC_CONN_REQ:    return "HCI_OP_REJECT_SYNC_CONN_REQ";
+        // 0x0CXX
+        case HCI_OP_SET_EVENT_MASK: return "HCI_OP_SET_EVENT_MASK";
+        case HCI_OP_RESET:            return "HCI_OP_RESET";
+        case HCI_OP_SET_EVENT_FLT:  return "HCI_OP_SET_EVENT_FLT";
+        case HCI_OP_WRITE_LOCAL_NAME:   return "HCI_OP_WRITE_LOCAL_NAME";
+        case HCI_OP_READ_LOCAL_NAME:    return "HCI_OP_READ_LOCAL_NAME";
+        case HCI_OP_WRITE_CA_TIMEOUT:   return "HCI_OP_WRITE_CA_TIMEOUT";
+        case HCI_OP_WRITE_PG_TIMEOUT:   return "HCI_OP_WRITE_PG_TIMEOUT";
+        case HCI_OP_WRITE_SCAN_ENABLE:  return "HCI_OP_WRITE_SCAN_ENABLE";
+        case HCI_OP_READ_AUTH_ENABLE:   return "HCI_OP_READ_AUTH_ENABLE";
+        case HCI_OP_WRITE_AUTH_ENABLE:  return "HCI_OP_WRITE_AUTH_ENABLE";
+        case HCI_OP_READ_ENCRYPT_MODE:  return "HCI_OP_READ_ENCRYPT_MODE";
+        case HCI_OP_WRITE_ENCRYPT_MODE: return "HCI_OP_WRITE_ENCRYPT_MODE";
+        case HCI_OP_READ_CLASS_OF_DEV:  return "HCI_OP_READ_CLASS_OF_DEV";
+        case HCI_OP_WRITE_CLASS_OF_DEV:    return "HCI_OP_WRITE_CLASS_OF_DEV";
+        case HCI_OP_READ_VOICE_SETTING: return "HCI_OP_READ_VOICE_SETTING";
+        case HCI_OP_WRITE_VOICE_SETTING:    return "HCI_OP_WRITE_VOICE_SETTING";
+        case HCI_OP_HOST_BUFFER_SIZE:   return "HCI_OP_HOST_BUFFER_SIZE";
+        case HCI_OP_READ_SSP_MODE:      return "HCI_OP_READ_SSP_MODE";
+        case HCI_OP_WRITE_SSP_MODE: return "HCI_OP_WRITE_SSP_MODE";
+
+        // 10xx
+        case HCI_OP_READ_LOCAL_VERSION: return "HCI_OP_READ_LOCAL_VERSION";
+        case HCI_OP_READ_LOCAL_COMMANDS: return "HCI_OP_READ_LOCAL_COMMANDS";
+        case HCI_OP_READ_LOCAL_FEATURES: return "HCI_OP_READ_LOCAL_FEATURES";
+        case HCI_OP_READ_LOCAL_EXT_FEATURES: return "HCI_OP_READ_LOCAL_EXT_FEATURES";
+        case HCI_OP_READ_BUFFER_SIZE: return "HCI_OP_READ_BUFFER_SIZE";
+        case HCI_OP_READ_BD_ADDR: return "HCI_OP_READ_BD_ADDR";
+    }
+    return "Unknown Cmd";
+}
+
+const char* HCIErrStr(int err)
+{
+    switch (err)
+    {
+        case 0: return "OK";
+        case HCI_UNKNOWN_HCI_COMMAND:    return "HCI_UNKNOWN_HCI_COMMAND";
+        case HCI_NO_CONNECTION:    return "HCI_NO_CONNECTION";
+        case HCI_HW_FAILURE:    return "HCI_HW_FAILURE";
+        case HCI_PAGE_TIMEOUT:    return "HCI_PAGE_TIMEOUT";
+        case HCI_AUTHENTICATION_FAILURE:    return "HCI_AUTHENTICATION_FAILURE";
+        case HCI_KEY_MISSING:    return "HCI_KEY_MISSING";
+        case HCI_MEMORY_FULL:    return "HCI_MEMORY_FULL";
+        case HCI_CONN_TIMEOUT:    return "HCI_CONN_TIMEOUT";
+        case HCI_MAX_NUMBER_OF_CONNECTIONS:    return "HCI_CONN_TIMEOUT";
+        case HCI_MAX_NUMBER_OF_SCO_CONNECTIONS_TO_DEVICE:    return "HCI_MAX_NUMBER_OF_SCO_CONNECTIONS_TO_DEVICE";
+        case HCI_ACL_CONNECTION_EXISTS:    return "HCI_ACL_CONNECTION_EXISTS";
+        case HCI_COMMAND_DISSALLOWED:    return "HCI_COMMAND_DISSALLOWED";
+        case HCI_HOST_REJECTED_DUE_TO_LIMITED_RESOURCES:    return "HCI_HOST_REJECTED_DUE_TO_LIMITED_RESOURCES";
+        case HCI_HOST_REJECTED_DUE_TO_SECURITY_REASONS:    return "HCI_HOST_REJECTED_DUE_TO_SECURITY_REASONS";
+        case HCI_HOST_REJECTED_DUE_TO_REMOTE_DEVICE_ONLY_PERSONAL_SERVICE:    return "HCI_HOST_REJECTED_DUE_TO_REMOTE_DEVICE_ONLY_PERSONAL_SERVICE";
+        case HCI_HOST_TIMEOUT:    return "HCI_HOST_TIMEOUT";
+        case HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE:    return "HCI_UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE";
+        case HCI_INVALID_HCI_COMMAND_PARAMETERS:    return "HCI_INVALID_HCI_COMMAND_PARAMETERS";
+        case HCI_OTHER_END_TERMINATED_CONN_USER_ENDED:    return "HCI_OTHER_END_TERMINATED_CONN_USER_ENDED";
+        case HCI_OTHER_END_TERMINATED_CONN_LOW_RESOURCES:    return "HCI_OTHER_END_TERMINATED_CONN_LOW_RESOURCES";
+        case HCI_OTHER_END_TERMINATED_CONN_ABOUT_TO_POWER_OFF:    return "HCI_OTHER_END_TERMINATED_CONN_ABOUT_TO_POWER_OFF";
+        case HCI_CONN_TERMINATED_BY_LOCAL_HOST:    return "HCI_CONN_TERMINATED_BY_LOCAL_HOST";
+        case HCI_REPETED_ATTEMPTS:    return "HCI_REPEATED_ATTEMPTS";
+        case HCI_PAIRING_NOT_ALLOWED:    return "HCI_PAIRING_NOT_ALLOWED";
+        case HCI_UNKNOWN_LMP_PDU:    return "HCI_UNKNOWN_LMP_PDU";
+        case HCI_UNSUPPORTED_REMOTE_FEATURE:    return "HCI_UNSUPPORTED_REMOTE_FEATURE";
+        case HCI_SCO_OFFSET_REJECTED:    return "HCI_SCO_OFFSET_REJECTED";
+        case HCI_SCO_INTERVAL_REJECTED:    return "HCI_SCO_INTERVAL_REJECTED";
+        case HCI_SCO_AIR_MODE_REJECTED:    return "HCI_SCO_AIR_MODE_REJECTED";
+        case HCI_INVALID_LMP_PARAMETERS:    return "HCI_INVALID_LMP_PARAMETERS";
+        case HCI_UNSPECIFIED_ERROR:    return "HCI_UNSPECIFIED_ERROR";
+        case HCI_UNSUPPORTED_LMP_PARAMETER_VALUE:    return "HCI_UNSUPPORTED_LMP_PARAMETER_VALUE";
+        case HCI_ROLE_CHANGE_NOT_ALLOWED:    return "HCI_ROLE_CHANGE_NOT_ALLOWED";
+        case HCI_LMP_RESPONSE_TIMEOUT:    return "HCI_LMP_RESPONSE_TIMEOUT";
+        case HCI_LMP_ERROR_TRANSACTION_COLLISION:    return "HCI_LMP_ERROR_TRANSACTION_COLLISION";
+        case HCI_LMP_PDU_NOT_ALLOWED:    return "HCI_LMP_PDU_NOT_ALLOWED";
+        case HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE:    return "HCI_ENCRYPTION_MODE_NOT_ACCEPTABLE";
+        case HCI_UNIT_KEY_USED:    return "HCI_UNIT_KEY_USED";
+        case HCI_QOS_NOT_SUPPORTED:    return "HCI_QOS_NOT_SUPPORTED";
+        case HCI_INSTANT_PASSED:    return "HCI_INSTANT_PASSED";
+        case HCI_PAIRING_UNIT_KEY_NOT_SUPPORTED:    return "HCI_PAIRING_UNIT_KEY_NOT_SUPPORTED";
+    };
+    return "Unknow HCI err";
+};
+
+
+#endif // HCI_PRIVATE_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/rfcomm/RFCOMM.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,660 @@
+#include "mbed.h"
+#include "Utils.h"
+#include "RFCOMM.h"
+
+// Control field values      bit no.       1 2 3 4 5   6 7 8
+#define BT_RFCOMM_SABM       0x3F       // 1 1 1 1 P/F 1 0 0
+#define BT_RFCOMM_UA         0x73       // 1 1 0 0 P/F 1 1 0
+#define BT_RFCOMM_DM         0x0F       // 1 1 1 1 P/F 0 0 0
+#define BT_RFCOMM_DM_PF      0x1F
+#define BT_RFCOMM_DISC       0x53       // 1 1 0 0 P/F 0 1 0
+#define BT_RFCOMM_UIH        0xEF       // 1 1 1 1 P/F 1 1 1
+#define BT_RFCOMM_UIH_PF     0xFF
+
+// Multiplexer message types
+#define BT_RFCOMM_PN_CMD     0x83
+#define BT_RFCOMM_PN_RSP     0x81
+#define BT_RFCOMM_TEST_CMD   0x23
+#define BT_RFCOMM_TEST_RSP   0x21
+#define BT_RFCOMM_FCON_CMD   0xA3
+#define BT_RFCOMM_FCON_RSP   0xA1
+#define BT_RFCOMM_FCOFF_CMD  0x63
+#define BT_RFCOMM_FCOFF_RSP  0x61
+#define BT_RFCOMM_MSC_CMD    0xE3
+#define BT_RFCOMM_MSC_RSP    0xE1
+#define BT_RFCOMM_RPN_CMD    0x93
+#define BT_RFCOMM_RPN_RSP    0x91
+#define BT_RFCOMM_RLS_CMD    0x53
+#define BT_RFCOMM_RLS_RSP    0x51
+#define BT_RFCOMM_NSC_RSP    0x11
+
+// FCS calc
+#define BT_RFCOMM_CODE_WORD         0xE0 // pol = x8+x2+x1+1
+#define BT_RFCOMM_CRC_CHECK_LEN     3
+#define BT_RFCOMM_UIHCRC_CHECK_LEN  2
+
+#define NR_CREDITS  1
+#define INITIAL_CREDITS 1 //0...7
+#define MAX_FRAME_SIZE  350  //ACL buffer - some headroom
+
+#define DEBUG   0
+
+//  Instance
+RFCOMMManager rfcomm_manager;
+
+//uint8_t rfcomm_out_buffer[1000];//seems a bit big as default max framesize is 127
+unsigned rfcomm::maxframesize = MAX_FRAME_SIZE; //only initial value
+
+//these functions are obtained from rfcomm.c on google code
+void _bt_rfcomm_send_sabm(unsigned short source_cid, unsigned char initiator, unsigned char channel);
+void _bt_rfcomm_send_uih_pn_command(unsigned short source_cid, unsigned char initiator, unsigned char channel, unsigned short max_frame_size);
+void _bt_rfcomm_send_uih_msc_cmd(unsigned short source_cid, unsigned char initiator, unsigned char channel, unsigned char signals);
+void _bt_rfcomm_send_uih_rpn_cmd(uint16_t source_cid, uint8_t initiator, uint8_t dlci, port_settings *val);
+int rfcomm_send_packet(unsigned short source_cid, unsigned char address, unsigned char control, unsigned char credits, const unsigned char *data, unsigned short len);
+uint8_t crc8_calc(uint8_t *data, uint16_t len);
+
+
+//find a free socket slot for channel ch
+int rfcomm::find_slot(unsigned ch) {
+    for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
+        if (sckts[i] != 0) { //socket is in use
+            RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
+            if (s==0) {
+                printf("find_slot: socket  %d not found\n", sckts[i]);
+                continue;
+            }
+            if (s->dlci >> 1 == ch) {
+                printf("Channel %d is already in use on socket %d\n", ch, sckts[i]);
+                return -1;
+            }
+        } else //slot is free
+            return i;
+    }
+    return -2; //no free slots
+}
+
+//find the rfcomm socket for dlci
+RFCOMMSocket* rfcomm::find_socket(unsigned dlci) {
+    for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
+        if (sckts[i] != 0) { //socket is in use
+            RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
+            if (s==0) {
+                printf("find_socket: socket  %d not found\n", sckts[i]);
+                continue;
+            }
+            if (s->dlci == dlci) {
+                return s;
+            }
+        }
+    }
+    printf("RFCOMMSocket for dlci %d was not found!\n", dlci);
+    return 0; //socket not found
+}
+
+//send a PN command to all sockets waiting to be opened
+void rfcomm::initChannels(int socket) {
+    for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
+        if (sckts[i] != 0) { //socket is in use
+            RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
+            if (s==0) {
+                printf("initChannels: socket  %d not found\n", sckts[i]);
+                continue;
+            }
+            if (s->State == SocketState_Opening) {
+                printf("Sending PN for DLCI %d on socket %d\n", s->dlci, sckts[i]);
+                _bt_rfcomm_send_uih_pn_command(socket, 1, s->dlci, maxframesize);
+                s->State = SocketState_L2CAP_Config_wait;
+            }
+        }
+    }
+}
+
+unsigned rfcomm::release_channel(unsigned dlci) {
+    int n = 0;
+    for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
+        if (sckts[i] != 0) { //socket is in use
+            RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
+            if (s==0) {
+                printf("Release: socket for dlci %d not found\n", dlci);
+                continue;
+            }
+            if (s->dlci == dlci)
+                sckts[i] = 0;
+            else
+                n++;
+        }
+    }
+    return n;
+}
+
+int rfcomm::Send(SocketInternal *sock, const u8* data, int len) {//also see if credits need to be send
+    RFCOMMSocket *s = (RFCOMMSocket*)sock;
+    char credits = 0;
+    char control = BT_RFCOMM_UIH;
+    if (len + 14 > maxframesize) //hci/l2cap header =8, rfcomm header ~ 6
+        printf("Error! packetsize = %d, maxframesize = %d\n", len, maxframesize);
+    if (s->peer_credits == 0) {//peer is low on credits
+        credits = NR_CREDITS;
+        control = BT_RFCOMM_UIH_PF;
+        s->peer_credits += NR_CREDITS;//so provide some more
+    }
+    unsigned char address = (1 << 0) | (initiator << 1) | (s->dlci << 2);
+    if (s->my_credits) {
+        s->my_credits--;
+        return rfcomm_send_packet(_l2cap, address, control, credits, data, len);
+    } else
+        return rfcomm_send_packet(_l2cap, address, control, credits, data, 0);//send an empty packet when credits run out
+}
+
+int rfcomm::Close(SocketInternal* sock) {
+    RFCOMMSocket *s = (RFCOMMSocket*)sock;
+    int id = s->dlci;
+    printf("Closing rfcomm dlci %d state=%d\n", id, s->State);
+    Disconnect(s);
+    int n = release_channel(id);
+    printf("%d channels are still open\n", n);
+    if (n == 0) {//all rfcomm channels are closed
+        printf("....L2CAP must be closed as well\n");
+        rfcomm_send_packet(_l2cap, (1 << 0) | (initiator << 1) /*|  (!initiator << 2)*/, BT_RFCOMM_DISC, 0, 0, 0); //close dlci0
+        Socket_Close(_l2cap);
+        _l2cap = 0; //return rfcomm to the pool
+    }
+    return 0;
+}
+
+int rfcomm::Disconnect(RFCOMMSocket *s) {
+    unsigned char address = (1 << 0) | (initiator << 1) | (s->dlci << 2);
+    return rfcomm_send_packet(_l2cap, address, BT_RFCOMM_DISC, 0, 0, 0);
+}
+
+//expect this to be called with socket type=SOCKET_RFCOM and addr->psm = channel and addr->bdaddr is the BT addr
+//of the device to connect to.
+//eg. Socket_Open(SOCKET_RFCOM, rfcommaddr(bdaddr, chan), receiver_func, appl_obj);
+int rfcomm::Open(SocketInternal* sock, SocketAddrHdr* addr) {
+    int ch = ((L2CAPAddr*)addr)->psm;//abused psm for channel ID
+    RFCOMMSocket *s = (RFCOMMSocket*)sock;
+    int slot = find_slot(ch);
+    if (slot < 0) return 0;
+    sckts[slot] = s->ID;
+    s->serdevice = this;
+    s->State = SocketState_Opening;
+
+    if (_l2cap == 0) { //no rfcomm -> l2cap connection yet
+        printf("Need to open L2CAP channel first before opening RFCOMM channel %d\n", s->dlci);
+        ((L2CAPAddr*)addr)->psm = L2CAP_PSM_RFCOMM;//open the l2cap channel and the rfcomm_ch channel
+        initiator = 1;
+        s->dlci = (ch<<1)|!initiator; 
+        _l2cap = Socket_Open(SOCKET_L2CAP, addr, OnRfCommControl, this);//this is the socket between the RFCOMM and the L2CAP layer
+        if (_l2cap)
+            printf("Successfully opened L2CAP channel on socket %d\n", _l2cap);
+        else {
+            printf("Opening L2CAP channel failed\n");
+            sckts[slot] = 0;
+            s->State = SocketState_Closed;
+            return 0;
+        }
+    } else {//bypass the l2cap channel creation
+        s->dlci = (ch<<1)|!initiator; 
+        _bt_rfcomm_send_uih_pn_command(_l2cap, initiator, s->dlci, maxframesize);
+        s->State = SocketState_L2CAP_Config_wait;
+    }
+    return s->ID; //return the application unique socket nr.
+}
+
+int rfcomm::set_remote_port_parameters(unsigned char dlci, port_settings *p) {
+    _bt_rfcomm_send_uih_rpn_cmd(_l2cap, initiator, dlci, p);
+    return 0;
+}
+
+/*
+int rfcomm::Open(BD_ADDR* bdAddr, inquiry_info* info) {//obsolete???
+    _addr = *bdAddr;
+    L2CAPAddr sockAddr;
+    sockAddr.bdaddr = _addr;
+    //open an L2CAP socket for RFCOMM
+    sockAddr.psm = L2CAP_PSM_RFCOMM;
+    _l2cap = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnRfCommControl,this);//this is the socket between the RFCOMM and the L2CAP layer
+
+    printfBytes("OPEN DEVICE CLASS",info->dev_class,3);
+    _devClass = (info->dev_class[0] << 16) | (info->dev_class[1] << 8) | info->dev_class[2];
+    return _l2cap;
+}
+*/
+
+//socket is an L2CAP socket and state is the state of the L2CAP socket, not the RFCOMM socket
+void rfcomm::OnRfCommControl(int socket, SocketState state, const u8* data, int len, void* userData) {
+    int packet_processed = 0;
+    rfcomm* self = (rfcomm*)userData;
+    const u8 initiator = self->initiator;
+    printf("\x1B[%dm", 32); //debug: set a different colour
+    //printf("OnRfCommControl sock = %d, state = %d, length = %d\n", socket, state, len);
+
+    if (len == 0) {//client only
+        if (state==SocketState_Open) {//callback after change to 'open', the rfcomm->l2cap channel is now open
+            _bt_rfcomm_send_sabm(socket, initiator, 0); //setup the rfcomm control channel dlci==0
+            return;
+        }
+        return; //or other states to handle, e.g. Closing or Closed
+    }
+    //we have data, so parse the header
+    const u8 &addr = data[0];
+    u8 dlci = addr>>2;
+    const u8 &control = data[1];
+    u16 length = data[2]>>1;
+    const u8 *payload = data+3;
+    const u8 *pFCS = data+len-1; //expected position of the CRC
+    if (data[2]&1 == 0) { //two byte length
+        length += data[3]<<7;
+        payload++;
+    }
+    u8 credits = 0;
+    if (control == BT_RFCOMM_UIH_PF)//this packet carries credits
+        credits = *(payload++);
+    //sanity check
+    if (payload+length != pFCS)
+        printf("RFCOMM size mismatch, expected %d payload bytes, got %d\n", length, pFCS-payload);
+
+    if (DEBUG) {
+        printf("RFCOMM: EA=%d, C/R=%d, D=%d, ch=%d; control=%02X (P/F=%d); length=%d\n", addr&1, (addr>>1)&1, (addr>>2)&1, (addr>>3), control, (control>>4)&1, length);
+        printfBytes("payload:", payload, length);
+    }
+    if (dlci == 0) { //dlci==0 control channel
+        L2CAPSocket *s = (L2CAPSocket*)GetSocketInternal(socket);
+        switch (control) {
+            case BT_RFCOMM_UA://     received 1. message BT_RF_COMM_UA
+                packet_processed++;
+                if (s->si.State == SocketState_Closing || s->si.State==SocketState_L2CAP_WaitDisconnect) { //Confirmation of disconnect
+                    printf("Remote side confirmed disconnect for socket %d\n", s->si.ID);
+                    s->si.SetState(SocketState_Closed);
+                    break;
+                }
+                printf("Received RFCOMM unnumbered acknowledgement for channel 0 - multiplexer working\n");
+                printf("Sending UIH Parameter Negotiation Command from OnRfCommControl\n");
+                self->initChannels(socket);
+                //_bt_rfcomm_send_uih_pn_command(socket, initiator, rfcomm_ch, MAX_FRAME_SIZE);
+                break;
+            case BT_RFCOMM_UIH://  received UIH Parameter Negotiation Response
+                switch (payload[0]) {
+                    case BT_RFCOMM_PN_RSP: {//client
+                        packet_processed++;
+                        printf("UIH Parameter Negotiation Response\n");
+                        printf("Sending SABM #%u\n", payload[2]);
+                        _bt_rfcomm_send_sabm(socket, initiator, payload[2]);//was rfcomm_ch
+                        RFCOMMSocket *r = self->find_socket(payload[2]);
+                        if (r==0) break;
+                        r->my_credits = payload[9]; //initial amount of credits
+                        maxframesize = min(maxframesize, payload[6] + (payload[7]<<8));
+                        printf("Max Frame Size = %d, got %d initial credits\n", maxframesize, payload[9]);
+                    }
+                    break;
+                    case BT_RFCOMM_PN_CMD: { //remote side send PN command, mtu and initial credits
+                        packet_processed++;
+                        printf("UIH Parameter Negotiation Indication\n");
+                        maxframesize = min(maxframesize, payload[6] + (payload[7]<<8));
+                        unsigned char cred = payload[9] & 7;
+                        unsigned char _dlci = payload[2];
+
+                        int skt = rfcomm_manager.find_socket(_dlci>>1);
+                        if (skt == 0) { //No-one is listening
+                            printf("No-one is Listening on channel %d\n", _dlci>>1);
+                            rfcomm_send_packet(socket, (_dlci<<2)|1, BT_RFCOMM_DM, 0, 0, 0);
+                            break;
+                        }
+                        RFCOMMSocket *r = (RFCOMMSocket*)GetSocketInternal(skt);
+                        r->my_credits = cred;
+                        r->peer_credits = INITIAL_CREDITS;
+                        unsigned char reply[10];
+                        memcpy(reply, payload, sizeof(reply));
+                        reply[0] = BT_RFCOMM_PN_RSP;//[1]=len, [2]=dlci, [4]=priority, [5]=timer(must be 0), [8] retransmissions (must be 0)
+                        reply[3] = payload[3]==0xF0 ? 0xE0 : 0; //support credit based flow control
+                        reply[6] = maxframesize;
+                        reply[7] = maxframesize>>8;
+                        reply[9] = payload[3]==0xF0 ? r->peer_credits : 0;
+                        printf("Max Frame Size = %d, give %d initial credits\n", maxframesize, reply[9]);
+                        rfcomm_send_packet(socket, addr^2, BT_RFCOMM_UIH, 0, reply, sizeof(reply));
+                    }
+                    break;
+                    case BT_RFCOMM_MSC_CMD:
+                        packet_processed++;
+                        {
+                            printf("Received BT_RFCOMM_MSC_IND\n");
+                            // fine with this
+                            RFCOMMSocket *r = self->find_socket(payload[2]>>2);
+                            if (r==0) break;
+                            unsigned char reply[5];
+                            memcpy(reply, payload, 5); //keep length, dlci and value(s)
+                            reply[0]  = BT_RFCOMM_MSC_RSP;  // change command into response
+                            printf("Sending MSC_RSP (%d bytes)\n", length);
+                            rfcomm_send_packet(socket, addr^2, BT_RFCOMM_UIH, 0, reply, (payload[1]>>1)+2); // reply is 4 or 5 bytes
+                            switch (r->State) {
+                                case SocketState_L2CAP_Config_wait:
+                                    r->State = SocketState_L2CAP_Config_wait_send;
+                                    printf("Sending MSC_CMD\n");
+                                    _bt_rfcomm_send_uih_msc_cmd(socket, initiator, payload[2]>>2, 0x8d);  // ea=1,fc=0,rtc(DSR/DTR)=1,rtr(RTS/CTs)=1,ic(RI)=0,dv(DCD)=1
+                                    r->State = SocketState_L2CAP_Config_wait_rsp;
+                                    break;
+                                case SocketState_L2CAP_Config_wait_reqrsp:
+                                    r->State = SocketState_L2CAP_Config_wait_rsp;
+                                    break;
+                                case SocketState_L2CAP_Config_wait_req:
+                                    r->SetState(SocketState_Open);
+                                    break;
+                                case SocketState_Open:
+                                    //inform port adaptation layer
+                                    printf("Received MSC IND in state Open for dlci 0x%02x\n", payload[2]>>2);
+                                    break;
+                                default:
+                                    printf("Received MSC IND in state %d for dlci 0x%02x\n", r->State, payload[2]>>2);
+                            }
+                        }
+                        break;
+                    case BT_RFCOMM_MSC_RSP:
+                        packet_processed++;
+                        {
+                            RFCOMMSocket *r = self->find_socket(payload[2]>>2);
+                            if (r==0) break;
+                            if (r->State == SocketState_L2CAP_Config_wait_reqrsp)
+                                r->State =  SocketState_L2CAP_Config_wait_req;
+                            else if (r->State == SocketState_L2CAP_Config_wait_rsp)
+                                r->SetState(SocketState_Open);
+                            else
+                                printf("Received MSC confirmation in state %d for dlci 0x%02x\n", r->State, payload[2]>>2);
+                        }
+                        break;
+                    case BT_RFCOMM_RPN_CMD:
+                        packet_processed++;
+                        //accept and ignore all settings
+                        unsigned char reply[10];
+                        memcpy(reply, payload, length); //keep length, dlci and value(s)
+                        reply[0]  = BT_RFCOMM_RPN_RSP;  // change command into response
+                        printf("Responding to RPN indication (%d bytes)\n", length);
+                        rfcomm_send_packet(socket, addr^2, BT_RFCOMM_UIH, 0, reply, length);
+                        break;
+                    case BT_RFCOMM_RPN_RSP:
+                        packet_processed++;
+                        //ignore a response
+                        printf("Received RPN confirmation\n");
+                        break;
+                    default:
+                        printf("Unsupported multiplexer frame, type=%02XH\n", data[3]);
+                }
+                break;
+            case BT_RFCOMM_DISC:
+                printf("Remote site actively disconnected from DLCI0\n");
+                rfcomm_send_packet(socket, addr|2, BT_RFCOMM_UA, 0, 0, 0);//confirm disconnection
+                //intentional fall through
+            case BT_RFCOMM_DM:
+                packet_processed++;
+                printf("Remote side refused connection on DLCI0\n");
+                self->_l2cap = Socket_Close(socket);
+                break;
+            case BT_RFCOMM_SABM:
+                packet_processed++;
+                printf("Remote site is seeking connection on DLCI0\n"); //respond with UA
+                rfcomm_send_packet(socket, addr|2, BT_RFCOMM_UA, 0, 0, 0);//confirm connection
+                break;
+            default:
+                printf("Unexpected RFCOMM cmd %02XH for address %02XH, length=%d\n", control, addr, length);
+        }
+    } else { //data is for one of the serial sockets
+        RFCOMMSocket *s = 0;
+        if (control == BT_RFCOMM_SABM) { //req. for conn on this dlci
+            //cannot call self->rfcomm::find_socket because it has no socket yet
+            int skt = rfcomm_manager.find_socket(dlci>>1); //find the server socket
+            s = (RFCOMMSocket*)GetSocketInternal(skt);//the listening socket
+            if (s) {//move the listening socket to the appropriate rfcomm
+                int slot = self->find_slot(dlci>>1);
+                if (slot < 0) {
+                    printf("RFCOMM Channel %d is not free on rfcomm with l2cap socket %d\n", dlci>>1, self->_l2cap);
+                    return;
+                }
+                s->serdevice = self; //bind the socket to this refcomm entity
+                self->sckts[slot] = skt;
+                rfcomm_manager.remove_socket(skt);
+            } else {
+                printf("Couln't find a listening socket for dlci %d\n", dlci);
+                return;
+            }
+        } else
+            s = self->find_socket(dlci);
+        if (s==0){
+          printf("DLCI %d not found\n", dlci);
+          return;
+        }
+        switch (control) {
+            case BT_RFCOMM_SABM:
+                packet_processed++;
+                rfcomm_send_packet(socket, addr|2, BT_RFCOMM_UA, 0, 0, 0);//confirm connection
+                s->State = SocketState_L2CAP_Config_wait; //wait for msc cmd
+                break;
+            case BT_RFCOMM_UA://     received 2. message BT_RF_COMM_UA
+                packet_processed++;
+                if (s->State == SocketState_Closing) { //Confirmation of disconnect
+                    printf("Remote side confirmed disconnect for socket %d\n", s->ID);
+                    s->SetState(SocketState_Closed);
+                    break;
+                }
+                printf("Received RFCOMM unnumbered acknowledgement for dlci %u - channel opened\n", dlci);
+                if (s->State == SocketState_L2CAP_Config_wait) {
+                    printf("Sending MSC  CMD\n");
+                    _bt_rfcomm_send_uih_msc_cmd(socket, initiator, dlci, 0x8d);  // ea=1,fc=0,rtc(DSR/DTR)=1,rtr(RTS/CTs)=1,ic(RI)=0,dv(DCD)=1
+                    s->State = SocketState_L2CAP_Config_wait_reqrsp;
+                }
+                break;
+            case BT_RFCOMM_UIH_PF: //user data with credits
+                //printf("Got %u credits\n", credits);
+                s->my_credits += credits;
+                //intentional fall-through
+            case BT_RFCOMM_UIH: //user data
+                packet_processed++;
+                if (DEBUG) {
+                    printf("RX: address %02x, control %02x: ", addr, control);
+                    printHex( payload, length);
+                }
+                if (length) {
+                    s->peer_credits--;
+                    s->Recv(payload, length);
+                } 
+                if (length == 0 || s->peer_credits == 0) {//send credits when peer runs out
+                    //char ini = !(dlci & 1);
+                    unsigned char address = (1 << 0) | (initiator << 1) | (dlci << 2);
+                    //printf("send %d credits to dlci %d\n", NR_CREDITS, addr>>2);
+                    rfcomm_send_packet(socket, address, BT_RFCOMM_UIH_PF, NR_CREDITS, NULL, 0);
+                    s->peer_credits += NR_CREDITS;
+                }
+                break;
+            case BT_RFCOMM_DISC:
+                packet_processed++;
+                printf("Received DISC IND for dlci %d\n", dlci);
+                rfcomm_send_packet(socket, addr, BT_RFCOMM_UA, 0, 0, 0);//confirm disconnection
+                s->SetState(SocketState_Closed);                
+                break;
+            case BT_RFCOMM_DM:
+            case BT_RFCOMM_DM_PF:
+                packet_processed++;
+                printf("Received DM IND (%02X) for dlci %d\n", control, dlci);
+                s->SetState(SocketState_Closed);
+                break;
+            default:
+                printf("Unexpected RFCOMM cmd %02XH for address %02XH, length=%d\n", control, addr, length);
+        }
+    }
+
+    if (!packet_processed) {
+        // just dump data for now
+        printf("??: address %02x, control %02x: ", data[0], data[1]);
+        printHex( data, len );
+    }
+    printf("\x1B[%dm", 0);//reset terminal colour
+}
+
+/**
+ * @param credits - only used for RFCOMM flow control in UIH wiht P/F = 1
+ */
+/* Questionable optimisation. When OFFSET==8 a buffer is (dynamically) allocated that provides space for the lower
+   layer headers, this reduces copying to, and allocation of, a lower layer buffer. However, all other layers using
+   HCI/L2CAP must do the same.
+*/
+#define OFFSET  8
+
+int rfcomm_send_packet(uint16_t source_cid, uint8_t address, uint8_t control, uint8_t credits, const uint8_t *data, uint16_t len) {
+
+    uint16_t pos = OFFSET;
+    uint8_t crc_fields = 3;
+
+#if OFFSET == 8
+    uint8_t* rfcomm_out_buffer = new uint8_t[OFFSET+len+6];
+#else
+    static uint8_t rfcomm_out_buffer[MAXFRAMESIZE+6];//seems a bit big as default max framesize is 127
+#endif
+    rfcomm_out_buffer[pos++] = address;
+    rfcomm_out_buffer[pos++] = control;
+
+    // length field can be 1 or 2 octets
+    if (len < 128) {
+        rfcomm_out_buffer[pos++] = (len << 1)| 1;     // bits 0-6
+    } else {
+        rfcomm_out_buffer[pos++] = (len & 0x7f) << 1; // bits 0-6
+        rfcomm_out_buffer[pos++] = len >> 7;          // bits 7-14
+        crc_fields++;
+    }
+
+    // add credits for UIH frames when PF bit is set
+    if (control == BT_RFCOMM_UIH_PF) {
+        rfcomm_out_buffer[pos++] = credits;
+    }
+
+    // copy actual data
+    memcpy(&rfcomm_out_buffer[pos], data, len);
+    pos += len;
+
+    // UIH frames only calc FCS over address + control (5.1.1)
+    if ((control & 0xef) == BT_RFCOMM_UIH) {
+        crc_fields = 2;
+    }
+    rfcomm_out_buffer[pos++] =  crc8_calc(rfcomm_out_buffer+OFFSET, crc_fields); // calc fcs
+    int retval = Socket_Send( source_cid, rfcomm_out_buffer, pos);
+#if OFFSET == 8
+    delete[] rfcomm_out_buffer;
+#endif
+    if (retval <= 0)
+        return retval;
+    return len;//return the size of the payload
+}
+
+void _bt_rfcomm_send_sabm(uint16_t source_cid, uint8_t initiator, uint8_t dlci) {
+    uint8_t address = (1 << 0) | (initiator << 1) |  (dlci << 2);
+    rfcomm_send_packet(source_cid, address, BT_RFCOMM_SABM, 0, NULL, 0);
+}
+
+void _bt_rfcomm_send_uih_pn_command(uint16_t source_cid, uint8_t initiator, uint8_t dlci, uint16_t max_frame_size) {
+    uint8_t payload[10];
+    uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
+    uint8_t pos = 0;
+    payload[pos++] = BT_RFCOMM_PN_CMD;
+    payload[pos++] = 8 << 1 | 1;  // len
+    payload[pos++] = dlci;
+    payload[pos++] = 0xf0; // pre defined for Bluetooth, see 5.5.3 of TS 07.10 Adaption for RFCOMM
+    payload[pos++] = 0; // priority
+    payload[pos++] = 0; // max 60 seconds ack
+    payload[pos++] = max_frame_size & 0xff; // max framesize low
+    payload[pos++] = max_frame_size >> 8;   // max framesize high
+    payload[pos++] = 0x00; // number of retransmissions
+    payload[pos++] = INITIAL_CREDITS; // unused error recovery window
+    rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
+}
+
+void _bt_rfcomm_send_uih_data(uint16_t source_cid, uint8_t initiator, uint8_t channel, uint8_t *data, uint16_t len) {
+    uint8_t address = (1 << 0) | (initiator << 1) |  (!initiator << 2) | (channel << 3);
+    rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, data, len);
+}
+
+void _bt_rfcomm_send_uih_msc_cmd(uint16_t source_cid, uint8_t initiator, uint8_t dlci, uint8_t signals) {
+    uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
+    uint8_t payload[5];
+    uint8_t pos = 0;
+    payload[pos++] = BT_RFCOMM_MSC_CMD;
+    payload[pos++] = 2 << 1 | 1;  // len, should be adapted when adding break byte
+    payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2); //C/R is always 1
+    payload[pos++] = signals;
+    // payload[pos++]   = brk;
+    rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
+}
+
+void _bt_rfcomm_send_uih_rpn_cmd(uint16_t source_cid, uint8_t initiator, uint8_t dlci, port_settings *val) {
+    uint8_t address = (1 << 0) | (initiator << 1); // EA and C/R bit set - always server channel 0
+    uint8_t payload[sizeof(port_settings)+3];
+    uint8_t pos = 0;
+    payload[pos++] = BT_RFCOMM_RPN_CMD;//type
+    if (val) {
+        payload[pos++] = ((1+sizeof(port_settings)) << 1) | 1;  // len
+        payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2);
+        memcpy(payload+pos, (char*)val, sizeof(port_settings));
+        pos += sizeof(port_settings);
+    } else {
+        payload[pos++] = (1 << 1) | 1;  // len
+        payload[pos++] = (1 << 0) | (1 << 1) | (dlci << 2);
+    }
+    rfcomm_send_packet(source_cid, address, BT_RFCOMM_UIH, 0, (uint8_t *) payload, pos);
+}
+
+int set_remote_port_parameters(int socket, port_settings *p) {
+    RFCOMMSocket* si = (RFCOMMSocket*)GetSocketInternal(socket);//gets the RFCOMM socket
+    if (!si || si->ID != socket)
+        return ERR_SOCKET_NOT_FOUND;
+    return si->serdevice->set_remote_port_parameters(si->dlci, p);
+}
+
+
+/*
+ * CRC (reversed crc) lookup table as calculated by the table generator in ETSI TS 101 369 V6.3.0.
+ */
+static const uint8_t crc8table[256] = {    /* reversed, 8-bit, poly=0x07 */
+    0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B,
+    0x1C, 0x8D, 0xFF, 0x6E, 0x1B, 0x8A, 0xF8, 0x69, 0x12, 0x83, 0xF1, 0x60, 0x15, 0x84, 0xF6, 0x67,
+    0x38, 0xA9, 0xDB, 0x4A, 0x3F, 0xAE, 0xDC, 0x4D, 0x36, 0xA7, 0xD5, 0x44, 0x31, 0xA0, 0xD2, 0x43,
+    0x24, 0xB5, 0xC7, 0x56, 0x23, 0xB2, 0xC0, 0x51, 0x2A, 0xBB, 0xC9, 0x58, 0x2D, 0xBC, 0xCE, 0x5F,
+    0x70, 0xE1, 0x93, 0x02, 0x77, 0xE6, 0x94, 0x05, 0x7E, 0xEF, 0x9D, 0x0C, 0x79, 0xE8, 0x9A, 0x0B,
+    0x6C, 0xFD, 0x8F, 0x1E, 0x6B, 0xFA, 0x88, 0x19, 0x62, 0xF3, 0x81, 0x10, 0x65, 0xF4, 0x86, 0x17,
+    0x48, 0xD9, 0xAB, 0x3A, 0x4F, 0xDE, 0xAC, 0x3D, 0x46, 0xD7, 0xA5, 0x34, 0x41, 0xD0, 0xA2, 0x33,
+    0x54, 0xC5, 0xB7, 0x26, 0x53, 0xC2, 0xB0, 0x21, 0x5A, 0xCB, 0xB9, 0x28, 0x5D, 0xCC, 0xBE, 0x2F,
+    0xE0, 0x71, 0x03, 0x92, 0xE7, 0x76, 0x04, 0x95, 0xEE, 0x7F, 0x0D, 0x9C, 0xE9, 0x78, 0x0A, 0x9B,
+    0xFC, 0x6D, 0x1F, 0x8E, 0xFB, 0x6A, 0x18, 0x89, 0xF2, 0x63, 0x11, 0x80, 0xF5, 0x64, 0x16, 0x87,
+    0xD8, 0x49, 0x3B, 0xAA, 0xDF, 0x4E, 0x3C, 0xAD, 0xD6, 0x47, 0x35, 0xA4, 0xD1, 0x40, 0x32, 0xA3,
+    0xC4, 0x55, 0x27, 0xB6, 0xC3, 0x52, 0x20, 0xB1, 0xCA, 0x5B, 0x29, 0xB8, 0xCD, 0x5C, 0x2E, 0xBF,
+    0x90, 0x01, 0x73, 0xE2, 0x97, 0x06, 0x74, 0xE5, 0x9E, 0x0F, 0x7D, 0xEC, 0x99, 0x08, 0x7A, 0xEB,
+    0x8C, 0x1D, 0x6F, 0xFE, 0x8B, 0x1A, 0x68, 0xF9, 0x82, 0x13, 0x61, 0xF0, 0x85, 0x14, 0x66, 0xF7,
+    0xA8, 0x39, 0x4B, 0xDA, 0xAF, 0x3E, 0x4C, 0xDD, 0xA6, 0x37, 0x45, 0xD4, 0xA1, 0x30, 0x42, 0xD3,
+    0xB4, 0x25, 0x57, 0xC6, 0xB3, 0x22, 0x50, 0xC1, 0xBA, 0x2B, 0x59, 0xC8, 0xBD, 0x2C, 0x5E, 0xCF
+};
+
+#define CRC8_INIT  0xFF          // Initial FCS value 
+#define CRC8_OK    0xCF          // Good final FCS value 
+/*-----------------------------------------------------------------------------------*/
+uint8_t crc8(uint8_t *data, uint16_t len) {
+    uint16_t count;
+    uint8_t crc = CRC8_INIT;
+    for (count = 0; count < len; count++)
+        crc = crc8table[crc ^ data[count]];
+    return crc;
+}
+
+/*-----------------------------------------------------------------------------------*/
+uint8_t crc8_check(uint8_t *data, uint16_t len, uint8_t check_sum) {
+    uint8_t crc;
+
+    crc = crc8(data, len);
+
+    crc = crc8table[crc ^ check_sum];
+    if (crc == CRC8_OK)
+        return 0;               /* Valid */
+    else
+        return 1;               /* Failed */
+
+}
+
+/*-----------------------------------------------------------------------------------*/
+uint8_t crc8_calc(uint8_t *data, uint16_t len) {
+    /* Ones complement */
+    return 0xFF - crc8(data, len);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/rfcomm/RFCOMM.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,309 @@
+#ifndef RFCOMM_H
+#define RFCOMM_H
+#include "USBHost.h"
+#include "hci.h"
+#include "Utils.h"
+
+#define MAX_RFCOMM_SCKTS    4
+/*
+template <class T>
+T min(T a, T b) {
+  return a<b ? a : b;
+}
+*/
+
+#define MASK_BITRATE    0X0001
+#define MASK_DATABITS   0X0002
+#define MASK_STOPBITS   0X0004
+#define MASK_PARITYBITS 0X0008
+#define MASK_PARITYTYPE 0X0010
+#define MASK_XONCHAR    0X0020
+#define MASK_XOFFCHAR   0X0040
+#define MASK_XONXOFFIN  0X0100
+#define MASK_XONXOFFOUT 0X0200
+#define MASK_RTRIN      0X0400
+#define MASK_RTROUT     0X0800
+#define MASK_RTCIN      0X1000
+#define MASK_RTCOUT     0X2000
+
+struct port_settings {
+    unsigned char baud;
+unsigned char bits:
+    2;
+unsigned char stop:
+    1;
+unsigned char par:
+    1;
+unsigned char par_t:
+    2;
+unsigned char :
+    2;
+unsigned char flow:
+    6;
+unsigned char :
+    2;
+    unsigned char xon;
+    unsigned char xoff;
+    unsigned short mask;
+};
+
+class rfcomm;
+class RFCOMMManager;
+#define MAX_RFCOMM_DEVICES 8    //physical devices
+
+class RFCOMMSocket: public SocketInternal {//this object must not be larger than SocketInternalPad (socketinternal + 8 bytes)
+public:
+    rfcomm* serdevice;
+    u8 dlci; //channel + D bit, D bit is inverted initiator bit
+    u8 my_credits, peer_credits;
+};
+
+class rfcomm: public SocketHandler {
+    int _l2cap; //socket to the l2cap layer
+    int _devClass;
+    BD_ADDR _addr;
+    u8 initiator;
+    u8  _pad[0];    // Struct align
+    char sckts[MAX_RFCOMM_SCKTS];
+    static unsigned maxframesize;
+    int find_slot(unsigned ch);
+    RFCOMMSocket* find_socket(unsigned dlci);
+    void initChannels(int socket);
+    unsigned release_channel(unsigned dlci);
+    static void OnRfCommControl(int socket, SocketState state, const u8* data, int len, void* userData);//I guess this is called when data comes out of the socket
+    int Disconnect(RFCOMMSocket*);
+public:
+    rfcomm() : _l2cap(0), _devClass(0) {
+        for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) sckts[i] = 0;
+    }
+
+    bool InUse() {
+        return _l2cap != 0;
+    }
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
+    virtual int Send(SocketInternal* sock, const u8* data, int len);//wrap data in RFCOMM frame and dispatch
+    virtual int Close(SocketInternal* sock);
+    virtual char* Name() {
+        return "rfcomm SocketHandler";
+    }
+    void Recv(const u8* data, int len) {
+        printf("rfcomm::Recv was called\n");
+    }
+#if 0
+    int Listen(unsigned char ch=0) {//passive open, similar semantics to 'Open' but connection is only made at request of the peer
+        RFCOMMSocket *s = 0;//this entity may or may not be bound to a remote entity
+        if (ch>0) {//specific channel
+            s = find_socket(ch<<1);
+            if (s) { //socket for this channel already in use
+                printf("rfcomm::Listen: channel %d already in use\n", ch);
+                return 0;
+            } //else s==0, no socket for channel ch
+        }//else listen to any channel
+        int sn = find_slot(ch);
+        if (sn<0) {
+            printf("No socket could be found for channel %d\n", ch);
+            return 0;
+        } //else use slot 'sn' for the new rfcomm socket
+        int sock = Socket_Create(SOCKET_RFCOM, OnRfCommControl, this);//allocate an rfcomm socket
+        sckts[sn] = sock; //claim the socket
+        RFCOMMSocket *rs = (RFCOMMSocket*)GetSocketInternal(sock);
+        rs->serdevice = this;
+        rs->dlci = (ch<<1)|1;//server socket
+        //initiator = 0; what to do if already connected actively on different channel???
+        /*l2cap is already present or is created when accepting the connection
+                if (_l2cap == 0) { //no rfcomm -> l2cap connection yet
+                    printf("Need to open L2CAP channel first before opening RFCOMM channel %d\n", rs->dlci);
+                    ((L2CAPAddr*)addr)->psm = L2CAP_PSM_RFCOMM;//open the l2cap channel and the rfcomm_ch channel
+                    initiator = 0;
+                    _l2cap = Socket_Create(SOCKET_L2CAP, addr, OnRfCommControl, this);//this is the socket between the RFCOMM and the L2CAP layer
+                    if (_l2cap)
+                        printf("Successfully opened L2CAP channel on socket %d\n", _l2cap);
+                    else {
+                        printf("Opening L2CAP channel failed\n");
+                        return 0;
+                    }
+                }
+        */
+        return sock;
+    }
+#endif
+    //int Open(BD_ADDR* bdAddr, inquiry_info* info);
+    int set_remote_port_parameters(unsigned char dlci, port_settings *p);
+    friend RFCOMMManager;
+};
+
+class RFCOMMManager: public SocketHandler {
+    rfcomm _devs[MAX_RFCOMM_DEVICES];
+    int serverSock;
+    char sckts[MAX_RFCOMM_SCKTS];//listening sockets
+public:
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) {
+        L2CAPAddr* ad = (L2CAPAddr*)addr;
+        BD_ADDR* a = &ad->bdaddr;
+        rfcomm *r = FindRfCommDevice(a);
+        if (r==0)
+            r = NewRfCommDevice();
+        if (r==0)
+            return 0;
+        return r->Open(sock, addr);
+    }
+
+    int FindSocket(BTDevice* dev) {//finds the l2cap socket for a certain rfcomm-btdevice connection
+        for (int i = 0; i < MAX_RFCOMM_DEVICES; i++) {
+            rfcomm *r = _devs+i;
+            int l2cap = r->_l2cap;
+            if (l2cap) {
+                L2CAPSocket *p = (L2CAPSocket*)GetSocketInternal(l2cap);
+                if (p->btdevice == dev)
+                    return l2cap;
+            }
+        }
+        return 0;
+    }
+
+    rfcomm* FindDev(BTDevice* dev) {//finds the rfcomm entity for a certain rfcomm-btdevice connection
+        for (int i = 0; i < MAX_RFCOMM_DEVICES; i++) {
+            rfcomm *r = _devs+i;
+            int l2cap = r->_l2cap;
+            if (l2cap) {
+                L2CAPSocket *p = (L2CAPSocket*)GetSocketInternal(l2cap);
+                if (p->btdevice == dev)
+                    return r;
+            }
+        }
+        return 0;
+    }
+
+    int BindSocket(int s) {
+        L2CAPSocket *ls = (L2CAPSocket*)GetSocketInternal(s);
+        printf("Binding l2cap socket %d to a new rfcomm server entity\n", s);
+        rfcomm *r = NewRfCommDevice();
+        r->_l2cap = s;
+        r->initiator = 0;//we are server
+        ls->si.userData = r;//was BTDevice, make rfcomm
+        return 0;
+    }
+
+    int new_slot(unsigned ch) {
+        for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
+            if (sckts[i] != 0) { //socket is in use
+                RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
+                if (s==0) {
+                    printf("find_slot: socket  %d not found\n", sckts[i]);
+                    continue;
+                }
+                if ((s->dlci >> 1) == ch) {
+                    printf("Channel %d is already in use on socket %d\n", ch, sckts[i]);
+                    return -1;
+                }
+            } else //slot is free
+                return i;
+        }
+        return -2; //no free slots
+    }
+
+    int find_socket(unsigned ch) {
+        for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
+            if (sckts[i] != 0) { //socket is in use
+                RFCOMMSocket *s = (RFCOMMSocket*)GetSocketInternal(sckts[i]);
+                if (s==0) {
+                    printf("find_slot: socket  %d not found\n", sckts[i]);
+                    continue;
+                }
+                if ((s->dlci >> 1) == ch) {
+                    printf("Found Channel %d on socket %d\n", ch, sckts[i]);
+                    return sckts[i];
+                }
+                else
+                  printf("slot %d has socket %d has dlci %d\n", i, sckts[i], s->dlci);
+            }
+            else
+              printf("Slot %d is free\n", i);
+        }
+        printf("channel %d not found\n", ch);
+        return 0; //channel not found
+    }
+
+    int remove_socket(int sock) {
+        for (int i = 0; i < MAX_RFCOMM_SCKTS; i++) {
+          if (sckts[i] == sock) {
+            sckts[i] = 0;
+            return 0;
+          }
+        }
+        return -1;
+    }
+
+    virtual int Listen(SocketInternal* sock, int ch) {//called by Socket_Listen(SOCKET_RFCOM, channel, callback, userData)
+        int slot = new_slot(ch);
+        switch (slot) {
+            case -1:
+                printf("There is already someone listening on ch %d\n", ch);
+                return ERR_SOCKET_CANT_LISTEN;//channel is occupied
+            case -2:
+                printf("All listener sockets are in use\n");
+                return ERR_SOCKET_NONE_LEFT;
+        }
+        RFCOMMSocket *rs = (RFCOMMSocket*)sock;
+        const char dir = 0;
+        rs->dlci = (ch<<1)|dir;
+        rs->State = SocketState_Listen;
+        rs->serdevice = 0;//don't know yet
+        sckts[slot] = rs->ID;
+        printf("RFCOMM listener socket %d for ch %d (dlci 0x%02X) is assigned to slot %d\n", rs->ID, ch, rs->dlci, slot);
+        return rs->ID;
+    }
+/*
+    virtual int Accept(SocketInternal *sock, int scid, int rxid) { //called indirectly from BTDevice::Control
+        //sock is registered as an RFCOMM sock but we use it as an L2CAP sock
+        //sock->type=RFCOM, meaning open/close/send/accept go to RFCOMMManager first
+        //sock->userData = BTDevice, necessary to make the call back to BTDevice::Accept
+        //Internal = L2CAPSocket, for scid, dcid
+        BTDevice *l2cap = (BTDevice*)sock->userData;
+        //sock->si.dcid = scid
+        //sock->si.scid = something based on sock->ID
+        serverSock = sock->ID;
+        printf("Invoking accept on %p (%s) for sock %d and scid=%d\n", l2cap, l2cap->Name(), sock->ID, scid);
+        return l2cap->Accept(sock, scid, rxid); //connect 'serverSock' to the remote RFCOMM client
+    }
+*/
+    virtual int Send(SocketInternal* sock, const u8* data, int len) {
+        RFCOMMSocket *s = (RFCOMMSocket*)sock;
+        return s->serdevice->Send(sock, data, len);
+    }
+
+    virtual int Close(SocketInternal* sock) {
+        RFCOMMSocket *s = (RFCOMMSocket*)sock;
+        return s->serdevice->Close(sock);
+    }
+
+    virtual char* Name() {
+        return "RFCOMMManager SocketHandler";
+    }
+
+    rfcomm* NewRfCommDevice() {//allocate a new RFCOMM device from the pool
+        for (int i = 0; i < MAX_RFCOMM_DEVICES; i++)
+            if (!_devs[i].InUse())
+                return _devs+i;
+        return 0;
+    }
+
+    rfcomm* FindRfCommDevice(BD_ADDR* ad) {//get a specific RFCOMM device from the pool
+        for (int i = 0; i < MAX_RFCOMM_DEVICES; i++)
+            if (_devs[i].InUse() && memcmp(ad, &_devs[i]._addr, 6)==0)
+                return _devs+i;
+        return 0;
+    }
+
+    static void SerServer(int socket, SocketState state, const u8* data, int len, void* userData) {
+        printfBytes("SerServer: ", data, len);
+        //userData is the rfcomm
+        rfcomm::OnRfCommControl(socket, state, data, len, userData);
+    }
+    //friend rfcomm;
+};
+
+int set_remote_port_parameters(int socket, port_settings *p);
+extern RFCOMMManager rfcomm_manager;
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/sdp/sdp.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,787 @@
+#include "mbed.h"
+#include "Utils.h"
+#include "hci.h"
+#include "sdp_data.h"
+#include "sdp.h"
+
+SDPManager SDP; //instance
+const unsigned char base_uuid[16] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0, 0x07, 0x70, 0, 0x10, 0, 0};
+map<unsigned, serv_rec*> SDPManager::server;
+int SDPManager::serverSock = 0;
+
+void attribHandler(serv_rec *r) {
+    printf("Service 0x%08X\n", (*r)[0x0000]->asUnsigned());
+    map<unsigned short, sdp_data*>::iterator it = r->begin();
+    for (;it != r->end();it++) {
+        printf("   0x%04X: %s\n", (*it).first, (*it).second->asString());
+    }
+}
+
+#define BROWSEROOT  0x1002
+#define SERIALSERV  0x1101
+
+SDPHandler::SDPHandler(): txid(1), tree(0) {
+    ErrorResponse=errorhandler;
+    ServiceSearchResponse=0;
+    ServiceAttributeResponse=attribHandler;
+    ServiceSearchAttributeResponse=0;
+    buf = l2cap_buf+OFFSET;
+    contBuf = 0;
+    byteCount = 0;
+    contState[0] = 0;
+    _state = 0;
+}
+
+void SDPHandler::Clear() {
+    for (index = services.begin(); index != services.end(); index++) {//for all services
+        for (serv_rec::iterator it = index->second->begin(); it != index->second->end(); it++)//for all attributes
+            delete it->second; //delete the attribute value tree
+        delete (*index).second; //delete the attribute list
+    }
+    services.clear();//and empty the services list
+}
+
+//Called as: Socket_Open(SOCKET_SDP, addr, callback, userdata(this)) from SDPManager
+//never called
+int SDPHandler::Open(SocketInternal* sock, SocketAddrHdr* addr) {
+    printf("Successfully opened SDP socket %d\n", sock->ID);
+    sock->SetState(SocketState_Open);
+    sdp_socket = sock->ID;
+    return sdp_socket;
+}
+
+int SDPHandler::Send(SocketInternal* sock, const u8* data, int len) {
+    printf("SDPHandler::Send should not be called directly\n");
+//        return Socket_Send(_l2cap, data, len);
+    BTDevice *l2cap = (BTDevice*)sock->userData;
+    return l2cap->Send(sock, data, len);
+}
+
+int SDPHandler::Close(SocketInternal* sock) {
+    printf("SDPHandler::Close(%d)\n", sock->ID);
+    Clear();
+//    printf("SDP socket %d and L2CAP socket %d closed, freemem=%d\n", sock->ID, _l2cap, AvailableMemory(1));
+    int retval = 0;//Socket_Close(_l2cap);//could also keep it open for the next connection
+    return retval;
+}
+
+//this function is called when the L2CAP layer receives SDP packets (see SDPHandler::Open), userdata is the sdpmanager instance
+void SDPHandler::OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
+    printf("\x1B[%dm", 35);
+//        printf("OnSdpRsp(socket=%d, state=%d, len=%d)\n", socket, state, len);
+    printf("SDPHandler::OnSdpRsp(socket=%d, state=%d, len=%d, freemem=%d\n", socket, state, len, AvailableMemory(1));
+    SDPHandler *self = (SDPHandler*)userData;
+    if (state == SocketState_Open) {
+        self->sdp_socket = socket;
+        self->OnSdpRsp(data, len);
+    } else if (state == SocketState_Closed) {
+        SDP.Destroy(socket);
+    }
+    printf("\x1B[%dm", 0);
+}
+
+//this function is called when the L2CAP layer receives SDP packets (see SDPHandler::Open), userdata is the sdpmanager instance
+//void SDPHandler::OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
+void SDPHandler::OnSdpRsp(const u8* data, int len) {
+    static sdp_data list(sdp_data::SEQUENCE);
+    static sdp_data all(0x0000ffffU,4);
+    static sdp_data serviceID(0U, 2);
+    static sdp_data name(0x100U, 2);
+    static sdp_data root(sdp_data::UUID, BROWSEROOT);
+    static sdp_data req(sdp_data::SEQUENCE);
+    static bool once = true;
+//    printf("_state=%d first=%d   ", _state, once);
+    if (once) {
+        list.add_element(&all);
+        //list.add_element(&serviceID);
+        //list.add_element(&name);
+        req.add_element(&root);
+        once = false;
+    }
+    if (data) {
+        parseRsp(data, len);
+    }
+    switch (_state) {
+        case 0: //closed
+            if (len==0) { //socket just opened
+                //'Open' cleared the services list
+                ServiceSearchRequest(&req, 10);
+                _state = 1; //wait for service handles
+            }
+            break;
+        case 1: //service handles arriving
+            if (contState[0]) {//continuation, repeat request
+                ServiceSearchRequest(&req, 5);
+            } else {
+                if (data[0]==3) {
+                    index = services.begin();
+                    if (index != services.end()) {
+                        unsigned handle = (*index).first;
+                        //printf("req.: handle %#X\n", handle);
+                        ServiceAttributeRequest(handle, 100, &list);//0x1001D
+                    } else
+                        printf(" - empty list - \n");//should not happen
+                    _state = 2; //wait for attribute response
+                } else
+                    printf("Expected a ServiceSearchResponse 0x03, got %#x\n", data[0]);
+            }
+            break;
+        case 2:
+            if (contState[0])//repeat request
+                ServiceAttributeRequest((*index).first, 100, &list);
+            else {
+                if (data[0]==5) {
+                    index++; //move to next service
+                    if (index != services.end()) {
+                        //printf("req.: handle %#X\n", (*index).first);
+                        ServiceAttributeRequest((*index).first, 100, &list);
+                    } else {
+                        printf(" - end of list - \n");
+                        Socket_Close(sdp_socket); //Note: socket=L2CAP, sdp_socket=SDP !!!
+                        _state = 0;
+                    }
+                } else
+                    printf("Expected a ServiceAttributeResponse 0x05, got %#x\n", data[0]);
+            }
+            break;
+    }
+}
+
+//this function is called when the SDP sockets receives data (see HCICallback in TestShell),
+//currently does not happen because not forwarded from OnSdpRsp, can be used to handle multiple connections
+void SDPHandler::OnSockCallback(int socket, SocketState state, const u8* data, int len, void* userData) {
+    printf("SDPHandler::OnSockCallback(socket=%d, state=%d, len=%d)\n", socket, state, len);
+    printfBytes("Got SDP Response from socket: ", data, len);
+}
+
+//void SDPHandler::errorhandler(unsigned err) {//default error handler
+void errorhandler(unsigned err) {//default error handler
+    switch (err) {
+        case 1:
+            printf("Unsupported version of SDP\n");
+            break;
+        case 2:
+            printf("Invalid SDP ServiceRecordHandle\n");
+            break;
+        case 3:
+            printf("SDP syntax error\n");
+            break;
+        case 4:
+            printf("PDU size was invalid\n");
+            break;
+        case 5:
+            printf("Continuation state was invalid\n");
+            break;
+        case 6:
+            printf("SDP server has insufficient resources\n");
+            break;
+        default:
+            printf("Unknown SDP error code\n");
+            break;
+    }
+}
+
+int SDPHandler::ServiceSearchRequest(sdp_data *sp, unsigned count, unsigned cs) {
+    int parlen = sp->Size() + contState[0] + 3;
+    buf[0] = 2; //pdu
+    buf[1] = txid>>8;
+    buf[2] = txid++;
+    buf[4] = parlen;
+    buf[3] = parlen>>8;
+    int p = sp->build(buf+5, 100-10);
+    buf[p+6] = count;
+    buf[p+5] = count>>8;
+    buf[p+7] = contState[0];
+    for (int j = 1; j <= contState[0]; j++)
+        buf[p+j+7] = contState[j];
+    //printfBytes("SDP Send: ", buf, parlen+5);
+    return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
+}
+
+int SDPHandler::ServiceAttributeRequest(unsigned handle, unsigned count, sdp_data* al, unsigned cs) {
+    int parlen = al->Size() + contState[0] + 7;
+    buf[0] = 4; //pdu
+    buf[1] = txid>>8;
+    buf[2] = txid++;
+    buf[4] = parlen;
+    buf[3] = parlen>>8;
+    for (int i = 0; i < 4; i++)
+        buf[i+5] = ((char*)&handle)[3-i];
+    buf[9] = count>>8;
+    buf[10] = count;
+    int p = al->build(buf+11, 100-26);
+    buf[p+11] = contState[0];
+    for (int j = 1; j <= contState[0]; j++)
+        buf[p+j+11] = contState[j];
+    //printfBytes("SDP Send: ", buf, parlen+5);
+    return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
+}
+
+int SDPHandler::ServiceSearchAttributeRequest(sdp_data *sp, unsigned count, sdp_data* al, unsigned cs) {
+    int parlen = sp->Size() + al->Size() + contState[0] + 3; // count (2 bytes) + at least 1 cont
+    buf[0] = 6; //pdu
+    buf[1] = txid>>8;
+    buf[2] = txid++;
+    buf[4] = parlen;
+    buf[3] = parlen>>8;
+    int p = sp->build(buf+5, 30);
+    buf[p+6] = count;
+    buf[p+5] = count>>8;
+    p += al->build(buf+11, 100-38);
+    buf[p+7] = contState[0];
+    for (int j = 1; j <= contState[0]; j++)
+        buf[p+j+7] = contState[j];
+    //printfBytes("SDP Send: ", buf, parlen+5);
+    return Socket_Send(sdp_socket, l2cap_buf, parlen + 5 + OFFSET);
+}
+
+int SDPManager::ServiceSearchAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs) {
+    unsigned size = al->Size();
+    unsigned cont = 0;//outgoing continuation
+    unsigned char *_buf = new unsigned char[OFFSET+5+2+size+3];
+    unsigned char *buf = _buf+OFFSET;
+    unsigned byteCount = size - cs; //remainder of data to send
+    unsigned parlen = 2 + byteCount + 1 ;// attributelistbytecount+payload+no_continuation
+    if (byteCount > count) {//still too large, need continuation
+        byteCount = count; //limit at maximum
+        cont = cs + count; //start for next iteration
+        parlen = 2 + byteCount + 3; //adjusted for payload and continuation
+        printf("Need continuation, sending bytes [%d, %d> of attributeList\n", cs, cont);
+    } else {
+     //   printf("Final or only block, sending bytes [%d, %d> of attributeList\n", cs, cs+byteCount);
+    }
+    buf[0] = 7; //pdu
+    buf[1] = rxid>>8;
+    buf[2] = rxid;
+    buf[3] = parlen>>8;
+    buf[4] = parlen;
+    buf[5] = byteCount>>8;
+    buf[6] = byteCount;
+    int p = al->build(buf+7, size);//limited only by buffersize
+    //printf("'build' added %d bytes to the buffer\n", p);
+    if (cs == 0) { //this is not a continuation
+        buf[byteCount+7] = 0;
+    } else { //this is a continuation
+        memcpy(buf+7, buf+7+cs, byteCount);//move part of interrest to beginning of buffer
+        buf[byteCount+7] = 2;
+        buf[byteCount+8] = cont>>8;
+        buf[byteCount+9] = cont;
+    }
+    //printfBytes("SDP Send: ", buf, parlen+5);
+    int retval = Socket_Send(serverSock, _buf, parlen + 5 + OFFSET);
+    delete[] _buf;
+    return retval;
+}
+
+//unsigned SDPHandler::getval(const unsigned char *p, int n) {
+unsigned getval(const unsigned char *p, int n) {
+    unsigned ret = 0;
+    for (int i = 0; i < n; i++)
+        ret = (ret<<8) + (unsigned)p[i];
+    return ret;
+}
+
+//unsigned SDPHandler::length(const unsigned char *el, unsigned &p) {
+unsigned length(const unsigned char *el, unsigned &p) {
+    unsigned len = 0;
+    switch (el[p++] & 7) {//length
+        case 0:
+            len = 1;
+            break;
+        case 1:
+            len = 2;
+            break;
+        case 2:
+            len = 4;
+            break;
+        case 3:
+            len = 8;
+            break;
+        case 4:
+            len = 16;
+            break;
+        case 7://4bytes
+            len= el[p++]<<24;
+            len += el[p++]<<16;
+        case 6://2bytes
+            len += el[p++]<<8;
+        case 5://1byte
+            len += el[p++];
+            break;
+    }
+    return len;
+}
+
+extern "C" void HardFault_Handler() {
+    printf("Hard Fault! %d bytes left\n", AvailableMemory(1));
+    while (1);
+}
+
+unsigned SDPHandler::parseLight (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) {
+    unsigned p = 0;
+    unsigned len = length(el, p);
+    int end = p+len;//end is the index of the item just after the sequence
+    sdp_data *item = 0;
+    switch (el[0]>>3) {//type
+        case sdp_data::NULL_:
+            printf("NULL ");
+            break;
+        case sdp_data::UNSIGNED:
+            printf("UINT%d=%u ", len, (unsigned)getval(el+p, len));
+            break;
+        case sdp_data::SIGNED:
+            printf("INT%d=%d ", len, (unsigned)getval(el+p, len));
+            break;
+        case sdp_data::UUID:
+            if (len==16) {
+                printf("UUID16= ");
+                for (int i = 0; i < 16; i++)
+                    printf("%02x ", el[p+i]);
+            } else
+                printf("UUID%d=%u ", len, (unsigned)getval(el+p, len));
+            break;
+        case sdp_data::STRING:
+            printf("STR%d='%s' ", len, (char*)el+p);
+            break;
+        case sdp_data::BOOL:
+            printf("BOOL%d=%d ", len, (unsigned)getval(el+p, len));
+            break;
+        case sdp_data::SEQUENCE:
+            goto skip;
+        case sdp_data::ALTERNATIVE:
+skip: {//p points just after the length indicator, hence at the first item IN the sequence
+                printf("SEQ%d{%p ", len, item);
+                int n = 0;
+                unsigned short key;
+                serv_rec *dummy = 0;
+                while (p < end) {
+                    sdp_data *elem = 0;
+                    p += parseLight(el + p, len-p, elem, dummy);//parse each element in the sequence, the second arg is as yet unused
+                    if (record) {
+                        if (n & 1) { //value
+                            record->insert(pair<unsigned short, sdp_data*>(key, elem));
+                        } else //key
+                            key = n;
+                        n++;
+                    }
+                }
+            }
+            printf("}\n");
+            break;
+        case 8:
+            printf("URL%d='%s' ", len, (char*)el+p);
+            break;
+        default:
+            printf("Parse: Unknown type %d, len=%d (code=%#02X)\n", el[0]>>3, len, el[0]);
+    }
+    result = item;
+    return end;
+}
+
+unsigned SDPHandler::parse (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) {
+    unsigned p = 0;
+    unsigned len = length(el, p);
+    int end = p+len;//end is the index of the item just after the sequence
+    sdp_data *item = 0;
+    switch (el[0]>>3) {//type
+        case sdp_data::NULL_:
+            item = new sdp_data();
+            break;
+        case sdp_data::UNSIGNED:
+            item = new sdp_data((unsigned)getval(el+p, len), len);
+            break;
+        case sdp_data::SIGNED:
+            item = new sdp_data((int)getval(el+p, len), len);
+            break;
+        case sdp_data::UUID:
+            if (len==16) {
+                char rev[16];
+                for (int i = 0; i < 16; i++)
+                    rev[i] = el[p+15-i];
+                item = new sdp_data(sdp_data::UUID, rev, len);
+            } else
+                item = new sdp_data(sdp_data::UUID, getval(el+p, len), len);
+            break;
+        case sdp_data::STRING:
+            item = new sdp_data((char*)el+p, len);
+            break;
+        case sdp_data::BOOL:
+            item = new sdp_data((bool)getval(el+p, len), len);
+            break;
+        case sdp_data::SEQUENCE:
+            item = new sdp_data(sdp_data::SEQUENCE);
+            goto skip;
+        case sdp_data::ALTERNATIVE:
+            item = new sdp_data(sdp_data::ALTERNATIVE);
+skip: {//p points just after the length indicator, hence at the first item IN the sequence
+                //printf("SEQ%d{%p ", len, item);
+                int n = 0;
+                unsigned short key;
+                serv_rec *dummy = 0;//means: there is no service record to fill in for deeper levels
+                while (p < end) {
+                    sdp_data *elem = 0; //this becomes the tree with attribute values
+                    p += parse(el + p, len-p, elem, dummy);//parse each element in the sequence, the second arg is as yet unused
+                    if (record) { //if at the level of attribute list, add elem to record as key/value pair
+                        if (n & 1) { //value
+                            record->insert(pair<unsigned short, sdp_data*>(key, elem));
+                        } else //key
+                            key = elem->asUnsigned();
+                        n++;
+                    } else //just add the elements to the value tree
+                        item->add_element(elem);
+                }
+            }
+            //printf("}\n");
+            break;
+        case 8:
+            item = new sdp_data(sdp_data::URL, (char*)el+p, len);
+            break;
+        default:
+            printf("Parse: Unknown type %d, len=%d (code=%#02X)\n", el[0]>>3, len, el[0]);
+    }
+    result = item;
+    return end;
+}
+
+void SDPHandler::append(const unsigned char *payload, int len) {
+    unsigned char *tmp = new unsigned char[byteCount + len];//append the payload to the previous continuation buffer
+    if (contBuf && byteCount) {
+        memcpy(tmp, contBuf, byteCount); //copy the existing part
+        delete[] contBuf;//delete the old buffer
+    }
+    memcpy(tmp+byteCount, payload, len); //append the new part
+    contBuf = tmp;
+    byteCount += len;
+}
+
+void SDPHandler::freeBuf() {
+    if (contBuf) {
+        delete[] contBuf;
+        contBuf = 0;
+    }
+    byteCount = 0;
+}
+
+
+//TODO: test case 7, add server support (cases 2, 4, 6)
+//3 cases: cont==0 && contBuf==0 -> use rsp; cont!=0 -> append; cont==0 && contBuf!=0 -> append and use contBuf
+int SDPHandler::parseRsp(const unsigned char*rsp, int len) {
+    //unsigned tid = rsp[2] + ((unsigned)rsp[1]<<8);
+    unsigned parlen = rsp[4] + ((unsigned)rsp[3]<<8);
+    //printf("ParseRsp: tid=%04X, parlen=%d ", tid, parlen);
+    unsigned cont = 0;
+    switch (rsp[0]) {
+        case 1: {//errorRsp
+            unsigned errorcode = rsp[6] + ((unsigned)rsp[5]<<8);
+            if (parlen > 2) {
+                printf("ErrorInfo (%d bytes) for error %d is available\n", parlen-2, errorcode);
+            }
+            if (ErrorResponse)
+                ErrorResponse(errorcode);
+            return errorcode;
+        }
+        //break;
+        case 3: { //servicesearchRsp
+            //unsigned total = rsp[6] + ((unsigned)rsp[5]<<8);
+            unsigned current = rsp[8] + ((unsigned)rsp[7]<<8);
+            cont = rsp[9+4*current];
+            memcpy(contState, &rsp[9+4*current], cont+1);//copy the continuation state
+            //printf("total=%d, current=%d, cont=%d\n", total, current, cont);
+            if (cont) {
+                //no special handling here, just append the servicerecordhandles
+            }
+            //linear list of 32bit service-handles
+            for (int i = 0; i < current; i++) {
+                unsigned result = 0;
+                for (int j = 0; j< 4; j++)
+                    result = (result<<8) + rsp[9 + 4*i + j];
+                printf("SDP Search handle %08X\n", result);
+                services.insert(pair<unsigned, serv_rec*>(result, 0));
+            }
+            if (ServiceSearchResponse)
+                ServiceSearchResponse();
+        }
+        break;
+        case 5: { //serviceattributeRsp
+            unsigned count = rsp[6] + ((unsigned)rsp[5]<<8);//bytes in this part of the attribute list
+//            append(rsp+7, count);
+            cont = rsp[7+count];
+            memcpy(contState, &rsp[7+count], cont+1);//copy the continuation state
+            if (cont) {
+                append(rsp+7, count);
+                break;
+            }
+            //printf("count=%d parsing...\n", byteCount);
+            serv_rec *serv = new serv_rec;
+            if (contBuf) {
+                append(rsp+7, count);
+                parse(contBuf, byteCount, tree, serv);
+            } else
+                parse(rsp+7, count, tree, serv);
+            //printf("...parsing done,  ");
+            //get the AttributeID, make sure attribId 0 is always included in the request
+            unsigned key = (*serv)[0]->asUnsigned();//AttributeID '0' always refers to the serviceID
+            //printf("Key=%#X\n", key); //key will be 0 when not requested
+            services[key] = serv; //Add the attribute list to the services
+            freeBuf();
+            if (ServiceAttributeResponse)
+                ServiceAttributeResponse(serv);
+        }
+        break;
+        //below is UNTESTED
+        case 7: { //servicesearchattributeRsp
+            unsigned count = rsp[6] + ((unsigned)rsp[5]<<8);
+            append(rsp+7, count);
+            cont = rsp[7+count];
+            memcpy(contState, &rsp[7+count], cont+1);
+            if (cont)
+                break;
+            unsigned pos = 0;
+            if (contBuf[pos]>>3 != sdp_data::SEQUENCE) {
+                printf("Expected a sequence of attribute lists\n");
+                break;
+            }
+            unsigned len = length(contBuf, pos);//get the length of the list of lists and advance pos to the first list
+            while (pos<len) {
+                printf("pos=%d, count=%d, parsing...\n", pos, len);
+                serv_rec *serv = new serv_rec;
+                pos = parse(contBuf+pos, len, tree, serv);
+                unsigned key = (*serv)[0]->asUnsigned();
+                services[key] = serv;
+            }
+            freeBuf();
+            printf("...parsing done, pos=%d\n", pos);
+            if (ServiceSearchAttributeResponse)
+                ServiceSearchAttributeResponse();
+        }
+        break;
+        default:
+            printf("Unknown SDP response type %02X\n", rsp[0]);
+            break;
+    }
+    return 0;
+}
+
+//************************ SERVER related *******************************************//
+
+//unsigned SDPHandler::parseUUID(const u8* data, int len, unsigned &p) {
+unsigned parseUUID(const u8* data, int len, unsigned &p) {
+    unsigned u = 0;
+    if ((data[p]>>3) != sdp_data::UUID) {
+        printf(" UUID expected, got %d ", data[p]>>3);
+        return (unsigned)-1;
+    }
+    switch (data[p++] & 7) {
+        case 1:
+            u = getval(data+p, 2);
+            p +=2;
+            break;
+        case 2:
+            u = getval(data+p, 4);
+            p += 4;
+            break;
+        case 4:
+            u = getval(data+p, 4);
+            p += 16;
+            break;
+        default:
+            printf(" UUID must be 2, 4 or 16 bytes, got type %d\n", data[p-1]);
+    }
+    return u;
+}
+
+#define SVC_HANDLE  0x0001001DU  //serial service
+void SDPManager::buildServer() {
+    static sdp_data rfcomm(sdp_data::SEQUENCE);
+    static sdp_data l2cap(sdp_data::SEQUENCE);
+    static sdp_data protocol(sdp_data::SEQUENCE);
+    static sdp_data serviceclass(sdp_data::SEQUENCE);
+    static sdp_data browsegroup(sdp_data::SEQUENCE);
+    static sdp_data root(sdp_data::UUID, BROWSEROOT);
+    static sdp_data l2capuuid(sdp_data::UUID, 0x0100);
+    static sdp_data rfcommuuid(sdp_data::UUID, 0x003);
+    static sdp_data serial(sdp_data::UUID, 0x1101);
+    static sdp_data chan(1U,1);
+    static sdp_data handle(SVC_HANDLE,4);
+    static sdp_data serviceID(0U, 2);
+    static sdp_data name("MBED BlueUSB RFCOMM Serial");
+    rfcomm.add_element(&rfcommuuid);
+    rfcomm.add_element(&chan);
+    l2cap.add_element(&l2capuuid);
+    protocol.add_element(&l2cap);
+    protocol.add_element(&rfcomm);
+    serviceclass.add_element(&serial);
+    browsegroup.add_element(&root);
+    static serv_rec attr_list;
+    attr_list[0] = &handle;
+    attr_list[1] = &serviceclass;
+    attr_list[4] = &protocol;
+    attr_list[5] = &browsegroup;
+    attr_list[0x100] = &name;
+    server[SVC_HANDLE] = &attr_list;//server is static and this statement crashes the program when invoked from the constructor which is also invoked statically
+}
+
+int SDPManager::findUUID(unsigned h, unsigned uuid) {
+    serv_rec *rec = server[h];
+    for ( serv_rec::iterator it = rec->begin(); it != rec->end(); it++) {
+        if (it->second->findUUID(uuid))
+            return it->first;
+    }
+    printf("rejected %08X because of %04Xx\n", h, uuid);
+    return -1;
+}
+
+void SDPManager::match(bool elig[], unsigned uuid) {
+    map<unsigned, serv_rec*>::iterator idx;
+    int i = 0;
+    for (idx = server.begin(); idx != server.end(); idx++, i++)
+        if (findUUID(idx->first, uuid) < 0)
+            elig[i] = false;
+}
+
+bool SDPManager::isInList(unsigned short id, const unsigned char* list, int end) {
+    int len;
+    for (unsigned pos = 0; pos < end; pos += len) {
+        len = length(list, pos);
+        switch (len) {
+            case 2: //single value
+                if (getval(list+pos, 2) == id)
+                    return true;
+                break;
+            case 4: //range
+                if (getval(list+pos, 2) > id) break;
+                if (getval(list+pos+2, 2) < id) break;
+                return true;
+            default:
+                printf("Unexpected length %d\n", len);
+        }
+    }
+    return false;
+}
+
+void SDPManager::addToReply(sdp_data *svc, serv_rec *list, const unsigned char* att, int end) {
+    unsigned short len, low, high;
+    serv_rec::iterator from, to, idx;
+    for (unsigned pos = 0; pos < end; pos += len) {
+        len = length(att, pos);
+        switch (len) {
+            case 2: //single value
+                low = getval(att+pos, 2);
+                svc->add_element(new sdp_data(low, 2));
+                svc->add_element((*list)[low]);
+                printf("Found attrib %d\n", low);
+                break;
+            case 4: //range
+                low = getval(att+pos, 2);
+                high = getval(att+pos+2, 2);
+                from = list->lower_bound(low);
+                to = list->upper_bound(high);
+                for (idx = from; idx != to; idx++) {
+                  svc->add_element(new sdp_data(idx->first, 2));
+                  svc->add_element(idx->second);
+                  printf("Found attrib %d\n", idx->first);
+                }
+                break;
+            default:
+                printf("Unexpected length %d\n", len);
+        }
+    }
+}
+
+//for continuations, just generate the entire list, truncate to desired length and append position of the remainder as continuation
+//on the next iteration, generate the list again, use continuation to find remainder and reiterate
+void SDPManager::SDPServer(int socket, SocketState state, const u8* data, int len, void* userData) {
+    unsigned tid = data[2] + ((unsigned)data[1]<<8);
+    unsigned parlen = data[4] + ((unsigned)data[3]<<8);
+    //printf("ParseReq: PDU_ID=%d, tid=%04X, parlen=%d ", data[0], tid, parlen);
+    unsigned pos = 5;
+    switch (data[0]) {
+        case 1: {//errorRsp
+            unsigned errorcode = data[6] + ((unsigned)data[5]<<8);
+            if (parlen > 2) {
+                printf("ErrorInfo (%d bytes) for error %d is available\n", parlen-2, errorcode);
+            }
+            errorhandler(errorcode);
+        }
+        break;
+        case 2: { //servicesearchReq
+        }
+        break;
+        case 4: { //serviceattributeReq
+        }
+        break;
+        case 6: { //servicesearchattributeReq
+            sdp_data reply(sdp_data::SEQUENCE);//the attributelist of the reply
+
+            unsigned pat[12];//the received search pattern
+            int pn;//number of uuids in the pattern
+            if (data[pos]>>3 != sdp_data::SEQUENCE) {//the uuids are wrapped in a sequence
+                printf("Expected a sequence of UUIDs\n");
+                break;
+            }
+            unsigned end = pos + length(data, pos);//get the length of the list of lists and advance pos to the first list
+            bool *eligible = new bool[server.size()];//marks for the services identified by the search pattern
+            for (int i = 0; i < server.size(); i++) eligible[i] = true;
+            for (pn = 0; pn < 12 && pos < end; pn++) {
+                pat[pn] = parseUUID(data,end, pos);//store uuid from the sequence in the pattern
+                match(eligible, pat[pn]);//unmark a service when it does not contain the uuid
+                //printf("pos=%d, count=%d, uuid=%#X\n", pos, len, pat[pn]);
+            }
+
+            unsigned count = getval(data+pos, 2); //maximum length of attribute list to return
+            pos += 2;
+
+            int len = length(data, pos); //get the length of the attributeID list
+            int cont = pos + len;
+            //printf("Count = %d pos=%d, data[pos]=%02x, len=%d, cont=%d\n", count, pos, data[pos], len, cont);
+            int i = 0;
+            for (map<unsigned, serv_rec*>::iterator idx = server.begin(); idx != server.end(); idx++, i++) {//foreach service
+                //printf("testing service handle %08X\n", idx->first);
+                if (!eligible[i]) continue; //skip services that don't match the pattern
+                sdp_data *svc = new sdp_data(sdp_data::SEQUENCE); //create a sequence for the attributes of the present service
+#if 0
+                for (serv_rec::iterator attr = idx->second->begin(); attr != idx->second->end(); attr++) {//foreach attrib in the service
+                    //printf("testing attribID %u\n", attr->first);
+                    if (isInList(attr->first, data+pos, len)) {//check if it is requested
+                        printf("Found attribID %d\n", attr->first);
+                        sdp_data *p = attr->second; //the attribute
+                        svc->add_element(new sdp_data(attr->first, 2)); //add the attribute ID as an unsigned short
+                        svc->add_element(p);                            //add the attribute
+                        //printf("appending %d bytes\n", p->Size());
+                    }
+                }
+#else
+//alternatively use map::lower/upper_bound and equal_range, needs only one pass over the range list for each service
+                addToReply(svc, idx->second, data+pos, len);
+#endif
+                reply.add_element(svc); //append the new attribute list to the reply list
+            }
+            
+            unsigned tail = data[cont];
+            if (tail) {
+                tail = getval(data+cont+1, tail);
+                printf("requested continuation tailpos=%u, size=%u\n", tail, reply.Size());
+            }
+            else {
+                //printf("No continuation requested\n");
+            }
+            ServiceSearchAttributeReply(tid, &reply, count, tail);
+            
+            for (int j = 0; j < reply.items(); j++) {
+                sdp_data *al = reply.item(j);
+                for (int k = 0; k < al->items(); k++) {
+                    if ((k & 1) == 0) //even hence ID
+                        delete al->item(k); //destroy the ID
+                    al->remove(k);  //set all items to nil to prevent destruction of the DB
+                }
+                delete al; //destroy the list;
+                reply.remove(j);
+            }
+            delete[] eligible;
+        }
+        break;
+        default:
+            printf("Unknown SDP request type %02X\n", data[0]);
+            break;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/sdp/sdp.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,184 @@
+#ifndef SDP_H
+#define SDP_H
+#include "AvailableMemory.h"
+#include "sdp_data.h"
+#include <map>
+#define OFFSET  8
+
+class SDPManager;
+extern SDPManager SDP;
+typedef map<unsigned short, sdp_data*> serv_rec;
+
+void attribHandler(serv_rec *r);
+unsigned parseUUID(const u8* data, int len, unsigned &p);
+unsigned length(const unsigned char *el, unsigned &p);
+unsigned getval(const unsigned char *p, int n) ;
+void errorhandler(unsigned err);//default error handler
+
+
+class SDPHandler: public SocketHandler {
+//    int _l2cap;
+    int sdp_socket;
+    unsigned char l2cap_buf[100+OFFSET];
+    unsigned char* buf;
+    unsigned txid;
+    unsigned char contState[17];//maximum size, in practive it is 3
+    unsigned char *contBuf;
+    unsigned byteCount;
+    int _state;
+    sdp_data *tree;//root of the entire service tree
+    map<unsigned, serv_rec*> services;//the set of supported services <handle, service>
+    map<unsigned, serv_rec*>::iterator index;
+//server properties
+//    static map<unsigned, serv_rec*> server;
+//    static int serverSock;
+public:
+    SDPHandler();
+    void Clear();
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
+//    virtual int Accept(SocketInternal *sock, int scid, int rxid); //called indirectly from BTDevice::Control
+    virtual int Send(SocketInternal* sock, const u8* data, int len);
+    virtual int Close(SocketInternal* sock);
+    virtual char* Name() {
+        return "SDPHandler SocketHandler";
+    }
+    void OnSdpRsp(const u8* data, int len);
+    static void OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData);
+
+    //this function is called when the SDP sockets receives data (see HCICallback in TestShell),
+    //currently does not happen because not forwarded from OnSdpRsp, can be used to handle multiple connections
+    static void OnSockCallback(int socket, SocketState state, const u8* data, int len, void* userData) ;
+    //The SDP server is stateless hence can be static
+//    static void SDPServer(int socket, SocketState state, const u8* data, int len, void* userData) ;
+
+    void (*ErrorResponse)(unsigned) ;
+    void (*ServiceSearchResponse)() ;
+    void (*ServiceAttributeResponse)(serv_rec*) ;
+    void (*ServiceSearchAttributeResponse)() ;
+    int ServiceSearchRequest(sdp_data *sp, unsigned count, unsigned cs=0);
+    int ServiceAttributeRequest(unsigned handle, unsigned count, sdp_data* al, unsigned cs=0) ;
+    int ServiceSearchAttributeRequest(sdp_data *sp, unsigned count, sdp_data* al, unsigned cs=0);
+//server
+//    static int ServiceSearchAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs=0);
+private:
+//    static unsigned length(const unsigned char *el, unsigned &p);
+//    static unsigned getval(const unsigned char *p, int n) ;
+//    static unsigned parseUUID(const u8* data, int len, unsigned &p);
+    unsigned parse (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
+    unsigned parseLight (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
+    int parseRsp(const unsigned char*rsp, int len) ;
+    void append(const unsigned char*rsp, int len) ;
+    void freeBuf();
+};
+/*
+class SDPClient: public SDPHandler {
+};
+
+class SDPServer: public SDPHandler {
+};
+*/
+class SDPManager: public SocketHandler {
+    map<int, SDPHandler*> handlers;
+//server properties
+//    SDPHandler *Server;
+    static map<unsigned, serv_rec*> server;
+    static int serverSock;
+    bool once;
+public:
+    SDPManager() {
+        once = true;
+    }
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr) {
+        printf("SDPManager::Open(sock (ID=%d, type=%d), addr): should not be called\n", sock->ID, sock->Type);
+        return sock->ID;//((SDPHandler*)sock->userData)->Open(sock, addr);
+    }
+    int Open(SocketAddrHdr* addr) {
+        L2CAPAddr* ad = (L2CAPAddr*)addr;
+        ad->psm = L2CAP_PSM_SDP;//open the l2cap channel
+        SDPHandler *h = new SDPHandler;
+        int s = Socket_Open(SOCKET_L2CAP, addr, &SDPHandler::OnSdpRsp, h);
+        handlers[s] = h;
+        return s;
+    }
+    virtual int Accept(SocketInternal *sock, int scid, int rxid) { //called indirectly from BTDevice::Control
+        if (once) {
+            once = false;
+            buildServer();//build the DB on the first connection
+        }
+        //sock is registered as an SDP sock but we use it as an L2CAP sock
+        //type=SDP
+        //userData = BTDevice
+        //Internal = L2CAPSocket
+        BTDevice *l2cap = (BTDevice*)sock->userData;
+        //sock->dcid = scid
+        //sock->scid = something based on sock->ID
+        serverSock = sock->ID;
+        printf("Invoking accept on %p (%s) for sock %d and scid=%d\n", l2cap, l2cap->Name(), sock->ID, scid);
+        return l2cap->Accept(sock, scid, rxid);
+    }
+    virtual int Send(SocketInternal* sock, const u8* data, int len) {//called by the server
+        BTDevice *l2cap = (BTDevice*)sock->userData;
+        return l2cap->Send(sock, data, len);
+    }
+    virtual int Close(SocketInternal* sock) {
+        printf("SDPManager::Close() closing  socket %d\n", sock->ID);
+        SDPHandler *h = handlers[sock->ID];
+        int retval = h->Close(sock);
+        delete h;
+        handlers[sock->ID] = 0;
+        return retval;
+    }
+    void Destroy(int s) {
+        printf("Deleting handler for socket %d\n", s);
+        delete handlers[s];
+        handlers[s] = 0;
+    }
+    virtual char* Name() {
+        return "SDPManager SocketHandler";
+    }
+    //void OnSdpRsp(const u8* data, int len);
+    static void OnSdpRsp(int socket, SocketState state, const u8* data, int len, void* userData) {
+        printf("SDPManager::OnSdpRsp(socket %d, state %d, len %d)\n", socket, state, len);
+    }
+    //The SDP server is (almost) stateless hence can be static
+    static void SDPServer(int socket, SocketState state, const u8* data, int len, void* userData) ;
+    static void match(bool elig[], unsigned uuid);
+    static bool isInList(unsigned short id, const unsigned char* list, int end);
+    static void addToReply(sdp_data *svc, serv_rec *list, const unsigned char* att, int end);
+    static int findUUID(unsigned h, unsigned uuid);
+    void buildServer();
+    static int ServiceSearchAttributeReply(unsigned rxid, sdp_data* al, unsigned count, unsigned cs=0);
+    /*
+        //this function is called when the SDP sockets receives data (see HCICallback in TestShell),
+        //currently does not happen because not forwarded from OnSdpRsp, can be used to handle multiple connections
+        static void OnSockCallback(int socket, SocketState state, const u8* data, int len, void* userData) ;
+
+        static void errorhandler(unsigned err);
+
+        void (*ErrorResponse)(unsigned) ;
+        void (*ServiceSearchResponse)() ;
+        void (*ServiceAttributeResponse)(serv_rec*) ;
+        void (*ServiceSearchAttributeResponse)() ;
+        int ServiceSearchRequest(sdp_data *sp, unsigned count, unsigned cs=0);
+        int ServiceAttributeRequest(unsigned handle, unsigned count, sdp_data* al, unsigned cs=0) ;
+        int ServiceSearchAttributeRequest(sdp_data *sp, unsigned count, sdp_data* al, unsigned cs=0);
+    //server
+    private:
+        static unsigned length(const unsigned char *el, unsigned &p);
+        static unsigned getval(const unsigned char *p, int n) ;
+        static unsigned parseUUID(const u8* data, int len, unsigned &p);
+        static void addAttrib(unsigned h, unsigned short id, sdp_data *attrib);
+        static void addIndex(unsigned h, unsigned uuid);
+        static int findUUID(unsigned h, unsigned uuid);
+        static void match(bool elig[], unsigned uuid);
+        static bool isInList(unsigned short id, const unsigned char* list, int end);
+        void buildServer();
+        unsigned parse (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
+        unsigned parseLight (const unsigned char *el, unsigned count, sdp_data* &result, serv_rec* &record) ;
+        int parseRsp(const unsigned char*rsp, int len) ;
+        void append(const unsigned char*rsp, int len) ;
+        void freeBuf();
+    */
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/sdp/sdp_data.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,229 @@
+#include "mbed.h"
+#include "sdp_data.h"
+#include "Utils.h"
+
+char sdp_data::ret[12];
+
+unsigned sdp_data::asUnsigned() {
+    switch (type) {
+        case NULL_:
+            return 0;
+        case UNSIGNED:
+        case SIGNED:
+        case BOOL:
+            return data;
+        case UUID:
+#ifdef LONGUUID
+            return uuid[6] + uuid[7]<<16;
+#else
+            return data;
+#endif
+        default:
+            return 0;
+    }
+}
+
+const char* sdp_data::asString(bool alt) {
+    char sep = ',';
+    switch (type) {
+        case NULL_:
+            return "NULL";
+        case UNSIGNED:
+            if (alt) sprintf(ret, "0x%0*X", size*2, data);
+            else sprintf(ret, "%u", data);
+            return ret;
+        case SIGNED:
+            sprintf(ret, "%d", data);
+            return ret;
+        case BOOL:
+            return data ? "TRUE" : "FALSE";
+        case STRING:
+        case URL:
+            return str;
+        case ALTERNATIVE:
+            sep = '|';
+        case SEQUENCE: {
+            if (longstr) delete[] longstr;
+            int n = sprintf(ret, "SEQ %d { ", size) + 1;
+            longstr = new char[n];
+            strcpy(longstr, ret);
+            for (int i = 0; i < sequence.size(); i++) {
+                const char *s = sequence[i]->asString(alt);
+                n = strlen(longstr) + strlen(s) + 2;
+                char *t = new char[n];
+                strcpy(t, longstr);
+                strcat(t, s);
+                t[n-2] = sep;
+                t[n-1]='\0';
+                //printf("[%s]+[%s]+%c=[%s]\n", longstr, s, sep, t);
+                delete[] longstr;
+                longstr = t;
+            }
+            longstr[n-2] = '}';
+        }
+        return longstr;
+        case UUID:
+#ifdef LONGUUID
+            switch (size) {
+                case 2:
+                    sprintf(ret, "0x%04X", uuid[6]);
+                    return ret;
+                case 4:
+                    sprintf(ret, "0x%04X%04X", uuid[7],uuid[6]);
+                    return ret;
+                case 16:
+                    longstr = new char[35];
+                    sprintf(longstr, "%04X%04X-%04X-%04X-%04X-%04X%04X%04X", uuid[7],uuid[6],uuid[5],uuid[4],uuid[3],uuid[2],uuid[1],uuid[0]);
+                    return longstr;
+            }
+#else
+            switch (size) {
+                case 2:
+                    sprintf(ret, "0x%04X", data & 0xffff);
+                    return ret;
+                case 4:
+                    sprintf(ret, "0x%08X", data);
+                    return ret;
+                case 16:
+                    longstr = new char[35];
+                    sprintf(longstr, "%08X-%04X-%04X-%04X-%04X%04X%04X", data,base_uuid[5],base_uuid[4],base_uuid[3],base_uuid[2],base_uuid[1],base_uuid[0]);
+                    return longstr;
+            }
+#endif
+    }
+    return "Unsupported";
+}
+
+unsigned sdp_data::Size() {
+    if (size==0 && type==SEQUENCE)
+      return 2;
+    if (size<3 || size==4 || size==8 || size==16)
+        return size+1;//include descriptor
+    if (size < 256) return size+2; //1 extra byte
+    if (size < 65536) return size+3; //2 extra bytes
+    return size+5; //4 extra bytes
+}
+
+unsigned sdp_data::sizedesc(unsigned char *buf) {
+    int desc, extra=0;
+    switch (size) {
+        case 0:
+        /* should be:
+           if (type != NULL_) {
+                desc = 5;
+                extra = 1;
+                buf[1] = 0;
+           }
+        */
+        case 1:
+            desc = 0;
+            break;
+        case 2:
+            desc = 1;
+            break;
+        case 4:
+            desc = 2;
+            break;
+        case 8:
+            desc = 3;
+            break;
+        case 16:
+            desc = 4;
+            break;
+        default:
+            if (size < 256) {
+                desc = 5;
+                extra = 1;
+                buf[1] = size;
+            } else if (size < 65536) {
+                desc = 6;
+                extra = 2;
+                *(unsigned short*)&buf[1] = size;
+            } else {
+                desc = 7;
+                extra = 4;
+                *(unsigned*)&buf[1] = size;
+            }
+    }
+    buf[0] |= desc;
+    return extra+1;
+}
+
+void sdp_data::revcpy(unsigned char*d, const unsigned char*s, int n) {
+    for (int i = 0; i < n; i++)
+        d[i] = s[n-i-1];
+}
+
+unsigned sdp_data::build(unsigned char *buf, unsigned max) {//max is ignored
+    int p = 0;
+    buf[p] = type<<3;
+    switch (type) {
+        case NULL_:
+            p++;
+            break;
+        case UNSIGNED:
+        case SIGNED:
+        case BOOL:
+            p += sizedesc(buf+p);
+            revcpy(buf+p, (unsigned char*)&data, size);
+            break;
+        case UUID:
+            p += sizedesc(buf+p);
+#ifdef LONGUUID
+            switch (size) {
+                case 2:
+                case 4:
+                    revcpy(buf+p, (unsigned char*)&uuid[6], size);
+                    break;
+                case 16:
+                    revcpy(buf+p, (unsigned char*)uuid, size);
+                    break;
+            }
+#else
+            switch (size) {
+                case 2:
+                case 4:
+                    revcpy(buf+p, (unsigned char*)&data, size);
+                    break;
+                case 16:
+                    revcpy(buf+p, (unsigned char*)&data, 4);
+                    revcpy(buf+p+4, base_uuid, 12);
+                    break;
+            }
+#endif
+            break;
+        case STRING:
+        case URL:
+            p += sizedesc(buf+p);
+            memcpy(buf+p, str, size);
+            break;
+        case SEQUENCE:
+        case ALTERNATIVE: {
+            if (sequence.size()==0) {//hack: should be solved in sizedesc
+              buf[p++] |= 5;
+              buf[p++] = 0;
+              break;
+            }
+            int n = 0;
+            p += sizedesc(buf+p);
+            for (int i = 0; i < sequence.size(); i++)
+                n += sequence.at(i)->build(buf+p+n, max-p);
+        }
+        break;
+    }
+    p += size;
+//    printfBytes("Build:", buf, p);
+    return p;
+}
+
+bool sdp_data::findUUID(unsigned uuid) {
+    if (type == UUID)
+        return asUnsigned()==uuid;
+    if (type==SEQUENCE || type==ALTERNATIVE) {
+        for (int i = 0; i < sequence.size(); i++) {
+            if (sequence[i]->findUUID(uuid))
+                return true;
+        }
+    }
+    return false;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myBlueUSB/sdp/sdp_data.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,116 @@
+#ifndef SDP_DATA_H
+#define SDP_DATA_H
+
+#include <vector>
+
+extern const unsigned char base_uuid[16];// = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0, 0x07, 0x70, 0, 0x10, 0, 0};
+
+class sdp_data {
+public:
+    enum elements { NULL_, UNSIGNED, SIGNED, UUID, STRING, BOOL, SEQUENCE, ALTERNATIVE, URL};
+private:
+    enum elements type;
+    char size;
+    union {
+        unsigned data;
+        char *str;
+#ifdef LONGUUID
+        unsigned short uuid[8];
+#endif
+    };
+    vector<sdp_data*> sequence; //not allowed to be in union
+    static char ret[12];
+    char *longstr;
+public:
+    sdp_data(): type(NULL_), size(0), longstr(0) {
+        //printf("NULL%d ", size);
+    }
+    sdp_data(unsigned d, unsigned sz=4): type(UNSIGNED), size(sz), longstr(0) {
+        data=d;
+        //printf("UINT%d=%u ", size, data);
+    }
+    sdp_data(unsigned short d, unsigned sz=2): type(UNSIGNED), size(sz), longstr(0) {
+        data=d;
+        //printf("UINT%d=%u ", size, data);
+    }
+    sdp_data(signed d, unsigned sz=4): type(SIGNED), size(sz), longstr(0) {
+        data=d;
+           //printf("INT%d=%d ", size, data);
+    }
+    sdp_data(bool d, unsigned sz=1): type(BOOL), size(sz), longstr(0) {
+        data=d;
+           //printf("BOOL%d=%u ", size, data);
+    }
+    sdp_data(char*s, unsigned sz=0): type(STRING), longstr(0) {
+        if (sz) size = sz+1;
+        else size = strlen(s)+1;
+        str = new char[size];
+        strncpy(str, s, size);
+        str[size-1] = '\0';
+           //printf("STR%d='%s' ", size, str);
+    }
+    sdp_data(enum elements t, unsigned d, unsigned sz=2): type(t), size(sz), longstr(0) {
+        if (t==UUID) {
+#ifdef LONGUUID
+            memcpy(uuid, base_uuid, 16);
+            uuid[6] = d;
+            uuid[7] = d>>16;
+            //       printf("UUID%d=%04X%04X ", size, uuid[7], uuid[6]);
+#else
+            data = d;
+#endif
+        } else printf("Please use other constructor for type %d\n", t);
+    }
+    sdp_data(enum elements t, char *d=0, unsigned sz=0): type(t), size(sz), longstr(0) {
+        switch (t) {
+#ifdef LONGUUID
+            case UUID:
+                memcpy(uuid, d, size);
+                //           printf("UUID%d=%08X ", size, uuid[6]);
+                break;
+#endif
+            case URL:
+                //size = strlen(d)+1;
+                str = new char[size+1];
+                strcpy(str, d);
+                //         printf("URL%d='%u' ", size, str);
+                break;
+            case SEQUENCE:
+            case ALTERNATIVE:
+                break;
+            default:
+                printf("Please use other constructor for type %d\n", t);
+        }
+    }
+    ~sdp_data() {
+        switch (type) {
+            case STRING:
+            case URL:
+                delete[] str;
+                break;
+            case SEQUENCE:
+            case ALTERNATIVE:
+                for (int i = 0; i < sequence.size(); i++)
+                    delete sequence.at(i);
+                break;
+        }
+        if (longstr)
+           delete[] longstr;
+    }
+    void add_element(sdp_data *el) {
+        sequence.push_back(el);
+        size += el->Size();
+    }
+    unsigned asUnsigned() ;
+    const char* asString(bool alt=false) ;
+    unsigned Size() ;
+    unsigned items() { return sequence.size();}
+    sdp_data* item(int i) { return sequence[i];}
+    void remove(int i) { sequence[i] = 0;}
+    unsigned sizedesc(unsigned char *buf) ;
+    void revcpy(unsigned char*d, const unsigned char*s, int n) ;
+    unsigned build(unsigned char *buf, unsigned max) ;
+    bool findUUID(unsigned uuid);
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myUSBHost/AutoEvents.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,181 @@
+
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "mbed.h"
+#include "USBHost.h"
+#include "Utils.h"
+#include "ftusb.h"
+
+#define AUTOEVT(_class,_subclass,_protocol) (((_class) << 16) | ((_subclass) << 8) | _protocol)
+#define AUTO_KEYBOARD AUTOEVT(CLASS_HID,1,1)
+#define AUTO_MOUSE AUTOEVT(CLASS_HID,1,2)
+#define AUTO_SERIAL AUTOEVT(CLASS_COMM_AND_CDC_CONTROL,2,1)
+
+u8 auto_mouse[4];       // buttons,dx,dy,scroll
+u8 auto_keyboard[8];    // modifiers,reserved,keycode1..keycode6
+u8 auto_joystick[4];    // x,y,buttons,throttle
+u8 auto_serial[8];      //connection speed change structure or uart state bitmap
+
+void AutoEventCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
+{
+    int evt = (int)userData;
+    switch (evt)
+    {
+        case AUTO_KEYBOARD:
+            printf("AUTO_KEYBOARD ");
+            break;
+        case AUTO_MOUSE:
+            printf("AUTO_MOUSE ");
+            break;
+        case AUTO_SERIAL:
+            printf("AUTO_SERIAL %02X", status);
+            break;
+        default:
+            printf("HUH ");
+    }
+    printfBytes("data",data,len);
+    USBInterruptTransfer(device,endpoint,data,len,AutoEventCallback,userData);
+}
+
+//  Establish transfers for interrupt events
+void AddAutoEvent(int device, InterfaceDescriptor* id, EndpointDescriptor* ed)
+{
+    if ((ed->bmAttributes & 3) != ENDPOINT_INTERRUPT || !(ed->bEndpointAddress & 0x80))
+        return;
+    
+    // Make automatic interrupt enpoints for known devices
+    u32 evt = AUTOEVT(id->bInterfaceClass,id->bInterfaceSubClass,id->bInterfaceProtocol);
+    u8* dst = 0;
+    int len;
+    switch (evt)
+    {
+        case AUTO_MOUSE:
+            dst = auto_mouse;
+            len = sizeof(auto_mouse);
+            break;
+        case AUTO_KEYBOARD:
+            dst = auto_keyboard;
+            len = sizeof(auto_keyboard);
+            break;
+        case AUTO_SERIAL:
+            dst = auto_serial;
+            len = sizeof(auto_serial);
+            break;
+        default:
+            printf("Interrupt endpoint %02X %08X\n",ed->bEndpointAddress,evt);
+            break;
+    }
+    if (dst)
+    {
+        printf("Auto Event for %02X %08X\n",ed->bEndpointAddress,evt);
+        USBInterruptTransfer(device,ed->bEndpointAddress,dst,len,AutoEventCallback,(void*)evt);
+    }
+}
+
+void PrintString(int device, int i)
+{
+    u8 buffer[256];
+    int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,i,buffer,255);
+    if (le < 0)
+         return;
+    char* dst = (char*)buffer;
+    for (int j = 2; j < le; j += 2)
+        *dst++ = buffer[j];
+    *dst = 0;
+    printf("%d:%s\n",i,(const char*)buffer);
+ }
+ 
+//  Walk descriptors and create endpoints for a given device
+int StartAutoEvent(int device, int configuration, int interfaceNumber)
+{
+    u8 buffer[255];
+    int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,255);
+    if (err < 0)
+        return err;
+
+    int len = buffer[2] | (buffer[3] << 8);
+    u8* d = buffer;
+    u8* end = d + len;
+    while (d < end)
+    {
+        if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
+        {   InterfaceDescriptor* id = (InterfaceDescriptor*)d;
+        /*printf("StartAutoEvent device %d, interfaceDescriptor(T=%d, N=%d, C=%02X, S=%02X, P=%02X)\n", 
+                 device, id->bDescriptorType, id->bInterfaceNumber, id->bInterfaceClass, id->bInterfaceSubClass, id->bInterfaceProtocol);
+        */    
+            if (id->bInterfaceNumber == interfaceNumber)
+            {
+                 d += d[0];
+                while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE)
+                {
+                    if (d[1] == DESCRIPTOR_TYPE_ENDPOINT)
+                        AddAutoEvent(device,id,(EndpointDescriptor*)d);
+                    d += d[0];
+                }
+            }
+        }
+        d += d[0];
+    }
+    return 0;
+}
+
+//  Implemented in main.cpp
+int OnDiskInsert(int device);
+
+void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc)
+{
+    printf("LoadDevice %d %02X:%02X:%02X\n",device,interfaceDesc->bInterfaceClass,interfaceDesc->bInterfaceSubClass,interfaceDesc->bInterfaceProtocol);
+    char s[128];
+    for (int i = 1; i < 3; i++)
+    {
+        if (GetString(device,i,s,sizeof(s)) < 0)
+            break;
+        printf("%d: %s\n",i,s);
+    }
+    
+    if (deviceDesc->idVendor == 0x146A || deviceDesc->idVendor == 0x221D) {//Knobloch GMBH or MSC Vertrieb
+      OnLoadFtDevice(device, deviceDesc, interfaceDesc);
+      return;
+    }
+    switch (interfaceDesc->bInterfaceClass)
+    {
+        case CLASS_MASS_STORAGE:
+            if (interfaceDesc->bInterfaceSubClass == 0x06 && interfaceDesc->bInterfaceProtocol == 0x50)
+                OnDiskInsert(device);    // it's SCSI!
+            break;
+        case CLASS_COMM_AND_CDC_CONTROL:
+            if (interfaceDesc->bInterfaceSubClass == 0x02 && interfaceDesc->bInterfaceProtocol == 0x01){
+                printf("Found serial device\n");
+                //OnSerialInsert(device);    
+                StartAutoEvent(device,1,0);
+            }
+            break;
+        case CLASS_WIRELESS_CONTROLLER:
+            if (interfaceDesc->bInterfaceSubClass == 0x01 && interfaceDesc->bInterfaceProtocol == 0x01)
+                OnBluetoothInsert(device);    // it's bluetooth!
+            break;
+        default:
+            StartAutoEvent(device,1,0);
+            break;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myUSBHost/MassStorage.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,180 @@
+
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "stdlib.h"
+#include "stdio.h"
+#include "string.h"
+
+#include "Utils.h"
+#include "USBHost.h"
+
+
+int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize);
+int MassStorage_ReadBlock(int device, u32 block, u8* dst);
+int MassStorage_WriteBlock(int device, u32 block, const u8* dst);
+
+
+#define ERR_BAD_CSW_SIGNATURE -200
+
+#define CBW_SIGNATURE  0x43425355
+#define CSW_SIGNATURE  0x53425355
+
+//  Command Block
+typedef struct
+{
+    u32 Signature;
+    u32 Tag;
+    u32 TransferLength;
+    u8 Flags;
+    u8 LUN;
+    u8 CBLength;
+    u8 CB[16];   // only 6 really
+} CBW;
+
+//  Status block
+typedef struct
+{
+    u32 Signature;
+    u32 Tag;
+    u32 DataResidue;
+    u8 Status;
+} CSW;
+
+int SCSIRequestSense(int device);
+
+int DoSCSI(int device, const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen)
+{
+    CBW cbw;
+    cbw.Signature = CBW_SIGNATURE;
+    cbw.Tag = 0;
+    cbw.TransferLength = transferLen;
+    cbw.Flags = flags;
+    cbw.LUN = 0;
+    cbw.CBLength = cmdLen;
+    memset(cbw.CB,0,sizeof(cbw.CB));
+    memcpy(cbw.CB,cmd,cmdLen);
+
+    int r;
+    r = USBBulkTransfer(device,0x01,(u8*)&cbw,31);   // Send the command
+    if (r < 0)
+        return r;
+
+    if (data)
+    {
+        r = USBBulkTransfer(device,flags | 1,data,transferLen);
+        if (r < 0)
+            return r;
+    }
+
+    CSW csw;
+    csw.Signature = 0;
+    r = USBBulkTransfer(device,0x81,(u8*)&csw,13);
+    if (r < 0)
+        return r;
+
+    if (csw.Signature != CSW_SIGNATURE)
+        return ERR_BAD_CSW_SIGNATURE;
+
+    // ModeSense?
+    if (csw.Status == 1 && cmd[0] != 3)
+        return SCSIRequestSense(device);
+
+    return csw.Status;
+}
+
+int SCSITestUnitReady(int device)
+{
+    u8 cmd[6];
+    memset(cmd,0,6);
+    return DoSCSI(device,cmd,6,DEVICE_TO_HOST,0,0);
+}
+
+int SCSIRequestSense(int device)
+{
+    u8 cmd[6] = {0x03,0,0,0,18,0};
+    u8 result[18];
+    int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,18);
+    return r;
+}
+
+int SCSIInquiry(int device)
+{
+    u8 cmd[6] = {0x12,0,0,0,36,0};
+    u8 result[36+2];
+    result[36] = '\n';
+    result[37] = 0;
+    int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,36);
+    if (r == 0)
+        printf((const char*)result + 8);
+    return r;
+}
+
+int SCSIReadCapacity(int device, u32* blockCount, u32* blockSize)
+{
+    u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0};
+    u8 result[8];
+    *blockSize = 0;
+    *blockCount = 0;
+    int r = DoSCSI(device,cmd,10,DEVICE_TO_HOST,result,8);
+    if (r == 0)
+    {
+        *blockCount = BE32(result);
+        *blockSize = BE32(result+4);
+    }
+    return r;
+}
+
+int SCSITransfer(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction)
+{
+    //  USB hardware will only do 4k per transfer
+    while (blockCount*blockSize > 4096)
+    {
+        int count = 4096/blockSize;
+        int r = SCSITransfer(device,blockAddr,count,dst,blockSize,direction);
+        dst += count*blockSize;
+        blockAddr += count;
+        blockCount -= count;
+    }
+
+    u8 cmd[10];
+    memset(cmd,0,10);
+    cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
+    BE32(blockAddr,cmd+2);
+    BE16(blockCount,cmd+7);
+    return DoSCSI(device,cmd,10,direction,dst,blockSize*blockCount);
+}
+
+int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize)
+{
+    return SCSIReadCapacity(device,blockCount,blockSize);
+}
+
+int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
+{
+    return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,DEVICE_TO_HOST);
+}
+
+int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
+{
+    return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,HOST_TO_DEVICE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myUSBHost/USBHost.cpp	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,1076 @@
+
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "mbed.h"
+#include "USBHost.h"
+
+//    Config (default uses x bytes)
+#define MAX_DEVICES 8                // Max number of devices
+#define MAX_ENDPOINTS_TOTAL 16        // Max number of endpoints total
+#define MAX_ENDPOINTS_PER_DEVICE 8    // Max number of endpoints for any one device
+
+#define  USBLOG 1
+#if USBLOG
+#define  LOG(...)       printf(__VA_ARGS__)
+#else 
+#define  LOG(...)       do {} while(0)
+#endif
+
+// USB host structures
+
+#define USB_RAM_SIZE 16*1024    // AHB SRAM block 1 TODO MACHINE DEPENDENT
+#define USB_RAM_BASE 0x2007C000
+
+#define TOKEN_SETUP 0
+#define TOKEN_IN  1
+#define TOKEN_OUT 2
+
+//    Status flags from hub
+#define PORT_CONNECTION 0
+#define PORT_ENABLE  1
+#define PORT_SUSPEND  2
+#define PORT_OVER_CURRENT 3
+#define PORT_RESET 4
+#define PORT_POWER 8
+#define PORT_LOW_SPEED 9
+
+#define C_PORT_CONNECTION 16
+#define C_PORT_ENABLE 17
+#define C_PORT_SUSPEND 18
+#define C_PORT_OVER_CURRENT 19
+#define C_PORT_RESET 20
+
+typedef struct {
+    u8 bm_request_type;
+    u8 b_request;
+    u16 w_value;
+    u16 w_index;
+    u16 w_length;
+} Setup;
+
+
+//    Hub stuff is kept private just to keep api simple
+int SetPortFeature(int device, int feature, int index);
+int ClearPortFeature(int device, int feature, int index);
+int SetPortPower(int device, int port);
+int SetPortReset(int device, int port);
+int GetPortStatus(int device, int port, u32* status);
+
+//===================================================================
+//===================================================================
+//    Hardware defines
+
+//    HcControl
+#define PeriodicListEnable    0x00000004
+#define    IsochronousEnable    0x00000008
+#define    ControlListEnable    0x00000010
+#define    BulkListEnable        0x00000020
+#define    OperationalMask        0x00000080
+#define    HostControllerFunctionalState    0x000000C0
+
+//    HcCommandStatus
+#define HostControllerReset    0x00000001
+#define ControlListFilled    0x00000002
+#define BulkListFilled        0x00000004
+
+//    HcInterruptStatus Register
+#define    WritebackDoneHead        0x00000002
+#define    StartofFrame            0x00000004
+#define ResumeDetected            0x00000008
+#define UnrecoverableError        0x00000010
+#define FrameNumberOverflow        0x00000020
+#define RootHubStatusChange        0x00000040
+#define OwnershipChange            0x00000080
+#define MasterInterruptEnable    0x80000000
+
+//    HcRhStatus
+#define SetGlobalPower            0x00010000
+#define DeviceRemoteWakeupEnable    0x00008000
+
+//    HcRhPortStatus (hub 0, port 1)
+#define CurrentConnectStatus    0x00000001
+#define    PortEnableStatus        0x00000002
+#define PortSuspendStatus        0x00000004
+#define PortOverCurrentIndicator    0x00000008
+#define PortResetStatus            0x00000010
+
+#define PortPowerStatus            0x00000100
+#define LowspeedDevice            0x00000200
+#define HighspeedDevice            0x00000400
+
+#define ConnectStatusChange    (CurrentConnectStatus << 16)
+#define PortResetStatusChange    (PortResetStatus << 16)
+
+
+#define  TD_ROUNDING        (u32)0x00040000
+#define  TD_SETUP            (u32)0x00000000
+#define  TD_IN                (u32)0x00100000
+#define  TD_OUT                (u32)0x00080000
+#define  TD_DELAY_INT(x)    (u32)((x) << 21)
+#define  TD_TOGGLE_0        (u32)0x02000000
+#define  TD_TOGGLE_1        (u32)0x03000000
+#define  TD_CC                (u32)0xF0000000
+
+//    HostController EndPoint Descriptor
+typedef struct {
+    volatile u32    Control;
+    volatile u32    TailTd;
+    volatile u32    HeadTd;
+    volatile u32    Next;
+} HCED;
+
+// HostController Transfer Descriptor
+typedef struct {
+    volatile u32    Control;
+    volatile u32    CurrBufPtr;
+    volatile u32    Next;
+    volatile u32    BufEnd;
+} HCTD;
+
+// Host Controller Communication Area
+typedef struct {
+    volatile u32    InterruptTable[32];
+    volatile u16    FrameNumber;
+    volatile u16    FrameNumberPad;
+    volatile u32    DoneHead;
+    volatile u8        Reserved[120];
+} HCCA;
+
+//====================================================================================
+//====================================================================================
+
+class HostController;
+class Endpoint;
+class Device;
+
+//      must be 3*16 bytes long
+class Endpoint
+{
+public:
+    HCED    EndpointDescriptor;    // Pointer to EndpointDescriptor == Pointer to Endpoint
+    HCTD    TDHead;
+
+    enum State
+    {
+        Free,
+        NotQueued,
+        Idle,
+        SetupQueued,
+        DataQueued,
+        StatusQueued,
+        CallbackPending
+    };
+    
+    volatile u8 CurrentState;
+    u8        Flags;            // 0x80 In, 0x03 mask endpoint type
+
+    u16        Length;
+    u8*        Data;
+    USBCallback Callback;     // Must be a multiple of 16 bytes long
+    void*  UserData;
+  
+    int Address()
+    {
+        int ep = (EndpointDescriptor.Control >> 7) & 0xF;
+        if (ep)
+            ep |= Flags & 0x80;
+        return ep;
+    }
+    
+    int Device()
+    {
+        return EndpointDescriptor.Control & 0x7F;
+    }
+
+    int Status()
+    {
+        return (TDHead.Control >> 28) & 0xF;
+    }
+
+    u32 Enqueue(u32 head)
+    {
+        if (CurrentState == NotQueued)
+        {
+            EndpointDescriptor.Next = head;
+            head = (u32)&EndpointDescriptor;
+            CurrentState = Idle;
+        }
+        return head;
+    }
+};
+
+class Device
+{
+public:
+    u8    _endpointMap[MAX_ENDPOINTS_PER_DEVICE*2];
+    u8    Hub;
+    u8    Port;
+    u8    Addr;
+    u8    Pad;
+
+    //    Only if this device is a hub
+    u8    HubPortCount;    // nonzero if this is a hub
+    u8    HubInterruptData;
+    u8    HubMap;
+    u8    HubMask;
+
+    int Flags;        // 1 = Disconnected
+
+    Setup    SetupBuffer;
+
+    // Allocate endpoint zero
+    int Init(DeviceDescriptor* d, int hub, int port, int addr, int lowSpeed)
+    {
+        Hub = hub;
+        Port = port;
+        Addr = addr;
+        Flags = lowSpeed;
+        memset(_endpointMap,0xFF,sizeof(_endpointMap));
+        return 0;
+    }
+
+    int SetEndpointIndex(int ep, int endpointIndex)
+    {
+        for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
+        {
+            if (_endpointMap[i] == 0xFF)    // Add endpoint to map
+            {
+                _endpointMap[i] = ep;
+                _endpointMap[i+1] = endpointIndex;
+                return 0;
+            }
+        }
+        return ERR_ENDPOINT_NONE_LEFT;
+    }
+
+    int GetEndpointIndex(int ep)
+    {
+        for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
+        {
+            if (_endpointMap[i] == ep)
+                return _endpointMap[i+1];
+            if (_endpointMap[i] == 0xFF)
+                break;
+        }
+        return -1;
+    }
+};
+
+class HostController
+{
+public:
+    HCCA        CommunicationArea;
+    Endpoint    Endpoints[MAX_ENDPOINTS_TOTAL];    // Multiple of 16
+    
+    Endpoint    EndpointZero;                        // For device enumeration
+    HCTD        _commonTail;
+    Setup        _setupZero;
+    
+    Device    Devices[MAX_DEVICES];
+    u32    _frameNumber;            // 32 bit ms counter
+
+    u8    _callbacksPending;        //    Endpoints with callbacks are pending, set from ISR via ProcessDoneQueue
+    u8    _rootHubStatusChange;    //    Root hub status has changed, set from ISR
+    u8    _unused0;
+    u8    _unused1;
+
+    u8    _connectPending;    //    Reset has initiated a connect
+    u8    _connectCountdown;    //    Number of ms left after reset before we can connect
+    u8    _connectHub;        //    Will connect on this hub
+    u8    _connectPort;        //    ... and this port
+
+    u8    SRAM[0];            // Start of free SRAM
+
+    void Loop()
+    {
+        u16 elapsed = CommunicationArea.FrameNumber - (u16)_frameNumber;    // extend to 32 bits
+        _frameNumber += elapsed;
+
+        // Do callbacks, if any
+        while (_callbacksPending)
+        {
+            for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
+            {
+                Endpoint* endpoint = Endpoints + i;
+                if (endpoint->CurrentState == Endpoint::CallbackPending)
+                {
+                    _callbacksPending--;
+                    endpoint->CurrentState = Endpoint::Idle;
+                    endpoint->Callback(endpoint->Device(),endpoint->Address(),endpoint->Status(),endpoint->Data,endpoint->Length,endpoint->UserData);
+                }
+            }
+        }
+
+        //    Deal with changes on the root hub
+        if (_rootHubStatusChange)
+        {
+            u32 status = LPC_USB->HcRhPortStatus1;
+            _rootHubStatusChange = 0;
+            if (status >> 16)
+            {
+                HubStatusChange(0,1,status);
+                LPC_USB->HcRhPortStatus1 = status & 0xFFFF0000;    // clear status changes
+            }
+        }
+
+        //    Connect after reset timeout
+        if (_connectCountdown)
+        {
+            if (elapsed >= _connectCountdown)
+            {
+                _connectCountdown = 0;
+                Connect(_connectHub,_connectPort & 0x7F,_connectPort & 0x80);
+            } else
+                _connectCountdown -= elapsed;
+        }
+    }
+
+    //    HubInterrupt - bitmap in dev->HubInterruptData
+    void HubInterrupt(int device)
+    {
+        Device* dev = &Devices[device-1];
+        for (int i = 0; i < dev->HubPortCount; i++)
+        {
+            int port = i+1;
+            if (dev->HubInterruptData & (1 << port))
+            {
+                u32 status = 0;
+                GetPortStatus(device,port,&status);
+                if (status >> 16)
+                {
+                    if (_connectPending && (status & ConnectStatusChange))
+                        continue;    // Don't connect again until previous device has been added and addressed
+
+                    HubStatusChange(device,port,status);
+                    if (status & ConnectStatusChange)
+                        ClearPortFeature(device,C_PORT_CONNECTION,port);
+                    if (status & PortResetStatusChange)
+                        ClearPortFeature(device,C_PORT_RESET,port);
+                }
+            }
+        }
+    }
+
+    static void HubInterruptCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
+    {
+        HostController* controller = (HostController*)userData;
+        if (status == 0)
+            controller->HubInterrupt(device);
+        USBInterruptTransfer(device,endpoint,data,1,HubInterruptCallback,userData);
+    }
+
+    int InitHub(int device)
+    {
+        u8 buf[16];
+        int r= USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_DEVICE,GET_DESCRIPTOR,(DESCRIPTOR_TYPE_HUB << 8),0,buf,sizeof(buf));
+        if (r < 0)
+            return ERR_HUB_INIT_FAILED;
+        
+        //    turn on power on the hubs ports
+        Device* dev = &Devices[device-1];
+        int ports = buf[2];
+        dev->HubPortCount = ports;
+        for (int i = 0; i < ports; i++)
+            SetPortPower(device,i+1);
+        
+        // Enable hub change interrupts
+        return USBInterruptTransfer(device,0x81,&dev->HubInterruptData,1,HubInterruptCallback,this);
+    }
+    
+    int AddEndpoint(int device, int ep, int attributes, int maxPacketSize, int interval)
+    {
+        LOG("AddEndpoint D:%02X A:%02X T:%02X P:%04X I:%02X\n",device,ep,attributes,maxPacketSize,interval);
+        Device* dev = &Devices[device-1];
+        Endpoint* endpoint = AllocateEndpoint(device,ep,attributes,maxPacketSize);
+        if (!endpoint)
+            return ERR_ENDPOINT_NONE_LEFT;
+        dev->SetEndpointIndex(ep,endpoint - Endpoints);
+        endpoint->EndpointDescriptor.Control |= dev->Flags; // Map in slow speed
+        return 0;  // TODO ed->bInterval
+    }
+    
+    int AddEndpoint(int device, EndpointDescriptor* ed)
+    {
+        return AddEndpoint(device,ed->bEndpointAddress,ed->bmAttributes,ed->wMaxPacketSize,ed->bInterval);
+    }
+
+    //      allocate a endpoint
+    Endpoint* AllocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize)
+    {
+        for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
+        {
+            Endpoint* ep = &Endpoints[i];
+            if (ep->CurrentState == 0)
+            {
+                //LOG("Allocated endpoint %d to %02X:%02X\n",i,device,endpointAddress);
+                ep->Flags = (endpointAddress & 0x80) | (type & 3);
+                ep->CurrentState = Endpoint::NotQueued;
+                ep->EndpointDescriptor.Control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device;
+                return ep;
+            }
+        }
+        return 0;
+    }
+
+    Endpoint* GetEndpoint(int device, int ep)
+    {
+        if (device == 0)
+        {
+            //printf("WARNING: USING DEVICE 0\n");
+            return &EndpointZero;
+        }
+        if (device > MAX_DEVICES)
+            return 0;
+        int i = Devices[device-1].GetEndpointIndex(ep);
+        if (i == -1)
+            return 0;
+        return Endpoints + i;
+    }
+
+    int Transfer(Endpoint* endpoint, int token, u8* data, int len, int state)
+    {
+        //LOG("Transfer %02X T:%d Len:%d S:%d\n",endpoint->Address(),token,len,state);
+    
+        int toggle = 0;
+        if (endpoint->Address() == 0)
+            toggle = (token == TOKEN_SETUP) ? TD_TOGGLE_0 : TD_TOGGLE_1;
+
+        if (token != TOKEN_SETUP)
+            token = (token == TOKEN_IN ? TD_IN : TD_OUT);
+
+        HCTD* head = &endpoint->TDHead;
+        HCTD* tail = &_commonTail;
+
+        head->Control = TD_ROUNDING | token | TD_DELAY_INT(0) | toggle | TD_CC; 
+        head->CurrBufPtr = (u32)data;
+        head->BufEnd = (u32)(data + len - 1);
+        head->Next = (u32)tail;
+
+        HCED* ed = &endpoint->EndpointDescriptor;
+        ed->HeadTd = (u32)head | (ed->HeadTd & 0x00000002);    // carry toggle
+        ed->TailTd = (u32)tail;
+        
+        //HCTD* td = head;
+        //LOG("%04X TD %08X %08X %08X Next:%08X\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next);
+        //LOG("%04X ED %08X %08X %08X\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd);
+        
+        switch (endpoint->Flags & 3)
+        {
+            case ENDPOINT_CONTROL:
+                LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED);    // May change state NotQueued->Idle
+                endpoint->CurrentState = state;                                               // Get in before an int
+                LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | ControlListFilled;
+                LPC_USB->HcControl = LPC_USB->HcControl | ControlListEnable;
+                break;
+
+            case ENDPOINT_BULK:
+                LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED);
+                endpoint->CurrentState = state;
+                LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled;
+                LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable;
+                break;
+
+            case ENDPOINT_INTERRUPT:
+                CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]);
+                endpoint->CurrentState = state;
+                LPC_USB->HcControl |= PeriodicListEnable;
+                break;
+        }
+        return 0;
+    }
+    
+    //    Remove an endpoint from an active queue
+    bool Remove(HCED* ed, volatile HCED** queue)
+    {
+        if (*queue == 0)
+            return false;
+        if (*queue == (volatile HCED*)ed)
+        {
+            *queue = (volatile HCED*)ed->Next;    // At head of queue
+            return true;
+        }
+
+        volatile HCED* head = *queue;
+        while (head)
+        {
+            if (head->Next == (u32)ed)
+            {
+                head->Next = ed->Next;
+                return true;
+            }
+            head = (volatile HCED*)head->Next;
+        }
+        return false;
+    }
+
+    void Release(Endpoint* endpoint)
+    {
+        if (endpoint->CurrentState == Endpoint::NotQueued)
+        {
+            // Never event used it, nothing to do
+        }
+        else
+        {
+            HCED* ed = (HCED*)endpoint;
+            ed->Control |= 0x4000;    // SKIP
+            switch (endpoint->Flags & 0x03)
+            {
+                case ENDPOINT_CONTROL:
+                    Remove(ed,(volatile HCED**)&LPC_USB->HcControlHeadED);
+                    break;
+                case ENDPOINT_BULK:
+                    Remove(ed,(volatile HCED**)&LPC_USB->HcBulkHeadED);
+                    break;
+                case ENDPOINT_INTERRUPT:
+                    for (int i = 0; i < 32; i++)
+                        Remove(ed,(volatile HCED**)&CommunicationArea.InterruptTable[i]);
+                    break;
+            }
+
+            u16 fn = CommunicationArea.FrameNumber;
+            while (fn == CommunicationArea.FrameNumber)
+                ;    // Wait for next frame
+
+        }
+
+        //    In theory, the endpoint is now dead.
+        //    TODO: Will Callbacks ever be pending? BUGBUG
+        memset(endpoint,0,sizeof(Endpoint));
+    }
+
+    //      Pop the last TD from the list
+    HCTD* Reverse(HCTD* current) 
+    { 
+        HCTD *result = NULL,*temp; 
+        while (current) 
+        { 
+            temp = (HCTD*)current->Next; 
+            current->Next = (u32)result;
+            result = current;
+            current = temp;
+        }
+        return result;
+    }
+
+    //      Called from interrupt...
+    //      Control endpoints use a state machine to progress through the transfers
+    void ProcessDoneQueue(u32 tdList)
+    {
+        HCTD* list = Reverse((HCTD*)tdList);
+        while (list)
+        {
+            Endpoint* endpoint = (Endpoint*)(list-1);
+            list = (HCTD*)list->Next;
+            int ep = endpoint->Address();
+            bool in = endpoint->Flags & 0x80;
+            int status = (endpoint->TDHead.Control >> 28) & 0xF;
+
+            //LOG("ProcessDoneQueue %02X %08X\n",ep,endpoint->TDHead.Control);
+
+            if (status != 0)
+            {
+                LOG("ProcessDoneQueue status %02X %d\n",ep,status);
+                endpoint->CurrentState = Endpoint::Idle;
+            } else {
+                switch (endpoint->CurrentState)
+                {
+                    case Endpoint::SetupQueued:
+                        if (endpoint->Length == 0)
+                            Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Skip Data Phase
+                        else
+                            Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued);    // Setup is done, now Data
+                        break;
+
+                    case Endpoint::DataQueued:
+                        if (endpoint->TDHead.CurrBufPtr)
+                            endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data;
+
+                        if (ep == 0)
+                            Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Data is done, now Status, Control only
+                        else
+                            endpoint->CurrentState = Endpoint::Idle;
+                        break;
+
+                    case Endpoint::StatusQueued:    // Transaction is done
+                        endpoint->CurrentState = Endpoint::Idle;
+                        break;
+                }
+            }
+
+            //      Complete, flag if we need a callback
+            if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle)
+            {
+                endpoint->CurrentState = Endpoint::CallbackPending;
+                _callbacksPending++;
+            }
+        }
+    }
+
+    //    Hack to reset devices that don't want to connect
+    int AddDevice(int hub, int port, bool isLowSpeed)
+    {
+        int device = AddDeviceCore(hub,port,isLowSpeed);
+        if (device < 0)
+        {
+            LOG("========RETRY ADD DEVICE========\n");    // This will go for ever.. TODO power cycle root?
+            Disconnect(hub,port);    // Could not read descriptor at assigned address, reset this port and try again
+            ResetPort(hub,port);    // Cheap bluetooth dongles often need this on a hotplug
+            return -1;
+        }
+        return device;
+    }
+
+    int AddDeviceCore(int hub, int port, bool isLowSpeed)
+    {
+        int lowSpeed = isLowSpeed ? 0x2000 : 0;
+        DeviceDescriptor desc;
+        EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed;               // MaxPacketSize == 8
+        int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8);
+        if (r < 0)
+        {
+            LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\n");
+            return r;
+        }
+
+        EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed;     // Actual MaxPacketSize
+        r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
+        if (r < 0)
+            return r;
+
+        LOG("\nClass %02X found %04X:%04X\n\n",desc.bDeviceClass,desc.idVendor,desc.idProduct);
+
+        //      Now assign the device an address, move off EndpointZero
+        int device = 0;
+        for (int i = 0; i < MAX_DEVICES; i++)
+        {
+            if (Devices[i].Port == 0)
+            {
+                device = i+1;
+                break;
+            }
+        }
+        if (!device)
+            return ERR_DEVICE_NONE_LEFT;
+
+        r = SetAddress(0,device);
+        if (r)
+            return r;
+        DelayMS(2);
+        
+        // Now at a nonzero address, create control endpoint
+        Device* dev = &Devices[device-1];
+        dev->Init(&desc,hub,port,device,lowSpeed);
+        AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0);
+        _connectPending = 0;
+
+        //    Verify this all works
+        r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
+        if (r < 0)
+            return r;
+
+        //    Set to interface 0 by default
+        //    Calls LoadDevice if interface is found
+        r = SetConfigurationAndInterface(device,1,0,&desc);
+
+        if (desc.bDeviceClass == CLASS_HUB)
+            InitHub(device);            // Handle hubs in this code
+
+        return device;
+    }
+
+    // Walk descriptors and create endpoints for a given device
+    // TODO configuration !=1, alternate settings etc.
+    int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc)
+    {
+        u8 buffer[255];
+        int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,sizeof(buffer));
+        if (err < 0)
+            return err;
+
+        err = SetConfiguration(device,configuration);
+        if (err < 0)
+            return err;
+
+        //    Add the endpoints for this interface
+        int len = buffer[2] | (buffer[3] << 8);
+        u8* d = buffer;
+        u8* end = d + len;
+        InterfaceDescriptor* found = 0;
+//        for (int i = 0; i < len; i++) printf(" %02X ", *(d+i)); printf("\n"); 
+        while (d < end)
+        {
+            if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
+            {
+                InterfaceDescriptor* id = (InterfaceDescriptor*)d;
+                if (id->bInterfaceNumber == interfaceNumber)
+                {
+                    found = id;
+                    d += d[0];
+                    while (d < end && d[1] != DESCRIPTOR_TYPE_CONFIGURATION)//changed by AvdW: was INTERFACE
+                    {
+                        switch (d[1])
+                        {
+                            case DESCRIPTOR_TYPE_ENDPOINT:
+                                AddEndpoint(device,(EndpointDescriptor*)d);
+                                break;
+                            case DESCRIPTOR_TYPE_INTERFACE:
+                                LOG("Parsing interface %d descriptor (%d bytes)\n",d[2],d[0]);
+                                break;
+                            default:
+                                LOG("Skipping descriptor %02X (%d bytes)\n",d[1],d[0]);
+                        }
+                        d += d[0];
+                    }
+                }
+            }
+            d += d[0];
+        }
+
+        if (!found)
+            return ERR_INTERFACE_NOT_FOUND;
+        OnLoadDevice(device,desc,found);
+        return 0;
+    }
+
+    void Init()
+    {
+        LOG("USB INIT (Controller is %d bytes)\n",sizeof(*this));
+        memset(this,0,sizeof(HostController));
+        EndpointZero.CurrentState = Endpoint::NotQueued;
+        HWInit(&CommunicationArea);
+        DelayMS(10);
+    }
+
+    void ResetPort(int hub, int port)
+    {
+        LOG("ResetPort Hub:%d Port:%d\n",hub,port);
+        _connectPending++;            // Only reset/add 1 device at a time
+        if (hub == 0)
+            LPC_USB->HcRhPortStatus1 = PortResetStatus;    // Reset Root Hub, port 1
+        else
+            SetPortReset(hub,port);    // or reset other hub
+    }
+
+    void Disconnect(int hub, int port)
+    {
+        LOG("Disconnect Hub:%d Port:%d\n",hub,port);    // Mark a device for destruction
+        for (int i = 0; i < MAX_DEVICES; i++)
+        {
+            Device* dev = Devices + i;
+            if (dev->Port == port && dev->Hub == hub)
+            {
+                //    Disconnect everything that is attached to this device if it is a hub
+                for (int p = 0; p < dev->HubPortCount; p++)
+                    Disconnect(i+1,p+1);
+
+                //    Now release endpoints
+                for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2)
+                {
+                    u8 endpointIndex = dev->_endpointMap[j];
+                    if (endpointIndex != 0xFF)
+                        Release(Endpoints + endpointIndex);
+                }
+                dev->Port = 0;    // Device is now free
+                dev->Flags = 0;
+                return;
+            }
+        }
+    }
+
+    // called after reset
+    void Connect(int hub, int port, bool lowspeed)
+    {
+        LOG("Connect Hub:%d Port:%d %s\n",hub,port,lowspeed ? "slow" : "full");
+        AddDevice(hub,port,lowspeed);
+    }
+
+    // Called from interrupt
+    void HubStatusChange(int hub, int port, u32 status)
+    {
+        LOG("HubStatusChange Hub:%d Port:%d %08X\n",hub,port,status);
+        if (status & ConnectStatusChange)
+        {
+            if (status & CurrentConnectStatus)    // Connecting
+                ResetPort(hub,port);            // Reset to initiate connect (state machine?)
+            else
+                Disconnect(hub,port);
+        }
+
+        if (status & PortResetStatusChange)
+        {
+            if (!(status & PortResetStatus))
+            {
+                _connectCountdown = 200;        // Schedule a connection in 200ms
+                if (status & LowspeedDevice)
+                    port |= 0x80;
+                _connectHub = hub;
+                _connectPort = port;
+            }
+        }
+    }
+
+    #define HOST_CLK_EN        (1<<0)
+    #define PORTSEL_CLK_EN    (1<<3)
+    #define AHB_CLK_EN        (1<<4)
+    #define CLOCK_MASK        (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
+
+    #define  FRAMEINTERVAL        (12000-1)    // 1ms
+    #define  DEFAULT_FMINTERVAL    ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL)
+
+    void DelayMS(int ms)
+    {
+        u16 f = ms + CommunicationArea.FrameNumber;
+        while (f != CommunicationArea.FrameNumber)
+            ;
+    }
+
+    static void HWInit(HCCA* cca)
+    {
+        NVIC_DisableIRQ(USB_IRQn);
+        
+        // turn on power for USB
+        LPC_SC->PCONP        |= (1UL<<31);
+        // Enable USB host clock, port selection and AHB clock
+        LPC_USB->USBClkCtrl |= CLOCK_MASK;
+        // Wait for clocks to become available
+        while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
+            ;
+        
+        //    We are a Host
+        LPC_USB->OTGStCtrl |= 1;
+        LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;                // we don't need port selection clock until we do OTG
+        
+        // configure USB pins
+        LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28));    
+        LPC_PINCON->PINSEL1 |=    ((1<<26)|(1<<28));            // USB D+/D-
+            
+        LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22));        // USB_PPWR, USB_OVRCR
+        LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22));
+        
+        LPC_PINCON->PINSEL4 &= ~(3 << 18);                    // USB_CONNECT
+        LPC_PINCON->PINSEL4 |= (1 << 18);
+
+        //    Reset OHCI block
+        LPC_USB->HcControl         = 0;
+        LPC_USB->HcControlHeadED = 0;
+        LPC_USB->HcBulkHeadED     = 0;
+        
+        LPC_USB->HcCommandStatus = HostControllerReset;
+        LPC_USB->HcFmInterval     = DEFAULT_FMINTERVAL;
+        LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100;
+
+        LPC_USB->HcControl    = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask;
+        LPC_USB->HcRhStatus = SetGlobalPower;
+        
+        LPC_USB->HcHCCA = (u32)cca;
+        LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
+        LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow;
+
+        NVIC_SetPriority(USB_IRQn, 0);
+        NVIC_EnableIRQ(USB_IRQn);
+        while (cca->FrameNumber < 10)
+            ;    // 10ms delay before diving in
+    }
+};
+
+//====================================================================================
+//====================================================================================
+//      Host controller instance and Interrupt handler
+
+static HostController _controller __attribute__((at(USB_RAM_BASE)));
+
+extern "C" void USB_IRQHandler(void) __irq;
+void USB_IRQHandler (void) __irq
+{
+    u32 int_status = LPC_USB->HcInterruptStatus;
+
+    if (int_status & RootHubStatusChange)    //    Root hub status change
+        _controller._rootHubStatusChange++;    //    Just flag the controller, will be processed in USBLoop
+
+    u32 head = 0;
+    if (int_status & WritebackDoneHead)
+    {
+        head = _controller.CommunicationArea.DoneHead;        // Writeback Done
+        _controller.CommunicationArea.DoneHead = 0;
+    }             
+    LPC_USB->HcInterruptStatus = int_status;
+
+    if (head)
+       _controller.ProcessDoneQueue(head);     // TODO - low bit can be set BUGBUG
+}
+
+//====================================================================================
+//====================================================================================
+//      API Methods
+
+void USBInit()
+{
+    return _controller.Init();
+}
+
+void USBLoop()
+{
+    return _controller.Loop();
+}
+
+u8* USBGetBuffer(u32* len)
+{
+    *len = USB_RAM_SIZE - sizeof(HostController);
+    return _controller.SRAM;
+}
+
+static Setup* GetSetup(int device)
+{
+    if (device == 0)
+        return &_controller._setupZero;
+    
+    if (device < 1 || device > MAX_DEVICES)
+        return 0;
+    return &_controller.Devices[device-1].SetupBuffer;
+}
+
+//    Loop until IO on endpoint is complete
+static int WaitIODone(Endpoint* endpoint)
+{
+    if (endpoint->CurrentState == Endpoint::NotQueued)
+        return 0;
+    while (endpoint->CurrentState != Endpoint::Idle)
+        USBLoop();    // May generate callbacks, mount or unmount devices etc
+    int status = endpoint->Status();
+    if (status == 0)
+        return endpoint->Length;
+    return -status;
+}
+
+int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData)
+{
+    Endpoint* endpoint = _controller.GetEndpoint(device,ep);
+    if (!endpoint)
+        return ERR_ENDPOINT_NOT_FOUND;
+        
+    WaitIODone(endpoint);
+    endpoint->Flags = flags;
+    endpoint->Data = data;
+    endpoint->Length = length;
+    endpoint->Callback = callback;
+    endpoint->UserData = userData;
+    if (ep == 0)
+        _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued);
+    else
+        _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued);
+    if (callback)
+        return IO_PENDING;
+    return WaitIODone(endpoint);
+}
+
+int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData)
+{
+    Setup* setup = GetSetup(device);
+    if (!setup)
+        return ERR_DEVICE_NOT_FOUND;
+        
+    // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call
+    WaitIODone(_controller.GetEndpoint(device,0));
+    
+    setup->bm_request_type = request_type;
+    setup->b_request = request;
+    setup->w_value = value;
+    setup->w_index = index;
+    setup->w_length = length;
+    return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData);
+}
+
+int  USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
+{
+    return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData);
+}
+
+int  USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
+{
+    return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData);
+}
+
+int GetDescriptor(int device, int descType,int descIndex, u8* data, int length)
+{
+    return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0);
+}
+
+int GetString(int device, int index, char* dst, int length)
+{
+    u8 buffer[255];
+    int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer));
+    if (le < 0)
+        return le;
+    if (length < 1)
+        return -1;
+    length <<= 1;
+    if (le > length)
+        le = length;
+    for (int j = 2; j < le; j += 2)
+        *dst++ = buffer[j];
+    *dst = 0;
+    return (le>>1)-1;
+}
+
+int SetAddress(int device, int new_addr)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0);
+}
+
+int SetConfiguration(int device, int configNum)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0);
+}
+
+int SetInterface(int device, int ifNum, int altNum)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0);
+}
+
+//    HUB stuff
+int SetPortFeature(int device, int feature, int index)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0);
+}
+
+int ClearPortFeature(int device, int feature, int index)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0);
+}
+
+int SetPortPower(int device, int port)
+{
+    int r = SetPortFeature(device,PORT_POWER,port);
+    _controller.DelayMS(20);    // 80ms to turn on a hubs power... DESCRIPTOR? todo
+    return r;
+}
+
+int SetPortReset(int device, int port)
+{
+    return SetPortFeature(device,PORT_RESET,port);
+}
+
+int GetPortStatus(int device, int port, u32* status)
+{
+    return USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,GET_STATUS,0,port,(u8*)status,4);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/myUSBHost/USBHost.h	Wed Jun 15 19:12:25 2011 +0000
@@ -0,0 +1,200 @@
+
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef USBHOST_H
+#define USBHOST_H
+
+#ifndef u8
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+
+typedef char s8;
+typedef short s16;
+typedef char s32;
+#endif
+
+#define ENDPOINT_CONTROL 0
+#define ENDPOINT_ISOCRONOUS 1
+#define ENDPOINT_BULK 2
+#define ENDPOINT_INTERRUPT 3
+
+#define  DESCRIPTOR_TYPE_DEVICE            1
+#define  DESCRIPTOR_TYPE_CONFIGURATION    2
+#define  DESCRIPTOR_TYPE_STRING            3
+#define  DESCRIPTOR_TYPE_INTERFACE        4
+#define  DESCRIPTOR_TYPE_ENDPOINT        5
+
+#define DESCRIPTOR_TYPE_HID         0x21
+#define DESCRIPTOR_TYPE_REPORT      0x22
+#define DESCRIPTOR_TYPE_PHYSICAL    0x23
+#define DESCRIPTOR_TYPE_HUB         0x29
+
+enum USB_CLASS_CODE
+{
+    CLASS_DEVICE,
+    CLASS_AUDIO,
+    CLASS_COMM_AND_CDC_CONTROL,
+    CLASS_HID,
+    CLASS_PHYSICAL = 0x05,
+    CLASS_STILL_IMAGING,
+    CLASS_PRINTER,
+    CLASS_MASS_STORAGE,
+    CLASS_HUB,
+    CLASS_CDC_DATA,
+    CLASS_SMART_CARD,
+    CLASS_CONTENT_SECURITY = 0x0D,
+    CLASS_VIDEO = 0x0E,
+    CLASS_DIAGNOSTIC_DEVICE = 0xDC,
+    CLASS_WIRELESS_CONTROLLER = 0xE0,
+    CLASS_MISCELLANEOUS = 0xEF,
+    CLASS_APP_SPECIFIC = 0xFE,
+    CLASS_VENDOR_SPECIFIC = 0xFF
+};
+
+#define  DEVICE_TO_HOST         0x80
+#define  HOST_TO_DEVICE         0x00
+#define  REQUEST_TYPE_CLASS     0x20
+#define  RECIPIENT_DEVICE       0x00
+#define  RECIPIENT_INTERFACE    0x01
+#define  RECIPIENT_ENDPOINT        0x02
+#define  RECIPIENT_OTHER        0x03
+
+#define  GET_STATUS                0
+#define  CLEAR_FEATURE            1
+#define  SET_FEATURE            3
+#define  SET_ADDRESS            5
+#define  GET_DESCRIPTOR            6
+#define  SET_DESCRIPTOR            7
+#define  GET_CONFIGURATION        8
+#define  SET_CONFIGURATION        9
+#define  GET_INTERFACE            10
+#define  SET_INTERFACE            11
+#define  SYNCH_FRAME            11
+
+//        -5 is nak
+/*
+0010 ACK Handshake
+1010 NAK Handshake
+1110 STALL Handshake
+0110 NYET (No Response Yet)
+*/
+
+#define IO_PENDING -100
+#define ERR_ENDPOINT_NONE_LEFT -101
+#define ERR_ENDPOINT_NOT_FOUND -102
+#define ERR_DEVICE_NOT_FOUND -103
+#define ERR_DEVICE_NONE_LEFT -104
+#define ERR_HUB_INIT_FAILED -105
+#define ERR_INTERFACE_NOT_FOUND -106
+
+typedef struct
+{
+    u8    bLength;
+    u8    bDescriptorType;
+    u16 bcdUSB;
+    u8 bDeviceClass;
+    u8 bDeviceSubClass;
+    u8 bDeviceProtocol;
+    u8 bMaxPacketSize;
+    u16 idVendor;
+    u16 idProduct;
+    u16 bcdDevice;    // version
+    u8 iManufacturer;
+    u8 iProduct;
+    u8 iSerialNumber;
+    u8 bNumConfigurations;
+} DeviceDescriptor;    // 16 bytes
+
+typedef struct
+{
+    u8    bLength;
+    u8    bDescriptorType;
+    u16    wTotalLength;
+    u8    bNumInterfaces;
+    u8    bConfigurationValue;    // Value to use as an argument to select this configuration
+    u8    iConfiguration;            // Index of String Descriptor describing this configuration
+    u8    bmAttributes;            // Bitmap D7 Reserved, set to 1. (USB 1.0 Bus Powered),D6 Self Powered,D5 Remote Wakeup,D4..0 = 0
+    u8    bMaxPower;                // Maximum Power Consumption in 2mA units
+} ConfigurationDescriptor;
+
+typedef struct
+{
+    u8    bLength;
+    u8    bDescriptorType;
+    u8  bInterfaceNumber;
+    u8    bAlternateSetting;
+    u8    bNumEndpoints;
+    u8    bInterfaceClass;
+    u8    bInterfaceSubClass;
+    u8    bInterfaceProtocol;
+    u8    iInterface;                // Index of String Descriptor Describing this interface
+} InterfaceDescriptor;
+
+typedef struct
+{
+    u8    bLength;
+    u8    bDescriptorType;
+    u8    bEndpointAddress;    // Bits 0:3 endpoint, Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
+    u8    bmAttributes;        // Bits 0:1 00 = Control, 01 = Isochronous, 10 = Bulk, 11 = Interrupt
+    u16 wMaxPacketSize;
+    u8    bInterval;            // Interval for polling endpoint data transfers.
+} EndpointDescriptor;
+
+typedef struct {
+  u8    bLength;
+  u8    bDescriptorType;
+  u16   bcdHID;
+  u8    bCountryCode;
+  u8    bNumDescriptors;
+  u8    bDescriptorType2;
+  u16   wDescriptorLength;
+} HIDDescriptor;
+
+//============================================================================
+//============================================================================
+
+
+void USBInit();
+void USBLoop();
+u8* USBGetBuffer(u32* len);
+
+//    Optional callback for transfers, called at interrupt time
+typedef void (*USBCallback)(int device, int endpoint, int status, u8* data, int len, void* userData);
+
+//    Transfers
+int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback = 0, void* userData = 0);
+int USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback = 0, void* userData = 0);
+int USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback = 0, void* userData = 0);
+
+//    Standard Device methods
+int GetDescriptor(int device, int descType, int descIndex, u8* data, int length);
+int GetString(int device, int index, char* dst, int length);
+int SetAddress(int device, int new_addr);
+int SetConfiguration(int device, int configNum);
+int SetInterface(int device, int ifNum, int altNum);
+
+//    Implemented to notify app of the arrival of a device
+void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc);
+
+#endif
\ No newline at end of file