| Fabien Sanglard | 52a00a2 | 2024-11-09 12:20:28 -0800 | [diff] [blame] | 1 | # How ADB uses USB Zero-Length Packets (ZLP) |
| 2 | |
| 3 | ## TLDR; |
| 4 | There is no USB mechanism that lets a sender announce the size of a `Transfer`. This is not |
| 5 | a problem when the host side receives packet since is leverage the aprotocol to know what size |
| 6 | of transfer to expect. However, traffic towards the device must include zero length packets to |
| 7 | mark the boundaries since the device does not leverage the aprotocol. |
| 8 | |
| 9 | ## Introduction |
| 10 | |
| 11 | There is an asymmetry in how ADB communicates over USB. While all USB backends on the host side (Linux, |
| 12 | Windows, Mac, and libusb) send ZLPs, the device side never does. Why is that? This document explains |
| 13 | what ZLPs are, how ADB uses them, and why things are designed this way. |
| 14 | |
| 15 | ## USB Transfer 101 |
| 16 | |
| 17 | In the context of ADB, USB can be thought of as two unidirectional pipes per device. |
| 18 | One pipe takes care of upload while the other takes care of the download. On the pipe |
| 19 | transit payloads. The maximum size of a payload is set by the pipe buffers located |
| 20 | on the device. These buffers are called the `Endpoint`. |
| 21 | |
| 22 | ``` |
| 23 | ┌──────────┐ ┌──────────┐ |
| 24 | │ USB Host │ │USB Device│ |
| 25 | ├──────────┤ ├──────────┤ |
| 26 | │ │ │ │ |
| 27 | │ Pipe ◄──┼─────────────────────────┼ Endpoint │ |
| 28 | │ │ USB │ │ |
| 29 | │ Pipe ───┼─────────────────────────► Endpoint │ |
| 30 | └──────────┘ └──────────┘ |
| 31 | ``` |
| 32 | |
| 33 | In USB parlance, sending a buffer of data on a pipe and receiving it on the other end is called a `Transfer`. |
| 34 | On the sender side, the USB Controller is presented with a [buffer,size] pair called IRP. On the receiver |
| 35 | side, a similar IRP is provided to the USB controller. |
| 36 | |
| 37 | ``` |
| 38 | ┌────────┐ ┌──────────┐ |
| 39 | │ Sender │ │ Receiver │ |
| 40 | └────┬───┘ └─────┬────┘ |
| 41 | │ │ |
| 42 | ┌──▼───┐ ┌──▼───┐ |
| 43 | │ IRP │ │ IRP │ |
| 44 | └──┬───┘ └──▲───┘ |
| 45 | ┌──────▼───────┐ ┌──────┴───────┐ |
| 46 | │USB Controller│ │USB Controller│ |
| 47 | │ │ │ │ |
| 48 | │ ─┼───►─DP──►─DP ─►──DP──►─┼─► │ |
| 49 | └──────────────┘ └──────────────┘ |
| 50 | ``` |
| 51 | |
| 52 | Because of the endpoint buffer size (`wMaxPacketSize`), an IRP is broken down in |
| 53 | several data payloads called `Data Packets` (DP). |
| 54 | |
| 55 | Note: On the device, ADB uses `functionfs` which is not based on IRP. However, the logic is the same since received DP |
| 56 | must be re-assembled on the device to rebuild the original IRP. To simplify this document we use the name "IRP" |
| 57 | everywhere in this doc to mean "[buffer,size] pair provided to the USB Controller". |
| 58 | |
| 59 | ## When does a USB Transfer ends? |
| 60 | |
| 61 | If an IRP is broken down in DPs by the sender, how does the receiver reassemble |
| 62 | the DPs into an IRP on the other side? |
| 63 | |
| 64 | The key concept to get out of this whole document is that there is no mechanism |
| 65 | in USB for the sender to announce the size of a `Transfer`. Instead, the receiving |
| 66 | end uses the following rules. A `Transfer` is considered done when either of the following condition |
| 67 | is met. |
| 68 | |
| 69 | - An error occurred (device disconnected, ...). |
| 70 | - The IRP is full. |
| 71 | - The size of the packet is less than `wMaxPacketSize` (this is a Short-Packet). This is |
| 72 | a different behavior from the usual UNIX `read(3)` which is allowed to return less than required |
| 73 | without meaning that the stream is over. |
| 74 | - Too much data is received. The IRP overflows (this is also an error). |
| 75 | |
| 76 | See USB 2 specifications (5.8.3 Bulk Transfer Packet Size Constraints) for additional information. |
| 77 | ``` |
| 78 | An endpoint must always transmit data payloads with a data field less than or equal to the endpoint’s |
| 79 | reported wMaxPacketSize value. When a bulk IRP involves more data than can fit in one maximum-sized |
| 80 | data payload, all data payloads are required to be maximum size except for the last data payload, which will |
| 81 | contain the remaining data. A bulk transfer is complete when the endpoint does one of the following: |
| 82 | |
| 83 | • Has transferred exactly the amount of data expected |
| 84 | • Transfers a packet with a payload size less than wMaxPacketSize or transfers a zero-length packet |
| 85 | ``` |
| 86 | |
| 87 | ### Example 1: The IRP is full |
| 88 | |
| 89 | For a USB3 bulk pipe, the `wMaxPacketSize` is 1024. The sender "S" wishes |
| 90 | to send 2048 bytes. It creates a IRP, fills it with the 2048 bytes, and gives the IRP |
| 91 | to the USB controller. On the |
| 92 | received side "R", the USB controller is provided with a IRP of side 2048. |
| 93 | |
| 94 | ``` |
| 95 | Traffic: |
| 96 | S -> 1024 -> R |
| 97 | S -> 1024 -> R IRP full, Transfer OK! |
| 98 | ``` |
| 99 | |
| 100 | At this point R's IRP is full. R USB controller declares the `Transfer` over |
| 101 | and calls whatever callback the client provided the IRP. |
| 102 | |
| 103 | ### Example 2: Short-Packet |
| 104 | |
| 105 | Same USB3 bulk as Example 1. The `wMaxPacketSize` is 1024. The sender wishes |
| 106 | to send 2148 bytes. It creates a IRP of size 2148 bytes and fills it with data. |
| 107 | On the received side, the USB controller is provided with a IRP of size 4096. |
| 108 | |
| 109 | ``` |
| 110 | Traffic: |
| 111 | S -> 1024 -> R |
| 112 | S -> 1024 -> R |
| 113 | S -> 100 -> R Short-Packet, Transfer OK! |
| 114 | ``` |
| 115 | |
| 116 | The receiver end detects a short packet. Even though it was provided with a 4906 |
| 117 | byte IRP, it declares the `Transfer` completed (and records the actual size |
| 118 | of the `Transfer` in the IRP). |
| 119 | |
| 120 | ### Example 3: Overflow |
| 121 | |
| 122 | Same USB3 bulk as Example 1. The `wMaxPacketSize` is 1024. The sender wishes |
| 123 | to send 4096 bytes. It creates a IRP, fills it with the 4096 bytes. On the |
| 124 | receiver side, the USB controller is provided with an IRP of size 2148. |
| 125 | |
| 126 | ``` |
| 127 | Traffic: |
| 128 | S -> 1024 -> R |
| 129 | S -> 1024 -> R |
| 130 | S -> 1024 -> R ERROR, Transfer failed! |
| 131 | ``` |
| 132 | |
| 133 | On the third packet, the receiver runs out of space in the IRP (it only had 100 |
| 134 | bytes available). Without a way to fully store this packet, |
| 135 | it discards everything and returns an error stating that the `Transfer` was not successful. |
| 136 | |
| 137 | ## Preventing overflow and the need for Zero-Length Packets |
| 138 | |
| 139 | There are two techniques to avoid overflows. |
| 140 | |
| 141 | ### Using a protocol |
| 142 | One technique is to create a protocol on top of `Transfers`. |
| 143 | ADB does that with its "aprotocol" ([protocol.md](protocol.md)). |
| 144 | |
| 145 | In aprotocol, the sender creates a `Transfer` containing a header which is |
| 146 | always 24 bytes. Then it sends a separate `Transfer` containing the payload. |
| 147 | The size of the payload is in the header. This way the receiver always knows |
| 148 | what size of IRP to provide to the USB controller: it first requests a 24 byte IRP |
| 149 | read, extracts the size of the payload, then issues a second IRP read request |
| 150 | with the extracted size of the payload. |
| 151 | |
| 152 | ### Using a multiple of `wMaxPacketSize` |
| 153 | |
| 154 | The other technique to avoid overflows is for the receiver to always use a IRP with |
| 155 | a size which is a multiple of the `wMaxPacketSize`. This way a `Transfer` always ends properly. |
| 156 | * A max size packet will exactly finish to fill the IRP, ending the `Transfer`. |
| 157 | * A short packet will end the `Transfer`. |
| 158 | |
| 159 | This technique comes with an edge case. Take the example of a USB3 pipe where |
| 160 | `wMaxPacketSize` is 1024. The sender wishes to send 3072 byte. It creates a IRP |
| 161 | of that size, fills in the data and gives it to the USB controller which breaks |
| 162 | it into Packets. The receiver decides to read with a IRP of size 4096. |
| 163 | |
| 164 | ``` |
| 165 | Traffic: |
| 166 | S -> 1024 -> R |
| 167 | S -> 1024 -> R |
| 168 | S -> 1024 -> R |
| 169 | . |
| 170 | . |
| 171 | . |
| 172 | Stalled! |
| 173 | ``` |
| 174 | |
| 175 | After the USB controller on the sender side has sent all the data in the IRP, it won't send anything else. |
| 176 | But none of the ending conditions of a `Transfer` have been reached on the receiving end. No overflow, no short-packet, and the IRP is not |
| 177 | full (there is still 1024 bytes unused). As is, the USB controller on the receiving end will never declare the `Transfer` |
| 178 | either successful or failed. This is a stall (at least until another Packet is sent, if ever). |
| 179 | |
| 180 | This condition is entered when the size of a IRP to send is a multiple of `wMaxPacketSize` |
| 181 | but less than the size of the IRP provided by the receiving end. To fix this condition, |
| 182 | the sender MUST issue a Zero-Length Packet. Technically, this is a short packet (it is less |
| 183 | than `wMaxPacketSize`). Upon receiving the ZLP, the receiver declares the `Transfer` |
| 184 | finished. |
| 185 | |
| 186 | ``` |
| 187 | Traffic: |
| 188 | S -> 1024 -> R |
| 189 | S -> 1024 -> R |
| 190 | S -> 1024 -> R |
| 191 | S -> 0 -> R Short-Packet, Transfer is over! |
| 192 | ``` |
| 193 | |
| 194 | ## Implementation choices |
| 195 | |
| 196 | By now, it should be clear that whether a sender needs to send a ZLP depends on the way |
| 197 | the receiver end works. |
| 198 | |
| 199 | ### ADB Device to Host pipe communication design |
| 200 | |
| 201 | The receiver on the host leverages ADB aprotocol ([protocol.md](protocol.md)). It |
| 202 | first creates a IRP of size 24 bytes to receive the header. Then it creates a IRP |
| 203 | `Transfer` |
| 204 | of the size of the payload. Because the IRPs are always exactly the size of the `Transfer` |
| 205 | the device sends, there is no need for LZP. The USB Controller on the host side will always be able |
| 206 | to declare a `Transfer` complete when the IRP is full and there will never be any overflow. |
| 207 | |
| 208 | The drawback of this technique is that it can consume a lot of RAM because multiple |
| 209 | IRPs can be in flight at a time. With the maximum size of |
| 210 | a apacket payload being MAX_PAYLOAD (1MiB), things can quickly add up. |
| 211 | |
| 212 | |
| 213 | ### ADB Host to Device pipe communication design |
| 214 | |
| 215 | On the device side, the receiver does not leverage the ADB aprotocol ([protocol.md](protocol.md)). |
| 216 | I suspect this was done to reduce memory consumption (the first Android device had a total RAM size of 192MiB). |
| 217 | |
| 218 | The UsbFS connection always requests the same |
| 219 | `Transfer` size. To prevent overflows, the size is picked to be a multiple of the `wMaxPacketSize` (1x would be |
| 220 | valid but the overhead would kill performances). Currently, the value is kUsbReadSize (16384). USB endpoints |
| 221 | have a well known `wMaxPacketSize` so 16384 works for all of them (this list is for bulk transfers only which |
| 222 | ADB exclusively uses). |
| 223 | |
| 224 | * Full Speed: 8, 16, 32, or 64 bytes. |
| 225 | * High Speed: 512 bytes. |
| 226 | * Super Speed: 1024 bytes. |
| 227 | |
| 228 | When the apacket payload size is a multiple |
| 229 | of the `wMaxPacketSize`, the sender on the host side MUST send a ZLP to avoid stalling |
| 230 | on the receiver end. |
| 231 | |
| 232 | |
| 233 | ## What happens if the host sender has a bug and ZLPs are not sent? |
| 234 | |
| 235 | If there is a bug on the host and ZLPs are not sent, several things can happen. |
| 236 | You can observe normal behavior, stalled communication, or even device disconnection. |
| 237 | |
| 238 | Because there are many buffers before the USB controller layer |
| 239 | is hit, the issue won't be deterministic. However my experience showed that attempting to |
| 240 | push 10GiB rarely |
| 241 | fails to bring up instabilities. |
| 242 | |
| 243 | ``` |
| 244 | $ dd if=/dev/urandom of=r.bin bs=1G count=10 iflag=fullblock` |
| 245 | $ adb push -Z r.bin /datal/local/tmp |
| 246 | ``` |
| 247 | |
| 248 | ### 1. Nothing breaks |
| 249 | |
| 250 | You could be unlucky and not trigger the fault. |
| 251 | |
| 252 | ### 2. Stall |
| 253 | |
| 254 | A payload of a size that's a multiple of `wMaxPacketSize` but of size less than kUsbReadSize (16384) is sent. |
| 255 | This is a stall as previously described. |
| 256 | |
| 257 | ### 3. Disconnection (due to merged packets) |
| 258 | |
| 259 | In real-life usage, there is rarely a single thing happening on ADB. Users often also run logcat, Studio |
| 260 | monitors metrics, or perhaps the user has a shell opened. What happens if a connection goes stalls |
| 261 | but then something else sends an apacket? |
| 262 | |
| 263 | The first `Transfer` of the apacket will be an apacket header which is 24 bytes. This will be considered |
| 264 | a short-packet. The previous stalled `Transfer` will be completed with the header appended. This will |
| 265 | confuse UsbFS since the payload will be 24 bytes more than it should be. In this condition, the connection |
| 266 | is closed. The log message is |
| 267 | |
| 268 | ``` |
| 269 | received too many bytes while waiting for payload |
| 270 | ``` |
| 271 | |
| 272 | or |
| 273 | |
| 274 | ``` |
| 275 | received packet of unexpected length while reading header |
| 276 | ``` |
| 277 | |
| 278 | A summary inspection of logs may make it look like a payload `Transfer` |
| 279 | was merged with the next header `Transfer`. |