A optical beam breaker detector that appears to aPC as a USB keyboard, typing characters when the beam is broken
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 }
Generated on Tue Jul 12 2022 17:09:08 by 1.7.2