summaryrefslogtreecommitdiff
path: root/docs/reference/class/dfu.rst
blob: 6a95bbf89463211d7aa1d78a27fe92da2315f170 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
***
DFU
***

Role: device only.  Device Firmware Upgrade (DFU) has two distinct states:
runtime mode, where normal firmware advertises that it can reboot into an
updater, and DFU mode, where firmware images are transferred.

Runtime mode
============

Enable ``CFG_TUD_DFU_RUNTIME`` and add ``TUD_DFU_RT_DESCRIPTOR``.  When the
host sends DFU_DETACH, TinyUSB calls ``tud_dfu_runtime_reboot_to_dfu_cb()``.
Store any required boot flag, safely stop the application, and reset into the
DFU image from that callback.

The descriptor's detach attributes must describe the actual behavior.  In
particular, do not set ``bitWillDetach`` unless the callback will initiate the
detach/reset without a USB reset from the host.

See :doc:`../../examples/device/dfu_runtime`.

.. list-table::
   :header-rows: 1
   :widths: 38 62

   * - Descriptor attribute
     - Meaning
   * - ``DFU_ATTR_CAN_DOWNLOAD``
     - Host may send firmware to the device.
   * - ``DFU_ATTR_CAN_UPLOAD``
     - Host may read firmware from the device; omit it when disclosure is not
       intended.
   * - ``DFU_ATTR_MANIFESTATION_TOLERANT``
     - Device can remain in DFU mode after manifestation without reset.
   * - ``DFU_ATTR_WILL_DETACH``
     - Device performs its own detach/reset after DFU_DETACH.  Clear it when
       the host must issue the USB reset.

DFU mode
========

Enable ``CFG_TUD_DFU`` and set ``CFG_TUD_DFU_XFER_BUFSIZE`` to exactly the
``wTransferSize`` passed to ``TUD_DFU_DESCRIPTOR``.  Alternate settings can
represent partitions or targets; their string descriptors should clearly name
the target presented by each ``alt`` value.

.. list-table::
   :header-rows: 1
   :widths: 38 62

   * - Callback/API
     - Application responsibility
   * - ``tud_dfu_download_cb()``
     - Program one downloaded block, then call
       ``tud_dfu_finish_flashing()`` when the operation completes.
   * - ``tud_dfu_upload_cb()``
     - Fill the buffer with at most the requested number of bytes and return
       the count.
   * - ``tud_dfu_manifest_cb()``
     - Validate/finalize the image, then call ``tud_dfu_finish_flashing()``.
   * - ``tud_dfu_get_timeout_cb()``
     - Return an honest poll timeout for the current target and state.
   * - ``tud_dfu_abort_cb()``
     - Cancel pending storage work and return the target to a safe state.
   * - ``tud_dfu_detach_cb()``
     - Handles DFU_DETACH while in DFU mode; normally records state and resets
       or returns to runtime firmware according to the descriptor attributes.
   * - ``tud_dfu_finish_flashing()``
     - Completes a previously started download or manifestation.  An error
       status moves the state machine into the DFU error state.

Storage can be asynchronous: retain the operation state, return from the
callback, and call ``tud_dfu_finish_flashing(status)`` later.  Pass
``DFU_STATUS_OK`` only after the data is durably written or manifestation is
complete.

The :doc:`../../examples/device/dfu` example exposes two alternate settings
and can be exercised with ``dfu-util``.

Production safety
=================

Treat all DFU fields and image bytes as untrusted.  Bounds-check ``alt``, block
number, offset, and length before accessing storage.  A production updater
should authenticate the complete image, reject rollback when required, avoid
overwriting its recovery path, and remain bootable after loss of power at any
point.  TinyUSB implements the USB transport and DFU state machine; it does not
provide those product-specific security guarantees.

Specification used: *USB Device Class Specification for Device Firmware
Upgrade*, Version 1.1.