2 * Copyright (c) 2011, Olivier MATZ <zer0@droids-corp.org>
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the University of California, Berkeley nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <sys/types.h>
34 #include <sys/queue.h>
40 #include "xbee_neighbor.h"
41 #include "xbee_stats.h"
43 #include "xbee_proto.h"
51 static int xbee_settermios(struct xbee_dev *dev)
55 memset(&term, 0, sizeof(term));
56 term.c_cflag = CREAD | HUPCL;
59 case 50: term.c_cflag |= B50; break;
60 case 75: term.c_cflag |= B75; break;
61 case 110: term.c_cflag |= B110; break;
62 case 134: term.c_cflag |= B134; break;
63 case 150: term.c_cflag |= B150; break;
64 case 200: term.c_cflag |= B200; break;
65 case 300: term.c_cflag |= B300; break;
66 case 600: term.c_cflag |= B600; break;
67 case 1200: term.c_cflag |= B1200; break;
68 case 1800: term.c_cflag |= B1800; break;
69 case 2400: term.c_cflag |= B2400; break;
70 case 4800: term.c_cflag |= B4800; break;
71 case 9600: term.c_cflag |= B9600; break;
72 case 19200: term.c_cflag |= B19200; break;
73 case 38400: term.c_cflag |= B38400; break;
74 case 57600: term.c_cflag |= B57600; break;
75 case 115200: term.c_cflag |= B115200; break;
76 case 230400: term.c_cflag |= B230400; break;
78 fprintf(stderr, "invalid baudrate\n");
82 /* ignore modem control lines */
83 term.c_cflag |= CLOCAL;
85 /* non-canonical mode */
86 term.c_lflag &= ~ICANON;
88 /* minimum number of chars and minimum timeout for non-canonical read */
94 switch (dev->parity) {
95 case PARITY_ODD: term.c_cflag |= PARENB | PARODD; break;
96 case PARITY_EVEN: term.c_cflag |= PARENB; break;
101 term.c_cflag |= CSTOPB;
104 term.c_iflag |= IXON | IXOFF;
106 term.c_cflag |= CRTSCTS;
110 if (tcsetattr(dev->fd, TCSAFLUSH, &term) < 0) {
111 fprintf(stderr, "ERROR: tcsetattr(TCSAFLUSH) failed: %s\n",
118 int xbee_register_channel(struct xbee_dev *dev, int channel,
119 xbee_rx_cb_t *rx_cb, void *opaque)
121 /* user asked for any channel */
122 if (channel == XBEE_CHANNEL_ANY) {
125 /* skip XBEE_DEFAULT_CHANNEL == 0 */
126 for (ch = 1; ch < XBEE_MAX_CHANNEL; ch++) {
127 if (dev->channel[ch].registered == 0) {
132 /* no available channels */
133 if (channel == XBEE_CHANNEL_ANY)
136 /* user requested a specific channel */
137 else if (channel < 0 || channel >= XBEE_MAX_CHANNEL ||
138 dev->channel[channel].registered == 1)
139 return -1; /* not available */
141 dev->channel[channel].registered = 1;
142 dev->channel[channel].rx_cb = rx_cb;
143 dev->channel[channel].arg = opaque;
147 int xbee_unregister_channel(struct xbee_dev *dev, int channel)
149 if (channel < 0 || channel >= XBEE_MAX_CHANNEL ||
150 dev->channel[channel].registered == 0)
152 dev->channel[channel].registered = 0;
153 dev->channel[channel].rx_cb = NULL;
154 dev->channel[channel].arg = NULL;
158 struct xbee_dev *xbee_open(const char *devname, unsigned baudrate)
160 struct xbee_dev *dev;
163 /* allocate structure for xbee device */
164 dev = malloc(sizeof(*dev));
166 fprintf(stderr, "not enough memory\n");
169 memset(dev, 0, sizeof(*dev));
171 /* open the serial port */
172 fd = open(devname, O_NONBLOCK|O_RDWR);
174 fprintf(stderr, "cannot open %s: %s\n", devname,
181 dev->baud = baudrate;
183 if (xbee_settermios(dev) < 0) {
189 dev->name = strdup(devname);
190 xbee_bufq_init(&dev->queue);
191 xbee_neigh_init(dev);
196 /* read data from device fd and put it in queue */
197 int xbee_read(struct xbee_dev *dev)
199 struct xbee_buf *xbuf;
200 int n, tailroom, total = 0;
204 /* get an xbuf to store data */
205 xbuf = xbee_bufq_last(&dev->queue);
206 if (xbuf == NULL || xbee_buf_tailroom(xbuf) == 0) {
207 xbuf = xbee_buf_alloc();
210 fprintf(stderr, "FATAL: cannot allocate buffer\n");
214 /* put the xbuf in queue */
215 xbee_buf_enqueue(&dev->queue, xbuf);
218 /* read data from char device */
219 tailroom = xbee_buf_tailroom(xbuf);
220 data = xbee_buf_tail(xbuf);
221 n = read(dev->fd, data, tailroom);
225 fprintf(stderr, "read() failed: %s\n", strerror(errno));
229 /* update queue len and xbuf len */
230 xbee_bufq_append(&dev->queue, n);
234 } while (n == tailroom);
239 /* process all data in queue */
240 int xbee_process_queue(struct xbee_dev *dev)
242 char buf[XBEE_MAX_FRAME_LEN];
246 len = xbee_proto_get_frame(dev, buf, sizeof(buf));
247 if (len == 0) /* no more frame */
251 /* a frame was dropped... */
252 fprintf(stderr, "xbee_proto_get_frame() failed\n");
256 ret = xbee_proto_parse_frame(dev, buf, len);
258 fprintf(stderr, "xbee_proto_parse_frame() failed\n");