xref: /aosp_15_r20/external/openthread/src/lib/spinel/spi_frame.hpp (revision cfb92d1480a9e65faed56933e9c12405f45898b4)
1*cfb92d14SAndroid Build Coastguard Worker /*
2*cfb92d14SAndroid Build Coastguard Worker  *    Copyright (c) 2023, The OpenThread Authors.
3*cfb92d14SAndroid Build Coastguard Worker  *    All rights reserved.
4*cfb92d14SAndroid Build Coastguard Worker  *
5*cfb92d14SAndroid Build Coastguard Worker  *    Redistribution and use in source and binary forms, with or without
6*cfb92d14SAndroid Build Coastguard Worker  *    modification, are permitted provided that the following conditions are met:
7*cfb92d14SAndroid Build Coastguard Worker  *    1. Redistributions of source code must retain the above copyright
8*cfb92d14SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer.
9*cfb92d14SAndroid Build Coastguard Worker  *    2. Redistributions in binary form must reproduce the above copyright
10*cfb92d14SAndroid Build Coastguard Worker  *       notice, this list of conditions and the following disclaimer in the
11*cfb92d14SAndroid Build Coastguard Worker  *       documentation and/or other materials provided with the distribution.
12*cfb92d14SAndroid Build Coastguard Worker  *    3. Neither the name of the copyright holder nor the
13*cfb92d14SAndroid Build Coastguard Worker  *       names of its contributors may be used to endorse or promote products
14*cfb92d14SAndroid Build Coastguard Worker  *       derived from this software without specific prior written permission.
15*cfb92d14SAndroid Build Coastguard Worker  *
16*cfb92d14SAndroid Build Coastguard Worker  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17*cfb92d14SAndroid Build Coastguard Worker  *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*cfb92d14SAndroid Build Coastguard Worker  *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*cfb92d14SAndroid Build Coastguard Worker  *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20*cfb92d14SAndroid Build Coastguard Worker  *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21*cfb92d14SAndroid Build Coastguard Worker  *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22*cfb92d14SAndroid Build Coastguard Worker  *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23*cfb92d14SAndroid Build Coastguard Worker  *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24*cfb92d14SAndroid Build Coastguard Worker  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25*cfb92d14SAndroid Build Coastguard Worker  *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*cfb92d14SAndroid Build Coastguard Worker  */
27*cfb92d14SAndroid Build Coastguard Worker 
28*cfb92d14SAndroid Build Coastguard Worker /**
29*cfb92d14SAndroid Build Coastguard Worker  * @file
30*cfb92d14SAndroid Build Coastguard Worker  *   This file contains definitions of the SPI frame.
31*cfb92d14SAndroid Build Coastguard Worker  */
32*cfb92d14SAndroid Build Coastguard Worker 
33*cfb92d14SAndroid Build Coastguard Worker #ifndef SPINEL_SPI_FRAME_HPP_
34*cfb92d14SAndroid Build Coastguard Worker #define SPINEL_SPI_FRAME_HPP_
35*cfb92d14SAndroid Build Coastguard Worker 
36*cfb92d14SAndroid Build Coastguard Worker #include <stdint.h>
37*cfb92d14SAndroid Build Coastguard Worker 
38*cfb92d14SAndroid Build Coastguard Worker #include "lib/utils/endian.hpp"
39*cfb92d14SAndroid Build Coastguard Worker 
40*cfb92d14SAndroid Build Coastguard Worker namespace ot {
41*cfb92d14SAndroid Build Coastguard Worker namespace Spinel {
42*cfb92d14SAndroid Build Coastguard Worker 
43*cfb92d14SAndroid Build Coastguard Worker /*
44*cfb92d14SAndroid Build Coastguard Worker  *   SPI Framing Protocol
45*cfb92d14SAndroid Build Coastguard Worker  *
46*cfb92d14SAndroid Build Coastguard Worker  *   Each SPI frame starts with a 5-byte frame header:
47*cfb92d14SAndroid Build Coastguard Worker  *
48*cfb92d14SAndroid Build Coastguard Worker  *                  +---------+-----+----------+----------+
49*cfb92d14SAndroid Build Coastguard Worker  *                  | Octets: |  1  |    2     |    2     |
50*cfb92d14SAndroid Build Coastguard Worker  *                  +---------+-----+----------+----------+
51*cfb92d14SAndroid Build Coastguard Worker  *                  | Fields: | HDR | RECV_LEN | DATA_LEN |
52*cfb92d14SAndroid Build Coastguard Worker  *                  +---------+-----+----------+----------+
53*cfb92d14SAndroid Build Coastguard Worker  *
54*cfb92d14SAndroid Build Coastguard Worker  *   -  "HDR": The first byte is the header byte (defined below)
55*cfb92d14SAndroid Build Coastguard Worker  *   -  "RECV_LEN": The second and third bytes indicate the largest frame
56*cfb92d14SAndroid Build Coastguard Worker  *      size that that device is ready to receive.  If zero, then the
57*cfb92d14SAndroid Build Coastguard Worker  *      other device must not send any data. (Little endian)
58*cfb92d14SAndroid Build Coastguard Worker  *   -  "DATA_LEN": The fourth and fifth bytes indicate the size of the
59*cfb92d14SAndroid Build Coastguard Worker  *      pending data frame to be sent to the other device.  If this value
60*cfb92d14SAndroid Build Coastguard Worker  *      is equal-to or less-than the number of bytes that the other device
61*cfb92d14SAndroid Build Coastguard Worker  *      is willing to receive, then the data of the frame is immediately
62*cfb92d14SAndroid Build Coastguard Worker  *      after the header. (Little Endian)
63*cfb92d14SAndroid Build Coastguard Worker  *
64*cfb92d14SAndroid Build Coastguard Worker  *   The "HDR" byte is defined as:
65*cfb92d14SAndroid Build Coastguard Worker  *
66*cfb92d14SAndroid Build Coastguard Worker  *                       0   1   2   3   4   5   6   7
67*cfb92d14SAndroid Build Coastguard Worker  *                     +---+---+---+---+---+---+---+---+
68*cfb92d14SAndroid Build Coastguard Worker  *                     |RST|CRC|CCF|  RESERVED |PATTERN|
69*cfb92d14SAndroid Build Coastguard Worker  *                     +---+---+---+---+---+---+---+---+
70*cfb92d14SAndroid Build Coastguard Worker  *
71*cfb92d14SAndroid Build Coastguard Worker  *   -  "RST": This bit is set when that device has been reset since the
72*cfb92d14SAndroid Build Coastguard Worker  *      last time `CS` (chip select) was asserted.
73*cfb92d14SAndroid Build Coastguard Worker  *   -  "CRC": This bit is set when that device supports writing a 16-bit
74*cfb92d14SAndroid Build Coastguard Worker  *      CRC at the end of the data.  The CRC length is NOT included in
75*cfb92d14SAndroid Build Coastguard Worker  *      DATA_LEN.
76*cfb92d14SAndroid Build Coastguard Worker  *   -  "CCF": "CRC Check Failure".  Set if the CRC check on the last
77*cfb92d14SAndroid Build Coastguard Worker  *      received frame failed, cleared to zero otherwise.  This bit is
78*cfb92d14SAndroid Build Coastguard Worker  *      only used if both sides support CRC.
79*cfb92d14SAndroid Build Coastguard Worker  *   -  "RESERVED": These bits are all reserved for future used.  They
80*cfb92d14SAndroid Build Coastguard Worker  *      MUST be cleared to zero and MUST be ignored if set.
81*cfb92d14SAndroid Build Coastguard Worker  *   -  "PATTERN": These bits are set to a fixed value to help distinguish
82*cfb92d14SAndroid Build Coastguard Worker  *      valid SPI frames from garbage (by explicitly making "0xFF" and
83*cfb92d14SAndroid Build Coastguard Worker  *      "0x00" invalid values).  Bit 6 MUST be set to be one and bit 7
84*cfb92d14SAndroid Build Coastguard Worker  *      MUST be cleared (0).  A frame received that has any other values
85*cfb92d14SAndroid Build Coastguard Worker  *      for these bits MUST be dropped.
86*cfb92d14SAndroid Build Coastguard Worker  *
87*cfb92d14SAndroid Build Coastguard Worker  *   Prior to a sending or receiving a frame, the master MAY send a
88*cfb92d14SAndroid Build Coastguard Worker  *   5-octet frame with zeros for both the max receive frame size and the
89*cfb92d14SAndroid Build Coastguard Worker  *   the contained frame length.  This will induce the slave device to
90*cfb92d14SAndroid Build Coastguard Worker  *   indicate the length of the frame it wants to send (if any) and
91*cfb92d14SAndroid Build Coastguard Worker  *   indicate the largest frame it is capable of receiving at the moment.
92*cfb92d14SAndroid Build Coastguard Worker  *   This allows the master to calculate the size of the next transaction.
93*cfb92d14SAndroid Build Coastguard Worker  *   Alternatively, if the master has a frame to send it can just go ahead
94*cfb92d14SAndroid Build Coastguard Worker  *   and send a frame of that length and determine if the frame was
95*cfb92d14SAndroid Build Coastguard Worker  *   accepted by checking that the "RECV_LEN" from the slave frame is
96*cfb92d14SAndroid Build Coastguard Worker  *   larger than the frame the master just tried to send.  If the
97*cfb92d14SAndroid Build Coastguard Worker  *   "RECV_LEN" is smaller then the frame wasn't accepted and will need to
98*cfb92d14SAndroid Build Coastguard Worker  *   be transmitted again.
99*cfb92d14SAndroid Build Coastguard Worker  *
100*cfb92d14SAndroid Build Coastguard Worker  *   This protocol can be used either unidirectionally or bidirectionally,
101*cfb92d14SAndroid Build Coastguard Worker  *   determined by the behavior of the master and the slave.
102*cfb92d14SAndroid Build Coastguard Worker  *
103*cfb92d14SAndroid Build Coastguard Worker  *   If the the master notices "PATTERN" is not set correctly, the master
104*cfb92d14SAndroid Build Coastguard Worker  *   should consider the transaction to have failed and try again after 10
105*cfb92d14SAndroid Build Coastguard Worker  *   milliseconds, retrying up to 200 times.  After unsuccessfully trying
106*cfb92d14SAndroid Build Coastguard Worker  *   200 times in a row, the master MAY take appropriate remedial action
107*cfb92d14SAndroid Build Coastguard Worker  *   (like a NCP hardware reset, or indicating a communication failure to
108*cfb92d14SAndroid Build Coastguard Worker  *   a user interface).
109*cfb92d14SAndroid Build Coastguard Worker  *
110*cfb92d14SAndroid Build Coastguard Worker  *   At the end of the data of a frame is an optional 16-bit CRC, support
111*cfb92d14SAndroid Build Coastguard Worker  *   for which is indicated by the "CRC" bit of the "HDR" byte being set.
112*cfb92d14SAndroid Build Coastguard Worker  *   If these bits are set for both the master and slave frames, then CRC
113*cfb92d14SAndroid Build Coastguard Worker  *   checking is enabled on both sides, effectively requiring that frame
114*cfb92d14SAndroid Build Coastguard Worker  *   sizes be two bytes longer than would be otherwise required.  The CRC
115*cfb92d14SAndroid Build Coastguard Worker  *   is calculated using the same mechanism used for the CRC calculation
116*cfb92d14SAndroid Build Coastguard Worker  *   in HDLC-Lite (See Appendix A.1.2).  When both of the "CRC" bits are
117*cfb92d14SAndroid Build Coastguard Worker  *   set, both sides must verify that the "CRC" is valid before accepting
118*cfb92d14SAndroid Build Coastguard Worker  *   the frame.  If not enough bytes were clocked out for the CRC to be
119*cfb92d14SAndroid Build Coastguard Worker  *   read, then the frame must be ignored.  If enough bytes were clocked
120*cfb92d14SAndroid Build Coastguard Worker  *   out to perform a CRC check, but the CRC check fails, then the frame
121*cfb92d14SAndroid Build Coastguard Worker  *   must be rejected and the "CRC_FAIL" bit on the next frame (and ONLY
122*cfb92d14SAndroid Build Coastguard Worker  *   the next frame) MUST be set.
123*cfb92d14SAndroid Build Coastguard Worker  */
124*cfb92d14SAndroid Build Coastguard Worker 
125*cfb92d14SAndroid Build Coastguard Worker /**
126*cfb92d14SAndroid Build Coastguard Worker  * Defines a SPI frame.
127*cfb92d14SAndroid Build Coastguard Worker  *
128*cfb92d14SAndroid Build Coastguard Worker  */
129*cfb92d14SAndroid Build Coastguard Worker class SpiFrame
130*cfb92d14SAndroid Build Coastguard Worker {
131*cfb92d14SAndroid Build Coastguard Worker public:
132*cfb92d14SAndroid Build Coastguard Worker     enum
133*cfb92d14SAndroid Build Coastguard Worker     {
134*cfb92d14SAndroid Build Coastguard Worker         kHeaderSize = 5, ///< SPI header size (in bytes).
135*cfb92d14SAndroid Build Coastguard Worker     };
136*cfb92d14SAndroid Build Coastguard Worker 
137*cfb92d14SAndroid Build Coastguard Worker     /**
138*cfb92d14SAndroid Build Coastguard Worker      * Initializes an `SpiFrame` instance.
139*cfb92d14SAndroid Build Coastguard Worker      *
140*cfb92d14SAndroid Build Coastguard Worker      * @param[in] aBuffer     Pointer to buffer containing the frame.
141*cfb92d14SAndroid Build Coastguard Worker      *
142*cfb92d14SAndroid Build Coastguard Worker      */
SpiFrame(uint8_t * aBuffer)143*cfb92d14SAndroid Build Coastguard Worker     explicit SpiFrame(uint8_t *aBuffer)
144*cfb92d14SAndroid Build Coastguard Worker         : mBuffer(aBuffer)
145*cfb92d14SAndroid Build Coastguard Worker     {
146*cfb92d14SAndroid Build Coastguard Worker     }
147*cfb92d14SAndroid Build Coastguard Worker 
148*cfb92d14SAndroid Build Coastguard Worker     /**
149*cfb92d14SAndroid Build Coastguard Worker      * Gets a pointer to data portion in the SPI frame skipping the header.
150*cfb92d14SAndroid Build Coastguard Worker      *
151*cfb92d14SAndroid Build Coastguard Worker      * @returns  A pointer to data in the SPI frame.
152*cfb92d14SAndroid Build Coastguard Worker      *
153*cfb92d14SAndroid Build Coastguard Worker      */
GetData(void)154*cfb92d14SAndroid Build Coastguard Worker     uint8_t *GetData(void) { return mBuffer + kHeaderSize; }
155*cfb92d14SAndroid Build Coastguard Worker 
156*cfb92d14SAndroid Build Coastguard Worker     /**
157*cfb92d14SAndroid Build Coastguard Worker      * Indicates whether or not the frame is valid.
158*cfb92d14SAndroid Build Coastguard Worker      *
159*cfb92d14SAndroid Build Coastguard Worker      * In a valid frame the flag byte should contain the pattern bits.
160*cfb92d14SAndroid Build Coastguard Worker      *
161*cfb92d14SAndroid Build Coastguard Worker      * @returns TRUE if the frame is valid, FALSE otherwise.
162*cfb92d14SAndroid Build Coastguard Worker      *
163*cfb92d14SAndroid Build Coastguard Worker      */
IsValid(void) const164*cfb92d14SAndroid Build Coastguard Worker     bool IsValid(void) const { return ((mBuffer[kIndexFlagByte] & kFlagPatternMask) == kFlagPattern); }
165*cfb92d14SAndroid Build Coastguard Worker 
166*cfb92d14SAndroid Build Coastguard Worker     /**
167*cfb92d14SAndroid Build Coastguard Worker      * Indicates whether or not the "RST" bit is set.
168*cfb92d14SAndroid Build Coastguard Worker      *
169*cfb92d14SAndroid Build Coastguard Worker      * @returns TRUE if the "RST" bit is set, FALSE otherwise.
170*cfb92d14SAndroid Build Coastguard Worker      *
171*cfb92d14SAndroid Build Coastguard Worker      */
IsResetFlagSet(void) const172*cfb92d14SAndroid Build Coastguard Worker     bool IsResetFlagSet(void) const { return ((mBuffer[kIndexFlagByte] & kFlagReset) == kFlagReset); }
173*cfb92d14SAndroid Build Coastguard Worker 
174*cfb92d14SAndroid Build Coastguard Worker     /**
175*cfb92d14SAndroid Build Coastguard Worker      * Sets the "flag byte" field in the SPI frame header.
176*cfb92d14SAndroid Build Coastguard Worker      *
177*cfb92d14SAndroid Build Coastguard Worker      * @param[in] aResetFlag     The status of reset flag (TRUE to set the flag, FALSE to clear flag).
178*cfb92d14SAndroid Build Coastguard Worker      *
179*cfb92d14SAndroid Build Coastguard Worker      */
SetHeaderFlagByte(bool aResetFlag)180*cfb92d14SAndroid Build Coastguard Worker     void SetHeaderFlagByte(bool aResetFlag) { mBuffer[kIndexFlagByte] = kFlagPattern | (aResetFlag ? kFlagReset : 0); }
181*cfb92d14SAndroid Build Coastguard Worker 
182*cfb92d14SAndroid Build Coastguard Worker     /**
183*cfb92d14SAndroid Build Coastguard Worker      * Gets the "flag byte" field in the SPI frame header.
184*cfb92d14SAndroid Build Coastguard Worker      *
185*cfb92d14SAndroid Build Coastguard Worker      * @returns  The flag byte.
186*cfb92d14SAndroid Build Coastguard Worker      *
187*cfb92d14SAndroid Build Coastguard Worker      */
GetHeaderFlagByte(void) const188*cfb92d14SAndroid Build Coastguard Worker     uint8_t GetHeaderFlagByte(void) const { return mBuffer[kIndexFlagByte]; }
189*cfb92d14SAndroid Build Coastguard Worker 
190*cfb92d14SAndroid Build Coastguard Worker     /**
191*cfb92d14SAndroid Build Coastguard Worker      * Sets the "accept len" field in the SPI frame header.
192*cfb92d14SAndroid Build Coastguard Worker      *
193*cfb92d14SAndroid Build Coastguard Worker      * "accept len" specifies number of bytes the sender of the SPI frame can receive.
194*cfb92d14SAndroid Build Coastguard Worker      *
195*cfb92d14SAndroid Build Coastguard Worker      * @param[in] aAcceptLen    The accept length in bytes.
196*cfb92d14SAndroid Build Coastguard Worker      *
197*cfb92d14SAndroid Build Coastguard Worker      */
SetHeaderAcceptLen(uint16_t aAcceptLen)198*cfb92d14SAndroid Build Coastguard Worker     void SetHeaderAcceptLen(uint16_t aAcceptLen)
199*cfb92d14SAndroid Build Coastguard Worker     {
200*cfb92d14SAndroid Build Coastguard Worker         Lib::Utils::LittleEndian::WriteUint16(aAcceptLen, mBuffer + kIndexAcceptLen);
201*cfb92d14SAndroid Build Coastguard Worker     }
202*cfb92d14SAndroid Build Coastguard Worker 
203*cfb92d14SAndroid Build Coastguard Worker     /**
204*cfb92d14SAndroid Build Coastguard Worker      * Gets the "accept len" field in the SPI frame header.
205*cfb92d14SAndroid Build Coastguard Worker      *
206*cfb92d14SAndroid Build Coastguard Worker      * @returns  The accept length in bytes.
207*cfb92d14SAndroid Build Coastguard Worker      *
208*cfb92d14SAndroid Build Coastguard Worker      */
GetHeaderAcceptLen(void) const209*cfb92d14SAndroid Build Coastguard Worker     uint16_t GetHeaderAcceptLen(void) const { return Lib::Utils::LittleEndian::ReadUint16(mBuffer + kIndexAcceptLen); }
210*cfb92d14SAndroid Build Coastguard Worker 
211*cfb92d14SAndroid Build Coastguard Worker     /**
212*cfb92d14SAndroid Build Coastguard Worker      * Sets the "data len" field in the SPI frame header.
213*cfb92d14SAndroid Build Coastguard Worker      *
214*cfb92d14SAndroid Build Coastguard Worker      * "Data len" specifies number of data bytes in the transmitted SPI frame.
215*cfb92d14SAndroid Build Coastguard Worker      *
216*cfb92d14SAndroid Build Coastguard Worker      * @param[in] aDataLen    The data length in bytes.
217*cfb92d14SAndroid Build Coastguard Worker      *
218*cfb92d14SAndroid Build Coastguard Worker      */
SetHeaderDataLen(uint16_t aDataLen)219*cfb92d14SAndroid Build Coastguard Worker     void SetHeaderDataLen(uint16_t aDataLen)
220*cfb92d14SAndroid Build Coastguard Worker     {
221*cfb92d14SAndroid Build Coastguard Worker         Lib::Utils::LittleEndian::WriteUint16(aDataLen, mBuffer + kIndexDataLen);
222*cfb92d14SAndroid Build Coastguard Worker     }
223*cfb92d14SAndroid Build Coastguard Worker 
224*cfb92d14SAndroid Build Coastguard Worker     /**
225*cfb92d14SAndroid Build Coastguard Worker      * Gets the "data len" field in the SPI frame header.
226*cfb92d14SAndroid Build Coastguard Worker      *
227*cfb92d14SAndroid Build Coastguard Worker      * @returns  The data length in bytes.
228*cfb92d14SAndroid Build Coastguard Worker      *
229*cfb92d14SAndroid Build Coastguard Worker      */
GetHeaderDataLen(void) const230*cfb92d14SAndroid Build Coastguard Worker     uint16_t GetHeaderDataLen(void) const { return Lib::Utils::LittleEndian::ReadUint16(mBuffer + kIndexDataLen); }
231*cfb92d14SAndroid Build Coastguard Worker 
232*cfb92d14SAndroid Build Coastguard Worker private:
233*cfb92d14SAndroid Build Coastguard Worker     enum
234*cfb92d14SAndroid Build Coastguard Worker     {
235*cfb92d14SAndroid Build Coastguard Worker         kIndexFlagByte  = 0, // flag byte  (uint8_t).
236*cfb92d14SAndroid Build Coastguard Worker         kIndexAcceptLen = 1, // accept len (uint16_t little-endian encoding).
237*cfb92d14SAndroid Build Coastguard Worker         kIndexDataLen   = 3, // data len   (uint16_t little-endian encoding).
238*cfb92d14SAndroid Build Coastguard Worker 
239*cfb92d14SAndroid Build Coastguard Worker         kFlagReset       = (1 << 7), // Flag byte RESET bit.
240*cfb92d14SAndroid Build Coastguard Worker         kFlagPattern     = 0x02,     // Flag byte PATTERN bits.
241*cfb92d14SAndroid Build Coastguard Worker         kFlagPatternMask = 0x03,     // Flag byte PATTERN mask.
242*cfb92d14SAndroid Build Coastguard Worker     };
243*cfb92d14SAndroid Build Coastguard Worker 
244*cfb92d14SAndroid Build Coastguard Worker     uint8_t *mBuffer;
245*cfb92d14SAndroid Build Coastguard Worker };
246*cfb92d14SAndroid Build Coastguard Worker 
247*cfb92d14SAndroid Build Coastguard Worker } // namespace Spinel
248*cfb92d14SAndroid Build Coastguard Worker } // namespace ot
249*cfb92d14SAndroid Build Coastguard Worker #endif // SPINEL_SPI_FRAME_HPP_
250