Chris Styles
/
USB-A
Example program using USB A
Embed:
(wiki syntax)
Show/hide line numbers
usbhost_ms.c
00001 /* 00002 ************************************************************************************************************** 00003 * NXP USB Host Stack 00004 * 00005 * (c) Copyright 2008, NXP SemiConductors 00006 * (c) Copyright 2008, OnChip Technologies LLC 00007 * All Rights Reserved 00008 * 00009 * www.nxp.com 00010 * www.onchiptech.com 00011 * 00012 * File : usbhost_ms.c 00013 * Programmer(s) : Ravikanth.P 00014 * Version : 00015 * 00016 ************************************************************************************************************** 00017 */ 00018 00019 /* 00020 ************************************************************************************************************** 00021 * INCLUDE HEADER FILES 00022 ************************************************************************************************************** 00023 */ 00024 00025 #include "usbhost_ms.h" 00026 00027 /* 00028 ************************************************************************************************************** 00029 * GLOBAL VARIABLES 00030 ************************************************************************************************************** 00031 */ 00032 00033 USB_INT32U MS_BlkSize; 00034 00035 /* 00036 ************************************************************************************************************** 00037 * INITIALIZE MASS STORAGE INTERFACE 00038 * 00039 * Description: This function initializes the mass storage interface 00040 * 00041 * Arguments : None 00042 * 00043 * Returns : OK if Success 00044 * ERR_INVALID_BOOTSIG if Failed 00045 * 00046 ************************************************************************************************************** 00047 */ 00048 00049 USB_INT32S MS_Init (USB_INT32U *blkSize, USB_INT32U *numBlks, USB_INT08U *inquiryResult) 00050 { 00051 USB_INT08U retry; 00052 USB_INT32S rc; 00053 00054 MS_GetMaxLUN(); /* Get maximum logical unit number */ 00055 retry = 80; 00056 while(retry) { 00057 rc = MS_TestUnitReady(); /* Test whether the unit is ready */ 00058 if (rc == OK) { 00059 break; 00060 } 00061 MS_GetSenseInfo(); /* Get sense information */ 00062 retry--; 00063 } 00064 if (rc != OK) { 00065 PRINT_Err(rc); 00066 return (rc); 00067 } 00068 rc = MS_ReadCapacity(numBlks, blkSize); /* Read capacity of the disk */ 00069 MS_BlkSize = *blkSize; // Set global 00070 rc = MS_Inquire (inquiryResult); 00071 return (rc); 00072 } 00073 /* 00074 ************************************************************************************************************** 00075 * PARSE THE CONFIGURATION 00076 * 00077 * Description: This function is used to parse the configuration 00078 * 00079 * Arguments : None 00080 * 00081 * Returns : OK if Success 00082 * ERR_INVALID_BOOTSIG if Failed 00083 * 00084 ************************************************************************************************************** 00085 */ 00086 00087 USB_INT32S MS_ParseConfiguration (void) 00088 { 00089 volatile USB_INT08U *desc_ptr; 00090 USB_INT08U ms_int_found; 00091 00092 00093 desc_ptr = TDBuffer; 00094 ms_int_found = 0; 00095 00096 if (desc_ptr[1] != USB_DESCRIPTOR_TYPE_CONFIGURATION) { 00097 return (ERR_BAD_CONFIGURATION); 00098 } 00099 desc_ptr += desc_ptr[0]; 00100 00101 while (desc_ptr != TDBuffer + ReadLE16U(&TDBuffer[2])) { 00102 00103 switch (desc_ptr[1]) { 00104 00105 case USB_DESCRIPTOR_TYPE_INTERFACE: /* If it is an interface descriptor */ 00106 if (desc_ptr[5] == MASS_STORAGE_CLASS && /* check if the class is mass storage */ 00107 desc_ptr[6] == MASS_STORAGE_SUBCLASS_SCSI && /* check if the subclass is SCSI */ 00108 desc_ptr[7] == MASS_STORAGE_PROTOCOL_BO) { /* check if the protocol is Bulk only */ 00109 ms_int_found = 1; 00110 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00111 } 00112 break; 00113 00114 case USB_DESCRIPTOR_TYPE_ENDPOINT: /* If it is an endpoint descriptor */ 00115 if ((desc_ptr[3] & 0x03) == 0x02) { /* If it is Bulk endpoint */ 00116 if (desc_ptr[2] & 0x80) { /* If it is In endpoint */ 00117 EDBulkIn->Control = 1 | /* USB address */ 00118 ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */ 00119 (2 << 11) | /* direction */ 00120 (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */ 00121 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00122 } else { /* If it is Out endpoint */ 00123 EDBulkOut->Control = 1 | /* USB address */ 00124 ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */ 00125 (1 << 11) | /* direction */ 00126 (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */ 00127 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00128 } 00129 } else { /* If it is not bulk end point */ 00130 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00131 } 00132 break; 00133 00134 default: /* If the descriptor is neither interface nor endpoint */ 00135 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00136 break; 00137 } 00138 } 00139 if (ms_int_found) { 00140 PRINT_Log("Mass Storage device connected\n"); 00141 return (OK); 00142 } else { 00143 PRINT_Log("Not a Mass Storage device\n"); 00144 return (ERR_NO_MS_INTERFACE); 00145 } 00146 } 00147 00148 /* 00149 ************************************************************************************************************** 00150 * GET MAXIMUM LOGICAL UNIT 00151 * 00152 * Description: This function returns the maximum logical unit from the device 00153 * 00154 * Arguments : None 00155 * 00156 * Returns : OK if Success 00157 * ERR_INVALID_BOOTSIG if Failed 00158 * 00159 ************************************************************************************************************** 00160 */ 00161 00162 USB_INT32S MS_GetMaxLUN (void) 00163 { 00164 USB_INT32S rc; 00165 00166 00167 rc = Host_CtrlRecv(USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, 00168 MS_GET_MAX_LUN_REQ, 00169 0, 00170 0, 00171 1, 00172 TDBuffer); 00173 return (rc); 00174 } 00175 00176 /* 00177 ************************************************************************************************************** 00178 * GET SENSE INFORMATION 00179 * 00180 * Description: This function is used to get sense information from the device 00181 * 00182 * Arguments : None 00183 * 00184 * Returns : OK if Success 00185 * ERROR if Failed 00186 * 00187 ************************************************************************************************************** 00188 */ 00189 00190 USB_INT32S MS_GetSenseInfo (void) 00191 { 00192 USB_INT32S rc; 00193 00194 00195 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_REQUEST_SENSE, 6); 00196 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00197 if (rc == OK) { 00198 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 18); 00199 if (rc == OK) { 00200 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00201 if (rc == OK) { 00202 if (TDBuffer[12] != 0) { 00203 rc = ERR_MS_CMD_FAILED; 00204 } 00205 } 00206 } 00207 } 00208 return (rc); 00209 } 00210 00211 /* 00212 ************************************************************************************************************** 00213 * TEST UNIT READY 00214 * 00215 * Description: This function is used to test whether the unit is ready or not 00216 * 00217 * Arguments : None 00218 * 00219 * Returns : OK if Success 00220 * ERROR if Failed 00221 * 00222 ************************************************************************************************************** 00223 */ 00224 00225 USB_INT32S MS_TestUnitReady (void) 00226 { 00227 USB_INT32S rc; 00228 00229 00230 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_NONE, SCSI_CMD_TEST_UNIT_READY, 6); 00231 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00232 if (rc == OK) { 00233 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00234 if (rc == OK) { 00235 if (TDBuffer[12] != 0) { 00236 rc = ERR_MS_CMD_FAILED; 00237 } 00238 } 00239 } 00240 return (rc); 00241 } 00242 00243 /* 00244 ************************************************************************************************************** 00245 * READ CAPACITY 00246 * 00247 * Description: This function is used to read the capacity of the mass storage device 00248 * 00249 * Arguments : None 00250 * 00251 * Returns : OK if Success 00252 * ERROR if Failed 00253 * 00254 ************************************************************************************************************** 00255 */ 00256 00257 USB_INT32S MS_ReadCapacity (USB_INT32U *numBlks, USB_INT32U *blkSize) 00258 { 00259 USB_INT32S rc; 00260 00261 00262 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_READ_CAPACITY, 10); 00263 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00264 if (rc == OK) { 00265 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 8); 00266 if (rc == OK) { 00267 if (numBlks) 00268 *numBlks = ReadBE32U(&TDBuffer[0]); 00269 if (blkSize) 00270 *blkSize = ReadBE32U(&TDBuffer[4]); 00271 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00272 if (rc == OK) { 00273 if (TDBuffer[12] != 0) { 00274 rc = ERR_MS_CMD_FAILED; 00275 } 00276 } 00277 } 00278 } 00279 return (rc); 00280 } 00281 00282 00283 00284 USB_INT32S MS_Inquire (USB_INT08U *response) 00285 { 00286 USB_INT32S rc; 00287 USB_INT32U i; 00288 00289 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_INQUIRY, 6); 00290 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00291 if (rc == OK) { 00292 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, INQUIRY_LENGTH); 00293 if (rc == OK) { 00294 if (response) { 00295 for ( i = 0; i < INQUIRY_LENGTH; i++ ) 00296 *response++ = *TDBuffer++; 00297 #if 0 00298 MemCpy (response, TDBuffer, INQUIRY_LENGTH); 00299 StrNullTrailingSpace (response->vendorID, SCSI_INQUIRY_VENDORCHARS); 00300 StrNullTrailingSpace (response->productID, SCSI_INQUIRY_PRODUCTCHARS); 00301 StrNullTrailingSpace (response->productRev, SCSI_INQUIRY_REVCHARS); 00302 #endif 00303 } 00304 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00305 if (rc == OK) { 00306 if (TDBuffer[12] != 0) { // bCSWStatus byte 00307 rc = ERR_MS_CMD_FAILED; 00308 } 00309 } 00310 } 00311 } 00312 return (rc); 00313 } 00314 00315 /* 00316 ************************************************************************************************************** 00317 * RECEIVE THE BULK DATA 00318 * 00319 * Description: This function is used to receive the bulk data 00320 * 00321 * Arguments : None 00322 * 00323 * Returns : OK if Success 00324 * ERR_INVALID_BOOTSIG if Failed 00325 * 00326 ************************************************************************************************************** 00327 */ 00328 00329 USB_INT32S MS_BulkRecv ( USB_INT32U block_number, 00330 USB_INT16U num_blocks, 00331 volatile USB_INT08U *user_buffer) 00332 { 00333 USB_INT32S rc; 00334 int i; 00335 volatile USB_INT08U *c = user_buffer; 00336 for (i=0;i<MS_BlkSize*num_blocks;i++) 00337 *c++ = 0; 00338 00339 00340 Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_IN, SCSI_CMD_READ_10, 10); 00341 00342 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00343 if (rc == OK) { 00344 rc = Host_ProcessTD(EDBulkIn, TD_IN, user_buffer, MS_BlkSize * num_blocks); 00345 if (rc == OK) { 00346 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00347 if (rc == OK) { 00348 if (TDBuffer[12] != 0) { 00349 rc = ERR_MS_CMD_FAILED; 00350 } 00351 } 00352 } 00353 } 00354 return (rc); 00355 } 00356 00357 /* 00358 ************************************************************************************************************** 00359 * SEND BULK DATA 00360 * 00361 * Description: This function is used to send the bulk data 00362 * 00363 * Arguments : None 00364 * 00365 * Returns : OK if Success 00366 * ERR_INVALID_BOOTSIG if Failed 00367 * 00368 ************************************************************************************************************** 00369 */ 00370 00371 USB_INT32S MS_BulkSend ( USB_INT32U block_number, 00372 USB_INT16U num_blocks, 00373 volatile USB_INT08U *user_buffer) 00374 { 00375 USB_INT32S rc; 00376 00377 00378 Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_OUT, SCSI_CMD_WRITE_10, 10); 00379 00380 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00381 if (rc == OK) { 00382 rc = Host_ProcessTD(EDBulkOut, TD_OUT, user_buffer, MS_BlkSize * num_blocks); 00383 if (rc == OK) { 00384 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00385 if (rc == OK) { 00386 if (TDBuffer[12] != 0) { 00387 rc = ERR_MS_CMD_FAILED; 00388 } 00389 } 00390 } 00391 } 00392 return (rc); 00393 } 00394 00395 /* 00396 ************************************************************************************************************** 00397 * FILL MASS STORAGE COMMAND 00398 * 00399 * Description: This function is used to fill the mass storage command 00400 * 00401 * Arguments : None 00402 * 00403 * Returns : OK if Success 00404 * ERR_INVALID_BOOTSIG if Failed 00405 * 00406 ************************************************************************************************************** 00407 */ 00408 00409 void Fill_MSCommand (USB_INT32U block_number, 00410 USB_INT32U block_size, 00411 USB_INT16U num_blocks, 00412 MS_DATA_DIR direction, 00413 USB_INT08U scsi_cmd, 00414 USB_INT08U scsi_cmd_len) 00415 { 00416 USB_INT32U data_len; 00417 static USB_INT32U tag_cnt = 0; 00418 USB_INT32U cnt; 00419 00420 00421 for (cnt = 0; cnt < CBW_SIZE; cnt++) { 00422 TDBuffer[cnt] = 0; 00423 } 00424 switch(scsi_cmd) { 00425 00426 case SCSI_CMD_TEST_UNIT_READY: 00427 data_len = 0; 00428 break; 00429 case SCSI_CMD_READ_CAPACITY: 00430 data_len = 8; 00431 break; 00432 case SCSI_CMD_REQUEST_SENSE: 00433 data_len = 18; 00434 break; 00435 case SCSI_CMD_INQUIRY: 00436 data_len = 36; 00437 break; 00438 default: 00439 data_len = block_size * num_blocks; 00440 break; 00441 } 00442 WriteLE32U(TDBuffer, CBW_SIGNATURE); 00443 WriteLE32U(&TDBuffer[4], tag_cnt); 00444 WriteLE32U(&TDBuffer[8], data_len); 00445 TDBuffer[12] = (direction == MS_DATA_DIR_NONE) ? 0 : direction; 00446 TDBuffer[14] = scsi_cmd_len; /* Length of the CBW */ 00447 TDBuffer[15] = scsi_cmd; 00448 if ((scsi_cmd == SCSI_CMD_REQUEST_SENSE) 00449 || (scsi_cmd == SCSI_CMD_INQUIRY)) { 00450 TDBuffer[19] = (USB_INT08U)data_len; 00451 } else { 00452 WriteBE32U(&TDBuffer[17], block_number); 00453 } 00454 WriteBE16U(&TDBuffer[22], num_blocks); 00455 }
Generated on Thu Jul 14 2022 15:51:46 by 1.7.2