Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.
usbeh_controller.cpp
00001 /**************************************************************************** 00002 * Copyright 2010 Andy Kirkham, Stellar Technologies Ltd 00003 * 00004 * This file is part of the Satellite Observers Workbench (SOWB). 00005 * 00006 * SOWB is free software: you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation, either version 3 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * SOWB is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with SOWB. If not, see <http://www.gnu.org/licenses/>. 00018 * 00019 * $Id: main.cpp 5 2010-07-12 20:51:11Z ajk $ 00020 * 00021 ***************************************************************************/ 00022 00023 #include "sowb.h" 00024 #include "usbeh_endpoint.h" 00025 #include "usbeh_device.h" 00026 #include "usbeh_controller.h" 00027 #include "usbeh_api.h" 00028 00029 #include "main.h" 00030 #include "debug.h" 00031 00032 void USBEH_Controller::process(void) { 00033 USBEH_Endpoint *endpoint; 00034 USBEH_U16 elapsed = hcca.frameNumber - (USBEH_U16)this->frameNumber; 00035 this->frameNumber += elapsed; 00036 00037 while (this->callbacksPending) { 00038 for (int i = 0; i < USBEH_MAX_ENDPOINTS_TOTAL; i++) { 00039 endpoint = this->endpoints + i; 00040 if (endpoint->currentState == USBEH_Endpoint::callbackPending) { 00041 this->callbacksPending--; 00042 endpoint->currentState = USBEH_Endpoint::idle; 00043 endpoint->callback( 00044 endpoint->device(), 00045 endpoint->address(), 00046 endpoint->status(), 00047 (USBEH_U08 *)endpoint->userData, 00048 endpoint->length, 00049 endpoint->userData); 00050 } 00051 } 00052 } 00053 00054 if (this->rootHubStatusChange) { 00055 USBEH_U32 status = USBEH_HcRhPortStatus1; 00056 this->rootHubStatusChange = 0; 00057 if (status >> 16) { 00058 hubStatusChange(0, 1, status); 00059 USBEH_HcRhPortStatus1 = status & 0xFFFF0000; 00060 } 00061 } 00062 00063 if (this->connectCountdown) { 00064 if (elapsed >= this->connectCountdown) { 00065 this->connectCountdown = 0; 00066 connect(this->connectHub, this->connectPort & 0x7F, this->connectPort & 0x80); 00067 } 00068 else { 00069 this->connectCountdown -= elapsed; 00070 } 00071 } 00072 } 00073 00074 void USBEH_Controller::init(void) { 00075 memset(this, 0, sizeof(USBEH_Controller)); 00076 endpointZero.currentState = USBEH_Endpoint::notQueued; 00077 initHW(&hcca); 00078 delayMS(10); 00079 } 00080 00081 void USBEH_Controller::hubInterrupt(int device) { 00082 USBEH_Device *dev = &devices[device - 1]; 00083 00084 for (int i = 0; i < dev->hubPortCount; i++) { 00085 int port = i + 1; 00086 if (dev->hubInterruptData * (1 << port)) { 00087 USBEH_U32 status = 0; 00088 usbeh_api_get_port_status(device, port, &status); 00089 if (status >> 16) { 00090 if (connectPending && (status & USBEH_CONNECT_STATUS_CHANGE)) { 00091 hubStatusChange(device, port, status); 00092 if (status & USBEH_CONNECT_STATUS_CHANGE) { 00093 usbeh_api_clear_port_feature(device, USBEH_C_PORT_CONNECTION, port); 00094 } 00095 if (status & USBEH_PORT_RESET_STATUS_CAHNGE) { 00096 usbeh_api_clear_port_feature(device, USBEH_C_PORT_RESET, port); 00097 } 00098 } 00099 } 00100 } 00101 } 00102 } 00103 00104 void USBEH_Controller::hubInterruptCallback(int device, int endpoint, int status, USBEH_U08 *data, int length, void *userData) { 00105 USBEH_Controller *controller = (USBEH_Controller *)userData; 00106 if (status == 0) { 00107 controller->hubInterrupt(device); 00108 } 00109 usbeh_api_interrupt_transfer(device, endpoint, data, 1, hubInterruptCallback, userData); 00110 } 00111 00112 int USBEH_Controller::initHub(int device) { 00113 USBEH_U08 buffer[16]; 00114 int r = usbeh_api_control_transfer(device, USBEH_DEVICE_TO_HOST | USBEH_REQUEST_TYPE_CLASS | USBEH_RECIPIENT_DEVICE, USBEH_GET_DESCRIPTOR, (USBEH_DESCRIPTOR_TYPE_HUB << 8), 0, buffer, sizeof(buffer), 0, 0); 00115 if (r < 0) return -1; 00116 00117 USBEH_Device *dev = &this->devices[device - 1]; 00118 00119 int ports = buffer[2]; 00120 00121 for (int i = 0; i < ports; i++) { 00122 usbeh_api_set_port_power(device, i + 1); 00123 } 00124 00125 return usbeh_api_interrupt_transfer(device, 0x81, &dev->hubInterruptData,1, hubInterruptCallback, this); 00126 } 00127 00128 int USBEH_Controller::transfer(USBEH_Endpoint *endpoint, int token, USBEH_U08 *data, int len, int state) { 00129 00130 int toggle = 0; 00131 00132 if (endpoint->address() == 0) { 00133 toggle = (token == USBEH_TOKEN_SETUP) ? USBEH_TD_TOGGLE_0 : USBEH_TD_TOGGLE_1; 00134 } 00135 00136 if (token != USBEH_TOKEN_SETUP) { 00137 token = (token == USBEH_TOKEN_IN ? USBEH_TD_IN : USBEH_TD_OUT); 00138 } 00139 00140 USBEH_HCTD *head = &endpoint->tdHead; 00141 USBEH_HCTD *tail = &this->commonTail; 00142 00143 head->control = USBEH_TD_ROUNDING | token | USBEH_TD_DELAY_INT(0) | toggle | USBEH_TD_CC; 00144 head->currentBufferPointer = (USBEH_U32)data; 00145 head->bufferEnd = (USBEH_U32)(data + len - 1); 00146 head->next = (USBEH_U32)tail; 00147 00148 USBEH_HCED *ed = &endpoint->endpointDescriptor; 00149 ed->headTd = (USBEH_U32)head | (ed->headTd & 0x00000002); 00150 ed->tailTd = (USBEH_U32)tail; 00151 00152 switch (endpoint->flags & 3) { 00153 case USBEH_ENDPOINT_CONTROL: 00154 USBEH_HcControlHeadED = endpoint->queue(USBEH_HcControlHeadED); 00155 endpoint->currentState = state; 00156 USBEH_HcCommandStatus = USBEH_HcCommandStatus | USBEH_CONTROL_LIST_FILLED; 00157 USBEH_HcControl |= USBEH_CONTROL_LIST_ENABLE; 00158 break; 00159 case USBEH_ENDPOINT_BULK: 00160 USBEH_HcBulkHeadED = endpoint->queue(USBEH_HcBulkHeadED); 00161 endpoint->currentState = state; 00162 USBEH_HcCommandStatus = USBEH_HcCommandStatus | USBEH_BULK_LIST_FILLED; 00163 USBEH_HcControl |= USBEH_BULK_LIST_ENABLE; 00164 break; 00165 case USBEH_ENDPOINT_INTERRUPT: 00166 hcca.interruptTable[0] = endpoint->queue(hcca.interruptTable[0]); 00167 endpoint->currentState = state; 00168 USBEH_HcControl |= USBEH_PERIODIC_LIST_ENABLE; 00169 break; 00170 } 00171 00172 return 0; 00173 } 00174 00175 bool USBEH_Controller::remove(USBEH_HCED *ed, volatile USBEH_HCED **queue) { 00176 if (*queue == 0) return false; 00177 if (*queue == (volatile USBEH_HCED *)ed) { 00178 *queue = (volatile USBEH_HCED *)ed->next; 00179 return true; 00180 } 00181 00182 volatile USBEH_HCED *head = *queue; 00183 while (head) { 00184 if (head->next == (USBEH_U32)ed) { 00185 head->next = ed->next; 00186 return true; 00187 } 00188 head = (volatile USBEH_HCED *)head->next; 00189 } 00190 00191 return false; 00192 } 00193 00194 void USBEH_Controller::release(USBEH_Endpoint *endpoint) { 00195 if (endpoint->currentState != USBEH_Endpoint::notQueued) { 00196 USBEH_HCED *ed = (USBEH_HCED *)endpoint; 00197 ed->control |= 0x4000; 00198 switch (endpoint->flags & 0x3) { 00199 case USBEH_ENDPOINT_CONTROL: 00200 remove(ed, (volatile USBEH_HCED **)&USBEH_HcControlHeadED); 00201 break; 00202 case USBEH_ENDPOINT_BULK: 00203 remove(ed, (volatile USBEH_HCED **)&USBEH_HcBulkHeadED); 00204 break; 00205 case USBEH_ENDPOINT_INTERRUPT: 00206 for (int i = 0; i < 32; i++) { 00207 remove(ed, (volatile USBEH_HCED **)&hcca.interruptTable[i]); 00208 } 00209 break; 00210 } 00211 00212 USBEH_U16 fn = hcca.frameNumber; 00213 while (fn == hcca.frameNumber) ; 00214 } 00215 00216 memset(endpoint, 0, sizeof(USBEH_Endpoint)); 00217 } 00218 00219 int USBEH_Controller::addEndpoint(int device, USBEH_endpointDescriptor *endpoint) { 00220 return addEndpoint(device, endpoint->bEndpointAddress, endpoint->bmAttributes, endpoint->wMaxPacketSize, endpoint->bInterval); 00221 } 00222 00223 int USBEH_Controller::addEndpoint(int device, int endpoint, int attributes, int maxPacketSize, int interval) { 00224 USBEH_Device *dev = &this->devices[device - 1]; 00225 USBEH_Endpoint *ep = allocateEndpoint(device, endpoint, attributes, maxPacketSize); 00226 if (!ep) { 00227 return -1; 00228 } 00229 dev->setEndpointIndex(endpoint, ep - this->endpoints); 00230 ep->endpointDescriptor.control |= dev->flags; 00231 return 0; 00232 00233 } 00234 00235 USBEH_Endpoint * USBEH_Controller::allocateEndpoint(int device, int endpointAddress, int type, int maxPacketSize) { 00236 for (int i = 0; i < USBEH_MAX_ENDPOINTS_TOTAL; i++) { 00237 USBEH_Endpoint *ep = &this->endpoints[i]; 00238 if (ep->currentState == 0) { 00239 ep->flags = (endpointAddress & 0x80) | (type & 0x3); 00240 ep->currentState = USBEH_Endpoint::notQueued; 00241 ep->endpointDescriptor.control = (maxPacketSize << 16) | ((endpointAddress & 0x7F) << 7) | device; 00242 return ep; 00243 } 00244 } 00245 return 0; 00246 } 00247 00248 int USBEH_Controller::addDevice(int hub, int port, bool isLowSpeed) { 00249 int device = addDeviceCore(hub, port, isLowSpeed); 00250 if (device < 0) { 00251 disconnect(hub, port); 00252 resetPort(hub, port); 00253 return -1; 00254 } 00255 return device; 00256 } 00257 00258 int USBEH_Controller::addDeviceCore(int hub, int port, bool isLowSpeed) { 00259 00260 int lowSpeed = isLowSpeed ? 0x2000 : 0; 00261 00262 USBEH_deviceDescriptor desc; 00263 00264 endpointZero.endpointDescriptor.control = (8 << 16) | lowSpeed; 00265 00266 int result = usbeh_api_get_descriptor(0, USBEH_DESCRIPTOR_TYPE_DEVICE, 0, (USBEH_U08 *)&desc, 8); 00267 00268 if (result < 0) { 00269 #ifdef DEBUG_USB_DRIVER 00270 debug_printf("usbeh_api_get_descriptor() failed with %d (0x%x) at line %d\r\n", result, result, __LINE__); 00271 #endif 00272 return result; 00273 } 00274 00275 endpointZero.endpointDescriptor.control = (desc.bMaxPacketSize << 16) | lowSpeed; 00276 00277 result = usbeh_api_get_descriptor(0, USBEH_DESCRIPTOR_TYPE_DEVICE, 0, (USBEH_U08 *)&desc, sizeof(desc)); 00278 if (result < 0) { 00279 #ifdef DEBUG_USB_DRIVER 00280 debug_printf("usbeh_api_get_descriptor() failed with %d at line %d\r\n", result, __LINE__); 00281 #endif 00282 return result; 00283 } 00284 00285 int device = 0; 00286 for (int i = 0; i < USBEH_MAX_DEVICES; i++) { 00287 if (devices[i].port == 0) { 00288 device = i + 1; 00289 break; 00290 } 00291 } 00292 00293 if (!device) { 00294 return -1; 00295 } 00296 00297 result = usbeh_api_set_address(0, device); 00298 if (result) { 00299 return result; 00300 } 00301 00302 delayMS(2); 00303 00304 USBEH_Device *dev = &devices[device - 1]; 00305 dev->init(&desc, hub, port, device, lowSpeed); 00306 addEndpoint(device, 0, USBEH_ENDPOINT_CONTROL, desc.bMaxPacketSize, 0); 00307 this->connectPending = 0; 00308 00309 if ((result = usbeh_api_get_descriptor(device, USBEH_DESCRIPTOR_TYPE_DEVICE, 0, (USBEH_U08 *)&desc, sizeof(desc))) < 0) { 00310 #ifdef DEBUG_USB_DRIVER 00311 debug_printf("usbeh_api_get_descriptor() failed with %d at line %d\r\n", result, __LINE__); 00312 #endif 00313 return result; 00314 } 00315 00316 result = setConfigurationAndInterface(device, 1, -1, &desc); 00317 00318 if (desc.bDeviceClass == CLASS_HUB) { 00319 initHub(device); 00320 } 00321 00322 return device; 00323 } 00324 00325 int USBEH_Controller::setConfigurationAndInterface(int device, int configuration, int interfaceNumber, USBEH_deviceDescriptor *desc) { 00326 USBEH_U08 buffer[255]; 00327 USBEH_interfaceDescriptor *found[16]; 00328 USBEH_endpointDescriptor *ed; 00329 00330 for (int i = 0; i < 16; i++) { 00331 found[i] = (USBEH_interfaceDescriptor *)NULL; 00332 } 00333 00334 int err = usbeh_api_get_descriptor(device, USBEH_DESCRIPTOR_TYPE_CONFIGURATION, 0, buffer, sizeof(buffer)); 00335 if (err < 0) { 00336 #ifdef DEBUG_USB_DRIVER 00337 debug_printf("GET_DESCRIPTOR failed at line %d\r\n", __LINE__); 00338 #endif 00339 return err; 00340 } 00341 00342 err = usbeh_api_set_configuration(device, configuration); 00343 if (err < 0) { 00344 return err; 00345 } 00346 00347 int interfaceCounter = 0; 00348 int len = buffer[2] | (buffer[3] << 8); 00349 USBEH_U08 *d = buffer; 00350 USBEH_U08 *end = d + len; 00351 while (d < end) { 00352 //printf("Testing descriptor type %02x\n\r", d[1]); 00353 if (d[1] == USBEH_DESCRIPTOR_TYPE_INTERFACE) { 00354 //printf(" Found interface descriptor type %02x\n\r", d[1]); 00355 USBEH_interfaceDescriptor *id = (USBEH_interfaceDescriptor *)d; 00356 if (interfaceNumber == -1 || id->bInterfaceNumber == interfaceNumber) { 00357 found[interfaceCounter++] = id; 00358 d += d[0]; 00359 while (d < end && d[1] != USBEH_DESCRIPTOR_TYPE_INTERFACE) { 00360 switch (d[1]) { 00361 case USBEH_DESCRIPTOR_TYPE_ENDPOINT: 00362 ed = (USBEH_endpointDescriptor *)d; 00363 //printf(" Adding endpoint 0x%02x for interface %d\r\n", ed->bEndpointAddress, id->bInterfaceNumber); 00364 addEndpoint(device, ed); 00365 break; 00366 default: 00367 // Skip unknown descriptor. 00368 //printf(" Unknown descriptor type: %02x\r\n", d[1]); 00369 break; 00370 } 00371 d += d[0]; 00372 } 00373 } 00374 } 00375 else { 00376 d += d[0]; 00377 } 00378 } 00379 00380 if (interfaceCounter == 0) { 00381 return USBEH_ERR_INTERFACE_NOT_FOUND; 00382 } 00383 00384 usbeh_api_on_load_device(device, desc, found); 00385 00386 return 0; 00387 } 00388 00389 void USBEH_Controller::processDoneQueue(USBEH_U32 tdList) { 00390 USBEH_Endpoint *endpoint; 00391 USBEH_HCTD *list = reverse((USBEH_HCTD *)tdList); 00392 while (list) { 00393 endpoint = (USBEH_Endpoint *)(list - 1); 00394 list = (USBEH_HCTD *)list->next; 00395 int ep = endpoint->address(); 00396 bool in = endpoint->flags & 0x80; 00397 int status = (endpoint->tdHead.control >> 28) & 0xF; 00398 00399 if (status != 0) { 00400 endpoint->currentState = USBEH_Endpoint::idle; 00401 } 00402 else { 00403 switch (endpoint->currentState) { 00404 case USBEH_Endpoint::setupQueued: 00405 if (endpoint->length == 0) { 00406 transfer(endpoint, in ? USBEH_TOKEN_OUT : USBEH_TOKEN_IN, 0, 0, USBEH_Endpoint::statusQueued); 00407 } 00408 else { 00409 transfer(endpoint, in ? USBEH_TOKEN_IN : USBEH_TOKEN_OUT, (USBEH_U08 *)endpoint->data, endpoint->length, USBEH_Endpoint::dataQueued); 00410 } 00411 break; 00412 00413 case USBEH_Endpoint::dataQueued: 00414 if (endpoint->tdHead.currentBufferPointer) { 00415 endpoint->length = endpoint->tdHead.currentBufferPointer - (USBEH_U32)endpoint->data; 00416 } 00417 00418 if (ep == 0) { 00419 transfer(endpoint, in ? USBEH_TOKEN_OUT : USBEH_TOKEN_IN, 0, 0, USBEH_Endpoint::statusQueued); 00420 } 00421 else { 00422 endpoint->currentState = USBEH_Endpoint::idle; 00423 } 00424 break; 00425 00426 case USBEH_Endpoint::statusQueued: 00427 endpoint->currentState = USBEH_Endpoint::idle; 00428 break; 00429 } 00430 } 00431 00432 if (endpoint->callback && endpoint->currentState == USBEH_Endpoint::idle) { 00433 //if (endpoint->address() != 0x81) printf("\r\nCallback pending for 0x%02X\r\n", endpoint->address()); 00434 endpoint->currentState = USBEH_Endpoint::callbackPending; 00435 this->callbacksPending++; 00436 } 00437 } 00438 } 00439 00440 void USBEH_Controller::resetPort(int hub, int port) { 00441 this->connectPending++; 00442 if (hub == 0) { 00443 USBEH_HcRhPortStatus1 = USBEH_PORT_RESET_STATUS; 00444 } 00445 else { 00446 usbeh_api_set_port_reset(hub, port); 00447 } 00448 } 00449 00450 void USBEH_Controller::connect(int hub, int port, bool lowSpeed) { 00451 #ifdef DEBUG_USB_DRIVER 00452 debug_printf("%s called at line %d\r\n", __FUNCTION__, __LINE__); 00453 #endif 00454 addDevice(hub, port, lowSpeed); 00455 } 00456 00457 void USBEH_Controller::disconnect(int hub, int port) { 00458 for (int i = 0; i < USBEH_MAX_DEVICES; i++) { 00459 USBEH_Device *dev = this->devices + i; 00460 if (dev->port == port && dev->hub == hub) { 00461 for (int p = 0; p < dev->hubPortCount; p++) { 00462 disconnect(i + 1, p + 1); 00463 } 00464 for (int j = 1; j < USBEH_MAX_ENDPOINTS_PER_DEVICE * 2; j += 2) { 00465 USBEH_U08 endpointIndex = dev->endpoints[j]; 00466 if (endpointIndex != 0xFF) { 00467 release(this->endpoints + endpointIndex); 00468 } 00469 dev->port = 0; 00470 dev->flags = 0; 00471 return; 00472 } 00473 } 00474 } 00475 } 00476 00477 void USBEH_Controller::hubStatusChange(int hub, int port, USBEH_U32 status) { 00478 if (status & USBEH_CONNECT_STATUS_CHANGE) { 00479 if (status & USBEH_CURRENT_CONNECT_STATUS) { 00480 resetPort(hub, port); 00481 } 00482 else { 00483 disconnect(hub, port); 00484 } 00485 } 00486 00487 if (status & USBEH_PORT_RESET_STATUS_CHANGE) { 00488 if (!(status & USBEH_PORT_RESET_STATUS)) { 00489 this->connectCountdown = 200; 00490 if (status & USBEH_LOW_SPEED_DEVICE) { 00491 port |= 0x80; 00492 } 00493 this->connectHub = hub; 00494 this->connectPort = port; 00495 } 00496 } 00497 } 00498 00499 void USBEH_Controller::delayMS(int ms) { 00500 USBEH_U16 f = ms + hcca.frameNumber; 00501 while (f != hcca.frameNumber) ; 00502 } 00503 00504 void USBEH_Controller::initHW(USBEH_HCCA *cca) { 00505 NVIC_DisableIRQ(USB_IRQn); 00506 00507 LPC_SC->PCONP |= (1UL << 31); 00508 LPC_USB->USBClkCtrl |= USBEH_CLOCK_MASK; 00509 while ((LPC_USB->USBClkSt & USBEH_CLOCK_MASK) != USBEH_CLOCK_MASK); 00510 00511 USBEH_OTGStCtrl |= 1; 00512 USBEH_USBClkCtrl &= ~USBEH_PORTSEL_CLK_EN; 00513 00514 LPC_PINCON->PINSEL1 &= ~( (3<<26) | (3<<28) ); 00515 LPC_PINCON->PINSEL1 |= ( (1<<26) | (1<<28)); 00516 00517 USBEH_HcControl = 0; 00518 USBEH_HcControlHeadED = 0; 00519 USBEH_HcBulkHeadED = 0; 00520 USBEH_HcCommandStatus = USBEH_HOST_CONTROLLER_RESET; 00521 USBEH_HcFmInterval = USBEH_DEFAULT_FMINTERVAL; 00522 USBEH_HcPeriodicStart = USBEH_FRAMEINTERVAL * 90 / 100; 00523 00524 USBEH_HcControl = (USBEH_HcControl & (~USBEH_HOST_CONTROLLER_FUNCTIONAL_STATE)) | USBEH_OPERATIONAL_MASK; 00525 USBEH_HcRhStatus = USBEH_SET_GLOBAL_POWER; 00526 00527 USBEH_HcHCCA = (USBEH_U32)cca; 00528 USBEH_HcInterruptStatus |= USBEH_HcInterruptStatus; 00529 USBEH_HcInterruptEnable |= USBEH_MASTER_IRQ_ENABLE | USBEH_WRITEBACK_DONE_HEAD | USBEH_ROOT_HUB_STATUS_CHANGE | USBEH_FRAME_NUMBER_OVERFLOW | USBEH_START_OF_FRAME; 00530 00531 NVIC_EnableIRQ(USB_IRQn); 00532 while (cca->frameNumber < 10); 00533 } 00534 00535 USBEH_HCTD * USBEH_Controller::reverse(USBEH_HCTD *current) { 00536 USBEH_HCTD *result = NULL, *temp; 00537 while (current) { 00538 temp = (USBEH_HCTD *)current->next; 00539 current->next = (USBEH_U32)result; 00540 result = current; 00541 current = temp; 00542 } 00543 return result; 00544 } 00545 00546 USBEH_Endpoint * USBEH_Controller::getEndpoint(int device, int ep) { 00547 if (device == 0) { 00548 return &endpointZero; 00549 } 00550 if (device > USBEH_MAX_DEVICES) { 00551 return 0; 00552 } 00553 int i = devices[device - 1].getEndpointIndex(ep); 00554 if (i == -1) { 00555 return 0; 00556 } 00557 return endpoints + i; 00558 } 00559 00560 /* The controller is defined withinn the API section. */ 00561 extern USBEH_Controller sys_usb_controller; 00562 00563 USBEH_SOF_COUNTER *sof_counter_head = NULL; 00564 00565 /* The USB interrupt handler. */ 00566 extern "C" void USB_IRQHandler (void) __irq { 00567 00568 USBEH_U32 int_status = USBEH_HcInterruptStatus; 00569 00570 if (int_status & USBEH_ROOT_HUB_STATUS_CHANGE) { 00571 sys_usb_controller.rootHubStatusChange++; 00572 } 00573 00574 USBEH_U32 head = 0; 00575 00576 if (int_status & USBEH_WRITEBACK_DONE_HEAD) { 00577 head = sys_usb_controller.hcca.doneHead; 00578 sys_usb_controller.hcca.doneHead = 0; 00579 } 00580 00581 if (int_status & USBEH_START_OF_FRAME) { 00582 for (USBEH_SOF_COUNTER *list = sof_counter_head; list != NULL; list = list->next) { 00583 if (list->mode & USBEH_SOF_COUNTER_DEC && list->flag == 0) { 00584 if (list->counter > 0) list->counter--; 00585 if (list->counter == 0) { 00586 list->flag = 1; 00587 list->counter = list->reload; 00588 if (list->callback != NULL) { 00589 (list->callback)((struct _sof_counter *)list); 00590 } 00591 } 00592 } 00593 } 00594 } 00595 00596 USBEH_HcInterruptStatus = int_status; 00597 00598 if (head) { 00599 sys_usb_controller.processDoneQueue(head); 00600 } 00601 } 00602
Generated on Tue Jul 12 2022 18:05:35 by 1.7.2