Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 19:23:02 by
