summaryrefslogtreecommitdiffstats
path: root/tools/hciattach.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/hciattach.c')
-rw-r--r--tools/hciattach.c124
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;
}