btattach.c revision 1.12 1 1.12 joerg /* $NetBSD: btattach.c,v 1.12 2011/08/27 22:17:53 joerg Exp $ */
2 1.1 plunky
3 1.1 plunky /*-
4 1.1 plunky * Copyright (c) 2008 Iain Hibbert
5 1.1 plunky * All rights reserved.
6 1.1 plunky *
7 1.1 plunky * Redistribution and use in source and binary forms, with or without
8 1.1 plunky * modification, are permitted provided that the following conditions
9 1.1 plunky * are met:
10 1.1 plunky * 1. Redistributions of source code must retain the above copyright
11 1.1 plunky * notice, this list of conditions and the following disclaimer.
12 1.1 plunky * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 plunky * notice, this list of conditions and the following disclaimer in the
14 1.1 plunky * documentation and/or other materials provided with the distribution.
15 1.1 plunky *
16 1.1 plunky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.1 plunky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.1 plunky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.1 plunky * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.1 plunky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 1.1 plunky * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 1.1 plunky * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 1.1 plunky * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1.1 plunky * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 1.1 plunky * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1.1 plunky */
27 1.1 plunky
28 1.1 plunky #include <sys/cdefs.h>
29 1.2 lukem __COPYRIGHT("@(#) Copyright (c) 2008 Iain Hibbert. All rights reserved.");
30 1.12 joerg __RCSID("$NetBSD: btattach.c,v 1.12 2011/08/27 22:17:53 joerg Exp $");
31 1.1 plunky
32 1.1 plunky #include <sys/ioctl.h>
33 1.1 plunky #include <sys/param.h>
34 1.1 plunky #include <sys/uio.h>
35 1.1 plunky
36 1.1 plunky #include <bluetooth.h>
37 1.1 plunky #include <err.h>
38 1.1 plunky #include <errno.h>
39 1.1 plunky #include <fcntl.h>
40 1.1 plunky #include <stdio.h>
41 1.1 plunky #include <stdlib.h>
42 1.1 plunky #include <string.h>
43 1.1 plunky #include <termios.h>
44 1.1 plunky #include <unistd.h>
45 1.1 plunky #include <util.h>
46 1.1 plunky
47 1.1 plunky #include "btattach.h"
48 1.1 plunky
49 1.1 plunky static void sighandler(int);
50 1.12 joerg __dead static void usage(void);
51 1.8 kiyohara static void test(const char *, tcflag_t, tcflag_t);
52 1.1 plunky
53 1.1 plunky static int sigcount = 0; /* signals received */
54 1.1 plunky static int opt_debug = 0; /* global? */
55 1.1 plunky
56 1.12 joerg static const struct devtype types[] = {
57 1.1 plunky {
58 1.6 plunky .name = "bcm2035",
59 1.6 plunky .line = "btuart",
60 1.6 plunky .descr = "Broadcom BCM2035",
61 1.6 plunky .init = &init_bcm2035,
62 1.6 plunky .speed = B115200,
63 1.6 plunky },
64 1.6 plunky {
65 1.1 plunky .name = "bcsp",
66 1.1 plunky .line = "bcsp",
67 1.1 plunky .descr = "Generic BlueCore Serial Protocol",
68 1.7 kiyohara .cflag = CRTSCTS | PARENB,
69 1.1 plunky .speed = B57600,
70 1.1 plunky },
71 1.1 plunky {
72 1.1 plunky .name = "bgb2xx",
73 1.1 plunky .line = "btuart",
74 1.1 plunky .descr = "Philips BGB2xx module",
75 1.1 plunky .init = &init_bgb2xx,
76 1.1 plunky .cflag = CRTSCTS,
77 1.1 plunky .speed = B115200,
78 1.1 plunky },
79 1.1 plunky {
80 1.1 plunky .name = "btuart",
81 1.1 plunky .line = "btuart",
82 1.1 plunky .descr = "Generic UART (the default)",
83 1.1 plunky },
84 1.1 plunky {
85 1.1 plunky .name = "csr",
86 1.1 plunky .line = "btuart",
87 1.6 plunky .descr = "Cambridge Silicon Radio based modules (not BCSP)",
88 1.1 plunky .init = &init_csr,
89 1.1 plunky .cflag = CRTSCTS,
90 1.1 plunky .speed = B57600,
91 1.1 plunky },
92 1.1 plunky {
93 1.1 plunky .name = "digi",
94 1.1 plunky .line = "btuart",
95 1.1 plunky .descr = "Digianswer based cards",
96 1.1 plunky .init = &init_digi,
97 1.1 plunky .cflag = CRTSCTS,
98 1.1 plunky .speed = B9600,
99 1.1 plunky },
100 1.1 plunky {
101 1.1 plunky .name = "ericsson",
102 1.1 plunky .line = "btuart",
103 1.1 plunky .descr = "Ericsson based modules",
104 1.1 plunky .init = &init_ericsson,
105 1.1 plunky .cflag = CRTSCTS,
106 1.1 plunky .speed = B57600,
107 1.1 plunky },
108 1.1 plunky {
109 1.1 plunky .name = "st",
110 1.1 plunky .line = "btuart",
111 1.1 plunky .descr = "ST Microelectronics minikits based on STLC2410/STLC2415",
112 1.1 plunky .init = &init_st,
113 1.1 plunky .cflag = CRTSCTS,
114 1.1 plunky .speed = B57600,
115 1.1 plunky },
116 1.1 plunky {
117 1.1 plunky .name = "stlc2500",
118 1.1 plunky .descr = "ST Microelectronics minikits based on STLC2500",
119 1.1 plunky .init = &init_stlc2500,
120 1.1 plunky .cflag = CRTSCTS,
121 1.1 plunky .speed = B115200,
122 1.1 plunky },
123 1.1 plunky {
124 1.1 plunky .name = "swave",
125 1.1 plunky .line = "btuart",
126 1.1 plunky .descr = "Silicon Wave kits",
127 1.1 plunky .init = &init_swave,
128 1.1 plunky .cflag = CRTSCTS,
129 1.1 plunky .speed = B57600,
130 1.1 plunky },
131 1.1 plunky {
132 1.1 plunky .name = "texas",
133 1.1 plunky .line = "btuart",
134 1.1 plunky .descr = "Texas Instruments",
135 1.1 plunky .cflag = CRTSCTS,
136 1.1 plunky .speed = B115200,
137 1.1 plunky },
138 1.5 kiyohara {
139 1.5 kiyohara .name = "unistone",
140 1.5 kiyohara .line = "btuart",
141 1.5 kiyohara .descr = "Infineon UniStone",
142 1.5 kiyohara .init = &init_unistone,
143 1.5 kiyohara .cflag = CRTSCTS,
144 1.5 kiyohara .speed = B115200,
145 1.5 kiyohara },
146 1.1 plunky };
147 1.1 plunky
148 1.1 plunky int
149 1.1 plunky main(int argc, char *argv[])
150 1.1 plunky {
151 1.1 plunky const struct devtype *type;
152 1.1 plunky struct termios tio;
153 1.1 plunky unsigned int init_speed, speed;
154 1.7 kiyohara tcflag_t cflag, Cflag;
155 1.8 kiyohara int fd, ch, tflag, i;
156 1.1 plunky const char *name;
157 1.1 plunky char *ptr;
158 1.1 plunky
159 1.1 plunky init_speed = 0;
160 1.1 plunky cflag = CLOCAL;
161 1.7 kiyohara Cflag = 0;
162 1.8 kiyohara tflag = 0;
163 1.1 plunky name = "btuart";
164 1.1 plunky
165 1.8 kiyohara while ((ch = getopt(argc, argv, "dFfi:oPpt")) != -1) {
166 1.1 plunky switch (ch) {
167 1.1 plunky case 'd':
168 1.1 plunky opt_debug++;
169 1.1 plunky break;
170 1.1 plunky
171 1.7 kiyohara case 'F':
172 1.7 kiyohara Cflag |= CRTSCTS;
173 1.7 kiyohara break;
174 1.7 kiyohara
175 1.1 plunky case 'f':
176 1.1 plunky cflag |= CRTSCTS;
177 1.1 plunky break;
178 1.1 plunky
179 1.1 plunky case 'i':
180 1.1 plunky init_speed = strtoul(optarg, &ptr, 10);
181 1.1 plunky if (ptr[0] != '\0')
182 1.1 plunky errx(EXIT_FAILURE, "invalid speed: %s", optarg);
183 1.1 plunky
184 1.1 plunky break;
185 1.1 plunky
186 1.1 plunky case 'o':
187 1.1 plunky cflag |= (PARENB | PARODD);
188 1.1 plunky break;
189 1.1 plunky
190 1.7 kiyohara case 'P':
191 1.7 kiyohara Cflag |= PARENB;
192 1.7 kiyohara break;
193 1.7 kiyohara
194 1.1 plunky case 'p':
195 1.1 plunky cflag |= PARENB;
196 1.1 plunky break;
197 1.1 plunky
198 1.8 kiyohara case 't':
199 1.8 kiyohara tflag = 1;
200 1.8 kiyohara break;
201 1.8 kiyohara
202 1.1 plunky case '?':
203 1.1 plunky default:
204 1.1 plunky usage();
205 1.1 plunky }
206 1.1 plunky }
207 1.1 plunky argc -= optind;
208 1.1 plunky argv += optind;
209 1.1 plunky
210 1.8 kiyohara if (tflag) {
211 1.8 kiyohara if (argc != 1)
212 1.8 kiyohara usage();
213 1.8 kiyohara test(argv[0], cflag, Cflag);
214 1.8 kiyohara exit(EXIT_SUCCESS);
215 1.8 kiyohara }
216 1.8 kiyohara
217 1.1 plunky if (argc == 3) {
218 1.1 plunky name = argv[0];
219 1.1 plunky argv++;
220 1.1 plunky argc--;
221 1.1 plunky }
222 1.1 plunky
223 1.1 plunky for (i = 0; ; i++) {
224 1.1 plunky if (i == __arraycount(types))
225 1.1 plunky errx(EXIT_FAILURE, "unknown type: %s", name);
226 1.1 plunky
227 1.1 plunky type = &types[i];
228 1.1 plunky if (strcasecmp(type->name, name) == 0)
229 1.1 plunky break;
230 1.1 plunky }
231 1.1 plunky
232 1.1 plunky if (argc != 2)
233 1.1 plunky usage();
234 1.1 plunky
235 1.1 plunky /* parse tty speed */
236 1.1 plunky speed = strtoul(argv[1], &ptr, 10);
237 1.1 plunky if (ptr[0] != '\0')
238 1.1 plunky errx(EXIT_FAILURE, "invalid speed: %s", argv[1]);
239 1.1 plunky
240 1.1 plunky if (init_speed == 0)
241 1.1 plunky init_speed = (type->speed ? type->speed : speed);
242 1.1 plunky
243 1.1 plunky /* open tty */
244 1.4 kiyohara if ((fd = open(argv[0], O_RDWR | O_EXLOCK, 0)) < 0)
245 1.1 plunky err(EXIT_FAILURE, "%s", argv[0]);
246 1.1 plunky
247 1.1 plunky /* setup tty */
248 1.1 plunky if (tcgetattr(fd, &tio) < 0)
249 1.1 plunky err(EXIT_FAILURE, "tcgetattr");
250 1.1 plunky
251 1.1 plunky cfmakeraw(&tio);
252 1.1 plunky tio.c_cflag |= (cflag | type->cflag);
253 1.7 kiyohara tio.c_cflag &= ~Cflag;
254 1.1 plunky
255 1.1 plunky if (cfsetspeed(&tio, init_speed) < 0
256 1.1 plunky || tcsetattr(fd, TCSANOW, &tio) < 0
257 1.1 plunky || tcflush(fd, TCIOFLUSH) < 0)
258 1.1 plunky err(EXIT_FAILURE, "tty setup failed");
259 1.1 plunky
260 1.1 plunky /* initialize device */
261 1.1 plunky if (type->init != NULL)
262 1.1 plunky (*type->init)(fd, speed);
263 1.1 plunky
264 1.1 plunky if (cfsetspeed(&tio, speed) < 0
265 1.1 plunky || tcsetattr(fd, TCSADRAIN, &tio) < 0)
266 1.1 plunky err(EXIT_FAILURE, "tty setup failed");
267 1.1 plunky
268 1.1 plunky /* start line discipline */
269 1.1 plunky if (ioctl(fd, TIOCSLINED, type->line) < 0)
270 1.1 plunky err(EXIT_FAILURE, "%s", type->line);
271 1.1 plunky
272 1.1 plunky if (opt_debug == 0 && daemon(0, 0) < 0)
273 1.1 plunky warn("detach failed!");
274 1.1 plunky
275 1.1 plunky /* store PID in "/var/run/btattach-{tty}.pid" */
276 1.1 plunky ptr = strrchr(argv[0], '/');
277 1.1 plunky asprintf(&ptr, "%s-%s", getprogname(), (ptr ? ptr + 1 : argv[0]));
278 1.1 plunky if (ptr == NULL || pidfile(ptr) < 0)
279 1.1 plunky warn("no pidfile");
280 1.1 plunky
281 1.1 plunky free(ptr);
282 1.1 plunky
283 1.1 plunky (void)signal(SIGHUP, sighandler);
284 1.1 plunky (void)signal(SIGINT, sighandler);
285 1.1 plunky (void)signal(SIGTERM, sighandler);
286 1.1 plunky (void)signal(SIGTSTP, sighandler);
287 1.1 plunky (void)signal(SIGUSR1, sighandler);
288 1.1 plunky (void)signal(SIGUSR2, sighandler);
289 1.1 plunky
290 1.1 plunky while (sigcount == 0)
291 1.1 plunky select(0, NULL, NULL, NULL, NULL);
292 1.1 plunky
293 1.1 plunky return EXIT_SUCCESS;
294 1.1 plunky }
295 1.1 plunky
296 1.1 plunky static void
297 1.1 plunky usage(void)
298 1.1 plunky {
299 1.3 lukem size_t i;
300 1.1 plunky
301 1.1 plunky fprintf(stderr,
302 1.7 kiyohara "Usage: %s [-dFfoPp] [-i speed] [type] tty speed\n"
303 1.8 kiyohara " %s -t [-dFfoPp] tty\n"
304 1.1 plunky "\n"
305 1.1 plunky "Where:\n"
306 1.1 plunky "\t-d debug mode (no detach, dump io)\n"
307 1.7 kiyohara "\t-F disable flow control\n"
308 1.1 plunky "\t-f enable flow control\n"
309 1.1 plunky "\t-i speed init speed\n"
310 1.1 plunky "\t-o odd parity\n"
311 1.7 kiyohara "\t-P no parity\n"
312 1.1 plunky "\t-p even parity\n"
313 1.8 kiyohara "\t-t test mode\n"
314 1.1 plunky "\n"
315 1.1 plunky "Known types:\n"
316 1.8 kiyohara "", getprogname(), getprogname());
317 1.1 plunky
318 1.1 plunky for (i = 0; i < __arraycount(types); i++)
319 1.1 plunky fprintf(stderr, "\t%-12s%s\n", types[i].name, types[i].descr);
320 1.1 plunky
321 1.1 plunky exit(EXIT_FAILURE);
322 1.1 plunky }
323 1.1 plunky
324 1.1 plunky static void
325 1.1 plunky sighandler(int s)
326 1.1 plunky {
327 1.1 plunky
328 1.1 plunky sigcount++;
329 1.1 plunky }
330 1.1 plunky
331 1.1 plunky static void
332 1.1 plunky hexdump(uint8_t *ptr, size_t len)
333 1.1 plunky {
334 1.11 kiyohara
335 1.1 plunky while (len--)
336 1.1 plunky printf(" %2.2x", *ptr++);
337 1.1 plunky }
338 1.1 plunky
339 1.1 plunky /*
340 1.1 plunky * send HCI comamnd
341 1.1 plunky */
342 1.1 plunky void
343 1.1 plunky uart_send_cmd(int fd, uint16_t opcode, void *buf, size_t len)
344 1.1 plunky {
345 1.1 plunky struct iovec iov[2];
346 1.1 plunky hci_cmd_hdr_t hdr;
347 1.1 plunky
348 1.1 plunky hdr.type = HCI_CMD_PKT;
349 1.1 plunky hdr.opcode = htole16(opcode);
350 1.1 plunky hdr.length = len;
351 1.1 plunky
352 1.1 plunky iov[0].iov_base = &hdr;
353 1.1 plunky iov[0].iov_len = sizeof(hdr);
354 1.1 plunky iov[1].iov_base = buf;
355 1.1 plunky iov[1].iov_len = len;
356 1.1 plunky
357 1.1 plunky if (opt_debug) {
358 1.1 plunky printf("<<");
359 1.1 plunky hexdump(iov[0].iov_base, iov[0].iov_len);
360 1.1 plunky hexdump(iov[1].iov_base, iov[1].iov_len);
361 1.1 plunky printf("\n");
362 1.1 plunky fflush(stdout);
363 1.1 plunky }
364 1.1 plunky
365 1.1 plunky if (writev(fd, iov, __arraycount(iov)) < 0)
366 1.1 plunky err(EXIT_FAILURE, "writev");
367 1.1 plunky
368 1.1 plunky tcdrain(fd);
369 1.1 plunky }
370 1.1 plunky
371 1.1 plunky /*
372 1.1 plunky * get next character
373 1.1 plunky * store in iovec and inc counter if it fits
374 1.1 plunky */
375 1.1 plunky static uint8_t
376 1.1 plunky uart_getc(int fd, struct iovec *iov, int ioc, size_t *count)
377 1.1 plunky {
378 1.1 plunky uint8_t ch, *b;
379 1.1 plunky ssize_t n;
380 1.1 plunky size_t off;
381 1.1 plunky
382 1.1 plunky n = read(fd, &ch, sizeof(ch));
383 1.1 plunky if (n < 0)
384 1.1 plunky err(EXIT_FAILURE, "read");
385 1.1 plunky
386 1.1 plunky if (n == 0)
387 1.1 plunky errx(EXIT_FAILURE, "eof");
388 1.1 plunky
389 1.1 plunky if (opt_debug)
390 1.1 plunky printf(" %2.2x", ch);
391 1.1 plunky
392 1.1 plunky off = *count;
393 1.1 plunky while (ioc > 0) {
394 1.1 plunky if (iov->iov_len > off) {
395 1.1 plunky b = iov->iov_base;
396 1.1 plunky b[off] = ch;
397 1.1 plunky *count += 1;
398 1.1 plunky break;
399 1.1 plunky }
400 1.1 plunky
401 1.1 plunky off -= iov->iov_len;
402 1.1 plunky iov++;
403 1.1 plunky ioc--;
404 1.1 plunky }
405 1.1 plunky
406 1.1 plunky return ch;
407 1.1 plunky }
408 1.1 plunky
409 1.1 plunky /*
410 1.1 plunky * read next packet, storing into iovec
411 1.1 plunky */
412 1.1 plunky static size_t
413 1.1 plunky uart_recv_pkt(int fd, struct iovec *iov, int ioc)
414 1.1 plunky {
415 1.1 plunky size_t count, want;
416 1.1 plunky uint8_t type;
417 1.1 plunky
418 1.1 plunky if (opt_debug)
419 1.1 plunky printf(">>");
420 1.1 plunky
421 1.1 plunky count = 0;
422 1.1 plunky type = uart_getc(fd, iov, ioc, &count);
423 1.1 plunky switch(type) {
424 1.1 plunky case HCI_EVENT_PKT:
425 1.1 plunky (void)uart_getc(fd, iov, ioc, &count); /* event */
426 1.4 kiyohara want = uart_getc(fd, iov, ioc, &count);
427 1.1 plunky break;
428 1.1 plunky
429 1.1 plunky case HCI_ACL_DATA_PKT:
430 1.1 plunky (void)uart_getc(fd, iov, ioc, &count); /* handle LSB */
431 1.1 plunky (void)uart_getc(fd, iov, ioc, &count); /* handle MSB */
432 1.4 kiyohara want = uart_getc(fd, iov, ioc, &count) | /* LSB */
433 1.4 kiyohara uart_getc(fd, iov, ioc, &count) << 8; /* MSB */
434 1.1 plunky break;
435 1.1 plunky
436 1.1 plunky case HCI_SCO_DATA_PKT:
437 1.1 plunky (void)uart_getc(fd, iov, ioc, &count); /* handle LSB */
438 1.1 plunky (void)uart_getc(fd, iov, ioc, &count); /* handle MSB */
439 1.4 kiyohara want = uart_getc(fd, iov, ioc, &count);
440 1.1 plunky break;
441 1.1 plunky
442 1.1 plunky default: /* out of sync? */
443 1.4 kiyohara errx(EXIT_FAILURE, "unknown packet type 0x%2.2x\n", type);
444 1.1 plunky }
445 1.1 plunky
446 1.1 plunky while (want-- > 0)
447 1.1 plunky (void)uart_getc(fd, iov, ioc, &count);
448 1.1 plunky
449 1.1 plunky if (opt_debug)
450 1.1 plunky printf("\n");
451 1.1 plunky
452 1.1 plunky return count;
453 1.1 plunky }
454 1.1 plunky
455 1.1 plunky /*
456 1.1 plunky * read next matching event packet to buffer
457 1.1 plunky */
458 1.1 plunky size_t
459 1.1 plunky uart_recv_ev(int fd, uint8_t event, void *buf, size_t len)
460 1.1 plunky {
461 1.1 plunky struct iovec iov[2];
462 1.1 plunky hci_event_hdr_t hdr;
463 1.1 plunky size_t n;
464 1.1 plunky
465 1.1 plunky iov[0].iov_base = &hdr;
466 1.1 plunky iov[0].iov_len = sizeof(hdr);
467 1.1 plunky iov[1].iov_base = buf;
468 1.1 plunky iov[1].iov_len = len;
469 1.1 plunky
470 1.1 plunky for (;;) {
471 1.1 plunky n = uart_recv_pkt(fd, iov, __arraycount(iov));
472 1.1 plunky if (n < sizeof(hdr)
473 1.1 plunky || hdr.type != HCI_EVENT_PKT
474 1.1 plunky || hdr.event != event)
475 1.1 plunky continue;
476 1.1 plunky
477 1.1 plunky n -= sizeof(hdr);
478 1.1 plunky break;
479 1.1 plunky }
480 1.1 plunky
481 1.1 plunky return n;
482 1.1 plunky }
483 1.1 plunky
484 1.1 plunky /*
485 1.1 plunky * read next matching command_complete event to buffer
486 1.1 plunky */
487 1.1 plunky size_t
488 1.1 plunky uart_recv_cc(int fd, uint16_t opcode, void *buf, size_t len)
489 1.1 plunky {
490 1.1 plunky struct iovec iov[3];
491 1.1 plunky hci_event_hdr_t hdr;
492 1.1 plunky hci_command_compl_ep cc;
493 1.1 plunky size_t n;
494 1.1 plunky
495 1.1 plunky iov[0].iov_base = &hdr;
496 1.1 plunky iov[0].iov_len = sizeof(hdr);
497 1.1 plunky iov[1].iov_base = &cc;
498 1.1 plunky iov[1].iov_len = sizeof(cc);
499 1.1 plunky iov[2].iov_base = buf;
500 1.1 plunky iov[2].iov_len = len;
501 1.1 plunky
502 1.1 plunky for (;;) {
503 1.1 plunky n = uart_recv_pkt(fd, iov, __arraycount(iov));
504 1.1 plunky if (n < sizeof(hdr)
505 1.1 plunky || hdr.type != HCI_EVENT_PKT
506 1.1 plunky || hdr.event != HCI_EVENT_COMMAND_COMPL)
507 1.1 plunky continue;
508 1.1 plunky
509 1.1 plunky n -= sizeof(hdr);
510 1.1 plunky if (n < sizeof(cc)
511 1.1 plunky || cc.opcode != htole16(opcode))
512 1.1 plunky continue;
513 1.1 plunky
514 1.1 plunky n -= sizeof(cc);
515 1.1 plunky break;
516 1.1 plunky }
517 1.1 plunky
518 1.1 plunky return n;
519 1.1 plunky }
520 1.8 kiyohara
521 1.8 kiyohara static void
522 1.8 kiyohara test(const char *tty, tcflag_t cflag, tcflag_t Cflag)
523 1.8 kiyohara {
524 1.8 kiyohara struct termios tio;
525 1.9 plunky int fd, guessed;
526 1.9 plunky size_t i, j, k;
527 1.9 plunky ssize_t n;
528 1.8 kiyohara unsigned char buf[32];
529 1.8 kiyohara const int bauds[] = {
530 1.8 kiyohara 57600, /* BCSP specific default */
531 1.8 kiyohara 921600, /* latest major baud rate */
532 1.8 kiyohara 115200, /* old major baud rate */
533 1.8 kiyohara
534 1.8 kiyohara 460800,
535 1.8 kiyohara 230400,
536 1.8 kiyohara // 76800,
537 1.8 kiyohara 28800,
538 1.8 kiyohara 38400,
539 1.8 kiyohara 19200,
540 1.8 kiyohara 14400,
541 1.8 kiyohara 9600,
542 1.8 kiyohara 7200,
543 1.8 kiyohara 4800,
544 1.8 kiyohara 2400,
545 1.8 kiyohara 1800,
546 1.8 kiyohara 1200,
547 1.8 kiyohara 600,
548 1.8 kiyohara 300,
549 1.8 kiyohara 200,
550 1.8 kiyohara 150,
551 1.8 kiyohara 134,
552 1.8 kiyohara 110,
553 1.8 kiyohara 75,
554 1.8 kiyohara 50,
555 1.8 kiyohara };
556 1.8 kiyohara const unsigned char bcsp_lepkt[] =
557 1.8 kiyohara /* ESC ------- header ------- --- link establish --- ESC */
558 1.8 kiyohara { 0xc0, 0x00, 0x41, 0x00, 0xbe, 0xda, 0xdc, 0xed, 0xed, 0xc0 };
559 1.8 kiyohara
560 1.8 kiyohara printf("test mode\n");
561 1.8 kiyohara
562 1.8 kiyohara /* open tty */
563 1.8 kiyohara if ((fd = open(tty, O_RDWR | O_NONBLOCK | O_EXLOCK, 0)) < 0)
564 1.8 kiyohara err(EXIT_FAILURE, "%s", tty);
565 1.8 kiyohara
566 1.8 kiyohara /* setup tty */
567 1.8 kiyohara if (tcgetattr(fd, &tio) < 0)
568 1.8 kiyohara err(EXIT_FAILURE, "tcgetattr");
569 1.8 kiyohara cfmakeraw(&tio);
570 1.8 kiyohara tio.c_cflag |= (CLOCAL | CRTSCTS | PARENB);
571 1.8 kiyohara tio.c_cflag |= cflag;
572 1.8 kiyohara tio.c_cflag &= ~Cflag;
573 1.8 kiyohara
574 1.8 kiyohara guessed = 0;
575 1.8 kiyohara for (i = 0; i < __arraycount(bauds); i++) {
576 1.8 kiyohara if (cfsetspeed(&tio, bauds[i]) < 0
577 1.8 kiyohara || tcsetattr(fd, TCSANOW, &tio) < 0
578 1.9 plunky || tcflush(fd, TCIOFLUSH) < 0) {
579 1.8 kiyohara if (bauds[i] > 115200)
580 1.8 kiyohara continue;
581 1.8 kiyohara else
582 1.8 kiyohara err(EXIT_FAILURE, "tty setup failed");
583 1.9 plunky }
584 1.8 kiyohara
585 1.8 kiyohara if (opt_debug)
586 1.8 kiyohara printf(" try with B%d\n", bauds[i]);
587 1.8 kiyohara
588 1.8 kiyohara sleep(bauds[i] < 9600 ? 3 : 1);
589 1.8 kiyohara
590 1.8 kiyohara n = read(fd, buf, sizeof(buf));
591 1.8 kiyohara if (opt_debug > 1)
592 1.10 plunky printf(" %zd bytes read\n", n);
593 1.8 kiyohara if (n < 0) {
594 1.8 kiyohara if (i == 0 && errno == EAGAIN) {
595 1.8 kiyohara printf("This module is *maybe* supported by btuart(4).\n"
596 1.8 kiyohara "you specify aproporiate <speed>.\n"
597 1.8 kiyohara " Also can specify <type> for initialize.\n");
598 1.8 kiyohara guessed = 1;
599 1.8 kiyohara break;
600 1.8 kiyohara }
601 1.8 kiyohara if (errno == EAGAIN)
602 1.8 kiyohara continue;
603 1.8 kiyohara
604 1.8 kiyohara err(EXIT_FAILURE, "read");
605 1.8 kiyohara } else {
606 1.9 plunky if ((size_t)n < sizeof(bcsp_lepkt))
607 1.8 kiyohara continue;
608 1.8 kiyohara for (j = 0; j < n - sizeof(bcsp_lepkt); j++) {
609 1.11 kiyohara for (k = 0; k < sizeof(bcsp_lepkt); k++)
610 1.8 kiyohara if (buf[j + k] != bcsp_lepkt[k]) {
611 1.8 kiyohara j += k;
612 1.8 kiyohara break;
613 1.8 kiyohara }
614 1.8 kiyohara if (k < sizeof(bcsp_lepkt))
615 1.8 kiyohara continue;
616 1.8 kiyohara
617 1.8 kiyohara printf(
618 1.8 kiyohara "This module is supported by bcsp(4).\n"
619 1.8 kiyohara " baud rate %d\n",
620 1.8 kiyohara bauds[i]);
621 1.8 kiyohara if (tio.c_cflag & PARENB)
622 1.8 kiyohara printf(" with %sparity\n",
623 1.8 kiyohara tio.c_cflag & PARODD ? "odd " : "");
624 1.8 kiyohara guessed = 1;
625 1.8 kiyohara break;
626 1.8 kiyohara }
627 1.8 kiyohara if (guessed)
628 1.8 kiyohara break;
629 1.8 kiyohara }
630 1.8 kiyohara
631 1.8 kiyohara }
632 1.8 kiyohara
633 1.8 kiyohara close(fd);
634 1.8 kiyohara
635 1.8 kiyohara if (!guessed)
636 1.8 kiyohara printf("don't understand...\n");
637 1.8 kiyohara }
638