-5

Let us say I am receiving a packet with variable length data payload.

**byte_num**    **size**     **type**
   0             1        Length
   1             1        SrcArsDev
   2             4        Src_ID
   6             1        DstArsDev
   7             4        Dst_ID
  11             4        Session
  15             1        CMD
  16             N        N bytes payload N<=96
 16+N            2        CRC

The data will be received over SPI communication. What is the general method for parsing the packets so I can later manipulate the distinct elements?

Can you please show me a simple function/routine that fills the structure elements?

Paul R
  • 208,748
  • 37
  • 389
  • 560
  • 3
    What have you tried so far? Please post some code so we can answer a concrete question. – Jan Henke Feb 04 '15 at 12:41
  • we,, your `receive()` or `read()` or similar function should return you the number of bytes successfully read, right? from there, you can have your calculations on the received packet. – Sourav Ghosh Feb 04 '15 at 12:42

2 Answers2

0

One approach is to define a packed struct which represents the largest possible packet size:

#pragma pack(push,1) // make sure everything is packed to byte level
typedef struct {
    uint8_t        Length;
    uint8_t        SrcArsDev;
    uint32_t       Src_ID;
    uint8_t        DstArsDev;
    uint32_t       Dst_ID;
    uint32_t       Session;
    uint8_t        CMD;
    uint8_t        payload[96 + 2]; // payload + CRC
} Message;
#pragma pack(pop)    // restore struct packing

Your read routine then reads directly to such a struct, and then all the elements of the message can subsequently be accessed as fields within the struct.

The only tricky part is that you'll need to work out where the actual CRC bytes are based on Length and then extract these from the payload[] buffer, but this is not too difficult:

Message msg;

ssize_t n = read(fd, &msg, sizeof(msg));            // read data into `msg`

uint16_t crc = *(int16_t*)&msg.payload[msg.Length]; // extract CRC

// validate CRC + perhaps also verify that n is consistent with msg.Length

// then access elements as needed:

src_id = msg.Src_ID;
dst_id = msg.Dst_ID;
Paul R
  • 208,748
  • 37
  • 389
  • 560
  • If you're compiling with GCC, use `__attribute__((__packed__))` to align bytes by 1. – totten Feb 04 '15 at 12:47
  • 1
    @totten: gcc also supports `#pragma pack` for compatibility with other compilers. – Paul R Feb 04 '15 at 12:49
  • Thank you Paul R for the answer. Can you please show me a simple function/routine that fills the structure elements? – user3789035 Feb 04 '15 at 13:23
  • @user3789035: I've edited the answer now to include an example using [read()](http://linux.die.net/man/2/read). – Paul R Feb 04 '15 at 13:26
  • let assume that spi_read() returns one consecutive byte from the packet, what would be the routine to save all received bytes into the structure msg elements? – user3789035 Feb 04 '15 at 14:00
  • Can you please write the function definition of read(fd, &msg, sizeof(msg)); – user3789035 Feb 04 '15 at 14:21
  • `read()` is a standard C library call - I put a link to the man page in my comment above. `spi_read()` has a similar function signature. – Paul R Feb 04 '15 at 14:22
  • Should I first, save the packet into a buffer before I parse the data into the structure? – user3789035 Feb 04 '15 at 15:18
  • Why would you want to do that ? It would just be a redundant copy. You can just read the data directly to the struct, as I explained in the answer above. – Paul R Feb 04 '15 at 15:23
0

When you do not mind to check the CRC with a special function, you can cast a struct like @Paul defined. When you have read the inputbuf, you can use

struct *Message payload;   
payload = (Message *) inputbuf;

Now you can access payload members without copying them first.

Walter A
  • 19,067
  • 2
  • 23
  • 43