BlackOneとAndroidの連携デモプログラム AndroidAccessoryを改造してBlackOneとAndroidが連携できるようにしました。 サポートしているのは、デモアプリの ”Buttons” B1-SW1, B2-SW2, B3-SW3 ”LED2” RGB-LED のみです。 LCDに表示するイメージをマイクロSDカードに入れてLCDのソケットに挿入しておく必要があります。 イメージは、320X240ドットで”\Image”という名前のフォルダの直下に”10.jpg”という名前で入れてください。

Dependencies:   TextLCD mbed

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 
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\r\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\r\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\r\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\r\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next);
00476         //LOG("%04X ED %08X %08X %08X\r\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     { 
00565         HCTD *result = NULL,*temp; 
00566         while (current) 
00567         { 
00568             temp = (HCTD*)current->Next; 
00569             current->Next = (u32)result;
00570             result = current;
00571             current = temp;
00572         }
00573         return result;
00574     }
00575 
00576     //      Called from interrupt...
00577     //      Control endpoints use a state machine to progress through the transfers
00578     void ProcessDoneQueue(u32 tdList)
00579     {
00580         HCTD* list = Reverse((HCTD*)tdList);
00581         while (list)
00582         {
00583             Endpoint* endpoint = (Endpoint*)(list-1);
00584             list = (HCTD*)list->Next;
00585             int ep = endpoint->Address();
00586             bool in = endpoint->Flags & 0x80;
00587             int status = (endpoint->TDHead.Control >> 28) & 0xF;
00588 
00589             //LOG("ProcessDoneQueue %02X %08X\r\n",ep,endpoint->TDHead.Control);
00590 
00591             if (status != 0)
00592             {
00593                 //LOG("ProcessDoneQueue status %02X %d\r\n",ep,status);
00594                 endpoint->CurrentState = Endpoint::Idle;
00595             } else {
00596                 switch (endpoint->CurrentState)
00597                 {
00598                     case Endpoint::SetupQueued:
00599                         if (endpoint->Length == 0)
00600                             Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Skip Data Phase
00601                         else
00602                             Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued);    // Setup is done, now Data
00603                         break;
00604 
00605                     case Endpoint::DataQueued:
00606                         if (endpoint->TDHead.CurrBufPtr)
00607                             endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data;
00608 
00609                         if (ep == 0)
00610                             Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued);    // Data is done, now Status, Control only
00611                         else
00612                             endpoint->CurrentState = Endpoint::Idle;
00613                         break;
00614 
00615                     case Endpoint::StatusQueued:    // Transaction is done
00616                         endpoint->CurrentState = Endpoint::Idle;
00617                         break;
00618                 }
00619             }
00620 
00621             //      Complete, flag if we need a callback
00622             if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle)
00623             {
00624                 endpoint->CurrentState = Endpoint::CallbackPending;
00625                 _callbacksPending++;
00626             }
00627         }
00628     }
00629 
00630     //    Hack to reset devices that don't want to connect
00631     int AddDevice(int hub, int port, bool isLowSpeed)
00632     {
00633         int device = AddDeviceCore(hub,port,isLowSpeed);
00634         if (device < 0)
00635         {
00636             LOG("========RETRY ADD DEVICE========\r\n");    // This will go for ever.. TODO power cycle root?
00637             Disconnect(hub,port);    // Could not read descriptor at assigned address, reset this port and try again
00638             ResetPort(hub,port);    // Cheap bluetooth dongles often need this on a hotplug
00639             return -1;
00640         }
00641         return device;
00642     }
00643 
00644     int AddDeviceCore(int hub, int port, bool isLowSpeed)
00645     {
00646         int lowSpeed = isLowSpeed ? 0x2000 : 0;
00647         DeviceDescriptor desc;
00648         EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed;               // MaxPacketSize == 8
00649         int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8);
00650         if (r < 0)
00651         {
00652             LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\r\n");
00653             return r;
00654         }
00655 
00656         EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed;     // Actual MaxPacketSize
00657         r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
00658         if (r < 0)
00659             return r;
00660 
00661         LOG("\nClass %02X found %04X:%04X\r\n",desc.bDeviceClass,desc.idVendor,desc.idProduct);
00662 
00663         //      Now assign the device an address, move off EndpointZero
00664         int device = 0;
00665         for (int i = 0; i < MAX_DEVICES; i++)
00666         {
00667             if (Devices[i].Port == 0)
00668             {
00669                 device = i+1;
00670                 break;
00671             }
00672         }
00673         if (!device)
00674             return ERR_DEVICE_NONE_LEFT;
00675 
00676         r = SetAddress(0,device);
00677         if (r)
00678             return r;
00679         DelayMS(2);
00680         
00681         // Now at a nonzero address, create control endpoint
00682         Device* dev = &Devices[device-1];
00683         dev->Init(&desc,hub,port,device,lowSpeed);
00684         AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0);
00685         _connectPending = 0;
00686 
00687         //    Verify this all works
00688         r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc));
00689         if (r < 0)
00690             return r;
00691 
00692         //    Set to interface 0 by default
00693         //    Calls LoadDevice if interface is found
00694         r = SetConfigurationAndInterface(device,1,0,&desc);
00695 
00696         if (desc.bDeviceClass == CLASS_HUB)
00697             InitHub(device);            // Handle hubs in this code
00698 
00699         return device;
00700     }
00701 
00702     // Walk descriptors and create endpoints for a given device
00703     // TODO configuration !=1, alternate settings etc.
00704     int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc)
00705     {
00706         u8 buffer[255];
00707         int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,sizeof(buffer));
00708         if (err < 0)
00709             return err;
00710 
00711         err = SetConfiguration(device,configuration);
00712         if (err < 0)
00713             return err;
00714 
00715         //    Add the endpoints for this interface
00716         int len = buffer[2] | (buffer[3] << 8);
00717         u8* d = buffer;
00718         u8* end = d + len;
00719         InterfaceDescriptor* found = 0;
00720         while (d < end)
00721         {
00722             if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
00723             {
00724                 InterfaceDescriptor* id = (InterfaceDescriptor*)d;
00725                 if (id->bInterfaceNumber == interfaceNumber)
00726                 {
00727                     found = id;
00728                     d += d[0];
00729                     while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE)
00730                     {
00731                         switch (d[1])
00732                         {
00733                             case DESCRIPTOR_TYPE_ENDPOINT:
00734                                 AddEndpoint(device,(EndpointDescriptor*)d);
00735                                 break;
00736                             default:
00737                                 LOG("Skipping descriptor %02X (%d bytes)\r\n",d[1],d[0]);
00738                         }
00739                         d += d[0];
00740                     }
00741                 }
00742             }
00743             d += d[0];
00744         }
00745 
00746         if (!found)
00747             return ERR_INTERFACE_NOT_FOUND;
00748         OnLoadDevice(device,desc,found);
00749         return 0;
00750     }
00751 
00752     void Init()
00753     {
00754         LOG("USB INIT (Controller is %d bytes)\r\n",sizeof(*this));
00755         memset(this,0,sizeof(HostController));
00756         EndpointZero.CurrentState = Endpoint::NotQueued;
00757         HWInit(&CommunicationArea);
00758         DelayMS(10);
00759     }
00760 
00761     void ResetPort(int hub, int port)
00762     {        
00763         LOG("ResetPort Hub:%d Port:%d\r\n",hub,port);
00764         _connectPending++;            // Only reset/add 1 device at a time
00765         if (hub == 0)
00766             LPC_USB->HcRhPortStatus1 = PortResetStatus;    // Reset Root Hub, port 1
00767         else
00768             SetPortReset(hub,port);    // or reset other hub
00769     }
00770 
00771     void Disconnect(int hub, int port)
00772     {
00773         LOG("Disconnect Hub:%d Port:%d\r\n",hub,port);    // Mark a device for destruction
00774         for (int i = 0; i < MAX_DEVICES; i++)
00775         {
00776             Device* dev = Devices + i;
00777             if (dev->Port == port && dev->Hub == hub)
00778             {
00779                 //    Disconnect everything that is attached to this device if it is a hub
00780                 for (int p = 0; p < dev->HubPortCount; p++)
00781                     Disconnect(i+1,p+1);
00782 
00783                 //    Now release endpoints
00784                 for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2)
00785                 {
00786                     u8 endpointIndex = dev->_endpointMap[j];
00787                     if (endpointIndex != 0xFF)
00788                         Release(Endpoints + endpointIndex);
00789                 }
00790                 dev->Port = 0;    // Device is now free
00791                 dev->Flags = 0;
00792                 return;
00793             }
00794         }
00795     }
00796 
00797     // called after reset
00798     void Connect(int hub, int port, bool lowspeed)
00799     {
00800         LOG("Connect Hub:%d Port:%d %s\r\n",hub,port,lowspeed ? "slow" : "full");
00801         AddDevice(hub,port,lowspeed);
00802     }
00803 
00804     // Called from interrupt
00805     void HubStatusChange(int hub, int port, u32 status)
00806     {
00807         LOG("HubStatusChange Hub:%d Port:%d %08X\r\n",hub,port,status);
00808         if (status & ConnectStatusChange)
00809         {
00810             if (status & CurrentConnectStatus)    // Connecting
00811                 ResetPort(hub,port);            // Reset to initiate connect (state machine?)
00812             else
00813                 Disconnect(hub,port);
00814         }
00815 
00816         if (status & PortResetStatusChange)
00817         {
00818             if (!(status & PortResetStatus))
00819             {
00820                 _connectCountdown = 200;        // Schedule a connection in 200ms
00821                 if (status & LowspeedDevice)
00822                     port |= 0x80;
00823                 _connectHub = hub;
00824                 _connectPort = port;
00825             }
00826         }
00827     }
00828 
00829     #define HOST_CLK_EN        (1<<0)
00830     #define PORTSEL_CLK_EN    (1<<3)
00831     #define AHB_CLK_EN        (1<<4)
00832     #define CLOCK_MASK        (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN)
00833 
00834     #define  FRAMEINTERVAL        (12000-1)    // 1ms
00835     #define  DEFAULT_FMINTERVAL    ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL)
00836 
00837     void DelayMS(int ms)
00838     {
00839         u16 f = ms + CommunicationArea.FrameNumber;
00840         while (f != CommunicationArea.FrameNumber)
00841             ;
00842     }
00843 
00844     static void HWInit(HCCA* cca)
00845     {
00846         NVIC_DisableIRQ(USB_IRQn);
00847         
00848         // turn on power for USB
00849         LPC_SC->PCONP        |= (1UL<<31);
00850         // Enable USB host clock, port selection and AHB clock
00851         LPC_USB->USBClkCtrl |= CLOCK_MASK;
00852         // Wait for clocks to become available
00853         while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK)
00854             ;
00855         
00856         //    We are a Host
00857         LPC_USB->OTGStCtrl |= 1;
00858         LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN;                // we don't need port selection clock until we do OTG
00859         
00860         // configure USB pins
00861         LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28));    
00862         LPC_PINCON->PINSEL1 |=    ((1<<26)|(1<<28));            // USB D+/D-
00863             
00864         LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22));        // USB_PPWR, USB_OVRCR
00865         LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22));
00866         
00867         LPC_PINCON->PINSEL4 &= ~(3 << 18);                    // USB_CONNECT
00868         LPC_PINCON->PINSEL4 |= (1 << 18);
00869 
00870         //    Reset OHCI block
00871         LPC_USB->HcControl         = 0;
00872         LPC_USB->HcControlHeadED = 0;
00873         LPC_USB->HcBulkHeadED     = 0;
00874         
00875         LPC_USB->HcCommandStatus = HostControllerReset;
00876         LPC_USB->HcFmInterval     = DEFAULT_FMINTERVAL;
00877         LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100;
00878 
00879         LPC_USB->HcControl    = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask;
00880         LPC_USB->HcRhStatus = SetGlobalPower;
00881         
00882         LPC_USB->HcHCCA = (u32)cca;
00883         LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus;
00884         LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow;
00885 
00886         NVIC_SetPriority(USB_IRQn, 0);
00887         NVIC_EnableIRQ(USB_IRQn);
00888         while (cca->FrameNumber < 10)
00889             ;    // 10ms delay before diving in
00890     }
00891 };
00892 
00893 //====================================================================================
00894 //====================================================================================
00895 //      Host controller instance and Interrupt handler
00896 
00897 static HostController _controller __attribute__((at(USB_RAM_BASE)));
00898 
00899 extern "C" void USB_IRQHandler(void) __irq;
00900 void USB_IRQHandler (void) __irq
00901 {
00902     u32 int_status = LPC_USB->HcInterruptStatus;
00903 
00904     if(int_status & UnrecoverableError) //Error
00905     {
00906       LOG("USB_IRQHandler UnrecoverableError Please reset\r\n");
00907     }
00908 
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);     // TODO - low bit can be set BUGBUG
00923 }
00924 
00925 //====================================================================================
00926 //====================================================================================
00927 //      API Methods
00928 
00929 void USBInit()
00930 {
00931     return _controller.Init();
00932 }
00933 
00934 void USBLoop()
00935 {
00936     return _controller.Loop();
00937 }
00938 
00939 u8* USBGetBuffer(u32* len)
00940 {
00941     *len = USB_RAM_SIZE - sizeof(HostController);
00942     return _controller.SRAM;
00943 }
00944 
00945 static Setup* GetSetup(int device)
00946 {
00947     if (device == 0)
00948         return &_controller._setupZero;
00949     
00950     if (device < 1 || device > MAX_DEVICES)
00951         return 0;
00952     return &_controller.Devices[device-1].SetupBuffer;
00953 }
00954 
00955 //    Loop until IO on endpoint is complete
00956 static int WaitIODone(Endpoint* endpoint)
00957 {
00958     if (endpoint->CurrentState == Endpoint::NotQueued)
00959         return 0;
00960     while (endpoint->CurrentState != Endpoint::Idle)
00961         USBLoop();    // May generate callbacks, mount or unmount devices etc
00962     int status = endpoint->Status();
00963     if (status == 0)
00964         return endpoint->Length;
00965     return -status;
00966 }
00967 
00968 int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData)
00969 {
00970     Endpoint* endpoint = _controller.GetEndpoint(device,ep);
00971     if (!endpoint)
00972         return ERR_ENDPOINT_NOT_FOUND;
00973         
00974     WaitIODone(endpoint);
00975     endpoint->Flags = flags;
00976     endpoint->Data = data;
00977     endpoint->Length = length;
00978     endpoint->Callback = callback;
00979     endpoint->UserData = userData;
00980     if (ep == 0)
00981         _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued);
00982     else
00983         _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued);
00984     if (callback)
00985         return IO_PENDING;
00986     return WaitIODone(endpoint);
00987 }
00988 
00989 int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData)
00990 {
00991     Setup* setup = GetSetup(device);
00992     if (!setup)
00993         return ERR_DEVICE_NOT_FOUND;
00994         
00995     // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call
00996     WaitIODone(_controller.GetEndpoint(device,0));
00997     
00998     setup->bm_request_type = request_type;
00999     setup->b_request = request;
01000     setup->w_value = value;
01001     setup->w_index = index;
01002     setup->w_length = length;
01003     return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData);
01004 }
01005 
01006 int  USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
01007 {
01008     return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData);
01009 }
01010 
01011 int  USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData)
01012 {
01013     return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData);
01014 }
01015 
01016 int GetDescriptor(int device, int descType,int descIndex, u8* data, int length)
01017 {
01018     return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0);
01019 }
01020 
01021 int GetString(int device, int index, char* dst, int length)
01022 {
01023     u8 buffer[255];
01024     int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer));
01025     if (le < 0)
01026         return le;
01027     if (length < 1)
01028         return -1;
01029     length <<= 1;
01030     if (le > length)
01031         le = length;
01032     for (int j = 2; j < le; j += 2)
01033         *dst++ = buffer[j];
01034     *dst = 0;
01035     return (le>>1)-1;
01036 }
01037 
01038 int SetAddress(int device, int new_addr)
01039 {
01040     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0);
01041 }
01042 
01043 int SetConfiguration(int device, int configNum)
01044 {
01045     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0);
01046 }
01047 
01048 int SetInterface(int device, int ifNum, int altNum)
01049 {
01050     return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0);
01051 }
01052 
01053 //    HUB stuff
01054 int SetPortFeature(int device, int feature, int index)
01055 {
01056     return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0);
01057 }
01058 
01059 int ClearPortFeature(int device, int feature, int index)
01060 {
01061     return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0);
01062 }
01063 
01064 int SetPortPower(int device, int port)
01065 {
01066     int r = SetPortFeature(device,PORT_POWER,port);
01067     _controller.DelayMS(20);    // 80ms to turn on a hubs power... DESCRIPTOR? todo
01068     return r;
01069 }
01070 
01071 int SetPortReset(int device, int port)
01072 {
01073     return SetPortFeature(device,PORT_RESET,port);
01074 }
01075 
01076 int GetPortStatus(int device, int port, u32* status)
01077 {
01078     return USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,GET_STATUS,0,port,(u8*)status,4);
01079 }