xref: /OK3568_Linux_fs/external/rkwifibt/tools/rtk_hciattach/hciattach.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2000-2001  Qualcomm Incorporated
6  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
7  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
8  *
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23  *
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 #define _GNU_SOURCE
31 #include <stdio.h>
32 #include <errno.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <signal.h>
38 #include <syslog.h>
39 #include <termios.h>
40 #include <time.h>
41 #include <sys/time.h>
42 #include <sys/poll.h>
43 #include <sys/param.h>
44 #include <sys/ioctl.h>
45 #include <sys/socket.h>
46 #include <sys/uio.h>
47 #include <sys/timerfd.h>
48 
49 #include "hciattach.h"
50 
51 #define RFKILL_NODE	"/sys/class/rfkill/rfkill0/state"
52 
53 #ifdef NEED_PPOLL
54 #include "ppoll.h"
55 #endif
56 
57 /* #define SCHED_ENABLE */
58 
59 #ifdef SCHED_ENABLE
60 #include <sched.h>
61 #endif
62 
63 struct uart_t {
64 	char *type;
65 	int  m_id;
66 	int  p_id;
67 	int  proto;
68 	int  init_speed;
69 	int  speed;
70 	int  flags;
71 	int  pm;
72 	char *bdaddr;
73 	int  (*init) (int fd, struct uart_t *u, struct termios *ti);
74 	int  (*post) (int fd, struct uart_t *u, struct termios *ti);
75 };
76 
77 #define FLOW_CTL	0x0001
78 #define ENABLE_PM	1
79 #define DISABLE_PM	0
80 
81 static volatile sig_atomic_t __io_canceled = 0;
82 
sig_hup(int sig)83 static void sig_hup(int sig)
84 {
85 	RS_INFO("signal hup.");
86 }
87 
sig_term(int sig)88 static void sig_term(int sig)
89 {
90 	switch (sig) {
91 	case SIGINT:
92 		RS_INFO("signal int.");
93 		break;
94 	case SIGTERM:
95 		RS_INFO("signal term.");
96 		break;
97 	}
98 	__io_canceled = 1;
99 }
100 
sig_alarm(int sig)101 static void sig_alarm(int sig)
102 {
103 	RS_ERR("Initialization timed out.");
104 	exit(1);
105 }
106 
uart_speed(int s)107 static int uart_speed(int s)
108 {
109 	switch (s) {
110 	case 9600:
111 		return B9600;
112 	case 19200:
113 		return B19200;
114 	case 38400:
115 		return B38400;
116 	case 57600:
117 		return B57600;
118 	case 115200:
119 		return B115200;
120 	case 230400:
121 		return B230400;
122 	case 460800:
123 		return B460800;
124 	case 500000:
125 		return B500000;
126 	case 576000:
127 		return B576000;
128 	case 921600:
129 		return B921600;
130 	case 1000000:
131 		return B1000000;
132 	case 1152000:
133 		return B1152000;
134 	case 1500000:
135 		return B1500000;
136 	case 2000000:
137 		return B2000000;
138 #ifdef B2500000
139 	case 2500000:
140 		return B2500000;
141 #endif
142 #ifdef B3000000
143 	case 3000000:
144 		return B3000000;
145 #endif
146 #ifdef B3500000
147 	case 3500000:
148 		return B3500000;
149 #endif
150 #ifdef B4000000
151 	case 4000000:
152 		return B4000000;
153 #endif
154 	default:
155 		return B57600;
156 	}
157 }
158 
set_speed(int fd,struct termios * ti,int speed)159 int set_speed(int fd, struct termios *ti, int speed)
160 {
161 	if (cfsetospeed(ti, uart_speed(speed)) < 0)
162 		return -errno;
163 
164 	if (cfsetispeed(ti, uart_speed(speed)) < 0)
165 		return -errno;
166 
167 	if (tcsetattr(fd, TCSANOW, ti) < 0)
168 		return -errno;
169 
170 	return 0;
171 }
172 
realtek_init(int fd,struct uart_t * u,struct termios * ti)173 static int realtek_init(int fd, struct uart_t *u, struct termios *ti)
174 {
175 
176 	RS_INFO("Realtek Bluetooth init uart with init speed:%d, type:HCI UART %s",
177 		u->init_speed,
178 		(u->proto == HCI_UART_H4) ? "H4" : "H5");
179 	return rtb_init(fd, u->proto, u->speed, ti);
180 }
181 
realtek_post(int fd,struct uart_t * u,struct termios * ti)182 static int realtek_post(int fd, struct uart_t *u, struct termios *ti)
183 {
184 	RS_INFO("Realtek Bluetooth post process");
185 	return rtb_post(fd, u->proto, ti);
186 }
187 
188 struct uart_t uart[] = {
189 	{ "any",     0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, DISABLE_PM, NULL, NULL},
190 
191 	/* Realtek Bluetooth H4 */
192 	{ "rtk_h4",  0x0000, 0x0000, HCI_UART_H4,  115200,  115200, 0, DISABLE_PM, NULL, realtek_init, realtek_post },
193 
194 	/* Realtek Bluetooth H5 */
195 	{ "rtk_h5",  0x0000, 0x0000, HCI_UART_3WIRE, 115200,115200, 0, DISABLE_PM, NULL, realtek_init, realtek_post },
196 
197 	{ NULL, 0 }
198 };
199 
get_by_id(int m_id,int p_id)200 static struct uart_t * get_by_id(int m_id, int p_id)
201 {
202 	int i;
203 	for (i = 0; uart[i].type; i++) {
204 		if (uart[i].m_id == m_id && uart[i].p_id == p_id)
205 			return &uart[i];
206 	}
207 	return NULL;
208 }
209 
get_by_type(char * type)210 static struct uart_t * get_by_type(char *type)
211 {
212 	int i;
213 	for (i = 0; uart[i].type; i++) {
214 		if (!strcmp(uart[i].type, type))
215 			return &uart[i];
216 	}
217 	return NULL;
218 }
219 
220 /* Initialize UART driver */
init_uart(char * dev,struct uart_t * u,int send_break,int raw)221 static int init_uart(char *dev, struct uart_t *u, int send_break, int raw)
222 {
223 	struct termios ti;
224 	int fd, i;
225 	unsigned long flags = 0;
226 
227 	if (raw)
228 		flags |= 1 << HCI_UART_RAW_DEVICE;
229 
230 	fd = open(dev, O_RDWR | O_NOCTTY);
231 	if (fd < 0) {
232 		RS_ERR("Can't open serial port, %d, %s", errno,
233 		       strerror(errno));
234 		return -1;
235 	}
236 
237 	tcflush(fd, TCIOFLUSH);
238 
239 	if (tcgetattr(fd, &ti) < 0) {
240 		RS_ERR("Can't get port settings, %d, %s", errno,
241 		       strerror(errno));
242 		return -1;
243 	}
244 
245 	cfmakeraw(&ti);
246 
247 	ti.c_cflag |= CLOCAL;
248 	if (u->flags & FLOW_CTL)
249 		ti.c_cflag |= CRTSCTS;
250 	else
251 		ti.c_cflag &= ~CRTSCTS;
252 
253 	if (tcsetattr(fd, TCSANOW, &ti) < 0) {
254 		RS_ERR("Can't set port settings, %d, %s", errno,
255 		       strerror(errno));
256 		return -1;
257 	}
258 
259 	/* Set initial baudrate */
260 	if (set_speed(fd, &ti, u->init_speed) < 0) {
261 		RS_ERR("Can't set initial baud rate, %d, %s", errno,
262 		       strerror(errno));
263 		return -1;
264 	}
265 
266 	tcflush(fd, TCIOFLUSH);
267 
268 	if (send_break) {
269 		tcsendbreak(fd, 0);
270 		usleep(500000);
271 	}
272 
273 	if (u->init && u->init(fd, u, &ti) < 0)
274 		return -1;
275 
276 	tcflush(fd, TCIOFLUSH);
277 
278 	/* Set actual baudrate
279 	 * There is no need to change baudrate after uart init
280 	 * */
281 	/* if (set_speed(fd, &ti, u->speed) < 0) {
282 	 * 	perror("Can't set baud rate");
283 	 * 	return -1;
284 	 * }
285 	 */
286 
287 	/* Set TTY to N_HCI line discipline */
288 	i = N_HCI;
289 	if (ioctl(fd, TIOCSETD, &i) < 0) {
290 		RS_ERR("Can't set line discipline %d, %s", errno,
291 		       strerror(errno));
292 		return -1;
293 	}
294 
295 	if (flags && ioctl(fd, HCIUARTSETFLAGS, flags) < 0) {
296 		RS_ERR("Can't set UART flags %d, %s", errno, strerror(errno));
297 		return -1;
298 	}
299 
300 	if (ioctl(fd, HCIUARTSETPROTO, u->proto) < 0) {
301 		RS_ERR("Can't set device %d, %s", errno, strerror(errno));
302 		return -1;
303 	}
304 
305 	if (u->post && u->post(fd, u, &ti) < 0)
306 		return -1;
307 
308 	return fd;
309 }
310 
reset_bluetooth(void)311 static int reset_bluetooth(void)
312 {
313 
314 	int fd;
315 	char state[2];
316 	int result;
317 
318 	/* power off and power on BT */
319 	fd = open(RFKILL_NODE, O_RDWR);
320 	if (fd < 0) {
321 		RS_ERR("Cannot open %s, %d %s", RFKILL_NODE, errno,
322 				strerror(errno));
323 		return -1;
324 	}
325 	state[0] = '0';
326 	state[1] = '\0';
327 	result = write(fd, state, strlen(state) + 1);
328 	if (result != (strlen(state) + 1)) {
329 		RS_ERR("Cannot write 0 to rfkill state %d %s", errno,
330 				strerror(errno));
331 		close(fd);
332 		return -1;
333 	}
334 
335 	usleep(500000);
336 
337 	state[0] = '1';
338 	state[1] = '\0';
339 	result = write(fd, state, strlen(state) + 1);
340 	if (result != (strlen(state) + 1)) {
341 		RS_ERR("Cannot write 1 to rfkill state %d %s", errno,
342 				strerror(errno));
343 		close(fd);
344 		return -1;
345 	}
346 
347 	usleep(500000);
348 	close(fd);
349 
350 	return 0;
351 }
352 
usage(void)353 static void usage(void)
354 {
355 	RS_INFO("hciattach - HCI UART driver initialization utility");
356 	RS_INFO("Usage:");
357 	RS_INFO("\thciattach [-n] [-p] [-b] [-r] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]");
358 	RS_INFO("\thciattach -l");
359 }
360 
main(int argc,char * argv[])361 int main(int argc, char *argv[])
362 {
363 	struct uart_t *u = NULL;
364 	int detach, printpid, raw, opt, i, n, ld, err;
365 	int to = 10;
366 	int init_speed = 0;
367 	int send_break = 0;
368 	pid_t pid;
369 	struct sigaction sa;
370 	struct pollfd p;
371 	sigset_t sigs;
372 	char dev[PATH_MAX];
373 #ifdef SCHED_ENABLE
374 	struct sched_param sched_par;
375 #endif
376 
377 	detach = 1;
378 	printpid = 0;
379 	raw = 0;
380 
381 	while ((opt=getopt(argc, argv, "bnpt:s:lr")) != EOF) {
382 		switch(opt) {
383 		case 'b':
384 			send_break = 1;
385 			break;
386 
387 		case 'n':
388 			detach = 0;
389 			break;
390 
391 		case 'p':
392 			printpid = 1;
393 			break;
394 
395 		case 't':
396 			to = atoi(optarg);
397 			break;
398 
399 		case 's':
400 			init_speed = atoi(optarg);
401 			break;
402 
403 		case 'l':
404 			for (i = 0; uart[i].type; i++) {
405 				RS_INFO("%-10s0x%04x,0x%04x", uart[i].type,
406 							uart[i].m_id, uart[i].p_id);
407 			}
408 			exit(0);
409 
410 		case 'r':
411 			raw = 1;
412 			break;
413 
414 		default:
415 			usage();
416 			exit(1);
417 		}
418 	}
419 
420 	n = argc - optind;
421 	if (n < 2) {
422 		usage();
423 		exit(1);
424 	}
425 
426 	for (n = 0; optind < argc; n++, optind++) {
427 		char *opt;
428 
429 		opt = argv[optind];
430 
431 		switch(n) {
432 		case 0:
433 			dev[0] = 0;
434 			if (!strchr(opt, '/'))
435 				strcpy(dev, "/dev/");
436 			strcat(dev, opt);
437 			break;
438 
439 		case 1:
440 			if (strchr(argv[optind], ',')) {
441 				int m_id, p_id;
442 				sscanf(argv[optind], "%x,%x", &m_id, &p_id);
443 				u = get_by_id(m_id, p_id);
444 			} else {
445 				u = get_by_type(opt);
446 			}
447 
448 			if (!u) {
449 				RS_ERR("Unknown device type or id");
450 				exit(1);
451 			}
452 
453 			break;
454 
455 		case 2:
456 			u->speed = atoi(argv[optind]);
457 			break;
458 
459 		case 3:
460 			if (!strcmp("flow", argv[optind]))
461 				u->flags |=  FLOW_CTL;
462 			else
463 				u->flags &= ~FLOW_CTL;
464 			break;
465 
466 		case 4:
467 			if (!strcmp("sleep", argv[optind]))
468 				u->pm = ENABLE_PM;
469 			else
470 				u->pm = DISABLE_PM;
471 			break;
472 
473 		case 5:
474 			u->bdaddr = argv[optind];
475 			break;
476 		}
477 	}
478 
479 	if (!u) {
480 		RS_ERR("Unknown device type or id");
481 		exit(1);
482 	}
483 
484 start:
485 
486 #ifdef SCHED_ENABLE
487 	RS_INFO("Increase the priority of the process with set sched");
488 	memset(&sched_par, 0, sizeof(sched_par));
489 	sched_par.sched_priority = 99;
490 	err = sched_setscheduler(0, SCHED_FIFO, &sched_par);
491 	if (err == -1) {
492 		RS_ERR("Call sched_setscheduler error, %s",
493 			strerror(errno));
494 	}
495 /* #else
496  * 	RS_INFO("Increase the priority of the process with nice");
497  * 	err = nice(-20);
498  * 	if (err == -1) {
499  * 		RS_ERR("Call nice error, %s", strerror(errno));
500  * 	}
501  */
502 #endif
503 
504 	/* If user specified a initial speed, use that instead of
505 	   the hardware's default */
506 	if (init_speed)
507 		u->init_speed = init_speed;
508 
509 	memset(&sa, 0, sizeof(sa));
510 	sa.sa_flags   = SA_NOCLDSTOP;
511 	sa.sa_handler = sig_alarm;
512 	sigaction(SIGALRM, &sa, NULL);
513 
514 	/* 10 seconds should be enough for initialization */
515 	alarm(to);
516 
517 	n = init_uart(dev, u, send_break, raw);
518 	if (n < 0) {
519 		RS_ERR("Can't initialize device %d, %s", errno,
520 		       strerror(errno));
521 		exit(1);
522 	}
523 
524 	RS_INFO("Device setup complete");
525 
526 	alarm(0);
527 
528 	memset(&sa, 0, sizeof(sa));
529 	sa.sa_flags   = SA_NOCLDSTOP;
530 	sa.sa_handler = SIG_IGN;
531 	sigaction(SIGCHLD, &sa, NULL);
532 	sigaction(SIGPIPE, &sa, NULL);
533 
534 	sa.sa_handler = sig_term;
535 	sigaction(SIGTERM, &sa, NULL);
536 	sigaction(SIGINT,  &sa, NULL);
537 
538 	sa.sa_handler = sig_hup;
539 	sigaction(SIGHUP, &sa, NULL);
540 
541 	if (detach) {
542 		if ((pid = fork())) {
543 			if (printpid)
544 				RS_INFO("%d", pid);
545 			return 0;
546 		}
547 
548 		for (i = 0; i < 20; i++)
549 			if (i != n)
550 				close(i);
551 	}
552 
553 	p.fd = n;
554 	p.events = POLLERR | POLLHUP;
555 
556 	sigfillset(&sigs);
557 	sigdelset(&sigs, SIGCHLD);
558 	sigdelset(&sigs, SIGPIPE);
559 	sigdelset(&sigs, SIGTERM);
560 	sigdelset(&sigs, SIGINT);
561 	sigdelset(&sigs, SIGHUP);
562 
563 	while (!__io_canceled) {
564 		p.revents = 0;
565 		err = ppoll(&p, 1, NULL, &sigs);
566 		if (err < 0 && errno == EINTR) {
567 			RS_INFO("Got EINTR.");
568 			continue;
569 		} if (err)
570 			break;
571 	}
572 
573 	RS_INFO("err %d, p->revents %04x", err, p.revents);
574 
575 	/* Restore TTY line discipline */
576 	RS_INFO("Restore TTY line discipline");
577 	ld = N_TTY;
578 	if (ioctl(n, TIOCSETD, &ld) < 0) {
579 		RS_ERR("Can't restore line discipline %d, %s", errno,
580 		       strerror(errno));
581 		exit(1);
582 	}
583 
584 	if (p.revents & (POLLERR | POLLHUP)) {
585 		RS_INFO("Recover...");
586 		reset_bluetooth();
587 		goto start;
588 	}
589 
590 	return 0;
591 }
592 
util_hexdump(const uint8_t * buf,size_t len)593 void util_hexdump(const uint8_t *buf, size_t len)
594 {
595 	static const char hexdigits[] = "0123456789abcdef";
596 	char str[16 * 3];
597 	size_t i;
598 
599 	if (!buf || !len)
600 		return;
601 
602 	for (i = 0; i < len; i++) {
603 		str[((i % 16) * 3)] = hexdigits[buf[i] >> 4];
604 		str[((i % 16) * 3) + 1] = hexdigits[buf[i] & 0xf];
605 		str[((i % 16) * 3) + 2] = ' ';
606 		if ((i + 1) % 16 == 0) {
607 			str[16 * 3 - 1] = '\0';
608 			RS_INFO("%s", str);
609 		}
610 	}
611 
612 	if (i % 16 > 0) {
613 		str[(i % 16) * 3 - 1] = '\0';
614 		RS_INFO("%s", str);
615 	}
616 }
617 
timeout_set(int fd,unsigned int msec)618 int timeout_set(int fd, unsigned int msec)
619 {
620 	struct itimerspec itimer;
621 	unsigned int sec = msec / 1000;
622 
623 	memset(&itimer, 0, sizeof(itimer));
624 	itimer.it_interval.tv_sec = 0;
625 	itimer.it_interval.tv_nsec = 0;
626 	itimer.it_value.tv_sec = sec;
627 	itimer.it_value.tv_nsec = (msec - (sec * 1000)) * 1000 * 1000;
628 
629 	return timerfd_settime(fd, 0, &itimer, NULL);
630 }
631 
632