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)