ADKに対応していないAndroid端末にマイコンを繋いでADBインターフェースで通信できるMicroBridgeのmbed移植版。 mbedに繋いだサーボをAndroid端末から動かすサンプルプログラムです。 とりあえず暫定バージョンを公開します。 Dev Phone 1でのみ動作確認をしています。 USBのインターフェース番号を固定しているので他で繋がるかわかりません。

Dependencies:   TextLCD mbed

Files at this revision

API Documentation at this revision

Comitter:
jksoft
Date:
Sun Aug 21 14:36:35 2011 +0000
Commit message:

Changed in this revision

ADB/Adb.cpp Show annotated file Show diff for this revision Revisions of this file
ADB/Adb.h Show annotated file Show diff for this revision Revisions of this file
PacketBuffer/PacketBuffer.cpp Show annotated file Show diff for this revision Revisions of this file
PacketBuffer/PacketBuffer.h Show annotated file Show diff for this revision Revisions of this file
TextLCD.lib Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHost.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHost.h Show annotated file Show diff for this revision Revisions of this file
USBHost/USBHost_log.cpp 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 dde3f92088d5 ADB/Adb.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADB/Adb.cpp	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,891 @@
+/*
+    Copyright 2011 Niels Brouwers
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+*/
+
+/* Changed by Junichi Katsu */
+
+#include <string.h>
+#include <Adb.h>
+
+#define DEBUG
+
+#define MAX_BUF_SIZE 128
+
+#ifdef DEBUG
+#define  log(...)       printf(__VA_ARGS__)
+#else
+#define  log(...)       do {} while(0)
+#endif
+
+int input_ep;
+int output_ep;
+int _device;
+int _configuration;
+int _interfaceNumber;
+
+static Connection * firstConnection;
+static boolean connected;
+static int connectionLocalId = 1;
+unsigned char readbuff[MAX_BUF_SIZE];
+
+// Event handler callback function.
+adb_eventHandler * eventHandler;
+
+ADB* _adb;
+PacketBuffer recv_packet_buf(100,MAX_BUF_SIZE);
+Ticker timer;
+
+int time_ms = 0;
+
+
+void attime(void)
+{
+    time_ms++;
+}
+
+int millis()
+{
+    return(time_ms);
+}
+
+char *strdup(const char *src)
+{
+    char *p;
+    
+    if(src == NULL){
+        return NULL;
+    }
+    
+    p = (char *)malloc(strlen(src) + 1);
+    if(p != NULL) strcpy(p, src);
+    return p;
+
+}
+
+/**
+ * Initialises the ADB protocol. This function initialises the USB layer underneath so no further setup is required.
+ */
+void ADB::init()
+{   
+    recv_packet_buf.clear();
+    
+    // Signal that we are not connected.
+    _device = 0;
+    connected = false;
+    
+
+    // Initialise Usb host.
+    USBInit();
+    
+    timer.attach_us(&attime, 1000);
+}
+
+/**
+ * Sets the ADB event handler function. This function will be called by the ADB layer
+ * when interesting events occur, such as ADB connect/disconnect, connection open/close, and
+ * connection writes from the ADB device.
+ *
+ * @param handler event handler function.
+ */
+void ADB::setEventHandler(adb_eventHandler * handler)
+{
+    eventHandler = handler;
+}
+
+/**
+ * Fires an ADB event.
+ * @param connection ADB connection. May be NULL in case of global connect/disconnect events.
+ * @param type event type.
+ * @param length payload length or zero if no payload.
+ * @param data payload data if relevant or NULL otherwise.
+ */
+void ADB::fireEvent(Connection * connection, adb_eventType type, uint16_t length, uint8_t * data)
+{
+    // Fire the global event handler, if set.
+    if (eventHandler!=NULL)
+        eventHandler(connection, type, length, data);
+
+    // Fire the event handler of the connection in question, if relevant
+    if (connection!=NULL && connection->eventHandler!=NULL)
+        connection->eventHandler(connection, type, length, data);
+}
+
+/**
+ * Adds a new ADB connection. The connection string is per ADB specs, for example "tcp:1234" opens a
+ * connection to tcp port 1234, and "shell:ls" outputs a listing of the phone root filesystem. Connections
+ * can be made persistent by setting reconnect to true. Persistent connections will be automatically
+ * reconnected when the USB cable is re-plugged in. Non-persistent connections will connect only once,
+ * and should never be used after they are closed.
+ *
+ * The connection string is copied into the Connection record and may not exceed ADB_CONNECTIONSTRING_LENGTH-1
+ * characters.
+ *
+ * @param connectionString ADB connectionstring. I.e. "tcp:1234" or "shell:ls".
+ * @param reconnect true for automatic reconnect (persistent connections).
+ * @param handler event handler.
+ * @return an ADB connection record or NULL on failure (not enough slots or connection string too long).
+ */
+Connection * ADB::addConnection(const char * connectionString, boolean reconnect, adb_eventHandler * handler)
+{
+
+    // Allocate a new ADB connection object
+    Connection * connection = (Connection*)malloc(sizeof(Connection));
+    if (connection == NULL) return NULL;
+
+    // Allocate memory for the connection string
+    connection->connectionString = (char*)strdup(connectionString);
+    if (connection->connectionString==NULL)
+    {
+        // Free the connection object and return null
+        free(connection);
+        return NULL;
+    }
+
+    // Initialise the newly created object.
+    connection->localID = connectionLocalId ++;
+    connection->status = ADB_CLOSED;
+    connection->lastConnectionAttempt = 0;
+    connection->reconnect = reconnect;
+    connection->eventHandler = handler;
+
+    // Add the connection to the linked list. Note that it's easier to just insert
+    // at position 0 because you don't have to traverse the list :)
+    connection->next = firstConnection;
+    firstConnection = connection;
+
+    // Unable to find an empty spot, all connection slots in use.
+    return connection;
+}
+
+/**
+ * Prints an ADB_message, for debugging purposes.
+ * @param message ADB message to print.
+ */
+#ifdef DEBUG
+static void adb_printMessage(adb_message * message)
+{
+    switch(message->command)
+    {
+    case A_OKAY:
+        printf("OKAY message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
+        break;
+    case A_CLSE:
+        printf("CLSE message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
+        break;
+    case A_WRTE:
+        printf("WRTE message [%lx] %ld %ld, %ld bytes\r\n", message->command, message->arg0, message->arg1, message->data_length);
+        break;
+    case A_CNXN:
+        printf("CNXN message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
+        break;
+    case A_SYNC:
+        printf("SYNC message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
+        break;
+    case A_OPEN:
+        printf("OPEN message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
+        break;
+    default:
+        printf("WTF message [%lx] %ld %ld\r\n", message->command, message->arg0, message->arg1);
+        break;
+    }
+}
+#endif
+
+/**
+ * Writes an empty message (without payload) to the ADB device.
+ *
+ * @param device USB device handle.
+ * @param command ADB command.
+ * @param arg0 first ADB argument (command dependent).
+ * @param arg0 second ADB argument (command dependent).
+ * @return error code or 0 for success.
+ */
+int ADB::writeEmptyMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1)
+{
+    adb_message message;
+
+    message.command = command;
+    message.arg0 = arg0;
+    message.arg1 = arg1;
+    message.data_length = 0;
+    message.data_check = 0;
+    message.magic = command ^ 0xffffffff;
+
+#ifdef DEBUG
+    printf("OUT << "); adb_printMessage(&message);
+#endif
+
+    int r = USBBulkTransfer( device , output_ep , (uint8_t*)&message , sizeof(adb_message) );
+
+#ifdef DEBUG
+    log("[writeMessage1] size:%d\r\n",r);
+    
+    int ii,jj;
+    uint8_t* buf = (uint8_t*)&message;
+    for(ii = 0 ; ii < r ; ii+=16)
+    {
+        for(jj = 0 ; jj < 16 ; jj+=2 )
+        {
+            log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]);
+            if((ii+jj) > r) break;
+        }
+        log(" : ");
+        for(jj = 0 ; jj < 16 ; jj+=2 )
+        {
+            log("%c%c",buf[ii+jj],buf[ii+jj+1]);
+            if((ii+jj) > r) break;
+        }
+        log("\r\n");
+        if((ii+jj) > r) break;
+    }
+#endif
+
+    return r;
+}
+
+/**
+ * Writes an ADB message with payload to the ADB device.
+ *
+ * @param device USB device handle.
+ * @param command ADB command.
+ * @param arg0 first ADB argument (command dependent).
+ * @param arg0 second ADB argument (command dependent).
+ * @param length payload length.
+ * @param data command payload.
+ * @return error code or 0 for success.
+ */
+int ADB::writeMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1, uint32_t length, uint8_t * data)
+{
+    adb_message message;
+    uint8_t msg[256];
+    uint32_t count, sum = 0;
+    uint8_t * x;
+
+    // Calculate data checksum
+    count = length;
+    x = data;
+    while(count-- > 0) sum += *x++;
+
+    // Fill out the message record.
+    message.command = command;
+    message.arg0 = arg0;
+    message.arg1 = arg1;
+    message.data_length = length;
+    message.data_check = (sum);
+    message.magic = command ^ 0xffffffff;
+    
+#ifdef DEBUG
+    printf("OUT << "); adb_printMessage(&message);
+#endif
+
+    int r = USBBulkTransfer( device , output_ep , (uint8_t*)&message , sizeof(adb_message) );
+    
+    if (r<0) return r;
+
+#ifdef DEBUG
+    log("[writeMessage1] size:%d\r\n",r);
+    
+    int ii,jj;
+    uint8_t* buf = (uint8_t*)&message;
+    for(ii = 0 ; ii < r ; ii+=16)
+    {
+        for(jj = 0 ; jj < 16 ; jj+=2 )
+        {
+            log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]);
+            if((ii+jj) > r) break;
+        }
+        log(" : ");
+        for(jj = 0 ; jj < 16 ; jj+=2 )
+        {
+            log("%c%c",buf[ii+jj],buf[ii+jj+1]);
+            if((ii+jj) > r) break;
+        }
+        log("\r\n");
+        if((ii+jj) > r) break;
+    }
+#endif
+    
+    memcpy( msg , data , length );
+    
+    r = USBBulkTransfer( device , output_ep , msg , length );
+    log("USB SEND RET2:%d\r\n",r);
+    
+    if (r<0) return r;
+    
+#ifdef DEBUG
+    log("[writeMessage2] size:%d\r\n",r);
+    
+    buf = msg;
+    for(ii = 0 ; ii < r ; ii+=16)
+    {
+        for(jj = 0 ; jj < 16 ; jj+=2 )
+        {
+            log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]);
+            if((ii+jj) > r) break;
+        }
+        log(" : ");
+        for(jj = 0 ; jj < 16 ; jj+=2 )
+        {
+            log("%c%c",buf[ii+jj],buf[ii+jj+1]);
+            if((ii+jj) > r) break;
+        }
+        log("\r\n");
+        if((ii+jj) > r) break;
+    }
+#endif
+    
+    r = 0;
+    
+    return r;
+}
+
+/**
+ * Writes an ADB command with a string as payload.
+ *
+ * @param device USB device handle.
+ * @param command ADB command.
+ * @param arg0 first ADB argument (command dependent).
+ * @param arg0 second ADB argument (command dependent).
+ * @param str payload string.
+ * @return error code or 0 for success.
+ */
+int ADB::writeStringMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1, char * str)
+{
+    return ADB::writeMessage(device, command, arg0, arg1, strlen(str) + 1, (uint8_t*)str);
+}
+
+/**
+ * Poll an ADB message.
+ * @param message on success, the ADB message will be returned in this struct.
+ * @param poll true to poll for a packet on the input endpoint, false to wait for a packet. Use false here when a packet is expected (i.e. OKAY in response to WRTE)
+ * @return true iff a packet was successfully received, false otherwise.
+ */
+boolean ADB::pollMessage(adb_message * message, boolean poll)
+{
+    int bytesRead = 0;
+    uint8_t buf[ADB_USB_PACKETSIZE];
+
+    // Poll a packet from the USB
+    bytesRead = recv_packet_buf.GetPacket((char*)buf);
+
+    // Check if the USB in transfer was successful.
+    if (bytesRead<=0) return false;
+
+    log("[pollMessage] byteRead size:%d\r\n",bytesRead);
+    
+    // Check if the buffer contains a valid message
+    memcpy((void*)message, (void*)buf, sizeof(adb_message));
+
+    // If the message is corrupt, return.
+#if 1
+    if (message->magic != (message->command ^ 0xffffffff))
+    {
+#ifdef DEBUG
+        printf("Broken message, magic mismatch, %d bytes\r\n", bytesRead);
+        return false;
+#endif
+    }
+#endif
+    // Check if the received number of bytes matches our expected 24 bytes of ADB message header.
+    if (bytesRead != sizeof(adb_message)) return false;
+
+    return true;
+}
+
+/**
+ * Sends an ADB OPEN message for any connections that are currently in the CLOSED state.
+ */
+void ADB::openClosedConnections()
+{
+    uint32_t timeSinceLastConnect;
+    Connection * connection;
+
+    // Iterate over the connection list and send "OPEN" for the ones that are currently closed.
+    for (connection = firstConnection; connection!=NULL; connection = connection->next)
+    {
+        timeSinceLastConnect = millis() - connection->lastConnectionAttempt;
+        if (connection->status==ADB_CLOSED && timeSinceLastConnect>ADB_CONNECTION_RETRY_TIME)
+        {
+            // Issue open command.
+            ADB::writeStringMessage(_device, A_OPEN, connection->localID, 0, connection->connectionString);
+
+            // Record the last attempt time
+            connection->lastConnectionAttempt = millis();
+            connection->status = ADB_OPENING;
+
+        }
+    }
+
+}
+
+/**
+ * Handles and ADB OKAY message, which represents a transition in the connection state machine.
+ *
+ * @param connection ADB connection
+ * @param message ADB message struct.
+ */
+void ADB::handleOkay(Connection * connection, adb_message * message)
+{
+    // Check if the OKAY message was a response to a CONNECT message.
+    if (connection->status==ADB_OPENING)
+    {
+        connection->status = ADB_OPEN;
+        connection->remoteID = message->arg0;
+
+        ADB::fireEvent(connection, ADB_CONNECTION_OPEN, 0, NULL);
+    }
+
+    // Check if the OKAY message was a response to a WRITE message.
+    if (connection->status == ADB_WRITING)
+        connection->status = ADB_OPEN;
+
+}
+
+/**
+ * Handles an ADB CLOSE message, and fires an ADB event accordingly.
+ *
+ * @param connection ADB connection
+ */
+void ADB::handleClose(Connection * connection)
+{
+    // Check if the CLOSE message was a response to a CONNECT message.
+    if (connection->status==ADB_OPENING)
+        ADB::fireEvent(connection, ADB_CONNECTION_FAILED, 0, NULL);
+    else
+        ADB::fireEvent(connection, ADB_CONNECTION_CLOSE, 0, NULL);
+
+    // Connection failed
+    if (connection->reconnect)
+        connection->status = ADB_CLOSED;
+    else
+        connection->status = ADB_UNUSED;
+
+}
+
+/**
+ * Handles an ADB WRITE message.
+ *
+ * @param connection ADB connection
+ * @param message ADB message struct.
+ */
+void ADB::handleWrite(Connection * connection, adb_message * message)
+{
+    uint32_t bytesLeft = message->data_length;
+    uint8_t buf[ADB_USB_PACKETSIZE];
+    ConnectionStatus previousStatus;
+    int bytesRead;
+
+    previousStatus = connection->status;
+
+    connection->status = ADB_RECEIVING;
+    connection->dataRead = 0;
+    connection->dataSize = message->data_length;
+
+    while (bytesLeft>0)
+    {
+        int len = bytesLeft < ADB_USB_PACKETSIZE ? bytesLeft : ADB_USB_PACKETSIZE;
+
+        // Read payload
+        bytesRead = recv_packet_buf.GetPacket((char*)buf);
+        
+
+        // Poll the USB layer.
+        USBLoop();
+        
+        log("[handleWrite] byteRead size:%d\r\n",bytesRead);
+
+//        if (len != bytesRead)
+//            printf("bytes read mismatch: %d expected, %d read, %ld left\r\n", len, bytesRead, bytesLeft);
+
+        // Break out of the read loop if there's no data to read :(
+        if (bytesRead==-1) break;
+        else if(bytesRead!=0)
+        {
+            connection->dataRead += len;
+            ADB::fireEvent(connection, ADB_CONNECTION_RECEIVE, len, buf);
+
+            bytesLeft -= bytesRead;
+        }
+    }
+
+    // Send OKAY message in reply.
+    bytesRead = ADB::writeEmptyMessage(_device, A_OKAY, message->arg1, message->arg0);
+
+    connection->status = previousStatus;
+    
+}
+
+/**
+ * Close all ADB connections.
+ *
+ * @param connection ADB connection
+ * @param message ADB message struct.
+ */
+void ADB::closeAll()
+{
+    Connection * connection;
+
+    // Iterate over all connections and close the ones that are currently open.
+    for (connection = firstConnection; connection != NULL; connection = connection->next)
+        if (!(connection->status==ADB_UNUSED || connection->status==ADB_CLOSED))
+            ADB::handleClose(connection);
+
+}
+
+/**
+ * Handles an ADB connect message. This is a response to a connect message sent from our side.
+ * @param message ADB message.
+ */
+void ADB::handleConnect(adb_message * message)
+{
+    unsigned int bytesRead;
+    uint8_t buf[MAX_BUF_SIZE];
+    uint16_t len;
+
+    // Read payload (remote ADB device ID)
+    len = message->data_length < MAX_BUF_SIZE ? message->data_length : MAX_BUF_SIZE;
+    bytesRead = recv_packet_buf.GetPacket((char*)buf);
+    
+    log("[handleConnect] byteRead size:%d\r\n",bytesRead);
+
+    // Signal that we are now connected to an Android device (yay!)
+    connected = true;
+
+    // Fire event.
+    ADB::fireEvent(NULL, ADB_CONNECT, len, buf);
+
+}
+
+/**
+ * This method is called periodically to check for new messages on the USB bus and process them.
+ */
+void ADB::poll()
+{
+    Connection * connection;
+    adb_message message;
+
+    // Poll the USB layer.
+    USBLoop();
+
+    // If no USB device, there's no work for us to be done, so just return.
+    if (_device==0) return;
+
+    // If not connected, send a connection string to the device.
+    if (!connected)
+    {
+        ADB::writeStringMessage(_device, A_CNXN, 0x01000000, 4096, (char*)"host::microbridge");
+        for(int ii=0;ii<400;ii++)
+        {
+            USBLoop();
+            wait_ms(1);
+        }
+        //wait_ms(500); // Give the device some time to respond.
+    }
+
+    // If we are connected, check if there are connections that need to be opened
+    if (connected)
+        ADB::openClosedConnections();
+
+    // Check for an incoming ADB message.
+    if (!ADB::pollMessage(&message, true))
+        return;
+
+    // Handle a response from the ADB device to our CONNECT message.
+    if (message.command == A_CNXN)
+        ADB::handleConnect(&message);
+
+    // Handle messages for specific connections
+    for (connection = firstConnection; connection != NULL; connection = connection->next)
+    {
+        if(connection->status!=ADB_UNUSED && connection->localID==message.arg1)
+        {
+            switch(message.command)
+            {
+            case A_OKAY:
+                printf("HANDLE OKEY\r\n");
+                ADB::handleOkay(connection, &message);
+                break;
+            case A_CLSE:
+                printf("HANDLE CLOSE\r\n");
+                ADB::handleClose(connection);
+                break;
+            case A_WRTE:
+                printf("HANDLE WRITE\r\n");
+                ADB::handleWrite(connection, &message);
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+}
+
+void ADB::AdbreadCallback(int device, int endpoint, int status, u8* buf, int len, void* userData) {
+    
+    recv_packet_buf.PutPacket((char*)buf,len);
+    
+#ifdef DEBUG
+    log("[AdbreadCallback] size:%d\r\n",len);
+    
+    int ii,jj;
+    for(ii = 0 ; ii < len ; ii+=16)
+    {
+        for(jj = 0 ; jj < 16 ; jj+=2 )
+        {
+            log("%02X%02X ",buf[ii+jj],buf[ii+jj+1]);
+            if((ii+jj) > len) break;
+        }
+        log(" : ");
+        for(jj = 0 ; jj < 16 ; jj+=2 )
+        {
+            log("%c%c",buf[ii+jj],buf[ii+jj+1]);
+            if((ii+jj) > len) break;
+        }
+        log("\r\n");
+        if((ii+jj) > len) break;
+    }
+#endif
+    USBBulkTransfer(device, endpoint ,readbuff,sizeof(readbuff), AdbreadCallback, userData);
+  //  wait_ms(4);
+}
+
+/**
+ * Checks whether the a connected USB device is an ADB device and populates a configuration record if it is.
+ *
+ * @param device USB device.
+ * @param handle pointer to a configuration record. The endpoint device address, configuration, and endpoint information will be stored here.
+ * @return true iff the device is an ADB device.
+ */
+boolean ADB::isAdbDevice(int device, int configuration, int interfaceNumber)
+{
+    boolean ret = false;
+    
+    log("connecting Android \r\n");
+    
+    _device = device;
+    _configuration = configuration;
+    _interfaceNumber = interfaceNumber;
+    
+    log("device = %d configuration = %d interfaceNumber = %d\r\n", device, configuration, interfaceNumber);
+    
+    int err;
+    
+    u8 buffer[255];
+    err = GetDescriptor(_device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,4);
+    
+    if (err < 0) {
+        log("Failed to get descriptor\r\n");
+        return(ret);
+    }
+    
+    int len = buffer[2] | (buffer[3] << 8);
+    if (len > sizeof(buffer)) {
+        log("config descriptor too large\r\n");
+        /* might want to truncate here */
+        return(ret);
+    }
+    err = GetDescriptor(_device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,len);
+    u8* p = buffer;
+    input_ep=0;
+    output_ep=0;
+    EndpointDescriptor *epDesc;
+    
+    log("Descriptor size:%d\r\n",len);
+    int ii,jj;
+    for(ii = 0 ; ii < len ; ii+=16)
+    {
+        for(jj = 0 ; jj < 16 ; jj+=2 )
+        {
+            log("%02X%02X ",buffer[ii+jj],buffer[ii+jj+1]);
+            if((ii+jj) > len) break;
+        }
+        log("\r\n");
+        if((ii+jj) > len) break;
+    }
+    u8 interface_num = 0;
+    
+    while (p<(buffer+len)) {
+        u8 descLen  = p[0];
+        u8 descType = p[1];
+        log("descLen=%d,descType=%d\r\n",descLen,descType);
+        switch (descType) {
+            case DESCRIPTOR_TYPE_CONFIGURATION:
+                log("config desc\r\n");
+                break;
+            case DESCRIPTOR_TYPE_INTERFACE:
+                interface_num = p[2];
+                log("interface desc num[%d]\r\n",interface_num);
+                break;
+            case DESCRIPTOR_TYPE_ENDPOINT:
+                epDesc=(EndpointDescriptor*)p;
+                if( interface_num == 1 )
+                {
+                    if (!input_ep && (epDesc->bEndpointAddress& 0x80)) {
+                        input_ep=epDesc->bEndpointAddress& 0x7f;
+                        //PacketSize drop
+                        log("input Endpoint address=%d,wMaxPacketSize=%d,bmAttributes=%d\r\n",input_ep,epDesc->wMaxPacketSize,epDesc->bmAttributes);
+
+                    } else if (!output_ep) {
+                        output_ep=epDesc->bEndpointAddress& 0x7f;
+                        //PacketSize drop
+                        log("output Endpoint address=%d,wMaxPacketSize=%d,bmAttributes=%d\r\n",output_ep,epDesc->wMaxPacketSize,epDesc->bmAttributes);
+                    } else {
+                        //other
+                        log("non input,output Endpoint address=%d,wMaxPacketSize=%d,bmAttributes=%d\r\n",input_ep,epDesc->wMaxPacketSize,epDesc->bmAttributes);
+                    }
+                }
+                break;
+            default:
+                log("unkown desc type(%d) \r\n",descType);
+        }
+        p+=descLen;
+    }
+    
+    if (!(input_ep && output_ep)) {
+        log("can't find accessory endpoints\r\n");
+        return(false);
+    }
+    
+    log("SetConfiguration\r\n");
+    err = SetConfiguration(device,configuration);
+    if (err < 0) {
+        log("SetConfiguration error\r\n");
+        return(false);
+    }
+    
+    log("interrupt setup\r\n");
+    //interrupt setup
+    if (IO_PENDING!=USBBulkTransfer(_device,input_ep|0x80,readbuff,sizeof(readbuff),AdbreadCallback,NULL))    return(ret);
+    
+    log("ADB Standby\r\n");
+    ret = true;
+    
+    return(ret);
+}
+
+
+void desconnect(void)
+{
+    ADB::closeAll();
+    _device = 0;
+    connected = false;
+}
+
+/**
+ * Write a set of bytes to an open ADB connection.
+ *
+ * @param connection ADB connection to write the data to.
+ * @param length number of bytes to transmit.
+ * @param data data to send.
+ * @return number of transmitted bytes, or -1 on failure.
+ */
+int ADB::write(Connection * connection, uint16_t length, uint8_t * data)
+{
+    int ret;
+
+    // First check if we have a working ADB connection
+    if (_device==0 || !connected) return -1;
+
+    // Check if the connection is open for writing.
+    if (connection->status != ADB_OPEN) return -2;
+
+    // Write payload
+    ret = ADB::writeMessage(_device, A_WRTE, connection->localID, connection->remoteID, length, data);
+    if (ret==0)
+        connection->status = ADB_WRITING;
+
+    return ret;
+}
+
+/**
+ * Write a string to an open ADB connection. The trailing zero is not transmitted.
+ *
+ * @param connection ADB connection to write the data to.
+ * @param length number of bytes to transmit.
+ * @param data data to send.
+ * @return number of transmitted bytes, or -1 on failure.
+ */
+int ADB::writeString(Connection * connection, char * str)
+{
+    int ret;
+
+    // First check if we have a working ADB connection
+    if (_device==0 || !connected) return -1;
+
+    // Check if the connection is open for writing.
+    if (connection->status != ADB_OPEN) return -2;
+
+    // Write payload
+    ret = ADB::writeStringMessage(_device, A_WRTE, connection->localID, connection->remoteID, str);
+    if (ret==0)
+        connection->status = ADB_WRITING;
+
+    return ret;
+}
+
+/**
+ * Write a set of bytes to this ADB connection.
+ *
+ * @param length number of bytes to transmit.
+ * @param data data to send.
+ * @return number of transmitted bytes, or -1 on failure.
+ */
+int Connection::write(uint16_t length, uint8_t * data)
+{
+    return ADB::write(this, length, data);
+}
+
+/**
+ * Write a string to this connection.
+ *
+ * @param length number of bytes to transmit.
+ * @param data data to send.
+ * @return number of transmitted bytes, or -1 on failure.
+ */
+int Connection::writeString(char * str)
+{
+    return ADB::writeString(this, str);
+}
+
+/**
+ * Checks if the connection is open for writing.
+ * @return true iff the connection is open and ready to accept write commands.
+ */
+bool Connection::isOpen()
+{
+    return this->status == ADB_OPEN;
+}
+
+
+/** from USBHost load function. initialize Android device**/
+void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc) {
+    char s[128];
+    
+    log("LoadDevice %d %02X:%02X:%02X\r\n",device,interfaceDesc->bInterfaceClass,interfaceDesc->bInterfaceSubClass,interfaceDesc->bInterfaceProtocol);
+    
+    for (int i = 1; i < 4; i++) {
+        if (GetString(device,i,s,sizeof(s)) < 0)
+            break;
+        printf("%d: %s\r\n",i,s);
+    }
+    
+    // Adb?
+    if(1)
+    {
+        ADB::isAdbDevice(device,1,2);
+    }
+    
+}
diff -r 000000000000 -r dde3f92088d5 ADB/Adb.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ADB/Adb.h	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,152 @@
+/*
+    Copyright 2011 Niels Brouwers
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.#include <string.h>
+*/
+
+/* Changed by Junichi Katsu */
+
+#ifndef __adb_h__
+#define __adb_h__
+
+#include "mbed.h"
+#include "USBHost.h"
+#include "PacketBuffer.h"
+
+typedef bool boolean;
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+
+
+#define MAX_PAYLOAD 4096;
+
+#define A_SYNC 0x434e5953
+#define A_CNXN 0x4e584e43
+#define A_OPEN 0x4e45504f
+#define A_OKAY 0x59414b4f
+#define A_CLSE 0x45534c43
+#define A_WRTE 0x45545257
+
+#define ADB_CLASS 0xff
+#define ADB_SUBCLASS 0x42
+#define ADB_PROTOCOL 0x1
+
+#define ADB_USB_PACKETSIZE 0x40
+#define ADB_CONNECTION_RETRY_TIME 1000
+
+typedef struct
+{
+    uint8_t address;
+    uint8_t configuration;
+    uint8_t interface;
+    uint8_t inputEndPointAddress;
+    uint8_t outputEndPointAddress;
+} adb_usbConfiguration;
+
+typedef struct
+{
+    // Command identifier constant
+    uint32_t command;
+
+    // First argument
+    uint32_t arg0;
+
+    // Second argument
+    uint32_t arg1;
+
+    // Payload length (0 is allowed)
+    uint32_t data_length;
+
+    // Checksum of data payload
+    uint32_t data_check;
+
+    // Command ^ 0xffffffff
+    uint32_t magic;
+
+} adb_message;
+
+typedef enum
+{
+    ADB_UNUSED = 0,
+    ADB_CLOSED,
+    ADB_OPEN,
+    ADB_OPENING,
+    ADB_RECEIVING,
+    ADB_WRITING
+} ConnectionStatus;
+
+typedef enum
+{
+    ADB_CONNECT = 0,
+    ADB_DISCONNECT,
+    ADB_CONNECTION_OPEN,
+    ADB_CONNECTION_CLOSE,
+    ADB_CONNECTION_FAILED,
+    ADB_CONNECTION_RECEIVE
+} adb_eventType;
+
+class Connection;
+
+// Event handler
+typedef void(adb_eventHandler)(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data);
+
+class Connection
+{
+private:
+public:
+    char * connectionString;
+    uint32_t localID, remoteID;
+    uint32_t lastConnectionAttempt;
+    uint16_t dataSize, dataRead;
+    ConnectionStatus status;
+    boolean reconnect;
+    adb_eventHandler * eventHandler;
+    Connection * next;
+
+    int write(uint16_t length, uint8_t * data);
+    int writeString(char * str);
+    bool isOpen();
+};
+
+class ADB
+{
+
+private:
+    static void fireEvent(Connection * connection, adb_eventType type, uint16_t length, uint8_t * data);
+    static int writeEmptyMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1);
+    static int writeMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1, uint32_t length, uint8_t * data);
+    static int writeStringMessage(int device, uint32_t command, uint32_t arg0, uint32_t arg1, char * str);
+    static boolean pollMessage(adb_message * message, boolean poll);
+    static void openClosedConnections();
+    static void handleOkay(Connection * connection, adb_message * message);
+    static void handleClose(Connection * connection);
+    static void handleWrite(Connection * connection, adb_message * message);
+    static void handleConnect(adb_message * message);
+    static void AdbreadCallback(int device, int endpoint, int status, uint8_t* buf, int len, void* userData);
+    
+public:
+    static void init();
+    static void poll();
+
+    static void setEventHandler(adb_eventHandler * handler);
+    virtual void setupDevice()=0;
+    static Connection * addConnection(const char * connectionString, boolean reconnect, adb_eventHandler * eventHandler);
+    static int write(Connection * connection, uint16_t length, uint8_t * data);
+    static int writeString(Connection * connection, char * str);
+    
+    static boolean isAdbDevice(int device, int configuration, int interfaceNumber);
+    static void closeAll();
+};
+
+#endif
diff -r 000000000000 -r dde3f92088d5 PacketBuffer/PacketBuffer.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PacketBuffer/PacketBuffer.cpp	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,84 @@
+
+/** @file PacketBuffer.cpp
+ * @brief Ring Buffer
+ */
+
+#include "PacketBuffer.h"
+
+
+PacketBuffer::PacketBuffer(int num,int packet_size)
+{
+    max_num = num;
+    max_size = packet_size;
+
+    p_buf = new PacketBufInf[num];
+        
+    for(int i = 0 ; i < num ; i++)
+    {
+        p_buf[i].buf = new char[packet_size];
+        p_buf[i].size = 0;
+    }
+    addr_w = 0;
+    addr_r = 0;
+}
+
+PacketBuffer::~PacketBuffer()
+{
+    
+    for(int i = 0 ; i < max_num ; i++)
+    {
+        delete [] p_buf[i].buf;
+    }
+    delete [] p_buf;
+}
+
+int PacketBuffer::PutPacket(char *packet, int len)
+{
+    int next;
+    
+    if(max_size < len) return(-1);
+     
+    next = (addr_w + 1) % max_num;
+    
+    if( next == addr_r ) return(0);
+    
+    memcpy( p_buf[addr_w].buf , packet , len );
+    
+    p_buf[addr_w].size = len;
+    
+    addr_w = next;
+    
+    return(len);
+}
+
+int PacketBuffer::GetPacket(char *packet)
+{
+    int len;
+    
+    if( addr_w == addr_r ) return(0);
+    
+    len = p_buf[addr_r].size;
+    
+    memcpy( packet , p_buf[addr_r].buf , len );
+    
+    addr_r = (addr_r + 1) % max_num;
+    
+    return len;
+}
+
+int PacketBuffer::available () {
+    if (addr_w < addr_r) {
+        return addr_r - addr_w - 1;
+    } else {
+        return (max_num - addr_w) + addr_r - 1;
+    }
+}
+
+int PacketBuffer::use () {
+    return max_num - available() - 1;
+}
+
+void PacketBuffer::clear () {
+    addr_w = 0;
+    addr_r = 0;
+}
diff -r 000000000000 -r dde3f92088d5 PacketBuffer/PacketBuffer.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PacketBuffer/PacketBuffer.h	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,49 @@
+
+
+/** @file PacketBuffer.h
+ * @brief Packet Buffer
+ */
+
+#ifndef PacketBuffer_H
+#define PacketBuffer_H
+
+#include "mbed.h"
+
+typedef struct
+{
+    char *buf;
+    int size;
+} PacketBufInf;
+
+class PacketBuffer {
+public:
+    /** init Stack class
+     * @param num  buffering packet num
+     * @param packet_size size of packet(max size)
+     */
+    PacketBuffer(int num,int packet_size);
+    ~PacketBuffer();
+
+    /** put to Packet buffer
+     * @param packet packet data
+     * @param len packet length
+     * @return put length
+     */
+    int PutPacket(char *packet, int len);
+
+    /** get from ring buffer
+     * @param packet packet data
+     * @return get length
+     */
+    int GetPacket(char *packet);
+
+    void clear();
+    int available();
+    int use();
+
+private:
+    PacketBufInf *p_buf;
+    int max_num,max_size;
+    int addr_w, addr_r;
+};
+#endif
\ No newline at end of file
diff -r 000000000000 -r dde3f92088d5 TextLCD.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TextLCD.lib	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/simon/code/TextLCD/#44f34c09bd37
diff -r 000000000000 -r dde3f92088d5 USBHost/USBHost.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.cpp	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,1097 @@
+
+/*
+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"
+#ifndef  USBHOST_LOG
+
+#define DESC_INDEX 0
+
+//    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 0
+#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)
+                {
+                    LOG("Sorting Callbacks %i\r\n\r",endpoint->CurrentState);
+                    _callbacksPending--;
+                    endpoint->CurrentState = Endpoint::Idle;
+                    LOG("SatusChanged %i\r\n\r",endpoint->CurrentState);
+                    LOG("CallBack DataSize:%d",endpoint->Length);
+                    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\r\r\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\r\r\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\r\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\r\r\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\r\r\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next);
+        //LOG("%04X ED %08X %08X %08X\r\r\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\r\r\n",ep,endpoint->TDHead.Control);
+
+            if (status != 0)
+            {
+                LOG("ProcessDoneQueue status %02X %d\r\r\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========\r\r\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\r\r\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("\r\nClass %02X found %04X:%04X\r\r\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);
+        r = SetConfigurationAndInterface(device,1,1,&desc);
+        //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,DESC_INDEX,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)\r\r\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)\r\r\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\r\r\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\r\r\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\r\r\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\r\r\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 & UnrecoverableError) //Error
+    {
+      LOG("USB_IRQHandler UnrecoverableError Please reset\r\r\n");
+    }
+
+
+    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)
+{
+    LOG("Waiting\r\n\r");
+    if (endpoint->CurrentState == Endpoint::NotQueued)
+        return 0;
+    while (endpoint->CurrentState != Endpoint::Idle)
+        //LOG("Loopz");
+        USBLoop();    // May generate callbacks, mount or unmount devices etc
+    int status = endpoint->Status();
+    if (status == 0)
+        return endpoint->Length;
+        LOG("DATA SENT\r\n\r");
+    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);
+    LOG("before ep=%x,callback=%p\r\r\n",endpoint,endpoint->Callback);
+    endpoint->Flags = flags;
+    endpoint->Data = data;
+    endpoint->Length = length;
+    endpoint->Callback = callback;
+    endpoint->UserData = userData;
+    LOG("ep=%x,callback=%p\r\r\n",ep,callback);
+    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);
+}
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r dde3f92088d5 USBHost/USBHost.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.h	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,221 @@
+
+/*
+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
+
+//log mode on off
+//#define USBHOST_LOG
+#include "Adb.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_STANDARD     0x00
+#define  REQUEST_TYPE_CLASS     0x20
+#define  REQUEST_TYPE_VENDOR     0x40
+#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
+
+/* HID Request Codes */ 
+#define HID_REQUEST_GET_REPORT          0x01 
+#define HID_REQUEST_GET_IDLE            0x02 
+#define HID_REQUEST_GET_PROTOCOL        0x03 
+#define HID_REQUEST_SET_REPORT          0x09 
+#define HID_REQUEST_SET_IDLE            0x0A 
+#define HID_REQUEST_SET_PROTOCOL        0x0B 
+ 
+/* HID Report Types */ 
+#define HID_REPORT_INPUT                0x01 
+#define HID_REPORT_OUTPUT               0x02 
+#define HID_REPORT_FEATURE              0x03 
+
+
+//        -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 dde3f92088d5 USBHost/USBHost_log.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost_log.cpp	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,1175 @@
+
+/*
+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"
+//#define USBHOST_LOG
+#ifdef  USBHOST_LOG
+
+//    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()
+    {
+   // printf("Enter Loop \r\r\n");
+        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;
+                    LOG("CurrentState Change  Idle  endpoint(%d) currentState =%d\r\r\n",endpoint->Address(),endpoint->CurrentState);
+                    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;
+        }
+    
+   // printf("Outer Loop \r\r\n");
+    }
+
+    //    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\r\r\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\r\r\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\r\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)
+    {
+        //Makoto edit comment out 
+       // LOG("Transfer start\r\r\n");
+        LOG("Transfer ep=%02X Token:%d Len:%d State:%d\r\r\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\r\r\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next);
+        //LOG("%04X ED %08X %08X %08X\r\r\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd);
+        
+        //LOG("Transfer run01\r\r\n");
+        switch (endpoint->Flags & 3)
+        {
+            case ENDPOINT_CONTROL:
+                LOG("Transfer run ENDPOINT_CONTROL\r\r\n");
+                LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED);    // May change state NotQueued->Idle
+                //LOG("Transfer run02\r\r\n");
+                LOG("endpoint->CurrentState change %d->%d\r\r\n",endpoint->CurrentState,state);
+                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:
+                LOG("Transfer run ENDPOINT_BULK\r\r\n");
+                LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED);
+                LOG("endpoint->CurrentState change %d->%d\r\r\n",endpoint->CurrentState,state);
+                endpoint->CurrentState = state;
+                LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled;
+                LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable;
+                break;
+
+            case ENDPOINT_INTERRUPT:
+                LOG("Transfer run ENDPOINT_INTERRUPT\r\r\n");
+                CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]);
+                LOG("endpoint->CurrentState change %d->%d\r\r\n",endpoint->CurrentState,state);
+                endpoint->CurrentState = state;
+                LPC_USB->HcControl |= PeriodicListEnable;
+                break;
+        }
+        
+        LOG("Transfer end\r\r\n");
+        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)
+    {
+    
+    LOG("<<ProcessDoneQueue enter>>\r\r\n");
+        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\r\r\n",ep,endpoint->TDHead.Control);
+
+            if (status != 0)
+            {
+                LOG("ProcessDoneQueue status %02X %d\r\r\n",ep,status);
+                LOG("CurrentState Change  Idle endpoint(%d) currentState =%d\r\r\n",endpoint->Address(),endpoint->CurrentState);
+                endpoint->CurrentState = Endpoint::Idle;
+                
+                
+            } else {
+                switch (endpoint->CurrentState)
+                {
+                    case Endpoint::SetupQueued:
+                        if (endpoint->Length == 0)
+                        {
+                            LOG("ProcessDoneQueue endpoint->Length == 0 endpoint->CurrentState=%d\r\r\n",endpoint->CurrentState);
+                            Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Skip Data Phase
+                        }
+                        else
+                        {
+                            LOG("ProcessDoneQueue endpoint->Length != 0 endpoint->CurrentState=%d\r\r\n",endpoint->CurrentState);
+                            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)
+                        {
+                            LOG("ProcessDoneQueue ep == 0 endpoint->CurrentState=%d\r\r\n",endpoint->CurrentState);
+                            Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Data is done, now Status, Control only
+                        }
+                        else
+                        {
+                        
+                            LOG("ProcessDoneQueue ep != 0 endpoint->CurrentState=%d\r\r\n",endpoint->CurrentState);
+                            endpoint->CurrentState = Endpoint::Idle;
+                            LOG("CurrentState Change  Idle endpoint(%d) currentState =%d\r\r\n",endpoint->Address(),endpoint->CurrentState);
+                        }
+                        break;
+
+                    case Endpoint::StatusQueued:    // Transaction is done
+                        LOG("CurrentState Change  Idle endpoint(%d) currentState =%d\r\r\n",endpoint->Address(),endpoint->CurrentState);
+                        endpoint->CurrentState = Endpoint::Idle;
+                        break;
+                }
+            }
+
+            //      Complete, flag if we need a callback
+            if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle)
+            {
+                endpoint->CurrentState = Endpoint::CallbackPending;
+                _callbacksPending++;
+            }
+        }
+        LOG("<<ProcessDoneQueue out>>\r\r\n");
+    }
+
+    //    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========\r\r\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\r\r\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("\r\nClass %02X found %04X:%04X\r\r\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)\r\r\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)\r\r\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\r\r\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\r\r\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\r\r\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\r\r\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
+{
+LOG("USB_IRQHandler start \r\r\n");
+    u32 int_status = LPC_USB->HcInterruptStatus;
+    LOG("USB_IRQHandler int_status=%0x\r\r\n",int_status);
+    
+    if(int_status & UnrecoverableError) //Error
+    {
+      LOG("USB_IRQHandler UnrecoverableError Please reset\r\r\n");
+    }
+
+    if(int_status & MasterInterruptEnable)
+    {
+      LOG("USB_IRQHandler MasterInterruptEnable\r\r\n");
+    }
+    
+    if(int_status &OwnershipChange)
+    {
+      LOG("USB_IRQHandler OwnershipChange\r\r\n");
+    }
+
+    if(int_status &FrameNumberOverflow)
+    {
+      LOG("USB_IRQHandler FrameNumberOverflow\r\r\n");
+    }
+    if(int_status&ResumeDetected)
+    {
+      LOG("USB_IRQHandler ResumeDetected\r\r\n");
+    }
+    if(int_status&StartofFrame)
+    {
+      LOG("USB_IRQHandler StartofFrame\r\r\n");
+    }
+
+
+    if (int_status & RootHubStatusChange)    //    Root hub status change
+    {
+      LOG("USB_IRQHandler _rootHubStatusChange %0x->%0x \r\r\n", _controller._rootHubStatusChange, _controller._rootHubStatusChange+1);
+        _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;
+         LOG("USB_IRQHandler head=%0x\r\r\n",head);
+    }             
+    LPC_USB->HcInterruptStatus = int_status;
+
+    if (head)
+       _controller.ProcessDoneQueue(head);     // TODO - low bit can be set BUGBUG
+LOG("USB_IRQHandler end \r\r\n");
+}
+
+//====================================================================================
+//====================================================================================
+//      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)
+{
+    LOG("WaitIODone start\r\r\n");
+    if (endpoint->CurrentState == Endpoint::NotQueued)
+        return 0;
+    while (endpoint->CurrentState != Endpoint::Idle)
+    {
+       LOG("WaitIODone goto  USBloop  endpoint->CurrentState =%d \r\r\n",endpoint->CurrentState);
+        USBLoop();    // May generate callbacks, mount or unmount devices etc
+    }
+    int status = endpoint->Status();
+    
+    LOG("WaitIODone end\r\r\n");
+    if (status == 0)
+        return endpoint->Length;
+    return -status;
+}
+
+int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData)
+{
+   //LOG("USBTRANSFER start\r\r\n");
+    Endpoint* endpoint = _controller.GetEndpoint(device,ep);
+    if (!endpoint)
+    {
+        LOG("USBTRANSFER error Endpoint not found!!\r\r\n");
+        return ERR_ENDPOINT_NOT_FOUND;
+    }
+  
+   //LOG("USBTRANSFER run01\r\r\n");      
+    WaitIODone(endpoint);
+    endpoint->Flags = flags;
+    endpoint->Data = data;
+    endpoint->Length = length;
+    endpoint->Callback = callback;
+    endpoint->UserData = userData;
+    //LOG("USBTRANSFER run02\r\r\n");
+    if (ep == 0)
+    {
+      LOG("USBTRANSFER ep == 0(Setup) ------------------------------\r\r\n");
+        _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued);
+    }
+    else
+    {
+      LOG("USBTRANSFER ep != 0\r\r\n");
+        _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued);
+    }
+    if (callback)
+    {
+       LOG("USBTRANSFER end io_pending\r\r\n");
+        return IO_PENDING;
+    }
+    LOG("USBTRANSFER end wait io done \r\r\n");
+    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;
+    LOG("USBControlTransfer(device=%d,reqtype=%d,req=%d,value=%d,index=%d,data=%p,len=%d,callbak=%p,udata=%p)\r\r\n",
+        device,request_type,request,value,index,data,length,callback,userData);
+    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);
+}
+
+#endif
\ No newline at end of file
diff -r 000000000000 -r dde3f92088d5 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,62 @@
+#include "mbed.h"
+#include "Adb.h"
+#include <TextLCD.h>
+TextLCD lcd(p11, p12, p27, p28, p29, p30);
+Connection * connection;
+
+Serial pc(USBTX, USBRX);
+PwmOut servo1(p26);
+PwmOut servo2(p25);
+DigitalIn sw1(p13);
+DigitalOut led(LED1);
+
+void adbEventHandler(Connection * connection, adb_eventType event, uint16_t length, uint8_t * data)
+{
+    if (event == ADB_CONNECTION_RECEIVE)
+    {
+        printf("[ADB RECV]:%d   %d\r\n",data[0],data[1]);
+        float val = ((float)data[0] * 5.5) + 1000.0;
+        servo1.pulsewidth_us(val);
+        val = ((float)data[1] * 5.5) + 1000.0;
+        servo2.pulsewidth_us(val);
+    }
+}
+
+int main()
+{
+    int now=0,old;
+    unsigned short data = 0;
+    
+    pc.baud(115200);
+    servo1.period_us(20000);
+    servo2.period_us(20000);
+    sw1.mode(PullUp);
+    
+    
+    // Initialise the ADB subsystem.  
+    ADB::init();
+    // Open an ADB stream to the phone's shell. Auto-reconnect
+    connection = ADB::addConnection("tcp:4567", true, adbEventHandler);
+    
+    while(1)
+    {
+    
+        ADB::poll();
+        
+        lcd.locate(0, 0);
+        lcd.printf("MicroBridge Test");
+        
+        old = now;
+        now = sw1;
+        if((now == 1)&&(old==0))
+        {
+            printf("down key\r\n");
+            connection->write(2, (unsigned char*)&data);
+            lcd.locate(0, 1);
+            lcd.printf("COUNT = %d",data);
+
+            data++;
+        }
+        led = sw1;
+    }
+}
diff -r 000000000000 -r dde3f92088d5 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Aug 21 14:36:35 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0