USB device stack - modified

Dependents:   shaun_larada

Fork of USBDevice by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBDevice.cpp Source File

USBDevice.cpp

00001 /* Copyright (c) 2010-2011 mbed.org, MIT License
00002 *
00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
00004 * and associated documentation files (the "Software"), to deal in the Software without
00005 * restriction, including without limitation the rights to use, copy, modify, merge, publish,
00006 * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
00007 * Software is furnished to do so, subject to the following conditions:
00008 *
00009 * The above copyright notice and this permission notice shall be included in all copies or
00010 * substantial portions of the Software.
00011 *
00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00017 */
00018 
00019 #include "stdint.h"
00020 
00021 #include "USBEndpoints.h"
00022 #include "USBDevice.h"
00023 #include "USBDescriptor.h"
00024 
00025 //#define DEBUG
00026 
00027 /* Device status */
00028 #define DEVICE_STATUS_SELF_POWERED  (1U<<0)
00029 #define DEVICE_STATUS_REMOTE_WAKEUP (1U<<1)
00030 
00031 /* Endpoint status */
00032 #define ENDPOINT_STATUS_HALT        (1U<<0)
00033 
00034 /* Standard feature selectors */
00035 #define DEVICE_REMOTE_WAKEUP        (1)
00036 #define ENDPOINT_HALT               (0)
00037 
00038 /* Macro to convert wIndex endpoint number to physical endpoint number */
00039 #define WINDEX_TO_PHYSICAL(endpoint) (((endpoint & 0x0f) << 1) + \
00040                                       ((endpoint & 0x80) ? 1 : 0))
00041 
00042 
00043 bool USBDevice::requestGetDescriptor( void )
00044 {
00045     bool success = false;
00046 #ifdef DEBUG
00047     printf( "get descr: type: %d\r\n", DESCRIPTOR_TYPE( transfer.setup.wValue ) );
00048 #endif
00049 
00050     switch ( DESCRIPTOR_TYPE( transfer.setup.wValue ) )
00051     {
00052         case DEVICE_DESCRIPTOR:
00053             if ( deviceDesc() != NULL )
00054             {
00055                 if ( ( deviceDesc()[0] == DEVICE_DESCRIPTOR_LENGTH ) \
00056                         && ( deviceDesc()[1] == DEVICE_DESCRIPTOR ) )
00057                 {
00058 #ifdef DEBUG
00059                     printf( "device descr\r\n" );
00060 #endif
00061                     transfer.remaining = DEVICE_DESCRIPTOR_LENGTH;
00062                     transfer.ptr = deviceDesc();
00063                     transfer.direction = DEVICE_TO_HOST;
00064                     success = true;
00065                 }
00066             }
00067 
00068             break;
00069 
00070         case CONFIGURATION_DESCRIPTOR:
00071             if ( configurationDesc() != NULL )
00072             {
00073                 if ( ( configurationDesc()[0] == CONFIGURATION_DESCRIPTOR_LENGTH ) \
00074                         && ( configurationDesc()[1] == CONFIGURATION_DESCRIPTOR ) )
00075                 {
00076 #ifdef DEBUG
00077                     printf( "conf descr request\r\n" );
00078 #endif
00079                     /* Get wTotalLength */
00080                     transfer.remaining = configurationDesc()[2] \
00081                                          | ( configurationDesc()[3] << 8 );
00082                     transfer.ptr = configurationDesc();
00083                     transfer.direction = DEVICE_TO_HOST;
00084                     success = true;
00085                 }
00086             }
00087 
00088             break;
00089 
00090         case STRING_DESCRIPTOR:
00091 #ifdef DEBUG
00092             printf( "str descriptor\r\n" );
00093 #endif
00094 
00095             switch ( DESCRIPTOR_INDEX( transfer.setup.wValue ) )
00096             {
00097                 case STRING_OFFSET_LANGID:
00098 #ifdef DEBUG
00099                     printf( "1\r\n" );
00100 #endif
00101                     transfer.remaining = stringLangidDesc()[0];
00102                     transfer.ptr = stringLangidDesc();
00103                     transfer.direction = DEVICE_TO_HOST;
00104                     success = true;
00105                     break;
00106 
00107                 case STRING_OFFSET_IMANUFACTURER:
00108 #ifdef DEBUG
00109                     printf( "2\r\n" );
00110 #endif
00111                     transfer.remaining =  stringImanufacturerDesc()[0];
00112                     transfer.ptr = stringImanufacturerDesc();
00113                     transfer.direction = DEVICE_TO_HOST;
00114                     success = true;
00115                     break;
00116 
00117                 case STRING_OFFSET_IPRODUCT:
00118 #ifdef DEBUG
00119                     printf( "3\r\n" );
00120 #endif
00121                     transfer.remaining = stringIproductDesc()[0];
00122                     transfer.ptr = stringIproductDesc();
00123                     transfer.direction = DEVICE_TO_HOST;
00124                     success = true;
00125                     break;
00126 
00127                 case STRING_OFFSET_ISERIAL:
00128 #ifdef DEBUG
00129                     printf( "4\r\n" );
00130 #endif
00131                     transfer.remaining = stringIserialDesc()[0];
00132                     transfer.ptr = stringIserialDesc();
00133                     transfer.direction = DEVICE_TO_HOST;
00134                     success = true;
00135                     break;
00136 
00137                 case STRING_OFFSET_ICONFIGURATION:
00138 #ifdef DEBUG
00139                     printf( "5\r\n" );
00140 #endif
00141                     transfer.remaining = stringIConfigurationDesc()[0];
00142                     transfer.ptr = stringIConfigurationDesc();
00143                     transfer.direction = DEVICE_TO_HOST;
00144                     success = true;
00145                     break;
00146 
00147                 case STRING_OFFSET_IINTERFACE:
00148 #ifdef DEBUG
00149                     printf( "6\r\n" );
00150 #endif
00151                     transfer.remaining = stringIinterfaceDesc()[0];
00152                     transfer.ptr = stringIinterfaceDesc();
00153                     transfer.direction = DEVICE_TO_HOST;
00154                     success = true;
00155                     break;
00156             }
00157 
00158             break;
00159 
00160         case INTERFACE_DESCRIPTOR:
00161 #ifdef DEBUG
00162             printf( "interface descr\r\n" );
00163 #endif
00164 
00165         case ENDPOINT_DESCRIPTOR:
00166 #ifdef DEBUG
00167             printf( "endpoint descr\r\n" );
00168 #endif
00169             /* TODO: Support is optional, not implemented here */
00170             break;
00171 
00172         default:
00173 #ifdef DEBUG
00174             printf( "ERROR\r\n" );
00175 #endif
00176             break;
00177     }
00178 
00179     return success;
00180 }
00181 
00182 void USBDevice::decodeSetupPacket( uint8_t *data, SETUP_PACKET *packet )
00183 {
00184     /* Fill in the elements of a SETUP_PACKET structure from raw data */
00185     packet->bmRequestType.dataTransferDirection = ( data[0] & 0x80 ) >> 7;
00186     packet->bmRequestType.Type = ( data[0] & 0x60 ) >> 5;
00187     packet->bmRequestType.Recipient = data[0] & 0x1f;
00188     packet->bRequest = data[1];
00189     packet->wValue = ( data[2] | ( uint16_t )data[3] << 8 );
00190     packet->wIndex = ( data[4] | ( uint16_t )data[5] << 8 );
00191     packet->wLength = ( data[6] | ( uint16_t )data[7] << 8 );
00192 }
00193 
00194 
00195 bool USBDevice::controlOut( void )
00196 {
00197     /* Control transfer data OUT stage */
00198     uint8_t buffer[MAX_PACKET_SIZE_EP0];
00199     uint32_t packetSize;
00200 
00201     /* Check we should be transferring data OUT */
00202     if ( transfer.direction != HOST_TO_DEVICE )
00203     {
00204         return false;
00205     }
00206 
00207     /* Read from endpoint */
00208     packetSize = EP0getReadResult( buffer );
00209 
00210     /* Check if transfer size is valid */
00211     if ( packetSize > transfer.remaining )
00212     {
00213         /* Too big */
00214         return false;
00215     }
00216 
00217     /* Update transfer */
00218     transfer.ptr += packetSize;
00219     transfer.remaining -= packetSize;
00220 
00221     /* Check if transfer has completed */
00222     if ( transfer.remaining == 0 )
00223     {
00224         /* Transfer completed */
00225         if ( transfer.notify )
00226         {
00227             /* Notify class layer. */
00228             USBCallback_requestCompleted( buffer, packetSize );
00229             transfer.notify = false;
00230         }
00231 
00232         /* Status stage */
00233         EP0write( NULL, 0 );
00234     }
00235     else
00236     {
00237         EP0read();
00238     }
00239 
00240     return true;
00241 }
00242 
00243 bool USBDevice::controlIn( void )
00244 {
00245     /* Control transfer data IN stage */
00246     uint32_t packetSize;
00247 
00248     /* Check if transfer has completed (status stage transactions */
00249     /* also have transfer.remaining == 0) */
00250     if ( transfer.remaining == 0 )
00251     {
00252         if ( transfer.zlp )
00253         {
00254             /* Send zero length packet */
00255             EP0write( NULL, 0 );
00256             transfer.zlp = false;
00257         }
00258 
00259         /* Transfer completed */
00260         if ( transfer.notify )
00261         {
00262             /* Notify class layer. */
00263             USBCallback_requestCompleted( NULL, 0 );
00264             transfer.notify = false;
00265         }
00266 
00267         EP0read();
00268         /* Completed */
00269         return true;
00270     }
00271 
00272     /* Check we should be transferring data IN */
00273     if ( transfer.direction != DEVICE_TO_HOST )
00274     {
00275         return false;
00276     }
00277 
00278     packetSize = transfer.remaining;
00279 
00280     if ( packetSize > MAX_PACKET_SIZE_EP0 )
00281     {
00282         packetSize = MAX_PACKET_SIZE_EP0;
00283     }
00284 
00285     /* Write to endpoint */
00286     EP0write( transfer.ptr, packetSize );
00287     /* Update transfer */
00288     transfer.ptr += packetSize;
00289     transfer.remaining -= packetSize;
00290     return true;
00291 }
00292 
00293 bool USBDevice::requestSetAddress( void )
00294 {
00295     /* Set the device address */
00296     setAddress( transfer.setup.wValue );
00297 
00298     if ( transfer.setup.wValue == 0 )
00299     {
00300         device.state = DEFAULT;
00301     }
00302     else
00303     {
00304         device.state = ADDRESS;
00305     }
00306 
00307     return true;
00308 }
00309 
00310 bool USBDevice::requestSetConfiguration( void )
00311 {
00312     device.configuration = transfer.setup.wValue;
00313 
00314     /* Set the device configuration */
00315     if ( device.configuration == 0 )
00316     {
00317         /* Not configured */
00318         unconfigureDevice();
00319         device.state = ADDRESS;
00320     }
00321     else
00322     {
00323         if ( USBCallback_setConfiguration( device.configuration ) )
00324         {
00325             /* Valid configuration */
00326             configureDevice();
00327             device.state = CONFIGURED;
00328         }
00329         else
00330         {
00331             return false;
00332         }
00333     }
00334 
00335     return true;
00336 }
00337 
00338 bool USBDevice::requestGetConfiguration( void )
00339 {
00340     /* Send the device configuration */
00341     transfer.ptr = &device.configuration;
00342     transfer.remaining = sizeof( device.configuration );
00343     transfer.direction = DEVICE_TO_HOST;
00344     return true;
00345 }
00346 
00347 bool USBDevice::requestGetInterface( void )
00348 {
00349     /* Return the selected alternate setting for an interface */
00350     if ( device.state != CONFIGURED )
00351     {
00352         return false;
00353     }
00354 
00355     /* Send the alternate setting */
00356     transfer.setup.wIndex = currentInterface;
00357     transfer.ptr = &currentAlternate;
00358     transfer.remaining = sizeof( currentAlternate );
00359     transfer.direction = DEVICE_TO_HOST;
00360     return true;
00361 }
00362 
00363 bool USBDevice::requestSetInterface( void )
00364 {
00365     bool success = false;
00366 
00367     if( USBCallback_setInterface( transfer.setup.wIndex, transfer.setup.wValue ) )
00368     {
00369         success = true;
00370         currentInterface = transfer.setup.wIndex;
00371         currentAlternate = transfer.setup.wValue;
00372     }
00373 
00374     return success;
00375 }
00376 
00377 bool USBDevice::requestSetFeature()
00378 {
00379     bool success = false;
00380 
00381     if ( device.state != CONFIGURED )
00382     {
00383         /* Endpoint or interface must be zero */
00384         if ( transfer.setup.wIndex != 0 )
00385         {
00386             return false;
00387         }
00388     }
00389 
00390     switch ( transfer.setup.bmRequestType.Recipient )
00391     {
00392         case DEVICE_RECIPIENT:
00393             /* TODO: Remote wakeup feature not supported */
00394             break;
00395 
00396         case ENDPOINT_RECIPIENT:
00397             if ( transfer.setup.wValue == ENDPOINT_HALT )
00398             {
00399                 /* TODO: We should check that the endpoint number is valid */
00400                 stallEndpoint(
00401                     WINDEX_TO_PHYSICAL( transfer.setup.wIndex ) );
00402                 success = true;
00403             }
00404 
00405             break;
00406 
00407         default:
00408             break;
00409     }
00410 
00411     return success;
00412 }
00413 
00414 bool USBDevice::requestClearFeature()
00415 {
00416     bool success = false;
00417 
00418     if ( device.state != CONFIGURED )
00419     {
00420         /* Endpoint or interface must be zero */
00421         if ( transfer.setup.wIndex != 0 )
00422         {
00423             return false;
00424         }
00425     }
00426 
00427     switch ( transfer.setup.bmRequestType.Recipient )
00428     {
00429         case DEVICE_RECIPIENT:
00430             /* TODO: Remote wakeup feature not supported */
00431             break;
00432 
00433         case ENDPOINT_RECIPIENT:
00434 
00435             /* TODO: We should check that the endpoint number is valid */
00436             if ( transfer.setup.wValue == ENDPOINT_HALT )
00437             {
00438                 unstallEndpoint( WINDEX_TO_PHYSICAL( transfer.setup.wIndex ) );
00439                 success = true;
00440             }
00441 
00442             break;
00443 
00444         default:
00445             break;
00446     }
00447 
00448     return success;
00449 }
00450 
00451 bool USBDevice::requestGetStatus( void )
00452 {
00453     static uint16_t status;
00454     bool success = false;
00455 
00456     if ( device.state != CONFIGURED )
00457     {
00458         /* Endpoint or interface must be zero */
00459         if ( transfer.setup.wIndex != 0 )
00460         {
00461             return false;
00462         }
00463     }
00464 
00465     switch ( transfer.setup.bmRequestType.Recipient )
00466     {
00467         case DEVICE_RECIPIENT:
00468             /* TODO: Currently only supports self powered devices */
00469             status = DEVICE_STATUS_SELF_POWERED;
00470             success = true;
00471             break;
00472 
00473         case INTERFACE_RECIPIENT:
00474             status = 0;
00475             success = true;
00476             break;
00477 
00478         case ENDPOINT_RECIPIENT:
00479 
00480             /* TODO: We should check that the endpoint number is valid */
00481             if ( getEndpointStallState(
00482                         WINDEX_TO_PHYSICAL( transfer.setup.wIndex ) ) )
00483             {
00484                 status = ENDPOINT_STATUS_HALT;
00485             }
00486             else
00487             {
00488                 status = 0;
00489             }
00490 
00491             success = true;
00492             break;
00493 
00494         default:
00495             break;
00496     }
00497 
00498     if ( success )
00499     {
00500         /* Send the status */
00501         transfer.ptr = ( uint8_t * )&status; /* Assumes little endian */
00502         transfer.remaining = sizeof( status );
00503         transfer.direction = DEVICE_TO_HOST;
00504     }
00505 
00506     return success;
00507 }
00508 
00509 bool USBDevice::requestSetup( void )
00510 {
00511     bool success = false;
00512 
00513     /* Process standard requests */
00514     if ( ( transfer.setup.bmRequestType.Type == STANDARD_TYPE ) )
00515     {
00516         switch ( transfer.setup.bRequest )
00517         {
00518             case GET_STATUS:
00519                 success = requestGetStatus();
00520                 break;
00521 
00522             case CLEAR_FEATURE:
00523                 success = requestClearFeature();
00524                 break;
00525 
00526             case SET_FEATURE:
00527                 success = requestSetFeature();
00528                 break;
00529 
00530             case SET_ADDRESS:
00531                 success = requestSetAddress();
00532                 break;
00533 
00534             case GET_DESCRIPTOR:
00535                 success = requestGetDescriptor();
00536                 break;
00537 
00538             case SET_DESCRIPTOR:
00539                 /* TODO: Support is optional, not implemented here */
00540                 success = false;
00541                 break;
00542 
00543             case GET_CONFIGURATION:
00544                 success = requestGetConfiguration();
00545                 break;
00546 
00547             case SET_CONFIGURATION:
00548                 success = requestSetConfiguration();
00549                 break;
00550 
00551             case GET_INTERFACE:
00552                 success = requestGetInterface();
00553                 break;
00554 
00555             case SET_INTERFACE:
00556                 success = requestSetInterface();
00557                 break;
00558 
00559             default:
00560                 break;
00561         }
00562     }
00563 
00564     return success;
00565 }
00566 
00567 bool USBDevice::controlSetup( void )
00568 {
00569     bool success = false;
00570     /* Control transfer setup stage */
00571     uint8_t buffer[MAX_PACKET_SIZE_EP0];
00572     EP0setup( buffer );
00573     /* Initialise control transfer state */
00574     decodeSetupPacket( buffer, &transfer.setup );
00575     transfer.ptr = NULL;
00576     transfer.remaining = 0;
00577     transfer.direction = 0;
00578     transfer.zlp = false;
00579     transfer.notify = false;
00580 #ifdef DEBUG
00581     printf( "dataTransferDirection: %d\r\nType: %d\r\nRecipient: %d\r\nbRequest: %d\r\nwValue: %d\r\nwIndex: %d\r\nwLength: %d\r\n", transfer.setup.bmRequestType.dataTransferDirection,
00582             transfer.setup.bmRequestType.Type,
00583             transfer.setup.bmRequestType.Recipient,
00584             transfer.setup.bRequest,
00585             transfer.setup.wValue,
00586             transfer.setup.wIndex,
00587             transfer.setup.wLength );
00588 #endif
00589     /* Class / vendor specific */
00590     success = USBCallback_request();
00591 
00592     if ( !success )
00593     {
00594         /* Standard requests */
00595         if ( !requestSetup() )
00596         {
00597 #ifdef DEBUG
00598             printf( "fail!!!!\r\n" );
00599 #endif
00600             return false;
00601         }
00602     }
00603 
00604     /* Check transfer size and direction */
00605     if ( transfer.setup.wLength > 0 )
00606     {
00607         if ( transfer.setup.bmRequestType.dataTransferDirection \
00608                 == DEVICE_TO_HOST )
00609         {
00610             /* IN data stage is required */
00611             if ( transfer.direction != DEVICE_TO_HOST )
00612             {
00613                 return false;
00614             }
00615 
00616             /* Transfer must be less than or equal to the size */
00617             /* requested by the host */
00618             if ( transfer.remaining > transfer.setup.wLength )
00619             {
00620                 transfer.remaining = transfer.setup.wLength;
00621             }
00622         }
00623         else
00624         {
00625             /* OUT data stage is required */
00626             if ( transfer.direction != HOST_TO_DEVICE )
00627             {
00628                 return false;
00629             }
00630 
00631             /* Transfer must be equal to the size requested by the host */
00632             if ( transfer.remaining != transfer.setup.wLength )
00633             {
00634                 return false;
00635             }
00636         }
00637     }
00638     else
00639     {
00640         /* No data stage; transfer size must be zero */
00641         if ( transfer.remaining != 0 )
00642         {
00643             return false;
00644         }
00645     }
00646 
00647     /* Data or status stage if applicable */
00648     if ( transfer.setup.wLength > 0 )
00649     {
00650         if ( transfer.setup.bmRequestType.dataTransferDirection \
00651                 == DEVICE_TO_HOST )
00652         {
00653             /* Check if we'll need to send a zero length packet at */
00654             /* the end of this transfer */
00655             if ( transfer.setup.wLength > transfer.remaining )
00656             {
00657                 /* Device wishes to transfer less than host requested */
00658                 if ( ( transfer.remaining % MAX_PACKET_SIZE_EP0 ) == 0 )
00659                 {
00660                     /* Transfer is a multiple of EP0 max packet size */
00661                     transfer.zlp = true;
00662                 }
00663             }
00664 
00665             /* IN stage */
00666             controlIn();
00667         }
00668         else
00669         {
00670             /* OUT stage */
00671             EP0read();
00672         }
00673     }
00674     else
00675     {
00676         /* Status stage */
00677         EP0write( NULL, 0 );
00678     }
00679 
00680     return true;
00681 }
00682 
00683 void USBDevice::busReset( void )
00684 {
00685     device.state = DEFAULT;
00686     device.configuration = 0;
00687     device.suspended = false;
00688     /* Call class / vendor specific busReset function */
00689     USBCallback_busReset();
00690 }
00691 
00692 void USBDevice::EP0setupCallback( void )
00693 {
00694     /* Endpoint 0 setup event */
00695     if ( !controlSetup() )
00696     {
00697         /* Protocol stall */
00698         EP0stall();
00699     }
00700 
00701     /* Return true if an OUT data stage is expected */
00702 }
00703 
00704 void USBDevice::EP0out( void )
00705 {
00706     /* Endpoint 0 OUT data event */
00707     if ( !controlOut() )
00708     {
00709         /* Protocol stall; this will stall both endpoints */
00710         EP0stall();
00711     }
00712 }
00713 
00714 void USBDevice::EP0in( void )
00715 {
00716 #ifdef DEBUG
00717     printf( "EP0IN\r\n" );
00718 #endif
00719 
00720     /* Endpoint 0 IN data event */
00721     if ( !controlIn() )
00722     {
00723         /* Protocol stall; this will stall both endpoints */
00724         EP0stall();
00725     }
00726 }
00727 
00728 bool USBDevice::configured( void )
00729 {
00730     /* Returns true if device is in the CONFIGURED state */
00731     return ( device.state == CONFIGURED );
00732 }
00733 
00734 void USBDevice::connect( void )
00735 {
00736     /* Connect device */
00737     USBHAL::connect();
00738 
00739     /* Block if not configured */
00740     while ( !configured() );
00741 }
00742 
00743 void USBDevice::disconnect( void )
00744 {
00745     /* Disconnect device */
00746     USBHAL::disconnect();
00747 }
00748 
00749 CONTROL_TRANSFER *USBDevice::getTransferPtr( void )
00750 {
00751     return &transfer;
00752 }
00753 
00754 bool USBDevice::addEndpoint( uint8_t endpoint, uint32_t maxPacket )
00755 {
00756     return realiseEndpoint( endpoint, maxPacket, 0 );
00757 }
00758 
00759 bool USBDevice::addRateFeedbackEndpoint( uint8_t endpoint, uint32_t maxPacket )
00760 {
00761     /* For interrupt endpoints only */
00762     return realiseEndpoint( endpoint, maxPacket, RATE_FEEDBACK_MODE );
00763 }
00764 
00765 uint8_t *USBDevice::findDescriptor( uint8_t descriptorType )
00766 {
00767     /* Find a descriptor within the list of descriptors */
00768     /* following a configuration descriptor. */
00769     uint16_t wTotalLength;
00770     uint8_t *ptr;
00771 
00772     if ( configurationDesc() == NULL )
00773     {
00774         return NULL;
00775     }
00776 
00777     /* Check this is a configuration descriptor */
00778     if ( ( configurationDesc()[0] != CONFIGURATION_DESCRIPTOR_LENGTH ) \
00779             || ( configurationDesc()[1] != CONFIGURATION_DESCRIPTOR ) )
00780     {
00781         return NULL;
00782     }
00783 
00784     wTotalLength = configurationDesc()[2] | ( configurationDesc()[3] << 8 );
00785 
00786     /* Check there are some more descriptors to follow */
00787     if ( wTotalLength <= ( CONFIGURATION_DESCRIPTOR_LENGTH + 2 ) )
00788         /* +2 is for bLength and bDescriptorType of next descriptor */
00789     {
00790         return false;
00791     }
00792 
00793     /* Start at first descriptor after the configuration descriptor */
00794     ptr = &( configurationDesc()[CONFIGURATION_DESCRIPTOR_LENGTH] );
00795 
00796     do
00797     {
00798         if ( ptr[1] /* bDescriptorType */ == descriptorType )
00799         {
00800             /* Found */
00801             return ptr;
00802         }
00803 
00804         /* Skip to next descriptor */
00805         ptr += ptr[0]; /* bLength */
00806     }
00807     while ( ptr < ( configurationDesc() + wTotalLength ) );
00808 
00809     /* Reached end of the descriptors - not found */
00810     return NULL;
00811 }
00812 
00813 
00814 void USBDevice::connectStateChanged( unsigned int connected )
00815 {
00816 }
00817 
00818 void USBDevice::suspendStateChanged( unsigned int suspended )
00819 {
00820 }
00821 
00822 
00823 USBDevice::USBDevice( uint16_t vendor_id, uint16_t product_id, uint16_t product_release )
00824 {
00825     VENDOR_ID = vendor_id;
00826     PRODUCT_ID = product_id;
00827     PRODUCT_RELEASE = product_release;
00828     /* Set initial device state */
00829     device.state = POWERED;
00830     device.configuration = 0;
00831     device.suspended = false;
00832 };
00833 
00834 
00835 bool USBDevice::readStart( uint8_t endpoint, uint32_t maxSize )
00836 {
00837     return endpointRead( endpoint, maxSize ) == EP_PENDING;
00838 }
00839 
00840 
00841 bool USBDevice::write( uint8_t endpoint, uint8_t *buffer, uint32_t size, uint32_t maxSize )
00842 {
00843     EP_STATUS result;
00844 
00845     if ( size > maxSize )
00846     {
00847         return false;
00848     }
00849 
00850     if( !configured() )
00851     {
00852         return false;
00853     }
00854 
00855     /* Send report */
00856     result = endpointWrite( endpoint, buffer, size );
00857 
00858     if ( result != EP_PENDING )
00859     {
00860         return false;
00861     }
00862 
00863     /* Wait for completion */
00864     do
00865     {
00866         result = endpointWriteResult( endpoint );
00867     }
00868     while ( ( result == EP_PENDING ) && configured() );
00869 
00870     return ( result == EP_COMPLETED );
00871 }
00872 
00873 
00874 bool USBDevice::writeNB( uint8_t endpoint, uint8_t *buffer, uint32_t size, uint32_t maxSize )
00875 {
00876     EP_STATUS result;
00877 
00878     if ( size > maxSize )
00879     {
00880         return false;
00881     }
00882 
00883     if( !configured() )
00884     {
00885         return false;
00886     }
00887 
00888     /* Send report */
00889     result = endpointWrite( endpoint, buffer, size );
00890 
00891     if ( result != EP_PENDING )
00892     {
00893         return false;
00894     }
00895 
00896     result = endpointWriteResult( endpoint );
00897     return ( result == EP_COMPLETED );
00898 }
00899 
00900 
00901 
00902 bool USBDevice::readEP( uint8_t endpoint, uint8_t *buffer, uint32_t *size, uint32_t maxSize )
00903 {
00904     EP_STATUS result;
00905 
00906     if( !configured() )
00907     {
00908         return false;
00909     }
00910 
00911     /* Wait for completion */
00912     do
00913     {
00914         result = endpointReadResult( endpoint, buffer, size );
00915     }
00916     while ( ( result == EP_PENDING ) && configured() );
00917 
00918     return ( result == EP_COMPLETED );
00919 }
00920 
00921 
00922 bool USBDevice::readEP_NB( uint8_t endpoint, uint8_t *buffer, uint32_t *size, uint32_t maxSize )
00923 {
00924     EP_STATUS result;
00925 
00926     if( !configured() )
00927     {
00928         return false;
00929     }
00930 
00931     result = endpointReadResult( endpoint, buffer, size );
00932     return ( result == EP_COMPLETED );
00933 }
00934 
00935 
00936 
00937 uint8_t *USBDevice::deviceDesc()
00938 {
00939     static uint8_t deviceDescriptor[] =
00940     {
00941         DEVICE_DESCRIPTOR_LENGTH,       /* bLength */
00942         DEVICE_DESCRIPTOR,              /* bDescriptorType */
00943         LSB( USB_VERSION_2_0 ),         /* bcdUSB (LSB) */
00944         MSB( USB_VERSION_2_0 ),         /* bcdUSB (MSB) */
00945         0x00,                           /* bDeviceClass */
00946         0x00,                           /* bDeviceSubClass */
00947         0x00,                           /* bDeviceprotocol */
00948         MAX_PACKET_SIZE_EP0,            /* bMaxPacketSize0 */
00949         LSB( VENDOR_ID ),               /* idVendor (LSB) */
00950         MSB( VENDOR_ID ),               /* idVendor (MSB) */
00951         LSB( PRODUCT_ID ),              /* idProduct (LSB) */
00952         MSB( PRODUCT_ID ),              /* idProduct (MSB) */
00953         LSB( PRODUCT_RELEASE ),         /* bcdDevice (LSB) */
00954         MSB( PRODUCT_RELEASE ),         /* bcdDevice (MSB) */
00955         STRING_OFFSET_IMANUFACTURER,    /* iManufacturer */
00956         STRING_OFFSET_IPRODUCT,         /* iProduct */
00957         STRING_OFFSET_ISERIAL,          /* iSerialNumber */
00958         0x01                            /* bNumConfigurations */
00959     };
00960     return deviceDescriptor;
00961 }
00962 
00963 uint8_t *USBDevice::stringLangidDesc()
00964 {
00965     static uint8_t stringLangidDescriptor[] =
00966     {
00967         0x04,               /*bLength*/
00968         STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
00969         0x09, 0x00,         /*bString Lang ID - 0x009 - English*/
00970     };
00971     return stringLangidDescriptor;
00972 }
00973 
00974 uint8_t *USBDevice::stringImanufacturerDesc()
00975 {
00976     static uint8_t stringImanufacturerDescriptor[] =
00977     {
00978         0x12,                                            /*bLength*/
00979         STRING_DESCRIPTOR,                               /*bDescriptorType 0x03*/
00980         'm', 0, 'b', 0, 'e', 0, 'd', 0, '.', 0, 'o', 0, 'r', 0, 'g', 0, /*bString iManufacturer - mbed.org*/
00981     };
00982     return stringImanufacturerDescriptor;
00983 }
00984 
00985 uint8_t *USBDevice::stringIserialDesc()
00986 {
00987     static uint8_t stringIserialDescriptor[] =
00988     {
00989         0x16,                                                           /*bLength*/
00990         STRING_DESCRIPTOR,                                              /*bDescriptorType 0x03*/
00991         '0', 0, '1', 0, '2', 0, '3', 0, '4', 0, '5', 0, '6', 0, '7', 0, '8', 0, '9', 0, /*bString iSerial - 0123456789*/
00992     };
00993     return stringIserialDescriptor;
00994 }
00995 
00996 uint8_t *USBDevice::stringIConfigurationDesc()
00997 {
00998     static uint8_t stringIconfigurationDescriptor[] =
00999     {
01000         0x06,               /*bLength*/
01001         STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
01002         '0', 0, '1', 0,     /*bString iConfiguration - 01*/
01003     };
01004     return stringIconfigurationDescriptor;
01005 }
01006 
01007 uint8_t *USBDevice::stringIinterfaceDesc()
01008 {
01009     static uint8_t stringIinterfaceDescriptor[] =
01010     {
01011         0x08,               /*bLength*/
01012         STRING_DESCRIPTOR,  /*bDescriptorType 0x03*/
01013         'U', 0, 'S', 0, 'B', 0, /*bString iInterface - USB*/
01014     };
01015     return stringIinterfaceDescriptor;
01016 }
01017 
01018 uint8_t *USBDevice::stringIproductDesc()
01019 {
01020     static uint8_t stringIproductDescriptor[] =
01021     {
01022         0x16,                                                       /*bLength*/
01023         STRING_DESCRIPTOR,                                          /*bDescriptorType 0x03*/
01024         'U', 0, 'S', 0, 'B', 0, ' ', 0, 'D', 0, 'E', 0, 'V', 0, 'I', 0, 'C', 0, 'E', 0 /*bString iProduct - USB DEVICE*/
01025     };
01026     return stringIproductDescriptor;
01027 }
01028