|
24 | 24 | __all__ = [
|
25 | 25 | "Alarm",
|
26 | 26 | "AudioSample",
|
| 27 | + "BlockDevice", |
27 | 28 | "ByteStream",
|
28 | 29 | "FrameBuffer",
|
29 | 30 | "ReadableBuffer",
|
@@ -72,6 +73,58 @@ def write(self, buf: ReadableBuffer) -> Optional[int]:
|
72 | 73 | """Write the bytes in ``buf`` to the stream."""
|
73 | 74 |
|
74 | 75 |
|
| 76 | +class BlockDevice(Protocol): |
| 77 | + """Protocol for block device objects to enable a device to support |
| 78 | + CircuitPython filesystems. Classes which implement this protocol |
| 79 | + include `storage.VfsFat`. |
| 80 | + """ |
| 81 | + |
| 82 | + def readblocks(self, block_num: int, buf: bytearray) -> None: |
| 83 | + """Read aligned, multiples of blocks. Starting at |
| 84 | + the block given by the index ``block_num``, read blocks |
| 85 | + from the device into ``buf`` (an array of bytes). The number |
| 86 | + of blocks to read is given by the length of ``buf``, |
| 87 | + which will be a multiple of the block size. |
| 88 | + """ |
| 89 | + |
| 90 | + def writeblocks(self, block_num: int, buf: bytearray) -> None: |
| 91 | + """Write aligned, multiples of blocks, and require that |
| 92 | + the blocks that are written to be first erased (if necessary) |
| 93 | + by this method. Starting at the block given by the index |
| 94 | + ``block_num``, write blocks from ``buf`` (an array of bytes) to the |
| 95 | + device. The number of blocks to write is given by the length |
| 96 | + of ``buf``, which will be a multiple of the block size. |
| 97 | + """ |
| 98 | + |
| 99 | + def ioctl(self, operation: int, arg: Optional[int] = None) -> Optional[int]: |
| 100 | + """Control the block device and query its parameters. The operation to |
| 101 | + perform is given by ``operation`` which is one of the following integers: |
| 102 | +
|
| 103 | + * 1 - initialise the device (``arg`` is unused) |
| 104 | + * 2 - shutdown the device (``arg`` is unused) |
| 105 | + * 3 - sync the device (``arg`` is unused) |
| 106 | + * 4 - get a count of the number of blocks, should return an integer (``arg`` is unused) |
| 107 | + * 5 - get the number of bytes in a block, should return an integer, |
| 108 | + or ``None`` in which case the default value of 512 is used (``arg`` is unused) |
| 109 | + * 6 - erase a block, arg is the block number to erase |
| 110 | +
|
| 111 | + As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs ``ioctl(6, ...)`` |
| 112 | + must also be intercepted. The need for others is hardware dependent. |
| 113 | +
|
| 114 | + Prior to any call to ``writeblocks(block, ...)`` littlefs issues ``ioctl(6, block)``. |
| 115 | + This enables a device driver to erase the block prior to a write if the hardware |
| 116 | + requires it. Alternatively a driver might intercept ``ioctl(6, block)`` and return 0 |
| 117 | + (success). In this case the driver assumes responsibility for detecting the need |
| 118 | + for erasure. |
| 119 | +
|
| 120 | + Unless otherwise stated ``ioctl(operation, arg)`` can return ``None``. Consequently an |
| 121 | + implementation can ignore unused values of ``operation``. Where ``operation`` is |
| 122 | + intercepted, the return value for operations 4 and 5 are as detailed above. Other |
| 123 | + operations should return 0 on success and non-zero for failure, with the value returned |
| 124 | + being an ``OSError`` errno code. |
| 125 | + """ |
| 126 | + |
| 127 | + |
75 | 128 | # These types may not be in adafruit-blinka, so use the string form instead of a resolved name.
|
76 | 129 |
|
77 | 130 | AudioSample: TypeAlias = Union[
|
|
0 commit comments