00001
00017 #include <inttypes.h>
00018 #include "em_device.h"
00019 #include "em_usb.h"
00020 #include "msdscsi.h"
00021
00024 #define DEV_ADDR 1
00025 #define BULK_OUT &ep[ epOutIndex ]
00026 #define BULK_IN &ep[ epInIndex ]
00027
00028 static void PrintDeviceStrings(uint8_t *buf);
00029 static bool QualifyDevice(uint8_t *buf);
00030
00031 static USBH_Device_TypeDef device;
00032 static USBH_Ep_TypeDef ep[ 2 ];
00033 static int epOutIndex;
00034 static int epInIndex;
00035
00038
00059 bool MSDH_Init(uint8_t *usbDeviceInfo, int usbDeviceInfoSize)
00060 {
00061 EFM32_ALIGN(4)
00062 MSDSCSI_InquiryData_TypeDef inquiryData __attribute__ ((aligned(4)));
00063
00064 EFM32_ALIGN(4)
00065 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00066
00067 EFM32_ALIGN(4)
00068 MSDSCSI_RequestSenseData_TypeDef reqSenseData __attribute__ ((aligned(4)));
00069
00070 bool ready;
00071 int result, i;
00072
00073
00074 if (USBH_QueryDeviceB(usbDeviceInfo, usbDeviceInfoSize, USBH_GetPortSpeed())
00075 != USB_STATUS_OK)
00076 return false;
00077
00078
00079 if (!QualifyDevice(usbDeviceInfo))
00080 return false;
00081
00082
00083 if (!MSDSCSI_Init(BULK_OUT, BULK_IN))
00084 return false;
00085
00086
00087 if (!MSDSCSI_Inquiry(&inquiryData))
00088 {
00089
00090 if (!MSDSCSI_Inquiry(&inquiryData))
00091 return false;
00092 }
00093
00094 memcpy(usbDeviceInfo, &inquiryData.T10VendorId, sizeof(inquiryData.T10VendorId));
00095 usbDeviceInfo[ sizeof(inquiryData.T10VendorId) ] = '\0';
00096 USB_PRINTF("\nSCSI Inquiry Vendor ID string : \"%s\"", usbDeviceInfo);
00097
00098 memcpy(usbDeviceInfo, &inquiryData.ProductId, sizeof(inquiryData.ProductId));
00099 usbDeviceInfo[ sizeof(inquiryData.ProductId) ] = '\0';
00100 USB_PRINTF("\nSCSI Inquiry Product ID string : \"%s\"", usbDeviceInfo);
00101
00102 memcpy(usbDeviceInfo, &inquiryData.ProductRevisionLevel, sizeof(inquiryData.ProductRevisionLevel));
00103 usbDeviceInfo[ sizeof(inquiryData.ProductRevisionLevel) ] = '\0';
00104 USB_PRINTF("\nSCSI Inquiry Product Revision string : \"%s\"", usbDeviceInfo);
00105
00106
00107 if ((inquiryData.PeripheralQualifier != 0) ||
00108 (inquiryData.PeripheralDeviceType != 0))
00109 return false;
00110
00111
00112 i = 0;
00113 do
00114 {
00115 result = MSDSCSI_RequestSense(&reqSenseData);
00116 ready = MSDSCSI_TestUnitReady();
00117 if (!ready)
00118 USBTIMER_DelayMs(500);
00119 i++;
00120 } while (!ready && i < 10 && result);
00121
00122 if (!result)
00123 {
00124 USB_PRINTF("\n\nSCSI Request Sense execution error");
00125 return false;
00126 }
00127
00128 if (!ready)
00129 {
00130 USB_PRINTF("\n\nMSD device not ready");
00131 return false;
00132 }
00133
00134
00135 if (!MSDSCSI_ReadCapacity(&capacityData))
00136 {
00137 USB_PRINTF("\n\nSCSI Read Capacity execution error");
00138 return false;
00139 }
00140
00141 USB_PRINTF("\n\nSCSI Read Capacity LBA count : %ld = %ld MiB",
00142 capacityData.LogicalBlockAddress,
00143 (uint32_t)
00144 (((uint64_t)capacityData.LogicalBlockAddress
00145 * capacityData.LogicalBlockLength) / (1024 * 1024)));
00146 USB_PRINTF("\nSCSI Read Capacity LBA size : %ld\n\n",
00147 capacityData.LogicalBlockLength);
00148
00149 return true;
00150 }
00151
00152
00162 bool MSDH_GetSectorCount(uint32_t *sectorCount)
00163 {
00164 EFM32_ALIGN(4)
00165 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00166
00167 if (!MSDSCSI_ReadCapacity(&capacityData))
00168 return false;
00169
00170 *sectorCount = capacityData.LogicalBlockAddress;
00171
00172 return true;
00173 }
00174
00175
00185 bool MSDH_GetSectorSize(uint16_t *sectorSize)
00186 {
00187 EFM32_ALIGN(4)
00188 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00189
00190 if (!MSDSCSI_ReadCapacity(&capacityData))
00191 return false;
00192
00193 *sectorSize = (uint16_t) capacityData.LogicalBlockLength;
00194
00195 return true;
00196 }
00197
00198
00211 bool MSDH_GetBlockSize(uint32_t *blockSize)
00212 {
00213 EFM32_ALIGN(4)
00214 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00215
00216 if (!MSDSCSI_ReadCapacity(&capacityData))
00217 return false;
00218
00219 *blockSize = capacityData.LogicalBlockLength;
00220
00221 return true;
00222 }
00223
00224
00240 bool MSDH_ReadSectors(uint32_t lba, uint16_t sectors, void *data)
00241 {
00242 return MSDSCSI_Read10(lba, sectors, data);
00243 }
00244
00245
00261 bool MSDH_WriteSectors(uint32_t lba, uint16_t sectors, const void *data)
00262 {
00263 return MSDSCSI_Write10(lba, sectors, data);
00264 }
00265
00268
00279 static bool QualifyDevice(uint8_t *buf)
00280 {
00281 int i;
00282 bool retVal = false;
00283 bool epIn = false, epOut = false;
00284
00285 if ((USBH_QGetDeviceDescriptor(buf)->bDeviceClass == 0) &&
00286 (USBH_QGetDeviceDescriptor(buf)->bDeviceSubClass == 0) &&
00287 (USBH_QGetDeviceDescriptor(buf)->bDeviceProtocol == 0) &&
00288 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceClass == USB_CLASS_MSD) &&
00289 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceSubClass == USB_CLASS_MSD_SCSI_CMDSET) &&
00290 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceProtocol == USB_CLASS_MSD_BOT_TRANSPORT) &&
00291 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints >= 2))
00292 {
00293
00294
00295
00296
00297 for (i = 0; i < USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints; i++)
00298 {
00299 if (USBH_QGetEndpointDescriptor(buf, 0, 0, i)->bmAttributes == USB_EPTYPE_BULK)
00300 {
00301 if (USBH_QGetEndpointDescriptor(buf, 0, 0, i)->bEndpointAddress & USB_EP_DIR_IN)
00302 {
00303 if (!epIn)
00304 {
00305 epIn = true;
00306 epInIndex = i;
00307 }
00308 }
00309 else
00310 {
00311 if (!epOut)
00312 {
00313 epOut = true;
00314 epOutIndex = i;
00315 }
00316 }
00317 }
00318
00319
00320 if (epIn && epOut)
00321 break;
00322 }
00323
00324 if ((epIn && epOut) && (epInIndex < 2) && (epOutIndex < 2))
00325 {
00326
00327
00328
00329
00330
00331 USB_PRINTF("\nThis is a valid MSD device.");
00332 retVal = true;
00333 }
00334 }
00335
00336 if (retVal == false)
00337 {
00338 USBH_PrintDeviceDescriptor(USBH_QGetDeviceDescriptor(buf));
00339 USBH_PrintConfigurationDescriptor(USBH_QGetConfigurationDescriptor(buf, 0), USB_CONFIG_DESCSIZE);
00340 USBH_PrintInterfaceDescriptor(USBH_QGetInterfaceDescriptor(buf, 0, 0));
00341
00342 for (i = 0; i < USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints; i++)
00343 {
00344 USBH_PrintEndpointDescriptor(USBH_QGetEndpointDescriptor(buf, 0, 0, i));
00345 }
00346 USB_PRINTF("\nThis is not a valid MSD device, review device descriptors.");
00347 }
00348 else
00349 {
00350
00351
00352 USBH_InitDeviceData(&device, buf, ep, 2, USBH_GetPortSpeed());
00353 PrintDeviceStrings(buf);
00354 USBH_SetAddressB(&device, DEV_ADDR);
00355 USBH_SetConfigurationB(&device, device.confDesc.bConfigurationValue);
00356
00357
00358 USBH_AssignHostChannel(BULK_OUT, 2);
00359 USBH_AssignHostChannel(BULK_IN, 3);
00360
00361 USB_PRINTF("\n\nDevice VID/PID is 0x%04X/0x%04X, device bus speed is %s",
00362 device.devDesc.idVendor, device.devDesc.idProduct,
00363 USBH_GetPortSpeed() == PORT_FULL_SPEED ? "FULL" : "LOW");
00364 }
00365
00366 return retVal;
00367 }
00368
00369
00376 static void PrintDeviceStrings(uint8_t *buf)
00377 {
00378
00379
00380 if (device.devDesc.iManufacturer)
00381 {
00382 USBH_GetStringB(&device, buf, 255, device.devDesc.iManufacturer,
00383 USB_LANGID_ENUS);
00384 USBH_PrintString("\n\niManufacturer = \"",
00385 (USB_StringDescriptor_TypeDef*) buf, "\"");
00386 }
00387 else
00388 {
00389 USB_PRINTF("\n\niManufacturer = <NONE>");
00390 }
00391
00392 if (device.devDesc.iProduct)
00393 {
00394 USBH_GetStringB(&device, buf, 255, device.devDesc.iProduct,
00395 USB_LANGID_ENUS);
00396 USBH_PrintString("\niProduct = \"",
00397 (USB_StringDescriptor_TypeDef*) buf, "\"");
00398 }
00399 else
00400 {
00401 USB_PRINTF("\niProduct = <NONE>");
00402 }
00403
00404 if (device.devDesc.iSerialNumber)
00405 {
00406 USBH_GetStringB(&device, buf, 255, device.devDesc.iSerialNumber,
00407 USB_LANGID_ENUS);
00408 USBH_PrintString("\niSerialNumber = \"",
00409 (USB_StringDescriptor_TypeDef*) buf, "\"\n");
00410 }
00411 else
00412 {
00413 USB_PRINTF("\niSerialNumber = <NONE>\n");
00414 }
00415 }
00416