The modified AndroidAccessory Library
Dependents: ADKTerm droidcycle uva_nc androidservo ... more
USBHost_log.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 00025 #include "mbed.h" 00026 #include "USBHost.h" 00027 //#define USBHOST_LOG 00028 #ifdef USBHOST_LOG 00029 00030 // Config (default uses x bytes) 00031 #define MAX_DEVICES 8 // Max number of devices 00032 #define MAX_ENDPOINTS_TOTAL 16 // Max number of endpoints total 00033 #define MAX_ENDPOINTS_PER_DEVICE 8 // Max number of endpoints for any one device 00034 00035 //#define USBLOG 1 00036 #if USBLOG 00037 #define LOG(...) printf(__VA_ARGS__) 00038 #else 00039 #define LOG(...) do {} while(0) 00040 #endif 00041 00042 // USB host structures 00043 00044 #define USB_RAM_SIZE 16*1024 // AHB SRAM block 1 TODO MACHINE DEPENDENT 00045 #define USB_RAM_BASE 0x2007C000 00046 00047 #define TOKEN_SETUP 0 00048 #define TOKEN_IN 1 00049 #define TOKEN_OUT 2 00050 00051 // Status flags from hub 00052 #define PORT_CONNECTION 0 00053 #define PORT_ENABLE 1 00054 #define PORT_SUSPEND 2 00055 #define PORT_OVER_CURRENT 3 00056 #define PORT_RESET 4 00057 #define PORT_POWER 8 00058 #define PORT_LOW_SPEED 9 00059 00060 #define C_PORT_CONNECTION 16 00061 #define C_PORT_ENABLE 17 00062 #define C_PORT_SUSPEND 18 00063 #define C_PORT_OVER_CURRENT 19 00064 #define C_PORT_RESET 20 00065 00066 typedef struct { 00067 u8 bm_request_type; 00068 u8 b_request; 00069 u16 w_value; 00070 u16 w_index; 00071 u16 w_length; 00072 } Setup; 00073 00074 00075 // Hub stuff is kept private just to keep api simple 00076 int SetPortFeature(int device, int feature, int index); 00077 int ClearPortFeature(int device, int feature, int index); 00078 int SetPortPower(int device, int port); 00079 int SetPortReset(int device, int port); 00080 int GetPortStatus(int device, int port, u32* status); 00081 00082 //=================================================================== 00083 //=================================================================== 00084 // Hardware defines 00085 00086 // HcControl 00087 #define PeriodicListEnable 0x00000004 00088 #define IsochronousEnable 0x00000008 00089 #define ControlListEnable 0x00000010 00090 #define BulkListEnable 0x00000020 00091 #define OperationalMask 0x00000080 00092 #define HostControllerFunctionalState 0x000000C0 00093 00094 // HcCommandStatus 00095 #define HostControllerReset 0x00000001 00096 #define ControlListFilled 0x00000002 00097 #define BulkListFilled 0x00000004 00098 00099 // HcInterruptStatus Register 00100 #define WritebackDoneHead 0x00000002 00101 #define StartofFrame 0x00000004 00102 #define ResumeDetected 0x00000008 00103 #define UnrecoverableError 0x00000010 00104 #define FrameNumberOverflow 0x00000020 00105 #define RootHubStatusChange 0x00000040 00106 #define OwnershipChange 0x00000080 00107 #define MasterInterruptEnable 0x80000000 00108 00109 // HcRhStatus 00110 #define SetGlobalPower 0x00010000 00111 #define DeviceRemoteWakeupEnable 0x00008000 00112 00113 // HcRhPortStatus (hub 0, port 1) 00114 #define CurrentConnectStatus 0x00000001 00115 #define PortEnableStatus 0x00000002 00116 #define PortSuspendStatus 0x00000004 00117 #define PortOverCurrentIndicator 0x00000008 00118 #define PortResetStatus 0x00000010 00119 00120 #define PortPowerStatus 0x00000100 00121 #define LowspeedDevice 0x00000200 00122 #define HighspeedDevice 0x00000400 00123 00124 #define ConnectStatusChange (CurrentConnectStatus << 16) 00125 #define PortResetStatusChange (PortResetStatus << 16) 00126 00127 00128 #define TD_ROUNDING (u32)0x00040000 00129 #define TD_SETUP (u32)0x00000000 00130 #define TD_IN (u32)0x00100000 00131 #define TD_OUT (u32)0x00080000 00132 #define TD_DELAY_INT(x) (u32)((x) << 21) 00133 #define TD_TOGGLE_0 (u32)0x02000000 00134 #define TD_TOGGLE_1 (u32)0x03000000 00135 #define TD_CC (u32)0xF0000000 00136 00137 // HostController EndPoint Descriptor 00138 typedef struct { 00139 volatile u32 Control; 00140 volatile u32 TailTd; 00141 volatile u32 HeadTd; 00142 volatile u32 Next; 00143 } HCED; 00144 00145 // HostController Transfer Descriptor 00146 typedef struct { 00147 volatile u32 Control; 00148 volatile u32 CurrBufPtr; 00149 volatile u32 Next; 00150 volatile u32 BufEnd; 00151 } HCTD; 00152 00153 // Host Controller Communication Area 00154 typedef struct { 00155 volatile u32 InterruptTable[32]; 00156 volatile u16 FrameNumber; 00157 volatile u16 FrameNumberPad; 00158 volatile u32 DoneHead; 00159 volatile u8 Reserved[120]; 00160 } HCCA; 00161 00162 //==================================================================================== 00163 //==================================================================================== 00164 00165 class HostController; 00166 class Endpoint; 00167 class Device; 00168 00169 // must be 3*16 bytes long 00170 class Endpoint 00171 { 00172 public: 00173 HCED EndpointDescriptor; // Pointer to EndpointDescriptor == Pointer to Endpoint 00174 HCTD TDHead; 00175 00176 enum State 00177 { 00178 Free, 00179 NotQueued, 00180 Idle, 00181 SetupQueued, 00182 DataQueued, 00183 StatusQueued, 00184 CallbackPending 00185 }; 00186 00187 volatile u8 CurrentState; 00188 u8 Flags; // 0x80 In, 0x03 mask endpoint type 00189 00190 u16 Length; 00191 u8* Data; 00192 USBCallback Callback; // Must be a multiple of 16 bytes long 00193 void* UserData; 00194 00195 int Address() 00196 { 00197 int ep = (EndpointDescriptor.Control >> 7) & 0xF; 00198 if (ep) 00199 ep |= Flags & 0x80; 00200 return ep; 00201 } 00202 00203 int Device() 00204 { 00205 return EndpointDescriptor.Control & 0x7F; 00206 } 00207 00208 int Status() 00209 { 00210 return (TDHead.Control >> 28) & 0xF; 00211 } 00212 00213 u32 Enqueue(u32 head) 00214 { 00215 if (CurrentState == NotQueued) 00216 { 00217 EndpointDescriptor.Next = head; 00218 head = (u32)&EndpointDescriptor; 00219 CurrentState = Idle; 00220 } 00221 return head; 00222 } 00223 }; 00224 00225 class Device 00226 { 00227 public: 00228 u8 _endpointMap[MAX_ENDPOINTS_PER_DEVICE*2]; 00229 u8 Hub; 00230 u8 Port; 00231 u8 Addr; 00232 u8 Pad; 00233 00234 // Only if this device is a hub 00235 u8 HubPortCount; // nonzero if this is a hub 00236 u8 HubInterruptData; 00237 u8 HubMap; 00238 u8 HubMask; 00239 00240 int Flags; // 1 = Disconnected 00241 00242 Setup SetupBuffer; 00243 00244 // Allocate endpoint zero 00245 int Init(DeviceDescriptor* d, int hub, int port, int addr, int lowSpeed) 00246 { 00247 Hub = hub; 00248 Port = port; 00249 Addr = addr; 00250 Flags = lowSpeed; 00251 memset(_endpointMap,0xFF,sizeof(_endpointMap)); 00252 return 0; 00253 } 00254 00255 int SetEndpointIndex(int ep, int endpointIndex) 00256 { 00257 for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2) 00258 { 00259 if (_endpointMap[i] == 0xFF) // Add endpoint to map 00260 { 00261 _endpointMap[i] = ep; 00262 _endpointMap[i+1] = endpointIndex; 00263 return 0; 00264 } 00265 } 00266 return ERR_ENDPOINT_NONE_LEFT; 00267 } 00268 00269 int GetEndpointIndex(int ep) 00270 { 00271 for (int i = 0; i < MAX_ENDPOINTS_PER_DEVICE*2; i += 2) 00272 { 00273 if (_endpointMap[i] == ep) 00274 return _endpointMap[i+1]; 00275 if (_endpointMap[i] == 0xFF) 00276 break; 00277 } 00278 return -1; 00279 } 00280 }; 00281 00282 class HostController 00283 { 00284 public: 00285 HCCA CommunicationArea; 00286 Endpoint Endpoints[MAX_ENDPOINTS_TOTAL]; // Multiple of 16 00287 00288 Endpoint EndpointZero; // For device enumeration 00289 HCTD _commonTail; 00290 Setup _setupZero; 00291 00292 Device Devices[MAX_DEVICES]; 00293 u32 _frameNumber; // 32 bit ms counter 00294 00295 u8 _callbacksPending; // Endpoints with callbacks are pending, set from ISR via ProcessDoneQueue 00296 u8 _rootHubStatusChange; // Root hub status has changed, set from ISR 00297 u8 _unused0; 00298 u8 _unused1; 00299 00300 u8 _connectPending; // Reset has initiated a connect 00301 u8 _connectCountdown; // Number of ms left after reset before we can connect 00302 u8 _connectHub; // Will connect on this hub 00303 u8 _connectPort; // ... and this port 00304 00305 u8 SRAM[0]; // Start of free SRAM 00306 00307 void Loop() 00308 { 00309 // printf("Enter Loop \r\n"); 00310 u16 elapsed = CommunicationArea.FrameNumber - (u16)_frameNumber; // extend to 32 bits 00311 _frameNumber += elapsed; 00312 00313 // Do callbacks, if any 00314 while (_callbacksPending) 00315 { 00316 for (int i = 0; i < MAX_ENDPOINTS_TOTAL; i++) 00317 { 00318 Endpoint* endpoint = Endpoints + i; 00319 if (endpoint->CurrentState == Endpoint::CallbackPending) 00320 { 00321 _callbacksPending--; 00322 endpoint->CurrentState = Endpoint::Idle; 00323 LOG("CurrentState Change Idle endpoint(%d) currentState =%d\r\n",endpoint->Address(),endpoint->CurrentState); 00324 endpoint->Callback(endpoint->Device(),endpoint->Address(),endpoint->Status(),endpoint->Data,endpoint->Length,endpoint->UserData); 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 // Connect after reset timeout 00342 if (_connectCountdown) 00343 { 00344 if (elapsed >= _connectCountdown) 00345 { 00346 _connectCountdown = 0; 00347 Connect(_connectHub,_connectPort & 0x7F,_connectPort & 0x80); 00348 } else 00349 _connectCountdown -= elapsed; 00350 } 00351 00352 // printf("Outer Loop \r\n"); 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\r\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\r\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 //Makoto edit comment out 00460 // LOG("Transfer start\r\n"); 00461 LOG("Transfer ep=%02X Token:%d Len:%d State:%d\r\n",endpoint->Address(),token,len,state); 00462 00463 int toggle = 0; 00464 if (endpoint->Address() == 0) 00465 toggle = (token == TOKEN_SETUP) ? TD_TOGGLE_0 : TD_TOGGLE_1; 00466 00467 if (token != TOKEN_SETUP) 00468 token = (token == TOKEN_IN ? TD_IN : TD_OUT); 00469 00470 HCTD* head = &endpoint->TDHead; 00471 HCTD* tail = &_commonTail; 00472 00473 head->Control = TD_ROUNDING | token | TD_DELAY_INT(0) | toggle | TD_CC; 00474 head->CurrBufPtr = (u32)data; 00475 head->BufEnd = (u32)(data + len - 1); 00476 head->Next = (u32)tail; 00477 00478 HCED* ed = &endpoint->EndpointDescriptor; 00479 ed->HeadTd = (u32)head | (ed->HeadTd & 0x00000002); // carry toggle 00480 ed->TailTd = (u32)tail; 00481 00482 //HCTD* td = head; 00483 //LOG("%04X TD %08X %08X %08X Next:%08X\r\n",CommunicationArea.FrameNumber,td->Control,td->CurrBufPtr,td->BufEnd,td->Next); 00484 //LOG("%04X ED %08X %08X %08X\r\n",CommunicationArea.FrameNumber,ed->Control,ed->HeadTd,ed->TailTd); 00485 00486 //LOG("Transfer run01\r\n"); 00487 switch (endpoint->Flags & 3) 00488 { 00489 case ENDPOINT_CONTROL: 00490 LOG("Transfer run ENDPOINT_CONTROL\r\n"); 00491 LPC_USB->HcControlHeadED = endpoint->Enqueue(LPC_USB->HcControlHeadED); // May change state NotQueued->Idle 00492 //LOG("Transfer run02\r\n"); 00493 LOG("endpoint->CurrentState change %d->%d\r\n",endpoint->CurrentState,state); 00494 endpoint->CurrentState = state; // Get in before an int 00495 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | ControlListFilled; 00496 LPC_USB->HcControl = LPC_USB->HcControl | ControlListEnable; 00497 00498 break; 00499 00500 case ENDPOINT_BULK: 00501 LOG("Transfer run ENDPOINT_BULK\r\n"); 00502 LPC_USB->HcBulkHeadED = endpoint->Enqueue(LPC_USB->HcBulkHeadED); 00503 LOG("endpoint->CurrentState change %d->%d\r\n",endpoint->CurrentState,state); 00504 endpoint->CurrentState = state; 00505 LPC_USB->HcCommandStatus = LPC_USB->HcCommandStatus | BulkListFilled; 00506 LPC_USB->HcControl = LPC_USB->HcControl | BulkListEnable; 00507 break; 00508 00509 case ENDPOINT_INTERRUPT: 00510 LOG("Transfer run ENDPOINT_INTERRUPT\r\n"); 00511 CommunicationArea.InterruptTable[0] = endpoint->Enqueue(CommunicationArea.InterruptTable[0]); 00512 LOG("endpoint->CurrentState change %d->%d\r\n",endpoint->CurrentState,state); 00513 endpoint->CurrentState = state; 00514 LPC_USB->HcControl |= PeriodicListEnable; 00515 break; 00516 } 00517 00518 LOG("Transfer end\r\n"); 00519 return 0; 00520 } 00521 00522 // Remove an endpoint from an active queue 00523 bool Remove(HCED* ed, volatile HCED** queue) 00524 { 00525 if (*queue == 0) 00526 return false; 00527 if (*queue == (volatile HCED*)ed) 00528 { 00529 *queue = (volatile HCED*)ed->Next; // At head of queue 00530 return true; 00531 } 00532 00533 volatile HCED* head = *queue; 00534 while (head) 00535 { 00536 if (head->Next == (u32)ed) 00537 { 00538 head->Next = ed->Next; 00539 return true; 00540 } 00541 head = (volatile HCED*)head->Next; 00542 } 00543 return false; 00544 } 00545 00546 void Release(Endpoint* endpoint) 00547 { 00548 if (endpoint->CurrentState == Endpoint::NotQueued) 00549 { 00550 // Never event used it, nothing to do 00551 } 00552 else 00553 { 00554 HCED* ed = (HCED*)endpoint; 00555 ed->Control |= 0x4000; // SKIP 00556 switch (endpoint->Flags & 0x03) 00557 { 00558 case ENDPOINT_CONTROL: 00559 Remove(ed,(volatile HCED**)&LPC_USB->HcControlHeadED); 00560 break; 00561 case ENDPOINT_BULK: 00562 Remove(ed,(volatile HCED**)&LPC_USB->HcBulkHeadED); 00563 break; 00564 case ENDPOINT_INTERRUPT: 00565 for (int i = 0; i < 32; i++) 00566 Remove(ed,(volatile HCED**)&CommunicationArea.InterruptTable[i]); 00567 break; 00568 } 00569 00570 u16 fn = CommunicationArea.FrameNumber; 00571 while (fn == CommunicationArea.FrameNumber) 00572 ; // Wait for next frame 00573 00574 } 00575 00576 // In theory, the endpoint is now dead. 00577 // TODO: Will Callbacks ever be pending? BUGBUG 00578 memset(endpoint,0,sizeof(Endpoint)); 00579 } 00580 00581 // Pop the last TD from the list 00582 HCTD* Reverse(HCTD* current) 00583 { 00584 HCTD *result = NULL,*temp; 00585 while (current) 00586 { 00587 temp = (HCTD*)current->Next; 00588 current->Next = (u32)result; 00589 result = current; 00590 current = temp; 00591 } 00592 return result; 00593 } 00594 00595 // Called from interrupt... 00596 // Control endpoints use a state machine to progress through the transfers 00597 void ProcessDoneQueue(u32 tdList) 00598 { 00599 00600 LOG("<<ProcessDoneQueue enter>>\r\n"); 00601 HCTD* list = Reverse((HCTD*)tdList); 00602 while (list) 00603 { 00604 Endpoint* endpoint = (Endpoint*)(list-1); 00605 list = (HCTD*)list->Next; 00606 int ep = endpoint->Address(); 00607 bool in = endpoint->Flags & 0x80; 00608 int status = (endpoint->TDHead.Control >> 28) & 0xF; 00609 00610 //LOG("ProcessDoneQueue %02X %08X\r\n",ep,endpoint->TDHead.Control); 00611 00612 if (status != 0) 00613 { 00614 LOG("ProcessDoneQueue status %02X %d\r\n",ep,status); 00615 LOG("CurrentState Change Idle endpoint(%d) currentState =%d\r\n",endpoint->Address(),endpoint->CurrentState); 00616 endpoint->CurrentState = Endpoint::Idle; 00617 00618 00619 } else { 00620 switch (endpoint->CurrentState) 00621 { 00622 case Endpoint::SetupQueued: 00623 if (endpoint->Length == 0) 00624 { 00625 LOG("ProcessDoneQueue endpoint->Length == 0 endpoint->CurrentState=%d\r\n",endpoint->CurrentState); 00626 Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Skip Data Phase 00627 } 00628 else 00629 { 00630 LOG("ProcessDoneQueue endpoint->Length != 0 endpoint->CurrentState=%d\r\n",endpoint->CurrentState); 00631 Transfer(endpoint,in ? TOKEN_IN : TOKEN_OUT,endpoint->Data,endpoint->Length, Endpoint::DataQueued); // Setup is done, now Data 00632 } 00633 break; 00634 00635 case Endpoint::DataQueued: 00636 if (endpoint->TDHead.CurrBufPtr) 00637 endpoint->Length = endpoint->TDHead.CurrBufPtr - (u32)endpoint->Data; 00638 00639 if (ep == 0) 00640 { 00641 LOG("ProcessDoneQueue ep == 0 endpoint->CurrentState=%d\r\n",endpoint->CurrentState); 00642 Transfer(endpoint,in ? TOKEN_OUT : TOKEN_IN,0,0,Endpoint::StatusQueued); // Data is done, now Status, Control only 00643 } 00644 else 00645 { 00646 00647 LOG("ProcessDoneQueue ep != 0 endpoint->CurrentState=%d\r\n",endpoint->CurrentState); 00648 endpoint->CurrentState = Endpoint::Idle; 00649 LOG("CurrentState Change Idle endpoint(%d) currentState =%d\r\n",endpoint->Address(),endpoint->CurrentState); 00650 } 00651 break; 00652 00653 case Endpoint::StatusQueued: // Transaction is done 00654 LOG("CurrentState Change Idle endpoint(%d) currentState =%d\r\n",endpoint->Address(),endpoint->CurrentState); 00655 endpoint->CurrentState = Endpoint::Idle; 00656 break; 00657 } 00658 } 00659 00660 // Complete, flag if we need a callback 00661 if (endpoint->Callback && endpoint->CurrentState == Endpoint::Idle) 00662 { 00663 endpoint->CurrentState = Endpoint::CallbackPending; 00664 _callbacksPending++; 00665 } 00666 } 00667 LOG("<<ProcessDoneQueue out>>\r\n"); 00668 } 00669 00670 // Hack to reset devices that don't want to connect 00671 int AddDevice(int hub, int port, bool isLowSpeed) 00672 { 00673 int device = AddDeviceCore(hub,port,isLowSpeed); 00674 if (device < 0) 00675 { 00676 LOG("========RETRY ADD DEVICE========\r\n"); // This will go for ever.. TODO power cycle root? 00677 Disconnect(hub,port); // Could not read descriptor at assigned address, reset this port and try again 00678 ResetPort(hub,port); // Cheap bluetooth dongles often need this on a hotplug 00679 return -1; 00680 } 00681 return device; 00682 } 00683 00684 int AddDeviceCore(int hub, int port, bool isLowSpeed) 00685 { 00686 int lowSpeed = isLowSpeed ? 0x2000 : 0; 00687 DeviceDescriptor desc; 00688 EndpointZero.EndpointDescriptor.Control = (8 << 16) | lowSpeed; // MaxPacketSize == 8 00689 int r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,8); 00690 if (r < 0) 00691 { 00692 LOG("FAILED TO LOAD DESCRIPTOR FOR DEVICE 0\r\n"); 00693 return r; 00694 } 00695 00696 EndpointZero.EndpointDescriptor.Control = (desc.bMaxPacketSize << 16) | lowSpeed; // Actual MaxPacketSize 00697 r = GetDescriptor(0,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc)); 00698 if (r < 0) 00699 return r; 00700 00701 LOG("\nClass %02X found %04X:%04X\r\n",desc.bDeviceClass,desc.idVendor,desc.idProduct); 00702 00703 // Now assign the device an address, move off EndpointZero 00704 int device = 0; 00705 for (int i = 0; i < MAX_DEVICES; i++) 00706 { 00707 if (Devices[i].Port == 0) 00708 { 00709 device = i+1; 00710 break; 00711 } 00712 } 00713 if (!device) 00714 return ERR_DEVICE_NONE_LEFT; 00715 00716 r = SetAddress(0,device); 00717 if (r) 00718 return r; 00719 DelayMS(2); 00720 00721 // Now at a nonzero address, create control endpoint 00722 Device* dev = &Devices[device-1]; 00723 dev->Init(&desc,hub,port,device,lowSpeed); 00724 AddEndpoint(device,0,ENDPOINT_CONTROL,desc.bMaxPacketSize,0); 00725 _connectPending = 0; 00726 00727 // Verify this all works 00728 r = GetDescriptor(device,DESCRIPTOR_TYPE_DEVICE,0,(u8*)&desc,sizeof(desc)); 00729 if (r < 0) 00730 return r; 00731 00732 // Set to interface 0 by default 00733 // Calls LoadDevice if interface is found 00734 r = SetConfigurationAndInterface(device,1,0,&desc); 00735 00736 if (desc.bDeviceClass == CLASS_HUB) 00737 InitHub(device); // Handle hubs in this code 00738 00739 return device; 00740 } 00741 00742 // Walk descriptors and create endpoints for a given device 00743 // TODO configuration !=1, alternate settings etc. 00744 int SetConfigurationAndInterface(int device, int configuration, int interfaceNumber, DeviceDescriptor* desc) 00745 { 00746 u8 buffer[255]; 00747 int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,sizeof(buffer)); 00748 if (err < 0) 00749 return err; 00750 00751 err = SetConfiguration(device,configuration); 00752 if (err < 0) 00753 return err; 00754 00755 // Add the endpoints for this interface 00756 int len = buffer[2] | (buffer[3] << 8); 00757 u8* d = buffer; 00758 u8* end = d + len; 00759 InterfaceDescriptor* found = 0; 00760 while (d < end) 00761 { 00762 if (d[1] == DESCRIPTOR_TYPE_INTERFACE) 00763 { 00764 InterfaceDescriptor* id = (InterfaceDescriptor*)d; 00765 if (id->bInterfaceNumber == interfaceNumber) 00766 { 00767 found = id; 00768 d += d[0]; 00769 while (d < end && d[1] != DESCRIPTOR_TYPE_INTERFACE) 00770 { 00771 switch (d[1]) 00772 { 00773 case DESCRIPTOR_TYPE_ENDPOINT: 00774 AddEndpoint(device,(EndpointDescriptor*)d); 00775 break; 00776 default: 00777 LOG("Skipping descriptor %02X (%d bytes)\r\n",d[1],d[0]); 00778 } 00779 d += d[0]; 00780 } 00781 } 00782 } 00783 d += d[0]; 00784 } 00785 00786 if (!found) 00787 return ERR_INTERFACE_NOT_FOUND; 00788 OnLoadDevice(device,desc,found); 00789 return 0; 00790 } 00791 00792 void Init() 00793 { 00794 LOG("USB INIT (Controller is %d bytes)\r\n",sizeof(*this)); 00795 memset(this,0,sizeof(HostController)); 00796 EndpointZero.CurrentState = Endpoint::NotQueued; 00797 HWInit(&CommunicationArea); 00798 DelayMS(10); 00799 } 00800 00801 void ResetPort(int hub, int port) 00802 { 00803 LOG("ResetPort Hub:%d Port:%d\r\n",hub,port); 00804 _connectPending++; // Only reset/add 1 device at a time 00805 if (hub == 0) 00806 LPC_USB->HcRhPortStatus1 = PortResetStatus; // Reset Root Hub, port 1 00807 else 00808 SetPortReset(hub,port); // or reset other hub 00809 } 00810 00811 void Disconnect(int hub, int port) 00812 { 00813 LOG("Disconnect Hub:%d Port:%d\r\n",hub,port); // Mark a device for destruction 00814 for (int i = 0; i < MAX_DEVICES; i++) 00815 { 00816 Device* dev = Devices + i; 00817 if (dev->Port == port && dev->Hub == hub) 00818 { 00819 // Disconnect everything that is attached to this device if it is a hub 00820 for (int p = 0; p < dev->HubPortCount; p++) 00821 Disconnect(i+1,p+1); 00822 00823 // Now release endpoints 00824 for (int j = 1; j < MAX_ENDPOINTS_PER_DEVICE*2; j += 2) 00825 { 00826 u8 endpointIndex = dev->_endpointMap[j]; 00827 if (endpointIndex != 0xFF) 00828 Release(Endpoints + endpointIndex); 00829 } 00830 dev->Port = 0; // Device is now free 00831 dev->Flags = 0; 00832 return; 00833 } 00834 } 00835 } 00836 00837 // called after reset 00838 void Connect(int hub, int port, bool lowspeed) 00839 { 00840 LOG("Connect Hub:%d Port:%d %s\r\n",hub,port,lowspeed ? "slow" : "full"); 00841 AddDevice(hub,port,lowspeed); 00842 } 00843 00844 // Called from interrupt 00845 void HubStatusChange(int hub, int port, u32 status) 00846 { 00847 LOG("HubStatusChange Hub:%d Port:%d %08X\r\n",hub,port,status); 00848 if (status & ConnectStatusChange) 00849 { 00850 if (status & CurrentConnectStatus) // Connecting 00851 ResetPort(hub,port); // Reset to initiate connect (state machine?) 00852 else 00853 Disconnect(hub,port); 00854 } 00855 00856 if (status & PortResetStatusChange) 00857 { 00858 if (!(status & PortResetStatus)) 00859 { 00860 _connectCountdown = 200; // Schedule a connection in 200ms 00861 if (status & LowspeedDevice) 00862 port |= 0x80; 00863 _connectHub = hub; 00864 _connectPort = port; 00865 } 00866 } 00867 } 00868 00869 #define HOST_CLK_EN (1<<0) 00870 #define PORTSEL_CLK_EN (1<<3) 00871 #define AHB_CLK_EN (1<<4) 00872 #define CLOCK_MASK (HOST_CLK_EN | PORTSEL_CLK_EN | AHB_CLK_EN) 00873 00874 #define FRAMEINTERVAL (12000-1) // 1ms 00875 #define DEFAULT_FMINTERVAL ((((6 * (FRAMEINTERVAL - 210)) / 7) << 16) | FRAMEINTERVAL) 00876 00877 void DelayMS(int ms) 00878 { 00879 u16 f = ms + CommunicationArea.FrameNumber; 00880 while (f != CommunicationArea.FrameNumber) 00881 ; 00882 } 00883 00884 static void HWInit(HCCA* cca) 00885 { 00886 NVIC_DisableIRQ(USB_IRQn); 00887 00888 // turn on power for USB 00889 LPC_SC->PCONP |= (1UL<<31); 00890 // Enable USB host clock, port selection and AHB clock 00891 LPC_USB->USBClkCtrl |= CLOCK_MASK; 00892 // Wait for clocks to become available 00893 while ((LPC_USB->USBClkSt & CLOCK_MASK) != CLOCK_MASK) 00894 ; 00895 00896 // We are a Host 00897 LPC_USB->OTGStCtrl |= 1; 00898 LPC_USB->USBClkCtrl &= ~PORTSEL_CLK_EN; // we don't need port selection clock until we do OTG 00899 00900 // configure USB pins 00901 LPC_PINCON->PINSEL1 &= ~((3<<26)|(3<<28)); 00902 LPC_PINCON->PINSEL1 |= ((1<<26)|(1<<28)); // USB D+/D- 00903 00904 LPC_PINCON->PINSEL3 &= ~((3 << 6) | (3 << 22)); // USB_PPWR, USB_OVRCR 00905 LPC_PINCON->PINSEL3 |= ((2 << 6) | (2 << 22)); 00906 00907 LPC_PINCON->PINSEL4 &= ~(3 << 18); // USB_CONNECT 00908 LPC_PINCON->PINSEL4 |= (1 << 18); 00909 00910 // Reset OHCI block 00911 LPC_USB->HcControl = 0; 00912 LPC_USB->HcControlHeadED = 0; 00913 LPC_USB->HcBulkHeadED = 0; 00914 00915 LPC_USB->HcCommandStatus = HostControllerReset; 00916 LPC_USB->HcFmInterval = DEFAULT_FMINTERVAL; 00917 LPC_USB->HcPeriodicStart = FRAMEINTERVAL*90/100; 00918 00919 LPC_USB->HcControl = (LPC_USB->HcControl & (~HostControllerFunctionalState)) | OperationalMask; 00920 LPC_USB->HcRhStatus = SetGlobalPower; 00921 00922 LPC_USB->HcHCCA = (u32)cca; 00923 LPC_USB->HcInterruptStatus |= LPC_USB->HcInterruptStatus; 00924 LPC_USB->HcInterruptEnable = MasterInterruptEnable | WritebackDoneHead | RootHubStatusChange | FrameNumberOverflow; 00925 00926 NVIC_SetPriority(USB_IRQn, 0); 00927 NVIC_EnableIRQ(USB_IRQn); 00928 while (cca->FrameNumber < 10) 00929 ; // 10ms delay before diving in 00930 } 00931 }; 00932 00933 //==================================================================================== 00934 //==================================================================================== 00935 // Host controller instance and Interrupt handler 00936 00937 static HostController _controller __attribute__((at(USB_RAM_BASE))); 00938 00939 extern "C" void USB_IRQHandler(void) __irq; 00940 void USB_IRQHandler (void) __irq 00941 { 00942 LOG("USB_IRQHandler start \r\n"); 00943 u32 int_status = LPC_USB->HcInterruptStatus; 00944 LOG("USB_IRQHandler int_status=%0x\r\n",int_status); 00945 00946 if(int_status & UnrecoverableError) //Error 00947 { 00948 LOG("USB_IRQHandler UnrecoverableError Please reset\r\n"); 00949 } 00950 00951 if(int_status & MasterInterruptEnable) 00952 { 00953 LOG("USB_IRQHandler MasterInterruptEnable\r\n"); 00954 } 00955 00956 if(int_status &OwnershipChange) 00957 { 00958 LOG("USB_IRQHandler OwnershipChange\r\n"); 00959 } 00960 00961 if(int_status &FrameNumberOverflow) 00962 { 00963 LOG("USB_IRQHandler FrameNumberOverflow\r\n"); 00964 } 00965 if(int_status&ResumeDetected) 00966 { 00967 LOG("USB_IRQHandler ResumeDetected\r\n"); 00968 } 00969 if(int_status&StartofFrame) 00970 { 00971 LOG("USB_IRQHandler StartofFrame\r\n"); 00972 } 00973 00974 00975 if (int_status & RootHubStatusChange) // Root hub status change 00976 { 00977 LOG("USB_IRQHandler _rootHubStatusChange %0x->%0x \r\n", _controller._rootHubStatusChange, _controller._rootHubStatusChange+1); 00978 _controller._rootHubStatusChange++; // Just flag the controller, will be processed in USBLoop 00979 } 00980 00981 u32 head = 0; 00982 if (int_status & WritebackDoneHead) 00983 { 00984 head = _controller.CommunicationArea.DoneHead; // Writeback Done 00985 _controller.CommunicationArea.DoneHead = 0; 00986 LOG("USB_IRQHandler head=%0x\r\n",head); 00987 } 00988 LPC_USB->HcInterruptStatus = int_status; 00989 00990 if (head) 00991 _controller.ProcessDoneQueue(head); // TODO - low bit can be set BUGBUG 00992 LOG("USB_IRQHandler end \r\n"); 00993 } 00994 00995 //==================================================================================== 00996 //==================================================================================== 00997 // API Methods 00998 00999 void USBInit() 01000 { 01001 return _controller.Init(); 01002 } 01003 01004 void USBLoop() 01005 { 01006 return _controller.Loop(); 01007 } 01008 01009 u8* USBGetBuffer(u32* len) 01010 { 01011 *len = USB_RAM_SIZE - sizeof(HostController); 01012 return _controller.SRAM; 01013 } 01014 01015 static Setup* GetSetup(int device) 01016 { 01017 if (device == 0) 01018 return &_controller._setupZero; 01019 01020 if (device < 1 || device > MAX_DEVICES) 01021 return 0; 01022 return &_controller.Devices[device-1].SetupBuffer; 01023 } 01024 01025 // Loop until IO on endpoint is complete 01026 static int WaitIODone(Endpoint* endpoint) 01027 { 01028 LOG("WaitIODone start\r\n"); 01029 if (endpoint->CurrentState == Endpoint::NotQueued) 01030 return 0; 01031 while (endpoint->CurrentState != Endpoint::Idle) 01032 { 01033 LOG("WaitIODone goto USBloop endpoint->CurrentState =%d \r\n",endpoint->CurrentState); 01034 USBLoop(); // May generate callbacks, mount or unmount devices etc 01035 } 01036 int status = endpoint->Status(); 01037 01038 LOG("WaitIODone end\r\n"); 01039 if (status == 0) 01040 return endpoint->Length; 01041 return -status; 01042 } 01043 01044 int USBTransfer(int device, int ep, u8 flags, u8* data, int length, USBCallback callback, void* userData) 01045 { 01046 //LOG("USBTRANSFER start\r\n"); 01047 Endpoint* endpoint = _controller.GetEndpoint(device,ep); 01048 if (!endpoint) 01049 { 01050 LOG("USBTRANSFER error Endpoint not found!!\r\n"); 01051 return ERR_ENDPOINT_NOT_FOUND; 01052 } 01053 01054 //LOG("USBTRANSFER run01\r\n"); 01055 WaitIODone(endpoint); 01056 endpoint->Flags = flags; 01057 endpoint->Data = data; 01058 endpoint->Length = length; 01059 endpoint->Callback = callback; 01060 endpoint->UserData = userData; 01061 //LOG("USBTRANSFER run02\r\n"); 01062 if (ep == 0) 01063 { 01064 LOG("USBTRANSFER ep == 0(Setup) ------------------------------\r\n"); 01065 _controller.Transfer(endpoint,TOKEN_SETUP,(u8*)GetSetup(device),8,Endpoint::SetupQueued); 01066 } 01067 else 01068 { 01069 LOG("USBTRANSFER ep != 0\r\n"); 01070 _controller.Transfer(endpoint,flags & 0x80 ? TOKEN_IN : TOKEN_OUT,data,length,Endpoint::DataQueued); 01071 } 01072 if (callback) 01073 { 01074 LOG("USBTRANSFER end io_pending\r\n"); 01075 return IO_PENDING; 01076 } 01077 LOG("USBTRANSFER end wait io done \r\n"); 01078 return WaitIODone(endpoint); 01079 } 01080 01081 int USBControlTransfer(int device, int request_type, int request, int value, int index, u8* data, int length, USBCallback callback, void * userData) 01082 { 01083 Setup* setup = GetSetup(device); 01084 if (!setup) 01085 return ERR_DEVICE_NOT_FOUND; 01086 01087 // Async control calls may overwrite setup buffer of previous call, so we need to wait before setting up next call 01088 WaitIODone(_controller.GetEndpoint(device,0)); 01089 01090 setup->bm_request_type = request_type; 01091 setup->b_request = request; 01092 setup->w_value = value; 01093 setup->w_index = index; 01094 setup->w_length = length; 01095 LOG("USBControlTransfer(device=%d,reqtype=%d,req=%d,value=%d,index=%d,data=%p,len=%d,callbak=%p,udata=%p)\r\n", 01096 device,request_type,request,value,index,data,length,callback,userData); 01097 return USBTransfer(device,0,request_type & DEVICE_TO_HOST,data,length,callback,userData); 01098 } 01099 01100 int USBInterruptTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData) 01101 { 01102 return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_INTERRUPT,data,length,callback,userData); 01103 } 01104 01105 int USBBulkTransfer(int device, int ep, u8* data, int length, USBCallback callback, void* userData) 01106 { 01107 return USBTransfer(device,ep,(ep & 0x80) | ENDPOINT_BULK,data,length,callback,userData); 01108 } 01109 01110 int GetDescriptor(int device, int descType,int descIndex, u8* data, int length) 01111 { 01112 return USBControlTransfer(device,DEVICE_TO_HOST | RECIPIENT_DEVICE, GET_DESCRIPTOR,(descType << 8)|(descIndex), 0, data, length, 0); 01113 } 01114 01115 int GetString(int device, int index, char* dst, int length) 01116 { 01117 u8 buffer[255]; 01118 int le = GetDescriptor(device,DESCRIPTOR_TYPE_STRING,index,buffer,sizeof(buffer)); 01119 if (le < 0) 01120 return le; 01121 if (length < 1) 01122 return -1; 01123 length <<= 1; 01124 if (le > length) 01125 le = length; 01126 for (int j = 2; j < le; j += 2) 01127 *dst++ = buffer[j]; 01128 *dst = 0; 01129 return (le>>1)-1; 01130 } 01131 01132 int SetAddress(int device, int new_addr) 01133 { 01134 return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_ADDRESS, new_addr, 0, 0, 0, 0); 01135 } 01136 01137 int SetConfiguration(int device, int configNum) 01138 { 01139 return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_DEVICE, SET_CONFIGURATION, configNum, 0, 0, 0, 0); 01140 } 01141 01142 int SetInterface(int device, int ifNum, int altNum) 01143 { 01144 return USBControlTransfer(device,HOST_TO_DEVICE | RECIPIENT_INTERFACE, SET_INTERFACE, altNum, ifNum, 0, 0, 0); 01145 } 01146 01147 // HUB stuff 01148 int SetPortFeature(int device, int feature, int index) 01149 { 01150 return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,SET_FEATURE,feature,index,0,0); 01151 } 01152 01153 int ClearPortFeature(int device, int feature, int index) 01154 { 01155 return USBControlTransfer(device,HOST_TO_DEVICE | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,CLEAR_FEATURE,feature,index,0,0); 01156 } 01157 01158 int SetPortPower(int device, int port) 01159 { 01160 int r = SetPortFeature(device,PORT_POWER,port); 01161 _controller.DelayMS(20); // 80ms to turn on a hubs power... DESCRIPTOR? todo 01162 return r; 01163 } 01164 01165 int SetPortReset(int device, int port) 01166 { 01167 return SetPortFeature(device,PORT_RESET,port); 01168 } 01169 01170 int GetPortStatus(int device, int port, u32* status) 01171 { 01172 return USBControlTransfer(device,DEVICE_TO_HOST | REQUEST_TYPE_CLASS | RECIPIENT_OTHER,GET_STATUS,0,port,(u8*)status,4); 01173 } 01174 01175 #endif
Generated on Tue Jul 12 2022 15:55:45 by 1.7.2