Student project by David Berlin and Boris Dogadov made for the Embedded Systems Workshop course given in Tel-Aviv University on 2010 by Sivan Toledo. Visit the project website for more details: http://davidberlin.co.il/sadna/ .

Dependencies:   EthernetNetIf NTPClient_NetServices mbed HTTPServer HTTPClient CyaSSL

Files at this revision

API Documentation at this revision

Comitter:
sivan_toledo
Date:
Sun Apr 17 21:30:10 2011 +0000
Child:
1:b05231650f32
Commit message:

Changed in this revision

CyaSSL.lib Show annotated file Show diff for this revision Revisions of this file
Dropbox/Dropbox.cpp Show annotated file Show diff for this revision Revisions of this file
Dropbox/Dropbox.h Show annotated file Show diff for this revision Revisions of this file
Dropbox/HTTPFileSender.cpp Show annotated file Show diff for this revision Revisions of this file
Dropbox/HTTPFileSender.h Show annotated file Show diff for this revision Revisions of this file
Dropbox/base64.cpp Show annotated file Show diff for this revision Revisions of this file
Dropbox/base64.h Show annotated file Show diff for this revision Revisions of this file
EthernetNetIf.lib Show annotated file Show diff for this revision Revisions of this file
FATFileSystem.lib Show annotated file Show diff for this revision Revisions of this file
HTTPClient.lib Show annotated file Show diff for this revision Revisions of this file
HTTPServer.lib Show annotated file Show diff for this revision Revisions of this file
HttpHandlerSetup.cpp Show annotated file Show diff for this revision Revisions of this file
HttpHandlerSetup.h Show annotated file Show diff for this revision Revisions of this file
HttpHandlerUsbBrowser.cpp Show annotated file Show diff for this revision Revisions of this file
HttpHandlerUsbBrowser.h Show annotated file Show diff for this revision Revisions of this file
MassStorage/MassStorage.cpp Show annotated file Show diff for this revision Revisions of this file
MassStorage/UsbStorage.h Show annotated file Show diff for this revision Revisions of this file
NTPClient.lib Show annotated file Show diff for this revision Revisions of this file
USBHost/AutoEvents.cpp 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/Utils.cpp Show annotated file Show diff for this revision Revisions of this file
USBHost/Utils.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CyaSSL.lib	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/toddouska/code/CyaSSL/#5045d2638c29
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Dropbox/Dropbox.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,158 @@
+#include "Dropbox.h"
+#include "HTTPClient.h"
+#include "HTTPFileSender.h"
+#include "base64.h"
+#include "url.h"
+#include "ctc_hmac.h"
+#include "NTPClient.h"
+#include "HTTPData.h"
+
+// NET
+NTPClient ntpClient;
+HTTPResult result;
+
+// Dropbox
+string consumer_token = "p4t8cn8b3ddci2d";
+string consumer_token_secret = "wtib99x350qo5l6";
+char token[16] = {0};
+char token_secret[16] = {0};
+bool completed = false;
+int v = 6000;
+char buffer[1024] = {0};
+
+extern DigitalOut led1;
+extern DigitalOut led3;
+extern void USBLoop();
+
+Timer timer;
+
+void request_callback(HTTPResult r)
+{
+  result = r;
+  completed = true;
+}
+
+bool dropbox_getToken(char* username, char* password)
+{
+    HTTPClient client;
+    HTTPText data;
+    
+    /* Request Token */ 
+    printf("Requesting token\r\n");
+    
+    char request[128] = {0};
+    sprintf(request,
+            "http://api.getdropbox.com/0/token?oauth_consumer_key=p4t8cn8b3ddci2d&email=%s&password=%s",
+            username,
+            password);
+    
+    printf(request);
+    HTTPResult result = client.get(request, &data);
+                                   
+    if (result != HTTP_OK)
+    {
+        printf("R: %d", result);
+        return false;
+    }
+    
+    const char *dataContent = data.gets();    
+
+    memcpy(token, dataContent + 11, 15); 
+    memcpy(token_secret, dataContent + 40, 15); 
+    
+    printf("Got token %s %s %s\r\n", dataContent, token, token_secret);
+    
+    return true;
+}
+
+bool dropbox_syncTime()
+{
+    /* Get Time */
+    printf("Synchronizing time\r\n");
+    Host server(IpAddr(), 123, "0.pool.ntp.org");
+    NTPResult result = ntpClient.setTime(server);
+    
+    //srand(time(NULL));
+    
+    return (result == NTP_OK);
+}
+
+    
+bool dropbox_upload(string srcFile, string dstFile)
+{
+    HTTPClient client;
+    string dst = dstFile;
+    
+    time_t currentTime = time(NULL);
+      
+    v++; //= (rand() % 9999999) + 1000;
+
+    //printf("T: %d NONCE: %d\r\n", currentTime, v); 
+    
+    memset(buffer, 0x00, 1024);
+    sprintf(buffer, 
+            "POST&http%%3A%%2F%%2Fapi-content.dropbox.com%%2F0%%2Ffiles%%2Fdropbox%%2F&file%%3D%s%%26oauth_consumer_key%%3D%s%%26oauth_nonce%%3D%d%%26oauth_signature_method%%3DHMAC-SHA1%%26oauth_timestamp%%3D%d%%26oauth_token%%3D%s",
+            dst.c_str(),
+            consumer_token.c_str(),
+            v,
+            currentTime,
+            token);
+   
+    //printf("Sig: %s %d\n\r", buffer, strlen(buffer)); 
+              
+    string key = consumer_token_secret + "&" + token_secret;
+    
+    //printf("Key: %s %d\n\r", key.c_str(), key.size()); 
+    
+    byte hash[SHA_DIGEST_SIZE];
+    Hmac hmac;
+    HmacSetKey(&hmac, SHA, (const byte*)key.c_str(), key.size());
+    HmacUpdate(&hmac, (const byte*)buffer, strlen(buffer));
+    HmacFinal(&hmac, hash);
+
+    char sig[128] = {0};
+    base64enc((char*)hash, SHA_DIGEST_SIZE, sig);
+
+    char *encodedSig = url_encode(sig);
+    
+    memset(buffer, 0x00, 1024);
+    sprintf(buffer, 
+            "http://api-content.dropbox.com/0/files/dropbox/?file=%s&oauth_consumer_key=%s&oauth_nonce=%d&oauth_timestamp=%d&oauth_token=%s&oauth_signature_method=HMAC-SHA1&oauth_signature=%s",
+            dst.c_str(),
+            consumer_token.c_str(),
+            v,
+            currentTime,
+            token,
+            encodedSig);
+            
+    //printf("Req: %s %d\n\r", buffer, strlen(buffer));
+
+    HTTPFileSender httpFile(srcFile.c_str(), dst.c_str());
+
+    HTTPText res;
+
+    //client.setTimeout(5000);
+    
+    completed = false;
+    HTTPResult postResult = client.post(buffer, httpFile, &res, request_callback);
+    
+    timer.start();
+    
+    while (!completed)
+    {
+        led1 = (timer.read_ms() % 250) >= 125;
+        USBLoop();
+        Net::poll();
+    }
+    
+    timer.stop();
+    timer.reset();
+    
+    led1 = 1;
+    
+    printf("Res: %s %d %d\n\r", res.gets(), postResult, result);
+    
+    free(encodedSig);
+    
+    return (result == HTTP_OK);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Dropbox/Dropbox.h	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,8 @@
+#include "mbed.h"
+#include <string>
+
+bool dropbox_getToken(char* username, char* password);
+
+bool dropbox_syncTime();
+
+bool dropbox_upload(string srcFile, string dstFile);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Dropbox/HTTPFileSender.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,128 @@
+#include "HTTPFileSender.h"
+#include "USBHost.h"
+
+char HTTPFileSender::header[] = "";
+char HTTPFileSender::footer[] = "\r\n\r\n--R50hrfBj5JYyfR3vF3wR96GPCC9Fd2q2pVMERvEaOE3D8LZTgLLbRpNwXek3--\r\n";
+
+HTTPFileSender::HTTPFileSender(const char *fileName, const char *dstFile)
+{
+    pos = 0;
+    
+    printf("Opening %s\n\r", fileName);
+    
+    file = fopen(fileName, "r");
+    
+    printf("Opened %d\n\r", file);
+    
+    fseek(file, 0L, SEEK_END);
+    printf("seek1\r\n");
+    fileLen = ftell(file);
+    printf("seek2\r\n");
+    fseek(file, 0L, SEEK_SET);
+    
+    printf("Size %d\n\r", fileLen);
+    
+    /*string dst = dstFile;
+    string h = ;
+    memcpy(header, h.c_str(), sizeof(header));*/
+    sprintf(header, "--R50hrfBj5JYyfR3vF3wR96GPCC9Fd2q2pVMERvEaOE3D8LZTgLLbRpNwXek3\r\nContent-Disposition: form-data; name=file; filename=%s\r\nContent-type: application/octet-stream\r\n\r\n", dstFile);
+    
+    headerSize = strlen(header);
+    footerSize = strlen(footer);
+    
+    totalLen = fileLen + strlen(header) + strlen(footer);
+}
+
+HTTPFileSender::~HTTPFileSender()
+{
+    fclose(file);
+    printf("file %d closed\r\n", file);
+}
+
+int HTTPFileSender::read(char* buf, int len)
+{
+    //printf("read requested %d bytes from file %d\n\r", len, file);
+    
+    int dataSent = 0;
+
+    //printf("Header: %d, Footer: %d\r\n", headerSize, footerSize);
+
+    if (pos >= totalLen)
+    {
+        printf("End of file\n\r");
+        return 0;
+    }
+    
+    if (pos < headerSize)
+    {
+        int bytesToCopy = headerSize - pos;
+        memcpy(buf, header + pos, bytesToCopy);
+        
+        dataSent += bytesToCopy;
+        pos += bytesToCopy;
+        
+        //printf("transfer header %d\r\n", bytesToCopy);
+    }
+    
+    //printf("Before content: %d %d\r\n", pos, dataSent);
+   
+    if (pos >= headerSize &&
+        pos < (headerSize + fileLen))
+    {
+        int bytesRead = fread(buf + dataSent, 1, len - dataSent, file);
+        
+        dataSent += bytesRead;
+        pos += bytesRead;
+        
+       // printf("transfer content %d\r\n", bytesRead);
+    }
+    
+   // printf("Before footer: %d %d\n\r", pos, dataSent);
+    
+    if (dataSent < len &&
+        pos >= (headerSize + fileLen) &&
+        pos < (headerSize + fileLen + footerSize))
+    {
+        int posInFooter = pos - fileLen - headerSize;
+        int bytesToCopy = min(footerSize - posInFooter, len - dataSent);
+        
+        memcpy(buf + dataSent, footer + posInFooter, bytesToCopy);
+        
+        dataSent += bytesToCopy;
+        pos += bytesToCopy;
+        
+       // printf("transfer footer %d\r\n", bytesToCopy);
+    }
+    
+    //printf("After: %d %d\r\n", pos, dataSent);
+    
+    //int result = fread(buf, 1, len, file);
+    
+    //printf("read %s %d bytes\r\n", buf, dataSent);
+    if (pos % 1024 == 0) printf("read %d bytes pos %d\r\n", dataSent, pos);
+        
+    return dataSent;
+}
+
+string HTTPFileSender::getDataType()
+{
+   // printf("data type read\n\r");
+    return "multipart/form-data; boundary=R50hrfBj5JYyfR3vF3wR96GPCC9Fd2q2pVMERvEaOE3D8LZTgLLbRpNwXek3";
+}
+
+int HTTPFileSender::getDataLen() 
+{ 
+   // printf("get data len %d\n\r", totalLen);
+    return totalLen; 
+}
+
+void HTTPFileSender::clear() { }
+
+int HTTPFileSender::write(const char* buf, int len)  { return 0; }
+  
+void HTTPFileSender::setDataType(const string& type) { } 
+  
+bool HTTPFileSender::getIsChunked() { return false; }
+void HTTPFileSender::setIsChunked(bool chunked) { }
+  
+void HTTPFileSender::setDataLen(int len)  { }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Dropbox/HTTPFileSender.h	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,34 @@
+#include "HTTPData.h"
+//#include "HTTPText.h"
+#include "HTTPClient.h"
+
+class HTTPFileSender : public HTTPData
+{
+ public:
+  HTTPFileSender(const char *fileName, const char* dstFile);  
+  virtual ~HTTPFileSender();
+  virtual void clear();
+  virtual int read(char* buf, int len);
+  virtual int write(const char* buf, int len);
+  
+  virtual string getDataType(); //Internet media type for Content-Type header
+  virtual void setDataType(const string& type); //Internet media type from Content-Type header
+  
+  virtual bool getIsChunked(); //For Transfer-Encoding header
+  virtual void setIsChunked(bool chunked); //From Transfer-Encoding header
+  
+  virtual int getDataLen(); //For Content-Length header
+  virtual void setDataLen(int len); //From Content-Length header, or if the transfer is chunked, next chunk length
+ private:
+    FILE *file; 
+    
+    int pos;
+    int totalLen;
+    int fileLen;
+    
+    int headerSize;
+    int footerSize;
+    
+    static char header[256];
+    static char footer[128];
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Dropbox/base64.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,59 @@
+
+ /*
+ Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+  
+ 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 "base64.h"
+ //Originaly from Rolf's iputil.c
+ 
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ 
+ #include <string.h>
+ 
+ unsigned int base64enc_len(const char *str) {
+   return (((strlen(str)-1)/3)+1)<<2;
+ }
+ 
+ void base64enc(const char *input, unsigned int length, char *output) {
+   static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+   unsigned int c, c1, c2, c3;
+   for(unsigned int i = 0, j = 0; i<length; i+=3,j+=4) {
+     c1 = ((((unsigned char)*((unsigned char *)&input[i]))));
+     c2 = (length>i+1)?((((unsigned char)*((unsigned char *)&input[i+1])))):0;
+     c3 = (length>i+2)?((((unsigned char)*((unsigned char *)&input[i+2])))):0;
+ 
+     c = ((c1 & 0xFC) >> 2);
+     output[j+0] = base64[c];
+     c = ((c1 & 0x03) << 4) | ((c2 & 0xF0) >> 4);
+     output[j+1] = base64[c];
+     c = ((c2 & 0x0F) << 2) | ((c3 & 0xC0) >> 6);
+     output[j+2] = (length>i+1)?base64[c]:'=';
+     c = (c3 & 0x3F);
+     output[j+3] = (length>i+2)?base64[c]:'=';
+   }
+   output[(((length-1)/3)+1)<<2] = '\0';
+ }
+ 
+ #ifdef __cplusplus
+ }
+ #endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Dropbox/base64.h	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,68 @@
+
+ /*
+ Copyright (c) 2010 Donatien Garnier (donatiengar [at] gmail [dot] com)
+  
+ 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 BASE64_H
+ #define BASE64_H
+ 
+ #include <string>
+ using std::string;
+ 
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ 
+ //Originaly from Rolf's iputil.h
+ 
+ unsigned int base64enc_len(const char *str);
+ 
+ void base64enc(const char *input, unsigned int length, char *output);
+ 
+ #ifdef __cplusplus
+ }
+ #endif
+ 
+
+ class Base64
+ {
+ public:
+   static string encode(const string& str)
+   {
+     char* out = new char[ base64enc_len(str.c_str()) ];
+     base64enc(str.c_str(), str.length(), out);
+     string res(out);
+     delete[] out;
+     return res;
+   }
+   
+   static string encode(const char* buf, int len)
+   {
+     char* out = new char[len];
+     base64enc(buf, len, out);
+     string res(out);
+     delete[] out;
+     return res;
+   }
+ };
+ 
+ #endif /* LWIP_UTILS_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/EthernetNetIf.lib	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mamezu/code/EthernetNetIf/#0f6c82fcde82
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FATFileSystem.lib	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_unsupported/code/fatfilesystem/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPClient.lib	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mamezu/code/HTTPClient/#62fac7f06c8d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HTTPServer.lib	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/donatien/code/HTTPServer/#d753966e4d97
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HttpHandlerSetup.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,193 @@
+#include "HttpHandlerSetup.h"
+
+bool ReadSettings(char* username, char* password)
+{
+    //printf("ReadSettings start\r\n");
+    FILE* settingsFile = fopen("/usb/DBSet.txt", "r");
+    if (settingsFile)
+    {
+       //printf("before fseek %d\n\r", settingsFile);
+       fseek(settingsFile, 9L, SEEK_SET);
+       fgets(username, 32, settingsFile);
+       fseek(settingsFile, 9L, SEEK_CUR);
+       fgets(password, 32, settingsFile);
+
+
+       int len = strlen(username); username[len - 2] = 0; // remove /r/n
+       //printf("ReadSettings %s, %s, %d, %d,  %s\r\n", username, password, len, ftell(settingsFile), data);
+       
+       fclose(settingsFile);
+    }
+    
+    return settingsFile != 0;
+}
+
+HttpHandlerSetup::HttpHandlerSetup(const char* rootPath, const char* path, TCPSocket* pTCPSocket) :
+ HTTPRequestHandler(rootPath, path, pTCPSocket)
+{
+  //printf("HttpHandlerSetup()");
+}
+
+HttpHandlerSetup::~HttpHandlerSetup()
+{
+} 
+
+void HttpHandlerSetup::doGetPageWelcome()
+{
+  //printf("doGetPageWelcome()-start\r\n");
+  const char* resp = 
+    "<html><body>"
+    "<p><span style=\"color: #a9a9a9\"><span style=\"font-size: 12px\">DropBox Sync Setup</span></span></p><p>"
+    "<p><a href=\"/Setup\">Setup</a></p>"
+    "<p><a href=\"/UsbBrowser/root/\">DiskOnKey browser</a></p>"
+    "</form><p>&nbsp;</p>"
+    "<p><strong><span style=\"color: #000080\">BDDB Ltd.</span></strong></p>"
+    "</body>"
+    "</html>";
+  
+  int len = strlen(resp);
+  setContentLen(len);
+  respHeaders()["Connection"] = "close";
+  writeData(resp, len);
+}
+
+void HttpHandlerSetup::UpdateSettingsFile()
+{ 
+  if (m_WasDataRead)
+  {
+    return;
+  }
+
+  char buffer[256];
+  int dataLength = dataLen();
+  int readBytes = readData(buffer, 45 + dataLength);
+  
+  if (readBytes > 0)
+  {  
+      int offset = readBytes > dataLength ? 45 : 0; // Inconsistency id data reading
+      char* c1 = strchr(buffer, '&');
+      char* c2 = strchr(buffer + offset, '=') + 1;
+      char* c3 = strchr(c1, '=') + 1;
+      int lenU = c1 - c2;
+      int lenP = readBytes - (c3 - buffer);
+      
+      char* c2_fixed = strstr(c2, "%40");
+      if (c2_fixed) // case @ is replaced by %40
+      {
+        c2_fixed[0] = '@';
+        memcpy(c2_fixed + 1, c2_fixed + 3, lenU - (c2_fixed - c2) - 3);
+        lenU -= 2;
+        printf(c2);
+      }
+      
+      FILE* settingsFile = fopen("/usb/DBSet.txt", "w");
+      if (settingsFile)
+      {
+         fwrite("USERNAME=", 1, 9, settingsFile);
+         fwrite(c2, 1, lenU, settingsFile);
+         fwrite("\r\nPASSWORD=", 1, 11, settingsFile);
+         fwrite(c3, 1, lenP, settingsFile);
+         fclose(settingsFile);
+       
+         //printf("Updated %s, %s\r\n", c2, c3);
+       }
+       m_WasDataRead = true;      
+   }
+   
+   //printf("readBytes %d\r\n", readBytes);
+}
+
+void HttpHandlerSetup::doGet()
+{
+  //printf("Setup path %s\r\n", path());
+  if (path().size() <= 1)
+  {
+    doGetPageWelcome();
+    return;
+  }
+  
+  //printf("doGet()-start %s, %s\r\n", Username, Password);
+  const char* resp1 = 
+    "<html><body>"
+    "<p><span style=\"color: #a9a9a9\"><span style=\"font-size: 12px\">DropBox Sync Setup</span></span></p><p>"
+    "<form method=\"post\" action=\"\">"
+    "Username: <input type=\"text\" name=\"Username\" value=\"";
+  const char* resp2 = "\" /><br />Password: <input type=\"text\" name=\"Password\" value=\"";
+  const char* resp3 = 
+    "\" /><br /><input type=\"submit\" value=\"Submit\" />"
+    "</form><p>&nbsp;</p>"
+    "<p><strong><span style=\"color: #000080\">BDDB Ltd</span></strong></p>"
+    "</body>"
+    "</html>";
+
+  char username[32]="invalid", password[32]="error";
+  ReadSettings(username, password);
+  
+  int l1 = strlen(resp1), l2 = strlen(resp2), l3 = strlen(resp3);
+  int p = strlen(password), u = strlen(username);
+
+  respHeaders()["Connection"] = "close";
+  
+  setContentLen(l1 + l2 + l3 + p + u);
+  int t1 = writeData(resp1, l1);
+  int t2 = writeData(username, u);
+  int t3 = writeData(resp2, l2);
+  int t4 = writeData(password,p);
+  int t5 = writeData(resp3, l3);
+  
+  m_WasDataRead = false;
+  printf("doGet()-end\r\n");
+}
+
+void HttpHandlerSetup::doPost()
+{/*
+  map<string,string>::iterator it = reqHeaders().begin();
+  printf("printing %s\n\r", path());
+  while (it != reqHeaders().end())
+  {
+    printf("%s --- %s\r\n", it->first, it->second);
+    it++;
+  }
+ */
+  printf("doPost()-start\r\n");
+  UpdateSettingsFile();
+  
+  const char* resp = 
+    "<html><body>"
+    "<p><span style=\"color: #0080FF\"><span style=\"font-size: 14px\">Password changed</span></span></p><p>"
+    "<FORM><INPUT TYPE=\"button\" VALUE=\"Back\" onClick=\"history.go(-1);return true;\"></FORM>"
+    "</form><p>&nbsp;</p>"
+    "<p><strong><span style=\"color: #000080\">BDDB Ltd.</span></strong></p>"
+    "</body>"
+    "</html>";
+  const int length = strlen(resp);
+  setContentLen(length);
+  respHeaders()["Connection"] = "keep-alive";
+  writeData(resp, length);
+    
+  printf("doPost()-end\r\n");
+}
+
+void HttpHandlerSetup::doHead()
+{
+  printf("onHead\r\n");
+}
+  
+void HttpHandlerSetup::onReadable() //Data has been read
+{
+  printf("onReadable\r\n");
+  UpdateSettingsFile();  
+}
+
+void HttpHandlerSetup::onWriteable() //Data has been written & buf is free
+{
+//  printf("onWriteable() password: %s, username:%s \r\n", Password, Username);
+  printf("onWriteable\r\n");
+  //close(); //Data written, we can close the connection
+}
+
+void HttpHandlerSetup::onClose() //Connection is closing
+{
+  printf("onClose\r\n");
+  //Nothing to do
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HttpHandlerSetup.h	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,32 @@
+#include "HTTPServer.h"
+
+#ifndef HTTP_HANDLER_SETUP
+#define HTTP_HANDLER_SETUP
+
+bool ReadSettings(char* username, char* password);
+
+class HttpHandlerSetup : public HTTPRequestHandler
+{
+public:
+  HttpHandlerSetup(const char* rootPath, const char* path, TCPSocket* pTcpSocket);
+  virtual ~HttpHandlerSetup();
+  
+  static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTcpSocket) { return new HttpHandlerSetup(rootPath, path, pTcpSocket); }
+protected:
+
+  virtual void doGet();
+  virtual void doPost();
+  virtual void doHead();
+  
+  virtual void onReadable(); //Data has been read
+  virtual void onWriteable(); //Data has been written & buf is free
+  virtual void onClose(); //Connection is closing
+
+private:
+  void doGetPageWelcome();
+  void UpdateSettingsFile();
+  
+  bool m_WasDataRead;
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HttpHandlerUsbBrowser.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,130 @@
+#include "HttpHandlerUsbBrowser.h"
+#include "USBHost.h"
+#include "Utils.h"
+#include "UsbStorage.h"
+
+HttpHandlerUsbBrowser::HttpHandlerUsbBrowser(const char* rootPath, const char* path, TCPSocket* pTCPSocket) :
+ HTTPRequestHandler(rootPath, path, pTCPSocket)
+{
+  //printf("HttpHandlerUsbBrowser()");
+}
+
+HttpHandlerUsbBrowser::~HttpHandlerUsbBrowser()
+{
+}
+
+void HttpHandlerUsbBrowser::doGet()
+{
+  int cmpRes = path().compare(0, 5, "/root");
+  printf("doGet path:%d\r\n", cmpRes);    
+  
+  DIR*  d = 0;
+  FILE* f = 0;
+  
+  char usbFullPath[256] = "/usb";
+  if (cmpRes == 0)
+  {
+    path().copy(usbFullPath + 4, 252, 5);
+    int usbFullPathLen = strlen(usbFullPath);
+    if (usbFullPath[usbFullPathLen - 1] == '/') usbFullPath[usbFullPathLen - 1] = 0;
+ 
+    d = opendir(usbFullPath);
+    //printf("after open dir\r\n");
+    
+    if (!d) f = fopen(usbFullPath, "r");
+    //printf("after open file\r\n");
+  }
+  
+  if (!d && !f)
+  {    
+    printf("return no data\r\n");
+    respHeaders()["Connection"] = "close";
+    writeData("<html><body>No Data or Invalid Path</html></body>", 49);  
+    setContentLen(49);
+    return;
+  }
+
+  const char* resp1 = 
+    "<html><body>"
+    "<p><span style=\"color: #a9a9a9\"><span style=\"font-size: 12px\">DropBox Sync Flash-Explorer</span></span></p>";
+   
+  const char* resp2 =
+    "</form><p>&nbsp;</p>"
+    "<p><strong><span style=\"color: #000080\">BDDB Ltd.</span></strong></p>"
+    "</body>"
+    "</html>";
+  
+  int l1 = strlen(resp1), l2 = strlen(resp2);
+  int length = l1 + l2; 
+  
+  int t1 = writeData(resp1, l1);
+  
+  if (d)
+  {
+      printf("\nDumping root dir\n\r");
+      struct dirent *dir = readdir(d);
+      while (dir)
+      {
+        int len = sizeof(dirent);
+        printf("%s %d\n\r", dir->d_name, len);
+      
+        int nameLen = strlen(dir->d_name);
+      
+        writeData("<p><a href=\"", 12);
+        writeData(dir->d_name, nameLen);
+        writeData("/\">", 3);
+        writeData(dir->d_name, nameLen);
+        writeData("</a></p>", 8);
+        length += nameLen * 2 + 23;
+      
+        dir = readdir(d);
+      }
+      closedir(d);
+  }
+  else if (f)
+  {
+    printf("dumping file \r\n");
+    while (fgets(usbFullPath, 256, f) && length <= 4096)
+    {
+     // printf("%s\r\n", usbFullPath);
+      int len = strlen(usbFullPath);
+      writeData(usbFullPath, len);
+      
+      length += len;
+    }
+    
+    fclose(f);
+  }
+
+  int t3 = writeData(resp2, l2);
+  respHeaders()["Connection"] = "close";  
+  setContentLen(length);
+  
+  printf("doGet()-end length %d\r\n", length);
+}
+
+void HttpHandlerUsbBrowser::doPost()
+{
+  printf("doPost()\r\n");
+}
+
+void HttpHandlerUsbBrowser::doHead()
+{
+  printf("onHead\r\n");
+}
+  
+void HttpHandlerUsbBrowser::onReadable() //Data has been read
+{
+  printf("onReadable\r\n");
+}
+
+void HttpHandlerUsbBrowser::onWriteable() //Data has been written & buf is free
+{
+  printf("onWriteable\r\n");
+  close(); //Data written, we can close the connection
+}
+
+void HttpHandlerUsbBrowser::onClose() //Connection is closing
+{
+  //Nothing to do
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/HttpHandlerUsbBrowser.h	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,20 @@
+#include "HTTPServer.h"
+
+class HttpHandlerUsbBrowser : public HTTPRequestHandler
+{
+public:
+  HttpHandlerUsbBrowser(const char* rootPath, const char* path, TCPSocket* pTcpSocket);
+  virtual ~HttpHandlerUsbBrowser();
+  
+  static inline HTTPRequestHandler* inst(const char* rootPath, const char* path, TCPSocket* pTcpSocket) { return new HttpHandlerUsbBrowser(rootPath, path, pTcpSocket); }
+
+protected:
+
+  virtual void doGet();
+  virtual void doPost();
+  virtual void doHead();
+  
+  virtual void onReadable(); //Data has been read
+  virtual void onWriteable(); //Data has been written & buf is free
+  virtual void onClose(); //Connection is closing
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MassStorage/MassStorage.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,180 @@
+
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "stdlib.h"
+#include "stdio.h"
+#include "string.h"
+
+#include "Utils.h"
+#include "USBHost.h"
+
+
+int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize);
+int MassStorage_ReadBlock(int device, u32 block, u8* dst);
+int MassStorage_WriteBlock(int device, u32 block, const u8* dst);
+
+
+#define ERR_BAD_CSW_SIGNATURE -200
+
+#define CBW_SIGNATURE  0x43425355
+#define CSW_SIGNATURE  0x53425355
+
+//  Command Block
+typedef struct
+{
+    u32 Signature;
+    u32 Tag;
+    u32 TransferLength;
+    u8 Flags;
+    u8 LUN;
+    u8 CBLength;
+    u8 CB[16];   // only 6 really
+} CBW;
+
+//  Status block
+typedef struct
+{
+    u32 Signature;
+    u32 Tag;
+    u32 DataResidue;
+    u8 Status;
+} CSW;
+
+int SCSIRequestSense(int device);
+
+int DoSCSI(int device, const u8* cmd, int cmdLen, int flags, u8* data, u32 transferLen)
+{
+    CBW cbw;
+    cbw.Signature = CBW_SIGNATURE;
+    cbw.Tag = 0;
+    cbw.TransferLength = transferLen;
+    cbw.Flags = flags;
+    cbw.LUN = 0;
+    cbw.CBLength = cmdLen;
+    memset(cbw.CB,0,sizeof(cbw.CB));
+    memcpy(cbw.CB,cmd,cmdLen);
+
+    int r;
+    r = USBBulkTransfer(device,0x01,(u8*)&cbw,31);   // Send the command
+    if (r < 0)
+        return r;
+
+    if (data)
+    {
+        r = USBBulkTransfer(device,flags | 1,data,transferLen);
+        if (r < 0)
+            return r;
+    }
+
+    CSW csw;
+    csw.Signature = 0;
+    r = USBBulkTransfer(device,0x81,(u8*)&csw,13);
+    if (r < 0)
+        return r;
+
+    if (csw.Signature != CSW_SIGNATURE)
+        return ERR_BAD_CSW_SIGNATURE;
+
+    // ModeSense?
+    if (csw.Status == 1 && cmd[0] != 3)
+        return SCSIRequestSense(device);
+
+    return csw.Status;
+}
+
+int SCSITestUnitReady(int device)
+{
+    u8 cmd[6];
+    memset(cmd,0,6);
+    return DoSCSI(device,cmd,6,DEVICE_TO_HOST,0,0);
+}
+
+int SCSIRequestSense(int device)
+{
+    u8 cmd[6] = {0x03,0,0,0,18,0};
+    u8 result[18];
+    int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,18);
+    return r;
+}
+
+int SCSIInquiry(int device)
+{
+    u8 cmd[6] = {0x12,0,0,0,36,0};
+    u8 result[36+2];
+    result[36] = '\n';
+    result[37] = 0;
+    int r = DoSCSI(device,cmd,6,DEVICE_TO_HOST,result,36);
+    if (r == 0)
+        printf((const char*)result + 8);
+    return r;
+}
+
+int SCSIReadCapacity(int device, u32* blockCount, u32* blockSize)
+{
+    u8 cmd[10] = {0x25,0,0,0,8,0,0,0,0,0};
+    u8 result[8];
+    *blockSize = 0;
+    *blockCount = 0;
+    int r = DoSCSI(device,cmd,10,DEVICE_TO_HOST,result,8);
+    if (r == 0)
+    {
+        *blockCount = BE32(result);
+        *blockSize = BE32(result+4);
+    }
+    return r;
+}
+
+int SCSITransfer(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize, int direction)
+{
+    //  USB hardware will only do 4k per transfer
+    while (blockCount*blockSize > 4096)
+    {
+        int count = 4096/blockSize;
+        int r = SCSITransfer(device,blockAddr,count,dst,blockSize,direction);
+        dst += count*blockSize;
+        blockAddr += count;
+        blockCount -= count;
+    }
+
+    u8 cmd[10];
+    memset(cmd,0,10);
+    cmd[0] = (direction == DEVICE_TO_HOST) ? 0x28 : 0x2A;
+    BE32(blockAddr,cmd+2);
+    BE16(blockCount,cmd+7);
+    return DoSCSI(device,cmd,10,direction,dst,blockSize*blockCount);
+}
+
+int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize)
+{
+    return SCSIReadCapacity(device,blockCount,blockSize);
+}
+
+int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
+{
+    return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,DEVICE_TO_HOST);
+}
+
+int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize = 512)
+{
+    return SCSITransfer(device,blockAddr,blockCount,dst,blockSize,HOST_TO_DEVICE);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MassStorage/UsbStorage.h	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,45 @@
+#include "FATFileSystem.h"
+
+int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize);
+int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize);
+int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize);
+
+class USBFileSystem : public FATFileSystem
+{
+    int _device;
+    u32 _blockSize;
+    u32 _blockCount;
+    
+public:
+    USBFileSystem() : FATFileSystem("usb"),_device(0),_blockSize(0),_blockCount(0)
+    {
+    }
+    
+    void SetDevice(int device)
+    {
+        _device = device;
+    }
+    
+    virtual int disk_initialize()
+    {
+        return MassStorage_ReadCapacity(_device,&_blockCount,&_blockSize);
+    }
+    
+    virtual int disk_write(const char *buffer, int block_number)
+    {
+        return MassStorage_Write(_device,block_number,1,(u8*)buffer,_blockSize);
+    }
+    
+    virtual int disk_read(char *buffer, int block_number)
+    {
+        //printf("disk_readA\r\n");
+        int r = MassStorage_Read(_device,block_number,1,(u8*)buffer,_blockSize);
+        //printf("disk_readB\r\n");
+        return r;
+    }
+        
+    virtual int disk_sectors()
+    {
+        return _blockCount;
+    }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NTPClient.lib	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/donatien/code/NTPClient/#7c3f1199256a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/AutoEvents.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,154 @@
+
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "mbed.h"
+#include "USBHost.h"
+#include "Utils.h"
+
+#define AUTOEVT(_class,_subclass,_protocol) (((_class) << 16) | ((_subclass) << 8) | _protocol)
+#define AUTO_KEYBOARD AUTOEVT(CLASS_HID,1,1)
+#define AUTO_MOUSE AUTOEVT(CLASS_HID,1,2)
+
+u8 auto_mouse[4];       // buttons,dx,dy,scroll
+u8 auto_keyboard[8];    // modifiers,reserved,keycode1..keycode6
+u8 auto_joystick[4];    // x,y,buttons,throttle
+
+void AutoEventCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
+{
+    int evt = (int)userData;
+    switch (evt)
+    {
+        case AUTO_KEYBOARD:
+            printf("AUTO_KEYBOARD ");
+            break;
+        case AUTO_MOUSE:
+            printf("AUTO_MOUSE ");
+            break;
+        default:
+            printf("HUH ");
+    }
+    printfBytes("data",data,len);
+    USBInterruptTransfer(device,endpoint,data,len,AutoEventCallback,userData);
+}
+
+//  Establish transfers for interrupt events
+void AddAutoEvent(int device, InterfaceDescriptor* id, EndpointDescriptor* ed)
+{
+    if ((ed->bmAttributes & 3) != ENDPOINT_INTERRUPT || !(ed->bEndpointAddress & 0x80))
+        return;
+    
+    // Make automatic interrupt enpoints for known devices
+    u32 evt = AUTOEVT(id->bInterfaceClass,id->bInterfaceSubClass,id->bInterfaceProtocol);
+    u8* dst = 0;
+    int len;
+    switch (evt)
+    {
+        case AUTO_MOUSE:
+            dst = auto_mouse;
+            len = sizeof(auto_mouse);
+            break;
+        case AUTO_KEYBOARD:
+            dst = auto_keyboard;
+            len = sizeof(auto_keyboard);
+            break;
+        default:
+            printf("Interrupt endpoint %02X %08X\n",ed->bEndpointAddress,evt);
+            break;
+    }
+    if (dst)
+    {
+        printf("Auto Event for %02X %08X\n",ed->bEndpointAddress,evt);
+        USBInterruptTransfer(device,ed->bEndpointAddress,dst,len,AutoEventCallback,(void*)evt);
+    }
+}
+
+void PrintString(int device, int i)
+{
+    u8 buffer[256];
+    int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,i,buffer,255);
+    if (le < 0)
+         return;
+    char* dst = (char*)buffer;
+    for (int j = 2; j < le; j += 2)
+        *dst++ = buffer[j];
+    *dst = 0;
+    printf("%d:%s\n",i,(const char*)buffer);
+ }
+ 
+//  Walk descriptors and create endpoints for a given device
+int StartAutoEvent(int device, int configuration, int interfaceNumber)
+{
+    u8 buffer[255];
+    int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,255);
+    if (err < 0)
+        return err;
+
+    int len = buffer[2] | (buffer[3] << 8);
+    u8* d = buffer;
+    u8* end = d + len;
+    while (d < end)
+    {
+        if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
+        {
+            InterfaceDescriptor* id = (InterfaceDescriptor*)d;
+            if (id->bInterfaceNumber == interfaceNumber)
+            {
+                 d += d[0];
+                while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE)
+                {
+                    if (d[1] == DESCRIPTOR_TYPE_ENDPOINT)
+                        AddAutoEvent(device,id,(EndpointDescriptor*)d);
+                    d += d[0];
+                }
+            }
+        }
+        d += d[0];
+    }
+    return 0;
+}
+
+//  Implemented in main.cpp
+int OnDiskInsert(int device);
+
+void OnLoadDevice(int device, DeviceDescriptor* deviceDesc, InterfaceDescriptor* interfaceDesc)
+{
+    printf("LoadDevice %d %02X:%02X:%02X\n",device,interfaceDesc->bInterfaceClass,interfaceDesc->bInterfaceSubClass,interfaceDesc->bInterfaceProtocol);
+    char s[128];
+    for (int i = 1; i < 3; i++)
+    {
+        if (GetString(device,i,s,sizeof(s)) < 0)
+            break;
+        printf("%d: %s\n",i,s);
+    }
+    
+    switch (interfaceDesc->bInterfaceClass)
+    {
+        case CLASS_MASS_STORAGE:
+            if (interfaceDesc->bInterfaceSubClass == 0x06 && interfaceDesc->bInterfaceProtocol == 0x50)
+                OnDiskInsert(device);    // it's SCSI!
+            break;
+        default:
+            StartAutoEvent(device,1,0);
+            break;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,1090 @@
+
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "mbed.h"
+#include "USBHost.h"
+
+//    Config (default uses x bytes)
+#define MAX_DEVICES 8                // Max number of devices
+#define MAX_ENDPOINTS_TOTAL 16        // Max number of endpoints total
+#define MAX_ENDPOINTS_PER_DEVICE 8    // Max number of endpoints for any one device
+
+#define  USBLOG 1
+#if USBLOG
+#define  LOG(...)       printf(__VA_ARGS__)
+#else 
+#define  LOG(...)       do {} while(0)
+#endif
+
+// USB host structures
+
+#define USB_RAM_SIZE 16*1024    // AHB SRAM block 1 TODO MACHINE DEPENDENT
+#define USB_RAM_BASE 0x2007C000
+
+#define TOKEN_SETUP 0
+#define TOKEN_IN  1
+#define TOKEN_OUT 2
+
+//    Status flags from hub
+#define PORT_CONNECTION 0
+#define PORT_ENABLE  1
+#define PORT_SUSPEND  2
+#define PORT_OVER_CURRENT 3
+#define PORT_RESET 4
+#define PORT_POWER 8
+#define PORT_LOW_SPEED 9
+
+#define C_PORT_CONNECTION 16
+#define C_PORT_ENABLE 17
+#define C_PORT_SUSPEND 18
+#define C_PORT_OVER_CURRENT 19
+#define C_PORT_RESET 20
+
+typedef struct {
+    u8 bm_request_type;
+    u8 b_request;
+    u16 w_value;
+    u16 w_index;
+    u16 w_length;
+} Setup;
+
+
+//    Hub stuff is kept private just to keep api simple
+int SetPortFeature(int device, int feature, int index);
+int ClearPortFeature(int device, int feature, int index);
+int SetPortPower(int device, int port);
+int SetPortReset(int device, int port);
+int GetPortStatus(int device, int port, u32* status);
+
+//===================================================================
+//===================================================================
+//    Hardware defines
+
+//    HcControl
+#define PeriodicListEnable    0x00000004
+#define    IsochronousEnable    0x00000008
+#define    ControlListEnable    0x00000010
+#define    BulkListEnable        0x00000020
+#define    OperationalMask        0x00000080
+#define    HostControllerFunctionalState    0x000000C0
+
+//    HcCommandStatus
+#define HostControllerReset    0x00000001
+#define ControlListFilled    0x00000002
+#define BulkListFilled        0x00000004
+
+//    HcInterruptStatus Register
+#define    WritebackDoneHead        0x00000002
+#define    StartofFrame            0x00000004
+#define ResumeDetected            0x00000008
+#define UnrecoverableError        0x00000010
+#define FrameNumberOverflow        0x00000020
+#define RootHubStatusChange        0x00000040
+#define OwnershipChange            0x00000080
+#define MasterInterruptEnable    0x80000000
+
+//    HcRhStatus
+#define SetGlobalPower            0x00010000
+#define DeviceRemoteWakeupEnable    0x00008000
+
+//    HcRhPortStatus (hub 0, port 1)
+#define CurrentConnectStatus    0x00000001
+#define    PortEnableStatus        0x00000002
+#define PortSuspendStatus        0x00000004
+#define PortOverCurrentIndicator    0x00000008
+#define PortResetStatus            0x00000010
+
+#define PortPowerStatus            0x00000100
+#define LowspeedDevice            0x00000200
+#define HighspeedDevice            0x00000400
+
+#define ConnectStatusChange    (CurrentConnectStatus << 16)
+#define PortResetStatusChange    (PortResetStatus << 16)
+
+
+#define  TD_ROUNDING        (u32)0x00040000
+#define  TD_SETUP            (u32)0x00000000
+#define  TD_IN                (u32)0x00100000
+#define  TD_OUT                (u32)0x00080000
+#define  TD_DELAY_INT(x)    (u32)((x) << 21)
+#define  TD_TOGGLE_0        (u32)0x02000000
+#define  TD_TOGGLE_1        (u32)0x03000000
+#define  TD_CC                (u32)0xF0000000
+
+//    HostController EndPoint Descriptor
+typedef struct {
+    volatile u32    Control;
+    volatile u32    TailTd;
+    volatile u32    HeadTd;
+    volatile u32    Next;
+} HCED;
+
+// HostController Transfer Descriptor
+typedef struct {
+    volatile u32    Control;
+    volatile u32    CurrBufPtr;
+    volatile u32    Next;
+    volatile u32    BufEnd;
+} HCTD;
+
+// Host Controller Communication Area
+typedef struct {
+    volatile u32    InterruptTable[32];
+    volatile u16    FrameNumber;
+    volatile u16    FrameNumberPad;
+    volatile u32    DoneHead;
+    volatile u8        Reserved[120];
+} HCCA;
+
+//====================================================================================
+//====================================================================================
+
+class HostController;
+class Endpoint;
+class Device;
+
+//      must be 3*16 bytes long
+class Endpoint
+{
+public:
+    HCED    EndpointDescriptor;    // Pointer to EndpointDescriptor == Pointer to Endpoint
+    HCTD    TDHead;
+
+    enum State
+    {
+        Free,
+        NotQueued,
+        Idle,
+        SetupQueued,
+        DataQueued,
+        StatusQueued,
+        CallbackPending
+    };
+    
+    volatile u8 CurrentState;
+    u8        Flags;            // 0x80 In, 0x03 mask endpoint type
+
+    u16        Length;
+    u8*        Data;
+    USBCallback Callback;     // Must be a multiple of 16 bytes long
+    void*  UserData;
+  
+    int Address()
+    {
+        int ep = (EndpointDescriptor.Control >> 7) & 0xF;
+        if (ep)
+            ep |= Flags & 0x80;
+        return ep;
+    }
+    
+    int Device()
+    {
+        return EndpointDescriptor.Control & 0x7F;
+    }
+
+    int Status()
+    {
+        return (TDHead.Control >> 28) & 0xF;
+    }
+
+    u32 Enqueue(u32 head)
+    {
+        if (CurrentState == NotQueued)
+        {
+            EndpointDescriptor.Next = head;
+            head = (u32)&EndpointDescriptor;
+            CurrentState = Idle;
+        }
+        return head;
+    }
+};
+
+class Device
+{
+public:
+    u8    _endpointMap[MAX_ENDPOINTS_PER_DEVICE*2];
+    u8    Hub;
+    u8    Port;
+    u8    Addr;
+    u8    Pad;
+
+    //    Only if this device is a hub
+    u8    HubPortCount;    // nonzero if this is a hub
+    u8    HubInterruptData;
+    u8    HubMap;
+    u8    HubMask;
+
+    int Flags;        // 1 = Disconnected
+
+    Setup    SetupBuffer;
+
+    // Allocate endpoint zero
+    int Init(DeviceDescriptor* d, int hub, int port, int addr, int lowSpeed)
+    {
+        Hub = hub;
+        Port = port;
+        Addr = addr;
+        Flags = lowSpeed;
+        memset(_endpointMap,0xFF,sizeof(_endpointMap));
+        return 0;
+    }
+
+    int SetEndpointIndex(int ep, int endpointIndex)
+    {
+        for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
+        {
+            if (_endpointMap[i] == 0xFF)    // Add endpoint to map
+            {
+                _endpointMap[i] = ep;
+                _endpointMap[i+1] = endpointIndex;
+                return 0;
+            }
+        }
+        return ERR_ENDPOINT_NONE_LEFT;
+    }
+
+    int GetEndpointIndex(int ep)
+    {
+        for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
+        {
+            if (_endpointMap[i] == ep)
+                return _endpointMap[i+1];
+            if (_endpointMap[i] == 0xFF)
+                break;
+        }
+        return -1;
+    }
+};
+
+class HostController
+{
+public:
+    HCCA        CommunicationArea;
+    Endpoint    Endpoints[MAX_ENDPOINTS_TOTAL];    // Multiple of 16
+    
+    Endpoint    EndpointZero;                        // For device enumeration
+    HCTD        _commonTail;
+    Setup        _setupZero;
+    
+    Device    Devices[MAX_DEVICES];
+    u32    _frameNumber;            // 32 bit ms counter
+
+    u8    _callbacksPending;        //    Endpoints with callbacks are pending, set from ISR via ProcessDoneQueue
+    u8    _rootHubStatusChange;    //    Root hub status has changed, set from ISR
+    u8    _unused0;
+    u8    _unused1;
+
+    u8    _connectPending;    //    Reset has initiated a connect
+    u8    _connectCountdown;    //    Number of ms left after reset before we can connect
+    u8    _connectHub;        //    Will connect on this hub
+    u8    _connectPort;        //    ... and this port
+
+    u8    SRAM[0];            // Start of free SRAM
+
+    void Loop()
+    {
+        u16 elapsed = CommunicationArea.FrameNumber - (u16)_frameNumber;    // extend to 32 bits
+        _frameNumber += elapsed;
+
+        // Do callbacks, if any
+        while (_callbacksPending)
+        {
+            for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
+            {
+                Endpoint* endpoint = Endpoints + i;
+                if (endpoint->CurrentState == Endpoint::CallbackPending)
+                {
+                    _callbacksPending--;
+                    endpoint->CurrentState = Endpoint::Idle;
+                    endpoint->Callback(endpoint->Device(),endpoint->Address(),endpoint->Status(),endpoint->Data,endpoint->Length,endpoint->UserData);
+                }
+            }
+        }
+
+        //    Deal with changes on the root hub
+        if (_rootHubStatusChange)
+        {
+            u32 status = LPC_USB->HcRhPortStatus1;
+            _rootHubStatusChange = 0;
+            if (status >> 16)
+            {
+                HubStatusChange(0,1,status);
+                LPC_USB->HcRhPortStatus1 = status & 0xFFFF0000;    // clear status changes
+            }
+        }
+
+        //    Connect after reset timeout
+        if (_connectCountdown)
+        {
+            if (elapsed >= _connectCountdown)
+            {
+                _connectCountdown = 0;
+                Connect(_connectHub,_connectPort & 0x7F,_connectPort & 0x80);
+            } else
+                _connectCountdown -= elapsed;
+        }
+    }
+
+    //    HubInterrupt - bitmap in dev->HubInterruptData
+    void HubInterrupt(int device)
+    {
+        Device* dev = &Devices[device-1];
+        for (int i = 0; i < dev->HubPortCount; i++)
+        {
+            int port = i+1;
+            if (dev->HubInterruptData & (1 << port))
+            {
+                u32 status = 0;
+                GetPortStatus(device,port,&status);
+
+                if (status >> 16)
+                {
+                    if (_connectPending && (status & ConnectStatusChange))
+                        continue;    // Don't connect again until previous device has been added and addressed
+
+                    HubStatusChange(device,port,status);
+                    if (status & ConnectStatusChange)
+                        ClearPortFeature(device,C_PORT_CONNECTION,port);
+                    if (status & PortResetStatusChange)
+                        ClearPortFeature(device,C_PORT_RESET,port);
+                }
+            }
+        }
+    }
+
+    static void HubInterruptCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
+    {
+        HostController* controller = (HostController*)userData;
+        if (status == 0)
+            controller->HubInterrupt(device);
+        USBInterruptTransfer(device,endpoint,data,1,HubInterruptCallback,userData);
+    }
+
+    int InitHub(int device)
+    {
+        u8 buf[16];
+        int r= USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_DEVICE,GET_DESCRIPTOR,(DESCRIPTOR_TYPE_HUB << 8),0,buf,sizeof(buf));
+        if (r < 0)
+            return ERR_HUB_INIT_FAILED;
+        
+        //    turn on power on the hubs ports
+        Device* dev = &Devices[device-1];
+        int ports = buf[2];
+        dev->HubPortCount = ports;
+        for (int i = 0; i < ports; i++)
+            SetPortPower(device,i+1);
+        
+        // Enable hub change interrupts
+        return USBInterruptTransfer(device,0x81,&dev->HubInterruptData,1,HubInterruptCallback,this);
+    }
+    
+    int AddEndpoint(int device, int ep, int attributes, int maxPacketSize, int interval)
+    {
+        LOG("AddEndpoint D:%02X A:%02X T:%02X P:%04X I:%02X\n",device,ep,attributes,maxPacketSize,interval);
+        Device* dev = &Devices[device-1];
+        Endpoint* endpoint = AllocateEndpoint(device,ep,attributes,maxPacketSize);
+        if (!endpoint)
+            return ERR_ENDPOINT_NONE_LEFT;
+        dev->SetEndpointIndex(ep,endpoint - Endpoints);
+        endpoint->EndpointDescriptor.Control |= dev->Flags; // Map in slow speed
+        return 0;  // TODO ed->bInterval
+    }
+    
+    int AddEndpoint(int device, EndpointDescriptor* ed)
+    {
+        return AddEndpoint(device,ed->bEndpointAddress,ed->bmAttributes,ed->wMaxPacketSize,ed->bInterval);
+    }
+
+    //      allocate a endpoint
+    Endpoint* AllocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize)
+    {
+        for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
+        {
+            Endpoint* ep = &Endpoints[i];
+            if (ep->CurrentState == 0)
+            {
+                //LOG("Allocated endpoint %d to %02X:%02X\n",i,device,endpointAddress);
+                ep->Flags = (endpointAddress & 0x80) | (type & 3);
+                ep->CurrentState = Endpoint::NotQueued;
+                ep->EndpointDescriptor.Control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device;
+                return ep;
+            }
+        }
+        return 0;
+    }
+
+    Endpoint* GetEndpoint(int device, int ep)
+    {
+        if (device == 0)
+        {
+            //printf("WARNING: USING DEVICE 0\n");
+            return &EndpointZero;
+        }
+        if (device > MAX_DEVICES)
+            return 0;
+        int i = Devices[device-1].GetEndpointIndex(ep);
+        if (i == -1)
+            return 0;
+        return Endpoints + i;
+    }
+
+    int Transfer(Endpoint* endpoint, int token, u8* data, int len, int state)
+    {
+        //LOG("Transfer %02X T:%d Len:%d S:%d\n",endpoint->Address(),token,len,state);
+    
+        int toggle = 0;
+        if (endpoint->Address() == 0)
+            toggle = (token == TOKEN_SETUP) ? TD_TOGGLE_0 : TD_TOGGLE_1;
+
+        if (token != TOKEN_SETUP)
+            token = (token == TOKEN_IN ? TD_IN : TD_OUT);
+
+        HCTD* head = &endpoint->TDHead;
+        HCTD* tail = &_commonTail;
+
+        head->Control = TD_ROUNDING | token | TD_DELAY_INT(0) | toggle | TD_CC; 
+        head->CurrBufPtr = (u32)data;
+        head->BufEnd = (u32)(data + len - 1);
+        head->Next = (u32)tail;
+
+        HCED* ed = &endpoint->EndpointDescriptor;
+        ed->HeadTd = (u32)head | (ed->HeadTd & 0x00000002);    // carry toggle
+        ed->TailTd = (u32)tail;
+        
+        //HCTD* td = head;
+        //LOG("%04X TD %08X %08X %08X Next:%08X\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next);
+        //LOG("%04X ED %08X %08X %08X\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd);
+        
+        switch (endpoint->Flags & 3)
+        {
+            case ENDPOINT_CONTROL:
+                LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED);    // May change state NotQueued->Idle
+                endpoint->CurrentState = state;                                               // Get in before an int
+                LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | ControlListFilled;
+                LPC_USB->HcControl = LPC_USB->HcControl | ControlListEnable;
+                break;
+
+            case ENDPOINT_BULK:
+                LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED);
+                endpoint->CurrentState = state;
+                LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled;
+                LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable;
+                break;
+
+            case ENDPOINT_INTERRUPT:
+                CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]);
+                endpoint->CurrentState = state;
+                LPC_USB->HcControl |= PeriodicListEnable;
+                break;
+        }
+        return 0;
+    }
+    
+    //    Remove an endpoint from an active queue
+    bool Remove(HCED* ed, volatile HCED** queue)
+    {
+        if (*queue == 0)
+            return false;
+        if (*queue == (volatile HCED*)ed)
+        {
+            *queue = (volatile HCED*)ed->Next;    // At head of queue
+            return true;
+        }
+
+        volatile HCED* head = *queue;
+        while (head)
+        {
+            if (head->Next == (u32)ed)
+            {
+                head->Next = ed->Next;
+                return true;
+            }
+            head = (volatile HCED*)head->Next;
+        }
+        return false;
+    }
+
+    void Release(Endpoint* endpoint)
+    {
+        if (endpoint->CurrentState == Endpoint::NotQueued)
+        {
+            // Never event used it, nothing to do
+        }
+        else
+        {
+            HCED* ed = (HCED*)endpoint;
+            ed->Control |= 0x4000;    // SKIP
+            switch (endpoint->Flags & 0x03)
+            {
+                case ENDPOINT_CONTROL:
+                    Remove(ed,(volatile HCED**)&LPC_USB->HcControlHeadED);
+                    break;
+                case ENDPOINT_BULK:
+                    Remove(ed,(volatile HCED**)&LPC_USB->HcBulkHeadED);
+                    break;
+                case ENDPOINT_INTERRUPT:
+                    for (int i = 0; i < 32; i++)
+                        Remove(ed,(volatile HCED**)&CommunicationArea.InterruptTable[i]);
+                    break;
+            }
+
+            u16 fn = CommunicationArea.FrameNumber;
+            while (fn == CommunicationArea.FrameNumber)
+                ;    // Wait for next frame
+
+        }
+
+        //    In theory, the endpoint is now dead.
+        //    TODO: Will Callbacks ever be pending? BUGBUG
+        memset(endpoint,0,sizeof(Endpoint));
+    }
+
+    //      Pop the last TD from the list
+    HCTD* Reverse(HCTD* current) 
+    { 
+        HCTD *result = NULL,*temp; 
+        while (current) 
+        { 
+            temp = (HCTD*)current->Next; 
+            current->Next = (u32)result;
+            result = current;
+            current = temp;
+        }
+        return result;
+    }
+
+    //      Called from interrupt...
+    //      Control endpoints use a state machine to progress through the transfers
+    void ProcessDoneQueue(u32 tdList)
+    {
+        HCTD* list = Reverse((HCTD*)tdList);
+        while (list)
+        {
+            Endpoint* endpoint = (Endpoint*)(list-1);
+            list = (HCTD*)list->Next;
+            int ep = endpoint->Address();
+            bool in = endpoint->Flags & 0x80;
+            int status = (endpoint->TDHead.Control >> 28) & 0xF;
+
+            //LOG("ProcessDoneQueue %02X %08X\n",ep,endpoint->TDHead.Control);
+
+            if (status != 0)
+            {
+                LOG("ProcessDoneQueue status %02X %d\n",ep,status);
+                endpoint->CurrentState = Endpoint::Idle;
+            } else {
+                switch (endpoint->CurrentState)
+                {
+                    case Endpoint::SetupQueued:
+                        if (endpoint->Length == 0)
+                            Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Skip Data Phase
+                        else
+                            Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued);    // Setup is done, now Data
+                        break;
+
+                    case Endpoint::DataQueued:
+                        if (endpoint->TDHead.CurrBufPtr)
+                            endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data;
+
+                        if (ep == 0)
+                            Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Data is done, now Status, Control only
+                        else
+                            endpoint->CurrentState = Endpoint::Idle;
+                        break;
+
+                    case Endpoint::StatusQueued:    // Transaction is done
+                        endpoint->CurrentState = Endpoint::Idle;
+                        break;
+                }
+            }
+
+            //      Complete, flag if we need a callback
+            if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle)
+            {
+                endpoint->CurrentState = Endpoint::CallbackPending;
+                _callbacksPending++;
+            }
+        }
+    }
+
+    //    Hack to reset devices that don't want to connect
+    int AddDevice(int hub, int port, bool isLowSpeed)
+    {
+        int device = AddDeviceCore(hub,port,isLowSpeed);
+        if (device < 0)
+        {
+            LOG("========RETRY ADD DEVICE========\n");    // This will go for ever.. TODO power cycle root?
+            Disconnect(hub,port);    // Could not read descriptor at assigned address, reset this port and try again
+            ResetPort(hub,port);    // Cheap bluetooth dongles often need this on a hotplug
+            return -1;
+        }
+        return device;
+    }
+
+    int AddDeviceCore(int hub, int port, bool isLowSpeed)
+    {
+        int lowSpeed = isLowSpeed ? 0x2000 : 0;
+        DeviceDescriptor desc;
+        EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed;               // MaxPacketSize == 8
+        int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8);
+        if (r < 0)
+        {
+            LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\n");
+            return r;
+        }
+
+        EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed;     // Actual MaxPacketSize
+        r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
+        if (r < 0)
+            return r;
+
+        LOG("\nClass %02X found %04X:%04X\n\n",desc.bDeviceClass,desc.idVendor,desc.idProduct);
+
+        //      Now assign the device an address, move off EndpointZero
+        int device = 0;
+        for (int i = 0; i < MAX_DEVICES; i++)
+        {
+            if (Devices[i].Port == 0)
+            {
+                device = i+1;
+                break;
+            }
+        }
+        if (!device)
+            return ERR_DEVICE_NONE_LEFT;
+
+        r = SetAddress(0,device);
+        if (r)
+            return r;
+        DelayMS(2);
+        
+        // Now at a nonzero address, create control endpoint
+        Device* dev = &Devices[device-1];
+        dev->Init(&desc,hub,port,device,lowSpeed);
+        AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0);
+        _connectPending = 0;
+
+        //    Verify this all works
+        r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
+        if (r < 0)
+            return r;
+
+        //    Set to interface 0 by default
+        //    Calls LoadDevice if interface is found
+        r = SetConfigurationAndInterface(device,1,0,&desc);
+
+        if (desc.bDeviceClass == CLASS_HUB)
+            InitHub(device);            // Handle hubs in this code
+
+        return device;
+    }
+
+    // Walk descriptors and create endpoints for a given device
+    // TODO configuration !=1, alternate settings etc.
+    int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc)
+    {
+        u8 buffer[255];
+        int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,sizeof(buffer));
+        if (err < 0)
+            return err;
+
+        err = SetConfiguration(device,configuration);
+        if (err < 0)
+            return err;
+
+        //    Add the endpoints for this interface
+        int len = buffer[2] | (buffer[3] << 8);
+        u8* d = buffer;
+        u8* end = d + len;
+        InterfaceDescriptor* found = 0;
+        while (d < end)
+        {
+            if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
+            {
+                InterfaceDescriptor* id = (InterfaceDescriptor*)d;
+                if (id->bInterfaceNumber == interfaceNumber)
+                {
+                    found = id;
+                    d += d[0];
+                    while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE)
+                    {
+                        switch (d[1])
+                        {
+                            case DESCRIPTOR_TYPE_ENDPOINT:
+                                AddEndpoint(device,(EndpointDescriptor*)d);
+                                break;
+                            default:
+                                LOG("Skipping descriptor %02X (%d bytes)\n",d[1],d[0]);
+                        }
+                        d += d[0];
+                    }
+                }
+            }
+            d += d[0];
+        }
+
+        if (!found)
+            return ERR_INTERFACE_NOT_FOUND;
+        OnLoadDevice(device,desc,found);
+        return 0;
+    }
+
+    void Init()
+    {
+        LOG("USB INIT (Controller is %d bytes)\n",sizeof(*this));
+        memset(this,0,sizeof(HostController));
+        EndpointZero.CurrentState = Endpoint::NotQueued;
+        HWInit(&CommunicationArea);
+        DelayMS(10);
+    }
+
+    void ResetPort(int hub, int port)
+    {
+        LOG("ResetPort Hub:%d Port:%d\n",hub,port);
+        _connectPending++;            // Only reset/add 1 device at a time
+        if (hub == 0)
+            LPC_USB->HcRhPortStatus1 = PortResetStatus;    // Reset Root Hub, port 1
+        else
+            SetPortReset(hub,port);    // or reset other hub
+    }
+
+    void Disconnect(int hub, int port)
+    {
+        LOG("Disconnect Hub:%d Port:%d\n",hub,port);    // Mark a device for destruction
+        for (int i = 0; i < MAX_DEVICES; i++)
+        {
+            Device* dev = Devices + i;
+            if (dev->Port == port && dev->Hub == hub)
+            {
+                //    Disconnect everything that is attached to this device if it is a hub
+                for (int p = 0; p < dev->HubPortCount; p++)
+                    Disconnect(i+1,p+1);
+
+                //    Now release endpoints
+                for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2)
+                {
+                    u8 endpointIndex = dev->_endpointMap[j];
+                    if (endpointIndex != 0xFF)
+                        Release(Endpoints + endpointIndex);
+                }
+                dev->Port = 0;    // Device is now free
+                dev->Flags = 0;
+                return;
+            }
+        }
+    }
+
+    // called after reset
+    void Connect(int hub, int port, bool lowspeed)
+    {
+        LOG("Connect Hub:%d Port:%d %s\n",hub,port,lowspeed ? "slow" : "full");
+        AddDevice(hub,port,lowspeed);
+    }
+
+    // Called from interrupt
+    void HubStatusChange(int hub, int port, u32 status)
+    {
+        LOG("HubStatusChange Hub:%d Port:%d %08X\n",hub,port,status);
+        if (status & ConnectStatusChange)
+        {
+            if (status & CurrentConnectStatus)    // Connecting
+                ResetPort(hub,port);            // Reset to initiate connect (state machine?)
+            else
+                Disconnect(hub,port);
+        }
+
+        if (status & PortResetStatusChange)
+        {
+            if (!(status & PortResetStatus))
+            {
+                _connectCountdown = 200;        // Schedule a connection in 200ms
+                if (status & LowspeedDevice)
+                    port |= 0x80;
+                _connectHub = hub;
+                _connectPort = port;
+            }
+        }
+    }
+
+    #define HOST_CLK_EN        (1<<0)
+    #define PORTSEL_CLK_EN    (1<<3)
+    #define AHB_CLK_EN        (1<<4)
+    #define CLOCK_MASK        (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
+
+    #define  FRAMEINTERVAL        (12000-1)    // 1ms
+    #define  DEFAULT_FMINTERVAL    ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL)
+
+    void DelayMS(int ms)
+    {
+        u16 f = ms + CommunicationArea.FrameNumber;
+        while (f != CommunicationArea.FrameNumber)
+            ;
+    }
+
+    static void HWInit(HCCA* cca)
+    {
+        NVIC_DisableIRQ(USB_IRQn);
+        
+        // turn on power for USB
+        LPC_SC->PCONP        |= (1UL<<31);
+        // Enable USB host clock, port selection and AHB clock
+        LPC_USB->USBClkCtrl |= CLOCK_MASK;
+        // Wait for clocks to become available
+        while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
+            ;
+        
+        //    We are a Host
+        LPC_USB->OTGStCtrl |= 1;
+        LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;                // we don't need port selection clock until we do OTG
+        
+        // configure USB pins
+        LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28));    
+        LPC_PINCON->PINSEL1 |=    ((1<<26)|(1<<28));            // USB D+/D-
+            
+        LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22));        // USB_PPWR, USB_OVRCR
+        LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22));
+        
+        LPC_PINCON->PINSEL4 &= ~(3 << 18);                    // USB_CONNECT
+        LPC_PINCON->PINSEL4 |= (1 << 18);
+
+        //    Reset OHCI block
+        LPC_USB->HcControl         = 0;
+        LPC_USB->HcControlHeadED = 0;
+        LPC_USB->HcBulkHeadED     = 0;
+        
+        LPC_USB->HcCommandStatus = HostControllerReset;
+        LPC_USB->HcFmInterval     = DEFAULT_FMINTERVAL;
+        LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100;
+
+        LPC_USB->HcControl    = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask;
+        LPC_USB->HcRhStatus = SetGlobalPower;
+        
+        LPC_USB->HcHCCA = (u32)cca;
+        LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
+        LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow;
+
+        LPC_USB->HcRhDescriptorB |= 0xFFFF;
+
+        NVIC_SetPriority(USB_IRQn, 0);
+        NVIC_EnableIRQ(USB_IRQn);
+        while (cca->FrameNumber < 10)
+            ;    // 10ms delay before diving in
+    }
+};
+
+//====================================================================================
+//====================================================================================
+//      Host controller instance and Interrupt handler
+
+static HostController _controller __attribute__((at(USB_RAM_BASE)));
+
+extern "C" void USB_IRQHandler(void) __irq;
+void USB_IRQHandler (void) __irq
+{
+    u32 int_status = LPC_USB->HcInterruptStatus;
+
+    if (int_status & RootHubStatusChange)    //    Root hub status change
+        _controller._rootHubStatusChange++;    //    Just flag the controller, will be processed in USBLoop
+
+    u32 head = 0;
+    if (int_status & WritebackDoneHead)
+    {
+        head = _controller.CommunicationArea.DoneHead;        // Writeback Done
+        _controller.CommunicationArea.DoneHead = 0;
+    }             
+    LPC_USB->HcInterruptStatus = int_status;
+
+    if (head)
+       _controller.ProcessDoneQueue(head);     // TODO - low bit can be set BUGBUG
+}
+
+//====================================================================================
+//====================================================================================
+//      API Methods
+
+void USBInit()
+{
+    return _controller.Init();
+}
+
+void USBLoop()
+{
+    return _controller.Loop();
+}
+
+u8* USBGetBuffer(u32* len)
+{
+    *len = USB_RAM_SIZE - sizeof(HostController);
+    return _controller.SRAM;
+}
+
+void Disconnect()
+{
+_controller.Disconnect(0,1);
+}
+
+static Setup* GetSetup(int device)
+{
+    if (device == 0)
+        return &_controller._setupZero;
+    
+    if (device < 1 || device > MAX_DEVICES)
+        return 0;
+    return &_controller.Devices[device-1].SetupBuffer;
+}
+
+//    Loop until IO on endpoint is complete
+static int WaitIODone(Endpoint* endpoint)
+{
+    if (endpoint->CurrentState == Endpoint::NotQueued)
+        return 0;
+    while (endpoint->CurrentState != Endpoint::Idle)
+        USBLoop();    // May generate callbacks, mount or unmount devices etc
+    int status = endpoint->Status();
+    if (status == 0)
+        return endpoint->Length;
+    return -status;
+}
+
+int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData)
+{
+    Endpoint* endpoint = _controller.GetEndpoint(device,ep);
+    if (!endpoint)
+        return ERR_ENDPOINT_NOT_FOUND;
+        
+    WaitIODone(endpoint);
+    endpoint->Flags = flags;
+    endpoint->Data = data;
+    endpoint->Length = length;
+    endpoint->Callback = callback;
+    endpoint->UserData = userData;
+    if (ep == 0)
+        _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued);
+    else
+        _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued);
+    if (callback)
+        return IO_PENDING;
+    return WaitIODone(endpoint);
+}
+
+int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData)
+{
+    Setup* setup = GetSetup(device);
+    if (!setup)
+        return ERR_DEVICE_NOT_FOUND;
+        
+    // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call
+    WaitIODone(_controller.GetEndpoint(device,0));
+    
+    setup->bm_request_type = request_type;
+    setup->b_request = request;
+    setup->w_value = value;
+    setup->w_index = index;
+    setup->w_length = length;
+    return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData);
+}
+
+int  USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
+{
+    return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData);
+}
+
+int  USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
+{
+    return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData);
+}
+
+int GetDescriptor(int device, int descType,int descIndex, u8* data, int length)
+{
+    return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0);
+}
+
+int GetString(int device, int index, char* dst, int length)
+{
+    u8 buffer[255];
+    int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer));
+    if (le < 0)
+        return le;
+    if (length < 1)
+        return -1;
+    length <<= 1;
+    if (le > length)
+        le = length;
+    for (int j = 2; j < le; j += 2)
+        *dst++ = buffer[j];
+    *dst = 0;
+    return (le>>1)-1;
+}
+
+int SetAddress(int device, int new_addr)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0);
+}
+
+int SetConfiguration(int device, int configNum)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0);
+}
+
+int SetInterface(int device, int ifNum, int altNum)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0);
+}
+
+//    HUB stuff
+int SetPortFeature(int device, int feature, int index)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0);
+}
+
+int ClearPortFeature(int device, int feature, int index)
+{
+    return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0);
+}
+
+int SetPortPower(int device, int port)
+{
+    int r = SetPortFeature(device,PORT_POWER,port);
+    _controller.DelayMS(20);    // 80ms to turn on a hubs power... DESCRIPTOR? todo
+    return r;
+}
+
+void ClearPortPower()
+{
+    LPC_USB->HcRhPortStatus1 |= ConnectStatusChange;
+}
+
+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);
+}
+
+void Reset()
+{
+    LPC_USB->HcCommandStatus |= 1;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/USBHost.h	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,205 @@
+
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#ifndef USBHOST_H
+#define USBHOST_H
+
+#ifndef u8
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+
+typedef char s8;
+typedef short s16;
+typedef char s32;
+#endif
+
+#define ENDPOINT_CONTROL 0
+#define ENDPOINT_ISOCRONOUS 1
+#define ENDPOINT_BULK 2
+#define ENDPOINT_INTERRUPT 3
+
+#define  DESCRIPTOR_TYPE_DEVICE            1
+#define  DESCRIPTOR_TYPE_CONFIGURATION    2
+#define  DESCRIPTOR_TYPE_STRING            3
+#define  DESCRIPTOR_TYPE_INTERFACE        4
+#define  DESCRIPTOR_TYPE_ENDPOINT        5
+
+#define DESCRIPTOR_TYPE_HID         0x21
+#define DESCRIPTOR_TYPE_REPORT      0x22
+#define DESCRIPTOR_TYPE_PHYSICAL    0x23
+#define DESCRIPTOR_TYPE_HUB         0x29
+
+enum USB_CLASS_CODE
+{
+    CLASS_DEVICE,
+    CLASS_AUDIO,
+    CLASS_COMM_AND_CDC_CONTROL,
+    CLASS_HID,
+    CLASS_PHYSICAL = 0x05,
+    CLASS_STILL_IMAGING,
+    CLASS_PRINTER,
+    CLASS_MASS_STORAGE,
+    CLASS_HUB,
+    CLASS_CDC_DATA,
+    CLASS_SMART_CARD,
+    CLASS_CONTENT_SECURITY = 0x0D,
+    CLASS_VIDEO = 0x0E,
+    CLASS_DIAGNOSTIC_DEVICE = 0xDC,
+    CLASS_WIRELESS_CONTROLLER = 0xE0,
+    CLASS_MISCELLANEOUS = 0xEF,
+    CLASS_APP_SPECIFIC = 0xFE,
+    CLASS_VENDOR_SPECIFIC = 0xFF
+};
+
+#define  DEVICE_TO_HOST         0x80
+#define  HOST_TO_DEVICE         0x00
+#define  REQUEST_TYPE_CLASS     0x20
+#define  RECIPIENT_DEVICE       0x00
+#define  RECIPIENT_INTERFACE    0x01
+#define  RECIPIENT_ENDPOINT        0x02
+#define  RECIPIENT_OTHER        0x03
+
+#define  GET_STATUS                0
+#define  CLEAR_FEATURE            1
+#define  SET_FEATURE            3
+#define  SET_ADDRESS            5
+#define  GET_DESCRIPTOR            6
+#define  SET_DESCRIPTOR            7
+#define  GET_CONFIGURATION        8
+#define  SET_CONFIGURATION        9
+#define  GET_INTERFACE            10
+#define  SET_INTERFACE            11
+#define  SYNCH_FRAME            11
+
+//        -5 is nak
+/*
+0010 ACK Handshake
+1010 NAK Handshake
+1110 STALL Handshake
+0110 NYET (No Response Yet)
+*/
+
+#define IO_PENDING -100
+#define ERR_ENDPOINT_NONE_LEFT -101
+#define ERR_ENDPOINT_NOT_FOUND -102
+#define ERR_DEVICE_NOT_FOUND -103
+#define ERR_DEVICE_NONE_LEFT -104
+#define ERR_HUB_INIT_FAILED -105
+#define ERR_INTERFACE_NOT_FOUND -106
+
+typedef struct
+{
+    u8    bLength;
+    u8    bDescriptorType;
+    u16 bcdUSB;
+    u8 bDeviceClass;
+    u8 bDeviceSubClass;
+    u8 bDeviceProtocol;
+    u8 bMaxPacketSize;
+    u16 idVendor;
+    u16 idProduct;
+    u16 bcdDevice;    // version
+    u8 iManufacturer;
+    u8 iProduct;
+    u8 iSerialNumber;
+    u8 bNumConfigurations;
+} DeviceDescriptor;    // 16 bytes
+
+typedef struct
+{
+    u8    bLength;
+    u8    bDescriptorType;
+    u16    wTotalLength;
+    u8    bNumInterfaces;
+    u8    bConfigurationValue;    // Value to use as an argument to select this configuration
+    u8    iConfiguration;            // Index of String Descriptor describing this configuration
+    u8    bmAttributes;            // Bitmap D7 Reserved, set to 1. (USB 1.0 Bus Powered),D6 Self Powered,D5 Remote Wakeup,D4..0 = 0
+    u8    bMaxPower;                // Maximum Power Consumption in 2mA units
+} ConfigurationDescriptor;
+
+typedef struct
+{
+    u8    bLength;
+    u8    bDescriptorType;
+    u8  bInterfaceNumber;
+    u8    bAlternateSetting;
+    u8    bNumEndpoints;
+    u8    bInterfaceClass;
+    u8    bInterfaceSubClass;
+    u8    bInterfaceProtocol;
+    u8    iInterface;                // Index of String Descriptor Describing this interface
+} InterfaceDescriptor;
+
+typedef struct
+{
+    u8    bLength;
+    u8    bDescriptorType;
+    u8    bEndpointAddress;    // Bits 0:3 endpoint, Bits 7 Direction 0 = Out, 1 = In (Ignored for Control Endpoints)
+    u8    bmAttributes;        // Bits 0:1 00 = Control, 01 = Isochronous, 10 = Bulk, 11 = Interrupt
+    u16 wMaxPacketSize;
+    u8    bInterval;            // Interval for polling endpoint data transfers.
+} EndpointDescriptor;
+
+typedef struct {
+  u8    bLength;
+  u8    bDescriptorType;
+  u16   bcdHID;
+  u8    bCountryCode;
+  u8    bNumDescriptors;
+  u8    bDescriptorType2;
+  u16   wDescriptorLength;
+} HIDDescriptor;
+
+//============================================================================
+//============================================================================
+
+
+void USBInit();
+void USBLoop();
+u8* USBGetBuffer(u32* len);
+
+//    Optional callback for transfers, called at interrupt time
+typedef void (*USBCallback)(int device, int endpoint, int status, u8* data, int len, void* userData);
+
+//    Transfers
+int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback = 0, void* userData = 0);
+int USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback = 0, void* userData = 0);
+int USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback = 0, void* userData = 0);
+
+//    Standard Device methods
+int GetDescriptor(int device, int descType, int descIndex, u8* data, int length);
+int GetString(int device, int index, char* dst, int length);
+int SetAddress(int device, int new_addr);
+int SetConfiguration(int device, int configNum);
+int SetInterface(int device, int ifNum, int altNum);
+
+int SetPortReset(int device, int port);
+int GetPortStatus(int device, int port, u32* status);
+int SetPortPower(int device, int port);
+void ClearPortPower();
+void Reset();
+//    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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/Utils.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,48 @@
+
+
+#include "mbed.h"
+#include "Utils.h"
+
+void printfBytes(const char* s, const u8* data, int len)
+{
+    printf("%s %d:",s,len);
+    if (len > 256)
+        len = 256;
+    while (len-- > 0)
+        printf(" %02X",*data++);
+    printf("\n");
+}
+
+void printHexLine(const u8* d, int addr, int len)
+{
+    printf("%04X ",addr);
+    int i;
+    for (i = 0; i < len; i++)
+        printf("%02X ",d[i]);
+    for (;i < 16; i++)
+        printf("   ");
+    char s[16+1];
+    memset(s,0,sizeof(s));
+    for (i = 0; i < len; i++)
+    {
+        int c = d[i];
+        if (c < 0x20 || c > 0x7E)
+            c = '.';
+        s[i] = c;
+    }
+    printf("%s\n",s);
+}
+
+void printHex(const u8* d, int len)
+{
+    int addr = 0;
+    while (len)
+    {
+        int count = len;
+        if (count > 16)
+            count = 16;
+        printHexLine(d+addr,addr,count);
+        addr += 16;
+        len -= count;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHost/Utils.h	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,37 @@
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+
+void DelayMS(int ms);
+
+void printfBytes(const char* label,const u8* data, int len);
+void printHex(const u8* d, int len);
+
+#ifndef min
+#define min(_a,_b) ((_a) < (_b) ? (_a) : (_b))
+#endif
+
+inline int LE16(const u8* d)
+{
+    return d[0] | (d[1] << 8);
+}
+
+inline u32 BE32(const u8* d)
+{
+    return (d[0] << 24) | (d[1] << 16) | (d[2] << 8) | d[3];
+}
+
+inline void BE32(u32 n, u8* d)
+{
+    d[0] = (u8)(n >> 24);
+    d[1] = (u8)(n >> 16);
+    d[2] = (u8)(n >> 8);
+    d[3] = (u8)n;
+}
+
+inline void BE16(u32 n, u8* d)
+{
+    d[0] = (u8)(n >> 8);
+    d[1] = (u8)n;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,217 @@
+/*
+Copyright (c) 2010 Peter Barrett
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+#include "mbed.h"
+#include "USBHost.h"
+#include "Utils.h"
+#include "UsbStorage.h"
+
+#include "EthernetNetIf.h"
+#include "HTTPClient.h"
+#include "Dropbox.h"
+#include "HTTPServer.h"
+#include "HttpHandlerSetup.h"
+#include "HttpHandlerUsbBrowser.h"
+#include "HTTPFileSender.h"
+#include "base64.h"
+#include "url.h"
+#include "ctc_hmac.h"
+#include "NTPClient.h"
+#include "HTTPData.h"
+
+void test_dropbox();
+
+// USB
+Serial pc(USBTX, USBRX);
+USBFileSystem fs;
+int usbDevice = -1;
+
+// NET
+EthernetNetIf* eth;
+
+// LED
+DigitalOut led1(LED1);
+DigitalOut led2(LED2);
+DigitalOut led3(LED3);
+
+int OnDiskInsert(int device)
+{
+    printf("\r\nOnDiskInsert\r\n");
+    
+    usbDevice = device;
+    fs.SetDevice(usbDevice);
+    
+    return 0;
+}
+
+
+bool setup_eth()
+{
+  printf("\r\nSetting up...\r\n");
+
+  EthernetErr ethErr = eth->setup();
+  if(ethErr)
+  {
+    printf("Error %d in setup.\n", ethErr);
+    return false;
+  }
+  printf("\r\nSetup OK\r\n");
+  
+  return true;
+}
+
+bool setup_httpServer(HTTPServer& svr)
+{
+   svr.addHandler<HttpHandlerUsbBrowser>("/UsbBrowser");  
+   svr.addHandler<HttpHandlerSetup>("/");
+   svr.bind(80);
+
+   printf("Http Server initialized\r\n");  
+   
+   return true;   
+}
+
+bool upload_files(char* username, char* password)
+{
+    DIR *d = opendir("/usb/DROPBOX"); //TODO - global
+    int totalFiles = -1;
+    if (d)
+    {
+        char filenameSrc[64] = "/usb/DROPBOX/";
+        char filenameDst[32] = "USBSYNC_"; //TODO - remove?
+        int c = 0;
+        
+        printf("Synchronize Start\n\r");
+        if (!dropbox_syncTime())
+        {
+            printf("Failed to sync time");
+            led3 = 1;
+            return totalFiles;
+        }
+        if (!dropbox_getToken(username, password))
+        {
+            printf("Failed getting token\r\n");
+            led3 = 1;
+            return totalFiles;
+        }
+    
+        struct dirent *p = readdir(d);
+        while (p)
+        {
+            strcpy(filenameSrc + 13, p->d_name);
+            strcpy(filenameDst + 8, p->d_name);
+            printf("Uploading %s to %s\r\n", filenameSrc, filenameDst);
+            
+            dropbox_upload(filenameSrc, filenameDst);
+            c++;
+            p = readdir(d);
+        }
+        
+        closedir(d);
+        
+        totalFiles = c;
+        printf("Synchronizing finished (%d)\n\r", totalFiles);
+        led2 = 1;
+        
+        return totalFiles;
+    }
+    else
+    {
+        led3 = 1;
+        printf("Failed opening /usb/DROPBOX/\r\n");
+        return totalFiles;
+    }
+}
+
+int main()
+{
+    bool ethSetup = false, httpSetup = false;
+    USBInit();    
+    HTTPServer svr;
+    
+    int i = 0;
+    
+    led3 = 0; // clear error LED
+    
+    for (;;)
+    {
+        if (i++ % 500000 == 0) printf("looping\r\n"); //TODO replace with time
+        
+        USBLoop();
+        Net::poll();
+        
+        if (!ethSetup)
+        {
+            eth = new EthernetNetIf();
+            ethSetup = setup_eth();
+            
+            if (!ethSetup)
+            {
+                delete eth;
+                eth = 0;
+            }
+            
+            httpSetup = false;
+        }
+        
+        if (ethSetup && !httpSetup)
+        {
+           httpSetup = setup_httpServer(svr);         
+        }
+        
+        // Cehck if Ethernet setup and USB-Disk connected
+        if (usbDevice >= 0 && ethSetup)
+        {                       
+            usbDevice = -1;
+
+            led1 = 1;
+            led2 = 0;
+            
+            // Read username/password
+            char username[32] = {0};
+            char password[32] = {0};
+            if (!ReadSettings(username, password))
+            {
+                printf("Failed opening /usb/DBSet.txt\r\n");
+                led3 = 1;
+                continue;
+            }
+            
+            // Start synchronizing
+            int totalFiles = upload_files(username, password);
+
+            FILE* logFile = fopen("/usb/dbLog.txt", "a+");
+            if (logFile)
+            {
+                if (totalFiles >= 0)
+                    fprintf(logFile, "%d Synchronizing successfull %d files\r\n", time(NULL), totalFiles);
+                else
+                    fputs("Synchronizing failed\r\n", logFile); //TODO whats this?
+                
+                fclose(logFile);
+            }
+
+            led1 = 0;
+           ClearPortPower();
+        }
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Sun Apr 17 21:30:10 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0