Re: [PATCH] Add support for Texas Instruments' chips

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Jul 10, 2008 at 7:07 AM, Marcel Holtmann <marcel@xxxxxxxxxxxx> wrote:
> please put all the TI code into hciattach_ti.c and then I gonna apply
> this patch.

Patch attached.

Thanks,
Ohad.
From 61318cd9e55edf87556456350b144ccd281491ce Mon Sep 17 00:00:00 2001
From: Ohad <ohad@muesli.(none)>
Date: Thu, 10 Jul 2008 09:53:09 +0300
Subject: [PATCH] Add support for Texas Instruments' chips

---
 utils/tools/Makefile.am    |    2 +-
 utils/tools/hciattach.8    |    3 +
 utils/tools/hciattach.c    |  158 +++++++++------
 utils/tools/hciattach.h    |   69 +++++++
 utils/tools/hciattach_ti.c |  455 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 623 insertions(+), 64 deletions(-)
 create mode 100644 utils/tools/hciattach.h
 create mode 100644 utils/tools/hciattach_ti.c

diff --git a/utils/tools/Makefile.am b/utils/tools/Makefile.am
index bc46b3d..c0af73e 100644
--- a/utils/tools/Makefile.am
+++ b/utils/tools/Makefile.am
@@ -43,7 +43,7 @@ bin_PROGRAMS = $(tools_programs) $(dfutool_programs) $(dfubabel_programs)
 
 noinst_PROGRAMS = hcisecfilter ppporc avinfo $(usb_programs)
 
-hciattach_SOURCES = hciattach.c hciattach_st.c
+hciattach_SOURCES = hciattach.c hciattach_st.c hciattach_ti.c
 hciattach_LDADD = @BLUEZ_LIBS@
 
 hciconfig_SOURCES = hciconfig.c csr.h csr.c
diff --git a/utils/tools/hciattach.8 b/utils/tools/hciattach.8
index f9d295e..e658d87 100644
--- a/utils/tools/hciattach.8
+++ b/utils/tools/hciattach.8
@@ -69,6 +69,9 @@ Silicon Wave kits
 .TP
 .B bcsp
 Serial adapters using CSR chips with BCSP serial protocol
+.TP
+.B texas
+Texas Instruments' chips with HCILL serial protocol and BTS initialization files (put .bts files in /lib/firmware)
 .RE
 
 Supported IDs are (manufacturer id, product id)
diff --git a/utils/tools/hciattach.c b/utils/tools/hciattach.c
index 36f3c72..e382003 100644
--- a/utils/tools/hciattach.c
+++ b/utils/tools/hciattach.c
@@ -42,37 +42,13 @@
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/socket.h>
+#include <linux/types.h>
 
 #include <bluetooth/bluetooth.h>
 #include <bluetooth/hci.h>
 #include <bluetooth/hci_lib.h>
 
-#ifndef N_HCI
-#define N_HCI	15
-#endif
-
-#define HCIUARTSETPROTO		_IOW('U', 200, int)
-#define HCIUARTGETPROTO		_IOR('U', 201, int)
-#define HCIUARTGETDEVICE	_IOR('U', 202, int)
-
-#define HCI_UART_H4	0
-#define HCI_UART_BCSP	1
-#define HCI_UART_3WIRE	2
-#define HCI_UART_H4DS	3
-
-struct uart_t {
-	char *type;
-	int  m_id;
-	int  p_id;
-	int  proto;
-	int  init_speed;
-	int  speed;
-	int  flags;
-	char *bdaddr;
-	int  (*init) (int fd, struct uart_t *u, struct termios *ti);
-};
-
-#define FLOW_CTL	0x0001
+#include "hciattach.h"
 
 static volatile sig_atomic_t __io_canceled = 0;
 
@@ -143,7 +119,7 @@ static int uart_speed(int s)
 	}
 }
 
-static int set_speed(int fd, struct termios *ti, int speed)
+int set_speed(int fd, struct termios *ti, int speed)
 {
 	cfsetospeed(ti, uart_speed(speed));
 	return tcsetattr(fd, TCSANOW, ti);
@@ -152,7 +128,7 @@ static int set_speed(int fd, struct termios *ti, int speed)
 /* 
  * Read an HCI event from the given file descriptor.
  */
-static int read_hci_event(int fd, unsigned char* buf, int size) 
+int read_hci_event(int fd, unsigned char* buf, int size) 
 {
 	int remain, r;
 	int count = 0;
@@ -287,11 +263,49 @@ static int digi(int fd, struct uart_t *u, struct termios *ti)
 	return 0;
 }
 
+extern int brf_do_script(int fd, struct uart_t *u, struct termios *ti,
+							const char *bts_file);
+extern int is_it_texas(const __u8 *respond);
+extern const char *get_firmware_name(const __u8 *respond);
+
+#define BRF_DEEP_SLEEP_OPCODE_BYTE_1 	0x0c
+#define BRF_DEEP_SLEEP_OPCODE_BYTE_2 	0xfd
+#define BRF_DEEP_SLEEP_OPCODE		\
+	(BRF_DEEP_SLEEP_OPCODE_BYTE_1 |(BRF_DEEP_SLEEP_OPCODE_BYTE_2 << 8))
+
+static int texas_continue_script(int fd, struct uart_t *u, struct termios *ti)
+{
+	int dev_id, dd, ret = 0;
+
+	sleep(1);
+
+	dev_id = ioctl(fd, HCIUARTGETDEVICE, 0);
+	if (dev_id < 0) {
+		perror("cannot get device id");
+		return -1;
+	}
+
+	DPRINTF("\nAdded device hci%d\n", dev_id);
+
+	dd = hci_open_dev(dev_id);
+	if (dd < 0) {
+		perror("HCI device open failed");
+		return -1;
+	}
+
+	ret = brf_do_script(dd, u, ti, NULL);
+
+	hci_close_dev(dd);
+
+	return ret;
+}
+
 static int texas(int fd, struct uart_t *u, struct termios *ti)
 {
 	struct timespec tm = {0, 50000};
 	char cmd[4];
 	unsigned char resp[100];		/* Response */
+	const char *bts_file;
 	int n;
 
 	memset(resp,'\0', 100);
@@ -327,17 +341,20 @@ static int texas(int fd, struct uart_t *u, struct termios *ti)
 	} while (resp[4] != cmd[1] && resp[5] != cmd[2]);
 
 	/* Verify manufacturer */
-	if ((resp[11] & 0xFF) != 0x0d)
-		fprintf(stderr,"WARNING : module's manufacturer is not Texas Instrument\n");
+	if (! is_it_texas(resp)) {
+		fprintf(stderr,"ERROR: module's manufacturer is not Texas Instruments\n");
+		return -1;
+	}
 
-	/* Print LMP version */
-	fprintf(stderr, "Texas module LMP version : 0x%02x\n", resp[10] & 0xFF);
+	fprintf(stderr, "Found a Texas Instruments' chip!\n");
 
-	/* Print LMP subversion */
-	fprintf(stderr, "Texas module LMP sub-version : 0x%02x%02x\n", resp[14] & 0xFF, resp[13] & 0xFF);
+	bts_file = get_firmware_name(resp);
+	fprintf(stderr, "Firmware file : %s\n", bts_file);
+
+	n = brf_do_script( fd, u, ti, bts_file);
 
 	nanosleep(&tm, NULL);
-	return 0;
+	return n;
 }
 
 static int read_check(int fd, void *buf, int count)
@@ -1050,69 +1067,71 @@ static int bcm2035(int fd, struct uart_t *u, struct termios *ti)
 }
 
 struct uart_t uart[] = {
-	{ "any",        0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, NULL     },
-	{ "ericsson",   0x0000, 0x0000, HCI_UART_H4,   57600,  115200, FLOW_CTL, NULL, ericsson },
-	{ "digi",       0x0000, 0x0000, HCI_UART_H4,   9600,   115200, FLOW_CTL, NULL, digi     },
-	{ "texas",      0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, texas    },
+	{ "any",        0x0000, 0x0000, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, NULL, NULL, NULL     },
+	{ "ericsson",   0x0000, 0x0000, HCI_UART_H4, 0, 57600,  115200, FLOW_CTL, NULL, ericsson, NULL },
+	{ "digi",       0x0000, 0x0000, HCI_UART_H4, 0, 9600,   115200, FLOW_CTL, NULL, digi, NULL     },
 
-	{ "bcsp",       0x0000, 0x0000, HCI_UART_BCSP, 115200, 115200, 0,        NULL, bcsp     },
+	/* Texas Instruments Bluelink (BRF) modules */
+	{ "texas",      0x0000, 0x0000, HCI_UART_LL, BRF_DEEP_SLEEP_OPCODE, 115200, 115200, FLOW_CTL, NULL, texas, texas_continue_script    },
+
+	{ "bcsp",       0x0000, 0x0000, HCI_UART_BCSP, 0, 115200, 115200, 0,        NULL, bcsp, NULL     },
 
 	/* Xircom PCMCIA cards: Credit Card Adapter and Real Port Adapter */
-	{ "xircom",     0x0105, 0x080a, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, NULL     },
+	{ "xircom",     0x0105, 0x080a, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, NULL, NULL, NULL     },
 
 	/* CSR Casira serial adapter or BrainBoxes serial dongle (BL642) */
-	{ "csr",        0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, csr      },
+	{ "csr",        0x0000, 0x0000, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, NULL, csr, NULL      },
 
 	/* BrainBoxes PCMCIA card (BL620) */
-	{ "bboxes",     0x0160, 0x0002, HCI_UART_H4,   115200, 460800, FLOW_CTL, NULL, csr      },
+	{ "bboxes",     0x0160, 0x0002, HCI_UART_H4, 0, 115200, 460800, FLOW_CTL, NULL, csr, NULL      },
 
 	/* Silicon Wave kits */
-	{ "swave",      0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, swave    },
+	{ "swave",      0x0000, 0x0000, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, NULL, swave, NULL    },
 
 	/* ST Microelectronics minikits based on STLC2410/STLC2415 */
-	{ "st",         0x0000, 0x0000, HCI_UART_H4,    57600, 115200, FLOW_CTL, NULL, st       },
+	{ "st",         0x0000, 0x0000, HCI_UART_H4, 0, 57600, 115200, FLOW_CTL, NULL, st, NULL       },
 
 	/* ST Microelectronics minikits based on STLC2500 */
-	{ "stlc2500",   0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, "00:80:E1:00:AB:BA", stlc2500  },
+	{ "stlc2500",   0x0000, 0x0000, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, "00:80:E1:00:AB:BA", stlc2500, NULL  },
 
 	/* Philips generic Ericsson IP core based */
-	{ "philips",    0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, NULL     },
+	{ "philips",    0x0000, 0x0000, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, NULL, NULL, NULL     },
 
 	/* Philips BGB2xx Module */
-	{ "bgb2xx",    0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, "BD:B2:10:00:AB:BA", bgb2xx   },
+	{ "bgb2xx",    0x0000, 0x0000, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, "BD:B2:10:00:AB:BA", bgb2xx, NULL   },
 
 	/* Sphinx Electronics PICO Card */
-	{ "picocard",   0x025e, 0x1000, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, NULL     },
+	{ "picocard",   0x025e, 0x1000, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, NULL, NULL, NULL     },
 
 	/* Inventel BlueBird Module */
-	{ "inventel",   0x0000, 0x0000, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, NULL     },
+	{ "inventel",   0x0000, 0x0000, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, NULL, NULL, NULL     },
 
 	/* COM One Platinium Bluetooth PC Card */
-	{ "comone",     0xffff, 0x0101, HCI_UART_BCSP, 115200, 115200, 0,        NULL, bcsp     },
+	{ "comone",     0xffff, 0x0101, HCI_UART_BCSP, 0, 115200, 115200, 0,        NULL, bcsp, NULL     },
 
 	/* TDK Bluetooth PC Card and IBM Bluetooth PC Card II */
-	{ "tdk",        0x0105, 0x4254, HCI_UART_BCSP, 115200, 115200, 0,        NULL, bcsp     },
+	{ "tdk",        0x0105, 0x4254, HCI_UART_BCSP, 0, 115200, 115200, 0,        NULL, bcsp, NULL     },
 
 	/* Socket Bluetooth CF Card (Rev G) */
-	{ "socket",     0x0104, 0x0096, HCI_UART_BCSP, 230400, 230400, 0,        NULL, bcsp     },
+	{ "socket",     0x0104, 0x0096, HCI_UART_BCSP, 0, 230400, 230400, 0,        NULL, bcsp, NULL     },
 
 	/* 3Com Bluetooth Card (Version 3.0) */
-	{ "3com",       0x0101, 0x0041, HCI_UART_H4,   115200, 115200, FLOW_CTL, NULL, csr      },
+	{ "3com",       0x0101, 0x0041, HCI_UART_H4, 0, 115200, 115200, FLOW_CTL, NULL, csr, NULL      },
 
 	/* AmbiCom BT2000C Bluetooth PC/CF Card */
-	{ "bt2000c",    0x022d, 0x2000, HCI_UART_H4,    57600, 460800, FLOW_CTL, NULL, csr      },
+	{ "bt2000c",    0x022d, 0x2000, HCI_UART_H4, 0, 57600, 460800, FLOW_CTL, NULL, csr, NULL      },
 
 	/* Zoom Bluetooth PCMCIA Card */
-	{ "zoom",       0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200, 0,        NULL, bcsp     },
+	{ "zoom",       0x0279, 0x950b, HCI_UART_BCSP, 0, 115200, 115200, 0,        NULL, bcsp, NULL     },
 
 	/* Sitecom CN-504 PCMCIA Card */
-	{ "sitecom",    0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200, 0,        NULL, bcsp     },
+	{ "sitecom",    0x0279, 0x950b, HCI_UART_BCSP, 0, 115200, 115200, 0,        NULL, bcsp, NULL     },
 
 	/* Billionton PCBTC1 PCMCIA Card */
-	{ "billionton", 0x0279, 0x950b, HCI_UART_BCSP, 115200, 115200, 0,        NULL, bcsp     },
+	{ "billionton", 0x0279, 0x950b, HCI_UART_BCSP, 0, 115200, 115200, 0,        NULL, bcsp, NULL     },
 
 	/* Broadcom BCM2035 */
-	{ "bcm2035",    0x0A5C, 0x2035, HCI_UART_H4,   115200, 460800, FLOW_CTL, NULL, bcm2035  },
+	{ "bcm2035",    0x0A5C, 0x2035, HCI_UART_H4, 0, 115200, 115200, 0,        NULL, bcm2035, NULL  },
 
 	{ NULL, 0 }
 };
@@ -1205,6 +1224,9 @@ int init_uart(char *dev, struct uart_t *u, int send_break)
 		return -1;
 	}
 
+	if (u->init_post && u->init_post(fd, u, &ti) < 0)
+		return -1;
+
 	return fd;
 }
 
@@ -1212,7 +1234,7 @@ static void usage(void)
 {
 	printf("hciattach - HCI UART driver initialization utility\n");
 	printf("Usage:\n");
-	printf("\thciattach [-n] [-p] [-b] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]\n");
+	printf("\thciattach [-n] [-p] [-b] [-g device_param] [-t timeout] [-s initial_speed] <tty> <type | id> [speed] [flow|noflow] [bdaddr]\n");
 	printf("\thciattach -l\n");
 }
 
@@ -1220,8 +1242,9 @@ int main(int argc, char *argv[])
 {
 	struct uart_t *u = NULL;
 	int detach, printpid, opt, i, n, ld, err;
-	int to = 5; 
+	int to = 10;
 	int init_speed = 0;
+	__u16 device_param = 0;
 	int send_break = 0;
 	pid_t pid;
 	struct sigaction sa;
@@ -1231,7 +1254,7 @@ int main(int argc, char *argv[])
 	detach = 1;
 	printpid = 0;
 
-	while ((opt=getopt(argc, argv, "bnpt:s:l")) != EOF) {
+	while ((opt=getopt(argc, argv, "bnpt:g:s:l")) != EOF) {
 		switch(opt) {
 		case 'b':
 			send_break = 1;
@@ -1249,6 +1272,10 @@ int main(int argc, char *argv[])
 			to = atoi(optarg);
 			break;
 
+		case 'g':
+			device_param = (__u16)strtol(optarg, NULL, 16);
+			break;
+
 		case 's':
 			init_speed = atoi(optarg);
 			break;
@@ -1328,12 +1355,17 @@ int main(int argc, char *argv[])
 	if (init_speed)
 		u->init_speed = init_speed;
 
+	/* If user specified a device parameter, use that instead of
+	   the hardware's default */
+	if (device_param)
+		u->device_param = device_param;
+
 	memset(&sa, 0, sizeof(sa));
 	sa.sa_flags   = SA_NOCLDSTOP;
 	sa.sa_handler = sig_alarm;
 	sigaction(SIGALRM, &sa, NULL);
 
-	/* 5 seconds should be enough for initialization */
+	/* 10 seconds should be enough for initialization */
 	alarm(to);
 
 	n = init_uart(dev, u, send_break);
diff --git a/utils/tools/hciattach.h b/utils/tools/hciattach.h
new file mode 100644
index 0000000..c739101
--- /dev/null
+++ b/utils/tools/hciattach.h
@@ -0,0 +1,69 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2000-2001  Qualcomm Incorporated
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@xxxxxxxxxxxx>
+ *  Copyright (C) 2002-2008  Marcel Holtmann <marcel@xxxxxxxxxxxx>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef _HCIATTACH_H_
+#define _HCIATTACH_H_
+
+#ifndef N_HCI
+#define N_HCI	15
+#endif
+
+#define HCIUARTSETPROTO		_IOW('U', 200, int)
+#define HCIUARTGETPROTO		_IOR('U', 201, int)
+#define HCIUARTGETDEVICE	_IOR('U', 202, int)
+
+#define HCI_UART_H4	0
+#define HCI_UART_BCSP	1
+#define HCI_UART_3WIRE	2
+#define HCI_UART_H4DS	3
+#define HCI_UART_LL	4
+
+#ifdef HCIATTACH_DEBUG
+#define DPRINTF(x...)	printf(x)
+#else
+#define DPRINTF(x...)
+#endif
+
+struct uart_t {
+	char *type;
+	int  m_id;
+	int  p_id;
+	int  proto;
+	__u16 device_param;
+	int  init_speed;
+	int  speed;
+	int  flags;
+	char *bdaddr;
+	int  (*init) (int fd, struct uart_t *u, struct termios *ti);
+	int  (*init_post) (int fd, struct uart_t *u, struct termios *ti);
+};
+
+#define FLOW_CTL	0x0001
+
+extern int set_speed(int fd, struct termios *ti, int speed);
+extern int read_hci_event(int fd, unsigned char* buf, int size);
+
+#endif /* _HCIATTACH_H_ */
+
diff --git a/utils/tools/hciattach_ti.c b/utils/tools/hciattach_ti.c
new file mode 100644
index 0000000..ad9f12a
--- /dev/null
+++ b/utils/tools/hciattach_ti.c
@@ -0,0 +1,455 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2007-2008  Texas Instruments
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <syslog.h>
+#include <termios.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/types.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#include "hciattach.h"
+
+#ifndef MAKEWORD
+#define MAKEWORD(a, b)      ((__u16)(((__u8)(a)) | ((__u16)((__u8)(b))) << 8))
+#endif
+
+#define TI_MANUFACTURER_ID		13
+
+#define FIRMWARE_DIRECTORY 		"/lib/firmware/"
+
+#define ACTION_SEND_COMMAND		1
+#define ACTION_WAIT_EVENT		2
+#define ACTION_SERIAL			3
+#define ACTION_DELAY			4
+#define ACTION_RUN_SCRIPT		5
+#define ACTION_REMARKS			6
+
+
+#define FILE_HEADER_MAGIC   		0x42535442
+
+/*
+ * BRF Firmware header
+ */
+struct bts_header {
+	__u32	magic;
+	__u32	version;
+	__u8	future[24];
+	__u8	actions[0];
+}__attribute__ ((packed));
+
+/*
+ * BRF Actions structure
+ */
+struct bts_action {
+	__u16	type;
+	__u16	size;
+	__u8	data[0];
+} __attribute__ ((packed));
+
+struct bts_action_send
+{
+	__u8 data[0];
+} __attribute__ ((packed));
+
+struct bts_action_wait
+{
+	__u32 msec;
+	__u32 size;
+	__u8 data[0];
+}__attribute__ ((packed));
+
+struct bts_action_delay
+{
+	__u32 msec;
+}__attribute__ ((packed));
+
+struct bts_action_serial
+{
+	__u32 baud;
+	__u32 flow_control;
+}__attribute__ ((packed));
+
+FILE *bts_load_script(const char* file_name, __u32* version)
+{
+	struct bts_header header;
+	FILE* fp;
+
+	fp = fopen(file_name, "rb");
+	if (!fp) {
+		perror("can't open firmware file");
+		goto out;
+	}
+
+	if (1 != fread(&header, sizeof(struct bts_header), 1, fp)) {
+		perror("can't read firmware file");
+		goto errclose;
+	}
+
+	if (header.magic != FILE_HEADER_MAGIC) {
+		fprintf(stderr, "%s not a legal TI firmware file\n", file_name);
+		goto errclose;
+	}
+
+	if (NULL != version)
+		*version = header.version;
+
+	goto out;
+
+errclose:
+	fclose(fp);
+	fp = NULL;
+out:
+	return fp;
+}
+
+unsigned long bts_fetch_action(FILE* fp,
+				unsigned char* action_buf,
+				unsigned long buf_size,
+				__u16* action_type)
+{
+	struct bts_action action_hdr;
+	unsigned long nread;
+
+	if (!fp)
+		return 0;
+
+	if (1 != fread(&action_hdr, sizeof(struct bts_action), 1, fp))
+		return 0;
+
+	if (action_hdr.size > buf_size) {
+		fprintf(stderr, "bts_next_action: not enough space to read next action\n");
+		return 0;
+	}
+
+	nread = fread(action_buf, sizeof(__u8), action_hdr.size, fp);
+	if (nread != (action_hdr.size)) {
+		fprintf(stderr, "bts_next_action: fread failed to read next action\n");
+		return 0;
+	}
+
+	*action_type = action_hdr.type;
+
+	return nread * sizeof(__u8);
+}
+
+void bts_unload_script(FILE* fp)
+{
+	if (fp)
+		fclose(fp);
+}
+
+int is_it_texas(const __u8 *respond)
+{
+	__u16 manufacturer_id;
+
+	manufacturer_id = MAKEWORD(respond[11], respond[12]);
+
+	return TI_MANUFACTURER_ID == manufacturer_id ? 1 : 0;
+}
+
+const char *get_firmware_name(const __u8 *respond)
+{
+	static char firmware_file_name[PATH_MAX] = {0};
+	__u16 version = 0, chip = 0, min_ver = 0, maj_ver = 0;
+
+	version = MAKEWORD(respond[13], respond[14]);
+	chip =  (version & 0x7C00) >> 10;
+	min_ver = (version & 0x007F);
+	maj_ver = (version & 0x0380) >> 7;
+
+	if (version & 0x8000)
+		maj_ver |= 0x0008;
+
+	sprintf(firmware_file_name, FIRMWARE_DIRECTORY "TIInit_%d.%d.%d.bts",
+						chip, maj_ver, min_ver);
+
+	return firmware_file_name;
+}
+
+static void brf_delay(struct bts_action_delay *delay)
+{
+	usleep(1000*delay->msec);
+}
+
+static int brf_set_serial_params(struct bts_action_serial *serial_action,
+				int fd,
+				struct uart_t *u,
+				struct termios *ti)
+{
+	fprintf(stderr, "texas: changing baud rate to %u, flow control to %u\n",
+						serial_action->baud,
+						serial_action->flow_control );
+
+	tcflush(fd, TCIOFLUSH);
+
+	if (serial_action->flow_control)
+		ti->c_cflag |= CRTSCTS;
+	else
+		ti->c_cflag &= ~CRTSCTS;
+
+	if (tcsetattr(fd, TCSANOW, ti) < 0) {
+		perror("Can't set port settings");
+		return -1;
+	}
+
+	u->speed = serial_action->baud;
+
+	tcflush(fd, TCIOFLUSH);
+
+	if (set_speed(fd, ti, serial_action->baud) < 0) {
+		perror("Can't set baud rate");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int brf_send_command_socket(int fd, struct bts_action_send* send_action)
+{
+	char response[1024] = {0};
+	hci_command_hdr *cmd = (hci_command_hdr *) send_action->data;
+	uint16_t opcode = cmd->opcode;
+
+	struct hci_request rq;
+	memset(&rq, 0, sizeof(rq));
+	rq.ogf    = cmd_opcode_ogf(opcode);
+	rq.ocf    = cmd_opcode_ocf(opcode);
+	rq.event  = EVT_CMD_COMPLETE;
+	rq.cparam = &send_action->data[3];
+	rq.clen   = send_action->data[2];
+	rq.rparam = response;
+	rq.rlen   = sizeof(response);
+
+	if (hci_send_req(fd, &rq, 15) < 0) {
+		perror("Cannot send hci command to socket");
+		return -1;
+	}
+
+	/* verify success */
+	if (response[0]) {
+		errno = EIO;
+		return -1;
+	}
+
+	return 0;
+}
+
+static int brf_send_command_file(int fd, struct bts_action_send* send_action, long size)
+{
+	unsigned char response[1024] = {0};
+	long ret = 0;
+
+	/* send command */
+	if (size != write(fd, send_action, size)) {
+		perror("Texas: Failed to write action command");
+		return -1;
+	}
+
+	/* read response */
+	ret = read_hci_event(fd, response, sizeof(response));
+	if (ret < 0) {
+		perror("texas: failed to read command response");
+		return -1;
+	}
+
+	/* verify success */
+	if (ret < 7 || 0 != response[6]) {
+		fprintf( stderr, "TI init command failed.\n" );
+		errno = EIO;
+		return -1;
+	}
+
+	return 0;
+}
+
+static int brf_send_command(int fd, struct bts_action_send* send_action,
+					long size, int hcill_installed)
+{
+	int ret = 0;
+	char *fixed_action;
+
+	/* remove packet type when giving to socket API */
+	if (hcill_installed) {
+		fixed_action = ((char *) send_action) + 1;
+		ret = brf_send_command_socket(fd, (struct bts_action_send *)
+								fixed_action);
+	} else {
+		ret = brf_send_command_file(fd, send_action, size);
+	}
+
+	return ret;
+}
+
+static int brf_do_action(	__u16 brf_type, __u8 *brf_action,
+				long brf_size, int fd,
+				struct uart_t *u, struct termios *ti,
+				int hcill_installed)
+{
+	int ret = 0;
+
+	switch (brf_type) {
+	case ACTION_SEND_COMMAND:
+		DPRINTF("W");
+		ret = brf_send_command(fd, (struct bts_action_send*)
+					brf_action, brf_size, hcill_installed);
+		break;
+	case ACTION_WAIT_EVENT:
+		DPRINTF("R");
+		break;
+	case ACTION_SERIAL:
+		DPRINTF("S");
+		ret = brf_set_serial_params((struct bts_action_serial *)
+							brf_action, fd, u, ti);
+		break;
+	case ACTION_DELAY:
+		DPRINTF("D");
+		brf_delay((struct bts_action_delay *) brf_action);
+		break;
+	case ACTION_REMARKS:
+		DPRINTF("C");
+		break;
+	default:
+		fprintf(stderr, "brf_init: unknown firmware action type (%d)\n",
+								brf_type);
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * tests whether a given brf action is a HCI_VS_Sleep_Mode_Configurations cmd
+ */
+static int brf_action_is_deep_sleep(struct uart_t *u, __u8 *brf_action,
+						long brf_size, __u16 brf_type)
+{
+	__u16 opcode;
+
+	if (brf_type != ACTION_SEND_COMMAND)
+		return 0;
+
+	if (brf_size < 3)
+		return 0;
+
+	if (brf_action[0] != HCI_COMMAND_PKT)
+		return 0;
+
+	/* HCI data is little endian */
+	opcode = brf_action[1] | (brf_action[2] << 8);
+
+	if (opcode != u->device_param)
+		return 0;
+
+	/* action is deep sleep configuration command ! */
+	return 1;
+}
+
+/*
+ * This function is called twice.
+ * The first time it is called, it loads the brf script, and executes its
+ * commands until it reaches a deep sleep command (or its end).
+ * The second time it is called, it assumes HCILL protocol is set up,
+ * and sends rest of brf script via the supplied socket.
+ */
+int brf_do_script(int fd, struct uart_t *u, struct termios *ti,
+							const char *bts_file)
+{
+	int ret = 0,  hcill_installed = bts_file ? 0 : 1;
+	__u32 vers;
+	static FILE *brf_script_file = NULL;
+	static __u8 brf_action[256];
+	static long brf_size;
+	static __u16 brf_type;
+
+	/* is it the first time we are called ? */
+	if (0 == hcill_installed) {
+		DPRINTF("Sending script to serial device\n");
+		brf_script_file = bts_load_script(bts_file, &vers );
+		if (!brf_script_file) {
+			fprintf(stderr, "Warning: cannot find BTS file: %s\n",
+					bts_file);
+			return 0;
+		}
+
+		fprintf( stderr, "Loaded BTS script version %u\n", vers );
+
+		brf_size = bts_fetch_action(	brf_script_file,
+						brf_action,
+						sizeof(brf_action),
+						&brf_type );
+		if (brf_size == 0) {
+			fprintf(stderr, "Warning: BTS file is empty !");
+			return 0;
+		}
+	}
+	else {
+		DPRINTF("Sending script to bluetooth socket\n");
+	}
+
+	/* execute current action and continue to parse brf script file */
+	while (brf_size != 0) {
+		ret = brf_do_action(	brf_type, brf_action, brf_size,
+					fd, u, ti, hcill_installed);
+		if (ret == -1)
+			break;
+
+		brf_size = bts_fetch_action(	brf_script_file,
+						brf_action,
+						sizeof(brf_action),
+						&brf_type );
+
+		/* if this is the first time we run (no HCILL yet) */
+		/* and a deep sleep command is encountered */
+		/* we exit */
+		if (	0 == hcill_installed &&
+			brf_action_is_deep_sleep(u, brf_action,
+						brf_size, brf_type))
+			return 0;
+	}
+
+	bts_unload_script(brf_script_file);
+	brf_script_file = NULL;
+	DPRINTF("\n");
+
+	return ret;
+}
+
-- 
1.5.4.3

-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
Bluez-devel mailing list
Bluez-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/bluez-devel

[Index of Archives]     [Linux Bluetooth Devel]     [Linux USB Devel]     [Network Devel]     [Linux Audio Users]     [Yosemite News]     [Linux SCSI]

  Powered by Linux