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 return false;
00089
00090 memcpy(usbDeviceInfo, &inquiryData.T10VendorId, sizeof(inquiryData.T10VendorId));
00091 usbDeviceInfo[ sizeof(inquiryData.T10VendorId) ] = '\0';
00092 USB_PRINTF("\nSCSI Inquiry Vendor ID string : \"%s\"", usbDeviceInfo);
00093
00094 memcpy(usbDeviceInfo, &inquiryData.ProductId, sizeof(inquiryData.ProductId));
00095 usbDeviceInfo[ sizeof(inquiryData.ProductId) ] = '\0';
00096 USB_PRINTF("\nSCSI Inquiry Product ID string : \"%s\"", usbDeviceInfo);
00097
00098 memcpy(usbDeviceInfo, &inquiryData.ProductRevisionLevel, sizeof(inquiryData.ProductRevisionLevel));
00099 usbDeviceInfo[ sizeof(inquiryData.ProductRevisionLevel) ] = '\0';
00100 USB_PRINTF("\nSCSI Inquiry Product Revision string : \"%s\"", usbDeviceInfo);
00101
00102
00103 if ((inquiryData.PeripheralQualifier != 0) ||
00104 (inquiryData.PeripheralDeviceType != 0))
00105 return false;
00106
00107
00108 i = 0;
00109 do
00110 {
00111 result = MSDSCSI_RequestSense(&reqSenseData);
00112 ready = MSDSCSI_TestUnitReady();
00113 if (!ready)
00114 USBTIMER_DelayMs(500);
00115 i++;
00116 } while (!ready && i < 10 && result);
00117
00118 if (!result)
00119 {
00120 USB_PRINTF("\n\nSCSI Request Sense execution error");
00121 return false;
00122 }
00123
00124 if (!ready)
00125 {
00126 USB_PRINTF("\n\nMSD device not ready");
00127 return false;
00128 }
00129
00130
00131 if (!MSDSCSI_ReadCapacity(&capacityData))
00132 {
00133 USB_PRINTF("\n\nSCSI Read Capacity execution error");
00134 return false;
00135 }
00136
00137 USB_PRINTF("\n\nSCSI Read Capacity LBA count : %ld = %ld MiB",
00138 capacityData.LogicalBlockAddress,
00139 (capacityData.LogicalBlockAddress * capacityData.LogicalBlockLength) / (1024 * 1024));
00140 USB_PRINTF("\nSCSI Read Capacity LBA size : %ld\n\n", capacityData.LogicalBlockLength);
00141
00142 return true;
00143 }
00144
00145
00155 bool MSDH_GetSectorCount(uint32_t *sectorCount)
00156 {
00157 EFM32_ALIGN(4)
00158 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00159
00160 if (!MSDSCSI_ReadCapacity(&capacityData))
00161 return false;
00162
00163 *sectorCount = capacityData.LogicalBlockAddress;
00164
00165 return true;
00166 }
00167
00168
00178 bool MSDH_GetSectorSize(uint16_t *sectorSize)
00179 {
00180 EFM32_ALIGN(4)
00181 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00182
00183 if (!MSDSCSI_ReadCapacity(&capacityData))
00184 return false;
00185
00186 *sectorSize = (uint16_t) capacityData.LogicalBlockLength;
00187
00188 return true;
00189 }
00190
00191
00204 bool MSDH_GetBlockSize(uint32_t *blockSize)
00205 {
00206 EFM32_ALIGN(4)
00207 MSDSCSI_ReadCapacityData_TypeDef capacityData __attribute__ ((aligned(4)));
00208
00209 if (!MSDSCSI_ReadCapacity(&capacityData))
00210 return false;
00211
00212 *blockSize = capacityData.LogicalBlockLength;
00213
00214 return true;
00215 }
00216
00217
00233 bool MSDH_ReadSectors(uint32_t lba, uint16_t sectors, void *data)
00234 {
00235 return MSDSCSI_Read10(lba, sectors, data);
00236 }
00237
00238
00254 bool MSDH_WriteSectors(uint32_t lba, uint16_t sectors, const void *data)
00255 {
00256 return MSDSCSI_Write10(lba, sectors, data);
00257 }
00258
00261
00272 static bool QualifyDevice(uint8_t *buf)
00273 {
00274 int i;
00275 bool retVal = false;
00276 bool epIn = false, epOut = false;
00277
00278 if ((USBH_QGetDeviceDescriptor(buf)->bDeviceClass == 0) &&
00279 (USBH_QGetDeviceDescriptor(buf)->bDeviceSubClass == 0) &&
00280 (USBH_QGetDeviceDescriptor(buf)->bDeviceProtocol == 0) &&
00281 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceClass == USB_CLASS_MSD) &&
00282 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceSubClass == USB_CLASS_MSD_SCSI_CMDSET) &&
00283 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bInterfaceProtocol == USB_CLASS_MSD_BOT_TRANSPORT) &&
00284 (USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints >= 2))
00285 {
00286
00287
00288
00289
00290 for (i = 0; i < USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints; i++)
00291 {
00292 if (USBH_QGetEndpointDescriptor(buf, 0, 0, i)->bmAttributes == USB_EPTYPE_BULK)
00293 {
00294 if (USBH_QGetEndpointDescriptor(buf, 0, 0, i)->bEndpointAddress & USB_EP_DIR_IN)
00295 {
00296 if (!epIn)
00297 {
00298 epIn = true;
00299 epInIndex = i;
00300 }
00301 }
00302 else
00303 {
00304 if (!epOut)
00305 {
00306 epOut = true;
00307 epOutIndex = i;
00308 }
00309 }
00310 }
00311
00312
00313 if (epIn && epOut)
00314 break;
00315 }
00316
00317 if ((epIn && epOut) && (epInIndex < 2) && (epOutIndex < 2))
00318 {
00319
00320
00321
00322
00323
00324 USB_PRINTF("\nThis is a valid MSD device.");
00325 retVal = true;
00326 }
00327 }
00328
00329 if (retVal == false)
00330 {
00331 USBH_PrintDeviceDescriptor(USBH_QGetDeviceDescriptor(buf));
00332 USBH_PrintConfigurationDescriptor(USBH_QGetConfigurationDescriptor(buf, 0), USB_CONFIG_DESCSIZE);
00333 USBH_PrintInterfaceDescriptor(USBH_QGetInterfaceDescriptor(buf, 0, 0));
00334
00335 for (i = 0; i < USBH_QGetInterfaceDescriptor(buf, 0, 0)->bNumEndpoints; i++)
00336 {
00337 USBH_PrintEndpointDescriptor(USBH_QGetEndpointDescriptor(buf, 0, 0, i));
00338 }
00339 USB_PRINTF("\nThis is not a valid MSD device, review device descriptors.");
00340 }
00341 else
00342 {
00343
00344
00345 USBH_InitDeviceData(&device, buf, ep, 2, USBH_GetPortSpeed());
00346 USBH_SetAddressB(&device, DEV_ADDR);
00347 USBH_SetConfigurationB(&device, device.confDesc.bConfigurationValue);
00348
00349
00350 USBH_AssignHostChannel(BULK_OUT, 2);
00351 USBH_AssignHostChannel(BULK_IN, 3);
00352
00353 USB_PRINTF("\n\nDevice VID/PID is 0x%04X/0x%04X, device bus speed is %s",
00354 device.devDesc.idVendor, device.devDesc.idProduct,
00355 USBH_GetPortSpeed() == PORT_FULL_SPEED ? "FULL" : "LOW");
00356
00357 PrintDeviceStrings(buf);
00358 }
00359
00360 return retVal;
00361 }
00362
00363
00370 static void PrintDeviceStrings(uint8_t *buf)
00371 {
00372
00373
00374 if (device.devDesc.iManufacturer)
00375 {
00376 USBH_GetStringB(&device, buf, 255, device.devDesc.iManufacturer,
00377 USB_LANGID_ENUS);
00378 USBH_PrintString("\n\niManufacturer = \"",
00379 (USB_StringDescriptor_TypeDef*) buf, "\"");
00380 }
00381 else
00382 {
00383 USB_PRINTF("\n\niManufacturer = <NONE>");
00384 }
00385
00386 if (device.devDesc.iProduct)
00387 {
00388 USBH_GetStringB(&device, buf, 255, device.devDesc.iProduct,
00389 USB_LANGID_ENUS);
00390 USBH_PrintString("\niProduct = \"",
00391 (USB_StringDescriptor_TypeDef*) buf, "\"");
00392 }
00393 else
00394 {
00395 USB_PRINTF("\niProduct = <NONE>");
00396 }
00397
00398 if (device.devDesc.iSerialNumber)
00399 {
00400 USBH_GetStringB(&device, buf, 255, device.devDesc.iSerialNumber,
00401 USB_LANGID_ENUS);
00402 USBH_PrintString("\niSerialNumber = \"",
00403 (USB_StringDescriptor_TypeDef*) buf, "\"\n");
00404 }
00405 else
00406 {
00407 USB_PRINTF("\niSerialNumber = <NONE>\n");
00408 }
00409 }
00410