Skip to content

Commit 474dae8

Browse files
authored
Merge pull request #8699 from tannewt/ww_sd_card
Make SD cards available over web workflow
2 parents c09a4f9 + 1b25e64 commit 474dae8

File tree

52 files changed

+737
-537
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+737
-537
lines changed

docs/workflows.md

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,13 @@ Returns a JSON representation of the directory.
165165
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
166166
* `404 Not Found` - Missing directory
167167

168+
Returns directory information:
169+
* `free`: Count of free blocks on the disk holding this directory.
170+
* `total`: Total blocks that make up the disk holding this directory.
171+
* `block_size`: Size of a block in bytes.
172+
* `writable`: True when CircuitPython and the web workflow can write to the disk. USB may claim a disk instead.
173+
* `files`: Array of objects. One for each file.
174+
168175
Returns information about each file in the directory:
169176

170177
* `name` - File name. No trailing `/` on directory names
@@ -179,14 +186,20 @@ curl -v -u :passw0rd -H "Accept: application/json" -L --location-trusted http://
179186
```
180187

181188
```json
182-
[
183-
{
184-
"name": "world.txt",
185-
"directory": false,
186-
"modified_ns": 946934328000000000,
187-
"file_size": 12
188-
}
189-
]
189+
{
190+
"free": 451623,
191+
"total": 973344,
192+
"block_size": 32768,
193+
"writable": true,
194+
"files": [
195+
{
196+
"name": "world.txt",
197+
"directory": false,
198+
"modified_ns": 946934328000000000,
199+
"file_size": 12
200+
}
201+
]
202+
}
190203
```
191204

192205
##### PUT
@@ -196,7 +209,7 @@ time resolution) used for the directories modification time. The RTC time will u
196209

197210
Returns:
198211

199-
* `204 No Content` - Directory exists
212+
* `204 No Content` - Directory or file exists
200213
* `201 Created` - Directory created
201214
* `401 Unauthorized` - Incorrect password
202215
* `403 Forbidden` - No `CIRCUITPY_WEB_API_PASSWORD` set
@@ -373,10 +386,10 @@ curl -v -L http://circuitpython.local/cp/devices.json
373386
Returns information about the attached disk(s). A list of objects, one per disk.
374387

375388
* `root`: Filesystem path to the root of the disk.
376-
* `free`: Count of free bytes on the disk.
389+
* `free`: Count of free blocks on the disk.
390+
* `total`: Total blocks that make up the disk.
377391
* `block_size`: Size of a block in bytes.
378392
* `writable`: True when CircuitPython and the web workflow can write to the disk. USB may claim a disk instead.
379-
* `total`: Total bytes that make up the disk.
380393

381394
Example:
382395
```sh
@@ -405,7 +418,7 @@ This is an authenticated endpoint in both modes.
405418

406419
Returns information about the device.
407420

408-
* `web_api_version`: Between `1` and `3`. This versions the rest of the API and new versions may not be backwards compatible. See below for more info.
421+
* `web_api_version`: Between `1` and `4`. This versions the rest of the API and new versions may not be backwards compatible. See below for more info.
409422
* `version`: CircuitPython build version.
410423
* `build_date`: CircuitPython build date.
411424
* `board_name`: Human readable name of the board.
@@ -467,3 +480,5 @@ Only one WebSocket at a time is supported.
467480
* `1` - Initial version.
468481
* `2` - Added `/cp/diskinfo.json`.
469482
* `3` - Changed `/cp/diskinfo.json` to return a list in preparation for multi-disk support.
483+
* `4` - Changed directory json to an object with additional data. File list is under `files` and is
484+
the same as the old format.

extmod/vfs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
#define MP_BLOCKDEV_FLAG_USB_WRITABLE (0x0010)
4949
// Bit set when the above flag is checked before opening a file for write.
5050
#define MP_BLOCKDEV_FLAG_CONCURRENT_WRITE_PROTECTED (0x0020)
51+
// Bit set when something has claimed the right to mutate the blockdev.
52+
#define MP_BLOCKDEV_FLAG_LOCKED (0x0040)
5153

5254
// constants for block protocol ioctl
5355
#define MP_BLOCKDEV_IOCTL_INIT (1)

extmod/vfs_blockdev.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,41 @@
3030
#include "py/mperrno.h"
3131
#include "extmod/vfs.h"
3232

33+
#if CIRCUITPY_SDCARDIO
34+
#include "shared-bindings/sdcardio/SDCard.h"
35+
#endif
36+
#if CIRCUITPY_SDIOIO
37+
#include "shared-bindings/sdioio/SDCard.h"
38+
#endif
39+
40+
3341
#if MICROPY_VFS
3442

3543
void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
3644
mp_load_method(bdev, MP_QSTR_readblocks, self->readblocks);
3745
mp_load_method_maybe(bdev, MP_QSTR_writeblocks, self->writeblocks);
3846
mp_load_method_maybe(bdev, MP_QSTR_ioctl, self->u.ioctl);
47+
48+
// CIRCUITPY-CHANGE: Support native SD cards.
49+
#if CIRCUITPY_SDCARDIO
50+
if (mp_obj_get_type(bdev) == &sdcardio_SDCard_type) {
51+
self->flags |= MP_BLOCKDEV_FLAG_NATIVE | MP_BLOCKDEV_FLAG_HAVE_IOCTL;
52+
self->readblocks[0] = mp_const_none;
53+
self->readblocks[1] = bdev;
54+
self->readblocks[2] = (mp_obj_t)sdcardio_sdcard_readblocks; // native version
55+
self->writeblocks[0] = mp_const_none;
56+
self->writeblocks[1] = bdev;
57+
self->writeblocks[2] = (mp_obj_t)sdcardio_sdcard_writeblocks; // native version
58+
self->u.ioctl[0] = mp_const_none;
59+
self->u.ioctl[1] = bdev;
60+
self->u.ioctl[2] = (mp_obj_t)sdcardio_sdcard_ioctl; // native version
61+
}
62+
#endif
63+
#if CIRCUITPY_SDIOIO
64+
if (mp_obj_get_type(bdev) == &sdioio_SDCard_type) {
65+
// TODO: Enable native blockdev for SDIO too.
66+
}
67+
#endif
3968
if (self->u.ioctl[0] != MP_OBJ_NULL) {
4069
// Device supports new block protocol, so indicate it
4170
self->flags |= MP_BLOCKDEV_FLAG_HAVE_IOCTL;
@@ -48,8 +77,10 @@ void mp_vfs_blockdev_init(mp_vfs_blockdev_t *self, mp_obj_t bdev) {
4877

4978
int mp_vfs_blockdev_read(mp_vfs_blockdev_t *self, size_t block_num, size_t num_blocks, uint8_t *buf) {
5079
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
51-
mp_uint_t (*f)(uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2];
52-
return f(buf, block_num, num_blocks);
80+
// CIRCUITPY-CHANGE: Pass the blockdev object into native readblocks so
81+
// it has the corresponding state.
82+
mp_uint_t (*f)(mp_obj_t self, uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->readblocks[2];
83+
return f(self->readblocks[1], buf, block_num, num_blocks);
5384
} else {
5485
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, buf};
5586
self->readblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
@@ -80,8 +111,10 @@ int mp_vfs_blockdev_write(mp_vfs_blockdev_t *self, size_t block_num, size_t num_
80111
}
81112

82113
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
83-
mp_uint_t (*f)(const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2];
84-
return f(buf, block_num, num_blocks);
114+
// CIRCUITPY-CHANGE: Pass the blockdev object into native readblocks so
115+
// it has the corresponding state.
116+
mp_uint_t (*f)(mp_obj_t self, const uint8_t *, uint32_t, uint32_t) = (void *)(uintptr_t)self->writeblocks[2];
117+
return f(self->writeblocks[1], buf, block_num, num_blocks);
85118
} else {
86119
mp_obj_array_t ar = {{&mp_type_bytearray}, BYTEARRAY_TYPECODE, 0, num_blocks *self->block_size, (void *)buf};
87120
self->writeblocks[2] = MP_OBJ_NEW_SMALL_INT(block_num);
@@ -112,6 +145,16 @@ int mp_vfs_blockdev_write_ext(mp_vfs_blockdev_t *self, size_t block_num, size_t
112145

113146
mp_obj_t mp_vfs_blockdev_ioctl(mp_vfs_blockdev_t *self, uintptr_t cmd, uintptr_t arg) {
114147
if (self->flags & MP_BLOCKDEV_FLAG_HAVE_IOCTL) {
148+
// CIRCUITPY-CHANGE: Support native IOCTL so it can run outside of the VM.
149+
if (self->flags & MP_BLOCKDEV_FLAG_NATIVE) {
150+
size_t out_value;
151+
bool (*f)(mp_obj_t self, uint32_t, uint32_t, size_t *) = (void *)(uintptr_t)self->u.ioctl[2];
152+
bool b = f(self->u.ioctl[1], cmd, arg, &out_value);
153+
if (!b) {
154+
return mp_const_none;
155+
}
156+
return MP_OBJ_NEW_SMALL_INT(out_value);
157+
}
115158
// New protocol with ioctl
116159
self->u.ioctl[2] = MP_OBJ_NEW_SMALL_INT(cmd);
117160
self->u.ioctl[3] = MP_OBJ_NEW_SMALL_INT(arg);

extmod/vfs_fat.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ typedef struct _fs_user_mount_t {
3434
mp_obj_base_t base;
3535
mp_vfs_blockdev_t blockdev;
3636
FATFS fatfs;
37+
38+
// CIRCUITPY-CHANGE: Count the users that are manipulating the blockdev via
39+
// native fatfs so we can lock and unlock the blockdev.
40+
int8_t lock_count;
3741
} fs_user_mount_t;
3842

3943
extern const byte fresult_to_errno_table[20];

0 commit comments

Comments
 (0)