# Simpleserial Documentation

## Simpleserial v1.1

All communication is initiated by the capture board. The capture board begins
communication by sending a packet:

`[cmd, data_0, data_1, ..., data_n, '\n']`

where `cmd` is an ASCII character indicating the desired command and `data` is
an ASCII representation of the data (i.e. `0xAA` will be `'A'`, `'A'`)
The length of data is fixed by the firmware.

If the target board needs to respond with data, it sends back:

`['r', data_0, data_1, ..., data_n, '\n']`

Again, `data_n` is an ASCII representation of the data.

Whether or not the device sends back data, the device will send back an ack to
tell the capture board
that it is done its operation:

`['z', status, '\n']`

Where status is an 8-bit binary number indicating the result/status of the
operation. For example, most functions use 0x00 to indicate success.

The default baud rate is 38400bps.

### SimpleSerial v1.0

The same as SimpleSerial v1.1, except the ack packet is not included.

### Variable Length Commands

Variable length commands have been added, primarily to support masked AES.
Variable length commands are decided by firmware. In the case
of a variable length command, the send command will instead be:

`[cmd, len, data_0, data_1, ..., data_n, '\n']`

### Reserved Commands

The following commands are reserved by SimpleSerial v1:

* `'v'`: Get Simpleserial version (len=0)
* `'y'`: Get the number of Simpleserial commands on the target
* `'w'`: Get Simpleserial commands

## SimpleSerial v2.1

All communication is initiated by the capture board. The capture board begins
communication by sending a packet:

`[cmd, scmd, dlen, data_0, data_1, ..., data_n, CRC (poly=0x4D)]`

cmd indicates the desired command, `scmd` indicates a sub-command, `dlen` is the
length of the data, data is binary data, and the crc is a CRC of polynomial 0x4D
of the entire packet (from `cmd` to `data_n`). All bytes in the packet may take
any 8-bit binary value, except `dlen`, which is limited to less than 250.
Therefore, only 249 bytes can be sent per packet.

If the target board needs to respond with data, it sends back:

`[cmd, dlen, data_0, data_1, ..., data_n, CRC (poly=0x4D)]`

Whether or not the device sends back data, the device will send back an error
packet to tell the capture board that
it is done its operation:

`['e', 0x01, error, CRC (poly=0x4D)]`

Before being sent, all packets are [Consistent Overhead Byte Stuffing
(COBS)](https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing) and
null terminated:

`[overhead_byte, [packet], 0x00]`.

The following standard errors are used:

```text
0x00 - OK
0x01 - Invalid command
0x02 - Bad CRC
0x03 - Timeout
0x04 - Invalid length
0x05 - Unexpected frame byte (0x00)
0x06 - Reserved
...

0x0F - Reserved
```

Commands may use additional error codes to indicate the result of an operation.

The default baud rate is 230400bps.

**NOTE:** Only the XMEGA and STM32\* devices currently switch to this higher baud rate when building for SimpleSerial V2.1. Other devices will likely communicate at 38400bps instead.

### Reserved Commands

The following commands are reserved by SimpleSerial v2:

* `'v'`: Get simpleserial version (len=0)
* `'w'`: Get simpleserial commands

### SimpleSerial V2.0

As of ChipWhisperer 5.6.1, this SimpleSerial version is deprecated
because it used an incorrect constant for its CRC (0xA6 instead of 0x4D)

## Usage from C

You can use the C SimpleSerial library to listen to and send packets containing
commands, data, etc.

There are four exposed methods in the C library.

### `simpleserial_init`

This sets up the SimpleSerial module and prepares any internal commands. It
mostly there for future usage.

Calling it is as simple as:

```c
#include "simpleserial.h"

// ..snip

simpleserial_init();
```

### `simpleserial_addcmd`

Adds a listener on the target for a specific command. Depending on the version
of SimpleSerial you are using, the arguments are different.

> __Note:__ the C implementation of the SimpleSerial can only hold a maximum of
> 16 active command.

#### Arguments

Depending on whether we are using V1.\* or V2, it takes the following ordered
arguments:

##### SimpleSerial V1.\*

* `char` - the __command__ the target needs to listen for.
* `unsigned int` - the __amount of data bytes__ expected. The maximum is 64 bytes.
* `(uint8_t*, uint8_t) -> uint8_t` - the __handler__ for the command taking the
  __data buffer__ and the __actual data buffer length__ in bytes and returning a
  status code.

##### SimpleSerial V2

* `char` - the __command__ the target needs to listen for.
* `unsigned int` - the __amount of data bytes__ expected. The maximum is 192 bytes.
* `(uint8_t, uint8_t, uint8_t, uint8_t*) -> uint8_t` - the __handler__ for the
  command taking the arguments __command__, __sub-command__, __actual data buffer
  length__ and the __data buffer__ in bytes, in that order, and returning a
  status code.

#### Return value

Returns an `int` which is `1` if the maximum expected data buffer length is
exceeded and if the maximum number of commands has been reached. Will return `0`
otherwise.

#### Notes

* The callbacks function return value will be returned to the capture board. In
  SimpleSerial V1.1 this will be through a `'z'` message, as described above.

#### Example

The following is a SimpleSerial V2 example.

```c
#include "simpleserial.h"

uint8_t set_key(uint8_t cmd, uint8_t scmd, uint8_t dlen, uint8_t* data)
{
    // ...snip

    return 0;
}

uint8_t encrypt_plaintext(uint8_t cmd, uint8_t scmd, uint8_t dlen, uint8_t* data)
{
    // ...snip

    return 0;
}

// ... snip

simpleserial_addcmd('k', 16, set_key);
simpleserial_addcmd('p', 16, encrypt_plaintext);
```

### `simpleserial_put`

Write some data to the serial port, which should send a packet from the target
board to the capture board.

#### Arguments

This function takes the following ordered arguments:

* `char` - the __command__ for the capture board (e.g. `'z'` for ack, or `'e'`
  for error).
* `uint8_t` - the __size of the data buffer__.
* `uint8_t*` - the __data buffer__ of the packet send.

#### Example

The following is a SimpleSerial V2 example (although this has no impact on the
usage of the `simpleserial_put` function).

```c
#include "simpleserial.h"

uint8_t encrypt_plaintext(uint8_t cmd, uint8_t scmd, uint8_t dlen, uint8_t* data)
{
    // ...snip (do the actual encryption).

    // Send the result back to the capture board.
    simpleserial_put('r', 16, result_buffer);

    return 0;
}

// ... snip

simpleserial_addcmd('p', 16, encrypt_plaintext);
```

### `simpleserial_get`

Attempt to process a received command. If a packet from the capture board is
found relevant callback function(s) are called.

This is mostly used at the end of binaries to keep checking for commands being
check.

It might return without calling a callback for several reasons:

* There are no handler listening to the command send.
* The send packet is invalid. e.g. in SimpleSerial this could be due to data
  bytes not being in HexASCII format.
* The data buffer has an unexpected length.

#### Example

```c
#include "simpleserial.h"

// ...snip

// Add a listener
simpleserial_addcmd('p', 16, encrypt);

// Keep check if a command was send fitting one of the listeners.
while(1)
    simpleserial_get();
```
