comparison gsm-fw/g23m-aci/l2p/l2p.c @ 775:eedbf248bac0

gsm-fw/g23m-aci subtree: initial import from LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 12 Oct 2014 01:45:14 +0000
parents
children
comparison
equal deleted inserted replaced
774:40a721fd9854 775:eedbf248bac0
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 = &current_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 = &current_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