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];
111 // calculate which frame len to use. if greater than max payload, split
113 frm_len
= (len
> CHB_MAX_PAYLOAD
) ? CHB_MAX_PAYLOAD
: len
;
116 hdr_len
= chb_gen_hdr(hdr
, addr
, frm_len
);
119 status
= chb_tx(hdr
, data
, frm_len
);
121 if (status
!= CHB_SUCCESS
)
127 case CHB_SUCCESS_DATA_PENDING
:
135 case CHB_CHANNEL_ACCESS_FAILURE
:
136 pcb
.txd_channel_fail
++;
145 // adjust len and restart
151 /**************************************************************************/
153 Read data from the buffer. Need to pass in a buffer of at leasts max frame
154 size and two 16-bit containers for the src and dest addresses.
156 The read function will automatically populate the addresses and the data with
157 the frm payload. It will then return the len of the payload.
159 /**************************************************************************/
160 U8
chb_read(chb_rx_data_t
*rx
)
162 U8 i
, len
, seq
, *data_ptr
;
166 // first byte is always len. check it to make sure
167 // we have a valid len byte.
168 if ((len
= chb_buf_read()) > CHB_MAX_FRAME_LENGTH
)
174 // load the rest of the data into buffer
175 for (i
=0; i
<len
; i
++)
177 *data_ptr
++ = chb_buf_read();
180 // we're using the buffer that's fed in as an argument as a temp
181 // buffer as well to save resources.
182 // we'll use it as temp storage to parse the frame. then move the frame
183 // down so that only the payload will be in the buffer.
185 // extract the sequence number
186 data_ptr
= rx
->data
+ 3; // location of sequence number
189 // parse the buffer and extract the dest and src addresses
190 data_ptr
= rx
->data
+ 6; // location of dest addr
191 rx
->dest_addr
= *(U16
*)data_ptr
;
192 data_ptr
+= sizeof(U16
);
193 rx
->src_addr
= *(U16
*)data_ptr
;
194 data_ptr
+= sizeof(U16
);
196 // if the data in the rx buf is 0, then clear the rx_flag. otherwise, keep it raised
197 if (!chb_buf_get_len())
199 pcb
.data_rcv
= false;
202 #if (CFG_CHIBI_PROMISCUOUS == 1)
203 // if we're in promiscuous mode, we don't want to do any duplicate rejection and we don't want to move the payload
204 // to the front of the buffer. We want to capture the full frame so just keep the frame intact and return the length.
207 // duplicate frame check (dupe check). we want to remove frames that have been already been received since they
209 // note: this dupe check only removes duplicate frames from the previous transfer. if another frame from a different
210 // node comes in between the dupes, then the dupe will show up as a received frame.
211 if ((seq
== prev_seq
) && (rx
->src_addr
== prev_src_addr
))
213 // this is a duplicate frame from a retry. the remote node thinks we didn't receive
214 // it properly. discard.
220 prev_src_addr
= rx
->src_addr
;
223 // move the payload down to the beginning of the data buffer
224 memmove(rx
->data
, data_ptr
, len
- CHB_HDR_SZ
);
225 // finally, return the len of the payload
226 return len
- CHB_HDR_SZ
- CHB_FCS_LEN
;