Add 'USB config & command protocol'
parent
d877278d10
commit
1daabd0e37
|
@ -0,0 +1,115 @@
|
|||
# Wire protocol
|
||||
|
||||
The host sends a message and the device sends a reply. The device never initiates a transfer.
|
||||
|
||||
the first byte of a command is the combination of the mode it is meant for (in the high nybble), and the command number itself in the low nybble. Optional extra command bytes may follow, depending on the command itself. A high nybble of 0 signifies a general configuration command, not meant for a particular mode.
|
||||
|
||||
A response consists of a response status byte (`enum cfg_resp`), followed by a 7-, 14- or 22-bit VLQ int (little-endian) for the payload length, followed by the payload itself.
|
||||
|
||||
### Response/status enum:
|
||||
|
||||
* Ok: `0x00`
|
||||
* Illegal/unknown/unimplemented command: `0x01`
|
||||
* Bad mode for this command: `0x02`
|
||||
* No such mode exists: `0x03`
|
||||
* Bad command argument: `0x04`
|
||||
|
||||
## General commands
|
||||
|
||||
These commands work at any moment and are used to query the general device state and info.
|
||||
|
||||
* Get vesion (`0x00`): returns a payload of 2 bytes with version data. Should currently be `0x10 0x00` (`00.10h`).
|
||||
* Get modes (`0x01`): returns 2 bytes with a bitmap containing all supported modes. Bit 0 is for general config (aka this command group) and must always be 1.
|
||||
* Get cur mode (`0x02`): returns a single byte containing the current mode number.
|
||||
* Set cur mode (`0x03`): sets the current mode. One extra request byte (the mode number), no response payload.
|
||||
* Get info string (`0x04`): get a string containing human-readable info about the device. For display purposes only.
|
||||
|
||||
## Common mode commands
|
||||
|
||||
These commands work for any mode, and have the same effect across all of them.
|
||||
|
||||
* Get name (`0xM0`): returns a name or other descriptive string in the payload. For display purposes only.
|
||||
* Get version (`0xM1`): returns a 2-byte version number in the payload.
|
||||
* Get features (`0xM2`): gets a bitmap of supported features. Length and meaning of the bits depends on the mode.
|
||||
|
||||
## Mode-specific commands
|
||||
|
||||
A list of all the currently-implemented modes:
|
||||
|
||||
1. Default ('misc')
|
||||
|
||||
## Mode 1
|
||||
|
||||
### Features
|
||||
|
||||
* `0x01`: UART<->USB-CDC interface available
|
||||
* `0x02`: CMSIS-DAP available
|
||||
* `0x04`: SPI interface available
|
||||
* `0x08`: I2C interface available
|
||||
* `0x10`: Temperature sensor available
|
||||
|
||||
### Commands
|
||||
|
||||
* SPI (serprog) command prefix (`0x13`): Perform a SPI command, see below.
|
||||
* I2C command prefix (`0x14`): Perform an I2C command, see below.
|
||||
* Temperature sensor command prefix (`0x15`): Perform a temperature sensor command, see below.
|
||||
|
||||
#### SPI commands
|
||||
|
||||
The SPI command format used here is based heavily on [Serprog](https://github.com/flashrom/flashrom/blob/master/Documentation/serprog-protocol.txt). Keep in mind that serprog responses — including its `ACK` and `NAK` status bytes — are wrapped as a response payload as defined in the beginning of this document!
|
||||
|
||||
Supported standard serprog commands:
|
||||
* `NOP` (`0x00`)
|
||||
* `Q_IFACE` (`0x01`)
|
||||
* `Q_CMDMAP` (`0x02`)
|
||||
* `Q_PGMNAME` (`0x03`)
|
||||
* `Q_SERBUF` (`0x04`)
|
||||
* `Q_BUSTYPE` (`0x05`)
|
||||
* `Q_WRNMAXLEN` (`0x08`)
|
||||
* `SYNCNOP` (`0x10`)
|
||||
* `Q_RDNMAXLEN` (`0x11`)
|
||||
* `S_BUSTYPE` (`0x12`)
|
||||
* `SPIOP` (`0x13`)
|
||||
* `S_SPI_FREQ` (`0x14`)
|
||||
* SPI clock frequency defaults to 512 kHz
|
||||
* `S_PINSTATE` (`0x15`)
|
||||
|
||||
Additionally, a number of nonstandard commands are supported as well, for more specific SPI transfers not necessarily needed for flash programming:
|
||||
|
||||
* `S_CMD_Q_NUM_CS` (`0x40`): query the number of SPI devices (and chip select lines) available, single byte response.
|
||||
* `S_CMD_S_SPI_FLAGS` (`0x41`): set SPI transfer options:
|
||||
* `S_FLG_CPOL` (`0x01`): set this bit to set the SPI clock polarity to *high*, clear this bit to set it to *low*.
|
||||
* `S_FLG_CPHA` (`0x02`): set this bit to set the SPI clock phase to read or write data on the second edge, clear it to read/write it on the first edge.
|
||||
* `S_FLG_16BIT` (`0x03`): set this bit to transfer data in units of 16-bit, clear this to perform 8-bit transfers. Data is always sent MSB-first.
|
||||
* Flags default to all-zero.
|
||||
* `S_CMD_SPI_READ` (`0x42`): similar to `SPIOP` (`0x13`), except without data to write (and no "write data length" argument).
|
||||
* `S_CMD_SPI_WRITE` (`0x43`): similar to `SPIOP` (`0x13`), except without data to read (and no "read data length" argument).
|
||||
* `S_CMD_SPI_RDWR` (`0x44`): full-duplex SPI transfer (as opposed to `SPIOP` (`0x13`), which is only half-duplex), same arguments and result format as `SPIOP` (`0x13`).
|
||||
|
||||
#### I2C commands
|
||||
|
||||
The I2C command format used here is based heavily on the one of [I2C-Tiny-USB](http://www.harbaum.org/till/i2c_tiny_usb/) ([protocol](https://git.lain.faith/sys64738/DapperMime-JTAG/src/commit/45ae75818d4677747ec7f719dfac0f50aa169b9d/i2c-tiny-usb-misc/i2c-tiny-usb-proto.txt)).
|
||||
|
||||
* Echo (`0x00`): one single argument byte is echoed back as payload.
|
||||
* Get functions (`0x01`): get supported I2C and SMBus operations. Response payload is 4 bytes little endian, Linux kernel `I2C_FUNC_xxx` flags.
|
||||
* Set delay (`0x02`): sets the clock phase of the `SCL` signal, in microseconds, two little-endian bytes. No response payload.
|
||||
* Get status (`0x03`): returns the current status as a single payload byte.
|
||||
* `0x00`: idle status: nothing happened
|
||||
* `0x01`: The last transfer was successful, an ACK was received from the target I2C device.
|
||||
* `0x02`: The last transfer failed, a NAK was received from the target I2C device, or no devices responded to the address.
|
||||
* Do transfer (`0x04`..`0x07`): perform an I2C transfer.
|
||||
* Arguments: 2 little-endian 'flags' bytes (Linux kernel `I2C_M_xxx` flags), 2 little-endian I2C device address bytes, 2 little-endian transfer length bytes.
|
||||
* If the lowest bit (bit 0) of the command byte is set, a "start condition" is performed at the start of the I2C transfer. Otherwise, a "repstart" is done.
|
||||
* If bit 1 of the command byte is set, a "stop condition" is performed at the end of the transfer, causing the target device to stop listening to further commands, and go back to listening for its address on the bus.
|
||||
* If `flags & I2C_M_RD`, this is a read operation. The amount of bytes read (max. the number of bytes specified in the arguments) is returned as data payload.
|
||||
* If the transfer length is 0, this is an address probe. The response payload is a single byte with the current status (cf. cmd. `0x03`).
|
||||
* Otherwise, this is a write transfer. The number of bytes specified in the arguments is read from the USB host, and sent over the I2C bus.
|
||||
|
||||
#### Temperature sensor commands
|
||||
|
||||
* Get I2C address (`0x00`): gets the address of the virtual temperature sensor device on the I2C bus (the one used in cmd. `0x14`). `0xff` if disabled. Single byte response payload.
|
||||
* Set I2C address (`0x01`): sets the address of the virtual temperature sensor I2C device, `0xff` to disable. Single argument byte, two response bytes (old and new addresses).
|
||||
* Get temperature (`0x02`): returns the 2-byte 8.4 fixed point temperature, little endian.
|
||||
* Get lower temperature limit (`0x03`): returns the 2-byte minimum temperature fore things start going bad.
|
||||
* Get upper temperature limit (`0x04`): returns the 2-byte maximum temperature before things start going bad.
|
||||
* Get critical temperature limit (`0x05`): returns the 2-byte critical temperature when things are going really bad.
|
Loading…
Reference in New Issue