OSDN Git Service

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