api.h 8 KB
Newer Older
Franz's avatar
Franz committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
/*
  libxbee - a C library to aid the use of Digi's Series 1 XBee modules
            running in API mode (AP=2).

  Copyright (C) 2009  Attie Grande (attie@attie.co.uk)

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdio.h>
#include <stdlib.h>

#include <stdarg.h>

#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>

#ifdef __GNUC__ /* ---- */
#include <unistd.h>
#include <termios.h>
#define __USE_GNU
#include <pthread.h>
#undef __USE_GNU
#include <sys/time.h>
#else /* -------------- */
#include <Windows.h>
#include <io.h>
#include <time.h>
#include <sys/timeb.h>
#endif /* ------------- */

#ifdef __UMAKEFILE
  #define HOST_OS "Embedded"
#elif defined(__GNUC__)
  #define HOST_OS "Linux"
#elif defined(_WIN32)
  #define HOST_OS "Win32"
#else
  #define HOST_OS "UNKNOWN"
#endif

#define TRUE 1
#define FALSE 0

#define M8(x) (x & 0xFF)

/* various connection types */
#define XBEE_LOCAL_AT     0x88
#define XBEE_LOCAL_ATREQ  0x08
#define XBEE_LOCAL_ATQUE  0x09

#define XBEE_REMOTE_AT    0x97
#define XBEE_REMOTE_ATREQ 0x17

#define XBEE_MODEM_STATUS 0x8A

/* XBee Series 1 stuff */
#define XBEE_TX_STATUS    0x89
#define XBEE_64BIT_DATATX 0x00
#define XBEE_64BIT_DATARX 0x80
#define XBEE_16BIT_DATATX 0x01
#define XBEE_16BIT_DATARX 0x81
#define XBEE_64BIT_IO     0x82
#define XBEE_16BIT_IO     0x83

/* XBee Series 2 stuff */
#define XBEE2_DATATX      0x10
#define XBEE2_DATARX      0x90
#define XBEE2_TX_STATUS   0x8B

typedef struct xbee_hnd* xbee_hnd;

#define __LIBXBEE_API_H
#include "xbee.h"

typedef struct t_threadList t_threadList;
struct t_threadList {
  xbee_thread_t thread;
  t_threadList *next;
};

struct xbee_hnd {
  xbee_file_t tty;
#ifdef __GNUC__ /* ---- */
  int ttyfd;
#else /* -------------- */
  int ttyr;
  int ttyw;
  int ttyeof;

  OVERLAPPED ttyovrw;
  OVERLAPPED ttyovrr;
  OVERLAPPED ttyovrs;
#endif /* ------------- */

  char *path; /* serial port path */

  xbee_mutex_t logmutex;
  FILE *log;
  int logfd;

  xbee_mutex_t conmutex;
  xbee_con *conlist;

  xbee_mutex_t pktmutex;
  xbee_pkt *pktlist;
  xbee_pkt *pktlast;
  int pktcount;
  
  xbee_mutex_t sendmutex;

  xbee_thread_t listent;
  
  xbee_thread_t threadt;
  xbee_mutex_t  threadmutex;
  xbee_sem_t    threadsem;
  t_threadList *threadList;
  
  int run;

  int oldAPI;
  char cmdSeq;
  int cmdTime;

  /* ready flag.
     needs to be set to -1 so that the listen thread can begin. */
  volatile int xbee_ready;
  
  xbee_hnd next;
};
xbee_hnd default_xbee = NULL;
xbee_mutex_t xbee_hnd_mutex;

typedef struct t_data t_data;
struct t_data {
  unsigned char data[128];
  unsigned int length;
};

typedef struct t_LTinfo t_LTinfo;
struct t_LTinfo {
  int i;
  xbee_hnd xbee;
};

typedef struct t_CBinfo t_CBinfo;
struct t_CBinfo {
  xbee_hnd xbee;
  xbee_con *con;
};

typedef struct t_callback_list t_callback_list;
struct t_callback_list {
  xbee_pkt *pkt;
  t_callback_list *next;
};

static void *Xmalloc2(xbee_hnd xbee, size_t size);
static void *Xcalloc2(xbee_hnd xbee, size_t size);
static void *Xrealloc2(xbee_hnd xbee, void *ptr, size_t size);
static void Xfree2(void **ptr);
#define Xmalloc(x)     Xmalloc2(xbee,(x))
#define Xcalloc(x)     Xcalloc2(xbee,(x))
#define Xrealloc(x,y)  Xrealloc2(xbee,(x),(y))
#define Xfree(x)       Xfree2((void **)&x)

/* usage:
    xbee_logSf()   lock the log
    xbee_logEf()   unlock the log
    
    xbee_log()     lock   print with \n      unlock          # to print a single line
    xbee_logc()    lock   print with no \n                   # to print a single line with a custom ending
    xbee_logcf()          print \n           unlock          # to end a custom-ended single line
    
    xbee_logS()    lock   print with \n                      # to start a continuous block
    xbee_logI()           print with \n                      # to continue a continuous block
    xbee_logIc()          print with no \n                   # to continue a continuous block with a custom ending
    xbee_logIcf()         print \n                           # to continue a continuous block with ended custom-ended line
    xbee_logE()           print with \n      unlock          # to end a continuous block
*/
static void xbee_logf(xbee_hnd xbee, const char *logformat, const char *file,
                      const int line, const char *function, char *format, ...);
#define LOG_FORMAT "[%s:%d] %s(): %s"

#define xbee_logSf()      if (xbee->log) { xbee_mutex_lock(xbee->logmutex);   }
#define xbee_logEf()      if (xbee->log) { xbee_mutex_unlock(xbee->logmutex); }

#define xbee_log(...)     if (xbee->log) { xbee_logSf(); xbee_logf(xbee,LOG_FORMAT"\n",__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__); xbee_logEf(); }
#define xbee_logc(...)    if (xbee->log) { xbee_logSf(); xbee_logf(xbee,LOG_FORMAT    ,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__);               }
#define xbee_logcf()      if (xbee->log) {               fprintf(xbee->log, "\n");                                                  xbee_logEf(); }

#define xbee_logS(...)    if (xbee->log) { xbee_logSf(); xbee_logf(xbee,LOG_FORMAT"\n",__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__);               }
#define xbee_logI(...)    if (xbee->log) {               xbee_logf(xbee,LOG_FORMAT"\n",__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__);               }
#define xbee_logIc(...)   if (xbee->log) {               xbee_logf(xbee,LOG_FORMAT    ,__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__);               }
#define xbee_logIcf()     if (xbee->log) {               fprintf(xbee->log, "\n");                                                                }
#define xbee_logE(...)    if (xbee->log) {               xbee_logf(xbee,LOG_FORMAT"\n",__FILE__,__LINE__,__FUNCTION__,__VA_ARGS__); xbee_logEf(); }

#define xbee_perror(str)                                 \
  if (xbee->log) xbee_logI("%s:%s",str,strerror(errno)); \
  perror(str);

static int xbee_startAPI(xbee_hnd xbee);

static int xbee_sendAT(xbee_hnd xbee, char *command, char *retBuf, int retBuflen);
static int xbee_sendATdelay(xbee_hnd xbee, int guardTime, char *command, char *retBuf, int retBuflen);

static int xbee_parse_io(xbee_hnd xbee, xbee_pkt *p, unsigned char *d,
                         int maskOffset, int sampleOffset, int sample);

static void xbee_thread_watch(xbee_hnd xbee);
static void xbee_listen_wrapper(xbee_hnd xbee);
static int xbee_listen(xbee_hnd xbee);
static unsigned char xbee_getbyte(xbee_hnd xbee);
static unsigned char xbee_getrawbyte(xbee_hnd xbee);
static int xbee_matchpktcon(xbee_hnd xbee, xbee_pkt *pkt, xbee_con *con);

static t_data *xbee_make_pkt(xbee_hnd xbee, unsigned char *data, int len);
static int _xbee_send_pkt(xbee_hnd xbee, t_data *pkt, xbee_con *con);
static void xbee_callbackWrapper(t_CBinfo *info);

/* these functions can be found in the xsys files */
static int init_serial(xbee_hnd xbee, int baudrate);
static int xbee_select(xbee_hnd xbee, struct timeval *timeout);

#ifdef __GNUC__ /* ---- */
#include "xsys/linux.c"
#else /* -------------- */
#include "xsys\win32.c"
#endif /* ------------- */

#ifndef Win32Message
#define Win32Message()
#endif

#define ISREADY(a)      if (!xbee || !xbee->xbee_ready) {                                       \
                          if (stderr) fprintf(stderr,"libxbee: Run xbee_setup() first!...\n");  \
                          Win32Message();                                                       \
                          a;                                                                    \
                        }
#define ISREADYP()      ISREADY(return)
#define ISREADYR(a)     ISREADY(return a)