1 /* $NetBSD: btattach.c,v 1.4 2009/12/06 12:47:37 kiyohara Exp $ */
4 * Copyright (c) 2008 Iain Hibbert
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/cdefs.h>
29 __COPYRIGHT("@(#) Copyright (c) 2008 Iain Hibbert. All rights reserved.");
30 __RCSID("$NetBSD: btattach.c,v 1.4 2009/12/06 12:47:37 kiyohara Exp $");
32 #include <sys/ioctl.h>
33 #include <sys/param.h>
36 #include <bluetooth.h>
49 static void sighandler(int);
50 static void usage(void);
52 static int sigcount
= 0; /* signals received */
53 static int opt_debug
= 0; /* global? */
55 const struct devtype types
[] = {
59 .descr
= "Generic BlueCore Serial Protocol",
66 .descr
= "Broadcom BCM2035",
67 .init
= &init_bcm2035
,
73 .descr
= "Philips BGB2xx module",
81 .descr
= "Generic UART (the default)",
86 .descr
= "CSR Casira serial adaptor",
94 .descr
= "Digianswer based cards",
102 .descr
= "Ericsson based modules",
103 .init
= &init_ericsson
,
110 .descr
= "ST Microelectronics minikits based on STLC2410/STLC2415",
117 .descr
= "ST Microelectronics minikits based on STLC2500",
118 .init
= &init_stlc2500
,
125 .descr
= "Silicon Wave kits",
133 .descr
= "Texas Instruments",
140 .descr
= "Infineon UniStone",
141 .init
= &init_unistone
,
148 main(int argc
, char *argv
[])
150 const struct devtype
*type
;
152 unsigned int init_speed
, speed
;
162 while ((ch
= getopt(argc
, argv
, "dfi:op")) != -1) {
173 init_speed
= strtoul(optarg
, &ptr
, 10);
175 errx(EXIT_FAILURE
, "invalid speed: %s", optarg
);
180 cflag
|= (PARENB
| PARODD
);
202 if (i
== __arraycount(types
))
203 errx(EXIT_FAILURE
, "unknown type: %s", name
);
206 if (strcasecmp(type
->name
, name
) == 0)
213 /* parse tty speed */
214 speed
= strtoul(argv
[1], &ptr
, 10);
216 errx(EXIT_FAILURE
, "invalid speed: %s", argv
[1]);
219 init_speed
= (type
->speed
? type
->speed
: speed
);
222 if ((fd
= open(argv
[0], O_RDWR
| O_EXLOCK
, 0)) < 0)
223 err(EXIT_FAILURE
, "%s", argv
[0]);
226 if (tcgetattr(fd
, &tio
) < 0)
227 err(EXIT_FAILURE
, "tcgetattr");
230 tio
.c_cflag
|= (cflag
| type
->cflag
);
232 if (cfsetspeed(&tio
, init_speed
) < 0
233 || tcsetattr(fd
, TCSANOW
, &tio
) < 0
234 || tcflush(fd
, TCIOFLUSH
) < 0)
235 err(EXIT_FAILURE
, "tty setup failed");
237 /* initialize device */
238 if (type
->init
!= NULL
)
239 (*type
->init
)(fd
, speed
);
241 if (cfsetspeed(&tio
, speed
) < 0
242 || tcsetattr(fd
, TCSADRAIN
, &tio
) < 0)
243 err(EXIT_FAILURE
, "tty setup failed");
245 /* start line discipline */
246 if (ioctl(fd
, TIOCSLINED
, type
->line
) < 0)
247 err(EXIT_FAILURE
, "%s", type
->line
);
249 if (opt_debug
== 0 && daemon(0, 0) < 0)
250 warn("detach failed!");
252 /* store PID in "/var/run/btattach-{tty}.pid" */
253 ptr
= strrchr(argv
[0], '/');
254 asprintf(&ptr
, "%s-%s", getprogname(), (ptr
? ptr
+ 1 : argv
[0]));
255 if (ptr
== NULL
|| pidfile(ptr
) < 0)
260 (void)signal(SIGHUP
, sighandler
);
261 (void)signal(SIGINT
, sighandler
);
262 (void)signal(SIGTERM
, sighandler
);
263 (void)signal(SIGTSTP
, sighandler
);
264 (void)signal(SIGUSR1
, sighandler
);
265 (void)signal(SIGUSR2
, sighandler
);
267 while (sigcount
== 0)
268 select(0, NULL
, NULL
, NULL
, NULL
);
279 "Usage: %s [-dfop] [-i speed] [type] tty speed\n"
282 "\t-d debug mode (no detach, dump io)\n"
283 "\t-f enable flow control\n"
284 "\t-i speed init speed\n"
291 for (i
= 0; i
< __arraycount(types
); i
++)
292 fprintf(stderr
, "\t%-12s%s\n", types
[i
].name
, types
[i
].descr
);
305 hexdump(uint8_t *ptr
, size_t len
)
309 printf(" %2.2x", *ptr
++);
316 uart_send_cmd(int fd
, uint16_t opcode
, void *buf
, size_t len
)
321 hdr
.type
= HCI_CMD_PKT
;
322 hdr
.opcode
= htole16(opcode
);
325 iov
[0].iov_base
= &hdr
;
326 iov
[0].iov_len
= sizeof(hdr
);
327 iov
[1].iov_base
= buf
;
328 iov
[1].iov_len
= len
;
332 hexdump(iov
[0].iov_base
, iov
[0].iov_len
);
333 hexdump(iov
[1].iov_base
, iov
[1].iov_len
);
338 if (writev(fd
, iov
, __arraycount(iov
)) < 0)
339 err(EXIT_FAILURE
, "writev");
346 * store in iovec and inc counter if it fits
349 uart_getc(int fd
, struct iovec
*iov
, int ioc
, size_t *count
)
355 n
= read(fd
, &ch
, sizeof(ch
));
357 err(EXIT_FAILURE
, "read");
360 errx(EXIT_FAILURE
, "eof");
363 printf(" %2.2x", ch
);
367 if (iov
->iov_len
> off
) {
383 * read next packet, storing into iovec
386 uart_recv_pkt(int fd
, struct iovec
*iov
, int ioc
)
395 type
= uart_getc(fd
, iov
, ioc
, &count
);
398 (void)uart_getc(fd
, iov
, ioc
, &count
); /* event */
399 want
= uart_getc(fd
, iov
, ioc
, &count
);
402 case HCI_ACL_DATA_PKT
:
403 (void)uart_getc(fd
, iov
, ioc
, &count
); /* handle LSB */
404 (void)uart_getc(fd
, iov
, ioc
, &count
); /* handle MSB */
405 want
= uart_getc(fd
, iov
, ioc
, &count
) | /* LSB */
406 uart_getc(fd
, iov
, ioc
, &count
) << 8; /* MSB */
409 case HCI_SCO_DATA_PKT
:
410 (void)uart_getc(fd
, iov
, ioc
, &count
); /* handle LSB */
411 (void)uart_getc(fd
, iov
, ioc
, &count
); /* handle MSB */
412 want
= uart_getc(fd
, iov
, ioc
, &count
);
415 default: /* out of sync? */
416 errx(EXIT_FAILURE
, "unknown packet type 0x%2.2x\n", type
);
420 (void)uart_getc(fd
, iov
, ioc
, &count
);
429 * read next matching event packet to buffer
432 uart_recv_ev(int fd
, uint8_t event
, void *buf
, size_t len
)
438 iov
[0].iov_base
= &hdr
;
439 iov
[0].iov_len
= sizeof(hdr
);
440 iov
[1].iov_base
= buf
;
441 iov
[1].iov_len
= len
;
444 n
= uart_recv_pkt(fd
, iov
, __arraycount(iov
));
446 || hdr
.type
!= HCI_EVENT_PKT
447 || hdr
.event
!= event
)
458 * read next matching command_complete event to buffer
461 uart_recv_cc(int fd
, uint16_t opcode
, void *buf
, size_t len
)
465 hci_command_compl_ep cc
;
468 iov
[0].iov_base
= &hdr
;
469 iov
[0].iov_len
= sizeof(hdr
);
470 iov
[1].iov_base
= &cc
;
471 iov
[1].iov_len
= sizeof(cc
);
472 iov
[2].iov_base
= buf
;
473 iov
[2].iov_len
= len
;
476 n
= uart_recv_pkt(fd
, iov
, __arraycount(iov
));
478 || hdr
.type
!= HCI_EVENT_PKT
479 || hdr
.event
!= HCI_EVENT_COMMAND_COMPL
)
484 || cc
.opcode
!= htole16(opcode
))