diff options
| author | HiFiPhile <[email protected]> | 2026-08-01 19:22:52 +0200 |
|---|---|---|
| committer | HiFiPhile <[email protected]> | 2026-08-01 19:22:52 +0200 |
| commit | cd9bbed39f5851d5e4dc64271f18b8db777acb53 (patch) | |
| tree | 83866c4127a6d808ba9eb6d543fe5d3787cd3af2 /docs/reference/class/msc.rst | |
| parent | f3021b337fcea154b898489c417d428c92f88e92 (diff) | |
doc: add class docscodex/class-reference-docs
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'docs/reference/class/msc.rst')
| -rw-r--r-- | docs/reference/class/msc.rst | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/docs/reference/class/msc.rst b/docs/reference/class/msc.rst new file mode 100644 index 000000000..5049669e7 --- /dev/null +++ b/docs/reference/class/msc.rst @@ -0,0 +1,125 @@ +************ +Mass Storage +************ + +Roles: device and host. TinyUSB implements the USB Mass Storage Bulk-Only +Transport (BOT) and common SCSI commands. It exposes logical blocks; a +filesystem such as FatFs is a separate application layer. + +Device +====== + +Enable ``CFG_TUD_MSC`` and set ``CFG_TUD_MSC_EP_BUFSIZE``. Add one +``TUD_MSC_DESCRIPTOR`` for each Mass Storage function. Multiple logical units +(LUNs) normally share one function and are selected through the ``lun`` +callback argument. + +``CFG_TUD_MSC_EP_BUFSIZE`` has no default and is required when MSC is enabled. +It is the class transfer-buffer size per instance, not the media capacity. +Using at least one logical block is efficient; larger values improve large +transfers at the cost of static RAM. Keep it below 65536 bytes and consistent +with controller/DMA constraints. + +The minimum storage callbacks are: + +.. list-table:: + :header-rows: 1 + :widths: 38 62 + + * - Callback + - Purpose + * - ``tud_msc_inquiry_cb()`` + - Return fixed-width vendor, product, and revision fields. + * - ``tud_msc_test_unit_ready_cb()`` + - Report whether media is present and usable. + * - ``tud_msc_capacity_cb()`` + - Return the logical block count and block size. + * - ``tud_msc_read10_cb()`` + - Read ``bufsize`` bytes from ``lba`` plus ``offset``. + * - ``tud_msc_write10_cb()`` + - Write ``bufsize`` bytes to ``lba`` plus ``offset``. + * - ``tud_msc_scsi_cb()`` + - Handle commands not implemented by the class driver. + * - ``tud_msc_get_maxlun_cb()`` + - Returns the highest valid zero-based LUN number; implement it for + multiple LUNs. + * - ``tud_msc_is_writable_cb()`` + - Reports write protection before WRITE10. + * - ``tud_msc_start_stop_cb()`` + - Handles load/eject and start/stop requests, including safe-eject policy. + +Read and write callbacks may cover only part of a logical block. Honor both +``lba`` and ``offset`` instead of assuming one callback per block. On failure, +set useful sense data with ``tud_msc_set_sense()`` and return +``TUD_MSC_RET_ERROR``. + +For temporarily busy media, return ``TUD_MSC_RET_BUSY``; TinyUSB will invoke +the callback again with the same parameters. For true background I/O, return +``TUD_MSC_RET_ASYNC`` and later call ``tud_msc_async_io_done()`` with the byte +count or error. Do not report a write complete until data has reached the +durability level promised by the product. ``tud_msc_write10_complete_cb()`` is +a useful place to flush a cache. + +See :doc:`../../examples/device/cdc_msc` for a RAM disk and +:doc:`../../examples/device/msc_dual_lun` for multiple LUNs. + +Host +==== + +Set ``CFG_TUH_MSC`` to the maximum simultaneous Mass Storage devices and +``CFG_TUH_MSC_MAXLUN`` to the LUN limit per device. After +``tuh_msc_mount_cb(dev_addr)``, query cached geometry with +``tuh_msc_get_block_count()`` and ``tuh_msc_get_block_size()``. + +``CFG_TUH_MSC_MAXLUN`` defaults to 4 and allocates cached state per possible +LUN for every enabled MSC device. Set it to the maximum needed by the product, +not necessarily the maximum value a device claims. + +``tuh_msc_read10()`` and ``tuh_msc_write10()`` are asynchronous. Keep the +buffer valid, correctly aligned, cache coherent, and accessible to the USB +controller until the ``tuh_msc_complete_cb_t`` callback runs. Check +``tuh_msc_ready()`` before starting another command and inspect the completion +callback's transfer result and command status. + +.. list-table:: + :header-rows: 1 + :widths: 40 60 + + * - Host API or callback + - What it does + * - ``tuh_msc_mounted()`` / ``tuh_msc_ready()`` + - Tests whether the MSC device is present or currently able to accept a + new SCSI command. + * - ``tuh_msc_get_maxlun()`` / + ``tuh_msc_get_block_count()`` / + ``tuh_msc_get_block_size()`` + - Returns cached LUN range and geometry populated during enumeration. + * - ``tuh_msc_read10()`` / ``tuh_msc_write10()`` + - Queues an integral number of logical blocks and completes through the + supplied callback. + * - ``tuh_msc_inquiry()`` / ``tuh_msc_request_sense()`` + - Queues standard SCSI identification or detailed-error requests into an + application-owned response buffer. + * - ``tuh_msc_scsi_command()`` + - Queues a caller-built command block wrapper for commands without a + convenience API. + * - ``tuh_msc_mount_cb()`` / ``tuh_msc_umount_cb()`` + - Announces cached capacity availability or invalidates all filesystem and + media state for the address. + +TinyUSB does not mount a filesystem automatically. Connect the sector API to +your filesystem's disk I/O layer and invalidate that state in +``tuh_msc_umount_cb()``. The :doc:`../../examples/host/msc_file_explorer` +example demonstrates this with FatFs. + +Practical notes +=============== + +* Hosts cache filesystem data. Physical removal or firmware reset without an + eject/unmount can lose data even when USB transfers succeeded. +* Use the medium-present and write-protect responses consistently; mismatched + capacity or readiness information causes repeated SCSI recovery traffic. +* Validate every LUN and block range before calculating a storage address. + +Specification used: *USB Mass Storage Class Bulk-Only Transport*, Revision +1.0. Command formats and sense data come from the applicable SCSI command set. |
