Skip to content

Define BlockDevice class for VfsFat block device arguments #30

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 20, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions circuitpython_typing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
__all__ = [
"Alarm",
"AudioSample",
"BlockDevice",
"ByteStream",
"FrameBuffer",
"ReadableBuffer",
Expand Down Expand Up @@ -72,6 +73,58 @@ def write(self, buf: ReadableBuffer) -> Optional[int]:
"""Write the bytes in ``buf`` to the stream."""


class BlockDevice(Protocol):
"""Protocol for block device objects to enable a device to support
CircuitPython filesystems. Classes which implement this protocol
include `storage.VfsFat`.
"""

def readblocks(self, block_num: int, buf: bytearray) -> None:
"""Read aligned, multiples of blocks. Starting at
the block given by the index ``block_num``, read blocks
from the device into ``buf`` (an array of bytes). The number
of blocks to read is given by the length of ``buf``,
which will be a multiple of the block size.
"""

def writeblocks(self, block_num: int, buf: bytearray) -> None:
"""Write aligned, multiples of blocks, and require that
the blocks that are written to be first erased (if necessary)
by this method. Starting at the block given by the index
``block_num``, write blocks from ``buf`` (an array of bytes) to the
device. The number of blocks to write is given by the length
of ``buf``, which will be a multiple of the block size.
"""

def ioctl(self, operation: int, arg: Optional[int] = None) -> Optional[int]:
"""Control the block device and query its parameters. The operation to
perform is given by ``operation`` which is one of the following integers:

* 1 - initialise the device (``arg`` is unused)
* 2 - shutdown the device (``arg`` is unused)
* 3 - sync the device (``arg`` is unused)
* 4 - get a count of the number of blocks, should return an integer (``arg`` is unused)
* 5 - get the number of bytes in a block, should return an integer,
or ``None`` in which case the default value of 512 is used (``arg`` is unused)
* 6 - erase a block, arg is the block number to erase

As a minimum ``ioctl(4, ...)`` must be intercepted; for littlefs ``ioctl(6, ...)``
must also be intercepted. The need for others is hardware dependent.

Prior to any call to ``writeblocks(block, ...)`` littlefs issues ``ioctl(6, block)``.
This enables a device driver to erase the block prior to a write if the hardware
requires it. Alternatively a driver might intercept ``ioctl(6, block)`` and return 0
(success). In this case the driver assumes responsibility for detecting the need
for erasure.

Unless otherwise stated ``ioctl(operation, arg)`` can return ``None``. Consequently an
implementation can ignore unused values of ``operation``. Where ``operation`` is
intercepted, the return value for operations 4 and 5 are as detailed above. Other
operations should return 0 on success and non-zero for failure, with the value returned
being an ``OSError`` errno code.
"""


# These types may not be in adafruit-blinka, so use the string form instead of a resolved name.

AudioSample: TypeAlias = Union[
Expand Down