The layer number is encoded into the specified output in this manner by combining one of the OUT_* constants (or a variable containing that constant value) with one of the LAYER_* constants using | or +. The firmware opcodes use two separate parameters for layer and port but the API I have designed combines them into one.
#define OUT_A 0x01 /*!< Output port A */
#define OUT_B 0x02 /*!< Output port B */
#define OUT_C 0x04 /*!< Output port C */
#define OUT_D 0x08 /*!< Output port D */
#define OUT_AB 0x03 /*!< Output ports A and B */
#define OUT_AC 0x05 /*!< Output ports A and C */
#define OUT_AD 0x09 /*!< Output ports A and D */
#define OUT_BC 0x06 /*!< Output ports B and C */
#define OUT_BD 0x0a /*!< Output ports B and D */
#define OUT_CD 0x0c /*!< Output ports C and D */
#define OUT_ABC 0x07 /*!< Output ports A, B, and C */
#define OUT_BCD 0x0e /*!< Output ports B, C, and D */
#define OUT_ABCD 0x0f /*!< Output ports A, B, C, and D */
#define OUT_ALL 0x0f /*!< All output ports (A-D) */
#define OUT_MASK 0x0f /*!< The output port mask */
// daisy chain constants
#define LAYER_MASTER 0x00 /*!< The master layer */
#define LAYER_SLAVE1 0x10 /*!< The first slave layer */
#define LAYER_SLAVE2 0x20 /*!< The second slave layer */
#define LAYER_SLAVE3 0x40 /*!< The third slave layer */
#define LAYER_MASK 0x70 /*!< The layer mask */
Thank you for the tutorial, it was really helpful in learning everything about low-level EV3 interfacing! If anyone is interested, I wrote a simple, high-level function call to handle getting info from serial sensors, as well as an example program showing its use. It's pretty rough, but it works!
GetSensor(char port, long SensorType, long & values[])
// or
GetSensor(char port, long & values[]) // (in plain C: the pointer to the array: * values[])