Satellite Observers Workbench. NOT yet complete, just published for forum posters to \"cherry pick\" pieces of code as requiered as an example.

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbeh_controller.cpp Source File

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