うおーるぼっと用プログラム Wiiリモコンからのダイレクト操作モードのみ BlueUSBをベースに使用しています。

Dependencies:   BD6211F mbed SimpleFilter

Files at this revision

API Documentation at this revision

Comitter:
jksoft
Date:
Fri Apr 29 15:50:23 2011 +0000
Commit message:

Changed in this revision

BD6211F.lib Show annotated file Show diff for this revision Revisions of this file
BlueUSB/AutoEvents.cpp Show annotated file Show diff for this revision Revisions of this file
BlueUSB/FATFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
BlueUSB/L2CAP.cpp Show annotated file Show diff for this revision Revisions of this file
BlueUSB/MassStorage.cpp Show annotated file Show diff for this revision Revisions of this file
BlueUSB/Socket.cpp Show annotated file Show diff for this revision Revisions of this file
BlueUSB/Socket.h Show annotated file Show diff for this revision Revisions of this file
BlueUSB/TestShell.cpp Show annotated file Show diff for this revision Revisions of this file
BlueUSB/USBHost.cpp Show annotated file Show diff for this revision Revisions of this file
BlueUSB/USBHost.h Show annotated file Show diff for this revision Revisions of this file
BlueUSB/Utils.cpp Show annotated file Show diff for this revision Revisions of this file
BlueUSB/Utils.h Show annotated file Show diff for this revision Revisions of this file
BlueUSB/hci.cpp Show annotated file Show diff for this revision Revisions of this file
BlueUSB/hci.h Show annotated file Show diff for this revision Revisions of this file
BlueUSB/hci_private.h Show annotated file Show diff for this revision Revisions of this file
PowerControl/EthernetPowerControl.cpp Show annotated file Show diff for this revision Revisions of this file
PowerControl/EthernetPowerControl.h Show annotated file Show diff for this revision Revisions of this file
PowerControl/PowerControl.h Show annotated file Show diff for this revision Revisions of this file
SimpleFilter.lib Show annotated file Show diff for this revision Revisions of this file
Wiimote/Wiimote.cpp Show annotated file Show diff for this revision Revisions of this file
Wiimote/Wiimote.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.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 4f749f62c6d7 BD6211F.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BD6211F.lib	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/jksoft/code/BD6211F/#e27bf165308f
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/AutoEvents.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/AutoEvents.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,161 @@
+
+/*
+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"
+
+#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)
+
+u8 auto_mouse[4];       // buttons,dx,dy,scroll
+u8 auto_keyboard[8];    // modifiers,reserved,keycode1..keycode6
+u8 auto_joystick[4];    // x,y,buttons,throttle
+
+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;
+        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;
+        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;
+            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);
+
+//  Implemented in TestShell.cpp
+int OnBluetoothInsert(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);
+    }
+    
+    switch (interfaceDesc->bInterfaceClass)
+    {
+        case CLASS_MASS_STORAGE:
+            if (interfaceDesc->bInterfaceSubClass == 0x06 && interfaceDesc->bInterfaceProtocol == 0x50)
+                OnDiskInsert(device);    // it's SCSI!
+            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
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/FATFileSystem.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/FATFileSystem.lib	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_unsupported/code/fatfilesystem/
\ No newline at end of file
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/L2CAP.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/L2CAP.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,274 @@
+/*
+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"
+
+#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
+
+
+ /* 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";
+ }
+
+typedef struct
+{
+    u16    handle;
+    u16    length;            // total
+    u16    l2capLength;    // length -4
+    u16    cid;            // Signaling packet CID = 1
+    u8  data[64];       // Largest thing to send!!! todo
+} L2CAPData;
+
+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;
+
+//
+void BTDevice::Init()
+{
+    memset(&_info,0,sizeof(inquiry_info));
+    _handle = 0;
+    _name[0] = 0;
+    _state = 0;
+}
+
+// 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);
+    return sock->ID;
+}
+
+// virtual SocketHandler
+int BTDevice::Send(SocketInternal* sock, const u8* data, int len)
+{
+    L2CAPData d;
+    L2CAPSocket* s = (L2CAPSocket*)sock;
+
+    d.handle = _handle | 0x2000;
+    d.length = 4 + len;
+    d.l2capLength = len;
+    d.cid = s->dcid;
+
+    if (len > 64)
+        return -1;
+    memcpy(d.data,data,len);
+    return Send((u8*)&d,len+8);
+}
+
+// virtual SocketHandler
+int BTDevice::Close(SocketInternal* sock)
+{
+    printf("L2CAP close %d\n",sock->ID);
+    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)
+{
+     _transport->ACLSend(data,len);
+     return 0;
+}
+
+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];
+    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] = 0x02A0;  // 672
+    return Send(L2CAP_CONF_REQ,_txid++,p,4);
+}
+
+int BTDevice::ConfigureResponse(u8 rxid, int dcid)
+{
+    u16 p[3];
+    p[0] = dcid;
+    p[1] = 0;
+    p[2] = 0;
+    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 BTDevice::Control(const u8* data, int len)
+{
+    int cc = data[8];
+    printf(L2CAP_ComandCodeStr(cc));
+    int result = LE16(data+16);
+    printf(" Result %d\n",result);
+    switch (cc)
+    {
+        case L2CAP_COMMAND_REJ:
+           break;
+        case L2CAP_CONN_REQ:
+            break;
+
+        // Response to our initial connect from Remote
+        case L2CAP_CONN_RSP:
+            {
+                if (result == 0)
+                {
+                    int dcid = LE16(data+12);
+                    int scid = LE16(data+14);
+                    L2CAPSocket* s = SCIDToSocket(scid);
+                    if (s)
+                    {
+                        s->dcid = dcid;
+                        ConfigureRequest(dcid);
+                    }
+                } else
+                    printf("Connect failed?\n");
+            }
+            break;
+
+        case L2CAP_CONF_RSP:
+            {
+                int scid = LE16(data+12);
+                SocketInternal* s = (SocketInternal*)SCIDToSocket(scid);
+                if (s)
+                    s->SetState(SocketState_Open);
+            }
+            break;
+
+        case L2CAP_CONF_REQ:
+            {
+                int scid = LE16(data+12);
+                L2CAPSocket* s = SCIDToSocket(scid);
+                if (s)
+                    ConfigureResponse(data[9],s->dcid);
+            }
+            break;
+    }
+}
+
+void BTDevice::ACLRecv(const u8* data, int len)
+{
+   // printfBytes("L2CP",data,16);
+    int handle = LE16(data);
+    if (handle != (0x2000 | _handle))
+        return;
+
+    int cid = LE16(data+6);
+    if (cid == 1)
+    {
+        Control(data,len);
+        return;
+    }
+
+    SocketInternal* s = (SocketInternal*)SCIDToSocket(cid);
+    if (s)
+        s->Recv(data+8,LE16(data+2)-4);
+    else
+        printf("Bad event cid %d\n",cid);
+}
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/MassStorage.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/MassStorage.cpp	Fri Apr 29 15:50:23 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);
+}
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/Socket.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/Socket.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,140 @@
+/*
+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 3
+#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 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;
+                return h->Open(si,addr);
+            }
+        }
+        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;
+        return GetHandler(si->Type)->Send(si,data,len);
+    }
+
+    int Close(int socket)
+    {
+        SocketInternal* si = GetInternal(socket);
+        if (!si || si->ID != socket)
+            return ERR_SOCKET_NOT_FOUND;
+        si->ID = 0;
+        return GetHandler(si->Type)->Close(si);
+    }
+};
+
+SocketManager gSocketManager;
+
+int Socket_Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData)
+{
+    return gSocketManager.Open(type,addr,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);
+}
+
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/Socket.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/Socket.h	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,96 @@
+/*
+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
+
+typedef struct
+{
+    u8  AddressSpecific[0]; // BDADDR,psm etc
+} SocketAddrHdr;
+
+enum SocketState
+{
+    SocketState_Unknown,
+    SocketState_Opening,
+    SocketState_Open,
+    SocketState_Closing,
+    SocketState_Closed
+};
+
+typedef void (*SocketCallback)(int socket, SocketState state, const u8* data, int len, void* userData);
+
+int Socket_Open(int type, SocketAddrHdr* addr, SocketCallback callback, void* userData);   // Open a socket
+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);
+    }
+};
+
+class SocketHandler
+{
+    public:
+    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;
+};
+
+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
+
+#endif // SOCKET_H_INCLUDED
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/TestShell.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/TestShell.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,411 @@
+
+/*
+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 "USBHost.h"
+#include "hci.h"
+
+extern int wall_bot_remote(char *c,int stat);
+
+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]);
+}
+
+#define MAX_HCL_SIZE 260
+#define MAX_ACL_SIZE 400
+
+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;
+        if (t)
+            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;
+        if (t)
+            t->ACLRecv(data,len);
+        USBBulkTransfer(device,0x82,data,MAX_ACL_SIZE,AclCallback,userData);
+    }
+
+    virtual void HCISend(const u8* data, int len)
+    {
+        USBControlTransfer(_device,REQUEST_TYPE_CLASS, 0, 0, 0,(u8*)data,len);
+    }
+
+    virtual void ACLSend(const u8* data, int len)
+    {
+        USBBulkTransfer(_device,0x02,(u8*)data,len);
+    }
+};
+
+
+#define WII_REMOTE 0x042500
+
+class HIDBluetooth
+{
+    int _control;   // Sockets for control (out) and interrupt (in)
+    int _interrupt;
+    int _devClass;
+    BD_ADDR _addr;
+    u8  _pad[2];    // Struct align
+    
+public:
+    HIDBluetooth() : _control(0),_interrupt(0),_devClass(0) {};
+
+    bool InUse()
+    {
+        return _control != 0;
+    }
+
+    static void OnHidInterrupt(int socket, SocketState state, const u8* data, int len, void* userData)
+    {
+        HIDBluetooth* t = (HIDBluetooth*)userData;
+        int stat = 0x10;
+        static int old_stat;
+        
+        if (data)
+        {
+            if (t->_devClass == WII_REMOTE && data[1] == 0x30)
+            {
+                printf("================wii====================\n");
+                t->Led(stat);
+                t->Hid();   // ask for accelerometer
+                t->_devClass = 0;
+            }
+
+            const u8* d = data;
+            switch (d[1])
+            {
+                case 0x02:
+                {
+                    int x = (signed char)d[3];
+                    int y = (signed char)d[4];
+                    printf("Mouse %2X dx:%d dy:%d\n",d[2],x,y);
+                }
+                break;
+
+                case 0x37: // Accelerometer http://wiki.wiimoteproject.com/Reports
+                {
+#if 0
+                    int pad = (d[2] & 0x9F) | ((d[3] & 0x9F) << 8);
+                    int x = (d[2] & 0x60) >> 5 | d[4] << 2;
+                    int y = (d[3] & 0x20) >> 4 | d[5] << 2;
+                    int z = (d[3] & 0x40) >> 5 | d[6] << 2;
+                    printf("WII %04X %d %d %d\n",pad,x,y,z);
+#else
+                    old_stat = stat;
+                    stat = wall_bot_remote( (char*)&d[2] , stat );
+                    
+                    if( old_stat != stat )
+                    {
+                        t->Led(stat);
+                    }
+#endif
+                }
+                break;
+                default:
+                    printHex(data,len);
+            }
+        }
+    }
+
+    static void OnHidControl(int socket, SocketState state, const u8* data, int len, void* userData)
+    {
+        printf("OnHidControl\n");
+        if (data)
+            printHex(data,len);
+    }
+
+    void Open(BD_ADDR* bdAddr, inquiry_info* info)
+    {
+        printf("L2CAPAddr size %d\n",sizeof(L2CAPAddr));
+        _addr = *bdAddr;
+        L2CAPAddr sockAddr;
+        sockAddr.bdaddr = _addr;
+        sockAddr.psm = L2CAP_PSM_HID_INTR;
+                printf("Socket_Open size %d\n",sizeof(L2CAPAddr));
+        _interrupt = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidInterrupt,this);
+        sockAddr.psm = L2CAP_PSM_HID_CNTL;
+        _control = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidControl,this);
+
+        printfBytes("OPEN DEVICE CLASS",info->dev_class,3);
+        _devClass = (info->dev_class[0] << 16) | (info->dev_class[1] << 8) | info->dev_class[2];
+    }
+
+    void Close()
+    {
+        if (_control)
+            Socket_Close(_control);
+        if (_interrupt)
+            Socket_Close(_interrupt);
+       _control = _interrupt = 0;
+    }
+
+    void Led(int id = 0x10)
+    {
+        u8 led[3] = {0x52, 0x11, id};
+        if (_control)
+            Socket_Send(_control,led,3);
+    }
+
+    void Hid(int report = 0x37)
+    {
+        u8 hid[4] = { 0x52, 0x12, 0x00, report };
+        if (_control != -1)
+            Socket_Send(_control,hid,4);
+    }
+};
+
+
+HCI* gHCI = 0;
+
+#define MAX_HID_DEVICES 8
+
+int GetConsoleChar();
+class ShellApp
+{
+    char _line[64];
+    HIDBluetooth    _hids[MAX_HID_DEVICES];
+
+public:
+    void Ready()
+    {
+    printf("HIDBluetooth %d\n",sizeof(HIDBluetooth));
+         memset(_hids,0,sizeof(_hids));
+        Inquiry();
+
+    }
+
+    //  We have connected to a device
+    void ConnectionComplete(HCI* hci, connection_info* info)
+    {
+    printf("ConnectionComplete ");
+        BD_ADDR* a = &info->bdaddr;
+        printf(a);
+        BTDevice* bt = hci->Find(a);
+        HIDBluetooth* hid = NewHIDBluetooth();
+        printf("%08x %08x\n",bt,hid);
+        if (hid)
+            hid->Open(a,&bt->_info);
+    }
+
+    HIDBluetooth* NewHIDBluetooth()
+    {
+        for (int i = 0; i < MAX_HID_DEVICES; i++)
+            if (!_hids[i].InUse())
+                return _hids+i;
+        return 0;
+    }
+
+    void ConnectDevices()
+    {
+        BTDevice* devs[8];
+        int count = gHCI->GetDevices(devs,8);
+        for (int i = 0; i < count; i++)
+        {
+            printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
+            if (devs[i]->_handle == 0)
+            {
+                BD_ADDR* bd = &devs[i]->_info.bdaddr;
+                printf("Connecting to ");
+                printf(bd);
+                printf("\n");
+                gHCI->CreateConnection(bd);
+            }
+        }
+    }
+
+    const char* ReadLine()
+    {
+        int i;
+        for (i = 0; i < 255; )
+        {
+            USBLoop();
+            int c = GetConsoleChar();
+            if (c == -1)
+                continue;
+            if (c == '\n' || c == 13)
+                break;
+            _line[i++] = c;
+        }
+        _line[i] = 0;
+        return _line;
+    }
+
+    void Inquiry()
+    {
+        printf("Inquiry..\n");
+        gHCI->Inquiry();
+    }
+
+    void List()
+    {
+        #if 0
+        printf("%d devices\n",_deviceCount);
+        for (int i = 0; i < _deviceCount; i++)
+        {
+            printf(&_devices[i].info.bdaddr);
+            printf("\n");
+        }
+        #endif
+    }
+
+    void Connect()
+    {
+        ConnectDevices();
+    }
+
+    void Disconnect()
+    {
+        gHCI->DisconnectAll();
+    }
+
+    void CloseMouse()
+    {
+    }
+
+    void Quit()
+    {
+        CloseMouse();
+    }
+
+    void Run()
+    {
+        for(;;)
+        {
+            const char* cmd = ReadLine();
+            if (strcmp(cmd,"scan") == 0 || strcmp(cmd,"inquiry") == 0)
+                Inquiry();
+            else if (strcmp(cmd,"ls") == 0)
+                List();
+            else if (strcmp(cmd,"connect") == 0)
+                Connect();
+            else if (strcmp(cmd,"disconnect") == 0)
+                Disconnect();
+            else if (strcmp(cmd,"q")== 0)
+            {
+                Quit();
+                break;
+            } else {
+                printf("eh? %s\n",cmd);
+            }
+        }
+    }
+};
+
+//  Instance
+ShellApp gApp;
+
+static int HciCallback(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len)
+{
+    switch (evt)
+    {
+        case CALLBACK_READY:
+            printf("CALLBACK_READY\n");
+            gApp.Ready();
+            break;
+
+        case CALLBACK_INQUIRY_RESULT:
+            printf("CALLBACK_INQUIRY_RESULT ");
+            printf((BD_ADDR*)data);
+            printf("\n");
+            break;
+
+        case CALLBACK_INQUIRY_DONE:
+            printf("CALLBACK_INQUIRY_DONE\n");
+            gApp.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);
+            }
+            break;
+
+        case CALLBACK_CONNECTION_COMPLETE:
+            gApp.ConnectionComplete(hci,(connection_info*)data);
+            break;
+    };
+    return 0;
+}
+
+//  these should be placed in the DMA SRAM
+typedef struct
+{
+    u8 _hciBuffer[MAX_HCL_SIZE];
+    u8 _aclBuffer[MAX_ACL_SIZE];
+} SRAMPlacement;
+
+HCITransportUSB _HCITransportUSB;
+HCI _HCI;
+
+u8* USBGetBuffer(u32* len);
+int OnBluetoothInsert(int device)
+{
+    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);
+    _HCI.Open(&_HCITransportUSB,HciCallback);
+    RegisterSocketHandler(SOCKET_L2CAP,&_HCI);
+    gHCI = &_HCI;
+    gApp.Inquiry();
+    return 0;
+}
+
+void TestShell()
+{
+    USBInit();
+    gApp.Run();
+}
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/USBHost.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/USBHost.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,1072 @@
+
+/*
+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;
+        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_INTERFACE)
+                    {
+                        switch (d[1])
+                        {
+                            case DESCRIPTOR_TYPE_ENDPOINT:
+                                AddEndpoint(device,(EndpointDescriptor*)d);
+                                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
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/USBHost.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/USBHost.h	Fri Apr 29 15:50:23 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
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/Utils.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/Utils.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,48 @@
+
+
+#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;
+    }
+}
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/Utils.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/Utils.h	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,37 @@
+
+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);
+
+#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;
+}
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/hci.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/hci.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,426 @@
+
+/*
+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"
+
+enum hci_callback_evt
+{
+    NONE,
+    CONNECT,
+    DISCONECT,
+    INQUIRYRESULT
+};
+
+#define MAX_BLUETOOTH_ADAPTERS 1
+
+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
+};
+
+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;
+    }
+    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;
+}
+//
+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;
+    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::SendCmd(int cmd, const u8* params, int len)
+{
+    u8 b[32];
+    b[0] = cmd;
+    b[1] = (cmd >> 8);
+    b[2] = len;
+    if (params)
+        memcpy(b+3,params,len);
+    _transport->HCISend(b,len+3);
+    return 0;
+}
+
+void HCI::OnCommandComplete(int cmd, const u8* data, int len)
+{
+   // printf("%04X %s",cmd,CmdStr(cmd));
+    if (len < 0)
+        return;
+    //printfBytes(" complete",data,min(16,len));
+
+    switch (cmd)
+    {
+        //  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);
+            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;
+            Callback(CALLBACK_READY,data,6);
+            break;
+
+                   // 0CXX
+        case HCI_OP_READ_LOCAL_NAME:
+            break;
+
+        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 %04X\n",cmd);
+            break;
+    }
+}
+
+void HCI::Callback(HCI_CALLBACK_EVENT c, const u8* data, int len)
+{
+    _callback(this,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::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)
+{
+    u8 b[6+1+16];
+    memset(b,0,sizeof(b));
+    memcpy(b,data,6);
+    b[6] = 4;
+    b[7] = '0';
+    b[8] = '0';
+    b[9] = '0';
+    b[10] = '0';
+    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)
+        return;
+    if (info->status == 0)
+    {
+        d->_handle = info->handle;
+        printf("Connected on %04X\n",info->handle);
+    } else
+        printf("Connection failed with %d\n",info->status);
+}
+
+void HCI::HCIRecv(const u8* data, int len)
+{
+   // 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:
+            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\n",CmdStr(LE16(data+4)),errs);
+            }
+            break;
+
+        case HCI_EV_CMD_COMPLETE:
+            OnCommandComplete(data[3] | (data[4] << 8),data+6,data[1]-4);
+            break;
+
+        case HCI_EV_PIN_CODE_REQ:
+            PinCodeReply(data+2);
+            break;
+
+        case HCI_EV_LINK_KEY_REQ:
+            SendCmd(HCI_OP_LINK_KEY_NEG_REPLY,data+2,6);
+            break;
+
+        default:
+        ;
+           // printfBytes(":",data,data[1]+2);
+    }
+}
+
+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::Send(SocketInternal* sock, const u8* data, int len)
+{
+    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::ACLRecv(const u8* data, int len)
+{
+    int handle = LE16(data);
+    BTDevice* d = Find(handle & 0x0FFF);
+    if (d)
+        d->ACLRecv(data,len);
+}
+
+//===================================================================
+//===================================================================
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/hci.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/hci.h	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,224 @@
+/*
+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
+
+#include "Socket.h"
+
+#pragma pack(1)
+
+#define ERR_HCI_DEVICE_NOT_FOUND -300
+
+class HCI;
+class HCITransport;
+class BTDevice;
+
+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;
+
+#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;
+    char   _name[MAX_HCL_NAME_LENGTH];
+
+    void Init();
+
+    BD_ADDR* GetAddress() { return &_info.bdaddr; }
+
+    //  Called from HCI
+    void ACLRecv(const u8* data, int len);
+
+    // SocketHandler
+    virtual int Open(SocketInternal* sock, SocketAddrHdr* addr);
+    virtual int Send(SocketInternal* sock, const u8* data, int len);
+    virtual int Close(SocketInternal* sock);
+
+private:
+    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 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
+};
+
+//  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);
+
+#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;
+
+    public:
+
+    //  Open a local adapter
+    int Open(HCITransport* transport, HCICallback callback);
+
+    //  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);
+
+    //  get a name, delivered in callback
+    int RemoteNameRequest(const BD_ADDR* addr);
+
+    //  Connect to a remote device
+    int CreateConnection(const BD_ADDR* remoteAddr);
+
+    bool Busy();
+
+    //  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 Send(SocketInternal* sock, const u8* data, int len);
+    virtual int Close(SocketInternal* sock);
+
+    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);
+    void    Callback(HCI_CALLBACK_EVENT c, const u8* data, int len);
+    int     PinCodeReply(const u8* data);
+};
+
+class HCITransport
+{
+protected:
+    HCI* _target;
+public:
+    void Set(HCI* target) { _target = target; };
+    virtual void HCISend(const u8* data, int len) = 0;
+    virtual void ACLSend(const u8* data, int len) = 0;
+};
+
+#endif
diff -r 000000000000 -r 4f749f62c6d7 BlueUSB/hci_private.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BlueUSB/hci_private.h	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,323 @@
+/*
+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_HOST_BUFFER_SIZE        0x0c33
+#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_REPETED_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
diff -r 000000000000 -r 4f749f62c6d7 PowerControl/EthernetPowerControl.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PowerControl/EthernetPowerControl.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,138 @@
+#include "EthernetPowerControl.h"
+
+static void write_PHY (unsigned int PhyReg, unsigned short Value) {
+   /* Write a data 'Value' to PHY register 'PhyReg'. */
+   unsigned int tout;
+   /* Hardware MII Management for LPC176x devices. */
+   LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
+   LPC_EMAC->MWTD = Value;
+
+   /* Wait utill operation completed */
+   for (tout = 0; tout < MII_WR_TOUT; tout++) {
+      if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
+         break;
+      }
+   }
+}
+
+static unsigned short read_PHY (unsigned int PhyReg) {
+   /* Read a PHY register 'PhyReg'. */
+   unsigned int tout, val;
+
+   LPC_EMAC->MADR = DP83848C_DEF_ADR | PhyReg;
+   LPC_EMAC->MCMD = MCMD_READ;
+
+   /* Wait until operation completed */
+   for (tout = 0; tout < MII_RD_TOUT; tout++) {
+      if ((LPC_EMAC->MIND & MIND_BUSY) == 0) {
+         break;
+      }
+   }
+   LPC_EMAC->MCMD = 0;
+   val = LPC_EMAC->MRDD;
+   
+   return (val);
+}
+
+void EMAC_Init()
+{
+  unsigned int tout,regv;
+  /* Power Up the EMAC controller. */
+  Peripheral_PowerUp(LPC1768_PCONP_PCENET);
+  
+  LPC_PINCON->PINSEL2 = 0x50150105;
+  LPC_PINCON->PINSEL3 &= ~0x0000000F;
+  LPC_PINCON->PINSEL3 |= 0x00000005;
+
+  /* Reset all EMAC internal modules. */
+  LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX |
+             MAC1_SIM_RES | MAC1_SOFT_RES;
+  LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES;
+
+  /* A short delay after reset. */
+  for (tout = 100; tout; tout--);
+
+  /* Initialize MAC control registers. */
+  LPC_EMAC->MAC1 = MAC1_PASS_ALL;
+  LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN;
+  LPC_EMAC->MAXF = ETH_MAX_FLEN;
+  LPC_EMAC->CLRT = CLRT_DEF;
+  LPC_EMAC->IPGR = IPGR_DEF;
+
+  /* Enable Reduced MII interface. */
+  LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM;
+
+  /* Reset Reduced MII Logic. */
+  LPC_EMAC->SUPP = SUPP_RES_RMII;
+  for (tout = 100; tout; tout--);
+  LPC_EMAC->SUPP = 0;
+
+  /* Put the DP83848C in reset mode */
+  write_PHY (PHY_REG_BMCR, 0x8000);
+
+  /* Wait for hardware reset to end. */
+  for (tout = 0; tout < 0x100000; tout++) {
+    regv = read_PHY (PHY_REG_BMCR);
+    if (!(regv & 0x8000)) {
+      /* Reset complete */
+      break;
+    }
+  }
+}
+
+
+void PHY_PowerDown()
+{
+    if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
+        EMAC_Init(); //init EMAC if it is not already init'd
+    
+    unsigned int regv;
+    regv = read_PHY(PHY_REG_BMCR);
+    write_PHY(PHY_REG_BMCR, regv | (1 << PHY_REG_BMCR_POWERDOWN));
+    regv = read_PHY(PHY_REG_BMCR);
+    
+    //shouldn't need the EMAC now.
+    Peripheral_PowerDown(LPC1768_PCONP_PCENET);
+    
+    //and turn off the PHY OSC
+     LPC_GPIO1->FIODIR |= 0x8000000;
+     LPC_GPIO1->FIOCLR = 0x8000000;
+}
+
+void PHY_PowerUp()
+{   
+    if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
+        EMAC_Init(); //init EMAC if it is not already init'd
+        
+    LPC_GPIO1->FIODIR |= 0x8000000;
+    LPC_GPIO1->FIOSET = 0x8000000;
+    
+    //wait for osc to be stable
+    wait_ms(200);
+    
+    unsigned int regv;
+    regv = read_PHY(PHY_REG_BMCR);
+    write_PHY(PHY_REG_BMCR, regv & ~(1 << PHY_REG_BMCR_POWERDOWN));
+    regv = read_PHY(PHY_REG_BMCR);
+}
+
+void PHY_EnergyDetect_Enable()
+{
+    if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
+        EMAC_Init(); //init EMAC if it is not already init'd
+        
+    unsigned int regv;
+    regv = read_PHY(PHY_REG_EDCR);
+    write_PHY(PHY_REG_BMCR, regv | (1 << PHY_REG_EDCR_ENABLE));
+    regv = read_PHY(PHY_REG_EDCR);   
+}
+
+void PHY_EnergyDetect_Disable()
+{
+    if (!Peripheral_GetStatus(LPC1768_PCONP_PCENET))
+        EMAC_Init(); //init EMAC if it is not already init'd
+    unsigned int regv;
+    regv = read_PHY(PHY_REG_EDCR);
+    write_PHY(PHY_REG_BMCR, regv & ~(1 << PHY_REG_EDCR_ENABLE));
+    regv = read_PHY(PHY_REG_EDCR);   
+}
\ No newline at end of file
diff -r 000000000000 -r 4f749f62c6d7 PowerControl/EthernetPowerControl.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PowerControl/EthernetPowerControl.h	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,299 @@
+/* mbed PowerControl Library
+  * Copyright (c) 2010 Michael Wei
+  */ 
+  
+#ifndef MBED_POWERCONTROL_ETH_H 
+#define MBED_POWERCONTROL_ETH_H 
+
+#include "mbed.h"
+#include "PowerControl.h"
+
+#define PHY_REG_BMCR_POWERDOWN    0xB
+#define PHY_REG_EDCR_ENABLE       0xF
+
+
+void EMAC_Init();
+static unsigned short read_PHY (unsigned int PhyReg);
+static void write_PHY (unsigned int PhyReg, unsigned short Value);
+
+void PHY_PowerDown(void);
+void PHY_PowerUp(void);
+void PHY_EnergyDetect_Enable(void);
+void PHY_EnergyDetect_Disable(void);
+
+//From NXP Sample Code .... Probably from KEIL sample code
+/* EMAC Memory Buffer configuration for 16K Ethernet RAM. */
+#define NUM_RX_FRAG         4           /* Num.of RX Fragments 4*1536= 6.0kB */
+#define NUM_TX_FRAG         3           /* Num.of TX Fragments 3*1536= 4.6kB */
+#define ETH_FRAG_SIZE       1536        /* Packet Fragment size 1536 Bytes   */
+
+#define ETH_MAX_FLEN        1536        /* Max. Ethernet Frame Size          */
+
+/* EMAC variables located in 16K Ethernet SRAM */
+#define RX_DESC_BASE        0x20080000
+#define RX_STAT_BASE        (RX_DESC_BASE + NUM_RX_FRAG*8)
+#define TX_DESC_BASE        (RX_STAT_BASE + NUM_RX_FRAG*8)
+#define TX_STAT_BASE        (TX_DESC_BASE + NUM_TX_FRAG*8)
+#define RX_BUF_BASE         (TX_STAT_BASE + NUM_TX_FRAG*4)
+#define TX_BUF_BASE         (RX_BUF_BASE  + NUM_RX_FRAG*ETH_FRAG_SIZE)
+
+/* RX and TX descriptor and status definitions. */
+#define RX_DESC_PACKET(i)   (*(unsigned int *)(RX_DESC_BASE   + 8*i))
+#define RX_DESC_CTRL(i)     (*(unsigned int *)(RX_DESC_BASE+4 + 8*i))
+#define RX_STAT_INFO(i)     (*(unsigned int *)(RX_STAT_BASE   + 8*i))
+#define RX_STAT_HASHCRC(i)  (*(unsigned int *)(RX_STAT_BASE+4 + 8*i))
+#define TX_DESC_PACKET(i)   (*(unsigned int *)(TX_DESC_BASE   + 8*i))
+#define TX_DESC_CTRL(i)     (*(unsigned int *)(TX_DESC_BASE+4 + 8*i))
+#define TX_STAT_INFO(i)     (*(unsigned int *)(TX_STAT_BASE   + 4*i))
+#define RX_BUF(i)           (RX_BUF_BASE + ETH_FRAG_SIZE*i)
+#define TX_BUF(i)           (TX_BUF_BASE + ETH_FRAG_SIZE*i)
+
+/* MAC Configuration Register 1 */
+#define MAC1_REC_EN         0x00000001  /* Receive Enable                    */
+#define MAC1_PASS_ALL       0x00000002  /* Pass All Receive Frames           */
+#define MAC1_RX_FLOWC       0x00000004  /* RX Flow Control                   */
+#define MAC1_TX_FLOWC       0x00000008  /* TX Flow Control                   */
+#define MAC1_LOOPB          0x00000010  /* Loop Back Mode                    */
+#define MAC1_RES_TX         0x00000100  /* Reset TX Logic                    */
+#define MAC1_RES_MCS_TX     0x00000200  /* Reset MAC TX Control Sublayer     */
+#define MAC1_RES_RX         0x00000400  /* Reset RX Logic                    */
+#define MAC1_RES_MCS_RX     0x00000800  /* Reset MAC RX Control Sublayer     */
+#define MAC1_SIM_RES        0x00004000  /* Simulation Reset                  */
+#define MAC1_SOFT_RES       0x00008000  /* Soft Reset MAC                    */
+
+/* MAC Configuration Register 2 */
+#define MAC2_FULL_DUP       0x00000001  /* Full Duplex Mode                  */
+#define MAC2_FRM_LEN_CHK    0x00000002  /* Frame Length Checking             */
+#define MAC2_HUGE_FRM_EN    0x00000004  /* Huge Frame Enable                 */
+#define MAC2_DLY_CRC        0x00000008  /* Delayed CRC Mode                  */
+#define MAC2_CRC_EN         0x00000010  /* Append CRC to every Frame         */
+#define MAC2_PAD_EN         0x00000020  /* Pad all Short Frames              */
+#define MAC2_VLAN_PAD_EN    0x00000040  /* VLAN Pad Enable                   */
+#define MAC2_ADET_PAD_EN    0x00000080  /* Auto Detect Pad Enable            */
+#define MAC2_PPREAM_ENF     0x00000100  /* Pure Preamble Enforcement         */
+#define MAC2_LPREAM_ENF     0x00000200  /* Long Preamble Enforcement         */
+#define MAC2_NO_BACKOFF     0x00001000  /* No Backoff Algorithm              */
+#define MAC2_BACK_PRESSURE  0x00002000  /* Backoff Presurre / No Backoff     */
+#define MAC2_EXCESS_DEF     0x00004000  /* Excess Defer                      */
+
+/* Back-to-Back Inter-Packet-Gap Register */
+#define IPGT_FULL_DUP       0x00000015  /* Recommended value for Full Duplex */
+#define IPGT_HALF_DUP       0x00000012  /* Recommended value for Half Duplex */
+
+/* Non Back-to-Back Inter-Packet-Gap Register */
+#define IPGR_DEF            0x00000012  /* Recommended value                 */
+
+/* Collision Window/Retry Register */
+#define CLRT_DEF            0x0000370F  /* Default value                     */
+
+/* PHY Support Register */
+#define SUPP_SPEED          0x00000100  /* Reduced MII Logic Current Speed   */
+#define SUPP_RES_RMII       0x00000800  /* Reset Reduced MII Logic           */
+
+/* Test Register */
+#define TEST_SHCUT_PQUANTA  0x00000001  /* Shortcut Pause Quanta             */
+#define TEST_TST_PAUSE      0x00000002  /* Test Pause                        */
+#define TEST_TST_BACKP      0x00000004  /* Test Back Pressure                */
+
+/* MII Management Configuration Register */
+#define MCFG_SCAN_INC       0x00000001  /* Scan Increment PHY Address        */
+#define MCFG_SUPP_PREAM     0x00000002  /* Suppress Preamble                 */
+#define MCFG_CLK_SEL        0x0000001C  /* Clock Select Mask                 */
+#define MCFG_RES_MII        0x00008000  /* Reset MII Management Hardware     */
+
+/* MII Management Command Register */
+#define MCMD_READ           0x00000001  /* MII Read                          */
+#define MCMD_SCAN           0x00000002  /* MII Scan continuously             */
+
+#define MII_WR_TOUT         0x00050000  /* MII Write timeout count           */
+#define MII_RD_TOUT         0x00050000  /* MII Read timeout count            */
+
+/* MII Management Address Register */
+#define MADR_REG_ADR        0x0000001F  /* MII Register Address Mask         */
+#define MADR_PHY_ADR        0x00001F00  /* PHY Address Mask                  */
+
+/* MII Management Indicators Register */
+#define MIND_BUSY           0x00000001  /* MII is Busy                       */
+#define MIND_SCAN           0x00000002  /* MII Scanning in Progress          */
+#define MIND_NOT_VAL        0x00000004  /* MII Read Data not valid           */
+#define MIND_MII_LINK_FAIL  0x00000008  /* MII Link Failed                   */
+
+/* Command Register */
+#define CR_RX_EN            0x00000001  /* Enable Receive                    */
+#define CR_TX_EN            0x00000002  /* Enable Transmit                   */
+#define CR_REG_RES          0x00000008  /* Reset Host Registers              */
+#define CR_TX_RES           0x00000010  /* Reset Transmit Datapath           */
+#define CR_RX_RES           0x00000020  /* Reset Receive Datapath            */
+#define CR_PASS_RUNT_FRM    0x00000040  /* Pass Runt Frames                  */
+#define CR_PASS_RX_FILT     0x00000080  /* Pass RX Filter                    */
+#define CR_TX_FLOW_CTRL     0x00000100  /* TX Flow Control                   */
+#define CR_RMII             0x00000200  /* Reduced MII Interface             */
+#define CR_FULL_DUP         0x00000400  /* Full Duplex                       */
+
+/* Status Register */
+#define SR_RX_EN            0x00000001  /* Enable Receive                    */
+#define SR_TX_EN            0x00000002  /* Enable Transmit                   */
+
+/* Transmit Status Vector 0 Register */
+#define TSV0_CRC_ERR        0x00000001  /* CRC error                         */
+#define TSV0_LEN_CHKERR     0x00000002  /* Length Check Error                */
+#define TSV0_LEN_OUTRNG     0x00000004  /* Length Out of Range               */
+#define TSV0_DONE           0x00000008  /* Tramsmission Completed            */
+#define TSV0_MCAST          0x00000010  /* Multicast Destination             */
+#define TSV0_BCAST          0x00000020  /* Broadcast Destination             */
+#define TSV0_PKT_DEFER      0x00000040  /* Packet Deferred                   */
+#define TSV0_EXC_DEFER      0x00000080  /* Excessive Packet Deferral         */
+#define TSV0_EXC_COLL       0x00000100  /* Excessive Collision               */
+#define TSV0_LATE_COLL      0x00000200  /* Late Collision Occured            */
+#define TSV0_GIANT          0x00000400  /* Giant Frame                       */
+#define TSV0_UNDERRUN       0x00000800  /* Buffer Underrun                   */
+#define TSV0_BYTES          0x0FFFF000  /* Total Bytes Transferred           */
+#define TSV0_CTRL_FRAME     0x10000000  /* Control Frame                     */
+#define TSV0_PAUSE          0x20000000  /* Pause Frame                       */
+#define TSV0_BACK_PRESS     0x40000000  /* Backpressure Method Applied       */
+#define TSV0_VLAN           0x80000000  /* VLAN Frame                        */
+
+/* Transmit Status Vector 1 Register */
+#define TSV1_BYTE_CNT       0x0000FFFF  /* Transmit Byte Count               */
+#define TSV1_COLL_CNT       0x000F0000  /* Transmit Collision Count          */
+
+/* Receive Status Vector Register */
+#define RSV_BYTE_CNT        0x0000FFFF  /* Receive Byte Count                */
+#define RSV_PKT_IGNORED     0x00010000  /* Packet Previously Ignored         */
+#define RSV_RXDV_SEEN       0x00020000  /* RXDV Event Previously Seen        */
+#define RSV_CARR_SEEN       0x00040000  /* Carrier Event Previously Seen     */
+#define RSV_REC_CODEV       0x00080000  /* Receive Code Violation            */
+#define RSV_CRC_ERR         0x00100000  /* CRC Error                         */
+#define RSV_LEN_CHKERR      0x00200000  /* Length Check Error                */
+#define RSV_LEN_OUTRNG      0x00400000  /* Length Out of Range               */
+#define RSV_REC_OK          0x00800000  /* Frame Received OK                 */
+#define RSV_MCAST           0x01000000  /* Multicast Frame                   */
+#define RSV_BCAST           0x02000000  /* Broadcast Frame                   */
+#define RSV_DRIB_NIBB       0x04000000  /* Dribble Nibble                    */
+#define RSV_CTRL_FRAME      0x08000000  /* Control Frame                     */
+#define RSV_PAUSE           0x10000000  /* Pause Frame                       */
+#define RSV_UNSUPP_OPC      0x20000000  /* Unsupported Opcode                */
+#define RSV_VLAN            0x40000000  /* VLAN Frame                        */
+
+/* Flow Control Counter Register */
+#define FCC_MIRR_CNT        0x0000FFFF  /* Mirror Counter                    */
+#define FCC_PAUSE_TIM       0xFFFF0000  /* Pause Timer                       */
+
+/* Flow Control Status Register */
+#define FCS_MIRR_CNT        0x0000FFFF  /* Mirror Counter Current            */
+
+/* Receive Filter Control Register */
+#define RFC_UCAST_EN        0x00000001  /* Accept Unicast Frames Enable      */
+#define RFC_BCAST_EN        0x00000002  /* Accept Broadcast Frames Enable    */
+#define RFC_MCAST_EN        0x00000004  /* Accept Multicast Frames Enable    */
+#define RFC_UCAST_HASH_EN   0x00000008  /* Accept Unicast Hash Filter Frames */
+#define RFC_MCAST_HASH_EN   0x00000010  /* Accept Multicast Hash Filter Fram.*/
+#define RFC_PERFECT_EN      0x00000020  /* Accept Perfect Match Enable       */
+#define RFC_MAGP_WOL_EN     0x00001000  /* Magic Packet Filter WoL Enable    */
+#define RFC_PFILT_WOL_EN    0x00002000  /* Perfect Filter WoL Enable         */
+
+/* Receive Filter WoL Status/Clear Registers */
+#define WOL_UCAST           0x00000001  /* Unicast Frame caused WoL          */
+#define WOL_BCAST           0x00000002  /* Broadcast Frame caused WoL        */
+#define WOL_MCAST           0x00000004  /* Multicast Frame caused WoL        */
+#define WOL_UCAST_HASH      0x00000008  /* Unicast Hash Filter Frame WoL     */
+#define WOL_MCAST_HASH      0x00000010  /* Multicast Hash Filter Frame WoL   */
+#define WOL_PERFECT         0x00000020  /* Perfect Filter WoL                */
+#define WOL_RX_FILTER       0x00000080  /* RX Filter caused WoL              */
+#define WOL_MAG_PACKET      0x00000100  /* Magic Packet Filter caused WoL    */
+
+/* Interrupt Status/Enable/Clear/Set Registers */
+#define INT_RX_OVERRUN      0x00000001  /* Overrun Error in RX Queue         */
+#define INT_RX_ERR          0x00000002  /* Receive Error                     */
+#define INT_RX_FIN          0x00000004  /* RX Finished Process Descriptors   */
+#define INT_RX_DONE         0x00000008  /* Receive Done                      */
+#define INT_TX_UNDERRUN     0x00000010  /* Transmit Underrun                 */
+#define INT_TX_ERR          0x00000020  /* Transmit Error                    */
+#define INT_TX_FIN          0x00000040  /* TX Finished Process Descriptors   */
+#define INT_TX_DONE         0x00000080  /* Transmit Done                     */
+#define INT_SOFT_INT        0x00001000  /* Software Triggered Interrupt      */
+#define INT_WAKEUP          0x00002000  /* Wakeup Event Interrupt            */
+
+/* Power Down Register */
+#define PD_POWER_DOWN       0x80000000  /* Power Down MAC                    */
+
+/* RX Descriptor Control Word */
+#define RCTRL_SIZE          0x000007FF  /* Buffer size mask                  */
+#define RCTRL_INT           0x80000000  /* Generate RxDone Interrupt         */
+
+/* RX Status Hash CRC Word */
+#define RHASH_SA            0x000001FF  /* Hash CRC for Source Address       */
+#define RHASH_DA            0x001FF000  /* Hash CRC for Destination Address  */
+
+/* RX Status Information Word */
+#define RINFO_SIZE          0x000007FF  /* Data size in bytes                */
+#define RINFO_CTRL_FRAME    0x00040000  /* Control Frame                     */
+#define RINFO_VLAN          0x00080000  /* VLAN Frame                        */
+#define RINFO_FAIL_FILT     0x00100000  /* RX Filter Failed                  */
+#define RINFO_MCAST         0x00200000  /* Multicast Frame                   */
+#define RINFO_BCAST         0x00400000  /* Broadcast Frame                   */
+#define RINFO_CRC_ERR       0x00800000  /* CRC Error in Frame                */
+#define RINFO_SYM_ERR       0x01000000  /* Symbol Error from PHY             */
+#define RINFO_LEN_ERR       0x02000000  /* Length Error                      */
+#define RINFO_RANGE_ERR     0x04000000  /* Range Error (exceeded max. size)  */
+#define RINFO_ALIGN_ERR     0x08000000  /* Alignment Error                   */
+#define RINFO_OVERRUN       0x10000000  /* Receive overrun                   */
+#define RINFO_NO_DESCR      0x20000000  /* No new Descriptor available       */
+#define RINFO_LAST_FLAG     0x40000000  /* Last Fragment in Frame            */
+#define RINFO_ERR           0x80000000  /* Error Occured (OR of all errors)  */
+
+#define RINFO_ERR_MASK     (RINFO_FAIL_FILT | RINFO_CRC_ERR   | RINFO_SYM_ERR | \
+                            RINFO_LEN_ERR   | RINFO_ALIGN_ERR | RINFO_OVERRUN)
+
+/* TX Descriptor Control Word */
+#define TCTRL_SIZE          0x000007FF  /* Size of data buffer in bytes      */
+#define TCTRL_OVERRIDE      0x04000000  /* Override Default MAC Registers    */
+#define TCTRL_HUGE          0x08000000  /* Enable Huge Frame                 */
+#define TCTRL_PAD           0x10000000  /* Pad short Frames to 64 bytes      */
+#define TCTRL_CRC           0x20000000  /* Append a hardware CRC to Frame    */
+#define TCTRL_LAST          0x40000000  /* Last Descriptor for TX Frame      */
+#define TCTRL_INT           0x80000000  /* Generate TxDone Interrupt         */
+
+/* TX Status Information Word */
+#define TINFO_COL_CNT       0x01E00000  /* Collision Count                   */
+#define TINFO_DEFER         0x02000000  /* Packet Deferred (not an error)    */
+#define TINFO_EXCESS_DEF    0x04000000  /* Excessive Deferral                */
+#define TINFO_EXCESS_COL    0x08000000  /* Excessive Collision               */
+#define TINFO_LATE_COL      0x10000000  /* Late Collision Occured            */
+#define TINFO_UNDERRUN      0x20000000  /* Transmit Underrun                 */
+#define TINFO_NO_DESCR      0x40000000  /* No new Descriptor available       */
+#define TINFO_ERR           0x80000000  /* Error Occured (OR of all errors)  */
+
+/* DP83848C PHY Registers */
+#define PHY_REG_BMCR        0x00        /* Basic Mode Control Register       */
+#define PHY_REG_BMSR        0x01        /* Basic Mode Status Register        */
+#define PHY_REG_IDR1        0x02        /* PHY Identifier 1                  */
+#define PHY_REG_IDR2        0x03        /* PHY Identifier 2                  */
+#define PHY_REG_ANAR        0x04        /* Auto-Negotiation Advertisement    */
+#define PHY_REG_ANLPAR      0x05        /* Auto-Neg. Link Partner Abitily    */
+#define PHY_REG_ANER        0x06        /* Auto-Neg. Expansion Register      */
+#define PHY_REG_ANNPTR      0x07        /* Auto-Neg. Next Page TX            */
+
+/* PHY Extended Registers */
+#define PHY_REG_STS         0x10        /* Status Register                   */
+#define PHY_REG_MICR        0x11        /* MII Interrupt Control Register    */
+#define PHY_REG_MISR        0x12        /* MII Interrupt Status Register     */
+#define PHY_REG_FCSCR       0x14        /* False Carrier Sense Counter       */
+#define PHY_REG_RECR        0x15        /* Receive Error Counter             */
+#define PHY_REG_PCSR        0x16        /* PCS Sublayer Config. and Status   */
+#define PHY_REG_RBR         0x17        /* RMII and Bypass Register          */
+#define PHY_REG_LEDCR       0x18        /* LED Direct Control Register       */
+#define PHY_REG_PHYCR       0x19        /* PHY Control Register              */
+#define PHY_REG_10BTSCR     0x1A        /* 10Base-T Status/Control Register  */
+#define PHY_REG_CDCTRL1     0x1B        /* CD Test Control and BIST Extens.  */
+#define PHY_REG_EDCR        0x1D        /* Energy Detect Control Register    */
+
+#define PHY_FULLD_100M      0x2100      /* Full Duplex 100Mbit               */
+#define PHY_HALFD_100M      0x2000      /* Half Duplex 100Mbit               */
+#define PHY_FULLD_10M       0x0100      /* Full Duplex 10Mbit                */
+#define PHY_HALFD_10M       0x0000      /* Half Duplex 10MBit                */
+#define PHY_AUTO_NEG        0x3000      /* Select Auto Negotiation           */
+
+#define DP83848C_DEF_ADR    0x0100      /* Default PHY device address        */
+#define DP83848C_ID         0x20005C90  /* PHY Identifier                    */
+#endif
\ No newline at end of file
diff -r 000000000000 -r 4f749f62c6d7 PowerControl/PowerControl.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PowerControl/PowerControl.h	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,192 @@
+/* mbed PowerControl Library
+  * Copyright (c) 2010 Michael Wei
+  */ 
+  
+#ifndef MBED_POWERCONTROL_H 
+#define MBED_POWERCONTROL_H 
+
+//shouldn't have to include, but fixes weird problems with defines
+#include "LPC1768/LPC17xx.h"
+
+//System Control Register
+// bit 0: Reserved
+// bit 1: Sleep on Exit
+#define LPC1768_SCR_SLEEPONEXIT     0x2
+// bit 2: Deep Sleep
+#define LPC1768_SCR_SLEEPDEEP       0x4
+// bit 3: Resereved
+// bit 4: Send on Pending
+#define LPC1768_SCR_SEVONPEND        0x10
+// bit 5-31: Reserved
+
+//Power Control Register
+// bit 0: Power mode control bit 0 (power-down mode)
+#define LPC1768_PCON_PM0            0x1
+// bit 1: Power mode control bit 1 (deep power-down mode)
+#define LPC1768_PCON_PM1            0x2
+// bit 2: Brown-out reduced power mode
+#define LPC1768_PCON_BODRPM         0x4
+// bit 3: Brown-out global disable
+#define LPC1768_PCON_BOGD           0x8
+// bit 4: Brown-out reset disable
+#define LPC1768_PCON_BORD           0x10
+// bit 5-7 : Reserved
+// bit 8: Sleep Mode Entry Flag
+#define LPC1768_PCON_SMFLAG         0x100
+// bit 9: Deep Sleep Entry Flag
+#define LPC1768_PCON_DSFLAG         0x200
+// bit 10: Power Down Entry Flag
+#define LPC1768_PCON_PDFLAG         0x400
+// bit 11: Deep Power Down Entry Flag
+#define LPC1768_PCON_DPDFLAG        0x800
+// bit 12-31: Reserved
+
+//"Sleep Mode" (WFI).
+inline void Sleep(void)
+{
+    __WFI();
+}
+
+//"Deep Sleep" Mode
+inline void DeepSleep(void)
+{
+   SCB->SCR |= LPC1768_SCR_SLEEPDEEP;
+   __WFI();
+}
+
+//"Power-Down" Mode
+inline void PowerDown(void)
+{
+   SCB->SCR |= LPC1768_SCR_SLEEPDEEP;
+   LPC_SC->PCON &= ~LPC1768_PCON_PM1;
+   LPC_SC->PCON |= LPC1768_PCON_PM0;
+   __WFI();
+   //reset back to normal
+  LPC_SC->PCON &= ~(LPC1768_PCON_PM1 | LPC1768_PCON_PM0);
+}
+
+//"Deep Power-Down" Mode
+inline void DeepPowerDown(void)
+{
+   SCB->SCR |= LPC1768_SCR_SLEEPDEEP;
+   LPC_SC->PCON |= LPC1768_PCON_PM1 | LPC1768_PCON_PM0;
+   __WFI();
+   //reset back to normal
+  LPC_SC->PCON &= ~(LPC1768_PCON_PM1 | LPC1768_PCON_PM0);
+}
+
+//shut down BOD during power-down/deep sleep
+inline void BrownOut_ReducedPowerMode_Enable(void)
+{
+    LPC_SC->PCON |= LPC1768_PCON_BODRPM;
+}
+
+//turn on BOD during power-down/deep sleep
+inline void BrownOut_ReducedPowerMode_Disable(void)
+{
+    LPC_SC->PCON &= ~LPC1768_PCON_BODRPM;
+}
+
+//turn off brown out circutry
+inline void BrownOut_Global_Disable(void)
+{
+    LPC_SC->PCON |= LPC1768_PCON_BOGD;
+}
+
+//turn on brown out circutry
+inline void BrownOut_Global_Enable(void)
+{
+    LPC_SC->PCON &= !LPC1768_PCON_BOGD;
+}
+
+//turn off brown out reset circutry
+inline void BrownOut_Reset_Disable(void)
+{
+    LPC_SC->PCON |= LPC1768_PCON_BORD;
+}
+
+//turn on brown outreset  circutry
+inline void BrownOut_Reset_Enable(void)
+{
+    LPC_SC->PCON &= ~LPC1768_PCON_BORD;
+}
+//Peripheral Control Register
+// bit 0: Reserved
+// bit 1: PCTIM0: Timer/Counter 0 power/clock enable
+#define LPC1768_PCONP_PCTIM0        0x2
+// bit 2: PCTIM1: Timer/Counter 1 power/clock enable
+#define LPC1768_PCONP_PCTIM1        0x4
+// bit 3: PCUART0: UART 0 power/clock enable
+#define LPC1768_PCONP_PCUART0       0x8
+// bit 4: PCUART1: UART 1 power/clock enable
+#define LPC1768_PCONP_PCUART1       0x10
+// bit 5: Reserved
+// bit 6: PCPWM1: PWM 1 power/clock enable
+#define LPC1768_PCONP_PCPWM1        0x40
+// bit 7: PCI2C0: I2C interface 0 power/clock enable
+#define LPC1768_PCONP_PCI2C0        0x80
+// bit 8: PCSPI: SPI interface power/clock enable
+#define LPC1768_PCONP_PCSPI         0x100
+// bit 9: PCRTC: RTC power/clock enable
+#define LPC1768_PCONP_PCRTC         0x200
+// bit 10: PCSSP1: SSP interface 1 power/clock enable
+#define LPC1768_PCONP_PCSSP1        0x400
+// bit 11: Reserved
+// bit 12: PCADC: A/D converter power/clock enable
+#define LPC1768_PCONP_PCADC         0x1000
+// bit 13: PCCAN1: CAN controller 1 power/clock enable
+#define LPC1768_PCONP_PCCAN1        0x2000
+// bit 14: PCCAN2: CAN controller 2 power/clock enable
+#define LPC1768_PCONP_PCCAN2        0x4000
+// bit 15: PCGPIO: GPIOs power/clock enable
+#define LPC1768_PCONP_PCGPIO        0x8000
+// bit 16: PCRIT: Repetitive interrupt timer power/clock enable
+#define LPC1768_PCONP_PCRIT         0x10000
+// bit 17: PCMCPWM: Motor control PWM power/clock enable
+#define LPC1768_PCONP_PCMCPWM       0x20000
+// bit 18: PCQEI: Quadrature encoder interface power/clock enable
+#define LPC1768_PCONP_PCQEI         0x40000
+// bit 19: PCI2C1: I2C interface 1 power/clock enable
+#define LPC1768_PCONP_PCI2C1        0x80000
+// bit 20: Reserved
+// bit 21: PCSSP0: SSP interface 0 power/clock enable
+#define LPC1768_PCONP_PCSSP0        0x200000
+// bit 22: PCTIM2: Timer 2 power/clock enable
+#define LPC1768_PCONP_PCTIM2        0x400000
+// bit 23: PCTIM3: Timer 3 power/clock enable
+#define LPC1768_PCONP_PCQTIM3       0x800000
+// bit 24: PCUART2: UART 2 power/clock enable
+#define LPC1768_PCONP_PCUART2       0x1000000
+// bit 25: PCUART3: UART 3 power/clock enable
+#define LPC1768_PCONP_PCUART3       0x2000000
+// bit 26: PCI2C2: I2C interface 2 power/clock enable
+#define LPC1768_PCONP_PCI2C2        0x4000000
+// bit 27: PCI2S: I2S interface power/clock enable
+#define LPC1768_PCONP_PCI2S         0x8000000
+// bit 28: Reserved
+// bit 29: PCGPDMA: GP DMA function power/clock enable
+#define LPC1768_PCONP_PCGPDMA       0x20000000
+// bit 30: PCENET: Ethernet block power/clock enable
+#define LPC1768_PCONP_PCENET        0x40000000
+// bit 31: PCUSB: USB interface power/clock enable
+#define LPC1768_PCONP_PCUSB         0x80000000
+
+//Powers Up specified Peripheral(s)
+inline unsigned int Peripheral_PowerUp(unsigned int bitMask)
+{
+    return LPC_SC->PCONP |= bitMask;
+}   
+
+//Powers Down specified Peripheral(s) 
+inline unsigned int Peripheral_PowerDown(unsigned int bitMask)
+{
+    return LPC_SC->PCONP &= ~bitMask;
+}
+
+//returns if the peripheral is on or off
+inline bool Peripheral_GetStatus(unsigned int peripheral)
+{
+    return (LPC_SC->PCONP & peripheral) ? true : false;
+}
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r 4f749f62c6d7 SimpleFilter.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SimpleFilter.lib	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/shimniok/code/SimpleFilter/#70348515ed2f
diff -r 000000000000 -r 4f749f62c6d7 Wiimote/Wiimote.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wiimote/Wiimote.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,101 @@
+/* Copyright (c) 2011, mbed
+ * 
+ * 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.
+ */
+
+// Simple decode class for Wii Remote data
+
+#include "Wiimote.h"
+
+// Wii Report Formats: 
+//  * http://wiibrew.org/wiki/Wiimote#0x37:_Core_Buttons_and_Accelerometer_with_10_IR_bytes_and_6_Extension_Bytes
+//  * http://wiki.wiimoteproject.com/Reports#0x37_BTN_.2B_XLR_.2B_IR_.2B_6_EXT
+
+// Input Report 0x37:
+// 
+// 0 [ ?    |    X(1:0)   | PLUS  | UP | DOWN | RIGHT | LEFT ]
+// 1 [ HOME | Z(1) | Y(1) | MINUS |  A |   B  |  ONE  |  TWO ]
+// 2 [                        X(9:2)                         ]
+// 3 [                        Y(9:2)                         ]
+// 4 [                        Z(9:2)                         ]
+//
+
+#include <stdio.h>
+#include <math.h>
+
+#define WII_ZERO 0x206
+#define WII_1G   0x6A
+
+void Wiimote::decode(char* data) {
+
+    // read buttons
+    left  = (data[0] >> 0) & 0x1;
+    right = (data[0] >> 1) & 0x1;
+    down  = (data[0] >> 2) & 0x1;
+    up    = (data[0] >> 3) & 0x1;
+    plus  = (data[0] >> 4) & 0x1;
+    two   = (data[1] >> 0) & 0x1;
+    one   = (data[1] >> 1) & 0x1;
+    b     = (data[1] >> 2) & 0x1;
+    a     = (data[1] >> 3) & 0x1;
+    minus = (data[1] >> 4) & 0x1;
+    home  = (data[1] >> 7) & 0x1;
+    
+    // read accelerometers
+    rawx = (data[2] << 2) | (data[0] & 0x60) >> 5;
+    rawy = (data[3] << 2) | (data[1] & 0x20) >> 4;
+    rawz = (data[4] << 2) | (data[1] & 0x40) >> 5;
+
+    // calculate accelerometer gravity
+    x = (float)((int)rawx - WII_ZERO) / (float)WII_1G;
+    y = (float)((int)rawy - WII_ZERO) / (float)WII_1G;
+    z = (float)((int)rawz - WII_ZERO) / (float)WII_1G;
+
+    // calculate wheel angle    
+    wheel = atan2(-y, -x) * (180.0 / 3.141592);
+} 
+
+void Wiimote::dump() {
+    printf("%d%d%d%d%d%d%d%d%d%d%d %.3f %.3f %.3f %.2f\n", left, right, down, up, plus, two, one, b, a, minus, home, x, y, z, wheel);
+}
+
+
+// Accelerometer data
+//      y-
+//     +---+               +--+
+//     | + |               +  B
+//     | A |               A  |
+//     |   |               |  |
+// x+  |   |  x-       z+  |  |  z-
+//     | 1 |               1  |
+//     | 2 |               2  |
+//     +---+               +--+
+//      y+
+//
+// x+ 0x19B
+// x0 0x205
+// x- 0x26E
+//
+// y+ 0x19C   0x6A
+// y0 0x206
+// y- 0x26E   0x68
+//
+// z+ 0x19C 
+// z0 0x208
+// z- 0x26E
diff -r 000000000000 -r 4f749f62c6d7 Wiimote/Wiimote.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Wiimote/Wiimote.h	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,61 @@
+/* Copyright (c) 2011, mbed
+ * 
+ * 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.
+ */
+ 
+// Simple decoder class for Wii Remote data
+
+#ifndef WIIMOTE_H
+#define WIIMOTE_H
+
+#include <stdint.h>
+
+class Wiimote {
+
+public: 
+
+    void decode(char *data);
+    void dump();
+    
+    // buttons
+    uint32_t left:1;
+    uint32_t right:1;
+    uint32_t down:1;
+    uint32_t up:1;
+    uint32_t plus:1;
+    uint32_t two:1;
+    uint32_t one:1;
+    uint32_t a:1;
+    uint32_t b:1;
+    uint32_t minus:1;
+    uint32_t home:1;
+
+    // accelerometers
+    uint16_t rawx;
+    uint16_t rawy;
+    uint16_t rawz;
+    
+    float x;
+    float y;
+    float z;
+    float wheel;
+};
+
+#endif
+     
\ No newline at end of file
diff -r 000000000000 -r 4f749f62c6d7 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,335 @@
+/*
+Copyright (c) 2011 JKSOFT
+
+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 "BD6211F.h"
+#include "Wiimote.h"
+#include "EthernetPowerControl.h"
+#include "SimpleFilter.h"
+
+// #define _SENSOR_6
+
+#define SENSOR_CYCLE        0.005f  // 5ms
+#define SENSOR_SAMPLING     0.020f  // 20ms
+#ifndef _SENSOR_6
+#define SENSOR_NUM          4
+#else
+#define SENSOR_NUM          6
+#endif
+
+#define USB_INIT_CNT_MAX    40 // 0.5s X 40 = 20s
+
+// ----- Wallbot I/O Setting ----- 
+
+// Motor
+BD6211F      RightMotor(p21,p22);
+BD6211F      LeftMotor(p23,p24);
+
+// Floor Sensor
+AnalogIn     RightSideSensor(p15);
+AnalogIn     RightCenterSensor(p16);
+AnalogIn     LeftCenterSensor(p17);
+AnalogIn     LeftSideSensor(p18);
+#ifdef _SENSOR_6
+AnalogIn    RightBackSensor(p19);
+AnalogIn    LeftBackSensor(p20);
+#endif
+
+#ifndef _SENSOR_6
+AnalogIn    _FloorSensor[] = {
+    RightSideSensor ,
+    RightCenterSensor ,
+    LeftCenterSensor ,
+    LeftSideSensor
+};
+#else
+AnalogIn    _FloorSensor[] = {
+    RightSideSensor ,
+    RightCenterSensor ,
+    LeftCenterSensor ,
+    LeftSideSensor ,
+    RightBackSensor ,
+    LeftBackSensor
+};
+#endif
+// Setting Sw
+// It is a Pull-Up
+DigitalIn    sw1(p29);
+DigitalIn    sw2(p30);
+
+// LED
+DigitalOut    chk_led(LED4);
+
+// ------------------------------- 
+
+// Input processing (Sensor & Sw)
+Ticker sensor;
+int sampling = (int)(SENSOR_SAMPLING / SENSOR_CYCLE);
+int        sw[2][10];
+
+SimpleFilter fl1(4);
+SimpleFilter fl2(4);
+SimpleFilter fl3(4);
+SimpleFilter fl4(4);
+SimpleFilter fl5(4);
+SimpleFilter fl6(4);
+SimpleFilter FloorSensor_fl[] = { fl1, fl2, fl3, fl4, fl5, fl6 };
+
+// Wii remote chk
+int wd_timer = 0;
+int usb_init_count = 0;
+
+// Timer tick(SENSOR_CYCLE[ms])
+void cycle_proc()
+{
+    static int counter = 0;
+    int i;
+    
+    if( counter >= sampling )
+    {
+        counter = 0;
+    }
+    
+    // Sw
+    sw[0][counter] = sw1;
+    sw[1][counter] = sw2;
+
+    
+    // FloorSensor
+    for( i = 0 ; i < SENSOR_NUM ; i++ )
+    {
+        FloorSensor_fl[i].filter(_FloorSensor[i].read_u16() >> 1);
+    }
+    
+    
+    counter ++;
+    wd_timer ++;
+}
+
+// 
+int GetFloorSensor(int num)
+{
+    int ret;
+    
+    if( num >= SENSOR_NUM )    return( 0 );
+    
+    ret = (int)FloorSensor_fl[num].value();
+    
+    return(ret);
+}
+
+// Sw ON:true OFF:false
+bool GetSw(int num)
+{
+    int i,sum = 0;
+    bool ret = false;
+    
+    for( i = 0 ; i < sampling ; i++ )
+    {
+        sum += sw[num][i];
+    }
+    if( sum == 0 )
+    {
+        ret = true;
+    }
+    
+    return( ret );
+}
+
+// Direct control mode
+int DirectMode( Wiimote* wii, int stat )
+{
+    int ret = stat;
+    
+    if( wii->left )
+    {
+        RightMotor = 1.0;
+        LeftMotor = -1.0;
+    }
+    else if( wii->right )
+    {
+        RightMotor = -1.0;
+        LeftMotor = 1.0;
+    }    
+    else if( wii->up )
+    {
+        RightMotor = 1.0;
+        LeftMotor = 1.0;
+    }
+    else if( wii->down )
+    {
+        RightMotor = -1.0;
+        LeftMotor = -1.0;
+    }
+    else
+    {
+        RightMotor = 0.0;
+        LeftMotor = 0.0;
+    }
+
+    float factor = wii->wheel / 150.0f; 
+    
+    float left_factor = (factor >= 0.0) ? 1.0 : 1.0 - (-factor);
+    float right_factor = (factor <= 0.0) ? 1.0 : 1.0 - factor;
+    
+    if( wii->one )
+    {
+        RightMotor = right_factor;
+        LeftMotor = left_factor;
+    }
+    if( wii->two )
+    {
+        RightMotor = -left_factor;
+        LeftMotor = -right_factor;
+    }
+    
+    return(ret);
+}
+
+// Processing when receiving it from Wiiremote
+int wall_bot_remote(char *c,int stat)
+{
+    Wiimote wii;
+    int ret = stat;
+    
+    wii.decode(c);
+    
+    ret = DirectMode( &wii ,ret );
+    
+    wd_timer = 0;
+    chk_led = 0;
+    usb_init_count = USB_INIT_CNT_MAX; 
+    
+    return(ret);
+}
+
+void input_chk(void)
+{
+    short fl[4];
+    int i;
+    bool sw[2];
+    
+    for(i=0;i<4;i++)
+    {
+        fl[i] = GetFloorSensor(i);
+    }
+    sw[0] = GetSw(0);
+    sw[1] = GetSw(1);
+    
+    printf("%d\t%d\t%d\t%d\t%d\t%d\t\r\n",fl[0],fl[1],fl[2],fl[3],sw[0],sw[1]);
+    
+}
+
+void output_chk(void)
+{
+    static int step = 0;
+    
+    switch(step)
+    {
+    case 0:
+        RightMotor = 1.0;
+        LeftMotor = 1.0;
+        break;
+    case 1:
+        RightMotor = -1.0;
+        LeftMotor = -1.0;
+        break;
+    case 2:
+        RightMotor = -1.0;
+        LeftMotor = 1.0;
+        break;
+    case 3:
+        RightMotor = 1.0;
+        LeftMotor = -1.0;
+        break;
+    }
+    step = (step+1)%4;
+}
+
+// Wii Time Out chk
+void wd_wii_chk(void)
+{
+    if( wd_timer > (0.5/SENSOR_CYCLE) )
+    {
+        chk_led = !chk_led;
+        
+        wd_timer = 0;
+        
+        RightMotor.speed(0.0);
+        LeftMotor.speed(0.0);
+        
+        usb_init_count++;
+        
+        if(usb_init_count > USB_INIT_CNT_MAX)
+        {
+            USBInit();
+            usb_init_count = 0;
+        }
+    }
+}
+
+int GetConsoleChar()
+{
+    return(0);
+}
+
+int OnDiskInsert(int device)
+{
+    return(0);
+}
+
+int main()
+{
+    // Init
+    
+    // Ether PHY Stop
+    PHY_PowerDown();
+    
+    // Sw Pull up
+    sw1.mode(PullUp);
+    sw2.mode(PullUp);
+    
+    // Motor stop
+    RightMotor.speed(0.0);
+    LeftMotor.speed(0.0);
+    
+    // USB Init is done for Bluetooth
+    USBInit();
+    usb_init_count = 0;
+    
+    // Sensing Processing
+    sensor.attach(&cycle_proc, SENSOR_CYCLE);
+
+    while(1)
+    {
+        
+       // USB Processing is done for Bluetooth
+       USBLoop();
+       wd_wii_chk();
+       
+       // input_chk();
+       // output_chk();
+       // wait(0.1);
+    }
+}
diff -r 000000000000 -r 4f749f62c6d7 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Fri Apr 29 15:50:23 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0