Skip to content

Commit 154fde4

Browse files
committed
MSC add optional ready callback, also add setUnitReady() API
1 parent e694841 commit 154fde4

File tree

5 files changed

+151
-10
lines changed

5 files changed

+151
-10
lines changed

examples/msc_ramdisk/msc_ramdisk.ino

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ void setup()
4141
usb_msc.setCapacity(0, DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
4242

4343
// Set callback
44-
usb_msc.setCallback(0, ram_read_cb, ram_write_cb, ram_flush_cb);
44+
usb_msc.setReadWriteCallback(0, ram_read_cb, ram_write_cb, ram_flush_cb);
45+
46+
// Set Lun ready (RAM disk is always ready)
47+
usb_msc.setUnitReady(0, true);
4548

4649
usb_msc.begin();
4750

examples/msc_ramdisk_dual/msc_ramdisk_dual.ino

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ void setup()
3939
// Set disk size and callback for Logical Unit 0 (LUN 0)
4040
usb_msc.setID(0, "Adafruit", "Lun0", "1.0");
4141
usb_msc.setCapacity(0, DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
42-
usb_msc.setCallback(0, ram0_read_cb, ram0_write_cb, ram0_flush_cb);
42+
usb_msc.setReadWriteCallback(0, ram0_read_cb, ram0_write_cb, ram0_flush_cb);
43+
usb_msc.setUnitReady(0, true);
4344

4445
// Set disk size and callback for Logical Unit 1 (LUN 1)
4546
usb_msc.setID(1, "Adafruit", "Lun1", "1.0");
4647
usb_msc.setCapacity(1, DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
47-
usb_msc.setCallback(1, ram1_read_cb, ram1_write_cb, ram1_flush_cb);
48+
usb_msc.setReadWriteCallback(1, ram1_read_cb, ram1_write_cb, ram1_flush_cb);
49+
usb_msc.setUnitReady(1, true);
4850

4951
usb_msc.begin();
5052

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2019 Ha Thach for Adafruit Industries
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*/
24+
25+
#include "Adafruit_TinyUSB.h"
26+
#include "SD.h"
27+
28+
#ifdef ARDUINO_NRF52832_FEATHER
29+
const int chipSelect = 11;
30+
#else
31+
const int chipSelect = 10;
32+
#endif
33+
34+
Adafruit_USBD_MSC usb_msc;
35+
36+
Sd2Card card;
37+
SdVolume volume;
38+
39+
// the setup function runs once when you press reset or power the board
40+
void setup()
41+
{
42+
// Set disk vendor id, product id and revision with string up to 8, 16, 4 characters respectively
43+
usb_msc.setID(0, "Adafruit", "SD Card", "1.0");
44+
45+
// Set read write callback
46+
usb_msc.setReadWriteCallback(0, sd_read_cb, sd_write_cb, sd_flush_cb);
47+
48+
// Still initialize MSC but tell usb stack that MSC is not ready to read/write
49+
// If we don't initialize, board will be enumerated as CDC only
50+
usb_msc.setUnitReady(0, false);
51+
usb_msc.begin();
52+
53+
Serial.begin(115200);
54+
while ( !Serial ) delay(10); // wait for native usb
55+
56+
Serial.println("Adafruit TinyUSB SD Card Reader example");
57+
58+
Serial.println("\nInitializing SD card...");
59+
60+
if ( !card.init(SPI_HALF_SPEED, chipSelect) )
61+
{
62+
Serial.println("initialization failed. Things to check:");
63+
Serial.println("* is a card inserted?");
64+
Serial.println("* is your wiring correct?");
65+
Serial.println("* did you change the chipSelect pin to match your shield or module?");
66+
while (1) delay(1);
67+
}
68+
69+
// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
70+
if (!volume.init(card)) {
71+
Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
72+
while (1) delay(1);
73+
}
74+
75+
uint32_t block_count = volume.blocksPerCluster()*volume.clusterCount();
76+
77+
Serial.print("Volume size (MB): ");
78+
Serial.println((block_count/2) / 1024);
79+
80+
// Set disk size, SD block size is always 512
81+
usb_msc.setCapacity(0, block_count, 512);
82+
83+
// MSC is ready for read/write
84+
usb_msc.setUnitReady(0, true);
85+
}
86+
87+
void loop()
88+
{
89+
// nothing to do
90+
}
91+
92+
int32_t sd_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
93+
{
94+
(void) bufsize;
95+
return card.readBlock(lba, (uint8_t*) buffer) ? 512 : -1;
96+
}
97+
98+
// Callback invoked when received WRITE10 command.
99+
// Process data in buffer to disk's storage and
100+
// return number of written bytes (must be multiple of block size)
101+
int32_t sd_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
102+
{
103+
return card.writeBlock(lba, buffer) ? 512 : -1;
104+
}
105+
106+
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
107+
// used to flush any pending cache.
108+
void sd_flush_cb (void)
109+
{
110+
// nothing to do
111+
}

src/Adafruit_USBD_MSC.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,23 @@ void Adafruit_USBD_MSC::getCapacity(uint8_t lun, uint32_t* block_count, uint16_t
7575
*block_size = _lun[lun].block_size;
7676
}
7777

78-
void Adafruit_USBD_MSC::setCallback(uint8_t lun, read_callback_t rd_cb, write_callback_t wr_cb, flush_callback_t fl_cb)
78+
void Adafruit_USBD_MSC::setUnitReady(uint8_t lun, bool ready)
79+
{
80+
_lun[lun].unit_ready = ready;
81+
}
82+
83+
void Adafruit_USBD_MSC::setReadWriteCallback(uint8_t lun, read_callback_t rd_cb, write_callback_t wr_cb, flush_callback_t fl_cb)
7984
{
8085
_lun[lun].rd_cb = rd_cb;
8186
_lun[lun].wr_cb = wr_cb;
8287
_lun[lun].fl_cb = fl_cb;
8388
}
8489

90+
void Adafruit_USBD_MSC::setReadyCallback(uint8_t lun, ready_callback_t cb)
91+
{
92+
_lun[lun].ready_cb = cb;
93+
}
94+
8595
bool Adafruit_USBD_MSC::begin(void)
8696
{
8797
if ( !USBDevice.addInterface(*this) ) return false;
@@ -107,6 +117,7 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16
107117
{
108118
if (!_msc_dev) return;
109119

120+
// If not set use default ID "Adafruit - Mass Storage - 1.0"
110121
const char* vid = (_msc_dev->_lun[lun]._inquiry_vid ? _msc_dev->_lun[lun]._inquiry_vid : "Adafruit");
111122
const char* pid = (_msc_dev->_lun[lun]._inquiry_pid ? _msc_dev->_lun[lun]._inquiry_pid : "Mass Storage");
112123
const char* rev = (_msc_dev->_lun[lun]._inquiry_rev ? _msc_dev->_lun[lun]._inquiry_rev : "1.0");
@@ -120,9 +131,14 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16
120131
// return true allowing host to read/write this LUN e.g SD card inserted
121132
bool tud_msc_test_unit_ready_cb(uint8_t lun)
122133
{
123-
(void) lun;
134+
if (!_msc_dev) return false;
135+
136+
if (_msc_dev->_lun[lun].ready_cb)
137+
{
138+
_msc_dev->_lun[lun].unit_ready = _msc_dev->_lun[lun].ready_cb();
139+
}
124140

125-
return true; // RAM disk is always ready
141+
return _msc_dev->_lun[lun].unit_ready;
126142
}
127143

128144
// Callback invoked to determine disk's size

src/Adafruit_USBD_MSC.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ class Adafruit_USBD_MSC : Adafruit_USBD_Interface
3333
typedef int32_t (*read_callback_t ) (uint32_t lba, void* buffer, uint32_t bufsize);
3434
typedef int32_t (*write_callback_t) (uint32_t lba, uint8_t* buffer, uint32_t bufsize);
3535
typedef void (*flush_callback_t) (void);
36+
typedef bool (*ready_callback_t) (void);
3637

3738
Adafruit_USBD_MSC(void);
3839

@@ -46,7 +47,10 @@ class Adafruit_USBD_MSC : Adafruit_USBD_Interface
4647
void setCapacity(uint8_t lun, uint32_t block_count, uint16_t block_size);
4748
void getCapacity(uint8_t lun, uint32_t* block_count, uint16_t* block_size);
4849

49-
void setCallback(uint8_t lun, read_callback_t rd_cb, write_callback_t wr_cb, flush_callback_t fl_cb);
50+
void setUnitReady(uint8_t lun, bool ready);
51+
52+
void setReadWriteCallback(uint8_t lun, read_callback_t rd_cb, write_callback_t wr_cb, flush_callback_t fl_cb);
53+
void setReadyCallback(uint8_t lun, ready_callback_t cb);
5054

5155
// from Adafruit_USBD_Interface
5256
virtual uint16_t getDescriptor(uint8_t* buf, uint16_t bufsize);
@@ -57,21 +61,26 @@ class Adafruit_USBD_MSC : Adafruit_USBD_Interface
5761
read_callback_t rd_cb;
5862
write_callback_t wr_cb;
5963
flush_callback_t fl_cb;
60-
61-
uint32_t block_count;
62-
uint16_t block_size;
64+
ready_callback_t ready_cb;
6365

6466
const char* _inquiry_vid;
6567
const char* _inquiry_pid;
6668
const char* _inquiry_rev;
69+
70+
uint32_t block_count;
71+
uint16_t block_size;
72+
bool unit_ready;
73+
6774
} _lun[MAX_LUN];
6875

6976
uint8_t _maxlun;
7077

78+
// Make all tinyusb callback friend to access private data
7179
friend int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize);
7280
friend int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize);
7381
friend void tud_msc_write10_complete_cb (uint8_t lun);
7482
friend void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]);
83+
friend bool tud_msc_test_unit_ready_cb(uint8_t lun);
7584
};
7685

7786
#endif /* ADAFRUIT_USBD_MSC_H_ */

0 commit comments

Comments
 (0)