diff -u -p tools/hciattach.m1.c tools/hciattach.c --- tools/hciattach.m1.c Wed Nov 14 15:04:04 2001 +++ tools/hciattach.c Wed Nov 14 16:06:16 2001 @@ -70,6 +70,10 @@ static int uart_speed(int s) return B57600; case 115200: return B115200; + case 460800: + return B460800; + case 921600: + return B921600; default: return B57600; } @@ -176,11 +180,205 @@ static int digi(int fd, struct uart_t *u return 0; } +/* + * CSR specific initialization + * Inspired strongly by code in OpenBT and experimentations with Brainboxes + * Pcmcia card. + * Jean Tourrilhes - 14.11.01 + */ +static int csr(int fd, struct uart_t *u, struct termios *ti) +{ + struct timespec tm = {0, 10000000}; /* 10ms - be generous */ + char cmd[30]; /* Command */ + char resp[30]; /* Response */ + int clen = 0; /* Command len */ + int rlen = 0; /* Response len */ + int min_rlen = 16; /* Minimum response len that is ok */ + 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. + * On the other hand, doing a read before setting the CSR speed + * seems to be ok. + * Therefore, the strategy is to read the build ID (useful for + * debugging) and only then set the CSR UART speed. Doing like + * this is more complex but at least it works ;-) + * The CSR UART control may be slow to wake up or something because + * every time I read its speed, its bogus... + * Jean II */ + + /* Try to read the build ID of the CSR chip */ + clen = 5 + (5 + 6)*2; + /* -- HCI header */ + cmd[0] = HCI_COMMAND_PKT; + cmd[1] = 0x00; /* CSR command */ + cmd[2] = 0xfc; /* MANUFACTURER_SPEC */ + cmd[3] = 1 + (5 + 6)*2; /* len */ + /* -- CSR MSG header -- */ + cmd[4] = 0xC2; /* first+last+channel=BCC */ + /* -- CSR BCC header -- */ + cmd[5] = 0x00; /* type = GET-REQ */ + cmd[6] = 0x00; /* - msB */ + cmd[7] = 5 + 4; /* len */ + cmd[8] = 0x00; /* - msB */ + cmd[9] = csr_seq & 0xFF; /* seq num */ + cmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */ + csr_seq++; + cmd[11] = 0x19; /* var_id = CSR_CMD_BUILD_ID */ + cmd[12] = 0x28; /* - msB */ + cmd[13] = 0x00; /* status = STATUS_OK */ + cmd[14] = 0x00; /* - msB */ + /* -- CSR BCC payload -- */ + memset(cmd + 15, 0, 6*2); + + /* Send command */ + if (write(fd, cmd, clen) != clen) { + perror("Failed to write init command (GET_BUILD_ID)"); + return -1; + } + tcflush(fd, TCIOFLUSH); + + /* Wait for reply - maybe we should test some status here */ + rlen = read(fd, resp, 100); + if (rlen < min_rlen) { + perror("Failed to read init response (GET_BUILD_ID)"); + return -1; + } + +#ifdef CSR_DEBUG + { + char temp[512]; + int i; + for(i = 0; i < rlen; i++) + sprintf(temp + (i*3), "-%02X", resp[i]); + fprintf(stderr, "Reading CSR build ID %d [%s]\n", rlen, temp + 1); + // In theory, it should look like : + // 04-FF-13-FF-01-00-09-00-00-00-19-28-00-00-73-00-00-00-00-00-00-00 + } +#endif + /* Display that to user */ + fprintf(stderr, "CSR build ID 0x%02X-0x%02X\n", resp[15], resp[14]); + + /* Try to read the current speed of the CSR chip */ + clen = 5 + (5 + 4)*2; + /* -- HCI header */ + cmd[3] = 1 + (5 + 4)*2; /* len */ + /* -- CSR BCC header -- */ + cmd[9] = csr_seq & 0xFF; /* seq num */ + cmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */ + csr_seq++; + cmd[11] = 0x02; /* var_id = CONFIG_UART */ + cmd[12] = 0x68; /* - msB */ + +#ifdef CSR_DEBUG + /* Send command */ + if (write(fd, cmd, clen) != clen) { + perror("Failed to write init command (GET_UART_SPEED)"); + return -1; + } + tcflush(fd, TCIOFLUSH); + + /* Wait for reply - maybe we should test some status here */ + rlen = read(fd, resp, 100); + if (rlen < min_rlen) { + perror("Failed to read init response (GET_UART_SPEED)"); + return -1; + } + + { + char temp[512]; + int i; + for(i = 0; i < rlen; i++) + sprintf(temp + (i*3), "-%02X", resp[i]); + fprintf(stderr, "Reading CSR UART speed %d [%s]\n", rlen, temp + 1); + } +#endif + + /* Now, create the command that will set the UART speed */ + /* -- CSR BCC header -- */ + cmd[5] = 0x02; /* type = SET-REQ */ + cmd[6] = 0x00; /* - msB */ + cmd[9] = csr_seq & 0xFF; /* seq num */ + 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; + } + /* No parity, one stop bit -> divisor |= 0x0000; */ + cmd[15] = (divisor) & 0xFF; /* divider */ + cmd[16] = (divisor >> 8) & 0xFF; /* - msB */ + /* The rest of the payload will be 0x00 */ + +#ifdef CSR_DEBUG + { + char temp[512]; + int i; + for(i = 0; i < clen; i++) + sprintf(temp + (i*3), "-%02X", cmd[i]); + fprintf(stderr, "Writing CSR UART speed %d [%s]\n", clen, temp + 1); + // In theory, it should look like : + // 01-00-FC-13-C2-02-00-09-00-03-00-02-68-00-00-BF-0E-00-00-00-00-00-00 + // 01-00-FC-13-C2-02-00-09-00-01-00-02-68-00-00-D8-01-00-00-00-00-00-00 + } +#endif + + /* Send the command to set the CSR UART speed */ + if (write(fd, cmd, clen) != clen) { + perror("Failed to write init command (SET_UART_SPEED)"); + return -1; + } + + /* Make sure data reach the chip before waiting - Jean II */ + tcflush(fd, TCIOFLUSH); + nanosleep(&tm, NULL); + + /* Set actual baudrate */ + if (set_speed(fd, ti, u->speed) < 0) { + perror("Can't set baud rate"); + return -1; + } + return 0; +} + struct uart_t uart[] = { { "any", 0x0000, 0x0000, 115200, FLOW_CTL, NULL }, { "ericsson", 0x0000, 0x0000, 115200, FLOW_CTL, ericsson }, { "digi", 0x0000, 0x0000, 115200, FLOW_CTL, digi }, { "xircom", 0x0105, 0x080a, 115200, FLOW_CTL, NULL }, + /* Casira serial adapter or BrainBoxes serial dongle (BL642) */ + { "csr", 0x0000, 0x0000, 115200, FLOW_CTL, csr }, + /* BrainBoxes Pcmcia card (BL620) */ + { "brain", 0x0160, 0x0002, 460800, FLOW_CTL, csr }, { NULL, 0 } };