diff options
-rw-r--r-- | tools/hciattach.c | 128 |
1 files changed, 58 insertions, 70 deletions
diff --git a/tools/hciattach.c b/tools/hciattach.c index 15a9d367..7b8c20a0 100644 --- a/tools/hciattach.c +++ b/tools/hciattach.c @@ -51,6 +51,7 @@ struct uart_t { int m_id; int p_id; int proto; + int start_speed; int speed; int flags; int (*init) (int fd, struct uart_t *u, struct termios *ti); @@ -79,6 +80,8 @@ static int uart_speed(int s) return B921600; case 1000000: return B1000000; + case 1152000: + return B1152000; default: return B57600; } @@ -149,12 +152,6 @@ static int ericsson(int fd, struct uart_t *u, struct termios *ti) struct timespec tm = {0, 50000}; char cmd[10]; - /* Switch to default Ericsson baudrate*/ - if (set_speed(fd, ti, 57600) < 0) { - perror("Can't set default baud rate"); - return -1; - } - cmd[0] = HCI_COMMAND_PKT; cmd[1] = 0x09; cmd[2] = 0xfc; @@ -199,12 +196,6 @@ static int digi(int fd, struct uart_t *u, struct termios *ti) struct timespec tm = {0, 50000}; char cmd[10]; - /* Switch to default Digi baudrate*/ - if (set_speed(fd, ti, 9600) < 0) { - perror("Can't set default baud rate"); - return -1; - } - /* DigiAnswer set baud rate command */ cmd[0] = HCI_COMMAND_PKT; cmd[1] = 0x07; @@ -242,12 +233,6 @@ static int texas(int fd, struct uart_t *u, struct termios *ti) memset(resp,'\0', 100); - /* Switch to default Texas baudrate*/ - if (set_speed(fd, ti, 115200) < 0) { - perror("Can't set default baud rate"); - return -1; - } - /* It is possible to get software version with manufacturer specific HCI command HCI_VS_TI_Version_Number. But the only thing you get more is if this is point-to-point or point-to-multipoint module */ @@ -484,12 +469,6 @@ static int csr(int fd, struct uart_t *u, struct termios *ti) static int csr_seq = 0; /* Sequence number of command */ int divisor; - /* Switch to default CSR baudrate */ - if (set_speed(fd, ti, 115200) < 0) { - perror("Can't set default baud rate"); - return -1; - } - /* It seems that if we set the CSR UART speed straight away, it * won't work, the CSR UART gets into a state where we can't talk * to it anymore. @@ -596,6 +575,19 @@ static int csr(int fd, struct uart_t *u, struct termios *ti) } #endif + if (u->speed > 1500000) { + fprintf(stderr, "Speed %d too high. Remaining at %d baud\n", + u->speed, u->start_speed); + u->speed = u->start_speed; + } else if (u->speed != 57600 && uart_speed(u->speed) == B57600) { + /* Unknown speed. Why oh why can't we just pass an int to the kernel? */ + fprintf(stderr, "Speed %d unrecognised. Remaining at %d baud\n", + u->speed, u->start_speed); + u->speed = u->start_speed; + } + if (u->speed == u->start_speed) + return 0; + /* Now, create the command that will set the UART speed */ /* CSR BCC header */ cmd[5] = 0x02; /* type = SET-REQ */ @@ -604,30 +596,8 @@ static int csr(int fd, struct uart_t *u, struct termios *ti) cmd[10] = (csr_seq >> 8) & 0xFF;/* - msB */ csr_seq++; - switch (u->speed) { - case 9600: - divisor = 0x0027; - break; - /* Various speeds ommited */ - case 57600: - divisor = 0x00EC; - break; - case 115200: - divisor = 0x01D8; - break; - /* For Brainbox Pcmcia cards */ - case 460800: - divisor = 0x075F; - break; - case 921600: - divisor = 0x0EBF; - break; - default: - /* Safe default */ - divisor = 0x01D8; - u->speed = 115200; - break; - } + divisor = (u->speed*64+7812)/15625; + /* No parity, one stop bit -> divisor |= 0x0000; */ cmd[15] = (divisor) & 0xFF; /* divider */ cmd[16] = (divisor >> 8) & 0xFF; /* - msB */ @@ -665,12 +635,6 @@ static int swave(int fd, struct uart_t *u, struct termios *ti) char cmd[10], rsp[100]; int r; - /* Switch to default Silicon Wave baudrate*/ - if (set_speed(fd, ti, 115200) < 0) { - perror("Can't set default baud rate"); - return -1; - } - // Silicon Wave set baud rate command // see HCI Vendor Specific Interface from Silicon Wave // first send a "param access set" command to set the @@ -766,33 +730,33 @@ static int swave(int fd, struct uart_t *u, struct termios *ti) } struct uart_t uart[] = { - { "any", 0x0000, 0x0000, HCI_UART_H4, 115200, FLOW_CTL, NULL }, - { "ericsson", 0x0000, 0x0000, HCI_UART_H4, 115200, FLOW_CTL, ericsson }, - { "digi", 0x0000, 0x0000, HCI_UART_H4, 115200, FLOW_CTL, digi }, - { "texas", 0x0000, 0x0000, HCI_UART_H4, 115200, FLOW_CTL, texas}, + { "any", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL }, + { "ericsson", 0x0000, 0x0000, HCI_UART_H4, 57600, 115200, FLOW_CTL, ericsson }, + { "digi", 0x0000, 0x0000, HCI_UART_H4, 9600, 115200, FLOW_CTL, digi }, + { "texas", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, texas}, - { "bcsp", 0x0000, 0x0000, HCI_UART_BCSP, 115200, 0, bcsp }, + { "bcsp", 0x0000, 0x0000, HCI_UART_BCSP, 115200, 115200, 0, bcsp }, /* Xircom PCMCIA cards: Credit Card Adapter and Real Port Adapter */ - { "xircom", 0x0105, 0x080a, HCI_UART_H4, 115200, FLOW_CTL, NULL }, + { "xircom", 0x0105, 0x080a, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL }, /* CSR Casira serial adapter or BrainBoxes serial dongle (BL642) */ - { "csr", 0x0000, 0x0000, HCI_UART_H4, 115200, FLOW_CTL, csr }, + { "csr", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, csr }, /* BrainBoxes PCMCIA card (BL620) */ - { "bboxes", 0x0160, 0x0002, HCI_UART_H4, 460800, FLOW_CTL, csr }, + { "bboxes", 0x0160, 0x0002, HCI_UART_H4, 115200, 460800, FLOW_CTL, csr }, /* Silicon Wave kits */ - { "swave", 0x0000, 0x0000, HCI_UART_H4, 115200, FLOW_CTL, swave }, + { "swave", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, swave }, /* Sphinx Electronics PICO Card */ - { "picocard", 0x025e, 0x1000, HCI_UART_H4, 115200, FLOW_CTL, NULL }, + { "picocard", 0x025e, 0x1000, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL }, /* Inventel BlueBird Module */ - { "inventel", 0x0000, 0x0000, HCI_UART_H4, 115200, FLOW_CTL, NULL }, + { "inventel", 0x0000, 0x0000, HCI_UART_H4, 115200, 115200, FLOW_CTL, NULL }, /* COM One Platinium Bluetooth PC Card */ - { "comone", 0xffff, 0x0101, HCI_UART_BCSP, 115200, 0, bcsp }, + { "comone", 0xffff, 0x0101, HCI_UART_BCSP, 115200, 115200, 0, bcsp }, { NULL, 0 } }; @@ -818,7 +782,7 @@ struct uart_t * get_by_type(char *type) } /* Initialize UART driver */ -int init_uart(char *dev, struct uart_t *u) +int init_uart(char *dev, struct uart_t *u, int send_break) { struct termios ti; int fd, i; @@ -849,8 +813,17 @@ int init_uart(char *dev, struct uart_t *u) return -1; } + /* Set initial baudrate */ + if (set_speed(fd, &ti, u->start_speed) < 0) { + perror("Can't set initial baud rate"); + return -1; + } + tcflush(fd, TCIOFLUSH); + if (send_break) + tcsendbreak(fd, 0); + if (u->init && u->init(fd, u, &ti) < 0) return -1; @@ -881,7 +854,7 @@ static void usage(void) { printf("hciattach - HCI UART driver initialization utility\n"); printf("Usage:\n"); - printf("\thciattach [-n] [-p] [-t timeout] <tty> <type | id> [speed] [flow]\n"); + printf("\thciattach [-n] [-p] [-b] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow]\n"); printf("\thciattach -l\n"); } @@ -893,6 +866,8 @@ int main(int argc, char *argv[]) struct uart_t *u = NULL; int detach, printpid, opt, i, n; int to = 5; + int start_speed = 0; + int send_break = 0; pid_t pid; struct sigaction sa; char dev[20]; @@ -900,8 +875,12 @@ int main(int argc, char *argv[]) detach = 1; printpid = 0; - while ((opt=getopt(argc, argv, "npt:l")) != EOF) { + while ((opt=getopt(argc, argv, "bnpt:s:l")) != EOF) { switch(opt) { + case 'b': + send_break = 1; + break; + case 'n': detach = 0; break; @@ -914,6 +893,10 @@ int main(int argc, char *argv[]) to = atoi(optarg); break; + case 's': + start_speed = atoi(optarg); + break; + case 'l': for (i = 0; uart[i].type; i++) { printf("%-10s0x%04x,0x%04x\n", uart[i].type, @@ -980,6 +963,11 @@ int main(int argc, char *argv[]) exit(1); } + /* If user specified a starting speed, use that instead of + the hardware's default */ + if (start_speed) + u->start_speed = start_speed; + memset(&sa, 0, sizeof(sa)); sa.sa_flags = SA_NOCLDSTOP; sa.sa_handler = sig_alarm; @@ -988,7 +976,7 @@ int main(int argc, char *argv[]) /* 5 seconds should be enough for initialization */ alarm(to); - n = init_uart(dev, u); + n = init_uart(dev, u, send_break); if (n < 0) { perror("Can't initialize device"); exit(1); |