This package contains a simple test of tests for various elements of the SmartBoard hardware, which is a simple baseboard designed for easy embedding. It is able to run both a semi-automatic test suite as well as allow interactive testing.

Dependencies:   EthernetNetIf NTPClient_NetServices mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers usbhost_ms.c Source File

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