25 #define BULK_OUT &ep[ epOutIndex ]
26 #define BULK_IN &ep[ epInIndex ]
27 #define SCSI_INQUIRY_RETRIES 10 // Retries during MSDH_Init()
28 #define SCSI_TESTUNITREADY_RETRIES 10 // Retries during MSDH_Init()
30 static void PrintDeviceStrings(uint8_t *buf);
31 static bool QualifyDevice(uint8_t *buf);
33 static USBH_Device_TypeDef device;
34 static USBH_Ep_TypeDef ep[ 2 ];
35 static int epOutIndex;
61 bool MSDH_Init(uint8_t *usbDeviceInfo,
int usbDeviceInfoSize)
76 if (USBH_QueryDeviceB(usbDeviceInfo, usbDeviceInfoSize, USBH_GetPortSpeed())
79 USB_PRINTF(
"\nUSB descriptor retrieval failed.");
84 if (!QualifyDevice(usbDeviceInfo))
92 USB_PRINTF(
"\nMSD BOT initialization failed.");
108 }
while (!ready && i < SCSI_INQUIRY_RETRIES);
116 memcpy(usbDeviceInfo, &inquiryData.T10VendorId,
sizeof(inquiryData.T10VendorId));
117 usbDeviceInfo[
sizeof(inquiryData.T10VendorId) ] =
'\0';
118 USB_PRINTF(
"\nSCSI Inquiry Vendor ID string : \"%s\"", usbDeviceInfo);
120 memcpy(usbDeviceInfo, &inquiryData.ProductId,
sizeof(inquiryData.ProductId));
121 usbDeviceInfo[
sizeof(inquiryData.ProductId) ] =
'\0';
122 USB_PRINTF(
"\nSCSI Inquiry Product ID string : \"%s\"", usbDeviceInfo);
124 memcpy(usbDeviceInfo, &inquiryData.ProductRevisionLevel,
sizeof(inquiryData.ProductRevisionLevel));
125 usbDeviceInfo[
sizeof(inquiryData.ProductRevisionLevel) ] =
'\0';
126 USB_PRINTF(
"\nSCSI Inquiry Product Revision string : \"%s\"", usbDeviceInfo);
129 if ((inquiryData.PeripheralQualifier != 0) ||
130 (inquiryData.PeripheralDeviceType != 0))
146 }
while (!ready && i < SCSI_TESTUNITREADY_RETRIES && result);
150 USB_PRINTF(
"\n\nSCSI Request Sense execution error");
163 USB_PRINTF(
"\n\nSCSI Read Capacity execution error");
167 USB_PRINTF(
"\n\nSCSI Read Capacity LBA count : %ld = %ld MiB",
168 capacityData.LogicalBlockAddress,
170 (((uint64_t)capacityData.LogicalBlockAddress
171 * capacityData.LogicalBlockLength) / (1024 * 1024)));
172 USB_PRINTF(
"\nSCSI Read Capacity LBA size : %ld\n\n",
173 capacityData.LogicalBlockLength);
196 *sectorCount = capacityData.LogicalBlockAddress;
219 *sectorSize = (uint16_t) capacityData.LogicalBlockLength;
245 *blockSize = capacityData.LogicalBlockLength;
305 static bool QualifyDevice(uint8_t *buf)
309 bool epIn =
false, epOut =
false;
311 if ((USBH_QGetDeviceDescriptor(buf)->bDeviceClass == 0) &&
312 (USBH_QGetDeviceDescriptor(buf)->bDeviceSubClass == 0) &&
313 (USBH_QGetDeviceDescriptor(buf)->bDeviceProtocol == 0) &&
314 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceClass ==
USB_CLASS_MSD) &&
317 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints >= 2))
323 for (i = 0; i < USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints; i++)
325 if (USBH_QGetEndpointDescriptor(buf, 0, 0, i)->bmAttributes ==
USB_EPTYPE_BULK)
327 if (USBH_QGetEndpointDescriptor(buf, 0, 0, i)->bEndpointAddress &
USB_EP_DIR_IN)
350 if ((epIn && epOut) && (epInIndex < 2) && (epOutIndex < 2))
364 USBH_PrintDeviceDescriptor(USBH_QGetDeviceDescriptor(buf));
365 USBH_PrintConfigurationDescriptor(USBH_QGetConfigurationDescriptor(buf, 0),
USB_CONFIG_DESCSIZE);
366 USBH_PrintInterfaceDescriptor(USBH_QGetInterfaceDescriptor(buf, 0, 0));
368 for (i = 0; i < USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints; i++)
370 USBH_PrintEndpointDescriptor(USBH_QGetEndpointDescriptor(buf, 0, 0, i));
372 USB_PRINTF(
"\nThis is not a valid MSD device, review device descriptors.");
378 USBH_InitDeviceData(&device, buf, ep, 2, USBH_GetPortSpeed());
379 PrintDeviceStrings(buf);
380 USBH_SetAddressB(&device, DEV_ADDR);
381 USBH_SetConfigurationB(&device, device.confDesc.bConfigurationValue);
384 USBH_AssignHostChannel(BULK_OUT, 2);
385 USBH_AssignHostChannel(BULK_IN, 3);
387 USB_PRINTF(
"\n\nDevice VID/PID is 0x%04X/0x%04X, device bus speed is %s",
388 device.devDesc.idVendor, device.devDesc.idProduct,
402 static void PrintDeviceStrings(uint8_t *buf)
406 if (device.devDesc.iManufacturer)
408 USBH_GetStringB(&device, buf, 255, device.devDesc.iManufacturer,
410 USBH_PrintString(
"\n\niManufacturer = \"",
418 if (device.devDesc.iProduct)
420 USBH_GetStringB(&device, buf, 255, device.devDesc.iProduct,
422 USBH_PrintString(
"\niProduct = \"",
430 if (device.devDesc.iSerialNumber)
432 USBH_GetStringB(&device, buf, 255, device.devDesc.iSerialNumber,
434 USBH_PrintString(
"\niSerialNumber = \"",
bool MSDSCSI_TestUnitReady(void)
Issue a SCSI Test Unit Ready command.
SCSI Inquiry response data typedef.
bool MSDH_WriteSectors(uint32_t lba, uint16_t sectors, const void *data)
Write sectors to device.
SCSI Request Sense response data typedef.
int USB_PRINTF(const char *format,...)
Transmit "printf" formated data on the debug serial port.
CMSIS Cortex-M Peripheral Access Layer for Silicon Laboratories microcontroller devices.
#define SL_ALIGN(X)
Macro for aligning a variable. Use this macro before the variable definition. X denotes the stora...
bool MSDH_ReadSectors(uint32_t lba, uint16_t sectors, void *data)
Read sectors from device.
SCSI Read Capacity response data typedef.
bool MSDH_GetBlockSize(uint32_t *blockSize)
Get blocksize from the device.
#define USB_CLASS_MSD_BOT_TRANSPORT
bool MSDSCSI_Write10(uint32_t lba, uint16_t sectors, const void *data)
Perform a SCSI Write(10) command.
void USBTIMER_DelayMs(uint32_t msec)
Active wait millisecond delay function. Can also be used inside interrupt handlers.
bool MSDH_GetSectorSize(uint16_t *sectorSize)
Get sectorsize from the device.
SCSI interface for Mass Storage Devices (MSD).
#define USB_CONFIG_DESCSIZE
#define SL_ATTRIBUTE_ALIGN(X)
GCC style macro for aligning a variable.
bool MSDH_Init(uint8_t *usbDeviceInfo, int usbDeviceInfoSize)
Initialize an USB connected Mass Storage Device. Checks if the device is a valid MSD device...
USB protocol stack library API for EFM32/EZR32.
#define USB_CLASS_MSD_SCSI_CMDSET
bool MSDSCSI_RequestSense(MSDSCSI_RequestSenseData_TypeDef *data)
Issue a SCSI Request Sense command.
bool MSDH_GetSectorCount(uint32_t *sectorCount)
Get sectorcount from the device.
bool MSDSCSI_Init(USBH_Ep_TypeDef *out, USBH_Ep_TypeDef *in)
MSDSCSI module initialization.
bool MSDSCSI_Read10(uint32_t lba, uint16_t sectors, void *data)
Issue a SCSI Read(10) command.
bool MSDSCSI_ReadCapacity(MSDSCSI_ReadCapacityData_TypeDef *data)
Issue a SCSI Read Capacity command.
bool MSDSCSI_Inquiry(MSDSCSI_InquiryData_TypeDef *data)
Issue a SCSI Inquiry command.