diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/hciattach.c | 84 |
1 files changed, 78 insertions, 6 deletions
diff --git a/tools/hciattach.c b/tools/hciattach.c index ca81117b..cee27e46 100644 --- a/tools/hciattach.c +++ b/tools/hciattach.c @@ -77,6 +77,8 @@ static int uart_speed(int s) return B460800; case 921600: return B921600; + case 1000000: + return B1000000; default: return B57600; } @@ -233,18 +235,88 @@ static int digi(int fd, struct uart_t *u, struct termios *ti) */ static int bcsp(int fd, struct uart_t *u, struct termios *ti) { - ti->c_cflag &= ~CBAUD; - ti->c_cflag |= B115200 | CS8 | CLOCAL | PARENB; - ti->c_cflag &= ~(PARODD|CRTSCTS); + unsigned char byte, bcsph[4], bcspp[4], + bcsp_sync_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xda,0xdc,0xed,0xed,0xc0}, + bcsp_sync_resp_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xac,0xaf,0xef,0xee,0xc0}, + bcsp_conf_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xad,0xef,0xac,0xed,0xc0}, + bcsp_conf_resp_pkt[10] = {0xc0,0x00,0x41,0x00,0xbe,0xde,0xad,0xd0,0xd0,0xc0}, + bcspsync[4] = {0xda, 0xdc, 0xed, 0xed}, + bcspsyncresp[4] = {0xac,0xaf,0xef,0xee}, + bcspconf[4] = {0xad,0xef,0xac,0xed}, + bcspconfresp[4] = {0xde,0xad,0xd0,0xd0}; + int sync_sent = 0; + + if (set_speed(fd, ti, u->speed) < 0) { + perror("Can't set default baud rate"); + return -1; + } - ti->c_oflag = 0; /* turn off output processing */ - ti->c_lflag = 0; /* no local modes */ + ti->c_cflag |= PARENB; + ti->c_cflag &= ~(PARODD); if (tcsetattr(fd, TCSANOW, ti) < 0) { perror("Can't set port settings"); return -1; } + /* State = shy */ + + while (1) { + do { + read(fd, &byte, 1); + } while(byte != 0xC0); + + do { + read(fd, &bcsph[0], 1); + } while(bcsph[0] == 0xC0); + + read(fd, &bcsph[1], 3); + if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3]) + continue; + if (bcsph[1] != 0x41 || bcsph[2] != 0x00) + continue; + + read(fd, &bcspp, 4); + if (!memcmp(bcspp, bcspsync, 4)) { + write(fd, &bcsp_sync_resp_pkt,10); + if (!sync_sent) { + write(fd, &bcsp_sync_pkt, 10); /* muzzled = false */ + sync_sent = 1; + } + } else if (!memcmp(bcspp, bcspsyncresp, 4)) + break; + } + + /* State = curious */ + + write(fd, &bcsp_conf_pkt, 10); + while (1) { + do { + read(fd, &byte, 1); + } while(byte != 0xC0); + + do { + read(fd, &bcsph[0], 1); + } while(bcsph[0] == 0xC0); + + read(fd, &bcsph[1], 3); + if (((bcsph[0] + bcsph[1] + bcsph[2]) & 0xFF) != (unsigned char)~bcsph[3]) + continue; + + if (bcsph[1] != 0x41 || bcsph[2] != 0x00) + continue; + + read(fd, &bcspp, 4); + if (!memcmp(bcspp, bcspsync, 4)) + write(fd, &bcsp_sync_resp_pkt, 10); + else if (!memcmp(bcspp, bcspconf, 4)) + write(fd, &bcsp_conf_resp_pkt, 10); + else if (!memcmp(bcspp, bcspconfresp, 4)) + break; + } + + /* State = garrulous */ + return 0; } @@ -763,7 +835,7 @@ int main(int argc, char *argv[]) sa.sa_handler = sig_alarm; sigaction(SIGALRM, &sa, NULL); - /* 5 seconds should be enought for intialization */ + /* 5 seconds should be enough for intialization */ alarm(to); n = init_uart(dev, u); |