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