--- daemons/hcid.m1.h Tue Oct 23 10:33:41 2001 +++ daemons/hcid.h Tue Oct 23 10:34:47 2001 @@ -55,6 +55,7 @@ extern int uart_num; #define UART_ERICSSON 0x1000 #define UART_DIGI 0x2000 +#define UART_CSR 0x4000 #define UART_VENDOR 0xf000 int init_uart(struct uart_struct *u); --- daemons/hcid_conf.m1.c Tue Oct 23 10:33:50 2001 +++ daemons/hcid_conf.c Tue Oct 23 10:35:32 2001 @@ -50,6 +50,7 @@ struct kword uart_param[] = { { "flow", UART_FLOW_ON }, { "ericsson", UART_ERICSSON }, { "digianswer", UART_DIGI }, + { "csr", UART_CSR }, { NULL , 0 } }; --- daemons/hcid_uart.m1.c Tue Oct 23 10:33:08 2001 +++ daemons/hcid_uart.c Thu Nov 8 11:55:46 2001 @@ -53,6 +53,76 @@ struct uart_struct uart[HCI_MAX_DEV]; int uart_num = 0; +static int csr_seq = 0; /* Sequence number (for CSR) */ + +/* + * It seems that the first read on the CSR on the Brainboxes Pcmcia card + * always fail, the first char is eaten away. + * This attempt to read the current speed at which the CSR chip is + * configured, which will unstuck the chip/UART. + * It will also helps debugging non standard UARTs ;-) + * Jean II */ +static int test_csr(int fd) +{ + char icmd[100]; + int ilen = 0; + int rlen = 0; + char temp[512]; + int i; + struct timespec tm = { 0, 50000 }; + + /* Be safe ;-) Make sure UART speed has time to settle... */ + nanosleep(&tm, NULL); + + /* Try to read the current speed of the CSR chip */ + ilen = 5 + (5 + 4)*2; + /* -- HCI header */ + icmd[0] = HCI_COMMAND_PKT; + icmd[1] = 0x00; /* CSR command */ + icmd[2] = 0xfc; /* MANUFACTURER_SPEC */ + icmd[3] = 1 + (5 + 4)*2; /* len */ + /* -- CSR MSG header -- */ + icmd[4] = 0xC2; /* first+last+channel=BCC */ + /* -- CSR BCC header -- */ + icmd[5] = 0x00; /* type = GET-REQ */ + icmd[6] = 0x00; /* - msB */ + icmd[7] = 5 + 4; /* len */ + icmd[8] = 0x00; /* - msB */ + icmd[9] = csr_seq & 0xFF; /* seq num */ + icmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */ + csr_seq++; + icmd[11] = 0x02; /* var_id = CONFIG_UART */ + icmd[12] = 0x68; /* - msB */ + icmd[13] = 0x00; /* status = STATUS_OK */ + icmd[14] = 0x00; /* - msB */ + /* -- CSR BCC payload -- */ + memset(icmd + 15, 0, 4*2); + + /* Send command */ + if (write(fd, icmd, ilen) != ilen) { + syslog(LOG_ERR,"Can't write cmd. %s(%d)", strerror(errno),errno); + return -1; + } + tcflush(fd, TCIOFLUSH); + + /* Wait for reply */ + rlen = read(fd, icmd, 100); + if (rlen < 0) { + syslog(LOG_ERR,"Can't read cmd. %s(%d)", strerror(errno),errno); + return -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 + // For me, first chars are garbled... - Jean II + for(i = 0; i < rlen; i++) + sprintf(temp + (i*3), "-%02X", icmd[i]); + syslog(LOG_ERR, "Reading CSR speed [%s]\n", temp + 1); + + return 0; +} + static int uart_speed(int s) { switch (s) { @@ -66,6 +136,10 @@ static int uart_speed(int s) return B57600; case 115200: return B115200; + case 460800: + return B460800; + case 921600: + return B921600; default: return B57600; } @@ -75,13 +149,61 @@ static int uart_speed(int s) int init_uart(struct uart_struct *u) { struct termios ti; - char icmd[100]; - int ilen = 0, ispd = 9600; + char icmd[100]; /* Initialisation command */ + int ilen = 0; /* Length of the command */ + int ispd = 9600; /* Initial chip speed (before changing it) */ + int isleep = 50000; /* Configuration delay of the chip */ int fd, i; + int temp; + /* Get the initial speed */ switch (u->flags & UART_VENDOR) { case UART_ERICSSON: ispd = 57600; + break; + + case UART_DIGI: + ispd = 9600; + break; + + case UART_CSR: + ispd = 115200; /* Default speed after reset */ + //isleep = 2000000; + isleep = 10000000; /* Be generous */ + break; + + default: + ispd = u->speed; + break; + } + + /* Get serial port ready */ + if ((fd=open(u->dev, O_RDWR | O_NOCTTY)) < 0) { + syslog(LOG_ERR,"Can't open serial port. %s(%d)", strerror(errno),errno); + return -1; + } + + tcflush(fd, TCIOFLUSH); + + if (tcgetattr(fd, &ti) < 0) { + syslog(LOG_ERR,"Can't get port settings. %s(%d)", strerror(errno),errno); + return -1; + } + + cfmakeraw(&ti); + cfsetospeed(&ti, uart_speed(ispd)); + ti.c_cflag |= CLOCAL; + if (u->flags & UART_FLOW_ON) + ti.c_cflag |= CRTSCTS; + + if (tcsetattr(fd, TCSANOW, &ti) < 0) { + syslog(LOG_ERR,"Can't set port settings. %s(%d)", strerror(errno),errno); + return -1; + } + + /* Create configuration command */ + switch (u->flags & UART_VENDOR) { + case UART_ERICSSON: ilen = 5; icmd[0] = HCI_COMMAND_PKT; icmd[1] = 0x09; @@ -103,7 +225,6 @@ int init_uart(struct uart_struct *u) case UART_DIGI: /* DigiAnswer set baud rate command */ - ispd = 9600; ilen = 5; icmd[0] = HCI_COMMAND_PKT; icmd[1] = 0x07; @@ -124,32 +245,74 @@ int init_uart(struct uart_struct *u) } break; - default: - ispd = u->speed; - break; - } - - if ((fd=open(u->dev, O_RDWR | O_NOCTTY)) < 0) { - syslog(LOG_ERR,"Can't open serial port. %s(%d)", strerror(errno),errno); - return -1; - } - - tcflush(fd, TCIOFLUSH); - - if (tcgetattr(fd, &ti) < 0) { - syslog(LOG_ERR,"Can't get port settings. %s(%d)", strerror(errno),errno); - return -1; - } + case UART_CSR: + /* This make sure that the CSR chip is in a sane + * state... */ + test_csr(fd); + + /* CSR set baud rate command */ + /* Note : this setting is only temporary. Next time + * the module is reset, it will be back to the default + * of 115k. This guarantee that invalid speed + * settings won't render the card unusable and that + * we can always assume the initial speed is 115k. + * Jean II + */ + ilen = 5 + (5 + 4)*2; + /* -- HCI header */ + icmd[0] = HCI_COMMAND_PKT; + icmd[1] = 0x00; /* CSR command */ + icmd[2] = 0xfc; /* MANUFACTURER_SPEC */ + icmd[3] = 1 + (5 + 4)*2; /* len */ + /* -- CSR MSG header -- */ + icmd[4] = 0xC2; /* first+last+channel=BCC */ + /* -- CSR BCC header -- */ + icmd[5] = 0x02; /* type = SET-REQ */ + icmd[6] = 0x00; /* - msB */ + icmd[7] = 5 + 4; /* len */ + icmd[8] = 0x00; /* - msB */ + icmd[9] = csr_seq & 0xFF; /* seq num */ + icmd[10] = (csr_seq >> 8) & 0xFF; /* - msB */ + csr_seq++; + icmd[11] = 0x02; /* var_id = CONFIG_UART */ + icmd[12] = 0x68; /* - msB */ + icmd[13] = 0x00; /* status = STATUS_OK */ + icmd[14] = 0x00; /* - msB */ + /* -- CSR BCC payload -- */ + memset(icmd + 15, 0, 4*2); - cfmakeraw(&ti); - cfsetospeed(&ti, uart_speed(ispd)); - ti.c_cflag |= CLOCAL; - if (u->flags & UART_FLOW_ON) - ti.c_cflag |= CRTSCTS; + switch (u->speed) { + case 9600: + temp = 0x0027; + break; + /* Various speeds ommited */ + case 57600: + temp = 0x00EC; + break; + case 115200: + temp = 0x01D8; + break; + /* For Brainbox Pcmcia cards */ + case 460800: + temp = 0x075F; + break; + case 921600: + temp = 0x0EBF; + break; + default: + /* Safe default */ + temp = 0x01D8; + u->speed = 115200; + break; + } + /* No parity, one stop bit -> temp |= 0x0000; */ + icmd[15] = (temp) & 0xFF; /* divider */ + icmd[16] = (temp >> 8) & 0xFF; /* - msB */ + /* The rest of the payload will be 0x00 */ + break; - if (tcsetattr(fd, TCSANOW, &ti) < 0) { - syslog(LOG_ERR,"Can't set port settings. %s(%d)", strerror(errno),errno); - return -1; + default: + break; } if (ilen) { @@ -160,6 +323,9 @@ int init_uart(struct uart_struct *u) syslog(LOG_ERR,"Can't write init cmd. %s(%d)", strerror(errno),errno); return -1; } + /* Make sure data reach the chip before waiting - Jean II */ + tcflush(fd, TCIOFLUSH); + tm.tv_nsec = isleep; nanosleep(&tm, NULL); /* Set actual baudrate */