Skip to content

Commit eb932cd

Browse files
committed
add msc multiple lun support
1 parent 39f8118 commit eb932cd

File tree

6 files changed

+107
-55
lines changed

6 files changed

+107
-55
lines changed

examples/msc_ramdisk/msc_ramdisk.ino

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ Adafruit_USBD_MSC usbmsc;
77
void setup()
88
{
99
// block count and size are defined in variant.h
10-
usbmsc.setCapacity(DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
11-
usbmsc.setCallback(ram_read_cb, ram_write_cb, ram_flush_cb);
10+
usbmsc.setCapacity(0, DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
11+
usbmsc.setCallback(0, ram_read_cb, ram_write_cb, ram_flush_cb);
1212
usbmsc.begin();
1313

1414
Serial.begin(115200);
@@ -22,27 +22,31 @@ void loop()
2222
// nothing to do
2323
}
2424

25-
int32_t ram_read_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
25+
// Callback invoked when received READ10 command.
26+
// Copy disk's data to buffer (up to bufsize) and
27+
// return number of copied bytes (must be multiple of block size)
28+
int32_t ram_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
2629
{
27-
(void) lun;
28-
uint8_t const* addr = msc_disk[lba] + offset;
30+
uint8_t const* addr = msc_disk[lba];
2931
memcpy(buffer, addr, bufsize);
3032

3133
return bufsize;
3234
}
3335

34-
int32_t ram_write_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
36+
// Callback invoked when received WRITE10 command.
37+
// Process data in buffer to disk's storage and
38+
// return number of written bytes (must be multiple of block size)
39+
int32_t ram_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
3540
{
36-
(void) lun;
37-
38-
uint8_t* addr = msc_disk[lba] + offset;
41+
uint8_t* addr = msc_disk[lba];
3942
memcpy(addr, buffer, bufsize);
4043

4144
return bufsize;
4245
}
4346

44-
void ram_flush_cb (uint8_t lun)
47+
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
48+
// used to flush any pending cache.
49+
void ram_flush_cb (void)
4550
{
46-
(void) lun;
4751
// nothing to do
4852
}

examples/msc_ramdisk/ramdisk.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,14 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
4242
// fat_num = 1; fat12_root_entry_num = 16;
4343
// sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0;
4444
// drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29;
45-
// filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "tinyusb msc";
45+
// filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC";
46+
// FAT magic code at offset 510-511
4647
{
4748
0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00,
4849
0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
49-
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 0x74, 0x69, 0x6E, 0x79, 0x75,
50-
0x73, 0x62, 0x20, 0x6D, 0x73, 0x63, 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
51-
50+
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' ,
51+
'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00,
52+
5253
// Zero up to 2 last bytes of FAT magic code
5354
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5455
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -76,11 +77,11 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
7677
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7778
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
7879
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79-
80+
8081
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8182
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
8283
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA, // FAT magic code at 510-511
84+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA
8485
},
8586

8687
//------------- Block1: FAT12 Table -------------//
@@ -91,7 +92,7 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] =
9192
//------------- Block2: Root Directory -------------//
9293
{
9394
// first entry is volume label
94-
0x54, 0x49, 0x4E, 0x59, 0x55, 0x53, 0x42, 0x20, 0x4D, 0x53, 0x43, 0x08, 0x00, 0x00, 0x00, 0x00,
95+
'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00,
9596
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9697
// second entry is readme file
9798
'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D,

src/Adafruit_USBD_HID.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,15 @@ bool Adafruit_USBD_HID::begin(void)
6565

6666
return true;
6767
}
68+
69+
bool Adafruit_USBD_HID::ready(void)
70+
{
71+
return tud_hid_ready();
72+
}
73+
74+
bool Adafruit_USBD_HID::sendReport(uint8_t report_id, void const* report, uint8_t len)
75+
{
76+
return tud_hid_report(report_id, report, len);
77+
}
78+
79+

src/Adafruit_USBD_HID.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,30 @@
3030
class Adafruit_USBD_HID : Adafruit_USBD_Interface
3131
{
3232
public:
33+
typedef uint16_t (*get_report_callback_t) (uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen);
34+
typedef void (*set_report_callback_t)(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize);
35+
3336
Adafruit_USBD_HID(void);
3437

3538
void setBootProtocol(uint8_t protocol); // 0: None, 1: Keyboard, 2:Mouse
3639
void setReportDescriptor(uint8_t const* desc_report, uint16_t len);
40+
void setReportCallback();
3741

3842
bool begin(void);
3943

44+
bool ready(void);
45+
bool sendReport(uint8_t report_id, void const* report, uint8_t len);
46+
4047
// from Adafruit_USBD_Interface
4148
virtual uint16_t getDescriptor(uint8_t* buf, uint16_t bufsize);
4249

4350
private:
4451
uint8_t _protocol;
4552
uint8_t const* _desc_report;
4653
uint16_t _desc_report_len;
54+
55+
get_report_callback_t _get_report_cb;
56+
set_report_callback_t _set_report_cb;
4757
};
4858

4959
#endif /* ADAFRUIT_USBD_HID_H_ */

src/Adafruit_USBD_MSC.cpp

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@ static Adafruit_USBD_MSC* _msc_dev = NULL;
3232

3333
Adafruit_USBD_MSC::Adafruit_USBD_MSC(void)
3434
{
35-
_block_count = 0;
36-
_block_size = 0;
35+
_maxlun = 1;
36+
memset(_lun, 0, sizeof(_lun));
3737
}
3838

3939
uint16_t Adafruit_USBD_MSC::getDescriptor(uint8_t* buf, uint16_t bufsize)
@@ -46,23 +46,33 @@ uint16_t Adafruit_USBD_MSC::getDescriptor(uint8_t* buf, uint16_t bufsize)
4646
return len;
4747
}
4848

49-
void Adafruit_USBD_MSC::setCapacity(uint32_t block_count, uint16_t block_size)
49+
void Adafruit_USBD_MSC::setMaxLun(uint8_t maxlun)
5050
{
51-
_block_count = block_count;
52-
_block_size = block_size;
51+
_maxlun = maxlun;
5352
}
5453

55-
void Adafruit_USBD_MSC::getCapacity(uint32_t* block_count, uint16_t* block_size)
54+
uint8_t Adafruit_USBD_MSC::getMaxLun(void)
5655
{
57-
(*block_count) = _block_count;
58-
(*block_size) = _block_size;
56+
return _maxlun;
5957
}
6058

61-
void Adafruit_USBD_MSC::setCallback(read_callback_t rd_cb, write_callback_t wr_cb, flush_callback_t fl_cb)
59+
void Adafruit_USBD_MSC::setCapacity(uint8_t lun, uint32_t block_count, uint16_t block_size)
6260
{
63-
_rd_cb = rd_cb;
64-
_wr_cb = wr_cb;
65-
_fl_cb = fl_cb;
61+
_lun[lun].block_count = block_count;
62+
_lun[lun].block_size = block_size;
63+
}
64+
65+
void Adafruit_USBD_MSC::getCapacity(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
66+
{
67+
*block_count = _lun[lun].block_count;
68+
*block_size = _lun[lun].block_size;
69+
}
70+
71+
void Adafruit_USBD_MSC::setCallback(uint8_t lun, read_callback_t rd_cb, write_callback_t wr_cb, flush_callback_t fl_cb)
72+
{
73+
_lun[lun].rd_cb = rd_cb;
74+
_lun[lun].wr_cb = wr_cb;
75+
_lun[lun].fl_cb = fl_cb;
6676
}
6777

6878
bool Adafruit_USBD_MSC::begin(void)
@@ -76,6 +86,20 @@ bool Adafruit_USBD_MSC::begin(void)
7686
extern "C"
7787
{
7888

89+
// Invoked to determine max LUN
90+
uint8_t tud_msc_maxlun_cb(void)
91+
{
92+
if (!_msc_dev) return 0;
93+
return _msc_dev->getMaxLun();
94+
}
95+
96+
// Callback invoked to determine disk's size
97+
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
98+
{
99+
if (!_msc_dev) return;
100+
_msc_dev->getCapacity(lun, block_count, block_size);
101+
}
102+
79103
// Callback invoked when received an SCSI command not in built-in list below
80104
// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
81105
// - READ10 and WRITE10 has their own callbacks
@@ -132,36 +156,28 @@ int32_t tud_msc_scsi_cb (uint8_t lun, const uint8_t scsi_cmd[16], void* buffer,
132156
// Copy disk's data to buffer (up to bufsize) and return number of copied bytes.
133157
int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize)
134158
{
135-
if ( !(_msc_dev && _msc_dev->_rd_cb) ) return -1;
159+
if ( !(_msc_dev && _msc_dev->_lun[lun].rd_cb) ) return -1;
136160

137-
return _msc_dev->_rd_cb(lun, lba, offset, buffer, bufsize);
161+
return _msc_dev->_lun[lun].rd_cb(lba, buffer, bufsize);
138162
}
139163

140164
// Callback invoked when received WRITE10 command.
141165
// Process data in buffer to disk's storage and return number of written bytes
142166
int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize)
143167
{
144-
if ( !(_msc_dev && _msc_dev->_wr_cb) ) return -1;
168+
if ( !(_msc_dev && _msc_dev->_lun[lun].wr_cb) ) return -1;
145169

146-
return _msc_dev->_wr_cb(lun, lba, offset, buffer, bufsize);
170+
return _msc_dev->_lun[lun].wr_cb(lba, buffer, bufsize);
147171
}
148172

149173
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
150174
// used to flush any pending cache.
151175
void tud_msc_write10_complete_cb (uint8_t lun)
152176
{
153-
if ( !(_msc_dev && _msc_dev->_fl_cb) ) return;
177+
if ( !(_msc_dev && _msc_dev->_lun[lun].fl_cb) ) return;
154178

155179
// flush pending cache when write10 is complete
156-
return _msc_dev->_fl_cb(lun);
157-
}
158-
159-
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
160-
{
161-
(void) lun;
162-
if (!_msc_dev) return;
163-
164-
_msc_dev->getCapacity(block_count, block_size);
180+
return _msc_dev->_lun[lun].fl_cb();
165181
}
166182

167183
}

src/Adafruit_USBD_MSC.h

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,28 +30,37 @@
3030
class Adafruit_USBD_MSC : Adafruit_USBD_Interface
3131
{
3232
public:
33-
typedef int32_t (*read_callback_t ) (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize);
34-
typedef int32_t (*write_callback_t) (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize);
35-
typedef void (*flush_callback_t) (uint8_t lun);
33+
typedef int32_t (*read_callback_t ) (uint32_t lba, void* buffer, uint32_t bufsize);
34+
typedef int32_t (*write_callback_t) (uint32_t lba, uint8_t* buffer, uint32_t bufsize);
35+
typedef void (*flush_callback_t) (void);
3636

3737
Adafruit_USBD_MSC(void);
3838

3939
bool begin(void);
4040

41-
void setCapacity(uint32_t block_count, uint16_t block_size);
42-
void getCapacity(uint32_t* block_count, uint16_t* block_size);
43-
void setCallback(read_callback_t rd_cb, write_callback_t wr_cb, flush_callback_t fl_cb);
41+
void setMaxLun(uint8_t maxlun);
42+
uint8_t getMaxLun(void);
43+
44+
void setCapacity(uint8_t lun, uint32_t block_count, uint16_t block_size);
45+
void getCapacity(uint8_t lun, uint32_t* block_count, uint16_t* block_size);
46+
47+
void setCallback(uint8_t lun, read_callback_t rd_cb, write_callback_t wr_cb, flush_callback_t fl_cb);
4448

4549
// from Adafruit_USBD_Interface
4650
virtual uint16_t getDescriptor(uint8_t* buf, uint16_t bufsize);
4751

4852
private:
49-
uint32_t _block_count;
50-
uint16_t _block_size;
53+
enum { MAX_LUN = 2 };
54+
struct {
55+
read_callback_t rd_cb;
56+
write_callback_t wr_cb;
57+
flush_callback_t fl_cb;
58+
59+
uint32_t block_count;
60+
uint16_t block_size;
61+
} _lun[MAX_LUN];
5162

52-
read_callback_t _rd_cb;
53-
write_callback_t _wr_cb;
54-
flush_callback_t _fl_cb;
63+
uint8_t _maxlun;
5564

5665
friend int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize);
5766
friend int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize);

0 commit comments

Comments
 (0)