SD

Dependents:   Andar_Linha_Reta_Robo_Claw_v1

Fork of MSCFileSystem by Chris Styles

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbhost_ms.cpp Source File

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 }