• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2000-2005  CSR Ltd.
6  *
7  *
8  *  Permission is hereby granted, free of charge, to any person obtaining
9  *  a copy of this software and associated documentation files (the
10  *  "Software"), to deal in the Software without restriction, including
11  *  without limitation the rights to use, copy, modify, merge, publish,
12  *  distribute, sublicense, and/or sell copies of the Software, and to
13  *  permit persons to whom the Software is furnished to do so, subject to
14  *  the following conditions:
15  *
16  *  The above copyright notice and this permission notice shall be included
17  *  in all copies or substantial portions of the Software.
18  *
19  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22  *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23  *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24  *  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  *  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  *
27  */
28 
29 #ifdef HAVE_CONFIG_H
30 #include <config.h>
31 #endif
32 
33 /*****************************************************************************/
34 /*****************************************************************************/
35 /*****************************************************************************/
36 /**                                                                         **/
37 /** ubcsp,c                                                                 **/
38 /**                                                                         **/
39 /** MicroBCSP - a very low cost implementation of the BCSP protocol         **/
40 /**                                                                         **/
41 /*****************************************************************************/
42 
43 #include "ubcsp.h"
44 
45 #if SHOW_PACKET_ERRORS || SHOW_LE_STATES
46 #include <stdio.h>
47 #include <windows.h>
48 #endif
49 
50 static uint16 ubcsp_calc_crc (uint8 ch, uint16 crc);
51 static uint16 ubcsp_crc_reverse (uint16);
52 
53 /*****************************************************************************/
54 /**                                                                         **/
55 /** Constant Data - ROM                                                     **/
56 /**                                                                         **/
57 /*****************************************************************************/
58 
59 /* This is the storage for the link establishment messages */
60 
61 static const uint8 ubcsp_le_buffer[4][4] =
62 	{
63 		{ 0xDA, 0xDC, 0xED, 0xED },
64 		{ 0xAC, 0xAF, 0xEF, 0xEE },
65 		{ 0xAD, 0xEF, 0xAC, 0xED },
66 		{ 0xDE, 0xAD, 0xD0, 0xD0 },
67 	};
68 
69 /* These are the link establishment headers */
70 /* The two version are for the CRC and non-CRC varients */
71 
72 #if UBCSP_CRC
73 static const uint8 ubcsp_send_le_header[4] =
74 	{
75 		0x40, 0x41, 0x00, 0x7E
76 	};
77 #else
78 static const uint8 ubcsp_send_le_header[4] =
79 	{
80 		0x00, 0x41, 0x00, 0xBE
81 	};
82 #endif
83 
84 /*****************************************************************************/
85 /**                                                                         **/
86 /** Static Data - RAM                                                       **/
87 /**                                                                         **/
88 /*****************************************************************************/
89 
90 /* This is the storage for all state data for ubcsp */
91 
92 static struct ubcsp_configuration ubcsp_config;
93 
94 /* This is the ACK packet header - this will be overwritten when
95    we create an ack packet */
96 
97 static uint8 ubcsp_send_ack_header[4] =
98 	{
99 		0x00, 0x00, 0x00, 0x00
100 	};
101 
102 /* This is the deslip lookup table */
103 
104 static const uint8 ubcsp_deslip[2] =
105 	{
106 		SLIP_FRAME, SLIP_ESCAPE,
107 	};
108 
109 /* This is a state machine table for link establishment */
110 
111 static uint8 next_le_packet[16] =
112 	{
113 		ubcsp_le_sync,			// uninit
114 		ubcsp_le_conf,			// init
115 		ubcsp_le_none,			// active
116 		ubcsp_le_none,
117 		ubcsp_le_sync_resp,		// sync_resp
118 		ubcsp_le_sync_resp,
119 		ubcsp_le_none,
120 		ubcsp_le_none,
121 		ubcsp_le_none,			// conf_resp
122 		ubcsp_le_conf_resp,
123 		ubcsp_le_conf_resp,
124 		ubcsp_le_none,
125 	};
126 
127 /* This is the storage required for building send and crc data */
128 
129 static uint8 ubcsp_send_header[4];
130 static uint8 ubcsp_send_crc[2];
131 
132 /* This is where the receive header is stored before the payload arrives */
133 
134 static uint8 ubcsp_receive_header[4];
135 
136 /*****************************************************************************/
137 /**                                                                         **/
138 /** Code - ROM or RAM                                                       **/
139 /**                                                                         **/
140 /*****************************************************************************/
141 
142 /*****************************************************************************/
143 /**                                                                         **/
144 /** ubcsp_initialize                                                        **/
145 /**                                                                         **/
146 /** This initializes the state of the ubcsp engine to a known values        **/
147 /**                                                                         **/
148 /*****************************************************************************/
149 
ubcsp_initialize(void)150 void ubcsp_initialize (void)
151 {
152 	ubcsp_config.ack_number = 0;
153 	ubcsp_config.sequence_number = 0;
154 	ubcsp_config.send_ptr = 0;
155 	ubcsp_config.send_size = 0;
156 	ubcsp_config.receive_index = -4;
157 
158 	ubcsp_config.delay = 0;
159 
160 #if SHOW_LE_STATES
161 	printf ("Hello Link Uninitialized\n");
162 #endif
163 
164 	ubcsp_config.link_establishment_state = ubcsp_le_uninitialized;
165 	ubcsp_config.link_establishment_packet = ubcsp_le_sync;
166 }
167 
168 /*****************************************************************************/
169 /**                                                                         **/
170 /** ubcsp_send_packet                                                       **/
171 /**                                                                         **/
172 /** This sends a packet structure for sending to the ubcsp engine           **/
173 /** This can only be called when the activity indication from ubcsp_poll    **/
174 /** indicates that a packet can be sent with UBCSP_PACKET_SENT              **/
175 /**                                                                         **/
176 /*****************************************************************************/
177 
ubcsp_send_packet(struct ubcsp_packet * send_packet)178 void ubcsp_send_packet (struct ubcsp_packet *send_packet)
179 {
180 	/* Initialize the send data to the packet we want to send */
181 
182 	ubcsp_config.send_packet = send_packet;
183 
184 	/* we cannot send the packet at the moment
185 	   when we can at the moment, just set things to 0 */
186 
187 	ubcsp_config.send_size = 0;
188 	ubcsp_config.send_ptr = 0;
189 }
190 
191 /*****************************************************************************/
192 /**                                                                         **/
193 /** ubcsp_receive_packet                                                    **/
194 /**                                                                         **/
195 /** This sends a packet structure for receiving to the ubcsp engine         **/
196 /** This can only be called when the activity indication from ubcsp_poll    **/
197 /** indicates that a packet can be sent with UBCSP_PACKET_RECEIVED          **/
198 /**                                                                         **/
199 /*****************************************************************************/
200 
ubcsp_receive_packet(struct ubcsp_packet * receive_packet)201 void ubcsp_receive_packet (struct ubcsp_packet *receive_packet)
202 {
203 	/* Initialize the receive data to the packet we want to receive */
204 
205 	ubcsp_config.receive_packet = receive_packet;
206 
207 	/* setup to receive the header first */
208 
209 	ubcsp_config.receive_index = -4;
210 }
211 
212 /*****************************************************************************/
213 /**                                                                         **/
214 /** ubcsp_calc_crc                                                          **/
215 /**                                                                         **/
216 /** Takes the next 8 bit value ch, and updates the crc with this value      **/
217 /**                                                                         **/
218 /*****************************************************************************/
219 
220 
221 #ifdef UBCSP_CRC
222 
ubcsp_calc_crc(uint8 ch,uint16 crc)223 static uint16 ubcsp_calc_crc (uint8 ch, uint16 crc)
224 {
225 	/* Calculate the CRC using the above 16 entry lookup table */
226 
227 	static const uint16 crc_table[] =
228 		{
229 			0x0000, 0x1081, 0x2102, 0x3183,
230 			0x4204, 0x5285, 0x6306, 0x7387,
231 			0x8408, 0x9489, 0xa50a, 0xb58b,
232 			0xc60c, 0xd68d, 0xe70e, 0xf78f
233 		};
234 
235 	/* Do this four bits at a time - more code, less space */
236 
237     crc = (crc >> 4) ^ crc_table[(crc ^ ch) & 0x000f];
238     crc = (crc >> 4) ^ crc_table[(crc ^ (ch >> 4)) & 0x000f];
239 
240 	return crc;
241 }
242 
243 /*****************************************************************************/
244 /**                                                                         **/
245 /** ubcsp_crc_reverse                                                       **/
246 /**                                                                         **/
247 /** Reserves the bits in crc and returns the new value                      **/
248 /**                                                                         **/
249 /*****************************************************************************/
250 
ubcsp_crc_reverse(uint16 crc)251 static uint16 ubcsp_crc_reverse (uint16 crc)
252 {
253 	int32
254 		b,
255 		rev;
256 
257 	/* Reserse the bits to compute the actual CRC value */
258 
259 	for (b = 0, rev=0; b < 16; b++)
260 	{
261 		rev = rev << 1;
262 		rev |= (crc & 1);
263 		crc = crc >> 1;
264 	}
265 
266 	return rev;
267 }
268 
269 #endif
270 
271 /*****************************************************************************/
272 /**                                                                         **/
273 /** ubcsp_put_slip_uart                                                     **/
274 /**                                                                         **/
275 /** Outputs a single octet to the uart                                      **/
276 /** If the octet needs to be escaped, then output the escape value          **/
277 /** and then store the second octet to be output later                      **/
278 /**                                                                         **/
279 /*****************************************************************************/
280 
ubcsp_put_slip_uart(uint8 ch)281 static void ubcsp_put_slip_uart (uint8 ch)
282 {
283 	/* output a single UART octet */
284 
285 	/* If it needs to be escaped, then output the escape octet
286 	   and set the send_slip_escape so that the next time we
287 	   output the second octet for the escape correctly.
288 	   This is done right at the top of ubcsp_poll */
289 
290 	if (ch == SLIP_FRAME)
291 	{
292 		put_uart (SLIP_ESCAPE);
293 		ubcsp_config.send_slip_escape = SLIP_ESCAPE_FRAME;
294 	}
295 	else if (ch == SLIP_ESCAPE)
296 	{
297 		put_uart (SLIP_ESCAPE);
298 		ubcsp_config.send_slip_escape = SLIP_ESCAPE_ESCAPE;
299 	}
300 	else
301 	{
302 		/* Not escaped, so just output octet */
303 
304 		put_uart (ch);
305 	}
306 }
307 
308 /*****************************************************************************/
309 /**                                                                         **/
310 /** ubcsp_which_le_payload                                                  **/
311 /**                                                                         **/
312 /** Check the payload of this packet, and determine which of the four       **/
313 /** link establishment packets this was.                                    **/
314 /** Can return 5 if it is not a valid link establishment packet             **/
315 /**                                                                         **/
316 /*****************************************************************************/
317 
ubcsp_which_le_payload(const uint8 * payload)318 static uint32 ubcsp_which_le_payload (const uint8 *payload)
319 {
320 	static int32
321 		octet,
322 		loop;
323 
324 	/* Search through the various link establishment payloads to find
325 	   which one we have received */
326 
327 	for (loop = 0; loop < 4; loop ++)
328 	{
329 		for (octet = 0; octet < 4; octet ++)
330 		{
331 			if (payload[octet] != ubcsp_le_buffer[loop][octet])
332 			{
333 				/* Bad match, just to loop again */
334 				goto bad_match_loop;
335 			}
336 		}
337 
338 		/* All the octets matched, return the value */
339 
340 		return loop;
341 
342 		/* Jumps out of octet loop if we got a bad match */
343 bad_match_loop:
344 		{}
345 	}
346 
347 	/* Non of the link establishment payloads matched - return invalid value */
348 
349 	return 5;
350 }
351 
352 /*****************************************************************************/
353 /**                                                                         **/
354 /** ubcsp_recevied_packet                                                   **/
355 /**                                                                         **/
356 /** This function is called when we have a SLIP END octet and a full        **/
357 /** packet header and possibly data in the receive packet                   **/
358 /**                                                                         **/
359 /*****************************************************************************/
360 
ubcsp_recevied_packet(void)361 static uint8 ubcsp_recevied_packet (void)
362 {
363 	static uint8
364 		receive_crc,
365 		receive_seq,
366 		receive_ack,
367 		activity;
368 
369 #if UBCSP_CRC
370 	static int32
371 		loop;
372 
373 	static uint16
374 		crc;
375 #endif
376 
377 	static uint16
378 		length;
379 
380 	/* Keep track of what activity this received packet will cause */
381 
382 	activity = 0;
383 
384 	/*** Do all error checks that we can ***/
385 
386 	/* First check the header checksum */
387 
388 	if (((ubcsp_receive_header[0] + ubcsp_receive_header[1] + ubcsp_receive_header[2] + ubcsp_receive_header[3]) & 0xff) != 0xff)
389 	{
390 		/* Header Checksum Error */
391 
392 #if SHOW_PACKET_ERRORS
393 		printf ("\n######################## Header Checksum Error %02X %02X %02X %02X\n",
394 			ubcsp_receive_header[0],
395 			ubcsp_receive_header[1],
396 			ubcsp_receive_header[2],
397 			ubcsp_receive_header[3]);
398 #endif
399 
400 		/* If we have a header checksum error, send an ack in return
401 		   this gets a packet to be resent as quickly as possible */
402 
403 		ubcsp_config.send_ack = 1;
404 
405 		return activity;
406 	}
407 
408 	/* Decode the received packets header */
409 
410 	ubcsp_config.receive_packet->reliable = (ubcsp_receive_header[0] & 0x80) >> 7;
411 
412 	receive_crc = (ubcsp_receive_header[0] & 0x40) >> 6;
413 	receive_ack = (ubcsp_receive_header[0] & 0x38) >> 3;
414 	receive_seq = (ubcsp_receive_header[0] & 0x07);
415 
416 	ubcsp_config.receive_packet->channel = (ubcsp_receive_header[1] & 0x0f);
417 
418 	length =
419 		((ubcsp_receive_header[1] & 0xf0) >> 4) |
420 		(ubcsp_receive_header[2] << 4);
421 
422 #if SHOW_PACKET_ERRORS
423 	if (ubcsp_config.receive_packet->reliable)
424 	{
425 		printf (" : %10d         Recv SEQ: %d ACK %d\n",
426 			GetTickCount () % 100000,
427 			receive_seq,
428 			receive_ack);
429 	}
430 	else if (ubcsp_config.receive_packet->channel != 1)
431 	{
432 		printf (" : %10d          Recv        ACK %d\n",
433 			GetTickCount () % 100000,
434 			receive_ack);
435 	}
436 #endif
437 
438 	/* Check for length errors */
439 
440 #if UBCSP_CRC
441 	if (receive_crc)
442 	{
443 		/* If this packet had a CRC, then the length of the payload
444 		   should be 2 less than the received size of the payload */
445 
446 		if (length + 2 != ubcsp_config.receive_index)
447 		{
448 			/* Slip Length Error */
449 
450 #if SHOW_PACKET_ERRORS
451 			printf ("\n######################## Slip Length Error (With CRC) %d,%d\n", length, ubcsp_config.receive_index - 2);
452 #endif
453 
454 			/* If we have a payload length error, send an ack in return
455 			   this gets a packet to be resent as quickly as possible */
456 
457 			ubcsp_config.send_ack = 1;
458 			return activity;
459 		}
460 
461 		/* We have a CRC at the end of this packet */
462 
463 		ubcsp_config.receive_index -= 2;
464 
465 		/* Calculate the packet CRC */
466 
467 		crc = 0xffff;
468 
469 		/* CRC the packet header */
470 
471 		for (loop = 0; loop < 4; loop ++)
472 		{
473 			crc = ubcsp_calc_crc (ubcsp_receive_header[loop], crc);
474 		}
475 
476 		/* CRC the packet payload - without the CRC bytes */
477 
478 		for (loop = 0; loop < ubcsp_config.receive_index; loop ++)
479 		{
480 			crc = ubcsp_calc_crc (ubcsp_config.receive_packet->payload[loop], crc);
481 		}
482 
483 		/* Reverse the CRC */
484 
485 		crc = ubcsp_crc_reverse (crc);
486 
487 		/* Check the CRC is correct */
488 
489 		if
490 		(
491 			(((crc & 0xff00) >> 8) != ubcsp_config.receive_packet->payload[ubcsp_config.receive_index]) ||
492 			((crc & 0xff) != ubcsp_config.receive_packet->payload[ubcsp_config.receive_index + 1])
493 		)
494 		{
495 #if SHOW_PACKET_ERRORS
496 			printf ("\n######################## CRC Error\n");
497 #endif
498 
499 			/* If we have a packet crc error, send an ack in return
500 			   this gets a packet to be resent as quickly as possible */
501 
502 			ubcsp_config.send_ack = 1;
503 			return activity;
504 		}
505 	}
506 	else
507 	{
508 #endif
509 		/* No CRC present, so just check the length of payload with that received */
510 
511 		if (length != ubcsp_config.receive_index)
512 		{
513 			/* Slip Length Error */
514 
515 #if SHOW_PACKET_ERRORS
516 			printf ("\n######################## Slip Length Error (No CRC) %d,%d\n", length, ubcsp_config.receive_index);
517 #endif
518 
519 			/* If we have a payload length error, send an ack in return
520 			   this gets a packet to be resent as quickly as possible */
521 
522 			ubcsp_config.send_ack = 1;
523 			return activity;
524 		}
525 #if UBCSP_CRC
526 	}
527 #endif
528 
529 	/*** We have a fully formed packet having passed all data integrity checks ***/
530 
531 	/* Check if we have an ACK for the last packet we sent */
532 
533 	if (receive_ack != ubcsp_config.sequence_number)
534 	{
535 		/* Since we only have a window size of 1, if the ACK is not equal to SEQ
536 		   then the packet was sent */
537 
538 		if
539 		(
540 			(ubcsp_config.send_packet) &&
541 			(ubcsp_config.send_packet->reliable)
542 		)
543 		{
544 			/* We had sent a reliable packet, so clear this packet
545 			   Then increament the sequence number for the next packet */
546 
547 			ubcsp_config.send_packet = 0;
548 			ubcsp_config.sequence_number ++;
549 			ubcsp_config.delay = 0;
550 
551 			/* Notify the caller that we have SENT a packet */
552 
553 			activity |= UBCSP_PACKET_SENT;
554 		}
555 	}
556 
557 	/*** Now we can concentrate of the packet we have received ***/
558 
559 	/* Check for Link Establishment packets */
560 
561 	if (ubcsp_config.receive_packet->channel == 1)
562 	{
563 		/* Link Establishment */
564 
565 		ubcsp_config.delay = 0;
566 
567 		/* Find which link establishment packet this payload means
568 		   This could return 5, meaning none */
569 
570 		switch (ubcsp_which_le_payload (ubcsp_config.receive_packet->payload))
571 		{
572 			case 0:
573 			{
574 				/* SYNC Recv'd */
575 
576 #if SHOW_LE_STATES
577 				printf ("Recv SYNC\n");
578 #endif
579 
580 				/* If we receive a SYNC, then we respond to it with a SYNC RESP
581 				   but only if we are not active.
582 				   If we are active, then we have a PEER RESET */
583 
584 				if (ubcsp_config.link_establishment_state < ubcsp_le_active)
585 				{
586 					ubcsp_config.link_establishment_resp = 1;
587 				}
588 				else
589 				{
590 					/* Peer reset !!!! */
591 
592 #if SHOW_LE_STATES
593 					printf ("\n\n\n\n\nPEER RESET\n\n");
594 #endif
595 
596 					/* Reinitialize the link */
597 
598 					ubcsp_initialize ();
599 
600 					/* Tell the host what has happened */
601 
602 					return UBCSP_PEER_RESET;
603 				}
604 				break;
605 			}
606 
607 			case 1:
608 			{
609 				/* SYNC RESP Recv'd */
610 
611 #if SHOW_LE_STATES
612 				printf ("Recv SYNC RESP\n");
613 #endif
614 
615 				/* If we receive a SYNC RESP, push us into the initialized state */
616 
617 				if (ubcsp_config.link_establishment_state < ubcsp_le_initialized)
618 				{
619 #if SHOW_LE_STATES
620 					printf ("Link Initialized\n");
621 #endif
622 					ubcsp_config.link_establishment_state = ubcsp_le_initialized;
623 				}
624 
625 				break;
626 			}
627 
628 			case 2:
629 			{
630 				/* CONF Recv'd */
631 
632 #if SHOW_LE_STATES
633 				printf ("Recv CONF\n");
634 #endif
635 
636 				/* If we receive a CONF, and we are initialized or active
637 				   then respond with a CONF RESP */
638 
639 				if (ubcsp_config.link_establishment_state >= ubcsp_le_initialized)
640 				{
641 					ubcsp_config.link_establishment_resp = 2;
642 				}
643 
644 				break;
645 			}
646 
647 			case 3:
648 			{
649 				/* CONF RESP Recv'd */
650 
651 #if SHOW_LE_STATES
652 				printf ("Recv CONF RESP\n");
653 #endif
654 
655 				/* If we received a CONF RESP, then push us into the active state */
656 
657 				if (ubcsp_config.link_establishment_state < ubcsp_le_active)
658 				{
659 #if SHOW_LE_STATES
660 					printf ("Link Active\n");
661 #endif
662 
663 					ubcsp_config.link_establishment_state = ubcsp_le_active;
664 					ubcsp_config.send_size = 0;
665 
666 					return activity | UBCSP_PACKET_SENT;
667 				}
668 
669 				break;
670 			}
671 		}
672 
673 		/* We have finished processing Link Establishment packets */
674 	}
675 	else if (ubcsp_config.receive_index)
676 	{
677 		/* We have some payload data we need to process
678 		   but only if we are active - otherwise, we just ignore it */
679 
680 		if (ubcsp_config.link_establishment_state == ubcsp_le_active)
681 		{
682 			if (ubcsp_config.receive_packet->reliable)
683 			{
684 				/* If the packet we've just received was reliable
685 				   then send an ACK */
686 
687 				ubcsp_config.send_ack = 1;
688 
689 				/* We the sequence number we received is the same as
690 				   the last ACK we sent, then we have received a packet in sequence */
691 
692 				if (receive_seq == ubcsp_config.ack_number)
693 				{
694 					/* Increase the ACK number - which will be sent in the next ACK
695 					   or normal packet we send */
696 
697 					ubcsp_config.ack_number ++;
698 
699 					/* Set the values in the receive_packet structure, so the caller
700 					   knows how much data we have */
701 
702 					ubcsp_config.receive_packet->length = length;
703 					ubcsp_config.receive_packet = 0;
704 
705 					/* Tell the caller that we have received a packet, and that it
706 					   will be ACK'ed */
707 
708 					activity |= UBCSP_PACKET_RECEIVED | UBCSP_PACKET_ACK;
709 				}
710 			}
711 			else
712 			{
713 				/* Set the values in the receive_packet structure, so the caller
714 				   knows how much data we have */
715 
716 				ubcsp_config.receive_packet->length = length;
717 				ubcsp_config.receive_packet = 0;
718 
719 				/* Tell the caller that we have received a packet */
720 
721 				activity |= UBCSP_PACKET_RECEIVED;
722 			}
723 		}
724 	}
725 
726 	/* Just return any activity that occured */
727 
728 	return activity;
729 }
730 
731 /*****************************************************************************/
732 /**                                                                         **/
733 /** ubcsp_setup_packet                                                      **/
734 /**                                                                         **/
735 /** This function is called to setup a packet to be sent                    **/
736 /** This allows just a header, or a header and payload to be sent           **/
737 /** It also allows the header checksum to be precalcuated                   **/
738 /** or calculated here                                                      **/
739 /** part1 is always 4 bytes                                                 **/
740 /**                                                                         **/
741 /*****************************************************************************/
742 
ubcsp_setup_packet(uint8 * part1,uint8 calc,uint8 * part2,uint16 len2)743 static void ubcsp_setup_packet (uint8 *part1, uint8 calc, uint8 *part2, uint16 len2)
744 {
745 	/* If we need to calculate the checksum, do that now */
746 
747 	if (calc)
748 	{
749 		part1[3] =
750 			~(part1[0] + part1[1] + part1[2]);
751 	}
752 
753 	/* Setup the header send pointer and size so we can clock this out */
754 
755 	ubcsp_config.send_ptr = part1;
756 	ubcsp_config.send_size = 4;
757 
758 	/* Setup the payload send pointer and size */
759 
760 	ubcsp_config.next_send_ptr = part2;
761 	ubcsp_config.next_send_size = len2;
762 
763 #if UBCSP_CRC
764 	/* Initialize the crc as required */
765 
766 	ubcsp_config.send_crc = -1;
767 
768 	ubcsp_config.need_send_crc = 1;
769 #endif
770 }
771 
772 /*****************************************************************************/
773 /**                                                                         **/
774 /** ubcsp_sent_packet                                                       **/
775 /**                                                                         **/
776 /** Called when we have finished sending a packet                           **/
777 /** If this packet was unreliable, then notify caller, and clear the data   **/
778 /**                                                                         **/
779 /*****************************************************************************/
780 
ubcsp_sent_packet(void)781 static uint8 ubcsp_sent_packet (void)
782 {
783 	if (ubcsp_config.send_packet)
784 	{
785 		if (!ubcsp_config.send_packet->reliable)
786 		{
787 			/* We had a packet sent that was unreliable */
788 
789 			/* Forget about this packet */
790 
791 			ubcsp_config.send_packet = 0;
792 
793 			/* Notify caller that they can send another one */
794 
795 			return UBCSP_PACKET_SENT;
796 		}
797 	}
798 
799 	/* We didn't have a packet, or it was reliable
800 	   Must wait for ACK before allowing another packet to be sent */
801 
802 	return 0;
803 }
804 
805 /*****************************************************************************/
806 /**                                                                         **/
807 /** ubcsp_poll                                                              **/
808 /**                                                                         **/
809 /** This is the main function for ubcsp                                     **/
810 /** It performs a number of tasks                                           **/
811 /**                                                                         **/
812 /** 1) Send another octet to the UART - escaping as required                **/
813 /** 2) Setup the payload to be sent after the header has been sent          **/
814 /** 3) Send the CRC for the packet if required                              **/
815 /**                                                                         **/
816 /** 4) Calculate the next Link Establishment State                          **/
817 /** 5) Send a Link Establishment packet                                     **/
818 /** 6) Send a normal packet if available                                    **/
819 /** 7) Send an ACK packet if required                                       **/
820 /**                                                                         **/
821 /** 8) Receive octets from UART and deslip them as required                 **/
822 /** 9) Place received octets into receive header or receive payload buffer  **/
823 /** 10) Process received packet when SLIP_END is received                   **/
824 /**                                                                         **/
825 /** 11) Keep track of ability of caller to delay recalling                  **/
826 /**                                                                         **/
827 /*****************************************************************************/
828 
ubcsp_poll(uint8 * activity)829 uint8 ubcsp_poll (uint8 *activity)
830 {
831 	uint8
832 		delay = UBCSP_POLL_TIME_IMMEDIATE;
833 
834 	uint8
835 		value;
836 
837 	/* Assume no activity to start with */
838 
839 	*activity = 0;
840 
841 	/* If we don't have to delay, then send something if we can */
842 
843 	if (!ubcsp_config.delay)
844 	{
845 		/* Do we have something we are sending to send */
846 
847 		if (ubcsp_config.send_size)
848 		{
849 			/* We have something to send so send it */
850 
851 			if (ubcsp_config.send_slip_escape)
852 			{
853 				/* Last time we send a SLIP_ESCAPE octet
854 				   this time send the second escape code */
855 
856 				put_uart (ubcsp_config.send_slip_escape);
857 
858 				ubcsp_config.send_slip_escape = 0;
859 			}
860 			else
861 			{
862 #if UBCSP_CRC
863 				/* get the value to send, and calculate CRC as we go */
864 
865 				value = *ubcsp_config.send_ptr ++;
866 
867 				ubcsp_config.send_crc = ubcsp_calc_crc (value, ubcsp_config.send_crc);
868 
869 				/* Output the octet */
870 
871 				ubcsp_put_slip_uart (value);
872 #else
873 				/* Just output the octet*/
874 
875 				ubcsp_put_slip_uart (*ubcsp_config.send_ptr ++);
876 #endif
877 			}
878 
879 			/* If we did output a SLIP_ESCAPE, then don't process the end of a block */
880 
881 			if ((!ubcsp_config.send_slip_escape) && ((ubcsp_config.send_size = ubcsp_config.send_size - 1) == 0))
882 			{
883 				/*** We are at the end of a block - either header or payload ***/
884 
885 				/* setup the next block */
886 
887 				ubcsp_config.send_ptr = ubcsp_config.next_send_ptr;
888 				ubcsp_config.send_size = ubcsp_config.next_send_size;
889 				ubcsp_config.next_send_ptr = 0;
890 				ubcsp_config.next_send_size = 0;
891 
892 #if UBCSP_CRC
893 				/* If we have no successor block
894 				   then we might need to send the CRC */
895 
896 				if (!ubcsp_config.send_ptr)
897 				{
898 					if (ubcsp_config.need_send_crc)
899 					{
900 						/* reverse the CRC from what we computed along the way */
901 
902 						ubcsp_config.need_send_crc = 0;
903 
904 						ubcsp_config.send_crc = ubcsp_crc_reverse (ubcsp_config.send_crc);
905 
906 						/* Save in the send_crc buffer */
907 
908 						ubcsp_send_crc[0] = (uint8) (ubcsp_config.send_crc >> 8);
909 						ubcsp_send_crc[1] = (uint8) ubcsp_config.send_crc;
910 
911 						/* Setup to send this buffer */
912 
913 						ubcsp_config.send_ptr = ubcsp_send_crc;
914 						ubcsp_config.send_size = 2;
915 					}
916 					else
917 					{
918 						/* We don't need to send the crc
919 						   either we just have, or this packet doesn't include it */
920 
921 						/* Output the end of FRAME marker */
922 
923 						put_uart (SLIP_FRAME);
924 
925 						/* Check if this is an unreliable packet */
926 
927 						*activity |= ubcsp_sent_packet ();
928 
929 						/* We've sent the packet, so don't need to have be called quickly soon */
930 
931 						delay = UBCSP_POLL_TIME_DELAY;
932 					}
933 				}
934 #else
935 				/* If we have no successor block
936 				   then we might need to send the CRC */
937 
938 				if (!ubcsp_config.send_ptr)
939 				{
940 					/* Output the end of FRAME marker */
941 
942 					put_uart (SLIP_FRAME);
943 
944 					/* Check if this is an unreliable packet */
945 
946 					*activity |= ubcsp_sent_packet ();
947 
948 					/* We've sent the packet, so don't need to have be called quickly soon */
949 
950 					delay = UBCSP_POLL_TIME_DELAY;
951 				}
952 #endif
953 			}
954 		}
955 		else if (ubcsp_config.link_establishment_packet == ubcsp_le_none)
956 		{
957 			/* We didn't have something to send
958 			   AND we have no Link Establishment packet to send */
959 
960 			if (ubcsp_config.link_establishment_resp & 2)
961 			{
962 				/* Send the start of FRAME packet */
963 
964 				put_uart (SLIP_FRAME);
965 
966 				/* We did require a RESP packet - so setup the send */
967 
968 				ubcsp_setup_packet ((uint8*) ubcsp_send_le_header, 0, (uint8*) ubcsp_le_buffer[ubcsp_le_conf_resp], 4);
969 
970 				/* We have now "sent" this packet */
971 
972 				ubcsp_config.link_establishment_resp = 0;
973 			}
974 			else if (ubcsp_config.send_packet)
975 			{
976 				/* There is a packet ready to be sent */
977 
978 				/* Send the start of FRAME packet */
979 
980 				put_uart (SLIP_FRAME);
981 
982 				/* Encode up the packet header using ACK and SEQ numbers */
983 
984 				ubcsp_send_header[0] =
985 					(ubcsp_config.send_packet->reliable << 7) |
986 #if UBCSP_CRC
987 					0x40 |	/* Always use CRC's */
988 #endif
989 					(ubcsp_config.ack_number << 3) |
990 					(ubcsp_config.sequence_number);
991 
992 				/* Encode up the packet header's channel and length */
993 				ubcsp_send_header[1] =
994 					(ubcsp_config.send_packet->channel & 0x0f) |
995 					((ubcsp_config.send_packet->length << 4) & 0xf0);
996 
997 				ubcsp_send_header[2] =
998 					(ubcsp_config.send_packet->length >> 4) & 0xff;
999 
1000 				/* Let the ubcsp_setup_packet function calculate the header checksum */
1001 
1002 				ubcsp_setup_packet ((uint8*) ubcsp_send_header, 1, ubcsp_config.send_packet->payload, ubcsp_config.send_packet->length);
1003 
1004 				/* Don't need to send an ACK - we just place on in this packet */
1005 
1006 				ubcsp_config.send_ack = 0;
1007 
1008 #if SHOW_PACKET_ERRORS
1009 				printf (" : %10d Send %d Ack %d\n",
1010 					GetTickCount () % 100000,
1011 					ubcsp_config.sequence_number,
1012 					ubcsp_config.ack_number);
1013 #endif
1014 			}
1015 			else if (ubcsp_config.send_ack)
1016 			{
1017 				/* Send the start of FRAME packet */
1018 
1019 				put_uart (SLIP_FRAME);
1020 
1021 #if SHOW_PACKET_ERRORS
1022 				printf (" : %10d Send ACK %d\n",
1023 					GetTickCount () % 100000,
1024 					ubcsp_config.ack_number);
1025 #endif
1026 
1027 				/* The ack packet is already computed apart from the first octet */
1028 
1029 				ubcsp_send_ack_header[0] =
1030 #if UBCSP_CRC
1031 					0x40 |
1032 #endif
1033 					(ubcsp_config.ack_number << 3);
1034 
1035 				/* Let the ubcsp_setup_packet function calculate the header checksum */
1036 
1037 				ubcsp_setup_packet (ubcsp_send_ack_header, 1, 0, 0);
1038 
1039 				/* We've now sent the ack */
1040 
1041 				ubcsp_config.send_ack = 0;
1042 			}
1043 			else
1044 			{
1045 				/* We didn't have a Link Establishment response packet,
1046 				   a normal packet or an ACK packet to send */
1047 
1048 				delay = UBCSP_POLL_TIME_DELAY;
1049 			}
1050 		}
1051 		else
1052 		{
1053 #if SHOW_PACKET_ERRORS
1054 //			printf (" : %10d Send LE %d\n",
1055 //				GetTickCount () % 100000,
1056 //				ubcsp_config.link_establishment_packet);
1057 #endif
1058 
1059 			/* Send A Link Establishment Message */
1060 
1061 			put_uart (SLIP_FRAME);
1062 
1063 			/* Send the Link Establishment header followed by the
1064 			   Link Establishment packet */
1065 
1066 			ubcsp_setup_packet ((uint8*) ubcsp_send_le_header, 0, (uint8*) ubcsp_le_buffer[ubcsp_config.link_establishment_packet], 4);
1067 
1068 			/* start sending immediately */
1069 
1070 			ubcsp_config.delay = 0;
1071 
1072 			/* workout what the next link establishment packet should be */
1073 
1074 			ubcsp_config.link_establishment_packet = next_le_packet[ubcsp_config.link_establishment_state + ubcsp_config.link_establishment_resp * 4];
1075 
1076 			/* We have now delt with any response packet that we needed */
1077 
1078 			ubcsp_config.link_establishment_resp = 0;
1079 
1080 			return 0;
1081 		}
1082 	}
1083 
1084 	/* We now need to receive any octets from the UART */
1085 
1086 	while ((ubcsp_config.receive_packet) && (get_uart (&value)))
1087 	{
1088 		/* If the last octet was SLIP_ESCAPE, then special processing is required */
1089 
1090 		if (ubcsp_config.receive_slip_escape)
1091 		{
1092 			/* WARNING - out of range values are not detected !!!
1093 			   This will probably be caught with the checksum or CRC check */
1094 
1095 			value = ubcsp_deslip[value - SLIP_ESCAPE_FRAME];
1096 
1097 			ubcsp_config.receive_slip_escape = 0;
1098 		}
1099 		else
1100 		{
1101 			/* Check for the SLIP_FRAME octet - must be start or end of packet */
1102 			if (value == SLIP_FRAME)
1103 			{
1104 				/* If we had a full header then we have a packet */
1105 
1106 				if (ubcsp_config.receive_index >= 0)
1107 				{
1108 					/* process the received packet */
1109 
1110 					*activity |= ubcsp_recevied_packet ();
1111 
1112 					if (*activity & UBCSP_PACKET_ACK)
1113 					{
1114 						/* We need to ACK this packet, then don't delay its sending */
1115 						ubcsp_config.delay = 0;
1116 					}
1117 				}
1118 
1119 				/* Setup to receive the next packet */
1120 
1121 				ubcsp_config.receive_index = -4;
1122 
1123 				/* Ok, next octet */
1124 
1125 				goto finished_receive;
1126 			}
1127 			else if (value == SLIP_ESCAPE)
1128 			{
1129 				/* If we receive a SLIP_ESCAPE,
1130 				   then remember to process the next special octet */
1131 
1132 				ubcsp_config.receive_slip_escape = 1;
1133 
1134 				goto finished_receive;
1135 			}
1136 		}
1137 
1138 		if (ubcsp_config.receive_index < 0)
1139 		{
1140 			/* We are still receiving the header */
1141 
1142 			ubcsp_receive_header[ubcsp_config.receive_index + 4] = value;
1143 
1144 			ubcsp_config.receive_index ++;
1145 		}
1146 		else if (ubcsp_config.receive_index < ubcsp_config.receive_packet->length)
1147 		{
1148 			/* We are receiving the payload */
1149 			/* We might stop comming here if we are receiving a
1150 			   packet which is longer than the receive_packet->length
1151 			   given by the host */
1152 
1153 			ubcsp_config.receive_packet->payload[ubcsp_config.receive_index] = value;
1154 
1155 			ubcsp_config.receive_index ++;
1156 		}
1157 
1158 finished_receive:
1159 		{
1160 		}
1161 	}
1162 
1163 	if (ubcsp_config.delay > 0)
1164 	{
1165 		/* We were delayed so delay some more
1166 		   this could be cancelled if we received something */
1167 
1168 		ubcsp_config.delay --;
1169 	}
1170 	else
1171 	{
1172 		/* We had no delay, so use the delay we just decided to us */
1173 
1174 		ubcsp_config.delay = delay;
1175 	}
1176 
1177 	/* Report the current delay to the user */
1178 
1179 	return ubcsp_config.delay;
1180 }
1181