summaryrefslogtreecommitdiff
path: root/docs/reference/class/msc.rst
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2026-08-01 19:22:52 +0200
committerHiFiPhile <[email protected]>2026-08-01 19:22:52 +0200
commitcd9bbed39f5851d5e4dc64271f18b8db777acb53 (patch)
tree83866c4127a6d808ba9eb6d543fe5d3787cd3af2 /docs/reference/class/msc.rst
parentf3021b337fcea154b898489c417d428c92f88e92 (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.rst125
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.