?? serialsource.c
字號:
#include <sys/types.h>#include <sys/stat.h>#include <termios.h>#include <unistd.h>#include <errno.h>#include <fcntl.h>#include <stdlib.h>#include <string.h>#include <sys/time.h>#include <stdio.h>#ifdef __CYGWIN__#include <windows.h>#include <io.h>#else#include <stdint.h>#endif/* C implementation of the mote serial protocol. See net.tinyos.packet.Packetizer for more details */#undef DEBUG#include "serialsource.h"typedef int bool;enum {#ifndef __CYGWIN__ FALSE = 0, TRUE = 1,#endif BUFSIZE = 256, MTU = 256, ACK_TIMEOUT = 1000000, /* in us */ SYNC_BYTE = 0x7e, ESCAPE_BYTE = 0x7d, P_ACK = 64, P_PACKET_ACK = 65, P_PACKET_NO_ACK = 66, P_UNKNOWN = 255};struct packet_list{ uint8_t *packet; int len; struct packet_list *next;};struct serial_source { int fd; bool non_blocking; void (*message)(serial_source_msg problem); /* Receive state */ struct { uint8_t buffer[BUFSIZE]; int bufpos, bufused; uint8_t packet[MTU]; bool in_sync, escaped; int count; struct packet_list *queue[256]; // indexed by protocol } recv; struct { uint8_t seqno; uint8_t *escaped; int escapeptr; uint16_t crc; } send;};static tcflag_t parse_baudrate(int requested){ int baudrate; switch (requested) {#ifdef B50 case 50: baudrate = B50; break;#endif#ifdef B75 case 75: baudrate = B75; break;#endif#ifdef B110 case 110: baudrate = B110; break;#endif#ifdef B134 case 134: baudrate = B134; break;#endif#ifdef B150 case 150: baudrate = B150; break;#endif#ifdef B200 case 200: baudrate = B200; break;#endif#ifdef B300 case 300: baudrate = B300; break;#endif#ifdef B600 case 600: baudrate = B600; break;#endif#ifdef B1200 case 1200: baudrate = B1200; break;#endif#ifdef B1800 case 1800: baudrate = B1800; break;#endif#ifdef B2400 case 2400: baudrate = B2400; break;#endif#ifdef B4800 case 4800: baudrate = B4800; break;#endif#ifdef B9600 case 9600: baudrate = B9600; break;#endif#ifdef B19200 case 19200: baudrate = B19200; break;#endif#ifdef B38400 case 38400: baudrate = B38400; break;#endif#ifdef B57600 case 57600: baudrate = B57600; break;#endif#ifdef B115200 case 115200: baudrate = B115200; break;#endif#ifdef B230400 case 230400: baudrate = B230400; break;#endif#ifdef B460800 case 460800: baudrate = B460800; break;#endif#ifdef B500000 case 500000: baudrate = B500000; break;#endif#ifdef B576000 case 576000: baudrate = B576000; break;#endif#ifdef B921600 case 921600: baudrate = B921600; break;#endif#ifdef B1000000 case 1000000: baudrate = B1000000; break;#endif#ifdef B1152000 case 1152000: baudrate = B1152000; break;#endif#ifdef B1500000 case 1500000: baudrate = B1500000; break;#endif#ifdef B2000000 case 2000000: baudrate = B2000000; break;#endif#ifdef B2500000 case 2500000: baudrate = B2500000; break;#endif#ifdef B3000000 case 3000000: baudrate = B3000000; break;#endif#ifdef B3500000 case 3500000: baudrate = B3500000; break;#endif#ifdef B4000000 case 4000000: baudrate = B4000000; break;#endif default: baudrate = 0; } return baudrate;}#ifdef DEBUGstatic void dump(const char *msg, unsigned char *packet, int len){ int i; printf("%s", msg); for (i = 0; i < len; i++) printf(" %02x", packet[i]); putchar('\n');}#endifstatic void message(serial_source src, serial_source_msg msg){ if (src->message) src->message(msg);}/* Work around buggy usb serial driver (returns 0 when no data is available, independent of the blocking/non-blocking mode) */static int buggyread(serial_source src, void *buffer, int n){ fd_set fds; int cnt; if (src->non_blocking) { cnt = read(src->fd, buffer, n); if (cnt == 0) { cnt = -1; errno = EAGAIN; } return cnt; } else for (;;) { FD_ZERO(&fds); FD_SET(src->fd, &fds); cnt = select(src->fd + 1, &fds, NULL, NULL, NULL); if (cnt < 0) return -1; cnt = read(src->fd, buffer, n); if (cnt != 0) return cnt; }}serial_source open_serial_source(const char *device, int baud_rate, int non_blocking, void (*message)(serial_source_msg problem))/* Effects: opens serial port device at specified baud_rate. If non_blocking is true, read_serial_packet calls will be non-blocking (writes are always blocking, for now at least) Returns: descriptor for serial forwarder at host:port, or NULL for failure (bad device or bad baud rate) */{ struct termios newtio; int fd; tcflag_t baudflag = parse_baudrate(baud_rate); if (!baudflag) return NULL; fd = open(device, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd < 0) return NULL;#ifdef __CYGWIN__ /* For some very mysterious reason, this incantation is necessary to make the serial port work under some windows machines */ HANDLE handle = (HANDLE)get_osfhandle(fd); DCB dcb; if (!(GetCommState(handle, &dcb) && SetCommState(handle, &dcb))) { close(fd); return NULL; }#endif /* Serial port setting */ memset(&newtio, 0, sizeof(newtio)); newtio.c_cflag = CS8 | CLOCAL | CREAD; newtio.c_iflag = IGNPAR | IGNBRK; cfsetispeed(&newtio, baudflag); cfsetospeed(&newtio, baudflag); /* Raw output_file */ newtio.c_oflag = 0; if (tcflush(fd, TCIFLUSH) >= 0 && tcsetattr(fd, TCSANOW, &newtio) >= 0) { serial_source src = malloc(sizeof *src); if (src) { memset(src, 0, sizeof src); src->fd = fd; src->non_blocking = non_blocking; src->message = message; src->send.seqno = 37; return src; } } close(fd); return NULL;}int serial_source_fd(serial_source src)/* Returns: the file descriptor used by serial source src (useful when non-blocking reads were requested)*/{ return src->fd;}int close_serial_source(serial_source src)/* Effects: closes serial source src Returns: 0 if successful, -1 if some problem occured (but source is considered closed anyway) */{ int ok = close(src->fd); free(src); return ok;}static int source_wait(serial_source src, struct timeval *deadline)/* Effects: waits until deadline for some data on source. deadline can be NULL for indefinite waiting. Returns: 0 if data is available, -1 if the deadline expires*/{ struct timeval tv; fd_set fds; int cnt; if (src->recv.bufpos < src->recv.bufused) return 0; for (;;) { if (deadline) { gettimeofday(&tv, NULL); tv.tv_sec = deadline->tv_sec - tv.tv_sec; tv.tv_usec = deadline->tv_usec - tv.tv_usec; if (tv.tv_usec < 0) { tv.tv_usec += 1000000; tv.tv_sec--; } if (tv.tv_sec < 0) return -1; } FD_ZERO(&fds); FD_SET(src->fd, &fds); cnt = select(src->fd + 1, &fds, NULL, NULL, deadline ? &tv : NULL); if (cnt < 0) { if (errno == EINTR) continue; message(src, msg_unix_error); return -1; } if (cnt == 0) return -1; return 0; }}static int source_write(serial_source src, const void *buffer, int count){ int actual = 0; if (fcntl(src->fd, F_SETFL, 0) < 0) { message(src, msg_unix_error); return -1; } while (count > 0) { int n = write(src->fd, buffer, count); if (n < 0 && errno == EINTR) continue; if (n < 0) { message(src, msg_unix_error); actual = -1; break; } count -= n; actual += n; buffer += n; } if (fcntl(src->fd, F_SETFL, O_NONBLOCK) < 0) { message(src, msg_unix_error); /* We're in trouble, but there's no obvious fix. */ } return actual;}static void push_protocol_packet(serial_source src,
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -