From fc4ca3634da071b9a75961be179cccbe88101b75 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 20 Mar 2006 22:29:03 +0000 Subject: Detect TTY detach and restore line discipline --- tools/hciattach.c | 124 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 89 insertions(+), 35 deletions(-) diff --git a/tools/hciattach.c b/tools/hciattach.c index e583e8db..cfccb9ab 100644 --- a/tools/hciattach.c +++ b/tools/hciattach.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -70,6 +71,23 @@ struct uart_t { #define FLOW_CTL 0x0001 +static volatile sig_atomic_t __io_canceled = 0; + +static void sig_hup(int sig) +{ +} + +static void sig_term(int sig) +{ + __io_canceled = 1; +} + +static void sig_alarm(int sig) +{ + fprintf(stderr, "Initialization timed out.\n"); + exit(1); +} + static int uart_speed(int s) { switch (s) { @@ -110,12 +128,6 @@ static int set_speed(int fd, struct termios *ti, int speed) return tcsetattr(fd, TCSANOW, ti); } -static void sig_alarm(int sig) -{ - fprintf(stderr, "Initialization timed out.\n"); - exit(1); -} - /* * Read an HCI event from the given file descriptor. */ @@ -158,6 +170,7 @@ static int read_hci_event(int fd, unsigned char* buf, int size) return -1; count += r; } + return count; } @@ -201,6 +214,7 @@ static int ericsson(int fd, struct uart_t *u, struct termios *ti) perror("Failed to write init command"); return -1; } + nanosleep(&tm, NULL); return 0; } @@ -237,6 +251,7 @@ static int digi(int fd, struct uart_t *u, struct termios *ti) perror("Failed to write init command"); return -1; } + nanosleep(&tm, NULL); return 0; } @@ -289,7 +304,7 @@ static int texas(int fd, struct uart_t *u, struct termios *ti) /* Print LMP subversion */ fprintf(stderr, "Texas module LMP sub-version : 0x%02x%02x\n", resp[14] & 0xFF, resp[13] & 0xFF); - + nanosleep(&tm, NULL); return 0; } @@ -297,7 +312,7 @@ static int texas(int fd, struct uart_t *u, struct termios *ti) static int read_check(int fd, void *buf, int count) { int res; - + do { res = read(fd, buf, count); if (res != -1) { @@ -305,10 +320,10 @@ static int read_check(int fd, void *buf, int count) count -= res; } } while (count && (errno == 0 || errno == EINTR)); - + if (count) return -1; - + return 0; } @@ -321,13 +336,14 @@ static void bcsp_tshy_sig_alarm(int sig) { static int retries=0; unsigned char bcsp_sync_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xda,0xdc,0xed,0xed,0xc0}; - + if (retries < 10) { retries++; write(serial_fd, &bcsp_sync_pkt, 10); alarm(1); return; } + tcflush(serial_fd, TCIOFLUSH); fprintf(stderr, "BCSP initialization timed out\n"); exit(1); @@ -337,12 +353,14 @@ static void bcsp_tconf_sig_alarm(int sig) { static int retries=0; unsigned char bcsp_conf_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xad,0xef,0xac,0xed,0xc0}; + if (retries < 10){ retries++; write(serial_fd, &bcsp_conf_pkt, 10); alarm(1); return; } + tcflush(serial_fd, TCIOFLUSH); fprintf(stderr, "BCSP initialization timed out\n"); exit(1); @@ -390,20 +408,19 @@ static int bcsp(int fd, struct uart_t *u, struct termios *ti) return -1; } } while (byte != 0xC0); - + do { if ( read_check(fd, &bcsph[0], 1) == -1){ perror("Failed to read"); return -1; } - } while (bcsph[0] == 0xC0); - + if ( read_check(fd, &bcsph[1], 3) == -1){ perror("Failed to read"); return -1; } - + if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3]) continue; if (bcsph[1] != 0x41 || bcsph[2] != 0x00) @@ -437,8 +454,8 @@ static int bcsp(int fd, struct uart_t *u, struct termios *ti) do { if (read_check(fd, &bcsph[0], 1) == -1){ - perror("Failed to read"); - return -1; + perror("Failed to read"); + return -1; } } while (bcsph[0] == 0xC0); @@ -446,7 +463,7 @@ static int bcsp(int fd, struct uart_t *u, struct termios *ti) perror("Failed to read"); return -1; } - + if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3]) continue; @@ -553,7 +570,7 @@ static int csr(int fd, struct uart_t *u, struct termios *ti) /* Display that to user */ fprintf(stderr, "CSR build ID 0x%02X-0x%02X\n", resp[15] & 0xFF, resp[14] & 0xFF); - + /* Try to read the current speed of the CSR chip */ clen = 5 + (5 + 4)*2; /* -- HCI header */ @@ -638,6 +655,7 @@ static int csr(int fd, struct uart_t *u, struct termios *ti) perror("Failed to write init command (SET_UART_SPEED)"); return -1; } + nanosleep(&tm, NULL); return 0; } @@ -715,7 +733,7 @@ static int swave(int fd, struct uart_t *u, struct termios *ti) // 01 flow on // 01 Hci Transport type = Uart // xx Baud rate set (see above) - } else { + } else { // ups, got error. return -1; } @@ -735,7 +753,7 @@ static int swave(int fd, struct uart_t *u, struct termios *ti) } nanosleep(&tm, NULL); - + // now the uart baud rate on the silicon wave module is set and effective. // change our own baud rate as well. Then there is a reset event comming in // on the *new* baud rate. This is *undocumented*! The packet looks like this: @@ -798,11 +816,11 @@ static int st(int fd, struct uart_t *u, struct termios *ti) perror("Failed to write init command"); return -1; } + nanosleep(&tm, NULL); return 0; } - /* * Broadcom specific initialization * Extracted from Jungo openrg @@ -819,11 +837,13 @@ static int bcm2035(int fd, struct uart_t *u, struct termios *ti) cmd[1] = 0x03; cmd[2] = 0x0c; cmd[3] = 0x00; + /* Send command */ if (write(fd, cmd, 4) != 4) { fprintf(stderr, "Failed to write reset command\n"); return -1; } + /* Read reply */ if ((n = read_hci_event(fd, resp, 4)) < 0) { fprintf(stderr, "Failed to reset chip\n"); @@ -837,12 +857,14 @@ static int bcm2035(int fd, struct uart_t *u, struct termios *ti) cmd[1] = 0x01; cmd[2] = 0x10; cmd[3] = 0x00; + /* Send command */ if (write(fd, cmd, 4) != 4) { fprintf(stderr, "Failed to write \"read local version\" " "command\n"); return -1; } + /* Read reply */ if ((n = read_hci_event(fd, resp, 4)) < 0) { fprintf(stderr, "Failed to read local version\n"); @@ -856,12 +878,14 @@ static int bcm2035(int fd, struct uart_t *u, struct termios *ti) cmd[1] = 0x02; cmd[2] = 0x10; cmd[3] = 0x00; + /* Send command */ if (write(fd, cmd, 4) != 4) { fprintf(stderr, "Failed to write \"read local supported " "commands\" command\n"); return -1; } + /* Read reply */ if ((n = read_hci_event(fd, resp, 4)) < 0) { fprintf(stderr, "Failed to read local supported commands\n"); @@ -906,10 +930,12 @@ static int bcm2035(int fd, struct uart_t *u, struct termios *ti) fprintf(stderr, "Failed to write \"set baud rate\" command\n"); return -1; } + if ((n = read_hci_event(fd, resp, 6)) < 0) { fprintf(stderr, "Failed to set baud rate\n"); return -1; } + return 0; } @@ -996,7 +1022,7 @@ struct uart_t * get_by_type(char *type) int init_uart(char *dev, struct uart_t *u, int send_break) { struct termios ti; - int fd, i; + int fd, i; fd = open(dev, O_RDWR | O_NOCTTY); if (fd < 0) { @@ -1071,23 +1097,21 @@ static void usage(void) printf("\thciattach -l\n"); } -extern int optind, opterr, optopt; -extern char *optarg; - int main(int argc, char *argv[]) { struct uart_t *u = NULL; - int detach, printpid, opt, i, n; + int detach, printpid, opt, i, n, ld; int to = 5; int init_speed = 0; int send_break = 0; pid_t pid; struct sigaction sa; + struct pollfd p; char dev[PATH_MAX]; detach = 1; printpid = 0; - + while ((opt=getopt(argc, argv, "bnpt:s:l")) != EOF) { switch(opt) { case 'b': @@ -1131,9 +1155,9 @@ int main(int argc, char *argv[]) for (n = 0; optind < argc; n++, optind++) { char *opt; - + opt = argv[optind]; - + switch(n) { case 0: dev[0] = 0; @@ -1182,13 +1206,13 @@ int main(int argc, char *argv[]) u->init_speed = init_speed; memset(&sa, 0, sizeof(sa)); - sa.sa_flags = SA_NOCLDSTOP; + sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = sig_alarm; sigaction(SIGALRM, &sa, NULL); /* 5 seconds should be enough for initialization */ alarm(to); - + n = init_uart(dev, u, send_break); if (n < 0) { perror("Can't initialize device"); @@ -1197,16 +1221,46 @@ int main(int argc, char *argv[]) alarm(0); + memset(&sa, 0, sizeof(sa)); + sa.sa_flags = SA_NOCLDSTOP; + sa.sa_handler = SIG_IGN; + sigaction(SIGCHLD, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); + + sa.sa_handler = sig_term; + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + + sa.sa_handler = sig_hup; + sigaction(SIGHUP, &sa, NULL); + if (detach) { if ((pid = fork())) { if (printpid) printf("%d\n", pid); return 0; } - for (i=0; i<20; i++) - if (i != n) close(i); + + for (i = 0; i < 20; i++) + if (i != n) + close(i); + } + + p.fd = n; + p.events = POLLERR | POLLHUP; + + while (!__io_canceled) { + p.revents = 0; + if (poll(&p, 1, 100)) + break; + } + + /* Restore TTY line discipline */ + ld = N_TTY; + if (ioctl(n, TIOCSETD, &ld) < 0) { + perror("Can't restore line discipline"); + exit(1); } - while (1) sleep(999999999); return 0; } -- cgit