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