Ilya I
/
pub_UsbHost
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 // while (desc_ptr != TDBuffer + *((USB_INT16U *) &TDBuffer[2])) { 00103 00104 switch (desc_ptr[1]) { 00105 00106 case USB_DESCRIPTOR_TYPE_INTERFACE: /* If it is an interface descriptor */ 00107 if (desc_ptr[5] == MASS_STORAGE_CLASS && /* check if the class is mass storage */ 00108 desc_ptr[6] == MASS_STORAGE_SUBCLASS_SCSI && /* check if the subclass is SCSI */ 00109 desc_ptr[7] == MASS_STORAGE_PROTOCOL_BO) { /* check if the protocol is Bulk only */ 00110 ms_int_found = 1; 00111 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00112 } 00113 break; 00114 00115 case USB_DESCRIPTOR_TYPE_ENDPOINT: /* If it is an endpoint descriptor */ 00116 if ((desc_ptr[3] & 0x03) == 0x02) { /* If it is Bulk endpoint */ 00117 if (desc_ptr[2] & 0x80) { /* If it is In endpoint */ 00118 EDBulkIn->Control = 1 | /* USB address */ 00119 ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */ 00120 (2 << 11) | /* direction */ 00121 (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */ 00122 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00123 } else { /* If it is Out endpoint */ 00124 EDBulkOut->Control = 1 | /* USB address */ 00125 ((desc_ptr[2] & 0x7F) << 7) | /* Endpoint address */ 00126 (1 << 11) | /* direction */ 00127 (ReadLE16U(&desc_ptr[4]) << 16); /* MaxPkt Size */ 00128 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00129 } 00130 } else { /* If it is not bulk end point */ 00131 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00132 } 00133 break; 00134 00135 default: /* If the descriptor is neither interface nor endpoint */ 00136 desc_ptr += desc_ptr[0]; /* Move to next descriptor start */ 00137 break; 00138 } 00139 } 00140 if (ms_int_found) { 00141 PRINT_Log("Mass Storage device connected\r\n"); 00142 return (OK); 00143 } else { 00144 PRINT_Log("Not a Mass Storage device\r\n"); 00145 return (ERR_NO_MS_INTERFACE); 00146 } 00147 } 00148 00149 /* 00150 ************************************************************************************************************** 00151 * GET MAXIMUM LOGICAL UNIT 00152 * 00153 * Description: This function returns the maximum logical unit from the device 00154 * 00155 * Arguments : None 00156 * 00157 * Returns : OK if Success 00158 * ERR_INVALID_BOOTSIG if Failed 00159 * 00160 ************************************************************************************************************** 00161 */ 00162 00163 USB_INT32S MS_GetMaxLUN (void) 00164 { 00165 USB_INT32S rc; 00166 00167 00168 rc = Host_CtrlRecv(USB_DEVICE_TO_HOST | USB_REQUEST_TYPE_CLASS | USB_RECIPIENT_INTERFACE, 00169 MS_GET_MAX_LUN_REQ, 00170 0, 00171 0, 00172 1, 00173 TDBuffer); 00174 return (rc); 00175 } 00176 00177 /* 00178 ************************************************************************************************************** 00179 * GET SENSE INFORMATION 00180 * 00181 * Description: This function is used to get sense information from the device 00182 * 00183 * Arguments : None 00184 * 00185 * Returns : OK if Success 00186 * ERROR if Failed 00187 * 00188 ************************************************************************************************************** 00189 */ 00190 00191 USB_INT32S MS_GetSenseInfo (void) 00192 { 00193 USB_INT32S rc; 00194 00195 00196 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_REQUEST_SENSE, 6); 00197 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00198 if (rc == OK) { 00199 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 18); 00200 if (rc == OK) { 00201 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00202 if (rc == OK) { 00203 if (TDBuffer[12] != 0) { 00204 rc = ERR_MS_CMD_FAILED; 00205 } 00206 } 00207 } 00208 } 00209 return (rc); 00210 } 00211 00212 /* 00213 ************************************************************************************************************** 00214 * TEST UNIT READY 00215 * 00216 * Description: This function is used to test whether the unit is ready or not 00217 * 00218 * Arguments : None 00219 * 00220 * Returns : OK if Success 00221 * ERROR if Failed 00222 * 00223 ************************************************************************************************************** 00224 */ 00225 00226 USB_INT32S MS_TestUnitReady (void) 00227 { 00228 USB_INT32S rc; 00229 00230 00231 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_NONE, SCSI_CMD_TEST_UNIT_READY, 6); 00232 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00233 if (rc == OK) { 00234 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00235 if (rc == OK) { 00236 if (TDBuffer[12] != 0) { 00237 rc = ERR_MS_CMD_FAILED; 00238 } 00239 } 00240 } 00241 return (rc); 00242 } 00243 00244 /* 00245 ************************************************************************************************************** 00246 * READ CAPACITY 00247 * 00248 * Description: This function is used to read the capacity of the mass storage device 00249 * 00250 * Arguments : None 00251 * 00252 * Returns : OK if Success 00253 * ERROR if Failed 00254 * 00255 ************************************************************************************************************** 00256 */ 00257 00258 USB_INT32S MS_ReadCapacity (USB_INT32U *numBlks, USB_INT32U *blkSize) 00259 { 00260 USB_INT32S rc; 00261 00262 00263 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_READ_CAPACITY, 10); 00264 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00265 if (rc == OK) { 00266 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, 8); 00267 if (rc == OK) { 00268 if (numBlks) 00269 *numBlks = ReadBE32U(&TDBuffer[0]); 00270 if (blkSize) 00271 *blkSize = ReadBE32U(&TDBuffer[4]); 00272 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00273 if (rc == OK) { 00274 if (TDBuffer[12] != 0) { 00275 rc = ERR_MS_CMD_FAILED; 00276 } 00277 } 00278 } 00279 } 00280 return (rc); 00281 } 00282 00283 00284 00285 USB_INT32S MS_Inquire (USB_INT08U *response) 00286 { 00287 USB_INT32S rc; 00288 USB_INT32U i; 00289 00290 Fill_MSCommand(0, 0, 0, MS_DATA_DIR_IN, SCSI_CMD_INQUIRY, 6); 00291 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00292 if (rc == OK) { 00293 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, INQUIRY_LENGTH); 00294 if (rc == OK) { 00295 if (response) { 00296 for ( i = 0; i < INQUIRY_LENGTH; i++ ) 00297 *response++ = *TDBuffer++; 00298 #if 0 00299 MemCpy (response, TDBuffer, INQUIRY_LENGTH); 00300 StrNullTrailingSpace (response->vendorID, SCSI_INQUIRY_VENDORCHARS); 00301 StrNullTrailingSpace (response->productID, SCSI_INQUIRY_PRODUCTCHARS); 00302 StrNullTrailingSpace (response->productRev, SCSI_INQUIRY_REVCHARS); 00303 #endif 00304 } 00305 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00306 if (rc == OK) { 00307 if (TDBuffer[12] != 0) { // bCSWStatus byte 00308 rc = ERR_MS_CMD_FAILED; 00309 } 00310 } 00311 } 00312 } 00313 return (rc); 00314 } 00315 00316 /* 00317 ************************************************************************************************************** 00318 * RECEIVE THE BULK DATA 00319 * 00320 * Description: This function is used to receive the bulk data 00321 * 00322 * Arguments : None 00323 * 00324 * Returns : OK if Success 00325 * ERR_INVALID_BOOTSIG if Failed 00326 * 00327 ************************************************************************************************************** 00328 */ 00329 00330 USB_INT32S MS_BulkRecv ( USB_INT32U block_number, 00331 USB_INT16U num_blocks, 00332 volatile USB_INT08U *user_buffer) 00333 { 00334 USB_INT32S rc; 00335 int i; 00336 volatile USB_INT08U *c = user_buffer; 00337 for (i=0;i<MS_BlkSize*num_blocks;i++) 00338 *c++ = 0; 00339 00340 00341 Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_IN, SCSI_CMD_READ_10, 10); 00342 00343 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00344 if (rc == OK) { 00345 rc = Host_ProcessTD(EDBulkIn, TD_IN, user_buffer, MS_BlkSize * num_blocks); 00346 if (rc == OK) { 00347 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00348 if (rc == OK) { 00349 if (TDBuffer[12] != 0) { 00350 rc = ERR_MS_CMD_FAILED; 00351 } 00352 } 00353 } 00354 } 00355 return (rc); 00356 } 00357 00358 /* 00359 ************************************************************************************************************** 00360 * SEND BULK DATA 00361 * 00362 * Description: This function is used to send the bulk data 00363 * 00364 * Arguments : None 00365 * 00366 * Returns : OK if Success 00367 * ERR_INVALID_BOOTSIG if Failed 00368 * 00369 ************************************************************************************************************** 00370 */ 00371 00372 USB_INT32S MS_BulkSend ( USB_INT32U block_number, 00373 USB_INT16U num_blocks, 00374 volatile USB_INT08U *user_buffer) 00375 { 00376 USB_INT32S rc; 00377 00378 00379 Fill_MSCommand(block_number, MS_BlkSize, num_blocks, MS_DATA_DIR_OUT, SCSI_CMD_WRITE_10, 10); 00380 00381 rc = Host_ProcessTD(EDBulkOut, TD_OUT, TDBuffer, CBW_SIZE); 00382 if (rc == OK) { 00383 rc = Host_ProcessTD(EDBulkOut, TD_OUT, user_buffer, MS_BlkSize * num_blocks); 00384 if (rc == OK) { 00385 rc = Host_ProcessTD(EDBulkIn, TD_IN, TDBuffer, CSW_SIZE); 00386 if (rc == OK) { 00387 if (TDBuffer[12] != 0) { 00388 rc = ERR_MS_CMD_FAILED; 00389 } 00390 } 00391 } 00392 } 00393 return (rc); 00394 } 00395 00396 /* 00397 ************************************************************************************************************** 00398 * FILL MASS STORAGE COMMAND 00399 * 00400 * Description: This function is used to fill the mass storage command 00401 * 00402 * Arguments : None 00403 * 00404 * Returns : OK if Success 00405 * ERR_INVALID_BOOTSIG if Failed 00406 * 00407 ************************************************************************************************************** 00408 */ 00409 00410 void Fill_MSCommand (USB_INT32U block_number, 00411 USB_INT32U block_size, 00412 USB_INT16U num_blocks, 00413 MS_DATA_DIR direction, 00414 USB_INT08U scsi_cmd, 00415 USB_INT08U scsi_cmd_len) 00416 { 00417 USB_INT32U data_len; 00418 static USB_INT32U tag_cnt = 0; 00419 USB_INT32U cnt; 00420 00421 00422 for (cnt = 0; cnt < CBW_SIZE; cnt++) { 00423 TDBuffer[cnt] = 0; 00424 } 00425 switch(scsi_cmd) { 00426 00427 case SCSI_CMD_TEST_UNIT_READY: 00428 data_len = 0; 00429 break; 00430 case SCSI_CMD_READ_CAPACITY: 00431 data_len = 8; 00432 break; 00433 case SCSI_CMD_REQUEST_SENSE: 00434 data_len = 18; 00435 break; 00436 case SCSI_CMD_INQUIRY: 00437 data_len = 36; 00438 break; 00439 default: 00440 data_len = block_size * num_blocks; 00441 break; 00442 } 00443 WriteLE32U(TDBuffer, CBW_SIGNATURE); 00444 WriteLE32U(&TDBuffer[4], tag_cnt); 00445 WriteLE32U(&TDBuffer[8], data_len); 00446 TDBuffer[12] = (direction == MS_DATA_DIR_NONE) ? 0 : direction; 00447 TDBuffer[14] = scsi_cmd_len; /* Length of the CBW */ 00448 TDBuffer[15] = scsi_cmd; 00449 if ((scsi_cmd == SCSI_CMD_REQUEST_SENSE) 00450 || (scsi_cmd == SCSI_CMD_INQUIRY)) { 00451 TDBuffer[19] = (USB_INT08U)data_len; 00452 } else { 00453 WriteBE32U(&TDBuffer[17], block_number); 00454 } 00455 WriteBE16U(&TDBuffer[22], num_blocks); 00456 }
Generated on Thu Jul 14 2022 00:28:57 by 1.7.2