A optical beam breaker detector that appears to aPC as a USB keyboard, typing characters when the beam is broken

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbdevice.cpp Source File

usbdevice.cpp

00001 /* usbdevice.cpp */
00002 /* Generic USB device */
00003 /* Copyright (c) Phil Wright 2008 */
00004 
00005 #include "mbed.h"
00006 #include "usbdevice.h"
00007 
00008 /* Standard requests */
00009 #define GET_STATUS        (0)
00010 #define CLEAR_FEATURE     (1)
00011 #define SET_FEATURE       (3)
00012 #define SET_ADDRESS       (5)
00013 #define GET_DESCRIPTOR    (6)
00014 #define SET_DESCRIPTOR    (7)
00015 #define GET_CONFIGURATION (8)
00016 #define SET_CONFIGURATION (9)
00017 #define GET_INTERFACE     (10)
00018 #define SET_INTERFACE     (11)
00019 
00020 /* Device status */
00021 #define DEVICE_STATUS_SELF_POWERED  (1<<0)
00022 #define DEVICE_STATUS_REMOTE_WAKEUP (1<<1)
00023 
00024 /* Endpoint status */
00025 #define ENDPOINT_STATUS_HALT        (1<<0)
00026 
00027 /* Standard feature selectors */
00028 #define DEVICE_REMOTE_WAKEUP        (1)
00029 #define ENDPOINT_HALT               (0)
00030 
00031 /* Macro to convert wIndex endpoint number to physical endpoint number */
00032 #define WINDEX_TO_PHYSICAL(endpoint) (((endpoint & 0x0f) << 1) + ((endpoint & 0x80) ? 1 : 0))
00033 
00034 CONTROL_TRANSFER transfer;
00035 USB_DEVICE device;
00036     
00037 usbdevice::usbdevice()
00038 {
00039     /* Set initial device state */
00040     device.state = POWERED;
00041     device.configuration = 0;
00042     device.suspended = false;
00043     
00044     /* Set the maximum packet size for the control endpoints */
00045     realiseEndpoint(EP0IN, MAX_PACKET_SIZE_EP0);
00046     realiseEndpoint(EP0OUT, MAX_PACKET_SIZE_EP0);
00047     
00048     /* Enable endpoint events for EP0 */
00049     enableEndpointEvent(EP0IN);
00050     enableEndpointEvent(EP0OUT);
00051 }
00052 
00053 void usbdevice::endpointEventEP0Setup(void)
00054 {
00055     /* Endpoint 0 setup event */
00056     if (!controlSetup())
00057     {    
00058         /* Protocol stall; this will stall both endpoints */
00059         stallEndpoint(EP0OUT);
00060     }
00061 }
00062 
00063 void usbdevice::endpointEventEP0Out(void)
00064 {
00065     /* Endpoint 0 OUT data event */
00066     if (!controlOut())
00067     {    
00068         /* Protocol stall; this will stall both endpoints */
00069         stallEndpoint(EP0OUT);
00070     }    
00071 }
00072 
00073 void usbdevice::endpointEventEP0In(void)
00074 {
00075     /* Endpoint 0 IN data event */
00076     if (!controlIn())
00077     {    
00078         /* Protocol stall; this will stall both endpoints */
00079         stallEndpoint(EP0OUT);
00080     }
00081 }
00082 
00083 void usbdevice::deviceEventReset(void)
00084 {
00085     device.state = DEFAULT;
00086     device.configuration = 0;
00087     device.suspended = false;
00088 }
00089 
00090 void usbdevice::decodeSetupPacket(unsigned char *data, SETUP_PACKET *packet)
00091 {
00092     /* Fill in the elements of a SETUP_PACKET structure from raw data */
00093     packet->bmRequestType.dataTransferDirection = (data[0] & 0x80) >> 7;
00094     packet->bmRequestType.Type = (data[0] & 0x60) >> 5;
00095     packet->bmRequestType.Recipient = data[0] & 0x1f;
00096     packet->bRequest = data[1];
00097     packet->wValue = (data[2] | (unsigned short)data[3] << 8);
00098     packet->wIndex = (data[4] | (unsigned short)data[5] << 8);
00099     packet->wLength = (data[6] | (unsigned short)data[7] << 8);
00100 }
00101 
00102 bool usbdevice::controlSetup(void)
00103 {
00104     /* Control transfer setup stage */
00105     unsigned char buffer[MAX_PACKET_SIZE_EP0];
00106     unsigned long count;
00107 
00108     count = endpointRead(EP0OUT, buffer);
00109     
00110     /* Must be 8 bytes of data */
00111     if (count != 8)
00112     {    
00113         return false;
00114     }
00115     
00116     /* Initialise control transfer state */
00117     decodeSetupPacket(buffer, &transfer.setup);        
00118     transfer.ptr = NULL;
00119     transfer.remaining = 0;
00120     transfer.direction = 0;
00121     transfer.zlp = false;
00122     
00123     /* Process request */
00124     if (!requestSetup())
00125     {
00126         return false;
00127     }
00128 
00129     /* Check transfer size and direction  */
00130     if (transfer.setup.wLength>0)
00131     {
00132         if (transfer.setup.bmRequestType.dataTransferDirection==DEVICE_TO_HOST)
00133         {
00134             /* IN data stage is required */
00135             if (transfer.direction != DEVICE_TO_HOST)
00136             {
00137                 return false;
00138             }
00139             
00140             /* Transfer must be less than or equal to the size requested by the host */
00141             if (transfer.remaining > transfer.setup.wLength)
00142             {
00143                 transfer.remaining = transfer.setup.wLength;
00144             }
00145         }
00146         else
00147         {
00148             /* OUT data stage is required */
00149             if (transfer.direction != HOST_TO_DEVICE)
00150             {
00151                 return false;
00152             }
00153             
00154             /* Transfer must be equal to the size requested by the host */
00155             if (transfer.remaining != transfer.setup.wLength)
00156             {
00157                 return false;
00158             }
00159         }
00160     }
00161     else
00162     {
00163         /* No data stage; transfer size must be zero */
00164         if (transfer.remaining != 0)
00165         {
00166             return false;
00167         }
00168     }                
00169     
00170     /* Data or status stage if applicable */
00171     if (transfer.setup.wLength>0)
00172     {
00173         if (transfer.setup.bmRequestType.dataTransferDirection==DEVICE_TO_HOST)
00174         {            
00175             /* Check if we'll need to send a zero length packet at the end of this transfer */
00176             if (transfer.setup.wLength > transfer.remaining)
00177             {
00178                 /* Device wishes to transfer less than host requested */
00179                 if ((transfer.remaining % MAX_PACKET_SIZE_EP0) == 0)
00180                 {
00181                     /* Transfer is a multiple of EP0 max packet size */
00182                     transfer.zlp = true;
00183                 }            
00184             }
00185             
00186             /* IN stage */
00187             controlIn();
00188         }
00189     }
00190     else
00191     {
00192         /* Status stage */
00193         endpointWrite(EP0IN, NULL, 0);
00194     }
00195     
00196     return true;
00197 }
00198 
00199 bool usbdevice::controlOut(void)
00200 {    
00201     /* Control transfer data OUT stage */
00202     unsigned char buffer[MAX_PACKET_SIZE_EP0];
00203     unsigned long packetSize;
00204 
00205     /* Check we should be transferring data OUT */
00206     if (transfer.direction != HOST_TO_DEVICE)
00207     {
00208         return false;
00209     }
00210     
00211     /* Read from endpoint */
00212     packetSize = endpointRead(EP0OUT, buffer);
00213     
00214     /* Check if transfer size is valid */
00215     if (packetSize > transfer.remaining)
00216     {
00217         /* Too big */
00218         return false;
00219     }
00220     
00221     /* Update transfer */
00222     transfer.ptr += packetSize;
00223     transfer.remaining -= packetSize;
00224     
00225     /* Check if transfer has completed */
00226     if (transfer.remaining == 0)
00227     {
00228         /* Process request */        
00229         if (!requestOut())
00230         {
00231             return false;
00232         }
00233         
00234         /* Status stage */
00235         endpointWrite(EP0IN, NULL, 0);
00236     }
00237     
00238     return true;
00239 }
00240 
00241 bool usbdevice::controlIn(void)
00242 {
00243     /* Control transfer data IN stage */    
00244     unsigned packetSize;
00245     
00246     /* Check if transfer has completed (status stage transactions also have transfer.remaining == 0) */
00247     if (transfer.remaining == 0)
00248     {
00249         if (transfer.zlp)
00250         {
00251             /* Send zero length packet */
00252             endpointWrite(EP0IN, NULL, 0);
00253             transfer.zlp = false;
00254         }
00255         
00256         /* Completed */
00257         return true;
00258     }
00259     
00260     /* Check we should be transferring data IN */
00261     if (transfer.direction != DEVICE_TO_HOST)
00262     {
00263         return false;
00264     }
00265     
00266     packetSize = transfer.remaining;
00267     
00268     if (packetSize > MAX_PACKET_SIZE_EP0)
00269     {
00270         packetSize = MAX_PACKET_SIZE_EP0;
00271     }
00272     
00273     /* Write to endpoint */
00274     endpointWrite(EP0IN, transfer.ptr, packetSize);
00275     
00276     /* Update transfer */
00277     transfer.ptr += packetSize;
00278     transfer.remaining -= packetSize;
00279     
00280     return true;
00281 }
00282 
00283 bool usbdevice::requestSetup(void)
00284 {
00285     bool success = false;
00286 
00287     /* Process standard requests */
00288     if ((transfer.setup.bmRequestType.Type == STANDARD_TYPE))
00289     {
00290         switch (transfer.setup.bRequest)
00291         {
00292              case GET_STATUS:
00293                  success = requestGetStatus();
00294                  break;
00295              case CLEAR_FEATURE:
00296                  success = requestClearFeature();
00297                  break;
00298              case SET_FEATURE:
00299                  success = requestSetFeature();
00300                  break;
00301              case SET_ADDRESS:
00302                 success = requestSetAddress();
00303                  break;    
00304              case GET_DESCRIPTOR:
00305                  success = requestGetDescriptor();
00306                  break;
00307              case SET_DESCRIPTOR:
00308                  /* TODO: Support is optional, not implemented here */
00309                  success = false;
00310                  break;
00311              case GET_CONFIGURATION:
00312                  success = requestGetConfiguration();
00313                  break;
00314              case SET_CONFIGURATION:
00315                  success = requestSetConfiguration();
00316                  break;
00317              case GET_INTERFACE:
00318                  success = requestGetInterface();
00319                  break;
00320              case SET_INTERFACE:
00321                  success = requestSetInterface();
00322                  break;
00323              default:
00324                  break;
00325         }
00326     }
00327     
00328     return success;
00329 }
00330 
00331 bool usbdevice::requestOut(void)
00332 {
00333     return true;
00334 }
00335 
00336 bool usbdevice::requestSetAddress(void)
00337 {
00338     /* Set the device address */
00339     setAddress(transfer.setup.wValue);    
00340     
00341     if (transfer.setup.wValue == 0)
00342     {
00343         device.state = DEFAULT;
00344     }
00345     else
00346     {
00347         device.state = ADDRESS;
00348     }
00349         
00350     return true;
00351 }
00352 
00353 bool usbdevice::requestSetConfiguration(void)
00354 {
00355     /* Set the device configuration */    
00356     if (transfer.setup.wValue == 0)
00357     {
00358         /* Not configured */
00359         unconfigureDevice();
00360         device.state = ADDRESS;
00361     }
00362     else
00363     {
00364         configureDevice();
00365         device.state = CONFIGURED;
00366     }
00367     
00368     /* TODO: We do not currently support multiple configurations, just keep a record of the configuration value */
00369     device.configuration = transfer.setup.wValue;
00370     
00371     return true;
00372 }
00373 
00374 bool usbdevice::requestGetConfiguration(void)
00375 {
00376     /* Send the device configuration */
00377     transfer.ptr = &device.configuration;
00378     transfer.remaining = sizeof(device.configuration);
00379     transfer.direction = DEVICE_TO_HOST;
00380     return true;
00381 }
00382 
00383 bool usbdevice::requestGetInterface(void)
00384 {
00385     static unsigned char alternateSetting;
00386     
00387     /* Return the selected alternate setting for an interface */
00388     
00389     if (device.state != CONFIGURED)
00390     {
00391         return false;
00392     }
00393     
00394     /* TODO: We currently do not support alternate settings so always return zero */
00395     /* TODO: Should check that the interface number is valid */    
00396     alternateSetting = 0;
00397     
00398     /* Send the alternate setting */
00399     transfer.ptr = &alternateSetting;
00400     transfer.remaining = sizeof(alternateSetting);
00401     transfer.direction = DEVICE_TO_HOST;
00402     return true;    
00403 }
00404 
00405 bool usbdevice::requestSetInterface(void)
00406 {
00407     /* TODO: We currently do not support alternate settings, return false */
00408     return false;
00409 }    
00410 
00411 bool usbdevice::requestSetFeature()
00412 {
00413     bool success = false;
00414     
00415     if (device.state != CONFIGURED)
00416     {
00417         /* Endpoint or interface must be zero */
00418         if (transfer.setup.wIndex != 0)
00419         {
00420             return false;
00421         }
00422     }
00423     
00424     switch (transfer.setup.bmRequestType.Recipient)
00425     {
00426         case DEVICE_RECIPIENT:
00427             /* TODO: Remote wakeup feature not supported */
00428             break;
00429         case ENDPOINT_RECIPIENT:    
00430             if (transfer.setup.wValue == ENDPOINT_HALT)
00431             {
00432                 /* TODO: We should check that the endpoint number is valid */
00433                 stallEndpoint(WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
00434                 success = true;
00435             }            
00436             break;
00437         default:
00438             break;
00439     }
00440     
00441     return success;
00442 }
00443 
00444 bool usbdevice::requestClearFeature()
00445 {
00446     bool success = false;
00447     
00448     if (device.state != CONFIGURED)
00449     {
00450         /* Endpoint or interface must be zero */
00451         if (transfer.setup.wIndex != 0)
00452         {
00453             return false;
00454         }
00455     }
00456     
00457     switch (transfer.setup.bmRequestType.Recipient)
00458     {
00459         case DEVICE_RECIPIENT:
00460             /* TODO: Remote wakeup feature not supported */
00461             break;
00462         case ENDPOINT_RECIPIENT:
00463             /* TODO: We should check that the endpoint number is valid */    
00464             if (transfer.setup.wValue == ENDPOINT_HALT)
00465             {
00466                 unstallEndpoint(WINDEX_TO_PHYSICAL(transfer.setup.wIndex));
00467                 success = true;
00468             }            
00469             break;
00470         default:
00471             break;
00472     }
00473     
00474     return success;
00475 }
00476 
00477 bool usbdevice::requestGetStatus(void)
00478 {
00479     static unsigned short status;
00480     bool success = false;
00481     
00482     if (device.state != CONFIGURED)
00483     {
00484         /* Endpoint or interface must be zero */
00485         if (transfer.setup.wIndex != 0)
00486         {
00487             return false;
00488         }
00489     }
00490     
00491     switch (transfer.setup.bmRequestType.Recipient)
00492     {
00493         case DEVICE_RECIPIENT:
00494             /* TODO: Currently only supports self powered devices */
00495             status = DEVICE_STATUS_SELF_POWERED;
00496             success = true;
00497             break;
00498         case INTERFACE_RECIPIENT:
00499             status = 0;
00500             success = true;
00501             break;
00502         case ENDPOINT_RECIPIENT:
00503             /* TODO: We should check that the endpoint number is valid */
00504             if (getEndpointStallState(WINDEX_TO_PHYSICAL(transfer.setup.wIndex)))
00505             {
00506                 status = ENDPOINT_STATUS_HALT;
00507             }
00508             else
00509             {
00510                 status = 0;
00511             } 
00512             success = true;
00513             break;
00514         default:
00515             break;
00516     }
00517     
00518     if (success)
00519     {
00520         /* Send the status */ 
00521         transfer.ptr = (unsigned char *)&status; /* Assumes little endian */
00522         transfer.remaining = sizeof(status); 
00523         transfer.direction = DEVICE_TO_HOST;
00524     }
00525     
00526     return success;
00527 }
00528 
00529 bool usbdevice::requestGetDescriptor(void)
00530 {
00531     return false;
00532 }