diff options
| author | Marcel Holtmann <marcel@holtmann.org> | 2006-03-20 22:29:03 +0000 | 
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2006-03-20 22:29:03 +0000 | 
| commit | fc4ca3634da071b9a75961be179cccbe88101b75 (patch) | |
| tree | cdd403007accd3538e27837917f59e851c0e6bd2 /tools/hciattach.c | |
| parent | fb3a213c3304d9855ad534d8d44151b3b8e92a32 (diff) | |
Detect TTY detach and restore line discipline
Diffstat (limited to 'tools/hciattach.c')
| -rw-r--r-- | tools/hciattach.c | 124 | 
1 files 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 <termios.h>  #include <time.h>  #include <sys/time.h> +#include <sys/poll.h>  #include <sys/ioctl.h>  #include <sys/socket.h> @@ -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;  } | 
