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