28static volatile uint8_t g_fat_drv_used[USBDRV_CNT];
29static TCHAR _path[3] = {
'3',
':', 0 };
31static void fatfs_drive_int()
33 memset((uint8_t *)g_fat_drv_used, 0,
sizeof(g_fat_drv_used));
36static int fatfs_drive_alloc()
40 for (i = 0; i < USBDRV_CNT; i++)
42 if (g_fat_drv_used[i] == 0)
44 g_fat_drv_used[i] = 1;
48 msc_debug_msg(
"Memory out! No free FATFS USB drive slots!\n");
52static void fatfs_drive_free(
int drv_no)
54 _path[0] = drv_no +
'0';
55 f_mount(
NULL, _path, 1);
56 g_fat_drv_used[drv_no-USBDRV_0] = 0;
59static MSC_T * find_msc_by_drive(
int drv_no)
61 MSC_T *msc = g_msc_list;
65 if (msc->drv_no == drv_no)
72static void msc_list_add(MSC_T *msc)
74 if (g_msc_list ==
NULL)
81 msc->next = g_msc_list;
86static void msc_list_remove(MSC_T *msc)
90 if (g_msc_list == msc)
92 g_msc_list = msc->next;
97 while ((p->next != msc) && (p->next !=
NULL))
110static void get_max_lun(MSC_T *msc)
112 UDEV_T *udev = msc->iface->udev;
114 uint8_t buff[2] = { 0, 0 };
122 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE,
123 0xFE, 0, msc->iface->if_num, 1, buff, &read_len, 200);
126 msc_debug_msg(
"Get Max Lun command failed! Assign 0...\n");
129 usbh_clear_halt(udev, 0);
132 msc->max_lun = buff[0];
133 msc_debug_msg(
"Max lun is %d\n", msc->max_lun);
136void msc_reset(MSC_T *msc)
138 UDEV_T *udev = msc->iface->udev;
142 msc_debug_msg(
"Reset MSC device...\n");
144 ret = usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_CLASS_DEV | REQ_TYPE_TO_IFACE,
145 0xFF, 0, msc->iface->if_num, 0,
NULL, &read_len, 100);
148 msc_debug_msg(
"UAMSS reset request failed!\n");
150 usbh_clear_halt(udev, msc->ep_bulk_out->bEndpointAddress);
151 usbh_clear_halt(udev, msc->ep_bulk_in->bEndpointAddress);
154static int msc_inquiry(MSC_T *msc)
156 struct bulk_cb_wrap *cmd_blk = &msc->cmd_blk;
159 msc_debug_msg(
"INQUIRY...\n");
160 memset(cmd_blk, 0,
sizeof(*cmd_blk));
162 cmd_blk->Flags = 0x80;
164 cmd_blk->CDB[0] = INQUIRY;
165 cmd_blk->CDB[1] = msc->lun << 5;
166 cmd_blk->CDB[4] = 36;
171 msc_debug_msg(
"INQUIRY command failed. [%d]\n", ret);
176 msc_debug_msg(
"INQUIRY command success.\n");
181static int msc_request_sense(MSC_T *msc)
183 struct bulk_cb_wrap *cmd_blk = &msc->cmd_blk;
186 msc_debug_msg(
"REQUEST_SENSE...\n");
187 memset(cmd_blk, 0,
sizeof(*cmd_blk));
189 cmd_blk->Flags = 0x80;
191 cmd_blk->CDB[0] = REQUEST_SENSE;
192 cmd_blk->CDB[1] = msc->lun << 5;
193 cmd_blk->CDB[4] = 18;
198 msc_debug_msg(
"REQUEST_SENSE command failed.\n");
205 msc_debug_msg(
"REQUEST_SENSE command success.\n");
206 if (msc->scsi_buff[2] != 0x6)
208 msc_debug_msg(
"Device is still not attention. 0x%x\n", msc->scsi_buff[2]);
215static int msc_test_unit_ready(MSC_T *msc)
217 struct bulk_cb_wrap *cmd_blk = &msc->cmd_blk;
220 msc_debug_msg(
"TEST_UNIT_READY...\n");
221 memset(cmd_blk, 0,
sizeof(*cmd_blk));
223 cmd_blk->Flags = 0x80;
225 cmd_blk->CDB[0] = TEST_UNIT_READY;
226 cmd_blk->CDB[1] = msc->lun << 5;
237 msc_debug_msg(
"TEST_UNIT_READY command success.\n");
254int usbh_umas_read(
int drv_no, uint32_t sec_no,
int sec_cnt, uint8_t *buff)
257 struct bulk_cb_wrap *cmd_blk;
262 msc = find_msc_by_drive(drv_no);
266 cmd_blk = &msc->cmd_blk;
269 memset(cmd_blk, 0,
sizeof(*cmd_blk));
271 cmd_blk->Flags = 0x80;
272 cmd_blk->Length = 10;
273 cmd_blk->CDB[0] = READ_10;
274 cmd_blk->CDB[1] = msc->lun << 5;
275 cmd_blk->CDB[2] = (sec_no >> 24) & 0xFF;
276 cmd_blk->CDB[3] = (sec_no >> 16) & 0xFF;
277 cmd_blk->CDB[4] = (sec_no >> 8) & 0xFF;
278 cmd_blk->CDB[5] = sec_no & 0xFF;
279 cmd_blk->CDB[7] = (sec_cnt >> 8) & 0xFF;
280 cmd_blk->CDB[8] = sec_cnt & 0xFF;
285 msc_debug_msg(
"usbh_umas_read failed! [%d]\n", ret);
303int usbh_umas_write(
int drv_no, uint32_t sec_no,
int sec_cnt, uint8_t *buff)
306 struct bulk_cb_wrap *cmd_blk;
311 msc = find_msc_by_drive(drv_no);
315 cmd_blk = &msc->cmd_blk;
316 memset((uint8_t *)&(msc->cmd_blk), 0,
sizeof(msc->cmd_blk));
319 cmd_blk->Length = 10;
320 cmd_blk->CDB[0] = WRITE_10;
321 cmd_blk->CDB[1] = msc->lun << 5;
322 cmd_blk->CDB[2] = (sec_no >> 24) & 0xFF;
323 cmd_blk->CDB[3] = (sec_no >> 16) & 0xFF;
324 cmd_blk->CDB[4] = (sec_no >> 8) & 0xFF;
325 cmd_blk->CDB[5] = sec_no & 0xFF;
326 cmd_blk->CDB[7] = (sec_cnt >> 8) & 0xFF;
327 cmd_blk->CDB[8] = sec_cnt & 0xFF;
332 msc_debug_msg(
"usbh_umas_write failed!\n");
353 msc = find_msc_by_drive(drv_no);
362 case GET_SECTOR_COUNT:
363 *(uint32_t *)buff = msc->uTotalSectorN;
366 case GET_SECTOR_SIZE:
367 *(uint32_t *)buff = msc->nSectorSize;
371 *(uint32_t *)buff = msc->nSectorSize;
388 if (find_msc_by_drive(drv_no) ==
NULL)
399int usbh_umas_reset_disk(
int drv_no)
404 msc_debug_msg(
"usbh_umas_reset_disk ...\n");
406 msc = find_msc_by_drive(drv_no);
410 udev = msc->iface->udev;
412 usbh_reset_device(udev);
417static int umass_init_device(MSC_T *msc)
419 MSC_T *try_msc = msc;
420 struct bulk_cb_wrap *cmd_blk;
422 int8_t bHasMedia = 0;
425 for (lun = 0; lun <= msc->max_lun; lun++)
427 msc_debug_msg(
"\n******* Read lun %d ******\n\n", lun);
430 cmd_blk = &try_msc->cmd_blk;
432 for (retries = 0; retries < 3; retries++)
440 if (msc_test_unit_ready(try_msc) == 0)
443 if (msc_request_sense(try_msc) == 0)
457 for (retries = 0; retries < 3; retries++)
459 msc_debug_msg(
"READ CAPACITY ==>\n");
461 memset(cmd_blk, 0,
sizeof(*cmd_blk));
463 cmd_blk->Flags = 0x80;
464 cmd_blk->Length = 10;
465 cmd_blk->CDB[0] = READ_CAPACITY;
466 cmd_blk->CDB[1] = lun << 5;
471 msc_debug_msg(
"READ_CAPACITY failed!\n");
483 try_msc->uTotalSectorN = (try_msc->scsi_buff[0] << 24) | (try_msc->scsi_buff[1] << 16) |
484 (try_msc->scsi_buff[2] << 8) | try_msc->scsi_buff[3];
485 try_msc->nSectorSize = (try_msc->scsi_buff[4] << 24) | (try_msc->scsi_buff[5] << 16) |
486 (try_msc->scsi_buff[6] << 8) | try_msc->scsi_buff[7];
488 try_msc->drv_no = fatfs_drive_alloc();
489 if (try_msc->drv_no < 0)
495 msc_debug_msg(
"USB disk [%c] found: size=%d MB, uTotalSectorN=%d\n", msc->drv_no+
'0', try_msc->uTotalSectorN / 2048, try_msc->uTotalSectorN);
497 msc_list_add(try_msc);
499 _path[0] = try_msc->drv_no +
'0';
500 f_mount(&try_msc->fatfs_vol, _path, 1);
507 try_msc = usbh_alloc_mem(
sizeof(*try_msc));
513 memcpy(try_msc, msc,
sizeof(*msc));
519 usbh_free_mem(try_msc,
sizeof(*try_msc));
525static int msc_probe(IFACE_T *iface)
527 ALT_IFACE_T *aif = iface->aif;
535 if (ifd->bInterfaceClass != USB_CLASS_MASS_STORAGE)
539 if ((ifd->bInterfaceSubClass != MSC_SCLASS_SCSI) && (ifd->bInterfaceSubClass != MSC_SCLASS_8070) &&
540 (ifd->bInterfaceSubClass != MSC_SCLASS_RBC))
544 if (ifd->bInterfaceProtocol != MSC_SPROTO_BULK)
546 msc_debug_msg(
"Not bulk-only MSC device!\n");
550 msc = usbh_alloc_mem(
sizeof(*msc));
556 for (i = 0; i < aif->ifd->bNumEndpoints; i++)
558 if ((aif->ep[i].bmAttributes & EP_ATTR_TT_MASK) == EP_ATTR_TT_BULK)
560 if ((aif->ep[i].bEndpointAddress & EP_ADDR_DIR_MASK) == EP_ADDR_DIR_IN)
561 msc->ep_bulk_in = &aif->ep[i];
563 msc->ep_bulk_out = &aif->ep[i];
567 if ((msc->ep_bulk_in ==
NULL) || (msc->ep_bulk_out ==
NULL))
569 usbh_free_mem(msc,
sizeof(*msc));
575 msc_debug_msg(
"USB Mass Storage device found. Iface:%d, Alt Iface:%d, bep_in:0x%x, bep_out:0x%x\n", ifd->bInterfaceNumber, ifd->bAlternateSetting, msc->ep_bulk_in->bEndpointAddress, msc->ep_bulk_out->bEndpointAddress);
579 return umass_init_device(msc);
582static void msc_disconnect(IFACE_T *iface)
591 for (i = 0; i < iface->aif->ifd->bNumEndpoints; i++)
593 iface->udev->hc_driver->quit_xfer(
NULL, &(iface->aif->ep[i]));
603 if (msc->iface == iface)
605 fatfs_drive_free(msc->drv_no);
606 msc_list_remove(msc);
607 usbh_free_mem(msc,
sizeof(*msc));
613UDEV_DRV_T msc_driver =
635 return usbh_register_driver(&msc_driver);
NuMicro peripheral access layer header file.
#define NULL
NULL pointer.
#define UMAS_ERR_DRIVE_NOT_FOUND
#define USBH_ERR_NOT_MATCHED
#define USBH_ERR_NOT_SUPPORTED
#define USBH_ERR_NOT_FOUND
#define USBH_ERR_MEMORY_OUT
#define UMAS_ERR_IVALID_PARM
#define USBH_ERR_NOT_EXPECTED
int usbh_umas_read(int drv_no, uint32_t sec_no, int sec_cnt, uint8_t *buff)
int usbh_umas_write(int drv_no, uint32_t sec_no, int sec_cnt, uint8_t *buff)
HIDDEN_SYMBOLS int usbh_umas_init(void)
Register and initialize USB Host Mass Storage driver.
int usbh_umas_ioctl(int drv_no, int cmd, void *buff)
int usbh_umas_disk_status(int drv_no)
uint32_t get_ticks(void)
A function return current tick count.
M480 MCU USB Host mass storage class header.
int run_scsi_command(MSC_T *msc, uint8_t *buff, uint32_t data_len, int bIsDataIn, int timeout_ticks)
USB Host library header file.