You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
8.0 KiB
254 lines
8.0 KiB
/* |
|
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)
|
|
|