Sergio Collado / Mbed 2 deprecated USBHostShell_HID_talkactive_alpha

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHost.cpp Source File

USBHost.cpp

00001 
00002 /*
00003 I changed a bit the code but all credit goes to the amazing work of :
00004 
00005 Copyright (c) 2010 Peter Barrett
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00020 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00021 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00022 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00023 THE SOFTWARE.
00024 */
00025 
00026 #include "mbed.h"
00027 #include "USBHost.h"
00028 
00029 //    Config (default uses x bytes)
00030 #define MAX_DEVICES 8                // Max number of devices
00031 #define MAX_ENDPOINTS_TOTAL 16        // Max number of endpoints total
00032 #define MAX_ENDPOINTS_PER_DEVICE 8    // Max number of endpoints for any one device
00033 
00034 #define  USBLOG 1
00035 #if USBLOG
00036 #define  LOG(...)       printf(__VA_ARGS__)
00037 #else 
00038 #define  LOG(...)       do {} while(0)
00039 #endif
00040 
00041 // USB host structures
00042 
00043 #define USB_RAM_SIZE 16*1024    // AHB SRAM block 1 TODO MACHINE DEPENDENT
00044 #define USB_RAM_BASE 0x2007C000
00045 
00046 #define TOKEN_SETUP 0
00047 #define TOKEN_IN  1
00048 #define TOKEN_OUT 2
00049 
00050 //    Status flags from hub
00051 #define PORT_CONNECTION 0
00052 #define PORT_ENABLE  1
00053 #define PORT_SUSPEND  2
00054 #define PORT_OVER_CURRENT 3
00055 #define PORT_RESET 4
00056 #define PORT_POWER 8
00057 #define PORT_LOW_SPEED 9
00058 
00059 #define C_PORT_CONNECTION 16
00060 #define C_PORT_ENABLE 17
00061 #define C_PORT_SUSPEND 18
00062 #define C_PORT_OVER_CURRENT 19
00063 #define C_PORT_RESET 20
00064 
00065 typedef struct {
00066     u8 bm_request_type;
00067     u8 b_request;
00068     u16 w_value;
00069     u16 w_index;
00070     u16 w_length;
00071 } Setup;
00072 
00073 
00074 //    Hub stuff is kept private just to keep api simple
00075 int SetPortFeature(int device, int feature, int index);
00076 int ClearPortFeature(int device, int feature, int index);
00077 int SetPortPower(int device, int port);
00078 int SetPortReset(int device, int port);
00079 int GetPortStatus(int device, int port, u32* status);
00080 
00081 //===================================================================
00082 //===================================================================
00083 //    Hardware defines
00084 
00085 //    HcControl
00086 #define    PeriodicListEnable    0x00000004
00087 #define    IsochronousEnable    0x00000008
00088 #define    ControlListEnable    0x00000010
00089 #define    BulkListEnable        0x00000020
00090 #define    OperationalMask        0x00000080
00091 #define    HostControllerFunctionalState    0x000000C0
00092 
00093 //    HcCommandStatus
00094 #define HostControllerReset    0x00000001
00095 #define ControlListFilled    0x00000002
00096 #define BulkListFilled        0x00000004
00097 
00098 //    HcInterruptStatus Register
00099 #define    WritebackDoneHead        0x00000002
00100 #define    StartofFrame            0x00000004
00101 #define ResumeDetected            0x00000008
00102 #define UnrecoverableError        0x00000010
00103 #define FrameNumberOverflow        0x00000020
00104 #define RootHubStatusChange        0x00000040
00105 #define OwnershipChange            0x00000080
00106 #define MasterInterruptEnable    0x80000000
00107 
00108 //    HcRhStatus
00109 #define SetGlobalPower            0x00010000
00110 #define DeviceRemoteWakeupEnable    0x00008000
00111 
00112 //    HcRhPortStatus (hub 0, port 1)
00113 #define CurrentConnectStatus    0x00000001
00114 #define    PortEnableStatus        0x00000002
00115 #define PortSuspendStatus        0x00000004
00116 #define PortOverCurrentIndicator    0x00000008
00117 #define PortResetStatus            0x00000010
00118 
00119 #define PortPowerStatus            0x00000100
00120 #define LowspeedDevice            0x00000200
00121 #define HighspeedDevice            0x00000400
00122 
00123 #define ConnectStatusChange    (CurrentConnectStatus << 16)
00124 #define PortResetStatusChange    (PortResetStatus << 16)
00125 
00126 
00127 #define  TD_ROUNDING        (u32)0x00040000
00128 #define  TD_SETUP            (u32)0x00000000
00129 #define  TD_IN                (u32)0x00100000
00130 #define  TD_OUT                (u32)0x00080000
00131 #define  TD_DELAY_INT(x)    (u32)((x) << 21)
00132 #define  TD_TOGGLE_0        (u32)0x02000000
00133 #define  TD_TOGGLE_1        (u32)0x03000000
00134 #define  TD_CC                (u32)0xF0000000
00135 
00136 //    HostController EndPoint Descriptor
00137 typedef struct {
00138     volatile u32    Control;
00139     volatile u32    TailTd;
00140     volatile u32    HeadTd;
00141     volatile u32    Next;
00142 } HCED;
00143 
00144 // HostController Transfer Descriptor
00145 typedef struct {
00146     volatile u32    Control;
00147     volatile u32    CurrBufPtr;
00148     volatile u32    Next;
00149     volatile u32    BufEnd;
00150 } HCTD;
00151 
00152 // Host Controller Communication Area
00153 typedef struct {
00154     volatile u32    InterruptTable[32];
00155     volatile u16    FrameNumber;
00156     volatile u16    FrameNumberPad;
00157     volatile u32    DoneHead;
00158     volatile u8     Reserved[120];
00159 } HCCA;
00160 
00161 //====================================================================================
00162 //====================================================================================
00163 
00164 class HostController;
00165 class Endpoint;
00166 class Device;
00167 
00168 //      must be 3*16 bytes long
00169 class Endpoint
00170 {
00171 public:
00172     HCED    EndpointDescriptor;    // Pointer to EndpointDescriptor == Pointer to Endpoint
00173     HCTD    TDHead;
00174 
00175     enum State
00176     {
00177         Free,
00178         NotQueued,
00179         Idle,
00180         SetupQueued,
00181         DataQueued,
00182         StatusQueued,
00183         CallbackPending
00184     };
00185     
00186     volatile u8 CurrentState;
00187     u8        Flags;            // 0x80 In, 0x03 mask endpoint type
00188 
00189     u16        Length;
00190     u8*        Data;
00191     USBCallback Callback;     // Must be a multiple of 16 bytes long
00192     void*  UserData;
00193   
00194     int Address()
00195     {
00196         int ep = (EndpointDescriptor.Control >> 7) & 0xF;
00197         if (ep)
00198             ep |= Flags & 0x80;
00199         return ep;
00200     }
00201     
00202     int Device()
00203     {
00204         return EndpointDescriptor.Control & 0x7F;
00205     }
00206 
00207     int Status()
00208     {
00209         return (TDHead.Control >> 28) & 0xF;
00210     }
00211 
00212     u32 Enqueue(u32 head)
00213     {
00214         if (CurrentState == NotQueued)
00215         {
00216             EndpointDescriptor.Next = head;
00217             head = (u32)&EndpointDescriptor;
00218             CurrentState = Idle;
00219         }
00220         return head;
00221     }
00222 };
00223 
00224 class Device
00225 {
00226 public:
00227     u8    _endpointMap[MAX_ENDPOINTS_PER_DEVICE*2];
00228     u8    Hub;
00229     u8    Port;
00230     u8    Addr;
00231     u8    Pad;
00232 
00233     //    Only if this device is a hub
00234     u8    HubPortCount;    // nonzero if this is a hub
00235     u8    HubInterruptData;
00236     u8    HubMap;
00237     u8    HubMask;
00238 
00239     int Flags;        // 1 = Disconnected
00240 
00241     Setup    SetupBuffer;
00242 
00243     // Allocate endpoint zero
00244     int Init(DeviceDescriptor* d, int hub, int port, int addr, int lowSpeed)
00245     {
00246         Hub = hub;
00247         Port = port;
00248         Addr = addr;
00249         Flags = lowSpeed;
00250         memset(_endpointMap,0xFF,sizeof(_endpointMap));
00251         return 0;
00252     }
00253 
00254     int SetEndpointIndex(int ep, int endpointIndex)
00255     {
00256         for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
00257         {
00258             if (_endpointMap[i] == 0xFF)    // Add endpoint to map
00259             {
00260                 _endpointMap[i] = ep;
00261                 _endpointMap[i+1] = endpointIndex;
00262                 return 0;
00263             }
00264         }
00265         return ERR_ENDPOINT_NONE_LEFT;
00266     }
00267 
00268     int GetEndpointIndex(int ep)
00269     {
00270         for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2)
00271         {
00272             if (_endpointMap[i] == ep)
00273                 return _endpointMap[i+1];
00274             if (_endpointMap[i] == 0xFF)
00275                 break;
00276         }
00277         return -1;
00278     }
00279 };
00280 
00281 class HostController
00282 {
00283 public:
00284     HCCA        CommunicationArea;
00285     Endpoint    Endpoints[MAX_ENDPOINTS_TOTAL];    // Multiple of 16
00286     
00287     Endpoint    EndpointZero;                        // For device enumeration
00288     HCTD        _commonTail;
00289     Setup        _setupZero;
00290     
00291     Device    Devices[MAX_DEVICES];
00292     u32    _frameNumber;            // 32 bit ms counter
00293 
00294     u8    _callbacksPending;        //    Endpoints with callbacks are pending, set from ISR via ProcessDoneQueue
00295     u8    _rootHubStatusChange;     //    Root hub status has changed, set from ISR
00296     u8    _unused0;
00297     u8    _unused1;
00298 
00299     u8    _connectPending;    //    Reset has initiated a connect
00300     u8    _connectCountdown;    //    Number of ms left after reset before we can connect
00301     u8    _connectHub;        //    Will connect on this hub
00302     u8    _connectPort;        //    ... and this port
00303 
00304     u8    SRAM[0];            // Start of free SRAM
00305 
00306     void Loop()
00307     {
00308         u16 elapsed = CommunicationArea.FrameNumber - (u16)_frameNumber;    // extend to 32 bits
00309         _frameNumber += elapsed;
00310 
00311         // Do callbacks, if any
00312         while (_callbacksPending)
00313         {
00314             for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
00315             {
00316                 Endpoint* endpoint = Endpoints + i;
00317                 if (endpoint->CurrentState == Endpoint::CallbackPending)
00318                 {
00319                     _callbacksPending--;
00320                     endpoint->CurrentState = Endpoint::Idle;
00321                     //remember:
00322                     //typedef void (*USBCallback)(int device, int endpoint, int status, u8* data, int len, void* userData);
00323                      endpoint->Callback(endpoint->Device(),endpoint->Address(),endpoint->Status(),endpoint->Data,endpoint->Length,endpoint->UserData);
00324                 
00325                 }
00326             }
00327         }
00328 
00329         //    Deal with changes on the root hub
00330         if (_rootHubStatusChange)
00331         {
00332             u32 status = LPC_USB->HcRhPortStatus1;
00333             _rootHubStatusChange = 0;
00334             if (status >> 16)
00335             {
00336                 HubStatusChange(0,1,status);
00337                 LPC_USB->HcRhPortStatus1 = status & 0xFFFF0000;    // clear status changes
00338             }
00339         
00340         }
00341 
00342         //    Connect after reset timeout
00343         if (_connectCountdown)
00344         {
00345             if (elapsed >= _connectCountdown)
00346             {
00347                 _connectCountdown = 0;
00348                 Connect(_connectHub,_connectPort & 0x7F,_connectPort & 0x80);
00349             } else
00350                 _connectCountdown -= elapsed;
00351         }
00352     }// END OF VOID LOOP()
00353     
00354 
00355     //    HubInterrupt - bitmap in dev->HubInterruptData
00356     void HubInterrupt(int device)
00357     {
00358         Device* dev = &Devices[device-1];
00359         for (int i = 0; i < dev->HubPortCount; i++)
00360         {
00361             int port = i+1;
00362             if (dev->HubInterruptData & (1 << port))
00363             {
00364                 u32 status = 0;
00365                 GetPortStatus(device,port,&status);
00366                 if (status >> 16)
00367                 {
00368                     if (_connectPending && (status & ConnectStatusChange))
00369                         continue;    // Don't connect again until previous device has been added and addressed
00370 
00371                     HubStatusChange(device,port,status);
00372                     if (status & ConnectStatusChange)
00373                         ClearPortFeature(device,C_PORT_CONNECTION,port);
00374                     if (status & PortResetStatusChange)
00375                         ClearPortFeature(device,C_PORT_RESET,port);
00376                 }
00377             }
00378         }
00379     }
00380 
00381     static void HubInterruptCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
00382     {
00383         HostController* controller = (HostController*)userData;
00384         if (status == 0)
00385             controller->HubInterrupt(device);
00386         USBInterruptTransfer(device,endpoint,data,1,HubInterruptCallback,userData);
00387     }
00388 
00389     int InitHub(int device)
00390     {
00391         u8 buf[16];
00392         int r= USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_DEVICE,GET_DESCRIPTOR,(DESCRIPTOR_TYPE_HUB << 8),0,buf,sizeof(buf));
00393         if (r < 0)
00394             return ERR_HUB_INIT_FAILED;
00395         
00396         //    turn on power on the hubs ports
00397         Device* dev = &Devices[device-1];
00398         int ports = buf[2];
00399         dev->HubPortCount = ports;
00400         for (int i = 0; i < ports; i++)
00401             SetPortPower(device,i+1);
00402         
00403         // Enable hub change interrupts
00404         return USBInterruptTransfer(device,0x81,&dev->HubInterruptData,1,HubInterruptCallback,this);
00405     }
00406     
00407     int AddEndpoint(int device, int ep, int attributes, int maxPacketSize, int interval)
00408     {
00409         LOG("AddEndpoint D:%02X A:%02X T:%02X P:%04X I:%02X\n",device,ep,attributes,maxPacketSize,interval);
00410         Device* dev = &Devices[device-1];
00411         Endpoint* endpoint = AllocateEndpoint(device,ep,attributes,maxPacketSize);
00412         if (!endpoint)
00413             return ERR_ENDPOINT_NONE_LEFT;
00414         dev->SetEndpointIndex(ep,endpoint - Endpoints);
00415         endpoint->EndpointDescriptor.Control |= dev->Flags; // Map in slow speed
00416         return 0;  // TODO ed->bInterval
00417     }
00418     
00419     int AddEndpoint(int device, EndpointDescriptor* ed)
00420     {
00421         return AddEndpoint(device,ed->bEndpointAddress,ed->bmAttributes,ed->wMaxPacketSize,ed->bInterval);
00422     }
00423 
00424     //      allocate a endpoint
00425     Endpoint* AllocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize)
00426     {
00427         for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++)
00428         {
00429             Endpoint* ep = &Endpoints[i];
00430             if (ep->CurrentState == 0)
00431             {
00432                 //LOG("Allocated endpoint %d to %02X:%02X\n",i,device,endpointAddress);
00433                 ep->Flags = (endpointAddress & 0x80) | (type & 3);
00434                 ep->CurrentState = Endpoint::NotQueued;
00435                 ep->EndpointDescriptor.Control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device;
00436                 return ep;
00437             }
00438         }
00439         return 0;
00440     }
00441 
00442     Endpoint* GetEndpoint(int device, int ep)
00443     {
00444         if (device == 0)
00445         {
00446             //printf("WARNING: USING DEVICE 0\n");
00447             return &EndpointZero;
00448         }
00449         if (device > MAX_DEVICES)
00450             return 0;
00451         int i = Devices[device-1].GetEndpointIndex(ep);
00452         if (i == -1)
00453             return 0;
00454         return Endpoints + i;
00455     }
00456 
00457     int Transfer(Endpoint* endpoint, int token, u8* data, int len, int state)
00458     {
00459         #ifdef USBLOG
00460         LOG("Transfer EDaddres:%02X Token:%d Len:%d State:%d \n",endpoint->Address(),token,len,state);
00461         LOG("Data %s: ",(token==TOKEN_IN)? "in": "out");
00462         
00463         //print the data:
00464         //@BUG, little endian- bigendian ??
00465         for (int i=0; i<len; i++)
00466         {
00467          if (  ((i%(int)8)==0)  ) LOG("\n"); 
00468             LOG("hx%02X  ",data[i]);   
00469         } 
00470         LOG("\n");
00471         
00472         if ( token==TOKEN_IN && len<30  && len>8)
00473         {
00474          
00475         LOG("bLength: %d d \n", data[0]);
00476         LOG("bDescriptorType: %d -",data[1]);
00477         /*
00478         bDescriptorType Descriptor Type Required?
00479 01h device Yes.
00480 02h configuration Yes.
00481 03h string No. Optional descriptive text.
00482 04h interface Yes.
00483 05h endpoint No, if the device uses only Endpoint 0.
00484 06h device_qualifier Yes, for devices that support both full and high
00485 speeds. Not allowed for other devices.
00486 07h other_speed_configuration Yes, for devices that support both full and high
00487 speeds. Not allowed for other devices.
00488 08h interface_power No. Supports interface-level power
00489 management.
00490 09h OTG For On-The-Go devices only.
00491 0Ah debug No.
00492 0Bh interface_association For composite devices.
00493         */
00494         switch (data[1])
00495         { 
00496            case(1): { LOG("DEVICE"); break;}
00497               case(2): { LOG("CONFIGURATION"); break;}
00498               case(3): { LOG("STRING"); break;}
00499               case(4): { LOG("INTERFACE"); break;}
00500               case(5): { LOG("ENDPOINT"); break;}
00501               case(6): { LOG("DEVICE_QUALIFIER"); break;}
00502               case(7): { LOG("OTHER_SPEED_CONFIGURATION"); break;}
00503               case(8): { LOG("ON_the_GO"); break;}
00504               case(9): { LOG("DEBUG"); break;}
00505               case(10): { LOG("INTERFACE_ASSOCIATION"); break;}
00506            default: {LOG("?");} ;
00507         }//end switch data1;
00508         LOG("\n");
00509         }
00510         
00511         //the descriptor for device:
00512         if(data[1]==1)
00513         {
00514         u16 *aux;
00515         aux=(u16*) &data[2];
00516         LOG("bcdUSB\t %04x\t",*aux);
00517          switch( *aux)
00518          {
00519           case(0x0200): {LOG("v2.0"); break;}
00520           case(0x0110): {LOG("v1.1"); break;}
00521           case(0x0100): {LOG("v1.0"); break;}
00522           default: {LOG("?");}
00523           }
00524          LOG("\n");
00525          }
00526         
00527         
00528         
00529         
00530         #endif
00531         
00532         int toggle = 0;
00533         if (endpoint->Address() == 0)
00534             toggle = (token == TOKEN_SETUP) ? TD_TOGGLE_0 : TD_TOGGLE_1;
00535 
00536         if (token != TOKEN_SETUP)
00537             token = (token == TOKEN_IN ? TD_IN : TD_OUT);
00538 
00539         HCTD* head = &endpoint->TDHead;
00540         HCTD* tail = &_commonTail;
00541 
00542         head->Control = TD_ROUNDING | token | TD_DELAY_INT(0) | toggle | TD_CC; 
00543         head->CurrBufPtr = (u32)data; //..data is a pointer.
00544         head->BufEnd = (u32)(data + len - 1); //pointers arithmetic :S
00545         head->Next = (u32)tail;
00546 
00547         HCED* ed = &endpoint->EndpointDescriptor;
00548         ed->HeadTd = (u32)head | (ed->HeadTd & 0x00000002);    // carry toggle
00549         ed->TailTd = (u32)tail;
00550         
00551         //HCTD* td = head;
00552         //LOG("%04X TD %08X %08X %08X Next:%08X\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next);
00553         //LOG("%04X ED %08X %08X %08X\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd);
00554         
00555         switch (endpoint->Flags & 3)
00556         {
00557             case ENDPOINT_CONTROL:
00558                 LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED);    // May change state NotQueued->Idle
00559                 endpoint->CurrentState = state;                                               // Get in before an int
00560                 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | ControlListFilled;
00561                 LPC_USB->HcControl = LPC_USB->HcControl | ControlListEnable;
00562                 break;
00563 
00564             case ENDPOINT_BULK:
00565                 LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED);
00566                 endpoint->CurrentState = state;
00567                 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled;
00568                 LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable;
00569                 break;
00570 
00571             case ENDPOINT_INTERRUPT:
00572                 CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]);
00573                 endpoint->CurrentState = state;
00574                 LPC_USB->HcControl |= PeriodicListEnable;
00575                 break;
00576         }
00577         return 0;
00578     }//end of transfer
00579     
00580     //    Remove an endpoint from an active queue
00581     bool Remove(HCED* ed, volatile HCED** queue)
00582     {
00583         if (*queue == 0)
00584             return false;
00585         if (*queue == (volatile HCED*)ed)
00586         {
00587             *queue = (volatile HCED*)ed->Next;    // At head of queue
00588             return true;
00589         }
00590 
00591         volatile HCED* head = *queue;
00592         while (head)
00593         {
00594             if (head->Next == (u32)ed)
00595             {
00596                 head->Next = ed->Next;
00597                 return true;
00598             }
00599             head = (volatile HCED*)head->Next;
00600         }
00601         return false;
00602     }
00603 
00604     void Release(Endpoint* endpoint)
00605     {
00606         if (endpoint->CurrentState == Endpoint::NotQueued)
00607         {
00608             // Never event used it, nothing to do
00609         }
00610         else
00611         {
00612             HCED* ed = (HCED*)endpoint;
00613             ed->Control |= 0x4000;    // SKIP
00614             switch (endpoint->Flags & 0x03)
00615             {
00616                 case ENDPOINT_CONTROL:
00617                     Remove(ed,(volatile HCED**)&LPC_USB->HcControlHeadED);
00618                     break;
00619                 case ENDPOINT_BULK:
00620                     Remove(ed,(volatile HCED**)&LPC_USB->HcBulkHeadED);
00621                     break;
00622                 case ENDPOINT_INTERRUPT:
00623                     for (int i = 0; i < 32; i++)
00624                         Remove(ed,(volatile HCED**)&CommunicationArea.InterruptTable[i]);
00625                     break;
00626             }
00627 
00628             u16 fn = CommunicationArea.FrameNumber;
00629             while (fn == CommunicationArea.FrameNumber)
00630                 ;    // Wait for next frame
00631 
00632         }
00633 
00634         //    In theory, the endpoint is now dead.
00635         //    TODO: Will Callbacks ever be pending? BUGBUG
00636         memset(endpoint,0,sizeof(Endpoint));
00637     }
00638 
00639     //      Pop the last TD from the list
00640     HCTD* Reverse(HCTD* current) 
00641     { 
00642         HCTD *result = NULL,*temp; 
00643         while (current) 
00644         { 
00645             temp = (HCTD*)current->Next; 
00646             current->Next = (u32)result;
00647             result = current;
00648             current = temp;
00649         }
00650         return result;
00651     }
00652 
00653     //      Called from interrupt...
00654     //      Control endpoints use a state machine to progress through the transfers
00655     void ProcessDoneQueue(u32 tdList)
00656     {
00657         HCTD* list = Reverse((HCTD*)tdList);
00658         while (list)
00659         {
00660             Endpoint* endpoint = (Endpoint*)(list-1);
00661             list = (HCTD*)list->Next;
00662             int ep = endpoint->Address();
00663             bool in = endpoint->Flags & 0x80;
00664             int status = (endpoint->TDHead.Control >> 28) & 0xF;
00665 
00666             LOG("ProcessDoneQueue %02X %08X\n\n",ep,endpoint->TDHead.Control);
00667 
00668             if (status != 0)
00669             {
00670                 LOG("ProcessDoneQueue status %02X %d\n\n",ep,status);
00671                 endpoint->CurrentState = Endpoint::Idle;
00672             } else {
00673                 switch (endpoint->CurrentState)
00674                 {
00675                     case Endpoint::SetupQueued:
00676                         if (endpoint->Length == 0)
00677                             Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Skip Data Phase
00678                         else
00679                             Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued);    // Setup is done, now Data
00680                         break;
00681 
00682                     case Endpoint::DataQueued:
00683                         if (endpoint->TDHead.CurrBufPtr)
00684                             endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data;
00685 
00686                         if (ep == 0)
00687                             Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Data is done, now Status, Control only
00688                         else
00689                             endpoint->CurrentState = Endpoint::Idle;
00690                         break;
00691 
00692                     case Endpoint::StatusQueued:    // Transaction is done
00693                         endpoint->CurrentState = Endpoint::Idle;
00694                         break;
00695                 }
00696             }
00697 
00698             //      Complete, flag if we need a callback
00699             if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle)
00700             {
00701                 endpoint->CurrentState = Endpoint::CallbackPending;
00702                 _callbacksPending++;
00703             }
00704         }
00705     }
00706 
00707     //    Hack to reset devices that don't want to connect
00708     int AddDevice(int hub, int port, bool isLowSpeed)
00709     {
00710         int device = AddDeviceCore(hub,port,isLowSpeed);
00711         if (device < 0)
00712         {
00713             LOG("========RETRY ADD DEVICE========\n");    // This will go for ever.. TODO power cycle root?
00714             Disconnect(hub,port);    // Could not read descriptor at assigned address, reset this port and try again
00715             ResetPort(hub,port);    // Cheap bluetooth dongles often need this on a hotplug
00716             return -1;
00717         }
00718         return device;
00719     }
00720 
00721     int AddDeviceCore(int hub, int port, bool isLowSpeed)
00722     {
00723         int lowSpeed = isLowSpeed ? 0x2000 : 0;
00724         DeviceDescriptor desc;
00725         EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed;               // MaxPacketSize == 8
00726         int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8);
00727         if (r < 0)
00728         {
00729             LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\n");
00730             return r;
00731         }
00732 
00733         EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed;     // Actual MaxPacketSize
00734         r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
00735         if (r < 0)
00736             return r;
00737 
00738         LOG("\nClass %02X found %04X:%04X\n\n",desc.bDeviceClass,desc.idVendor,desc.idProduct);
00739   
00740         
00741         // Now assign the device an address, move off EndpointZero
00742         int device = 0;
00743         for (int i = 0; i < MAX_DEVICES; i++)
00744         {
00745             if (Devices[i].Port == 0)
00746             {
00747                 device = i+1;
00748                 break;
00749             }
00750         }
00751         if (!device)
00752             return ERR_DEVICE_NONE_LEFT;
00753 
00754         r = SetAddress(0,device);
00755         if (r)
00756             return r;
00757         DelayMS(2);
00758         
00759         // Now at a nonzero address, create control endpoint
00760         Device* dev = &Devices[device-1];
00761         dev->Init(&desc,hub,port,device,lowSpeed);
00762         AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0);
00763         _connectPending = 0;
00764 
00765         //    Verify this all works
00766         r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
00767         if (r < 0)
00768             return r;
00769 
00770         //    Set to interface 0 by default
00771         //    Calls LoadDevice if interface is found
00772         r = SetConfigurationAndInterface(device,1,0,&desc);
00773 
00774         if (desc.bDeviceClass == CLASS_HUB)
00775             InitHub(device);            // Handle hubs in this code
00776 
00777         return device;
00778     }
00779 
00780     // Walk descriptors and create endpoints for a given device
00781     // TODO configuration !=1, alternate settings etc.
00782     int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc)
00783     {
00784         LOG("SetConfiguration and Interface\n");
00785         u8 buffer[255];
00786         int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,sizeof(buffer));
00787         if (err < 0)
00788             return err;
00789 
00790         err = SetConfiguration(device,configuration);
00791         if (err < 0)
00792             return err;
00793 
00794         //    Add the endpoints for this interface
00795         int len = buffer[2] | (buffer[3] << 8);
00796         u8* d = buffer;
00797         u8* end = d + len;
00798         InterfaceDescriptor* found = 0;
00799         while (d < end)
00800         {
00801             if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
00802             {
00803                 InterfaceDescriptor* id = (InterfaceDescriptor*)d;
00804                 if (id->bInterfaceNumber == interfaceNumber)
00805                 {
00806                     found = id;
00807                     d += d[0];
00808                     while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE)
00809                     {
00810                         switch (d[1])
00811                         {
00812                             case DESCRIPTOR_TYPE_ENDPOINT:
00813                                 AddEndpoint(device,(EndpointDescriptor*)d);
00814                                 break;
00815                             default:
00816                                 LOG("Skipping descriptor %02X (%d bytes)\n",d[1],d[0]);
00817                         }
00818                         d += d[0];
00819                     }
00820                 }
00821             }
00822             d += d[0];
00823         }
00824 
00825         if (!found)
00826             return ERR_INTERFACE_NOT_FOUND;
00827         OnLoadDevice(device,desc,found);
00828         return 0;
00829     }
00830 
00831     void Init()
00832     {
00833         LOG("USB INIT (Controller is %d bytes)\n",sizeof(*this));
00834         memset(this,0,sizeof(HostController));
00835         EndpointZero.CurrentState = Endpoint::NotQueued;
00836         HWInit(&CommunicationArea);
00837         DelayMS(10);
00838     }
00839 
00840     void ResetPort(int hub, int port)
00841     {
00842         LOG("ResetPort Hub:%d Port:%d\n",hub,port);
00843         _connectPending++;            // Only reset/add 1 device at a time
00844         if (hub == 0)
00845             LPC_USB->HcRhPortStatus1 = PortResetStatus;    // Reset Root Hub, port 1
00846         else
00847         
00848             SetPortReset(hub,port);    // or reset other hub
00849     }
00850 
00851     void Disconnect(int hub, int port)
00852     {
00853         LOG("Disconnect Hub:%d Port:%d\n",hub,port);    // Mark a device for destruction
00854         for (int i = 0; i < MAX_DEVICES; i++)
00855         {
00856             Device* dev = Devices + i;
00857             if (dev->Port == port && dev->Hub == hub)
00858             {
00859                 //    Disconnect everything that is attached to this device if it is a hub
00860                 for (int p = 0; p < dev->HubPortCount; p++)
00861                     Disconnect(i+1,p+1);
00862 
00863                 //    Now release endpoints
00864                 for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2)
00865                 {
00866                     u8 endpointIndex = dev->_endpointMap[j];
00867                     if (endpointIndex != 0xFF)
00868                         Release(Endpoints + endpointIndex);
00869                 }
00870                 dev->Port = 0;    // Device is now free
00871                 dev->Flags = 0;
00872                 return;
00873             }
00874         }
00875     }
00876 
00877     // called after reset
00878     void Connect(int hub, int port, bool lowspeed)
00879     {
00880         LOG("Connect Hub:%d Port:%d %s\n\n",hub,port,lowspeed ? "slow-speed" : "full-speed");
00881         AddDevice(hub,port,lowspeed);
00882     }
00883 
00884     // Called from interrupt
00885     void HubStatusChange(int hub, int port, u32 status)
00886     {
00887         LOG("HubStatusChange Hub:%d Port:%d %08X\n",hub,port,status);
00888         if (status & ConnectStatusChange)
00889         {
00890             if (status & CurrentConnectStatus)    // Connecting
00891                 ResetPort(hub,port);            // Reset to initiate connect (state machine?)
00892             else
00893                 Disconnect(hub,port);
00894         }
00895 
00896         if (status & PortResetStatusChange)
00897         {
00898             if (!(status & PortResetStatus))
00899             {
00900                 _connectCountdown = 200;        // Schedule a connection in 200ms
00901                 if (status & LowspeedDevice)
00902                     port |= 0x80;
00903                 _connectHub = hub;
00904                 _connectPort = port;
00905             }
00906         }
00907     }
00908 
00909     #define HOST_CLK_EN        (1<<0)
00910     #define PORTSEL_CLK_EN    (1<<3)
00911     #define AHB_CLK_EN        (1<<4)
00912     #define CLOCK_MASK        (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
00913 
00914     #define  FRAMEINTERVAL        (12000-1)    // 1ms
00915     #define  DEFAULT_FMINTERVAL    ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL)
00916 
00917     void DelayMS(int ms)
00918     {
00919         u16 f = ms + CommunicationArea.FrameNumber;
00920         while (f != CommunicationArea.FrameNumber)
00921             ;
00922     }
00923 
00924     static void HWInit(HCCA* cca)
00925     {
00926         NVIC_DisableIRQ(USB_IRQn); //no interruptions
00927         
00928         // turn on power for USB
00929         LPC_SC->PCONP        |= (1UL<<31);
00930         // Enable USB host clock, port selection and AHB clock
00931         LPC_USB->USBClkCtrl |= CLOCK_MASK;
00932         // Wait for clocks to become available
00933         while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
00934             ;
00935         
00936         //    We are a Host
00937         LPC_USB->OTGStCtrl |= 1;
00938         LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;                // we don't need port selection clock until we do OTG
00939         
00940         // configure USB pins
00941         LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28));    
00942         LPC_PINCON->PINSEL1 |=    ((1<<26)|(1<<28));            // USB D+/D-
00943             
00944         LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22));        // USB_PPWR, USB_OVRCR
00945         LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22));
00946         
00947         LPC_PINCON->PINSEL4 &= ~(3 << 18);                    // USB_CONNECT
00948         LPC_PINCON->PINSEL4 |= (1 << 18);
00949 
00950         //    Reset OHCI block
00951         LPC_USB->HcControl         = 0; //Defines the operating modes of the HC.
00952         
00953         LPC_USB->HcControlHeadED = 0;   //Contains the physical address of the first endpoint
00954                                         //descriptor of the control list.
00955                                         
00956         LPC_USB->HcBulkHeadED     = 0;  //Contains the physical address of the first endpoint
00957                                         //descriptor of the bulk list.
00958         
00959         LPC_USB->HcCommandStatus = HostControllerReset; //This register is used to receive the commands from the
00960                                                         //Host Controller Driver (HCD). It also indicates the status
00961                                                         //of the HC.
00962                                                         
00963         LPC_USB->HcFmInterval     = DEFAULT_FMINTERVAL;
00964         LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100;
00965 
00966         LPC_USB->HcControl    = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask;
00967         LPC_USB->HcRhStatus = SetGlobalPower;
00968         
00969         LPC_USB->HcHCCA = (u32)cca; //Contains the physical address of the host controller
00970                                     //communication area.
00971                                     
00972         LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; //Indicates the status on various events that cause
00973                                                                   //hardware interrupts by setting the appropriate bits.
00974         LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow;
00975 
00976         NVIC_SetPriority(USB_IRQn, 0); //top-priority
00977         NVIC_EnableIRQ(USB_IRQn); //enable USB interruptions.
00978         LOG("\nHWini\n");
00979         while (cca->FrameNumber < 10)
00980             ;    // 10ms delay before diving in
00981     }
00982 };
00983 
00984 //====================================================================================
00985 //====================================================================================
00986 //      Host controller instance and Interrupt handler
00987 
00988 static HostController _controller __attribute__((at(USB_RAM_BASE)));
00989 
00990 extern "C" void USB_IRQHandler(void) __irq;
00991 void USB_IRQHandler (void) __irq
00992 {
00993     u32 int_status = LPC_USB->HcInterruptStatus; //Indicates the status on various events that cause
00994                                                  //hardware interrupts by setting the appropriate bits.
00995 
00996     if (int_status & RootHubStatusChange)    //    Root hub status change
00997         _controller._rootHubStatusChange++;    //    Just flag the controller, will be processed in USBLoop
00998 
00999     u32 head = 0;
01000     if (int_status & WritebackDoneHead)
01001     {
01002         head = _controller.CommunicationArea.DoneHead;        // Writeback Done
01003         _controller.CommunicationArea.DoneHead = 0;
01004     }             
01005     LPC_USB->HcInterruptStatus = int_status;
01006 
01007     if (head)
01008        _controller.ProcessDoneQueue(head);     // TODO - low bit can be set BUGBUG
01009 }
01010 
01011 //====================================================================================
01012 //====================================================================================
01013 //      API Methods
01014 
01015 void USBInit()
01016 {
01017     return _controller.Init();
01018 }
01019 
01020 void USBLoop()
01021 {
01022     return _controller.Loop();
01023 }
01024 
01025 u8* USBGetBuffer(u32* len)
01026 {
01027     *len = USB_RAM_SIZE - sizeof(HostController);
01028     return _controller.SRAM;
01029 }
01030 
01031 
01032 static Setup* GetSetup(int device)
01033 {
01034     if (device == 0)
01035         return &_controller._setupZero;
01036     
01037     if (device < 1 || device > MAX_DEVICES)
01038         return 0;
01039     return &_controller.Devices[device-1].SetupBuffer;
01040 }
01041 
01042 //    Loop until IO on endpoint is complete
01043 static int WaitIODone(Endpoint* endpoint)
01044 {
01045     if (endpoint->CurrentState == Endpoint::NotQueued)
01046         return 0;
01047     while (endpoint->CurrentState != Endpoint::Idle)
01048         USBLoop();    // May generate callbacks, mount or unmount devices etc
01049     int status = endpoint->Status();
01050     if (status == 0)
01051         return endpoint->Length;
01052     return -status;
01053 }
01054 
01055 int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData)
01056 {
01057     Endpoint* endpoint = _controller.GetEndpoint(device,ep);
01058     if (!endpoint)
01059         return ERR_ENDPOINT_NOT_FOUND;
01060         
01061     WaitIODone(endpoint);
01062     endpoint->Flags = flags;
01063     endpoint->Data = data;
01064     endpoint->Length = length;
01065     endpoint->Callback = callback;
01066     endpoint->UserData = userData;
01067     if (ep == 0)
01068         _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued);
01069     else
01070         _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued);
01071     if (callback)
01072         return IO_PENDING;
01073     return WaitIODone(endpoint);
01074 }
01075 
01076 int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData)
01077 {
01078 
01079   
01080     Setup* setup = GetSetup(device);
01081     if (!setup)
01082         return ERR_DEVICE_NOT_FOUND;
01083         
01084     // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call
01085     WaitIODone(_controller.GetEndpoint(device,0));
01086     
01087     setup->bm_request_type = request_type;
01088     setup->b_request = request;
01089     setup->w_value = value;
01090     setup->w_index = index;
01091     setup->w_length = length;
01092     
01093     
01094     #ifdef USBLOG
01095       LOG("USBControlTransfer\n");
01096      LOG("bm_request_type\t %02x h", request_type);
01097      LOG( "\t %d%d%d%d%d%d%d%d b \t", (((request_type)&(128))>>7), (((request_type)&(64))>>6), ((request_type)&(32))>>5, ((request_type)&(16))>>4,((request_type)&(8))>>2,((request_type)&(4))>>1,((request_type)&(2) )>>1, (request_type)&(1) );
01098      if( request_type &1) LOG(" -> device-to-host");
01099      if(!( request_type & 1)) LOG(" -> host-to-device");
01100      LOG("\n");
01101      LOG("b_request\t %02x h  ",request);
01102      /* USB2.0 specs: table 9.4:
01103 GET_STATUS 0
01104 CLEAR_FEATURE 1
01105 Reserved for future use 2
01106 SET_FEATURE 3
01107 Reserved for future use 4
01108 SET_ADDRESS 5
01109 GET_DESCRIPTOR 6
01110 SET_DESCRIPTOR 7
01111 GET_CONFIGURATION 8
01112 SET_CONFIGURATION 9
01113 GET_INTERFACE 10
01114 SET_INTERFACE 11
01115 SYNCH_FRAME 12
01116      */
01117      LOG("\t");
01118      switch (request)
01119      {
01120         case (0) :{ LOG("GET_STATUS"); break; }
01121          case (1) :{ LOG("CLEAR_FEATURE"); break; }
01122          case (2) :{ LOG("reseved"); break; }
01123         case (3) :{ LOG("SET_FEATURE"); break; }
01124         case (6): { LOG("GET_DESCRIPTOR"); break; }
01125        case (5) :{ LOG("SET_ADDRESS"); break; }
01126        case (7): { LOG("SET_DESCRIPTOR"); break; }
01127       case (8) :{ LOG("GET_CONFIGURATION"); break; }
01128       case (9): { LOG("SET_CONFIGURATION"); break; }
01129       case (10): { LOG("GET_INTERFACE"); break; }
01130        case (11) :{ LOG("SET_INTERFACE"); break; }
01131         case (12): { LOG("SYNCH_FRAEM"); break; }
01132       
01133       }//end switch (reques)
01134      LOG("\n");
01135      LOG("w_value \t %04x h\t  ",value);
01136      /*
01137      Descriptor Types Value
01138 DEVICE 1
01139 CONFIGURATION 2
01140 STRING 3
01141 INTERFACE 4
01142 ENDPOINT 5
01143 DEVICE_QUALIFIER 6
01144 OTHER_SPEED_CONFIGURATION 7
01145 INTERFACE_POWER1 8
01146      */
01147      u8* pv=(u8*)&value;
01148      pv=pv+1;
01149      switch (request)
01150      {
01151          case (GET_DESCRIPTOR):
01152          {
01153            switch (*pv)
01154            {
01155            case(1): { LOG(" -> DEVICE"); break; } 
01156             case(2): { LOG(" -> CONFIGURATION"); break;}
01157             case(3): { LOG(" -> STRING"); break;}
01158             case( 4): { LOG(" -> INTERFACE"); break;}
01159             case(5): { LOG(" -> ENDPOINT"); break;}
01160             case( 6): { LOG(" -> DEVICE_QUALIFIER"); break;}
01161             case( 7): { LOG(" -> OTHER SPEED_CONFIGURATION"); break;}
01162              case (8) :{ LOG("SET_INTERFACE"); break; }
01163              default: {LOG("->%x",*pv);} ;
01164             }//end switch(value)
01165             break;
01166           }//end case 6
01167          
01168           case(SET_ADDRESS):
01169           {
01170            LOG("<-this value is the new adress"); break;
01171           }//end case set address.
01172            
01173          default :
01174          { LOG("."); break;
01175          }
01176      }
01177      LOG("\n");
01178      LOG("w_index = %04x h = %2d d \n",index, index);
01179      LOG("w_length = %04x h = %2d d ",length, length); 
01180      if (request==6) LOG(" -> this should be the descriptor/answer length");
01181      LOG("\n");
01182     #endif
01183     
01184     return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData);
01185 }
01186 
01187 int  USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
01188 {
01189     LOG("USBinterruptTransfer\n");
01190     return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData);
01191 }
01192 
01193 int  USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
01194 {
01195     LOG("USBBulkTransfer\n");
01196     return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData);
01197 }
01198 
01199 int GetDescriptor(int device, int descType,int descIndex, u8* data, int length)
01200 {    
01201     return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0);
01202 }
01203 
01204 int GetString(int device, int index, char* dst, int length)
01205 {
01206     u8 buffer[255];
01207     int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer));
01208     if (le < 0)
01209         return le;
01210     if (length < 1)
01211         return -1;
01212     length <<= 1;
01213     if (le > length)
01214         le = length;
01215     for (int j = 2; j < le; j += 2)
01216         *dst++ = buffer[j];
01217     *dst = 0;
01218     return (le>>1)-1;
01219 }
01220 
01221 int SetAddress(int device, int new_addr)
01222 {
01223     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0);
01224 }
01225 
01226 int SetConfiguration(int device, int configNum)
01227 {
01228     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0);
01229 }
01230 
01231 int SetInterface(int device, int ifNum, int altNum)
01232 {
01233     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0);
01234 }
01235 
01236 //    HUB stuff
01237 int SetPortFeature(int device, int feature, int index)
01238 {
01239     return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0);
01240 }
01241 
01242 int ClearPortFeature(int device, int feature, int index)
01243 {
01244     return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0);
01245 }
01246 
01247 int SetPortPower(int device, int port)
01248 {
01249     int r = SetPortFeature(device,PORT_POWER,port);
01250     _controller.DelayMS(20);    // 80ms to turn on a hubs power... DESCRIPTOR? todo
01251     return r;
01252 }
01253 
01254 int SetPortReset(int device, int port)
01255 {
01256     return SetPortFeature(device,PORT_RESET,port);
01257 }
01258 
01259 int GetPortStatus(int device, int port, u32* status)
01260 {
01261     return USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,GET_STATUS,0,port,(u8*)status,4);
01262 }