⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialsource.c

📁 tinyos-2.x.rar
💻 C
📖 第 1 页 / 共 2 页
字号:
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Avoid confusing windows w/o cygwin w/ cygwin */
#define LOSE32
#endif

#ifndef LOSE32
#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 <ctype.h>
#include <sys/time.h>
#include <stdio.h>
#ifdef __CYGWIN__
#include <windows.h>
#include <io.h>
#else
#include <stdint.h>
#endif
#endif

#ifdef LOSE32
#include <windows.h>
#include <stdint.h>
#endif

/* C implementation of the mote serial protocol. See
   net.tinyos.packet.Packetizer for more details */

#undef DEBUG

#include "serialsource.h"
#include "serialprotocol.h"

typedef int bool;

enum {
#ifndef __CYGWIN__
#ifndef LOSE32
  FALSE = 0,
  TRUE = 1,
#endif
#endif
  BUFSIZE = 256,
  MTU = 256,
  ACK_TIMEOUT = 100000, /* in us */
  SYNC_BYTE = SERIAL_HDLC_FLAG_BYTE,
  ESCAPE_BYTE = SERIAL_HDLC_CTLESC_BYTE,

  P_ACK = SERIAL_SERIAL_PROTO_ACK,
  P_PACKET_ACK = SERIAL_SERIAL_PROTO_PACKET_ACK,
  P_PACKET_NO_ACK = SERIAL_SERIAL_PROTO_PACKET_NOACK,
  P_UNKNOWN = SERIAL_SERIAL_PROTO_PACKET_UNKNOWN
};

struct packet_list
{
  uint8_t *packet;
  int len;
  struct packet_list *next;
};

struct serial_source_t {
#ifndef LOSE32
  int fd;
#else
  HANDLE hComm;
#endif
  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;
};

#ifndef LOSE32
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;
}
#endif

#ifdef DEBUG
static 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');
}
#endif

static void message(serial_source src, serial_source_msg msg)
{
  if (src->message)
    src->message(msg);
}

static int serial_read(serial_source src, int non_blocking, void *buffer, int n)
{
#ifndef LOSE32
  fd_set fds;
  int cnt;

  if (non_blocking)
    {
      cnt = read(src->fd, buffer, n);

      /* Work around buggy usb serial driver (returns 0 when no data
	 is available). Mac OS X seems to like to do this too (at
	 least with a Keyspan 49WG).
      */
      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;
      }
#else // LOSE32
  int cnt;

  if (non_blocking) {
    ReadFile(src->hComm, buffer, n, &cnt, NULL);

    return cnt;

  } else {
      for (;;) {
          DWORD eventMask;
          SetCommMask(src->hComm, EV_RXCHAR);
          if (!WaitCommEvent(src->hComm, &eventMask, NULL)) {
              return -1;
          }

          ReadFile(src->hComm, buffer, n, &cnt, NULL);

          if (cnt != 0) {
            return cnt;
          }
      }
  }
#endif
}

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)
 */
{
#ifndef LOSE32
  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;
#else // LOSE32
	LPCTSTR       ComName = (LPCTSTR)device;
    HANDLE        hComm;
	DCB           dcb;
    serial_source src;

	int buflen = MultiByteToWideChar(CP_ACP,0,(PCSTR)device,-1,(LPWSTR)ComName,0);
	MultiByteToWideChar(CP_ACP,0,(PCSTR)device,-1,(LPWSTR)ComName,buflen);
	
	//syncronize
	hComm = CreateFile(ComName,  GENERIC_READ | GENERIC_WRITE,  0,  NULL,  OPEN_EXISTING,
					FILE_ATTRIBUTE_NORMAL, NULL);

    if (hComm == INVALID_HANDLE_VALUE) {
        return NULL;
    }

    PurgeComm(hComm, PURGE_RXCLEAR);

	GetCommState(hComm, &dcb); 
	dcb.BaudRate = baud_rate;
	dcb.ByteSize = 8;
	dcb.Parity = NOPARITY;
	dcb.fParity = FALSE;
	dcb.StopBits = ONESTOPBIT;
    if (SetCommState(hComm, &dcb) == 0) {
        return NULL;
    }

    src = malloc(sizeof *src);

    if (src) {
	  memset(src, 0, sizeof *src);
	  src->hComm = hComm;
	  src->non_blocking = non_blocking;
	  src->message = message;
	  src->send.seqno = 37;

	}

	return src;

#endif // LOSE32
}

#ifndef LOSE32
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;
}
#endif

#ifdef LOSE32
HANDLE serial_source_handle(serial_source src)
/* Returns: the file descriptor used by serial source src (useful when
     non-blocking reads were requested)
*/
{
  return src->hComm;
}
#endif

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)
 */
{
#ifndef LOSE32
  int ok = close(src->fd);
#else
  int ok = CloseHandle(src->hComm);
#endif

  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
*/
{
#ifndef LOSE32
  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;
    }
#else // LOSE32
    // FIXME: the deadline is ignored here

    DWORD eventMask;
    SetCommMask(src->hComm, EV_RXCHAR);
    if (!WaitCommEvent(src->hComm, &eventMask, NULL)) {
        return -1;
    }

    return 0;

#endif
}

static int source_write(serial_source src, const void *buffer, int count)
{
#ifndef LOSE32
  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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -