/*
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 .
*/
#include
#include
#include
#include
#include
#include
#include
#ifdef __GNUC__ /* ---- */
#include
#include
#define __USE_GNU
#include
#undef __USE_GNU
#include
#else /* -------------- */
#include
#include
#include
#include
#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)