Fahrplan-Browser.
[hackover2013-badge-firmware.git] / drivers / rf / 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 U8 status, frm_len, hdr[CHB_HDR_SZ + 1];
109
110 while (len > 0)
111 {
112 // calculate which frame len to use. if greater than max payload, split
113 // up operation.
114 frm_len = (len > CHB_MAX_PAYLOAD) ? CHB_MAX_PAYLOAD : len;
115
116 // gen frame header
117 // hdr_len = chb_gen_hdr(hdr, addr, frm_len);
118 chb_gen_hdr(hdr, addr, frm_len);
119
120 // send data to chip
121 status = chb_tx(hdr, data, frm_len);
122
123 if (status != CHB_SUCCESS)
124 {
125 switch (status)
126 {
127 case RADIO_SUCCESS:
128 // fall through
129 case CHB_SUCCESS_DATA_PENDING:
130 pcb.txd_success++;
131 break;
132
133 case CHB_NO_ACK:
134 pcb.txd_noack++;
135 break;
136
137 case CHB_CHANNEL_ACCESS_FAILURE:
138 pcb.txd_channel_fail++;
139 break;
140
141 default:
142 break;
143 }
144 return status;
145 }
146
147 // adjust len and restart
148 len = len - frm_len;
149 }
150 return CHB_SUCCESS;
151 }
152
153 /**************************************************************************/
154 /*!
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.
157
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.
160 */
161 /**************************************************************************/
162 U8 chb_read(chb_rx_data_t *rx)
163 {
164 U8 i, len, seq, *data_ptr;
165
166 data_ptr = rx->data;
167
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)
171 {
172 return 0;
173 }
174 *data_ptr++ = len;
175
176 // load the rest of the data into buffer
177 for (i=0; i<len; i++)
178 {
179 *data_ptr++ = chb_buf_read();
180 }
181
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.
186
187 // extract the sequence number
188 data_ptr = rx->data + 3; // location of sequence number
189 seq = *data_ptr;
190
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);
197
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())
200 {
201 pcb.data_rcv = false;
202 }
203
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.
207 return len;
208 #else
209 // duplicate frame check (dupe check). we want to remove frames that have been already been received since they
210 // are just retries.
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))
214 {
215 // this is a duplicate frame from a retry. the remote node thinks we didn't receive
216 // it properly. discard.
217 return 0;
218 }
219 else
220 {
221 prev_seq = seq;
222 prev_src_addr = rx->src_addr;
223 }
224
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;
229 #endif
230 }
231
This page took 0.056236 seconds and 5 git commands to generate.