19 /* C implementation of the mote serial protocol. See
20 net.tinyos.packet.Packetizer for more details */
24 #include "serialsource.h"
25 #include "serialprotocol.h"
36 ACK_TIMEOUT = 1000000, /* in us */
37 SYNC_BYTE = SERIAL_HDLC_FLAG_BYTE,
38 ESCAPE_BYTE = SERIAL_HDLC_CTLESC_BYTE,
40 P_ACK = SERIAL_SERIAL_PROTO_ACK,
41 P_PACKET_ACK = SERIAL_SERIAL_PROTO_PACKET_ACK,
42 P_PACKET_NO_ACK = SERIAL_SERIAL_PROTO_PACKET_NOACK,
43 P_UNKNOWN = SERIAL_SERIAL_PROTO_PACKET_UNKNOWN
50 struct packet_list *next;
53 struct serial_source {
56 void (*message)(serial_source_msg problem);
60 uint8_t buffer[BUFSIZE];
63 bool in_sync, escaped;
65 struct packet_list *queue[256]; // indexed by protocol
75 static tcflag_t parse_baudrate(int requested)
82 case 50: baudrate = B50; break;
85 case 75: baudrate = B75; break;
88 case 110: baudrate = B110; break;
91 case 134: baudrate = B134; break;
94 case 150: baudrate = B150; break;
97 case 200: baudrate = B200; break;
100 case 300: baudrate = B300; break;
103 case 600: baudrate = B600; break;
106 case 1200: baudrate = B1200; break;
109 case 1800: baudrate = B1800; break;
112 case 2400: baudrate = B2400; break;
115 case 4800: baudrate = B4800; break;
118 case 9600: baudrate = B9600; break;
121 case 19200: baudrate = B19200; break;
124 case 38400: baudrate = B38400; break;
127 case 57600: baudrate = B57600; break;
130 case 115200: baudrate = B115200; break;
133 case 230400: baudrate = B230400; break;
136 case 460800: baudrate = B460800; break;
139 case 500000: baudrate = B500000; break;
142 case 576000: baudrate = B576000; break;
145 case 921600: baudrate = B921600; break;
148 case 1000000: baudrate = B1000000; break;
151 case 1152000: baudrate = B1152000; break;
154 case 1500000: baudrate = B1500000; break;
157 case 2000000: baudrate = B2000000; break;
160 case 2500000: baudrate = B2500000; break;
163 case 3000000: baudrate = B3000000; break;
166 case 3500000: baudrate = B3500000; break;
169 case 4000000: baudrate = B4000000; break;
178 static void dump(const char *msg, unsigned char *packet, int len)
183 for (i = 0; i < len; i++)
184 printf(" %02x", packet[i]);
189 static void message(serial_source src, serial_source_msg msg)
195 static int serial_read(serial_source src, int non_blocking, void *buffer, int n)
202 cnt = read(src->fd, buffer, n);
204 /* Work around buggy usb serial driver (returns 0 when no data
205 is available). Mac OS X seems to like to do this too (at
206 least with a Keyspan 49WG).
219 FD_SET(src->fd, &fds);
220 cnt = select(src->fd + 1, &fds, NULL, NULL, NULL);
224 cnt = read(src->fd, buffer, n);
230 serial_source open_serial_source(const char *device, int baud_rate,
232 void (*message)(serial_source_msg problem))
233 /* Effects: opens serial port device at specified baud_rate. If non_blocking
234 is true, read_serial_packet calls will be non-blocking (writes are
235 always blocking, for now at least)
236 Returns: descriptor for serial forwarder at host:port, or
237 NULL for failure (bad device or bad baud rate)
240 struct termios newtio;
242 tcflag_t baudflag = parse_baudrate(baud_rate);
247 fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK);
252 /* For some very mysterious reason, this incantation is necessary to make
253 the serial port work under some windows machines */
254 HANDLE handle = (HANDLE)get_osfhandle(fd);
256 if (!(GetCommState(handle, &dcb) && SetCommState(handle, &dcb)))
262 /* Serial port setting */
263 memset(&newtio, 0, sizeof(newtio));
264 newtio.c_cflag = CS8 | CLOCAL | CREAD;
265 newtio.c_iflag = IGNPAR | IGNBRK;
266 cfsetispeed(&newtio, baudflag);
267 cfsetospeed(&newtio, baudflag);
269 /* Raw output_file */
272 if (tcflush(fd, TCIFLUSH) >= 0 &&
273 tcsetattr(fd, TCSANOW, &newtio) >= 0)
275 serial_source src = malloc(sizeof *src);
279 memset(src, 0, sizeof *src);
281 src->non_blocking = non_blocking;
282 src->message = message;
283 src->send.seqno = 37;
293 int serial_source_fd(serial_source src)
294 /* Returns: the file descriptor used by serial source src (useful when
295 non-blocking reads were requested)
301 int close_serial_source(serial_source src)
302 /* Effects: closes serial source src
303 Returns: 0 if successful, -1 if some problem occured (but source is
304 considered closed anyway)
307 int ok = close(src->fd);
314 static int source_wait(serial_source src, struct timeval *deadline)
315 /* Effects: waits until deadline for some data on source. deadline
316 can be NULL for indefinite waiting.
317 Returns: 0 if data is available, -1 if the deadline expires
324 if (src->recv.bufpos < src->recv.bufused)
331 gettimeofday(&tv, NULL);
332 tv.tv_sec = deadline->tv_sec - tv.tv_sec;
333 tv.tv_usec = deadline->tv_usec - tv.tv_usec;
336 tv.tv_usec += 1000000;
344 FD_SET(src->fd, &fds);
345 cnt = select(src->fd + 1, &fds, NULL, NULL, deadline ? &tv : NULL);
350 message(src, msg_unix_error);
359 static int source_write(serial_source src, const void *buffer, int count)
363 if (fcntl(src->fd, F_SETFL, 0) < 0)
365 message(src, msg_unix_error);
370 int n = write(src->fd, buffer, count);
372 if (n < 0 && errno == EINTR)
376 message(src, msg_unix_error);
385 if (fcntl(src->fd, F_SETFL, O_NONBLOCK) < 0)
387 message(src, msg_unix_error);
388 /* We're in trouble, but there's no obvious fix. */
393 static void push_protocol_packet(serial_source src,
394 uint8_t type, uint8_t *packet, uint8_t len)
396 /* I'm assuming short queues */
397 struct packet_list *entry = malloc(sizeof *entry), **last;
401 message(src, msg_no_memory);
406 entry->packet = packet;
410 last = &src->recv.queue[type];
412 last = &(*last)->next;
416 static struct packet_list *pop_protocol_packet(serial_source src, uint8_t type)
418 struct packet_list *entry = src->recv.queue[type];
421 src->recv.queue[type] = entry->next;
426 static bool packet_available(serial_source src, uint8_t type)
428 return src->recv.queue[type] != NULL;
431 int serial_source_empty(serial_source src)
432 /* Returns: true if serial source does not contain any pending data, i.e.,
433 if the result is true and there is no data available on the source's
434 file descriptor, then read_serial_packet will:
435 - return NULL if the source is non-blocking
436 - block if it is blocking
438 (Note: the presence of this calls allows the serial_source to do some
442 return src->recv.bufpos >= src->recv.bufused &&
443 !packet_available(src, P_PACKET_NO_ACK);
446 /* Slow implementation of crc function */
447 static uint16_t crc_byte(uint16_t crc, uint8_t b)
455 crc = crc << 1 ^ 0x1021;
463 static uint16_t crc_packet(uint8_t *data, int len)
468 crc = crc_byte(crc, *data++);
473 static int read_byte(serial_source src, int non_blocking)
474 /* Returns: next byte (>= 0), or -1 if no data available and non-blocking is true.
477 if (src->recv.bufpos >= src->recv.bufused)
481 int n = serial_read(src, non_blocking, src->recv.buffer, sizeof src->recv.buffer);
483 if (n == 0) /* Can't occur because of serial_read bug workaround */
485 message(src, msg_closed);
491 dump("raw", src->recv.buffer, n);
493 src->recv.bufpos = 0;
494 src->recv.bufused = n;
500 message(src, msg_unix_error);
503 //printf("in %02x\n", src->recv.buffer[src->recv.bufpos]);
504 return src->recv.buffer[src->recv.bufpos++];
507 static void process_packet(serial_source src, uint8_t *packet, int len);
508 static int write_framed_packet(serial_source src,
509 uint8_t packet_type, uint8_t first_byte,
510 const uint8_t *packet, int count);
512 static void read_and_process(serial_source src, int non_blocking)
513 /* Effects: reads and processes up to one packet.
516 uint8_t *packet = src->recv.packet;
520 int byte = read_byte(src, non_blocking);
525 if (!src->recv.in_sync)
527 if (byte == SYNC_BYTE)
529 src->recv.in_sync = TRUE;
530 message(src, msg_sync);
532 src->recv.escaped = FALSE;
536 if (src->recv.count >= MTU)
538 message(src, msg_too_long);
539 src->recv.in_sync = FALSE;
542 if (src->recv.escaped)
544 if (byte == SYNC_BYTE)
546 /* sync byte following escape is an error, resync */
547 message(src, msg_bad_sync);
548 src->recv.in_sync = FALSE;
552 src->recv.escaped = FALSE;
554 else if (byte == ESCAPE_BYTE)
556 src->recv.escaped = TRUE;
559 else if (byte == SYNC_BYTE)
561 int count = src->recv.count;
563 uint16_t read_crc, computed_crc;
565 src->recv.count = 0; /* ready for next packet */
568 /* frames that are too small are ignored */
571 received = malloc(count - 2);
574 message(src, msg_no_memory);
577 memcpy(received, packet, count - 2);
579 read_crc = packet[count - 2] | packet[count - 1] << 8;
580 computed_crc = crc_packet(received, count - 2);
583 dump("received", packet, count);
584 printf(" crc %x comp %x\n", read_crc, computed_crc);
586 if (read_crc == computed_crc)
588 process_packet(src, received, count - 2);
589 return; /* give rest of world chance to do something */
593 message(src, msg_bad_crc);
595 /* We don't lose sync here. If we did, garbage on the line
596 at startup will cause loss of the first packet. */
600 packet[src->recv.count++] = byte;
604 static void process_packet(serial_source src, uint8_t *packet, int len)
606 int packet_type = packet[0], offset = 1;
608 if (packet_type == P_PACKET_ACK)
611 write_framed_packet(src, P_ACK, packet[1], NULL, 0);
612 /* And merge with un-acked packets */
613 packet_type = P_PACKET_NO_ACK;
616 /* packet must remain a valid pointer to pass to free. So we move the
617 data rather than pass an internal pointer */
618 memmove(packet, packet + offset, len - offset);
619 push_protocol_packet(src, packet_type, packet, len - offset);
622 void *read_serial_packet(serial_source src, int *len)
623 /* Effects: Read the serial source src. If a packet is available, return it.
624 If in blocking mode and no packet is available, wait for one.
625 Returns: the packet read (in newly allocated memory), with *len is
626 set to the packet length, or NULL if no packet is yet available and
627 the serial source is in non-blocking mode
630 read_and_process(src, TRUE);
633 struct packet_list *entry;
635 entry = pop_protocol_packet(src, P_PACKET_NO_ACK);
638 uint8_t *packet = entry->packet;
645 if (src->non_blocking && serial_source_empty(src))
647 source_wait(src, NULL);
648 read_and_process(src, src->non_blocking);
652 /* The escaper does the sync bytes+escape-like encoding+crc of packets */
654 static void escape_add(serial_source src, uint8_t b)
656 src->send.escaped[src->send.escapeptr++] = b;
659 static int init_escaper(serial_source src, int count)
661 src->send.escaped = malloc(count * 2 + 2);
662 if (!src->send.escaped)
664 message(src, msg_no_memory);
667 src->send.escapeptr = 0;
670 escape_add(src, SYNC_BYTE);
675 static void terminate_escaper(serial_source src)
677 escape_add(src, SYNC_BYTE);
680 static void escape_byte(serial_source src, uint8_t b)
682 src->send.crc = crc_byte(src->send.crc, b);
683 if (b == SYNC_BYTE || b == ESCAPE_BYTE)
685 escape_add(src, ESCAPE_BYTE);
686 escape_add(src, b ^ 0x20);
692 static void free_escaper(serial_source src)
694 free(src->send.escaped);
697 // Write a packet of type 'packetType', first byte 'firstByte'
698 // and bytes 2..'count'+1 in 'packet'
699 static int write_framed_packet(serial_source src,
700 uint8_t packet_type, uint8_t first_byte,
701 const uint8_t *packet, int count)
706 printf("writing %02x %02x", packet_type, first_byte);
707 dump("", packet, count);
710 if (init_escaper(src, count + 4) < 0)
713 escape_byte(src, packet_type);
714 escape_byte(src, first_byte);
715 for (i = 0; i < count; i++)
716 escape_byte(src, packet[i]);
719 escape_byte(src, crc & 0xff);
720 escape_byte(src, crc >> 8);
722 terminate_escaper(src);
725 dump("encoded", src->send.escaped, src->send.escapeptr);
728 if (source_write(src, src->send.escaped, src->send.escapeptr) < 0)
737 static void add_timeval(struct timeval *tv, long us)
738 /* Specialised for this app */
740 tv->tv_sec += us / 1000000;
741 tv->tv_usec += us % 1000000;
742 if (tv->tv_usec > 1000000)
744 tv->tv_usec -= 1000000;
749 int write_serial_packet(serial_source src, const void *packet, int len)
750 /* Effects: writes len byte packet to serial source src
751 Returns: 0 if packet successfully written, 1 if successfully written
752 but not acknowledged, -1 otherwise
755 struct timeval deadline;
758 if (write_framed_packet(src, P_PACKET_ACK, src->send.seqno, packet, len) < 0)
761 gettimeofday(&deadline, NULL);
762 add_timeval(&deadline, ACK_TIMEOUT);
765 struct packet_list *entry;
767 read_and_process(src, TRUE);
768 entry = pop_protocol_packet(src, P_ACK);
771 uint8_t acked = entry->packet[0];
775 if (acked == src->send.seqno)
778 else if (source_wait(src, &deadline) < 0)
783 /* This somewhat convoluted code allows us to use a common baudrate table
784 with the Java code. This could be improved if we generated the Java
785 code from a common table.
793 static void padd(struct pargs *args, const char *name, int baudrate)
795 if (!strcmp(args->name, name))
796 args->rate = baudrate;
799 static void init(void) { }
801 int platform_baud_rate(char *platform_name)
802 /* Returns: The baud rate of the specified platform, or -1 for unknown
806 /* The Java code looks like Platform.add(Platform.x, "name", baudrate);
807 Fake up some C stuff which will make that work right. */
810 void (*add)(struct pargs *args, const char *name, int baudrate);
812 } Platform = { padd, &args };
819 if (isdigit(platform_name[0]))
820 return atoi(platform_name);
822 args.name = platform_name;
832 #include "./BaudRate.java"