00001
00035 #include <inttypes.h>
00036 #include "em_device.h"
00037 #include "em_usb.h"
00038 #include "msdscsi.h"
00039
00042 #define DEV_ADDR 1
00043 #define BULK_OUT &ep[ epOutIndex ]
00044 #define BULK_IN &ep[ epInIndex ]
00045
00046 static void PrintDeviceStrings(uint8_t *buf);
00047 static bool QualifyDevice(uint8_t *buf);
00048
00049 static USBH_Device_TypeDef device;
00050 static USBH_Ep_TypeDef ep[ 2 ];
00051 static int epOutIndex;
00052 static int epInIndex;
00053
00056
00077 bool MSDH_Init(uint8_t *usbDeviceInfo, int usbDeviceInfoSize)
00078 {
00079 EFM32_ALIGN(4)
00080 MSDSCSI_InquiryData_TypeDef inquiryData __attribute__ ((aligned(4)));
00081
00082 EFM32_ALIGN(4)
00083 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00084
00085 EFM32_ALIGN(4)
00086 MSDSCSI_RequestSenseData_TypeDef reqSenseData __attribute__ ((aligned(4)));
00087
00088 bool ready;
00089 int result, i;
00090
00091
00092 if (USBH_QueryDeviceB(usbDeviceInfo, usbDeviceInfoSize, USBH_GetPortSpeed())
00093 != USB_STATUS_OK)
00094 return false;
00095
00096
00097 if (!QualifyDevice(usbDeviceInfo))
00098 return false;
00099
00100
00101 if (!MSDSCSI_Init(BULK_OUT, BULK_IN))
00102 return false;
00103
00104
00105 if (!MSDSCSI_Inquiry(&inquiryData))
00106 return false;
00107
00108 memcpy(usbDeviceInfo, &inquiryData.T10VendorId, sizeof(inquiryData.T10VendorId));
00109 usbDeviceInfo[ sizeof(inquiryData.T10VendorId) ] = '\0';
00110 USB_PRINTF("\nSCSI Inquiry Vendor ID string : \"%s\"", usbDeviceInfo);
00111
00112 memcpy(usbDeviceInfo, &inquiryData.ProductId, sizeof(inquiryData.ProductId));
00113 usbDeviceInfo[ sizeof(inquiryData.ProductId) ] = '\0';
00114 USB_PRINTF("\nSCSI Inquiry Product ID string : \"%s\"", usbDeviceInfo);
00115
00116 memcpy(usbDeviceInfo, &inquiryData.ProductRevisionLevel, sizeof(inquiryData.ProductRevisionLevel));
00117 usbDeviceInfo[ sizeof(inquiryData.ProductRevisionLevel) ] = '\0';
00118 USB_PRINTF("\nSCSI Inquiry Product Revision string : \"%s\"", usbDeviceInfo);
00119
00120
00121 if ((inquiryData.PeripheralQualifier != 0) ||
00122 (inquiryData.PeripheralDeviceType != 0))
00123 return false;
00124
00125
00126 i = 0;
00127 do
00128 {
00129 result = MSDSCSI_RequestSense(&reqSenseData);
00130 ready = MSDSCSI_TestUnitReady();
00131 if (!ready)
00132 USBTIMER_DelayMs(500);
00133 i++;
00134 } while (!ready && i < 10 && result);
00135
00136 if (!result)
00137 {
00138 USB_PRINTF("\n\nSCSI Request Sense execution error");
00139 return false;
00140 }
00141
00142 if (!ready)
00143 {
00144 USB_PRINTF("\n\nMSD device not ready");
00145 return false;
00146 }
00147
00148
00149 if (!MSDSCSI_ReadCapacity(&capacityData))
00150 {
00151 USB_PRINTF("\n\nSCSI Read Capacity execution error");
00152 return false;
00153 }
00154
00155 USB_PRINTF("\n\nSCSI Read Capacity LBA count : %ld = %ld MiB",
00156 capacityData.LogicalBlockAddress,
00157 (capacityData.LogicalBlockAddress * capacityData.LogicalBlockLength) / (1024 * 1024));
00158 USB_PRINTF("\nSCSI Read Capacity LBA size : %ld\n\n", capacityData.LogicalBlockLength);
00159
00160 return true;
00161 }
00162
00163
00173 bool MSDH_GetSectorCount(uint32_t *sectorCount)
00174 {
00175 EFM32_ALIGN(4)
00176 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00177
00178 if (!MSDSCSI_ReadCapacity(&capacityData))
00179 return false;
00180
00181 *sectorCount = capacityData.LogicalBlockAddress;
00182
00183 return true;
00184 }
00185
00186
00196 bool MSDH_GetSectorSize(uint16_t *sectorSize)
00197 {
00198 EFM32_ALIGN(4)
00199 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00200
00201 if (!MSDSCSI_ReadCapacity(&capacityData))
00202 return false;
00203
00204 *sectorSize = (uint16_t) capacityData.LogicalBlockLength;
00205
00206 return true;
00207 }
00208
00209
00222 bool MSDH_GetBlockSize(uint32_t *blockSize)
00223 {
00224 EFM32_ALIGN(4)
00225 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00226
00227 if (!MSDSCSI_ReadCapacity(&capacityData))
00228 return false;
00229
00230 *blockSize = capacityData.LogicalBlockLength;
00231
00232 return true;
00233 }
00234
00235
00251 bool MSDH_ReadSectors(uint32_t lba, uint16_t sectors, void *data)
00252 {
00253 return MSDSCSI_Read10(lba, sectors, data);
00254 }
00255
00256
00272 bool MSDH_WriteSectors(uint32_t lba, uint16_t sectors, const void *data)
00273 {
00274 return MSDSCSI_Write10(lba, sectors, data);
00275 }
00276
00279
00290 static bool QualifyDevice(uint8_t *buf)
00291 {
00292 int i;
00293 bool retVal = false;
00294 bool epIn = false, epOut = false;
00295
00296 if ((USBH_QGetDeviceDescriptor(buf)->bDeviceClass == 0) &&
00297 (USBH_QGetDeviceDescriptor(buf)->bDeviceSubClass == 0) &&
00298 (USBH_QGetDeviceDescriptor(buf)->bDeviceProtocol == 0) &&
00299 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceClass == USB_CLASS_MSD) &&
00300 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceSubClass == USB_CLASS_MSD_SCSI_CMDSET) &&
00301 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceProtocol == USB_CLASS_MSD_BOT_TRANSPORT) &&
00302 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints >= 2))
00303 {
00304
00305
00306
00307
00308 for (i = 0; i < USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints; i++)
00309 {
00310 if (USBH_QGetEndpointDescriptor(buf, 0, 0, i)->bmAttributes == USB_EPTYPE_BULK)
00311 {
00312 if (USBH_QGetEndpointDescriptor(buf, 0, 0, i)->bEndpointAddress & USB_EP_DIR_IN)
00313 {
00314 if (!epIn)
00315 {
00316 epIn = true;
00317 epInIndex = i;
00318 }
00319 }
00320 else
00321 {
00322 if (!epOut)
00323 {
00324 epOut = true;
00325 epOutIndex = i;
00326 }
00327 }
00328 }
00329
00330
00331 if (epIn && epOut)
00332 break;
00333 }
00334
00335 if ((epIn && epOut) && (epInIndex < 2) && (epOutIndex < 2))
00336 {
00337
00338
00339
00340
00341
00342 USB_PRINTF("\nThis is a valid MSD device.");
00343 retVal = true;
00344 }
00345 }
00346
00347 if (retVal == false)
00348 {
00349 USBH_PrintDeviceDescriptor(USBH_QGetDeviceDescriptor(buf));
00350 USBH_PrintConfigurationDescriptor(USBH_QGetConfigurationDescriptor(buf, 0), USB_CONFIG_DESCSIZE);
00351 USBH_PrintInterfaceDescriptor(USBH_QGetInterfaceDescriptor(buf, 0, 0));
00352
00353 for (i = 0; i < USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints; i++)
00354 {
00355 USBH_PrintEndpointDescriptor(USBH_QGetEndpointDescriptor(buf, 0, 0, i));
00356 }
00357 USB_PRINTF("\nThis is not a valid MSD device, review device descriptors.");
00358 }
00359 else
00360 {
00361
00362
00363 USBH_InitDeviceData(&device, buf, ep, 2, USBH_GetPortSpeed());
00364 USBH_SetAddressB(&device, DEV_ADDR);
00365 USBH_SetConfigurationB(&device, device.confDesc.bConfigurationValue);
00366
00367
00368 USBH_AssignHostChannel(BULK_OUT, 2);
00369 USBH_AssignHostChannel(BULK_IN, 3);
00370
00371 USB_PRINTF("\n\nDevice VID/PID is 0x%04X/0x%04X, device bus speed is %s",
00372 device.devDesc.idVendor, device.devDesc.idProduct,
00373 USBH_GetPortSpeed() == PORT_FULL_SPEED ? "FULL" : "LOW");
00374
00375 PrintDeviceStrings(buf);
00376 }
00377
00378 return retVal;
00379 }
00380
00381
00388 static void PrintDeviceStrings(uint8_t *buf)
00389 {
00390
00391
00392 if (device.devDesc.iManufacturer)
00393 {
00394 USBH_GetStringB(&device, buf, 255, device.devDesc.iManufacturer,
00395 USB_LANGID_ENUS);
00396 USBH_PrintString("\n\niManufacturer = \"",
00397 (USB_StringDescriptor_TypeDef*) buf, "\"");
00398 }
00399 else
00400 {
00401 USB_PRINTF("\n\niManufacturer = <NONE>");
00402 }
00403
00404 if (device.devDesc.iProduct)
00405 {
00406 USBH_GetStringB(&device, buf, 255, device.devDesc.iProduct,
00407 USB_LANGID_ENUS);
00408 USBH_PrintString("\niProduct = \"",
00409 (USB_StringDescriptor_TypeDef*) buf, "\"");
00410 }
00411 else
00412 {
00413 USB_PRINTF("\niProduct = <NONE>");
00414 }
00415
00416 if (device.devDesc.iSerialNumber)
00417 {
00418 USBH_GetStringB(&device, buf, 255, device.devDesc.iSerialNumber,
00419 USB_LANGID_ENUS);
00420 USBH_PrintString("\niSerialNumber = \"",
00421 (USB_StringDescriptor_TypeDef*) buf, "\"\n");
00422 }
00423 else
00424 {
00425 USB_PRINTF("\niSerialNumber = <NONE>\n");
00426 }
00427 }
00428