--- 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 */

