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.
Fork of MSCFileSystem by
usbhost_ms.cpp
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 Wed Jul 13 2022 18:06:37 by
1.7.2
