1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "diskio_impl.h"
8 #include "ffconf.h"
9 #include "ff.h"
10 #include "esp_log.h"
11 #include "diskio_usb.h"
12 #include "msc_scsi_bot.h"
13 #include "msc_common.h"
14 #include "usb/usb_types_stack.h"
15 
16 static usb_disk_t *s_disks[FF_VOLUMES] = { NULL };
17 
18 static const char *TAG = "diskio_usb";
19 
usb_disk_initialize(BYTE pdrv)20 static DSTATUS usb_disk_initialize (BYTE pdrv)
21 {
22     return RES_OK;
23 }
24 
usb_disk_status(BYTE pdrv)25 static DSTATUS usb_disk_status (BYTE pdrv)
26 {
27     return RES_OK;
28 }
29 
usb_disk_read(BYTE pdrv,BYTE * buff,DWORD sector,UINT count)30 static DRESULT usb_disk_read (BYTE pdrv, BYTE *buff, DWORD sector, UINT count)
31 {
32     assert(pdrv < FF_VOLUMES);
33     assert(s_disks[pdrv]);
34 
35     esp_err_t err;
36     usb_disk_t *disk = s_disks[pdrv];
37     size_t sector_size = disk->block_size;
38     msc_device_t *dev = __containerof(disk, msc_device_t, disk);
39 
40     for (int i = 0; i < count; i++) {
41         err = scsi_cmd_read10(dev, &buff[i * sector_size], sector + i, 1, sector_size);
42         if (err != ESP_OK) {
43             ESP_LOGE(TAG, "scsi_cmd_read10 failed (%d)", err);
44             return RES_ERROR;
45         }
46 
47     }
48 
49     return RES_OK;
50 }
51 
usb_disk_write(BYTE pdrv,const BYTE * buff,DWORD sector,UINT count)52 static DRESULT usb_disk_write (BYTE pdrv, const BYTE *buff, DWORD sector, UINT count)
53 {
54     assert(pdrv < FF_VOLUMES);
55     assert(s_disks[pdrv]);
56 
57     esp_err_t err;
58     usb_disk_t *disk = s_disks[pdrv];
59     size_t sector_size = disk->block_size;
60     msc_device_t *dev = __containerof(disk, msc_device_t, disk);
61 
62     for (int i = 0; i < count; i++) {
63         err = scsi_cmd_write10(dev, &buff[i * sector_size], sector + i, 1, sector_size);
64         if (err != ESP_OK) {
65             ESP_LOGE(TAG, "scsi_cmd_write10 failed (%d)", err);
66             return RES_ERROR;
67         }
68 
69     }
70     return RES_OK;
71 }
72 
usb_disk_ioctl(BYTE pdrv,BYTE cmd,void * buff)73 static DRESULT usb_disk_ioctl (BYTE pdrv, BYTE cmd, void *buff)
74 {
75     assert(pdrv < FF_VOLUMES);
76     assert(s_disks[pdrv]);
77 
78     usb_disk_t *disk = s_disks[pdrv];
79 
80     switch (cmd) {
81     case CTRL_SYNC:
82         return RES_OK;
83     case GET_SECTOR_COUNT:
84         *((DWORD *) buff) = disk->block_count;
85         return RES_OK;
86     case GET_SECTOR_SIZE:
87         *((WORD *) buff) = disk->block_size;
88         return RES_OK;
89     case GET_BLOCK_SIZE:
90         return RES_ERROR;
91     }
92     return RES_ERROR;
93 }
94 
ff_diskio_register_msc(BYTE pdrv,usb_disk_t * disk)95 void ff_diskio_register_msc(BYTE pdrv, usb_disk_t *disk)
96 {
97     assert(pdrv < FF_VOLUMES);
98 
99     static const ff_diskio_impl_t usb_disk_impl = {
100         .init = &usb_disk_initialize,
101         .status = &usb_disk_status,
102         .read = &usb_disk_read,
103         .write = &usb_disk_write,
104         .ioctl = &usb_disk_ioctl
105     };
106     s_disks[pdrv] = disk;
107     ff_diskio_register(pdrv, &usb_disk_impl);
108 }
109 
ff_diskio_get_pdrv_disk(const usb_disk_t * disk)110 BYTE ff_diskio_get_pdrv_disk(const usb_disk_t *disk)
111 {
112     for (int i = 0; i < FF_VOLUMES; i++) {
113         if (disk == s_disks[i]) {
114             return i;
115         }
116     }
117     return 0xff;
118 }
119