local fix version of myBlueUSB (http://mbed.org/users/networker/code/myBlueUSB/). - merge deleted files which are required to compile. - enable echo back of received data via RFCOMM.

Dependencies:   AvailableMemory FatFileSystem mbed myUSBHost

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBHost.cpp Source File

USBHost.cpp

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