e5a56dda58d4cb36ae57e213c03838ccb4e9c6d9
[hackover2013-badge-firmware.git] / drivers / chibi / chb.c
1 /*******************************************************************
2 Copyright (C) 2009 FreakLabs
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8
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.
17
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
28 SUCH DAMAGE.
29
30 Originally written by Christopher Wang aka Akiba.
31 Please post support questions to the FreakLabs forum.
32
33 *******************************************************************/
34 #include <stdio.h>
35 #include <string.h>
36
37 #include "chb.h"
38 #include "chb_drvr.h"
39 #include "chb_buf.h"
40
41 static chb_pcb_t pcb;
42 // these are for the duplicate checking and rejection
43 static U8 prev_seq = 0xFF;
44 static U16 prev_src_addr = 0xFFFE;
45 /**************************************************************************/
46 /*!
47
48 */
49 /**************************************************************************/
50 void chb_init()
51 {
52 memset(&pcb, 0, sizeof(chb_pcb_t));
53 pcb.src_addr = chb_get_short_addr();
54 chb_drvr_init();
55 }
56
57 /**************************************************************************/
58 /*!
59
60 */
61 /**************************************************************************/
62 chb_pcb_t *chb_get_pcb()
63 {
64 return &pcb;
65 }
66
67 /**************************************************************************/
68 /*!
69 Requires the dest addr, location to store data, and len of payload.
70 Returns the length of the hdr.
71 */
72 /**************************************************************************/
73 static U8 chb_gen_hdr(U8 *hdr, U16 addr, U8 len)
74 {
75 U8 *hdr_ptr = hdr;
76
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;
80
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;
85
86 *hdr_ptr++ = pcb.seq++;
87
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);
95
96 // return the len of the header
97 return hdr_ptr - hdr;
98 }
99
100 /**************************************************************************/
101 /*!
102
103 */
104 /**************************************************************************/
105 U8 chb_write(U16 addr, U8 *data, U8 len)
106 {
107 U8 status, frm_len, hdr_len, hdr[CHB_HDR_SZ + 1];
108
109 while (len > 0)
110 {
111 // calculate which frame len to use. if greater than max payload, split
112 // up operation.
113 frm_len = (len > CHB_MAX_PAYLOAD) ? CHB_MAX_PAYLOAD : len;
114
115 // gen frame header
116 hdr_len = chb_gen_hdr(hdr, addr, frm_len);
117
118 // send data to chip
119 status = chb_tx(hdr, data, frm_len);
120
121 if (status != CHB_SUCCESS)
122 {
123 switch (status)
124 {
125 case RADIO_SUCCESS:
126 // fall through
127 case CHB_SUCCESS_DATA_PENDING:
128 pcb.txd_success++;
129 break;
130
131 case CHB_NO_ACK:
132 pcb.txd_noack++;
133 break;
134
135 case CHB_CHANNEL_ACCESS_FAILURE:
136 pcb.txd_channel_fail++;
137 break;
138
139 default:
140 break;
141 }
142 return status;
143 }
144
145 // adjust len and restart
146 len = len - frm_len;
147 }
148 return CHB_SUCCESS;
149 }
150
151 /**************************************************************************/
152 /*!
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.
155
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.
158 */
159 /**************************************************************************/
160 U8 chb_read(chb_rx_data_t *rx)
161 {
162 U8 i, len, seq, *data_ptr;
163
164 data_ptr = rx->data;
165
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)
169 {
170 return 0;
171 }
172 *data_ptr++ = len;
173
174 // load the rest of the data into buffer
175 for (i=0; i<len; i++)
176 {
177 *data_ptr++ = chb_buf_read();
178 }
179
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.
184
185 // extract the sequence number
186 data_ptr = rx->data + 3; // location of sequence number
187 seq = *data_ptr;
188
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);
195
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())
198 {
199 pcb.data_rcv = false;
200 }
201
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.
205 return len;
206 #else
207 // duplicate frame check (dupe check). we want to remove frames that have been already been received since they
208 // are just retries.
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))
212 {
213 // this is a duplicate frame from a retry. the remote node thinks we didn't receive
214 // it properly. discard.
215 return 0;
216 }
217 else
218 {
219 prev_seq = seq;
220 prev_src_addr = rx->src_addr;
221 }
222
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;
227 #endif
228 }
229
This page took 0.075104 seconds and 3 git commands to generate.