1 /*******************************************************************
2 Copyright (C) 2009 FreakLabs
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 2. Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14 3. Neither the name of the the copyright holder nor the names of its contributors
15 may be used to endorse or promote products derived from this software
16 without specific prior written permission.
18 THIS SOFTWARE IS PROVIDED BY THE THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
19 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
22 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 Originally written by Christopher Wang aka Akiba.
31 Please post support questions to the FreakLabs forum.
33 *******************************************************************/
42 // these are for the duplicate checking and rejection
43 static U8 prev_seq
= 0xFF;
44 static U16 prev_src_addr
= 0xFFFE;
45 /**************************************************************************/
49 /**************************************************************************/
52 memset(&pcb
, 0, sizeof(chb_pcb_t
));
53 pcb
.src_addr
= chb_get_short_addr();
57 /**************************************************************************/
61 /**************************************************************************/
62 chb_pcb_t
*chb_get_pcb()
67 /**************************************************************************/
69 Requires the dest addr, location to store data, and len of payload.
70 Returns the length of the hdr.
72 /**************************************************************************/
73 static U8
chb_gen_hdr(U8
*hdr
, U16 addr
, U8 len
)
77 // calc frame size and put in 0 position of array
78 // frame size = hdr sz + payload len + fcs len
79 *hdr_ptr
++ = CHB_HDR_SZ
+ len
+ CHB_FCS_LEN
;
81 // use default fcf byte 0 val but test for ack request. we won't request
82 // ack if broadcast. all other cases we will.
83 *hdr_ptr
++ = CHB_FCF_BYTE_0
| ((addr
!= 0xFFFF) << CHB_ACK_REQ_POS
);
84 *hdr_ptr
++ = CHB_FCF_BYTE_1
;
86 *hdr_ptr
++ = pcb
.seq
++;
88 // fill out dest pan ID, dest addr, src addr
89 *(U16
*)hdr_ptr
= CFG_CHIBI_PANID
;
90 hdr_ptr
+= sizeof(U16
);
91 *(U16
*)hdr_ptr
= addr
;
92 hdr_ptr
+= sizeof(U16
);
93 *(U16
*)hdr_ptr
= pcb
.src_addr
;
94 hdr_ptr
+= sizeof(U16
);
96 // return the len of the header
100 /**************************************************************************/
104 /**************************************************************************/
105 U8
chb_write(U16 addr
, U8
*data
, U8 len
)
107 // U8 status, frm_len, hdr_len, hdr[CHB_HDR_SZ + 1];
108 U8 status
, frm_len
, hdr
[CHB_HDR_SZ
+ 1];
112 // calculate which frame len to use. if greater than max payload, split
114 frm_len
= (len
> CHB_MAX_PAYLOAD
) ? CHB_MAX_PAYLOAD
: len
;
117 // hdr_len = chb_gen_hdr(hdr, addr, frm_len);
118 chb_gen_hdr(hdr
, addr
, frm_len
);
121 status
= chb_tx(hdr
, data
, frm_len
);
123 if (status
!= CHB_SUCCESS
)
129 case CHB_SUCCESS_DATA_PENDING
:
137 case CHB_CHANNEL_ACCESS_FAILURE
:
138 pcb
.txd_channel_fail
++;
147 // adjust len and restart
153 /**************************************************************************/
155 Read data from the buffer. Need to pass in a buffer of at leasts max frame
156 size and two 16-bit containers for the src and dest addresses.
158 The read function will automatically populate the addresses and the data with
159 the frm payload. It will then return the len of the payload.
161 /**************************************************************************/
162 U8
chb_read(chb_rx_data_t
*rx
)
164 U8 i
, len
, seq
, *data_ptr
;
168 // first byte is always len. check it to make sure
169 // we have a valid len byte.
170 if ((len
= chb_buf_read()) > CHB_MAX_FRAME_LENGTH
)
176 // load the rest of the data into buffer
177 for (i
=0; i
<len
; i
++)
179 *data_ptr
++ = chb_buf_read();
182 // we're using the buffer that's fed in as an argument as a temp
183 // buffer as well to save resources.
184 // we'll use it as temp storage to parse the frame. then move the frame
185 // down so that only the payload will be in the buffer.
187 // extract the sequence number
188 data_ptr
= rx
->data
+ 3; // location of sequence number
191 // parse the buffer and extract the dest and src addresses
192 data_ptr
= rx
->data
+ 6; // location of dest addr
193 rx
->dest_addr
= *(U16
*)data_ptr
;
194 data_ptr
+= sizeof(U16
);
195 rx
->src_addr
= *(U16
*)data_ptr
;
196 data_ptr
+= sizeof(U16
);
198 // if the data in the rx buf is 0, then clear the rx_flag. otherwise, keep it raised
199 if (!chb_buf_get_len())
201 pcb
.data_rcv
= false;
204 #if (CFG_CHIBI_PROMISCUOUS == 1)
205 // if we're in promiscuous mode, we don't want to do any duplicate rejection and we don't want to move the payload
206 // to the front of the buffer. We want to capture the full frame so just keep the frame intact and return the length.
209 // duplicate frame check (dupe check). we want to remove frames that have been already been received since they
211 // note: this dupe check only removes duplicate frames from the previous transfer. if another frame from a different
212 // node comes in between the dupes, then the dupe will show up as a received frame.
213 if ((seq
== prev_seq
) && (rx
->src_addr
== prev_src_addr
))
215 // this is a duplicate frame from a retry. the remote node thinks we didn't receive
216 // it properly. discard.
222 prev_src_addr
= rx
->src_addr
;
225 // move the payload down to the beginning of the data buffer
226 memmove(rx
->data
, data_ptr
, len
- CHB_HDR_SZ
);
227 // finally, return the len of the payload
228 return len
- CHB_HDR_SZ
- CHB_FCS_LEN
;