FreeCalypso > hg > fc-tourmaline
comparison src/g23m-aci/l2p/l2p.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:4e78acac3d88 | 1:fa8dc04885d8 |
---|---|
1 /* | |
2 +----------------------------------------------------------------------------- | |
3 | Project : BAT L2P () | |
4 | Modul : BAT_L2P | |
5 +----------------------------------------------------------------------------- | |
6 | Copyright 2005 Texas Instruments Berlin, AG | |
7 | All rights reserved. | |
8 | | |
9 | This file is confidential and a trade secret of Texas | |
10 | Instruments Berlin, AG | |
11 | The receipt of or possession of this file does not convey | |
12 | any rights to reproduce or disclose its contents or to | |
13 | manufacture, use, or sell anything it may describe, in | |
14 | whole, or in part, without the specific written consent of | |
15 | Texas Instruments Berlin, AG. | |
16 +----------------------------------------------------------------------------- | |
17 | Purpose : L2P function definitions | |
18 +----------------------------------------------------------------------------- | |
19 */ | |
20 #include "typedefs.h" /* to get TI data types */ | |
21 #include "vsi.h" /* to get a lot of macros */ | |
22 #include "l2p_types.h" | |
23 #include "l2p.h" | |
24 | |
25 #include "string.h" | |
26 | |
27 T_L2P_CONTROL_BLOCK *l2p_control_block_list = (T_L2P_CONTROL_BLOCK *)0; | |
28 | |
29 /* | |
30 ** Local function declarations | |
31 */ | |
32 static char *L2P_write_data_to_seg(char *writePtr, char *dataPtr, U16 dataSize, U16 remain_seg_size, | |
33 U16 *bytesWritten); | |
34 | |
35 static char *L2P_read_data_from_seg(char *readPtr, char *writePtr, U16 dataSize, U16 remain_seg_size, | |
36 U16 *bytesWritten); | |
37 | |
38 | |
39 /* | |
40 ** L2P function definitions | |
41 */ | |
42 | |
43 /* | |
44 +--------------------------------------------------------------------+ | |
45 | PROJECT: BAT L2P MODULE: L2P | | |
46 | STATE : code ROUTINE: L2P_Configure | | |
47 +--------------------------------------------------------------------+ | |
48 | |
49 PURPOSE : L2P_Configure will initiaise the L2P for each instance of BAT Lib or BAT Module | |
50 that wishes to use its services. The following is a list of the parameters, and their uses: | |
51 | |
52 batId : A identifer to uniquely identify each instance of BAT using this L2P | |
53 mem : A block of memory for L2P to use as a Control Block (L2P cannot allocate its own memory) | |
54 num_mux_chnls: The number of clients being supported at the application end (this information is | |
55 passed to BAT Module as part of the startup process) | |
56 protocolId : The protocol being used to communicate with the peer entity | |
57 maxMTU : Maximum size of a transport unit. | |
58 xxx_CB : These are callback functions, provided by the BAT Lib or BAT Module, to provide necessary | |
59 services to L2P to get Send and Receive buffers, Send the Frames and receive fully | |
60 completed packets | |
61 | |
62 */ | |
63 T_L2P_STATUS L2P_Configure(U8 batid, void *mem, | |
64 T_L2P_SUPPORTED_PROTOCOLS protocolId, | |
65 U16 maxMTU, | |
66 L2P_Get_Tx_Buf_CB Get_Tx_Buf_Cb, | |
67 L2P_Get_Rx_Buf_CB Get_Rx_Buf_Cb, | |
68 L2P_Get_Next_Seg_CB Get_Next_Seg_Cb, | |
69 L2P_Send_Frame_CB Send_Frame_Cb, | |
70 L2P_Msg_Rxd_CB Msg_Rxd_Cb) | |
71 { | |
72 T_L2P_CONTROL_BLOCK **curr_lcb_next_ptr; | |
73 T_L2P_CONTROL_BLOCK *current_l2p_cntrl_block; | |
74 T_L2P_CONTROL_BLOCK *this_l2p_cntrl_block = (T_L2P_CONTROL_BLOCK *)mem; | |
75 | |
76 TRACE_EVENT("L2P_Configure"); | |
77 /* | |
78 ** check the incoming paramters to ensure they are valid | |
79 */ | |
80 if (mem == (void *)0) | |
81 { | |
82 TRACE_EVENT("L2P_Configure - Mem pointer Invalid"); | |
83 return L2P_STAT_INVALID_PARAMETER; | |
84 } | |
85 | |
86 /* protocolId is a non-negative value(so <0 check not reqd) */ | |
87 if ( protocolId >= L2P_SP_MAX_NUM ) | |
88 { | |
89 TRACE_EVENT("L2P_Configure - Protocol Id Invalid"); | |
90 return L2P_STAT_INVALID_PARAMETER; | |
91 } | |
92 | |
93 if (maxMTU <= (L2P_FRAME_CONTROL_SIZE)) | |
94 { | |
95 TRACE_EVENT("L2P_Configure - Max MTU value Invalid"); | |
96 return L2P_STAT_INVALID_PARAMETER; | |
97 } | |
98 | |
99 if (Get_Tx_Buf_Cb == (L2P_Get_Tx_Buf_CB)0) | |
100 { | |
101 TRACE_EVENT("L2P_Configure - Get Tx Buffer Callback Invalid"); | |
102 return L2P_STAT_INVALID_PARAMETER; | |
103 } | |
104 | |
105 if (Get_Rx_Buf_Cb == (L2P_Get_Rx_Buf_CB)0) | |
106 { | |
107 TRACE_EVENT("L2P_Configure - Get Rx Buffer Callback Invalid"); | |
108 return L2P_STAT_INVALID_PARAMETER; | |
109 } | |
110 | |
111 if (Get_Next_Seg_Cb == (L2P_Get_Next_Seg_CB)0) | |
112 { | |
113 TRACE_EVENT("L2P_Configure - Get Next Segment Callback Invalid"); | |
114 return L2P_STAT_INVALID_PARAMETER; | |
115 } | |
116 | |
117 if (Send_Frame_Cb == (L2P_Send_Frame_CB)0) | |
118 { | |
119 TRACE_EVENT("L2P_Configure - Send Frame Callback Invalid"); | |
120 return L2P_STAT_INVALID_PARAMETER; | |
121 } | |
122 | |
123 if (Msg_Rxd_Cb == (L2P_Msg_Rxd_CB)0) | |
124 { | |
125 TRACE_EVENT("L2P_Configure - Message Received Callback Invalid"); | |
126 return L2P_STAT_INVALID_PARAMETER; | |
127 } | |
128 | |
129 /* | |
130 ** initialise the data in the passed block of data | |
131 */ | |
132 this_l2p_cntrl_block->batId = batid; | |
133 this_l2p_cntrl_block->frameId = 0; | |
134 this_l2p_cntrl_block->protocolId = protocolId; | |
135 this_l2p_cntrl_block->maxMTU = maxMTU; | |
136 this_l2p_cntrl_block->rxBuf = (char *)0; | |
137 this_l2p_cntrl_block->muxId = 0xFD; /* Any value here will be a valid client Id, but this one is unlikely ... it MUST be initialised correctly before each use */ | |
138 this_l2p_cntrl_block->cmdTagReceived = 0; | |
139 this_l2p_cntrl_block->receivedCmdTag = 0; | |
140 this_l2p_cntrl_block->dataSize = 0; | |
141 this_l2p_cntrl_block->bytesToBeRead = 0; | |
142 this_l2p_cntrl_block->dataToBeRead = (char *)0; | |
143 | |
144 this_l2p_cntrl_block->callbacks.Get_TxBuf_Cb = Get_Tx_Buf_Cb; | |
145 this_l2p_cntrl_block->callbacks.Get_RxBuf_Cb = Get_Rx_Buf_Cb; | |
146 this_l2p_cntrl_block->callbacks.Get_Next_Seg_Cb = Get_Next_Seg_Cb; | |
147 this_l2p_cntrl_block->callbacks.Send_Frame_Cb = Send_Frame_Cb; | |
148 this_l2p_cntrl_block->callbacks.Msg_Rxd_Cb = Msg_Rxd_Cb; | |
149 | |
150 this_l2p_cntrl_block->next = (void *)0; | |
151 | |
152 /* | |
153 ** Check that the batId is not already in use | |
154 */ | |
155 if (l2p_control_block_list != (T_L2P_CONTROL_BLOCK *)0) | |
156 { | |
157 /* | |
158 ** Parse the list until either the batId is found (which would be an error) | |
159 ** or the batId is larger than the one passed (ie the current batId is not in the list, and is thereofre valid) | |
160 */ | |
161 curr_lcb_next_ptr = &l2p_control_block_list; | |
162 current_l2p_cntrl_block = l2p_control_block_list; | |
163 | |
164 while ((current_l2p_cntrl_block != (T_L2P_CONTROL_BLOCK *)0) && | |
165 (current_l2p_cntrl_block->batId < batid)) | |
166 { | |
167 /* | |
168 ** Jump to the next node on the linked list, | |
169 ** keeping track of the previous node so we can add in the details later | |
170 */ | |
171 curr_lcb_next_ptr = ¤t_l2p_cntrl_block->next; | |
172 current_l2p_cntrl_block = current_l2p_cntrl_block->next; | |
173 } | |
174 | |
175 if (current_l2p_cntrl_block == (T_L2P_CONTROL_BLOCK *)0) | |
176 { | |
177 /* | |
178 ** BAT Id was not found ... and we've reached the end of the list | |
179 ** need to add the details at the end of the linked list | |
180 */ | |
181 *curr_lcb_next_ptr = this_l2p_cntrl_block; | |
182 } | |
183 else if (current_l2p_cntrl_block->batId == batid) | |
184 { | |
185 /* | |
186 ** BAT Id was found in the current list ... it is already configured ... send an error | |
187 */ | |
188 TRACE_EVENT("L2P_Configure - BAT Id Already In Use"); | |
189 return L2P_STAT_BAT_ID_ALREADY_EXISTS; | |
190 } | |
191 else | |
192 { | |
193 /* | |
194 ** BAT Id was not found ... but we haven't reached the end of the list | |
195 ** need to add the details in the middle of the linked list | |
196 */ | |
197 this_l2p_cntrl_block->next = *curr_lcb_next_ptr; | |
198 *curr_lcb_next_ptr = this_l2p_cntrl_block; | |
199 } | |
200 } | |
201 else | |
202 { | |
203 /* | |
204 ** The linked list of BAT and L2P Control blocks is empty, this is the first instance of BAT | |
205 ** to register with the L2P. Add the details as the first entry to the linked list. | |
206 */ | |
207 l2p_control_block_list = this_l2p_cntrl_block; | |
208 } | |
209 return L2P_STAT_SUCCESS; | |
210 } | |
211 | |
212 /* | |
213 +--------------------------------------------------------------------+ | |
214 | PROJECT: BAT L2P MODULE: L2P | | |
215 | STATE : code ROUTINE: L2P_Remove | | |
216 +--------------------------------------------------------------------+ | |
217 | |
218 PURPOSE : L2P_Remove will delete a BAT from L2Ps service list. The following is a list of | |
219 the parameters, and their uses: | |
220 | |
221 batId : A identifer to uniquely identify each instance of BAT using this L2P | |
222 | |
223 */ | |
224 T_L2P_STATUS L2P_Remove(U8 batid) | |
225 { | |
226 T_L2P_CONTROL_BLOCK **curr_lcb_next_ptr; | |
227 T_L2P_CONTROL_BLOCK *current_l2p_cntrl_block; | |
228 | |
229 TRACE_EVENT("L2P_Remove()"); | |
230 | |
231 if (l2p_control_block_list == (T_L2P_CONTROL_BLOCK *)0) | |
232 { | |
233 return L2P_STAT_NO_SUCH_BAT_ID; | |
234 } | |
235 | |
236 if (l2p_control_block_list->batId == batid) | |
237 { | |
238 l2p_control_block_list = l2p_control_block_list->next; | |
239 return L2P_STAT_SUCCESS; | |
240 } | |
241 | |
242 /* | |
243 ** Parse the list until either the batId is found | |
244 ** or the batId is larger than the one passed (which would be an error) | |
245 */ | |
246 curr_lcb_next_ptr = &l2p_control_block_list; | |
247 current_l2p_cntrl_block = l2p_control_block_list; | |
248 | |
249 while ((current_l2p_cntrl_block != (T_L2P_CONTROL_BLOCK *)0) && | |
250 (current_l2p_cntrl_block->batId < batid)) | |
251 { | |
252 /* | |
253 ** Jump to the next node on the linked list, | |
254 ** keeping track of the previous node so we can add in the details later | |
255 */ | |
256 curr_lcb_next_ptr = ¤t_l2p_cntrl_block->next; | |
257 current_l2p_cntrl_block = current_l2p_cntrl_block->next; | |
258 } | |
259 | |
260 if (current_l2p_cntrl_block == (T_L2P_CONTROL_BLOCK *)0) | |
261 { | |
262 /* | |
263 ** BAT Id was not found and we've reached the end of the list | |
264 */ | |
265 return L2P_STAT_NO_SUCH_BAT_ID; | |
266 } | |
267 else if (current_l2p_cntrl_block->batId == batid) | |
268 { | |
269 /* | |
270 ** BAT Id was found in the current list ... remove the control balock from the linked list | |
271 */ | |
272 *curr_lcb_next_ptr = current_l2p_cntrl_block->next; | |
273 } | |
274 else | |
275 { | |
276 /* | |
277 ** BAT Id was not found ... the current batid must be greater tahn the one passed | |
278 */ | |
279 return L2P_STAT_NO_SUCH_BAT_ID; | |
280 } | |
281 | |
282 return L2P_STAT_SUCCESS; | |
283 } | |
284 | |
285 /* | |
286 +--------------------------------------------------------------------+ | |
287 | PROJECT: BAT L2P MODULE: L2P | | |
288 | STATE : code ROUTINE: L2P_Send | | |
289 +--------------------------------------------------------------------+ | |
290 | |
291 PURPOSE : L2P_Send will receive an AT Command Tag and its data from the L2P User, and depending on the | |
292 MTU size of the communications link being used, split the data into multiple frames and send those | |
293 Frames across the link. The following is a list of the parameters, and their uses: | |
294 | |
295 batId : A identifer to uniquely identify each instance of BAT using this L2P | |
296 muxId : A client identifier to identify which clinet of the BAT instance either sent, or is to receive, the data. | |
297 dataTag : This is a BAT Command or Response TAG to identify which AT command is being sent. This TAG | |
298 will be sent to the peer along with the data. | |
299 dataBuf : pointer to the payload data to send | |
300 dataLen : length of the data in the 'dataBuf' | |
301 errVal : If there is a driver error, L2P_Send will return L2P_STAT_UNKNOWN_ERROR and will provide | |
302 the driver error code in errVal. This is because the number may be positive, and all errors in | |
303 T_L2P_STATUS are negative. | |
304 | |
305 */ | |
306 T_L2P_STATUS L2P_Send(U8 batId, U8 muxId, U32 dataTag, void *dataBuf, U16 dataLen, int *errVal) | |
307 { | |
308 T_L2P_CONTROL_BLOCK *curr_l2p_cntrl_block; | |
309 T_L2P_FRAME_CONTROL_BYTES frameCntrlBytes; | |
310 U16 bytesRemainingToBeSent; | |
311 U16 frameCntrlBytesToBeWritten; | |
312 U16 bytesToBeWritten = 0; | |
313 U16 bytesWritten; | |
314 U16 frameSizeReq; | |
315 U16 totalBufSize; | |
316 U16 segSize; | |
317 U16 remainingSegSize; | |
318 U16 totalSegSize; | |
319 char *curTxSeg; | |
320 char *dataToBeWritten = NULL; | |
321 char *frameCntrlDataToBeWritten; | |
322 void *seg_hdr; | |
323 char *txWritePtr; | |
324 char cmdTagWritten = 0; | |
325 int drvRetVal = 0; | |
326 | |
327 TRACE_EVENT("L2P_Send()"); | |
328 | |
329 /* | |
330 ** Check that the Bat Id is valid | |
331 */ | |
332 | |
333 curr_l2p_cntrl_block = l2p_control_block_list; | |
334 | |
335 while ((curr_l2p_cntrl_block != (T_L2P_CONTROL_BLOCK *)0) && | |
336 (curr_l2p_cntrl_block->batId != batId)) | |
337 { | |
338 curr_l2p_cntrl_block = curr_l2p_cntrl_block->next; | |
339 } | |
340 | |
341 if (curr_l2p_cntrl_block == (T_L2P_CONTROL_BLOCK *)0) | |
342 { | |
343 return L2P_STAT_NO_SUCH_BAT_ID; | |
344 } | |
345 | |
346 /* | |
347 ** Check the rest of the parameters | |
348 */ | |
349 if ((dataBuf == (void *)0) && (dataLen != 0)) | |
350 { | |
351 TRACE_EVENT("L2P_Send() - Invalid Data Buffer Pointer"); | |
352 return L2P_STAT_INVALID_PARAMETER; | |
353 } | |
354 | |
355 if (errVal == (int *)0) | |
356 { | |
357 TRACE_EVENT("L2P_Send() - Invalid Error Return Pointer"); | |
358 return L2P_STAT_INVALID_PARAMETER; | |
359 } | |
360 | |
361 /* | |
362 ** The format of an L2 frame for BAT will be as follows : | |
363 ** | |
364 ** For the first frame | |
365 ** ---------------------------------------------------------------- | |
366 ** | L2 Control Bytes | BAT Cmd TAG | BAT Command Data | | |
367 ** | (n Bytes) | 4 Bytes | (Remaining Bytes) | | |
368 ** ---------------------------------------------------------------- | |
369 ** | |
370 ** For any subsequent frames | |
371 ** ---------------------------------------------------------------- | |
372 ** | L2 Control Bytes | BAT Command Data | | |
373 ** | (n Bytes) | (Remaining Bytes) | | |
374 ** ---------------------------------------------------------------- | |
375 */ | |
376 | |
377 bytesRemainingToBeSent = dataLen + sizeof(int); | |
378 | |
379 /* | |
380 ** Fill in the Frame Control Bytes | |
381 */ | |
382 frameCntrlBytes.dataLen = dataLen; | |
383 frameCntrlBytes.frame_id = 0; /* Each new packet will start with a frame Id of 0 */ | |
384 frameCntrlBytes.frame_type = L2P_FT_UNKNOWN_FRAME_TYPE; | |
385 frameCntrlBytes.mux_id = muxId; | |
386 frameCntrlBytes.protocol_id = (U8)curr_l2p_cntrl_block->protocolId; | |
387 | |
388 while (bytesRemainingToBeSent >0) | |
389 { | |
390 /* | |
391 ** Calculate the required size of Transmit buffer and how many frames will be required | |
392 */ | |
393 if ((bytesRemainingToBeSent + L2P_FRAME_CONTROL_SIZE) > curr_l2p_cntrl_block->maxMTU) | |
394 { | |
395 /* | |
396 ** Data will not fit in a single frame, so will need to be fragmented and reassembled | |
397 */ | |
398 frameSizeReq = curr_l2p_cntrl_block->maxMTU; | |
399 } | |
400 else | |
401 { | |
402 /* | |
403 ** Data will fit in a single frame, so will be sent complete | |
404 */ | |
405 frameSizeReq = bytesRemainingToBeSent + L2P_FRAME_CONTROL_SIZE; | |
406 } | |
407 | |
408 /* | |
409 ** Request the Transmit frame from the buffer | |
410 */ | |
411 curTxSeg = (char *)curr_l2p_cntrl_block->callbacks.Get_TxBuf_Cb(batId, frameSizeReq, | |
412 &seg_hdr, &totalBufSize, &segSize); | |
413 | |
414 if (curTxSeg == (char *)0) | |
415 { | |
416 return L2P_STAT_UNABLE_TO_GET_BUFFER; | |
417 } | |
418 | |
419 totalSegSize = remainingSegSize = segSize; | |
420 | |
421 /* | |
422 ** Now we know the size of buffer given so we can tell whether the entire message will fit in a single frame | |
423 */ | |
424 if (totalBufSize >= (bytesRemainingToBeSent + L2P_FRAME_CONTROL_SIZE)) | |
425 { | |
426 if (frameCntrlBytes.frame_type == L2P_FT_UNKNOWN_FRAME_TYPE) | |
427 frameCntrlBytes.frame_type = (U8)L2P_FT_COMPLETE_FRAME; | |
428 else | |
429 frameCntrlBytes.frame_type = (U8)L2P_FT_END_FRAME; | |
430 | |
431 frameCntrlBytes.frameLen = bytesRemainingToBeSent + L2P_FRAME_CONTROL_SIZE; | |
432 } | |
433 else | |
434 { | |
435 if (frameCntrlBytes.frame_type == L2P_FT_UNKNOWN_FRAME_TYPE) | |
436 frameCntrlBytes.frame_type = (U8)L2P_FT_START_FRAME; | |
437 else | |
438 frameCntrlBytes.frame_type = L2P_FT_CONTINUATION_FRAME; | |
439 | |
440 frameCntrlBytes.frameLen = totalBufSize; | |
441 } | |
442 | |
443 txWritePtr = curTxSeg; | |
444 | |
445 /* | |
446 ** We can assume that the buffer will be at least big enough for the L2 Frame Header plus some data | |
447 ** | |
448 ** Write the L2 Frames Control Bytes | |
449 */ | |
450 frameCntrlBytesToBeWritten = L2P_FRAME_CONTROL_SIZE; | |
451 frameCntrlDataToBeWritten = (char *)&frameCntrlBytes; | |
452 | |
453 while (frameCntrlBytesToBeWritten > 0) | |
454 { | |
455 txWritePtr = L2P_write_data_to_seg(txWritePtr, frameCntrlDataToBeWritten, frameCntrlBytesToBeWritten, | |
456 remainingSegSize, &bytesWritten); | |
457 frameCntrlBytesToBeWritten -= bytesWritten; | |
458 remainingSegSize -= bytesWritten; | |
459 frameCntrlDataToBeWritten += bytesWritten; | |
460 | |
461 /* | |
462 ** Frame Control Bytes are NOT included in the bytesRemainingToBeSent count so do not decrease the size! | |
463 */ | |
464 | |
465 if (txWritePtr == (char *)0) | |
466 { | |
467 /* | |
468 ** We have reached the end of the current Segment, so get the next. | |
469 */ | |
470 curTxSeg = curr_l2p_cntrl_block->callbacks.Get_Next_Seg_Cb(batId, seg_hdr, &seg_hdr, &segSize); | |
471 txWritePtr = curTxSeg; | |
472 totalSegSize +=segSize; | |
473 remainingSegSize = segSize; | |
474 } | |
475 } | |
476 | |
477 /* | |
478 ** if necessary, write the cmd Tag into the Buffer | |
479 */ | |
480 if ((frameCntrlBytes.frame_type == L2P_FT_COMPLETE_FRAME) || | |
481 (frameCntrlBytes.frame_type == L2P_FT_START_FRAME)) | |
482 { | |
483 bytesToBeWritten = sizeof(dataTag); | |
484 dataToBeWritten = (char *)&dataTag; | |
485 | |
486 while ((txWritePtr != (char *)0) && /* There is still space in the buffer segement */ | |
487 (!cmdTagWritten)) /* The command Tag has not completed */ | |
488 { | |
489 txWritePtr = L2P_write_data_to_seg(txWritePtr, dataToBeWritten, bytesToBeWritten, | |
490 remainingSegSize, &bytesWritten); | |
491 bytesToBeWritten -= bytesWritten; | |
492 remainingSegSize -= bytesWritten; | |
493 dataToBeWritten += bytesWritten; | |
494 | |
495 /* | |
496 ** Decrement the bytesRemainingToBeSent counter | |
497 */ | |
498 bytesRemainingToBeSent -= bytesWritten; | |
499 | |
500 if ((txWritePtr == (char *)0) && (totalSegSize < totalBufSize)) | |
501 { | |
502 /* | |
503 ** We have reached the end of the current Segment, so get the next. | |
504 */ | |
505 curTxSeg = curr_l2p_cntrl_block->callbacks.Get_Next_Seg_Cb(batId, seg_hdr, &seg_hdr, &segSize); | |
506 txWritePtr = curTxSeg; | |
507 totalSegSize +=segSize; | |
508 remainingSegSize = segSize; | |
509 } | |
510 | |
511 /* | |
512 ** If the Command Tag has been completed set a flag | |
513 */ | |
514 if (bytesToBeWritten == (U16)0) | |
515 { | |
516 cmdTagWritten = 1; | |
517 dataToBeWritten = (char *)dataBuf; /* Next Write the AT Command Data */ | |
518 bytesToBeWritten = dataLen; | |
519 } | |
520 } | |
521 } | |
522 | |
523 if (dataToBeWritten EQ NULL) | |
524 { | |
525 return L2P_STAT_INVALID_PARAMETER; | |
526 } | |
527 /* | |
528 ** if txWritePtr is NULL at this point it is because a buffer has been completed ... drop out and perform | |
529 ** the next loop of the while statement to create the next L2 Frame in an new buffer. | |
530 */ | |
531 while ((bytesToBeWritten > 0) && /* There is still data to write */ | |
532 (txWritePtr != (char *)0)) /* There is still space in the buffer segement */ | |
533 { | |
534 txWritePtr = L2P_write_data_to_seg(txWritePtr, dataToBeWritten, bytesToBeWritten, | |
535 remainingSegSize, &bytesWritten); | |
536 bytesToBeWritten -= bytesWritten; | |
537 remainingSegSize -= bytesWritten; | |
538 dataToBeWritten += bytesWritten; | |
539 | |
540 /* | |
541 ** Decrement the bytesRemainingToBeSent counter | |
542 */ | |
543 bytesRemainingToBeSent -= bytesWritten; | |
544 | |
545 if ((txWritePtr == (char *)0) && (totalSegSize < totalBufSize)) | |
546 { | |
547 /* | |
548 ** We have reached the end of the current Segment, so get the next. | |
549 */ | |
550 curTxSeg = curr_l2p_cntrl_block->callbacks.Get_Next_Seg_Cb(batId, seg_hdr, &seg_hdr, &segSize); | |
551 txWritePtr = curTxSeg; | |
552 totalSegSize +=segSize; | |
553 remainingSegSize = segSize; | |
554 } | |
555 | |
556 if ((bytesToBeWritten == (U16)0) && /* We've finished writing the data */ | |
557 (!cmdTagWritten)) /* but that data was the Command Tag */ | |
558 { | |
559 /* | |
560 ** now we have to write the AT Command Data | |
561 */ | |
562 cmdTagWritten = 1; | |
563 dataToBeWritten = (char *)dataBuf; | |
564 bytesToBeWritten = dataLen; | |
565 } | |
566 } | |
567 | |
568 /* | |
569 ** We have built a complete L2 Frame ... that it may or may not include the complete packet it isn't important | |
570 ** but we need to send it ... | |
571 */ | |
572 drvRetVal = curr_l2p_cntrl_block->callbacks.Send_Frame_Cb(batId); | |
573 frameCntrlBytes.frame_id ++; | |
574 | |
575 if (drvRetVal != 0) | |
576 { | |
577 /* | |
578 ** There was an error sending the frame | |
579 */ | |
580 *errVal = drvRetVal; | |
581 return L2P_STAT_UNKNOWN_ERROR; | |
582 } | |
583 } | |
584 | |
585 return L2P_STAT_SUCCESS; | |
586 } | |
587 | |
588 /* | |
589 +--------------------------------------------------------------------+ | |
590 | PROJECT: BAT L2P MODULE: L2P | | |
591 | STATE : code ROUTINE: L2P_Receive | | |
592 +--------------------------------------------------------------------+ | |
593 | |
594 PURPOSE : L2P_Receive is called on receipt of data by the BAT, BAT Command Tag is extracted and the rest | |
595 of the L2 frames are combined into a buffer and passed, complete, to the BAT. The following is a | |
596 list of the parameters, and their uses: | |
597 | |
598 batId : A identifer to uniquely identify each instance of BAT using this L2P | |
599 inBuf : pointer to the received buffer | |
600 dataLen : length of the data in the 'inBuf' | |
601 | |
602 */ | |
603 T_L2P_STATUS L2P_Receive(U8 batId, void *dataBuf, void *seg_hdr_ptr, U16 totalsize, U16 segSize) | |
604 { | |
605 T_L2P_CONTROL_BLOCK *curr_l2p_cntrl_block; | |
606 T_L2P_FRAME_CONTROL_BYTES frameCntrlBytes; | |
607 U16 frameCntrlBytesToBeRead; | |
608 U16 bytesRead; | |
609 U16 remainingSegSize; | |
610 U16 totalSegSize; | |
611 char *curRxSeg; | |
612 char *rxReadPtr; | |
613 char *frameCntrlDataToBeRead; | |
614 | |
615 TRACE_EVENT("L2P_Receive()"); | |
616 | |
617 /* | |
618 ** Check that the Bat Id is valid | |
619 */ | |
620 curr_l2p_cntrl_block = l2p_control_block_list; | |
621 | |
622 while ((curr_l2p_cntrl_block != (T_L2P_CONTROL_BLOCK *)0) && | |
623 (curr_l2p_cntrl_block->batId != batId)) | |
624 { | |
625 curr_l2p_cntrl_block = curr_l2p_cntrl_block->next; | |
626 } | |
627 | |
628 if (curr_l2p_cntrl_block == (T_L2P_CONTROL_BLOCK *)0) | |
629 { | |
630 return L2P_STAT_NO_SUCH_BAT_ID; | |
631 } | |
632 | |
633 /* | |
634 ** Check the rest of the parameters | |
635 */ | |
636 if (dataBuf == (void *)0) | |
637 { | |
638 TRACE_EVENT("L2P_Receive() - Invalid Data Buffer Pointer"); | |
639 return L2P_STAT_INVALID_PARAMETER; | |
640 } | |
641 | |
642 /* | |
643 ** Don't check the Segment Header Pointer, it is User Data and down to the | |
644 ** BAT Lib or BAT Module which pointer they pass : | |
645 ** pointer to current segment - never NULL | |
646 ** pointer to the next segment - may be NULL | |
647 ** | |
648 if (seg_hdr_ptr == (void *)0) | |
649 { | |
650 TRACE_EVENT("L2P_Receive() - Invalid Segment Header Pointer"); | |
651 return L2P_STAT_INVALID_PARAMETER; | |
652 } | |
653 */ | |
654 | |
655 if (totalsize <= (U16)L2P_FRAME_CONTROL_SIZE) | |
656 { | |
657 TRACE_EVENT("L2P_Receive() - Invalid Buffer Length"); | |
658 return L2P_STAT_INVALID_PARAMETER; | |
659 } | |
660 | |
661 if (segSize == (U16)0) | |
662 { | |
663 TRACE_EVENT("L2P_Receive() - Invalid Segment Size"); | |
664 return L2P_STAT_INVALID_PARAMETER; | |
665 } | |
666 | |
667 /* | |
668 ** The format of an L2 frame for BAT will be as follows : | |
669 ** | |
670 ** For the first frame | |
671 ** ---------------------------------------------------------------- | |
672 ** | L2 Control Bytes | BAT Cmd TAG | BAT Command Data | | |
673 ** | (n Bytes) | 4 Bytes | (Remaining Bytes) | | |
674 ** ---------------------------------------------------------------- | |
675 ** | |
676 ** For any subsequent frames | |
677 ** ---------------------------------------------------------------- | |
678 ** | L2 Control Bytes | BAT Command Data | | |
679 ** | (n Bytes) | (Remaining Bytes) | | |
680 ** ---------------------------------------------------------------- | |
681 */ | |
682 | |
683 /* | |
684 ** Read the L2 Frames Control Bytes | |
685 */ | |
686 curRxSeg = (char *)dataBuf; | |
687 frameCntrlBytesToBeRead = L2P_FRAME_CONTROL_SIZE; | |
688 frameCntrlDataToBeRead = (char *)&frameCntrlBytes; | |
689 totalSegSize = remainingSegSize = segSize; | |
690 rxReadPtr = dataBuf; | |
691 | |
692 while (frameCntrlBytesToBeRead > 0) | |
693 { | |
694 rxReadPtr = L2P_read_data_from_seg(rxReadPtr, frameCntrlDataToBeRead, frameCntrlBytesToBeRead, | |
695 remainingSegSize, &bytesRead); | |
696 frameCntrlBytesToBeRead-= bytesRead; | |
697 remainingSegSize -= bytesRead; | |
698 frameCntrlDataToBeRead += bytesRead; | |
699 | |
700 if (rxReadPtr == (char *)0) | |
701 { | |
702 /* | |
703 ** We have reached the end of the current Segment, so get the next. | |
704 */ | |
705 curRxSeg = curr_l2p_cntrl_block->callbacks.Get_Next_Seg_Cb(batId, seg_hdr_ptr, &seg_hdr_ptr, | |
706 &segSize); | |
707 rxReadPtr = curRxSeg; | |
708 totalSegSize +=segSize; | |
709 remainingSegSize = segSize; | |
710 } | |
711 } | |
712 | |
713 /* | |
714 ** Now we have the frame Control Bytes ... so we need to determine whether we need a | |
715 ** new Rx Buffer from the user | |
716 */ | |
717 | |
718 /* | |
719 ** If the frame Id is zero, this is a new message | |
720 */ | |
721 if ((frameCntrlBytes.frame_id == (U8)0) && | |
722 ((frameCntrlBytes.frame_type == L2P_FT_START_FRAME) || | |
723 (frameCntrlBytes.frame_type == L2P_FT_COMPLETE_FRAME))) | |
724 { | |
725 /* | |
726 ** Do we already have an Rx Buffer | |
727 */ | |
728 if (curr_l2p_cntrl_block->rxBuf == (char *)0) | |
729 { | |
730 /* | |
731 ** No -- Use the callback function to get an Rx Buffer | |
732 */ | |
733 curr_l2p_cntrl_block->rxBuf = (char *)curr_l2p_cntrl_block->callbacks.Get_RxBuf_Cb(batId); | |
734 | |
735 if (curr_l2p_cntrl_block->rxBuf == (char *)0) | |
736 { | |
737 /* | |
738 ** Failed to allocate a Rx Buffer | |
739 */ | |
740 return L2P_STAT_UNABLE_TO_GET_BUFFER; | |
741 } | |
742 } | |
743 /* comment out the 'else block' because there is no functionality to go inside it | |
744 else | |
745 { | |
746 ** Yes -- We will overwrite it automatically ... the previous message was lost! | |
747 } | |
748 */ | |
749 | |
750 /* | |
751 ** Pull the necessary data from the Frame Control Bytes | |
752 */ | |
753 curr_l2p_cntrl_block->dataSize = frameCntrlBytes.dataLen; /* length of the Command Data (excl the CmdTag) */ | |
754 curr_l2p_cntrl_block->muxId = frameCntrlBytes.mux_id; /* Sender or receipient of the message */ | |
755 curr_l2p_cntrl_block->cmdTagReceived = 0; | |
756 } | |
757 | |
758 /* | |
759 ** if necessary, read the cmd Tag from the Buffer | |
760 */ | |
761 if ((frameCntrlBytes.frame_type == L2P_FT_COMPLETE_FRAME) || | |
762 (frameCntrlBytes.frame_type == L2P_FT_START_FRAME)) | |
763 { | |
764 curr_l2p_cntrl_block->bytesToBeRead = sizeof(curr_l2p_cntrl_block->receivedCmdTag); | |
765 curr_l2p_cntrl_block->dataToBeRead = (char *)&curr_l2p_cntrl_block->receivedCmdTag; | |
766 | |
767 while ((rxReadPtr != (char *)0) && /* There is still data in the buffer segement */ | |
768 (!curr_l2p_cntrl_block->cmdTagReceived)) /* The command Tag has not completed */ | |
769 { | |
770 rxReadPtr = L2P_read_data_from_seg(rxReadPtr, curr_l2p_cntrl_block->dataToBeRead, | |
771 curr_l2p_cntrl_block->bytesToBeRead, | |
772 remainingSegSize, &bytesRead); | |
773 curr_l2p_cntrl_block->bytesToBeRead -= bytesRead; | |
774 remainingSegSize -= bytesRead; | |
775 curr_l2p_cntrl_block->dataToBeRead += bytesRead; | |
776 | |
777 if ((rxReadPtr == (char *)0) && (totalSegSize < totalsize) && (curr_l2p_cntrl_block->bytesToBeRead != (U16)0)) | |
778 { | |
779 /* | |
780 ** We have reached the end of the current Segment, so get the next. | |
781 */ | |
782 curRxSeg = curr_l2p_cntrl_block->callbacks.Get_Next_Seg_Cb(batId, seg_hdr_ptr, &seg_hdr_ptr, &segSize); | |
783 rxReadPtr = curRxSeg; | |
784 totalSegSize +=segSize; | |
785 remainingSegSize = segSize; | |
786 } | |
787 | |
788 /* | |
789 ** If the Command Tag has been completed set a flag | |
790 */ | |
791 if (curr_l2p_cntrl_block->bytesToBeRead == (U16)0) | |
792 { | |
793 curr_l2p_cntrl_block->cmdTagReceived = 1; | |
794 curr_l2p_cntrl_block->dataToBeRead = (char *)curr_l2p_cntrl_block->rxBuf; /* Next Write the AT Command Data */ | |
795 curr_l2p_cntrl_block->bytesToBeRead = curr_l2p_cntrl_block->dataSize; | |
796 } | |
797 } | |
798 } | |
799 | |
800 /* | |
801 ** if txWritePtr is NULL at this point it is because a buffer has been completed ... drop out and | |
802 ** wait for the next buffer which will contain the next frame. | |
803 */ | |
804 while ((curr_l2p_cntrl_block->bytesToBeRead > 0) && /* There is still data to read */ | |
805 (rxReadPtr != (char *)0)) /* There is still data in the buffer segement */ | |
806 { | |
807 rxReadPtr = L2P_read_data_from_seg(rxReadPtr, curr_l2p_cntrl_block->dataToBeRead, | |
808 curr_l2p_cntrl_block->bytesToBeRead, | |
809 remainingSegSize, &bytesRead); | |
810 curr_l2p_cntrl_block->bytesToBeRead -= bytesRead; | |
811 remainingSegSize -= bytesRead; | |
812 curr_l2p_cntrl_block->dataToBeRead += bytesRead; | |
813 | |
814 if ((rxReadPtr == (char *)0) && (totalSegSize < totalsize) && (curr_l2p_cntrl_block->bytesToBeRead != (U16)0)) | |
815 | |
816 { | |
817 /* | |
818 ** We have reached the end of the current Segment, so get the next. | |
819 */ | |
820 curRxSeg = curr_l2p_cntrl_block->callbacks.Get_Next_Seg_Cb(batId, seg_hdr_ptr, &seg_hdr_ptr, &segSize); | |
821 rxReadPtr = curRxSeg; | |
822 totalSegSize +=segSize; | |
823 remainingSegSize = segSize; | |
824 } | |
825 | |
826 if ((curr_l2p_cntrl_block->bytesToBeRead == (U16)0) && /* We've finished writing the data */ | |
827 (!curr_l2p_cntrl_block->cmdTagReceived)) /* but that data was the Command Tag */ | |
828 { | |
829 /* | |
830 ** now we have to write the AT Command Data | |
831 */ | |
832 curr_l2p_cntrl_block->cmdTagReceived = 1; | |
833 curr_l2p_cntrl_block->dataToBeRead = (char *)curr_l2p_cntrl_block->rxBuf; /* Next Write the AT Command Data */ | |
834 curr_l2p_cntrl_block->bytesToBeRead = curr_l2p_cntrl_block->dataSize; | |
835 } | |
836 } | |
837 | |
838 if (curr_l2p_cntrl_block->bytesToBeRead == (U16)0) | |
839 { | |
840 /* | |
841 ** We have built a complete message ... send it to the user .. | |
842 */ | |
843 curr_l2p_cntrl_block->callbacks.Msg_Rxd_Cb(batId, curr_l2p_cntrl_block->muxId, | |
844 curr_l2p_cntrl_block->receivedCmdTag, | |
845 curr_l2p_cntrl_block->rxBuf, | |
846 curr_l2p_cntrl_block->dataSize); | |
847 | |
848 /* | |
849 ** reset the Rx values | |
850 */ | |
851 curr_l2p_cntrl_block->rxBuf = (char *)0; | |
852 curr_l2p_cntrl_block->muxId = 0; | |
853 curr_l2p_cntrl_block->cmdTagReceived = 0; | |
854 curr_l2p_cntrl_block->receivedCmdTag = 0; | |
855 curr_l2p_cntrl_block->dataSize = 0; | |
856 curr_l2p_cntrl_block->dataToBeRead = (char *)0; | |
857 } | |
858 | |
859 return L2P_STAT_SUCCESS; | |
860 } | |
861 | |
862 | |
863 /* | |
864 +--------------------------------------------------------------------+ | |
865 | PROJECT: BAT L2P MODULE: L2P | | |
866 | STATE : code ROUTINE: L2P_write_data_to_seg | | |
867 +--------------------------------------------------------------------+ | |
868 | |
869 PURPOSE : L2P_write_data_to_seg is a local function to write a piece of data into a buffer segment. The buffer | |
870 segment may, or may not be big enough to hold the entire piece of data. If the segment is full when | |
871 the data has been written then the function will return a NULL pointer, otherwise it will return a pointer | |
872 to the next location to receive data. | |
873 The following is a list of the parameters, and their uses: | |
874 | |
875 writePtr : pointer to the start location to write the data to | |
876 dataPtr : pointer to the data to be written | |
877 dataSize : length of the data in dataPtr | |
878 remain_seg_size : The size of remaining space in the buffer segment | |
879 bytesWritten : output parameter in order to return the actual number of bytes written into the segment. | |
880 | |
881 */ | |
882 static char *L2P_write_data_to_seg(char *writePtr, char *dataPtr, U16 dataSize, U16 remain_seg_size, | |
883 U16 *bytesWritten) | |
884 { | |
885 char *retPtr; | |
886 | |
887 if (remain_seg_size <= dataSize) | |
888 { | |
889 retPtr = (char *)0; | |
890 *bytesWritten = remain_seg_size; | |
891 } | |
892 else | |
893 { | |
894 retPtr = writePtr + dataSize; | |
895 *bytesWritten = dataSize; | |
896 } | |
897 | |
898 memcpy(writePtr, dataPtr, *bytesWritten); | |
899 | |
900 return retPtr; | |
901 } | |
902 | |
903 | |
904 /* | |
905 +--------------------------------------------------------------------+ | |
906 | PROJECT: BAT L2P MODULE: L2P | | |
907 | STATE : code ROUTINE: L2P_write_data_to_seg | | |
908 +--------------------------------------------------------------------+ | |
909 | |
910 PURPOSE : L2P_read_data_from_seg is a local function to read a piece of data from a buffer segment, and write | |
911 it into a data structure (pointed to by writePtr). The buffer segment may, or may not be big enough to | |
912 hold the entire piece of data. If the end of the segment is reached when the data has been read then | |
913 the function will return a NULL pointer, otherwise it will return a pointer to the next location to read data | |
914 from. The following is a list of the parameters, and their uses: | |
915 | |
916 readPtr : pointer to the position in the segment to read from | |
917 writePtr : pointer to the start location to write the data to | |
918 dataSize : length of the data to be read from the segment | |
919 remain_seg_size : The size of remaining space in the buffer segment | |
920 bytesWritten : output parameter in order to return the actual number of bytes written. | |
921 | |
922 */ | |
923 static char *L2P_read_data_from_seg(char *readPtr, char *writePtr, U16 dataSize, U16 remain_seg_size, | |
924 U16 *bytesWritten) | |
925 { | |
926 char *retPtr; | |
927 | |
928 if (remain_seg_size <= dataSize) | |
929 { | |
930 retPtr = (char *)0; | |
931 *bytesWritten = remain_seg_size; | |
932 } | |
933 else | |
934 { | |
935 retPtr = readPtr + dataSize; | |
936 *bytesWritten = dataSize; | |
937 } | |
938 | |
939 memcpy(writePtr, readPtr, *bytesWritten); | |
940 | |
941 return retPtr; | |
942 } | |
943 |