Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USB.cpp Source File

USB.cpp

00001 #include "USB.h"
00002 
00003 #include <cstdio>
00004 
00005 #include "descriptor_cdc.h"
00006 #include "descriptor_msc.h"
00007 
00008 #define iprintf(...) do { } while (0)
00009 
00010 usbdesc_base *USB::descriptors[N_DESCRIPTORS];
00011 
00012 usbdesc_device USB::device = {
00013     DL_DEVICE,
00014     DT_DEVICE,
00015     USB_VERSION_2_0,    // .bcdUSB
00016     UC_MISC,            // .bDeviceClass
00017     SUBCLASS_IAD,       // .bDeviceSubClass
00018     PROTOCOL_IAD,       // .bDeviceProtocol
00019     64,                 // .bMaxPacketSize0
00020     0x1d50,             // .idVendor
00021     0x6015,             // .idProduct
00022     0x0100,             // .bcdDevice
00023     0,                  // .iManufacturer
00024     0,                  // .iProduct
00025     0,                  // .iSerialNumber
00026     1,                  // .bNumConfigurations
00027 };
00028 
00029 static usbdesc_language lang = {
00030     DL_LANGUAGE,
00031     DT_LANGUAGE,
00032     { SL_USENGLISH, },
00033 };
00034 
00035 static usbstring_const_init(manufacturer, "Uberclock");
00036 
00037 static usbstring_const_init(product, "Smoothieboard");
00038 
00039 static usbstring_init(serial, "01234567abcdefgh01234567abcdefgh");
00040 
00041 static usbstring_const_init(str_default, "Default");
00042 
00043 
00044 usbdesc_configuration USB::conf = {
00045     DL_CONFIGURATION,
00046     DT_CONFIGURATION,
00047     sizeof(usbdesc_configuration),
00048     0,                  // .bNumInterfaces
00049     1,                  // .bConfigurationValue
00050     0,                  // .iConfiguration
00051     CA_BUSPOWERED,      // .bmAttributes
00052     500 mA,             // .bMaxPower
00053 };
00054 
00055 USB::USB() {
00056     int i;
00057 
00058     i = 0;
00059     descriptors[i++] = (usbdesc_base *) &device;
00060     descriptors[i++] = (usbdesc_base *) &conf;
00061     for (;i < N_DESCRIPTORS; i++)
00062         descriptors[i] = (usbdesc_base *) 0;
00063 
00064     addString(&lang);
00065     device.iManufacturer = addString(&manufacturer);
00066     device.iProduct = addString(&product);
00067     device.iSerialNumber = addString(&serial);
00068     conf.iConfiguration = addString(&str_default);
00069 }
00070 
00071 USB::USB(uint16_t idVendor, uint16_t idProduct, uint16_t bcdFirmwareRevision) {
00072     USB();
00073     device.idVendor = idVendor;
00074     device.idProduct = idProduct;
00075     device.bcdDevice = bcdFirmwareRevision;
00076 }
00077 
00078 void USB::init() {
00079     iprintf("init\n");
00080 
00081     uint32_t chip_serial[4];
00082     getSerialNumber(4, chip_serial);
00083     for (int j = 0; j < 4; j++) {
00084         for (int i = 0; i < 8; i++) {
00085             uint8_t c = (chip_serial[j] & 15);
00086             serial.str[j * 8 + 7 - i] = (c < 10)?(c + '0'):(c - 10 + 'A');
00087             chip_serial[j] >>= 4;
00088         }
00089     }
00090 
00091     setDescriptors(descriptors);
00092 
00093     USBHAL::init();
00094 
00095     iprintf("OK\n");
00096 }
00097 
00098 bool USB::USBCallback_setConfiguration(uint8_t configuration)
00099 {
00100     iprintf("[CONFIGURE %d]", configuration);
00101     int i = findDescriptorIndex(0, DT_CONFIGURATION, configuration, 0);
00102     if (i > 0)
00103     {
00104         iprintf("[FOUND at %d]", i);
00105         uint8_t lastAlternate = 0;
00106         i++;
00107         for (; descriptors[i] != (usbdesc_base *) 0 && descriptors[i]->bDescType != DT_CONFIGURATION; i++) {
00108             switch(descriptors[i]->bDescType)
00109             {
00110                 case DT_INTERFACE: {
00111                     usbdesc_interface *interface = (usbdesc_interface *) descriptors[i];
00112                     iprintf("[INTERFACE %d:%d]",interface->bInterfaceNumber, interface->bAlternateSetting);
00113                     interface->selectedAlternate = 0;
00114                     lastAlternate = interface->bAlternateSetting;
00115                     break;
00116                 };
00117                 case DT_ENDPOINT: {
00118                     usbdesc_endpoint *ep = (usbdesc_endpoint *) descriptors[i];
00119                     iprintf("[EP 0x%02X](%d)", ep->bEndpointAddress, lastAlternate);
00120                     if (lastAlternate == 0) {
00121                         iprintf("[Realised!]\n");
00122                         realiseEndpoint(ep->bEndpointAddress, ep->wMaxPacketSize, ((ep->bmAttributes & 3) == EA_ISOCHRONOUS)?ISOCHRONOUS:0);
00123                     }
00124                     break;
00125                 };
00126             }
00127         }
00128         return true;
00129     }
00130     return false;
00131 }
00132 
00133 bool USB::USBCallback_setInterface(uint16_t interface, uint8_t alternate) {
00134     int i = findDescriptorIndex(0, DT_INTERFACE, interface, alternate);
00135     if (i > 0)
00136     {
00137         int j = findDescriptorIndex(0, DT_INTERFACE, interface, 0);
00138         if (j > 0) {
00139             ((usbdesc_interface *) descriptors[j])->selectedAlternate = alternate;
00140             for (; (descriptors[i]->bDescType != DT_INTERFACE) && (descriptors[i]->bDescType != DT_CONFIGURATION); i++) {
00141                 if (descriptors[i]->bDescType == DT_ENDPOINT) {
00142                     usbdesc_endpoint *ep = (usbdesc_endpoint *) descriptors[i];
00143                     realiseEndpoint(ep->bEndpointAddress, ep->wMaxPacketSize, ((ep->bmAttributes & 3) == EA_ISOCHRONOUS)?ISOCHRONOUS:0);
00144                 }
00145             }
00146         }
00147     }
00148     return false;
00149 }
00150 
00151 bool USB::USBEvent_busReset(void)
00152 {
00153     iprintf("USB:Bus Reset\n");
00154     USBDevice::USBEvent_busReset();
00155 
00156     return false;
00157 }
00158 
00159 bool USB::USBEvent_connectStateChanged(bool connected)
00160 {
00161     // TODO: something useful
00162     if (connected)
00163     {
00164         iprintf("USB:Connected\n");
00165         connect();
00166     }
00167     else
00168     {
00169         iprintf("USB:Disconnected\n");
00170         disconnect();
00171     }
00172     return true;
00173 };
00174 
00175 bool USB::USBEvent_suspendStateChanged(bool suspended)
00176 {
00177     // TODO: something useful
00178     if (suspended)
00179     {
00180         iprintf("USB:Suspended\n");
00181     }
00182     else
00183     {
00184         iprintf("USB:Unsuspended\n");
00185     }
00186     return true;
00187 };
00188 
00189 bool USB::USBEvent_Request(CONTROL_TRANSFER& transfer)
00190 {
00191 /*    if (transfer.setup.bmRequestType.Type == CLASS_TYPE)
00192         iprintf("[CLASS]");
00193     if (transfer.setup.bmRequestType.Type == VENDOR_TYPE)
00194         iprintf("[VENDOR]")*/;
00195     if (
00196         (transfer.setup.bmRequestType.Type == CLASS_TYPE)
00197         ||
00198         (transfer.setup.bmRequestType.Type == VENDOR_TYPE)
00199        )
00200     {
00201         // decode request destination
00202         switch(transfer.setup.bmRequestType.Recipient)
00203         {
00204             case INTERFACE_RECIPIENT: {
00205 //                 iprintf("[INTERFACE %d]", transfer.setup.wIndex);
00206                 int i = findDescriptorIndex(0, DT_INTERFACE, transfer.setup.wIndex, 0);
00207                 if (i >.0)
00208                 {
00209                     usbdesc_interface *interface = (usbdesc_interface *) descriptors[i];
00210 //                     iprintf("[FOUND at %d, handler is %p]", i, interface->classReceiver);
00211                     bool r = interface->classReceiver->USBEvent_Request(transfer);
00212 //                     if (r)
00213 //                         iprintf("[HANDLED]\n");
00214 //                     else
00215 //                         iprintf("[NOT handled]\n");
00216                     return r;
00217                 }
00218                 break;
00219             };
00220             case ENDPOINT_RECIPIENT: {
00221 //                 iprintf("[ENDPOINT 0x%02X]", transfer.setup.wIndex);
00222                 int i = findDescriptorIndex(0, DT_ENDPOINT, transfer.setup.wIndex, 0);
00223                 if (i >.0)
00224                 {
00225                     usbdesc_endpoint *ep = (usbdesc_endpoint *) descriptors[i];
00226 //                     iprintf("[FOUND at %d, handler is %p]", i, ep->epReceiver);
00227                     bool r = ep->epReceiver->USBEvent_Request(transfer);
00228 //                     if (r)
00229 //                         iprintf("[HANDLED]\n");
00230 //                     else
00231 //                         iprintf("[NOT handled]\n");
00232                     return r;
00233                 }
00234                 break;
00235             }
00236         }
00237     }
00238 //     iprintf("\n");
00239     return false;
00240 };
00241 
00242 bool USB::USBEvent_RequestComplete(CONTROL_TRANSFER& transfer, uint8_t *buf, uint32_t length)
00243 {
00244     if ((transfer.setup.bmRequestType.Type == CLASS_TYPE) ||
00245         (transfer.setup.bmRequestType.Type == VENDOR_TYPE))
00246     {
00247         // decode request destination
00248         switch(transfer.setup.bmRequestType.Recipient)
00249         {
00250             case INTERFACE_RECIPIENT: {
00251                 int i = findDescriptorIndex(0, DT_INTERFACE, transfer.setup.wIndex, 0);
00252                 if (i >.0)
00253                 {
00254                     usbdesc_interface *interface = (usbdesc_interface *) descriptors[i];
00255                     interface->classReceiver->USBEvent_RequestComplete(transfer, buf, length);
00256                 }
00257                 break;
00258             };
00259             case ENDPOINT_RECIPIENT: {
00260                 int i = findDescriptorIndex(0, DT_ENDPOINT, transfer.setup.wIndex, 0);
00261                 if (i >.0)
00262                 {
00263                     usbdesc_endpoint *ep = (usbdesc_endpoint *) descriptors[i];
00264                     ep->epReceiver->USBEvent_RequestComplete(transfer, buf, length);
00265                 }
00266                 break;
00267             }
00268         }
00269     }
00270     return false;
00271     return false;
00272 };
00273 
00274 bool USB::USBEvent_EPIn(uint8_t bEP, uint8_t bEPStatus)
00275 {
00276     int i = findDescriptorIndex(0, DT_ENDPOINT, bEP, 0);
00277     if (i > 0)
00278     {
00279         usbdesc_endpoint *ep = (usbdesc_endpoint *) descriptors[i];
00280 //         iprintf("[EPIn 0x%02X ST 0x%02X Handler %p]", bEP, bEPStatus, ep->epReceiver);
00281         return ep->epReceiver->USBEvent_EPIn(bEP, bEPStatus);
00282     }
00283     return false;
00284 
00285 };
00286 
00287 bool USB::USBEvent_EPOut(uint8_t bEP, uint8_t bEPStatus)
00288 {
00289 //     iprintf("[EPOut 0x%02X ST 0x%02X]\n", bEP, bEPStatus);
00290     int i = findDescriptorIndex(0, DT_ENDPOINT, bEP, 0);
00291     if (i > 0)
00292     {
00293 //         iprintf("[@%d ", i);
00294         usbdesc_endpoint *ep = (usbdesc_endpoint *) descriptors[i];
00295 //         iprintf("Handler %p]\n", ep->epReceiver);
00296         return ep->epReceiver->USBEvent_EPOut(bEP, bEPStatus);
00297     }
00298     return false;
00299 };
00300 
00301 
00302 int USB::addDescriptor(usbdesc_base *descriptor) {
00303     for (int i = 0; i < N_DESCRIPTORS; i++) {
00304         if (descriptors[i] == (usbdesc_base *) 0) {
00305             descriptors[i] = descriptor;
00306             conf.wTotalLength += descriptor->bLength;
00307             return i;
00308         }
00309     }
00310     return -1;
00311 }
00312 
00313 int USB::addDescriptor(void *descriptor)
00314 {
00315     return addDescriptor((usbdesc_base *) descriptor);
00316 }
00317 
00318 int USB::addInterface(usbdesc_interface *ifp) {
00319     usbdesc_interface *lastif = (usbdesc_interface *) 0;
00320     uint8_t i;
00321     for (i = 0; i < N_DESCRIPTORS; i++) {
00322         if (descriptors[i] == (usbdesc_base *) 0)
00323             break;
00324         if (descriptors[i]->bDescType == DT_INTERFACE)
00325             lastif = (usbdesc_interface *) descriptors[i];
00326     }
00327     if (i >= N_DESCRIPTORS) return -1;
00328 
00329     uint8_t n = conf.bNumInterfaces;
00330 
00331     if (lastif)
00332         if (ifp->bAlternateSetting != lastif->bAlternateSetting)
00333             n--;
00334 
00335     ifp->bInterfaceNumber = n;
00336 //  iprintf("[inserting Interface %p at %d]\n", ifp, i);
00337     descriptors[i] = (usbdesc_base *) ifp;
00338     conf.bNumInterfaces = n + 1;
00339     conf.wTotalLength += descriptors[i]->bLength;
00340 
00341     return n;
00342 }
00343 
00344 int USB::getFreeEndpoint() {
00345     uint8_t i;
00346     uint8_t lastii = 0;
00347     usbdesc_interface *lastif = (usbdesc_interface *) 0;
00348 
00349     for (i = 0; i < N_DESCRIPTORS; i++) {
00350         if (descriptors[i] == (usbdesc_base *) 0)
00351             break;
00352         if (descriptors[i]->bDescType == DT_INTERFACE) {
00353             lastif = (usbdesc_interface *) descriptors[i];
00354             lastii = i;
00355         }
00356     }
00357     if (i >= N_DESCRIPTORS) return -1;
00358     if (lastif == (usbdesc_interface *) 0) return -1;
00359     if (lastii == 0) return -1;
00360 
00361     uint8_t ep_count = 0;
00362     for (i = lastii; i < N_DESCRIPTORS; i++) {
00363         if (descriptors[i] == (usbdesc_base *) 0)
00364             return ep_count;
00365         if (descriptors[i]->bDescType == DT_ENDPOINT)
00366             ep_count++;
00367     }
00368     return ep_count;
00369 }
00370 
00371 int USB::addEndpoint(usbdesc_endpoint *epp) {
00372 //  iprintf("[EP ");
00373     uint8_t i;
00374     usbdesc_interface *lastif = (usbdesc_interface *) 0;
00375     for (i = 0; i < N_DESCRIPTORS; i++) {
00376         if (descriptors[i] == (usbdesc_base *) 0)
00377             break;
00378         if (descriptors[i]->bDescType == DT_INTERFACE)
00379             lastif = (usbdesc_interface *) descriptors[i];
00380     }
00381 //  iprintf("%d:%p ", i, lastif);
00382     if (i >= N_DESCRIPTORS) return -1;
00383     if (lastif == (usbdesc_interface *) 0) return -1;
00384 
00385     int n = getFreeEndpoint();
00386 
00387     // TODO: move this to the hardware-specific class
00388     // we need to scan through our descriptors, and find the first unused logical endpoint of the appropriate type
00389     // the LPC17xx has 16 logical endpoints mapped to 32 "physical" endpoints, looks like this means we have 16 endpoints to use and we get to pick direction
00390     // SO, let's first find all the endpoints in our list of the same type, pick the highest address then go find the next one
00391 
00392     // pick a starting logical endpoint- interrupt = 1, bulk = 2, iso = 3 then subtract 3 so we pick the first one later on
00393     int lepaddr = (4 - epp->bmAttributes) - 3;
00394 
00395     for (i = 0; i < N_DESCRIPTORS; i++) {
00396         if (descriptors[i] == (usbdesc_base *) 0)
00397             break;
00398         if (descriptors[i]->bDescType == DT_ENDPOINT) {
00399             usbdesc_endpoint *x = (usbdesc_endpoint *) descriptors[i];
00400             if (x->bmAttributes == epp->bmAttributes && ((x->bEndpointAddress & 0x80) == (epp->bEndpointAddress & 0x80)))
00401                 if ((x->bEndpointAddress & 0x0F) > lepaddr)
00402                     lepaddr = (x->bEndpointAddress & 0x0F);
00403         }
00404     }
00405 
00406     // now, lepaddr is the last logical endpoint of appropriate type
00407     // the endpoints go in groups of 3, except for the last one which is a bulk instead of isochronous
00408     // find the next free lep using this simple pattern
00409     if (epp->bmAttributes == EA_BULK && lepaddr == 14)
00410         lepaddr = 15;
00411     else
00412         lepaddr += 3;
00413     // now we have the next free logical endpoint of the appropriate type
00414 
00415     // if it's >15 we've run out, spit an error
00416     if (lepaddr > 15) return -1;
00417 
00418     // store logical address and direction bit
00419     epp->bEndpointAddress = lepaddr | (epp->bEndpointAddress & 0x80);
00420 
00421     descriptors[i] = (usbdesc_base *) epp;
00422     //  lastif->bNumEndPoints = n + 1;
00423 
00424     conf.wTotalLength += descriptors[i]->bLength;
00425 
00426     return n;
00427 }
00428 
00429 int USB::addString(const void *ss) {
00430     const usbdesc_base *s = (const usbdesc_base *) ss;
00431     if (s->bDescType == DT_STRING) {
00432         uint8_t i;
00433         uint8_t stringcount = 0;
00434         for (i = 0; i < N_DESCRIPTORS; i++) {
00435             if (descriptors[i] == (usbdesc_base *) 0)
00436                 break;
00437             if (descriptors[i]->bDescType == DT_STRING)
00438                 stringcount++;
00439         }
00440         if (i >= N_DESCRIPTORS) return -1;
00441 
00442         descriptors[i] = const_cast<usbdesc_base*>(s);
00443 
00444         return stringcount;
00445     }
00446     return -1;
00447 }
00448 
00449 int USB::findStringIndex(uint8_t strid) {
00450     uint8_t i;
00451     uint8_t strcounter = 0;
00452     for (i = 0; i < N_DESCRIPTORS; i++) {
00453         if (descriptors[i] == (usbdesc_base *) 0)
00454             return -1;
00455         if (descriptors[i]->bDescType == DT_STRING) {
00456             if (strcounter == strid)
00457                 return i;
00458             strcounter++;
00459         }
00460     }
00461     return -1;
00462 }
00463 
00464 void USB::dumpDevice(usbdesc_device *d) {
00465     iprintf("Device:\n");
00466     iprintf("\tUSB Version:  %d.%d\n", d->bcdUSB >> 8, (d->bcdUSB & 0xFF) >> 4);
00467     iprintf("\tClass:        0x%04X\n", d->bDeviceClass);
00468     iprintf("\tSubClass:     0x%04X\n", d->bDeviceSubClass);
00469     iprintf("\tProtocol:     0x%04X\n", d->bDeviceProtocol);
00470     iprintf("\tMax Packet:   %d\n", d->bMaxPacketSize);
00471     iprintf("\tVendor:       0x%04X\n", d->idVendor);
00472     iprintf("\tProduct:      0x%04X\n", d->idProduct);
00473     iprintf("\tManufacturer: "); dumpString(d->iManufacturer);
00474     iprintf("\tProduct:      "); dumpString(d->iProduct);
00475     iprintf("\tSerial:       "); dumpString(d->iSerialNumber);
00476     iprintf("\tNum Configs:  %d\n", d->bNumConfigurations);
00477 }
00478 
00479 void USB::dumpConfiguration(usbdesc_configuration *c) {
00480     iprintf("Configuration:\n");
00481     iprintf("\tTotal Length:        %db\n", c->wTotalLength);
00482     iprintf("\tNum Interfaces:      %d\n", c->bNumInterfaces);
00483     iprintf("\tConfiguration Value: %d\n", c->bConfigurationValue);
00484     iprintf("\tConfiguration:       "); dumpString(c->iConfiguration);
00485     iprintf("\tAttributes:          %s\n", ((c->bmAttributes & 0x80)?"Bus Powered":"Self Powered"));
00486     iprintf("\tMax Power:           %dmA\n", c->bMaxPower * 2);
00487 }
00488 
00489 void USB::dumpInterface(usbdesc_interface *i) {
00490     iprintf("\t*Interface\n");
00491     iprintf("\t\tNumber:        %d\n", i->bInterfaceNumber);
00492     iprintf("\t\tAlternate:     %d\n", i->bAlternateSetting);
00493     iprintf("\t\tNum Endpoints: %d\n", i->bNumEndPoints);
00494     iprintf("\t\tClass:         0x%02X ", i->bInterfaceClass);
00495     switch(i->bInterfaceClass) {
00496         case UC_COMM:
00497             iprintf("(COMM)");
00498             break;
00499         case UC_MASS_STORAGE:
00500             iprintf("(MSC)");
00501             break;
00502         case UC_CDC_DATA:
00503             iprintf("(CDC DATA)");
00504             break;
00505     }
00506     iprintf("\n");
00507     iprintf("\t\tSubClass:      0x%02X ", i->bInterfaceSubClass);
00508     switch(i->bInterfaceClass) {
00509         case UC_COMM: {
00510             switch(i->bInterfaceSubClass) {
00511                 case USB_CDC_SUBCLASS_ACM:
00512                     iprintf("(ACM)");
00513                     break;
00514                 case USB_CDC_SUBCLASS_ETHERNET:
00515                     iprintf("(ETHERNET)");
00516                     break;
00517             }
00518             break;
00519         }
00520         case UC_MASS_STORAGE: {
00521             switch(i->bInterfaceSubClass) {
00522                 case MSC_SUBCLASS_SCSI:
00523                     iprintf("(SCSI)");
00524                     break;
00525             }
00526             break;
00527         }
00528     }
00529     iprintf("\n");
00530     iprintf("\t\tProtocol:      0x%02X ", i->bInterfaceProtocol);
00531     iprintf("\n");
00532     iprintf("\t\tInterface:     "); dumpString(i->iInterface);
00533 }
00534 void USB::dumpEndpoint(usbdesc_endpoint *e) {
00535     static const char* const attr[4] __attribute__ ((used)) = { "", "Isochronous", "Bulk", "Interrupt" };
00536     iprintf("\t\t*Endpoint\n");
00537     iprintf("\t\t\tAddress:    0x%02X (%s)\n", e->bEndpointAddress, ((e->bEndpointAddress & EP_DIR_IN)?"IN":"OUT"));
00538     iprintf("\t\t\tAttributes: 0x%02X (%s)\n", e->bmAttributes, attr[e->bmAttributes]);
00539     iprintf("\t\t\tMax Packet: %d\n", e->wMaxPacketSize);
00540     iprintf("\t\t\tInterval:   %d\n", e->bInterval);
00541 }
00542 
00543 void USB::dumpString(int i) {
00544     if (i > 0) {
00545         uint8_t j = findStringIndex(i);
00546         if (j > 0) {
00547             iprintf("[%d] ", i);
00548             dumpString((usbdesc_string *) descriptors[j]);
00549             return;
00550         }
00551     }
00552     iprintf("-none-\n");
00553 }
00554 
00555 void USB::dumpString(usbdesc_string *s) {
00556     uint8_t i;
00557     for (i = 0; i < (s->bLength - 2) / 2; i++) {
00558         if (s->str[i] >= 32 && s->str[i] < 128)
00559             putchar(s->str[i]);
00560         else
00561             iprintf("\\0x%02X", s->str[i]);
00562     }
00563     putchar('\n');
00564 }
00565 
00566 void USB::dumpCDC(uint8_t *d) {
00567     switch(d[2]) {
00568         case USB_CDC_SUBTYPE_HEADER: {
00569             usbcdc_header *h = (usbcdc_header *) d;
00570             if (h)
00571             {
00572                 iprintf("\t\t*CDC header\n");
00573                 iprintf("\t\t\tbcdCDC:  0x%04X\n", h->bcdCDC);
00574             }
00575             break;
00576         }
00577         case USB_CDC_SUBTYPE_UNION: {
00578             usbcdc_union *u = (usbcdc_union *) d;
00579             if (u)
00580             {
00581                 iprintf("\t\t*CDC union\n");
00582                 iprintf("\t\t\tMaster:  %d\n", u->bMasterInterface);
00583                 iprintf("\t\t\tSlave:   %d\n", u->bSlaveInterface0);
00584             }
00585             break;
00586         }
00587         case USB_CDC_SUBTYPE_CALL_MANAGEMENT: {
00588             usbcdc_callmgmt *m = (usbcdc_callmgmt *) d;
00589             iprintf("\t\t*CDC Call Management\n");
00590             iprintf("\t\t\tCapabilities:  0x%02X ", m->bmCapabilities);
00591             if (m->bmCapabilities & USB_CDC_CALLMGMT_CAP_CALLMGMT)
00592                 iprintf("(CALLMGMT)");
00593             if (m->bmCapabilities & USB_CDC_CALLMGMT_CAP_DATAINTF)
00594                 iprintf("(DATAINTF)");
00595             iprintf("\n");
00596             iprintf("\t\t\tData Interface: %d\n", m->bDataInterface);
00597             break;
00598         }
00599         case USB_CDC_SUBTYPE_ACM: {
00600             usbcdc_acm *a = (usbcdc_acm *) d;
00601             iprintf("\t\t*CDC ACM\n");
00602             iprintf("\t\t\tCapabilities: 0x%02X ", a->bmCapabilities);
00603             if (a->bmCapabilities & USB_CDC_ACM_CAP_COMM)
00604                 iprintf("(COMM)");
00605             if (a->bmCapabilities & USB_CDC_ACM_CAP_LINE)
00606                 iprintf("(LINE)");
00607             if (a->bmCapabilities & USB_CDC_ACM_CAP_BRK)
00608                 iprintf("(BRK)");
00609             if (a->bmCapabilities & USB_CDC_ACM_CAP_NOTIFY)
00610                 iprintf("(NOTIFY)");
00611             iprintf("\n");
00612             break;
00613         }
00614         case USB_CDC_SUBTYPE_ETHERNET: {
00615             usbcdc_ether *e = (usbcdc_ether *) d;
00616             iprintf("\t\t*CDC Ethernet\n");
00617             iprintf("\t\t\tMAC address: "); dumpString(e->iMacAddress);
00618             iprintf("\t\t\tStatistics: 0x%02lX\n", e->bmEthernetStatistics);
00619             iprintf("\t\t\tMax Segment Size: %d\n", e->wMaxSegmentSize);
00620             iprintf("\t\t\tMC Filters: %d\n", e->wNumberMCFilters);
00621             iprintf("\t\t\tPower Filters: %d\n", e->bNumberPowerFilters);
00622             break;
00623         }
00624     }
00625 }
00626 
00627 void USB::dumpDescriptors() {
00628     uint8_t i;
00629     for (i = 0; i < N_DESCRIPTORS; i++) {
00630         if (descriptors[i] == (usbdesc_base *) 0) {
00631             iprintf("--- FIN at %d\n", i);
00632             return;
00633         }
00634         iprintf("[%d:+%d]", i, descriptors[i]->bLength);
00635         switch (descriptors[i]->bDescType) {
00636             case DT_DEVICE: {
00637                 dumpDevice((usbdesc_device *) descriptors[i]);
00638                 break;
00639             }
00640             case DT_CONFIGURATION: {
00641                 dumpConfiguration((usbdesc_configuration *) descriptors[i]);
00642                 break;
00643             }
00644             case DT_INTERFACE: {
00645                 dumpInterface((usbdesc_interface *) descriptors[i]);
00646                 break;
00647             }
00648             case DT_ENDPOINT: {
00649                 dumpEndpoint((usbdesc_endpoint *) descriptors[i]);
00650                 break;
00651             }
00652             case DT_STRING: {
00653                 dumpString((usbdesc_string *) descriptors[i]);
00654                 break;
00655             }
00656             case DT_CDC_DESCRIPTOR: {
00657                 dumpCDC((uint8_t *) descriptors[i]);
00658                 break;
00659             }
00660         }
00661     }
00662 }
00663 
00664 void USB::on_module_loaded()
00665 {
00666     register_for_event(ON_IDLE);
00667     connect();
00668 }
00669 
00670 void USB::on_idle(void*)
00671 {
00672     USBHAL::usbisr();
00673 }