|
From: Gordon M. <gm...@us...> - 2001-03-20 16:41:03
|
The following files were modified in linux/drivers/char/bluetooth:
Name Old version New version Comment
---- ----------- ----------- -------
bluetooth.c 1.154 1.154.2.1=20=20=20=20=20=20=20
hci.c 1.132 1.132.2.1=20=20=20=20=20=20=20
The accompanying log:
--Initial checking of changes to HCI. Including a) fixed the hci inquiry ha=
ng b) changed buffer allocation strategy for hci inquiry c) converted to ca=
ll tables for HCI Command Status & Command Complete processing.
The diff of the modified file(s):
--- bluetooth.c 2001/03/20 15:29:49 1.154
+++ bluetooth.c 2001/03/20 16:42:53 1.154.2.1
@@ -41,8 +41,16 @@
=20
/****************** INCLUDE FILES SECTION ********************************=
***/
=20
-#include <linux/bluetooth/sysdep-2.1.h>
#include <linux/config.h>
+
+#ifdef CONFIG_BLUETOOTH_KERNEL_THREAD
+#define __KERNEL_SYSCALLS__
+#include <linux/proc_fs.h>
+#include <linux/devfs_fs_kernel.h>
+#include <linux/unistd.h>
+#endif
+
+#include <linux/bluetooth/sysdep-2.1.h>
#include <linux/termios.h>
#include <linux/tty.h>
#include <linux/module.h>
@@ -93,6 +101,11 @@
#include <asm/io.h>
#endif
=20
+#ifdef CONFIG_BLUETOOTH_KERNEL_THREAD
+#include <linux/unistd.h>
+int bt_kernel_thread(void *);
+#endif
+
/****************** DEBUG CONSTANT AND MACRO SECTION *********************=
***/
=20
#if BT_DRIVER_DEBUG
@@ -180,7 +193,9 @@
static s32 bt_ctrl_init(void);
static s32 bt_connect(u8 *bd_addr, u32 con_id);
static s32 bt_disconnect(u32 con_id);
+#ifdef BT_DRIVER_DEBUG
static const u8* psmname(u16 psm);
+#endif
static void release_wq_timer(struct timer_list *wq_timer);
static void wq_timeout(unsigned long ptr);
static s32 bt_execute_sdp_request(bt_sdp_request *sdpRequest);
@@ -388,7 +403,9 @@
static s32
bt_open(struct tty_struct *tty, struct file * filp)
{
+#if BT_DRIVER_DEBUG
s32 line =3D GET_TTYLINE(tty);
+#endif
s32 ret_val;
=20=09
BT_DRIVER("bt_open on line %d\n", line);=09
@@ -691,20 +708,41 @@
=20=09
/* Link Control Command */
=20
+#ifdef CONFIG_BLUETOOTH_HCI_INQUIRY
case HCIINQUIRY:
{=20
inquiry_results *inq_res;
s32 in_param[2];
- u8 lap[3];
+
+ // REVISIT The user should specify this...
+ // --gmcnutt
+ u8 lap[3] =3D { 0x9e, 0x8b, 0x33 };
+ u8 num_resp;
+ int ret;
=20=09=09
BT_DRIVER(FNC"HCINQUIRY\n");
=20=09=09
copy_from_user(in_param, (s32*)arg, 8);
- if (!(inq_res =3D hci_inquiry(lap, in_param[1] , in_param[0])))
+ num_resp =3D in_param[0];
+
+ if ((inq_res =3D (inquiry_results*)=20
+ kmalloc(sizeof(inquiry_results) + 6 * num_resp,=20
+ GFP_ATOMIC)) =3D=3D NULL) {
return -ENOMEM;
- copy_to_user((s32*)arg, inq_res, size + 6 * inq_res->nbr_of_units);
+ }
+=09=09
+ if ((ret =3D hci_inquiry(lap, in_param[1] , in_param[0],=20
+ inq_res)) < 0)
+ goto end_inquiry;
+
+ copy_to_user((s32*)arg, inq_res, size + 6 *=20
+ inq_res->nbr_of_units);
+ end_inquiry:
+ kfree(inq_res);
+ return ret;
break;
}
+#endif /* CONFIG_BLUETOOTH_HCI_INQUIRY */
=20=09
case HCILINKKEYREPLY:
{
@@ -1556,7 +1594,11 @@
(SESSIONSTATE(line) =3D=3D BT_ACTIVE)) {
D_WARN("already got connection on line %d\n",=20
GET_RFCOMMLINE(con_id));=20
+#ifdef __KERNEL__
+ return -EBUSY;
+#else
return -1;
+#endif
}=20
=20
BT_DRIVER(FNC"Connecting srv ch %d on line %d\n",
@@ -1570,7 +1612,14 @@
&bt_ctrl.connect_wq[line]);
=20
interruptible_sleep_on(&bt_ctrl.connect_wq[line]);
+#ifdef __KERNEL__
+ if ((SESSIONSTATE(line) =3D=3D BT_LOWERCONNECTED)||
+ (SESSIONSTATE(line) =3D=3D BT_ACTIVE))
+ return 0;
+ return -EAGAIN;
+#else
return bt_ctrl.session[line].connect_status;
+#endif
}
break;
=20
@@ -1854,6 +1903,7 @@
}
#endif
=20
+
/**********************************/
/* Bluetooth Stack Initialization */
/**********************************/
@@ -2017,7 +2067,6 @@
procfs_status);
}
=20
-#endif /* CONFIG_BLUETOOTH_PROC */
=20
#ifdef CONFIG_BLUETOOTH_USE_TCI
#if LINUX_VERSION_CODE >=3D KERNEL_VERSION(2,4,0)
@@ -2043,6 +2092,7 @@
=20=09
sdp_create_proc_file();
=20
+#endif /* CONFIG_BLUETOOTH_PROC */
=20
#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
sec_man_create_proc_file();
@@ -2060,6 +2110,7 @@
hci_data.get =3D hci_data.head;;
#endif
=20
+
return 0; /*success*/
}
=20
@@ -2519,6 +2570,7 @@
return 0;
}
=20
+#if BT_DRIVER_DEBUG
static const u8*
psmname(u16 psm)
{
@@ -2534,7 +2586,7 @@
return "UNKNOWN";
}
}
-
+#endif
#if LINUX_VERSION_CODE >=3D KERNEL_VERSION(2,4,0)
void
start_wq_timer(struct timer_list *wq_timer,
@@ -2628,4 +2680,191 @@
=20
#endif /* MODULE */
=20
+/****************** Kernel Thread ****************************************=
***/
+#ifdef CONFIG_BLUETOOTH_KERNEL_THREAD
+#include <linux/bluetooth/btcommon.h>
+#include <linux/types.h>
+
+#define INIT_BAUD B57600
+#define FINAL_BAUD B115200
+#define SERIAL "/dev/ttyS1"
+
+#ifdef __KERNEL__
+typedef struct my_inquiry_results {
+ u32 nbr_of_units;
+ u32 inq_time;
+ u8 bd_addr[60];
+} inquiry_results_t;
+#endif
+
+static int bt_ldisc =3D N_BT, ser_fd, bt_fd;
+
+static void cfmakeraw(struct termios *t){
+ t->c_iflag &=3D ~(IGNBRK|BRKINT|PARMRK|ISTRIP|IGNCR|IXON);
+ t->c_oflag &=3D ~OPOST;
+ t->c_lflag &=3D ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+ t->c_cflag &=3D ~(CSIZE|PARENB);
+ t->c_cflag |=3D CS8;
+}
+
+static int do_initial_serial_port_setup(void)
+{
+ struct termios t;
+ int ret =3D 0;
+
+ printk(__FUNCTION__"\n");
+
+ if ((ser_fd =3D open(SERIAL, O_RDWR, O_NOCTTY)) < 0) {
+ printk(__FUNCTION__":open '%s' failed\n", SERIAL);
+ return ser_fd;
+ }
+
+ if ((ret =3D ioctl(ser_fd, TCGETA, (unsigned long) &t)) < 0) {
+ printk(__FUNCTION__":ioctl TCGETA failed\n");
+ goto exit;
+ }
+
+ cfmakeraw(&t);
+
+ t.c_cflag &=3D ~CBAUD;
+ t.c_cflag |=3D INIT_BAUD | CS8 | CLOCAL;
+ t.c_oflag =3D 0;
+ t.c_lflag =3D 0;
+ t.c_cflag &=3D ~CRTSCTS;
+
+ if ((ret =3D ioctl(ser_fd, TCSETA, (unsigned long) &t)) < 0) {
+ printk(__FUNCTION__":ioctl TCSETA failed\n");
+ goto exit;
+ }
+
+ if ((ret =3D ioctl(ser_fd, TIOCSETD, (unsigned long)&bt_ldisc)) < 0) {
+ printk(__FUNCTION__":ioctl TIOCSETD failed\n");
+ goto exit;
+ }
+ exit:
+ return ret;
+}
+static int initialize_bluetooth_stack(void)
+{
+ unsigned int tmp =3D 115200;
+ int ret =3D 0;
+
+ printk(__FUNCTION__"\n");
+ if ((bt_fd =3D open("/dev/ttyBTC", O_RDWR, O_NOCTTY)) < 0) {
+ printk(__FUNCTION__":open '/dev/ttyBTC' failed\n");
+ ret =3D bt_fd;
+ goto exit;
+ }
+
+ if ((ret =3D ioctl(bt_fd, BTINITSTACK, 0)) < 0) {
+ printk(__FUNCTION__":ioctl BTINITSTACK failed\n");
+ goto exit;
+ }
+
+ if ((ret =3D ioctl(bt_fd, HCISETBAUDRATE, (unsigned long)&tmp)) < 0) {
+ printk(__FUNCTION__":ioctl HCISETBAUDRATE failed\n");
+ goto exit;
+ }
+ exit:
+ return ret;
+
+}
+static int do_final_serial_port_setup(void)
+{
+ struct termios t;
+ int ret =3D 0;
+
+ printk(__FUNCTION__"\n");
+
+ if ((ret =3D ioctl(ser_fd, TCGETA, (unsigned long) &t)) < 0) {
+ printk(__FUNCTION__":ioctl TCGETA failed\n");
+ goto exit;
+ }
+
+ cfmakeraw(&t);
+
+ t.c_cflag &=3D ~CBAUD;
+ t.c_cflag |=3D INIT_BAUD | CS8 | CLOCAL;
+ t.c_oflag =3D 0;
+ t.c_lflag =3D 0;
+ t.c_cflag &=3D ~CRTSCTS;
+
+ if ((ret =3D ioctl(ser_fd, TCSETA, (unsigned long) &t)) < 0) {
+ printk(__FUNCTION__":ioctl TCSETA failed\n");
+ goto exit;
+ }
+
+ if ((ret =3D ioctl(ser_fd, TIOCSETD, (unsigned long)&bt_ldisc)) < 0) {
+ printk(__FUNCTION__":ioctl TIOCSETD failed\n");
+ goto exit;
+ }
+ exit:
+ return ret;
+}
+static int check_bluetooth_address(void)
+{
+ unsigned char BD_addr[6];
+ int i, ret =3D 0;
+
+ printk(__FUNCTION__"\n");
+ if((ret =3D ioctl(bt_fd, HCIREADLOCALBDADDR, (unsigned long)BD_addr)) <=
=20
+ 0) {
+ printk(__FUNCTION__":ioctl HCIREADLOCALBDADDR failed");
+ goto exit;
+ }
+
+ printk(__FUNCTION__":Local BD address: ");
+ for (i =3D 0; i < 6; i++) printk("0x%x ", BD_addr[i]);
+ printk("\n");
+ exit:
+ return ret;
+}
+static int look_for_other_bluetooth_devices(void)
+{
+ inquiry_results_t inq_res;
+ int i, j, ret =3D 0;
+
+ printk(__FUNCTION__"\n");
+
+ inq_res.nbr_of_units =3D 10;
+ inq_res.inq_time =3D 5;
+
+ if ((ret =3D ioctl(bt_fd, HCIINQUIRY, (unsigned long)&inq_res)) < 0)
+ {
+ printk(__FUNCTION__":ioctl HCIINQUIRY failed\n");
+ goto exit;
+ }
+
+ printk(__FUNCTION__":Remote BD addresses:\n");
+
+ for (i =3D 0; i < inq_res.nbr_of_units; i++) {
+ for (j =3D 0; j < 6; j++)=20
+ printk("0x%x ", inq_res.bd_addr[i * j + j]);
+ printk("\n");
+ }
+ exit:
+ return ret;
+}
+int bt_kernel_thread(void *unused)
+{
+ int ret =3D 0;
+
+ printk(__FUNCTION__"\n");
+
+ if ((ret =3D do_initial_serial_port_setup()) < 0) goto exit;
+ if ((ret =3D initialize_bluetooth_stack()) < 0) goto exit;
+ if ((ret =3D do_final_serial_port_setup()) < 0) goto exit;
+ if ((ret =3D check_bluetooth_address()) < 0) goto exit;
+ if ((ret =3D look_for_other_bluetooth_devices()) < 0) goto exit;
+
+ /*
+ * At this point we can either spawn ppp and wait, or we might be
+ * able to just hang and let other apps use the other /dev/ttyBT*
+ * devices.
+ */
+ exit:
+ printk(__FUNCTION__":Returning %d\n", ret);
+ return ret;
+}
+#endif // CONFIG_BLUETOOTH_KERNEL_THREAD
/****************** END OF FILE bluetooth.c ******************************=
***/
--- hci.c 2001/03/16 07:38:48 1.132
+++ hci.c 2001/03/20 16:42:53 1.132.2.1
@@ -38,6 +38,8 @@
*
* $Id$
*
+ * REFERENCES
+ * Bluetooth Core Specification Version 1.0B [BCS]
*/
=20
/****************** INCLUDE FILES SECTION ********************************=
***/
@@ -135,6 +137,7 @@
=20
#define USE_NCPTIMER=20
#define NCP_TIMEOUT (3*HZ)
+#define USE_INQTIMER
=20
/****************** TYPE DEFINITION SECTION ******************************=
***/
=20
@@ -187,7 +190,6 @@
static void init_cmd_buf(void);
static void send_cmd_queue(void);
static void update_nhcp(s32 nhcp);
-static s32 send_inq_cmd_block(u8 *cmd, u8 len);
#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
static u8* get_bd(u16 con_hdl);
#endif
@@ -226,19 +228,11 @@
static void release_ncp_timer(void);
#endif
=20
-#ifdef USE_INQTIMER
-static void start_inq_timer(void);
-static void release_inq_timer(void);
-#endif
-
#ifdef __KERNEL__
#ifdef USE_NCPTIMER
static void ncp_timeout(unsigned long ptr);
#endif
static void cmd_timeout(unsigned long ptr);
-#ifdef USE_INQTIMER
-static void inq_timeout(unsigned long ptr);
-#endif
#endif
=20
#ifdef HCI_EMULATION
@@ -269,10 +263,8 @@
#ifdef USE_NCPTIMER
static struct timer_list hci_ncp_timer;
#endif
+static int hci_cmd_timeout;
static struct timer_list hci_cmd_timer;
-#ifdef USE_INQTIMER
-static struct timer_list hci_inq_timer;
-#endif
=20
#ifdef USE_NCPTIMER
static struct hw_info {
@@ -288,17 +280,18 @@
=20
/* semaphore for protecting shared data */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+#define DECLARE_SEMAPHORE(sem) static struct semaphore sem =3D MUTEX
+#define INIT_SEMAPHORE(sem,val)
static struct semaphore hci_cmd_semaphore =3D MUTEX;
-static struct semaphore hci_inq_semaphore =3D MUTEX;
#else
+#define DECLARE_SEMAPHORE(sem) static struct semaphore sem
+#define INIT_SEMAPHORE(sem,val) sema_init(&sem,val)
static struct semaphore hci_cmd_semaphore;
-static struct semaphore hci_inq_semaphore;
#endif /* LINUX_VERSION_CODE */
=20
#endif /* __KERNEL__ */
=20
static u32 hci_cmd_pending =3D 0;
-static u32 hci_inq_pending =3D 0;
=20
#if __KERNEL__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
@@ -318,9 +311,8 @@
=20
static s32 result_param;
=20
-static struct inquiry_results *inq_res =3D NULL;
-
static s32 test_hci_hdl;
+static u8 cmd_timer_active =3D 0;
=20
/****************** FUNCTION DEFINITION SECTION **************************=
***/
=20
@@ -358,6 +350,7 @@
=20=20=20
D_INDATA(__FUNCTION__", hci-%d\n", tmp_data_len);
while (count > 0) {
+ c =3D 0;
switch (state) {
=20=09=09=09
/* The first byte will tell us whether it is an event or a
@@ -370,8 +363,6 @@
case ACL_PKT: state =3D WAIT_FOR_ACL_HDR; break;
case SCO_PKT: state =3D WAIT_FOR_SCO_HDR; break;
default:
- D_ERR(__FUNCTION__ ": discarding %d bytes\n",
- count);
/* An unrecognized HCI header type is usually a
* sign of a problem with the lower level=20
* driver. For example, if the UART drops some
@@ -381,10 +372,11 @@
* the next one.
* --gmcnutt
*/
- return;
+ D_ERR(__FUNCTION__":bad packet type '0x%x', "\
+ "discarding %d bytes\n", *buf, count);
+ state =3D WAIT_FOR_PACKET_TYPE;=09
}
- buf +=3D 1;
- count -=3D 1;
+ c =3D 1;
break;
=20
/* If it is an event packet we wait for the next byte
@@ -393,22 +385,21 @@
D_STATE(__FUNCTION__", WAIT_FOR_EVENT_TYPE\n");
event_type =3D *buf;
state =3D WAIT_FOR_EVENT_LENGTH;
- buf +=3D 1;
- count -=3D 1;=20=20
+ c =3D 1;
break;
=20
/* If it is an event the length-field is one byte */
case WAIT_FOR_EVENT_LENGTH:
D_STATE(__FUNCTION__", WAIT_FOR_EVENT_LENGTH\n");
event_len =3D *buf;
+ if (event_len <=3D count) {
buf +=3D 1;
count -=3D 1;
- if (event_len <=3D count) {
process_event(buf, event_len, event_type);
- buf +=3D event_len;
- count -=3D event_len;
+ c =3D event_len;
state =3D WAIT_FOR_PACKET_TYPE;
} else {
+ c =3D 1;
state =3D WAIT_FOR_EVENT_PARAM;
}
break;
@@ -417,18 +408,14 @@
whole event */
case WAIT_FOR_EVENT_PARAM:
D_STATE(__FUNCTION__", WAIT_FOR_EVENT_PARAM\n");
- if (tmp_pos < event_len) {
c =3D MIN(count, event_len - tmp_pos);
memcpy(event_buf + tmp_pos, buf, c);
tmp_pos +=3D c;
- count -=3D c;
- buf +=3D c;
if (tmp_pos =3D=3D event_len) {
process_event(event_buf,event_len,
event_type);
state =3D WAIT_FOR_PACKET_TYPE;
}
- }
break;
=20
/* Here we wait for the whole data header, four bytes*/
@@ -437,8 +424,6 @@
c =3D MIN(count, ACL_HDR_LEN - tmp_pos);
memcpy(hdr + tmp_pos, buf, c);
tmp_pos +=3D c;
- buf +=3D c;
- count -=3D c;
if (tmp_pos =3D=3D ACL_HDR_LEN) {
hci_hdl =3D CHAR2INT12(hdr[1],hdr[0]);
pb_flag =3D (((u32) hdr[1]) & 0x30) >> 4;
@@ -460,20 +445,13 @@
}
}
=20
-
host_nbrcompleted_packets(hci_hdl, 1);
=20
-
-
/* When we change state we reset data_index,
because we are using separate buffers for
the HCI header and the HCI data */
tmp_pos =3D 0;
state =3D WAIT_FOR_ACL_DATA;
- } else if (tmp_pos < ACL_HDR_LEN) {
- D_REC(__FUNCTION__" Didn't got whole header length, waiting for more\n=
");
- } else {
- D_ERR(__FUNCTION__" incorredt ACL header length\n");
}
break;
=20
@@ -481,7 +459,6 @@
whole data packet and then we send it to a higher
protocol layer, in this case the L2CAP-layer */
case WAIT_FOR_ACL_DATA:
- D_STATE(__FUNCTION__", WAIT_FOR_ACL_DATA\n");
/* Find out how much data we can copy, don't copy more
than one HCI packet at time */
c =3D MIN(count, data_len - tmp_pos);
@@ -489,15 +466,12 @@
memcpy(in_buf->buf_ptr, buf, c);
in_buf->buf_ptr +=3D c;
in_buf->count +=3D c;
- D_REC(__FUNCTION__", in_buf->count =3D %d\n",in_buf->count);
+ D_REC(__FUNCTION__", Copied %d bytes into "\
+ "inbuffer\n", c);
}
=20=20=20=20=20=20=20
- /* Increase the data_index and decrease the amount of
- data */
tmp_pos +=3D c;
- count -=3D c;
=20=20=20=20=20=20=20
- D_REC(__FUNCTION__", Copied %d bytes into inbuffer\n",c);
if (tmp_pos =3D=3D data_len) {
if (in_buf) {
process_acl_data(in_buf, pb_flag);
@@ -506,7 +480,6 @@
}
state =3D WAIT_FOR_PACKET_TYPE;
}
- buf +=3D c;
break;
=20=20=20=20=20=20=20
/* wait for the SCO header, three bytes */
@@ -516,8 +489,6 @@
c =3D MIN(count,SCO_HDR_LEN - tmp_pos);
memcpy(hdr + tmp_pos, buf, c);
tmp_pos +=3D c;
- buf +=3D c;
- count -=3D c;
if (tmp_pos =3D=3D SCO_HDR_LEN) {
hci_hdl =3D CHAR2INT12(hdr[1],hdr[0]);
data_len =3D hdr[2];
@@ -534,8 +505,6 @@
c =3D MIN(count, data_len - tmp_pos);
process_sco_packet(buf, hci_hdl, c);
tmp_pos +=3D c;
- buf +=3D c;
- count -=3D c;
if (tmp_pos =3D=3D data_len) {
state =3D WAIT_FOR_PACKET_TYPE;
=20=20=20=20=20=20=20=20=20
@@ -545,10 +514,17 @@
break;
=20
default:
- D_ERR(__FUNCTION__", : Oups shouldn't be possible...\n");
+ D_ERR(__FUNCTION__", : Oups shouldn't be possible..."\
+ "\n");
break;
}
+
+ buf +=3D c;
+ count -=3D c;
}
+
+ return;
+
}
=20
void
@@ -592,761 +568,8 @@
#endif=09
}
=20
-/*
- * Parses an eventpacket, buf is the event parameters, length the event le=
ngth
- * and event_code is the event's opcode
- */
-
-void
-process_event(u8 *buf, u32 len, u32 event_code)
-{
- u16 hci_hdl;
- s32 i;
- PRINTPKT(__FUNCTION__, buf, len);
-
- switch (event_code) {
- case INQUIRY_COMPLETE:
- D_CMD("INQUIRY_COMPLETE\n");
- hci_inq_pending =3D 0;
- wake_up_interruptible(&inq_wq);
-#ifndef __KERNEL__
- for (i =3D 0; i < inq_res->nbr_of_units; i++) {
- D_CMD(__FUNCTION__", BD %d: %02x:%02x:%02x:%02x:%02x:%02x\n",i,
- inq_res->bd_addr[0+6*i],inq_res->bd_addr[1+6*i],
- inq_res->bd_addr[2+6*i],inq_res->bd_addr[3+6*i],
- inq_res->bd_addr[4+6*i],inq_res->bd_addr[5+6*i]);
- }
-#endif
- break;
-
- case INQUIRY_RESULT:
- {
- s32 i, j;
- u8 tmp_bd[6];
-
- D_CMD(__FUNCTION__", INQUIRY_RESULT\n");
- for(i =3D 1; i < (buf[0] * 14) + 1; i +=3D 14) {=09=09
- printk("BD addr %d\n", i % 14);
-=09=09=09
- for (j =3D 0; j < 6; j++) {
- tmp_bd[5-j] =3D buf[i + j];
- }
- print_data("BD",tmp_bd, 6);
- for (j =3D 0; j < inq_res->nbr_of_units; j++) {
- if (!memcmp(inq_res->bd_addr + inq_res->nbr_of_units * 6, tmp_bd, 6)) {
- j =3D inq_res->nbr_of_units;
- }
- }
- if (j >=3D inq_res->nbr_of_units) {
- memcpy(inq_res->bd_addr + inq_res->nbr_of_units * 6, tmp_bd, 6);
- inq_res->nbr_of_units +=3D 1;
- }
- }
- break;
- }
-
- case CONNECTION_COMPLETE:
- {
- u8 link_type;
-
- D_CMD(__FUNCTION__", CONNECTION_COMPLETE: %s\n",
- get_err_msg(buf[0]));
-
- hci_ctrl.nbr_of_connections +=3D 1;
-
- link_type =3D buf[9];
- hci_hdl =3D CHAR2INT12(buf[2], buf[1]);
- test_hci_hdl =3D hci_hdl;
-
- if (link_type =3D=3D ACL_LINK) {
- lp_connect_cfm(buf + 3, (u32) buf[0], hci_hdl);
- } else {
- tcs_add_sco_link(buf[0], hci_hdl);
- }
-
-#ifndef HCI_EMULATION
- if (buf[0]) {
- /* remove hci handle if connection failed */
- DSYS(__FUNCTION__", CONNECTION_COMPLETE %s\n", get_err_msg(buf[0]));
- hci_ctrl.nbr_of_connections -=3D 1;
- reset_hci_con_bd(hci_hdl);
- } else {
- DSYS(__FUNCTION__", ACL link is up\n");
- change_connection_packet_type(hci_hdl, DM3|DH3|DM5|DH5);
- set_hci_con(buf + 3, hci_hdl);
- remote_name_request(buf + 3);
-// write_link_policy_settings(hci_hdl, 0x01); /* enable m/s switch */
-// hci_switch_role(buf + 3, 0);
- role_discovery(hci_hdl);
- }
-#endif /* HCI_EMULATION */
-
- if (test_wq_active) {
- test_wq_active =3D 0;
- wake_up_interruptible(&test_wq);
- }
-=09=09
- break;
- }
- case CONNECTION_REQUEST:
- D_CMD(__FUNCTION__", CONNECTION_REQUEST\n");
-
- if (buf[9] =3D=3D ACL_LINK) {
- lp_connect_ind(buf); /* BD_ADDRESS */
- } else {
- printk(__FUNCTION__", CONNECTION_REQUEST for SCO LINK");
- accept_connection_request(buf, 0x01); /* role ignored for SCO */
- }
- break;
-
- case DISCONNECTION_COMPLETE:
- DSYS(__FUNCTION__", DISCONNECTION_COMPLETE %s\n", get_err_msg(buf[3]));
-
- lp_disconnect_ind(CHAR2INT12(buf[2], buf[1]));
- /* FIXME: No more NBR_OF_COMPLETE_PACKETS will arrive for this
- connection handle, if we only support point-to-point
- connections we can acl_num by reading the buffersizes again,
- but this will not work in a multipoint connection. */
- hci_ctrl.nbr_of_connections -=3D 1;
-
- reset_hci_con_bd(CHAR2INT12(buf[2], buf[1]));
-=09=09
- if (hci_ctrl.nbr_of_connections <=3D 0) {
- hci_read_buffer_size(HCI_NON_BLOCK);
- }
- break;
-
- case AUTHENTICATION_COMPLETE:
- DSYS(__FUNCTION__", AUTHENTICATION_COMPLETE\n");
-#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
- if (buf[0]) {
- D_ERR(__FUNCTION__", AUTHENTICATION_COMPLETE: %s\n", get_err_msg(buf[0]=
));
-=09=09=09
- }
-=09=09
- sec_man_event(HCI, get_bd(CHAR2INT12(buf[2], buf[1])), AUTHENTICATION_CO=
MPLETE, buf, 1);
-#endif
- break;
-
- case REMOTE_NAME_REQUEST_COMPLETE:
- D_CMD(__FUNCTION__", REMOTE_NAME_REQUEST_COMPLETE %s\n", buf + 7);
- if (buf[0]) {
- D_ERR(__FUNCTION__", REMOTE_NAME_REQUEST_COMPLETE: %s\n",
- get_err_msg(buf[0]));
- } else {
- if (strlen(buf + 7) > 248) {
- D_ERR(__FUNCTION__", REMOTE_NAME_REQUEST_COMPLETE: too long name lengt=
h %d\n", (int)strlen(buf + 7));
- break;
- }
- set_hci_con_name(buf + 1, buf + 7);
- }
- break;
-
- case ENCRYPTION_CHANGE:
- DSYS(__FUNCTION__", ENCRYPTION_CHANGE\n");
-#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
- if (buf[0]) {
- D_ERR(__FUNCTION__", ENCRYPTION_CHANGE: %s\n", get_err_msg(buf[0]));
- }
-
- {
- u8 tmp[2];
- tmp[0] =3D buf[0];
- tmp[1] =3D buf[3];
-=09=09
- sec_man_event(HCI, get_bd(CHAR2INT12(buf[2], buf[1=
])), ENCRYPTION_CHANGE, tmp, 2);
- }
-#endif
- break;
-=09
- case CHANGE_CONNECTION_LINK_KEY_COMPLETE:
- DSYS(__FUNCTION__", CHANGE_CONNECTION_LINK_KEY_COMPLETE Not implemented!=
\n");
- break;
-
- case MASTER_LINK_KEY_COMPLETE:
- DSYS(__FUNCTION__", MASTER_LINK_KEY_COMPLETE Not implemented!\n");
- break;
-
- case READ_REMOTE_SUPPORTED_FEATURES_COMPLETE:
- DSYS(__FUNCTION__", READ_REMOTE_SUPPORTED_FEATURES_COMPLETE Not implemen=
ted!\n");
- break;
-
- case READ_REMOTE_VERSION_INFORMATION_COMPLETE:
- DSYS(__FUNCTION__", READ_REMOTE_VERSION_INFORMATION_COMPLETE Not impleme=
nted!\n");
- break;
-
- case QOS_SETUP_COMPLETE:
- DSYS(__FUNCTION__", QOS_SETUP_COMPLETE Not implemented!\n");
- break;
-
- case COMMAND_COMPLETE:
- D_CMD(__FUNCTION__", COMMAND_COMPLETE\n");
-
- /* FIXME - stop any outstanding send timers if cmd_num is > 0*/
- D_QUEUE("<CC>\n");
-
- process_return_param(buf);
- update_nhcp(buf[0]);
- break;
-
- /* used to prevent host from waiting on reply when a=20
- command has been received in HW and is currently=20
- performing the task for this command */
-=09=09
- case COMMAND_STATUS:
- release_cmd_timer();
- /*FIXME: hci_switch_role() will generate COMMAND_STATUS that
- shouldn't call wake_up_interruptible() */
- D_CMD(__FUNCTION__", COMMAND_STATUS\n");
-=09=09
- if (buf[0]) {
- D_ERR(__FUNCTION__", COMMAND_STATUS: %s\n",get_err_msg(buf[0]));
- }
-=09=09
- update_nhcp(buf[1]);
- wake_up_interruptible(&hci_wq);
- break;
- case FLUSH_OCCURRED:
- D_CMD(__FUNCTION__", FLUSH_OCCURRED on hci_hdl %d\n",
- CHAR2INT12(buf[1],buf[0]));
- btmem_flushhandle(CHAR2INT12(buf[1],buf[0]));=09=09
- break;
-
- case HARDWARE_ERROR:
- D_ERR(__FUNCTION__", An hardware error with error code 0x%02x occurred\n=
Please refer to your bluetooth module manual\n", buf[0]);
- break;
-
- case ROLE_CHANGED:
- D_CMD(__FUNCTION__", ROLE_CHANGED\n");
-
- if (buf[0]) {=20
- D_ERR(__FUNCTION__", Role changed faild due to %s\n",
- get_err_msg(buf[0]));
- } else if (buf[7]) {
- DSYS(__FUNCTION__", Role was changed to Slave for unit with BD Address =
0x%04x%08x\n", CHAR2INT16(buf[6], buf[5]), CHAR2INT32(buf[4], buf[3], buf[2=
], buf[1]));
- } else {
- DSYS(__FUNCTION__", Role was changed to Master for unit with BD Address=
0x%04x%08x\n", CHAR2INT16(buf[6], buf[5]), CHAR2INT32(buf[4], buf[3], buf[=
2], buf[1]));
- }
- break;
-
- case NBR_OF_COMPLETED_PACKETS:=20
-
- D_CMD(__FUNCTION__", NUMBER_OF_COMPLETED_PACKETS\n");
-=09
- update_ncp(buf[0], buf + 1);
-
- D_QUEUE("<NCP:%d>\n",hci_ctrl.hc_buf.acl_num);
-
- break;
-
- case MODE_CHANGE:
- D_CMD(__FUNCTION__", MODE_CHANGE on hci_hdl %d\n",
- CHAR2INT12(buf[2],buf[1]));
- break;
-
- case RETURN_LINK_KEYS:
- D_CMD(__FUNCTION__", RETURN_LINK_KEYS event\n");
-#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
- {
- u8 tmp_str[23];
-
- for (i =3D 0; i < buf[0]; i++) {
- D_CMD("%d: ",i);
- tmp_str[0] =3D i;
- memcpy(tmp_str + 1, (buf + 1) + (i * 6), 6=
);
- memcpy(tmp_str + 7, (buf + 1) + (buf[0] * =
6) + (i * 16), 16);
- sec_man_event(HCI, buf + 1, RETURN_LINK_KE=
YS, tmp_str, 17);
- }
- }
-#endif
- break;
-=09
- case PIN_CODE_REQUEST:
- D_CMD(__FUNCTION__", PIN_CODE_REQUEST forwarding event to security manag=
er\n");
-#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
- sec_man_event(HCI, buf, PIN_CODE_REQUEST, NULL, 0);
-#endif
- break;
-=09
- case LINK_KEY_REQUEST:
- D_CMD(__FUNCTION__", LINK_KEY_REQUEST\n");
-#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
- sec_man_event(HCI, buf, LINK_KEY_REQUEST, NULL, 0);
-#endif
- break;
-
- case LINK_KEY_NOTIFICATION:
- D_CMD(__FUNCTION__", LINK_KEY_NOTIFICATION forwarding event to security =
manager\n");
-#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
- sec_man_event(HCI, buf, LINK_KEY_NOTIFICATION, buf + 6, 16);
-#endif
- break;
-
- case LOOPBACK_COMMAND:
- DSYS(__FUNCTION__", LOOPBACK_COMMAND, loopback mode not supported\n");
- break;
-
- case DATA_BUFFER_OVERFLOW:
- D_ERR(__FUNCTION__", DATA_BUFFER_OVERFLOW\n");
- break;
-
- case MAX_SLOTS_CHANGE:
- D_CMD(__FUNCTION__", MAX_SLOTS_CHANGE to %d\n",
- (u32) buf[2]);
- break;
-
- case READ_CLOCK_OFFSET_COMPLETE:
- D_CMD(__FUNCTION__", READ_CLOCK_OFFSET_COMPLETE\n");
- break;
-
- case CONNECTION_PACKET_TYPE_CHANGED:
- D_CMD(__FUNCTION__", CHANGE_CONNECTION_PACKET_TYPE\n");
- break;
-
- case QOS_VIOLATION:
- D_CMD(__FUNCTION__", QOS_VIOLATION\n");
- break;
-
- case PAGE_SCAN_MODE_CHANGE:
- DSYS(__FUNCTION__", PAGE_SCAN_MODE_CHANGE Not implemented\n");
- break;
-
- case PAGE_SCAN_REPETITION_MODE_CHANGE:
- DSYS(__FUNCTION__", PAGE_SCAN_REPETITION_MODE_CHANGE Not implemented\n");
- break;=09
-
- case VENDOR_EVENT:
- process_vendor_event(buf, len, event_code);
- break;
-
- default:
- DSYS(__FUNCTION__", UNKNOWN EVENT CODE 0x%x\n",event_code);
- break;
- }
-}
-
-
-/* Parses the return parameters from the command complete event, see the
- bluetooth baseband specification part H:1, chapter 5.2.14 for a further
- description of the command complete event. */
-
-void=20
-process_return_param(u8 *buf)
-{
- u32 ogf,ocf;
- u8 *r_val;
-
- /* buf points at the start of the event parameters of the command
- complete event. The second and third byte (buf[1] and buf[2])
- contains the op-code, which consists of the OGF and the OCF values,
- see the baseband specification part H:1, chapter 4.4.1 for a
- description of these.
-
- r_val is set to point at the beginning of the return parameters at
- the command complete event */
-
- ogf =3D (u32) buf[2] >> 2;
- ocf =3D CHAR2INT10(buf[2],buf[1]);
- r_val =3D buf + 3;
-
- switch (ogf) {
-
- case HCI_LC:
-=20=20=20=20=20=20=20=20=20=20
- switch (ocf) {
- case LINK_KEY_REQUEST_REPLY:
- release_cmd_timer();
-=09=09=09
- D_CMD(__FUNCTION__", LINK_KEY_REQUEST_REPLY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", LINK_KEY_REQUEST_REPLY %s\n", get_err_msg(r_val[0=
]));
- result_param =3D - r_val[0];=20
- }
- else {
- D_CMD(__FUNCTION__", LINK_KEY_REQUEST_REPLY Success\n");
- result_param =3D 0;
- }
-=09=09=09
- wake_up_interruptible(&hci_wq);
- break;
-=09=09
- case LINK_KEY_REQUEST_NEGATIVE_REPLY:
- release_cmd_timer();
-=09=09=09
- D_CMD(__FUNCTION__", LINK_KEY_REQUEST_NEGATIVE_REPLY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", LINK_KEY_REQUEST_NEGATIVE_REPLY %s\n", get_err_ms=
g(r_val[0]));
- result_param =3D - r_val[0];=20
- }
- else {
- D_CMD(__FUNCTION__", LINK_KEY_REQUEST_NEGATIVE_REPLY Success\n");
- result_param =3D 0;
- }
-=09=09=09
- wake_up_interruptible(&hci_wq);
- break;
-=09=09
- case PIN_CODE_REQUEST_REPLY:
- release_cmd_timer();
-=09=09=09=09=09
- D_CMD(__FUNCTION__", PIN_CODE_REQUEST_REPLY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", PIN_CODE_REQUEST_REPLY %s\n", get_err_msg(r_val[0=
]));
- result_param =3D - r_val[0];=20
- }
- else {
- D_CMD(__FUNCTION__", PIN_CODE_REQUEST_REPLY Success\n");
- result_param =3D 0;
- }
-
- wake_up_interruptible(&hci_wq);
- break;
-
-
- case PIN_CODE_REQUEST_NEGATIVE_REPLY:
- release_cmd_timer();
-=09=09=09
- D_CMD(__FUNCTION__", PIN_CODE_REQUEST_NEGATIVE_REPLY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", PIN_CODE_REQUEST_NEGATIVE_REPLY %s\n", get_err_ms=
g(r_val[0]));
- result_param =3D - r_val[0];=20
- }
- else {
- D_CMD(__FUNCTION__", PIN_CODE_REQUEST_NEGATIVE_REPLY Success\n");
- result_param =3D 0;
- }
-
- wake_up_interruptible(&hci_wq);
- break;=09
-
- default:
- D_CMD(__FUNCTION__", HCI_LC, ocf %d not recognised!\n", ocf);
- break;
- }
-
- break;
-=20=20=20=20=20=20=20=20=20=20
- case HCI_HC: /* Host Controller commands */
- release_cmd_timer();
-/* FIX ME : The correct timer should be released */
-=20=20=20=20=20=20=20=20=20=20
- switch (ocf) {
-=09=09=09
- case CREATE_NEW_UNIT_KEY:
- D_CMD(__FUNCTION__", CREATE_NEW_UNIT_KEY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", CREATE_NEW_UNIT_KEY %s\n", get_err_msg(r_val[0]));
- result_param =3D - r_val[0];=20
- } else {
- D_CMD(__FUNCTION__", CREATE_NEW_UNIT_KEY Success\n");
- result_param =3D 0;
- }
- break;
-=09=09=09
-=09=09=09
- case READ_STORED_LINK_KEY:
- D_CMD(__FUNCTION__", READ_STORED_LINK_KEY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", READ_STORED_LINK_KEY %s\n", get_err_msg(r_val[0])=
);
- result_param =3D - r_val[0];
- } else {
- D_CMD(__FUNCTION__", READ_STORED_LINK_KEY Success\n");
- result_param =3D CHAR2INT16(r_val[4], r_val[3]);
- }
- D_CMD(__FUNCTION__", Max number of Linkkeys: %d\n",
- CHAR2INT16(r_val[2], r_val[1]));
- D_CMD(__FUNCTION__", Number of Linkkeys read: %d\n",
- CHAR2INT16(r_val[4], r_val[3]));
- break;
-
- case WRITE_STORED_LINK_KEY:
- D_CMD(__FUNCTION__", WRITE_STORED_LINK_KEY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_STORED_LINK_KEY %s\n", get_err_msg(r_val[0]=
));
- result_param =3D - r_val[0];=20
- }
- else {
- D_CMD(__FUNCTION__", WRITE_STORED_LINK_KEY Success\n");
- result_param =3D 0;
- }
- break;
-
- case DELETE_STORED_LINK_KEY:
- D_CMD(__FUNCTION__", DELETE_STORED_LINK_KEY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", DELETE_STORED_LINK_KEY %s\n", get_err_msg(r_val[0=
]));
- result_param =3D - r_val[0];
- } else {
- D_CMD(__FUNCTION__", DELETE_STORED_LINK_KEY Success\n");
- result_param =3D CHAR2INT16(r_val[2], r_val[1]);
- }
-=09=09=09
- D_CMD(__FUNCTION__", Number of Linkkeys deleted: %d\n",
- CHAR2INT16(r_val[2], r_val[1]));
- break;=09
-=20=20=20=20=20=20=20=20=20=20=20=20
- case SET_HOST_CONTROLLER_TO_HOST_FLOW_CONTROL:
- D_CMD(__FUNCTION__", SET_HOST_CONTROLLER_TO_HOST_FLOW_CONTROL\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", SET_HOST_CONTROLLER_TO_HOST_FLOW_CONTROL: %s\n",
- get_err_msg(r_val[0]));
- break;
- }
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case HOST_BUFFER_SIZE:=20=20
- D_CMD(__FUNCTION__", HOST_BUFFER_SIZE\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", HOST_BUFFER_SIZE: %s\n",
- get_err_msg(r_val[0]));
- }
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case CHANGE_LOCAL_NAME:
- D_CMD(__FUNCTION__", CHANGE_LOCAL_NAME\n");=20=20=20=20=20=20=20=20=20=
=20=20=20
- if (r_val[0]) {
- D_ERR(__FUNCTION__", CHANGE_LOCAL_NAME: %s\n",
- get_err_msg(r_val[0]));
- }
- break;
-
- case READ_SCAN_ENABLE:
- D_CMD(__FUNCTION__", READ_SCAN_ENABLE\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", READ_SCAN_ENABLE: %s\n",
- get_err_msg(r_val[0]));
- result_param =3D -r_val[0];
- } else {
- result_param =3D r_val[1];
- }
- printk("READ_SCAN_ENABLE %d\n", result_param);
- break;
-=09=09=09
- case WRITE_SCAN_ENABLE:
- D_CMD(__FUNCTION__", WRITE_SCAN_ENABLE\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_SCAN_ENABLE: %s\n",
- get_err_msg(r_val[0]));
- }
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case WRITE_PAGESCAN_ACTIVITY:
- D_CMD(__FUNCTION__", WRITE_PAGESCAN_ACTIVITY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_PAGESCAN_ACTIVITY: %s\n",
- get_err_msg(r_val[0]));
- }
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case WRITE_INQUIRYSCAN_ACTIVITY:
- D_CMD(__FUNCTION__", WRITE_INQUIRYSCAN_ACTIVITY\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_INQUIRYSCAN_ACTIVITY: %s\n",
- get_err_msg(r_val[0]));
- result_param =3D -r_val[0];
- }
- break;
-
- case READ_AUTHENTICATION_ENABLE:
- D_CMD(__FUNCTION__", READ_AUTHENTICATION_ENABLE\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", READ_AUTHENTICATION_ENABLE: %s\n", get_err_msg(r_=
val[0]));
- result_param =3D -r_val[0];
- } else {
- result_param =3D r_val[1];
- }
- break;
-=09=09=09
- case WRITE_AUTHENTICATION_ENABLE:
- D_CMD(__FUNCTION__", WRITE_AUTHENTICATION_ENABLE\n");
- if(r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_AUTHENTICATION_ENABLE: %s\n",
- get_err_msg(r_val[0]));
- result_param =3D -r_val[0];
- }=20
- break;
-=09=09=09
- case READ_ENCRYPTION_MODE:
- D_CMD(__FUNCTION__", READ_ENCRYPTION_MODE\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", READ_ENCRYPTION_MODE: %s\n", get_err_msg(r_val[0]=
));
- result_param =3D -r_val[0];
- } else {
- result_param =3D r_val[1];
- }
- break;
-=09=09=09
- case WRITE_ENCRYPTION_MODE:
- D_CMD(__FUNCTION__", WRITE_AUTHENTICATION_ENABLE\n");
- if(r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_AUTHENTICATION_ENABLE: %s\n",
- get_err_msg(r_val[0]));
- result_param =3D -r_val[0];
- }
- break;
-=09=09=09
- case WRITE_CLASS_OF_DEVICE:
- D_CMD(__FUNCTION__", WRITE_CLASS_OF_DEVICE\n");
- if(r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_CLASS_OF_DEVICE: %s\n",
- get_err_msg(r_val[0]));
- }
- break;
-
- case WRITE_AUTOMATIC_FLUSH_TIMEOUT:
- D_CMD(__FUNCTION__" WRITE_AUTOMATIC_FLUSH_TIMEOUT\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_AUTOMATIC_FLUSH_TIMEOUT: %s\n",
- get_err_msg(r_val[0]));
- } else {
- D_CMD(__FUNCTION__", WRITE_AUTOMATIC_FLUSH_TIMEOUT Success\n");
- }
-=09=09=09
- break;
-
-=20=20=20=20=20=20=20=20=20=20=20=20
- case READ_LINK_SUPERVISION_TIMEOUT:
- D_CMD(__FUNCTION__", Link supervision timeout is: %d\n",
- CHAR2INT16(buf[4],buf[3]));
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case WRITE_LINK_SUPERVISION_TIMEOUT:
- D_CMD(__FUNCTION__", WRITE_LINK_SUPERVISION_TO (%d)\n", r_val[0]);
- if (r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_LINK_SUPERVISION_TO: %s\n",
- get_err_msg(r_val[0]));
- }
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case RESET:
- D_CMD(__FUNCTION__", RESET\n");=09=09=09=20=20=20=20=20=20
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case SET_EVENT_FILTER:
- D_CMD(__FUNCTION__", SET_EVENT_FILTER\n");=09=09=09=20=20=20=20=20=20
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- default:
- D_CMD(__FUNCTION__", HCI_HC, ocf %d not recognised!\n", ocf);
- break;
- }
- /* FIX ME : Wake up from the correct queue */
- wake_up_interruptible(&hci_wq);
- break;
-
- case HCI_LP: /* Link policy commands */
- switch (ocf) {
- case ROLE_DISCOVERY:
- printk(__FUNCTION__", ROLE_DISCOVERY: ");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", ROLE_DISCOVERY: %s\n",
- get_err_msg(r_val[0]));
- break;
- }
- if (r_val[3])
- printk("Connected as Slave.\n");
- else
- printk("Connected as Master. \n");
- break;
- case WRITE_LINK_POLICY_SETTINGS:
- printk(__FUNCTION__", WRITE_LINK_POLICY_SETTINGS \n ");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", WRITE_LINK_POLICY_SETTINGS: %s\n",
- get_err_msg(r_val[0]));
- break;
- }
- break;
- default:
- D_CMD(__FUNCTION__", HCI_LP, ocf %d not recognised!\n", ocf);
- break;
- }
- break;
-=09=09
- case HCI_IP: /* Informational parameters */
- release_cmd_timer();
-
- switch (ocf) {
- case READ_BUFFER_SIZE:
- D_CMD(__FUNCTION__", READ_BUFFER_SIZE\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", READ_BUFFER_SIZE: %s\n",
- get_err_msg(r_val[0]));
- break;
- }
- hci_ctrl.hc_buf.acl_len =3D CHAR2INT16(r_val[2],r_val[1]);
- hci_ctrl.hc_buf.sco_len =3D (u32) r_val[3];
- hci_ctrl.hc_buf.acl_num =3D CHAR2INT16(r_val[5],r_val[4]);
- hci_ctrl.hc_buf.sco_num =3D CHAR2INT16(r_val[7],r_val[6]);
- printk("\nHW module contains...\n");
- printk("%d ACL buffers at %d bytes\n%d SCO buffers at %d bytes\n\n",
- hci_ctrl.hc_buf.acl_num, hci_ctrl.hc_buf.acl_len,
- hci_ctrl.hc_buf.sco_num, hci_ctrl.hc_buf.sco_len);
-
-#ifdef __KERNEL__
-#ifdef USE_NCPTIMER
- hw.max_acl_num =3D hci_ctrl.hc_buf.acl_num;
-#endif
-#endif
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case READ_BD_ADDR:
- D_CMD(__FUNCTION__", READ_BD_ADDR\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", READ_BD_ADDR: %s\n",
- get_err_msg(r_val[0]));
- break;
- }=20=20=20=20=20=20=20=20=20=20=20=20
- PRINTPKT(__FUNCTION__", READ_BD_ADDR : ", &r_val[1], 6);
- memcpy(hci_ctrl.local_bd, &r_val[1],6);
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- default:
- D_CMD(__FUNCTION__", HCI_IP, ocf %d not recognised!\n", ocf);
- break;
- }
- wake_up_interruptible(&hci_wq);
- break;
-=20=20=20=20=20=20=20=20=20=20
- case HCI_TC: /* Test Commands */
- release_cmd_timer();
-
- switch (ocf) {=20=20
- case READ_LOOPBACK_MODE:
- D_CMD(__FUNCTION__", READ_LOOPBACK_MODE -- not impl\n");
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case WRITE_LOOPBACK_MODE:
- D_CMD(__FUNCTION__", WRITE_LOOPBACK_MODE -- not impl\n");
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- case ENABLE_DEVICE_UNDER_TEST_MODE:
- D_CMD(__FUNCTION__", ENABLE_DEVICE_UNDER_TEST_MODE\n");
- if (r_val[0]) {
- D_ERR(__FUNCTION__", ENABLE_DEVICE_UNDER_TEST_MODE: %s\n",
- get_err_msg(r_val[0]));
- break;
- }
- printk(__FUNCTION__", *** Local device now under test\n***");
- break;
-=20=20=20=20=20=20=20=20=20=20=20=20
- default:
- D_CMD(__FUNCTION__", HCI_TC, ocf %d not recognised!\n", ocf);
- break;
- }
- wake_up_interruptible(&hci_wq);
- break;
=20=20=20=20=20=20=20=20=20=20=20
- case MANUFACTURER_SPEC: { /* manufacturer specific */
- D_CMD(__FUNCTION__", MANUFACTURER_SPEC\n");
- process_vendor_return_param(ocf, r_val);
- }
- break;
=20=20=20=20=20=20=20=20=20
- default:
- D_CMD(__FUNCTION__", ogf %d, not recognised! \n", ogf);
- break;
- }
-}
=20
/*Parses an ACL-data packet and copies it into the hci_in-buffer, data is =
a=20
pointer to the data in the memory, pb_flag is the packet boundary flag=
=20
@@ -1419,24 +642,34 @@
return;
}
}
- if (i >=3D MAX_NBR_OF_CONNECTIONS) {
- D_ERR(__FUNCTION__", : Didn't find connection with con_hdl %d\n", con_hd=
l);
- }
+
+ D_ERR(__FUNCTION__" : Didn't find connection with con_hdl %d\n",=20
+ con_hdl);
}
=20
void
set_hci_con_name(u8 *bd, u8 *name)
{
s32 i;
+ u8 len;
=20
if (!name) {
- D_ERR(__FUNCTION__", set_hci_con_name: No name defined\n");
+ D_ERR(__FUNCTION__": No name defined\n");
return;
}
=20
+ // "A UTF-8 encoded name can be up to 248 bytes in length.
+ // If it is shorter than 248 bytes, the end is indicated by
+ // a NULL bytes (0x00)" -- Bluetooth Core Spec 1.0b p. 714
+ // We'll truncate the name if it's too long.
+ // --gmcnutt
+
+ if ((len =3D strlen(name)) > 248)
+ len =3D 248;
+
for (i =3D 0; i < MAX_NBR_OF_CONNECTIONS; i++) {
if (memcmp(hci_ctrl.con[i].bd, bd, 6) =3D=3D 0) {
- strcpy(hci_ctrl.con[i].name, name);
+ memcpy(hci_ctrl.con[i].name, name, len);
return;
}
}
@@ -1576,87 +809,6 @@
}
=20
void=20
-hci_init(void)
-{
- u32 i;
-
- DSYS(__FUNCTION__", Initialising HCI\n");
-
-#ifdef HCI_EMULATION
- DSYS("*** HCI emulator on ***\n");
-#else
- DSYS("HCI emulator off\n");
-#endif
-=09
-#ifdef __KERNEL__
-#if LINUX_VERSION_CODE >=3D KERNEL_VERSION(2,4,0)
- init_waitqueue_head(&hci_wq);
- init_waitqueue_head(&inq_wq);
- init_waitqueue_head(&set_baudrate_wq);
- init_waitqueue_head(&test_wq);
- sema_init(&hci_cmd_semaphore, 1);
- sema_init(&hci_inq_semaphore, 1);
-#endif /* LINUX_VERSION_CODE */
-#endif /* __KERNEL__ */
-
- DSYS(__FUNCTION__", Initialising HCI inbuffers [%d]\n", HCI_IN_SIZE);
-
- /* Initiate the hci inbuffers */
- for (i =3D 0; i < NBR_OF_HCI_INBUFFERS; i++) {
- hci_ctrl.hci_in_buf[i].buf_ptr =3D hci_ctrl.hci_in_buf[i].buf;
- hci_ctrl.hci_in_buf[i].count =3D 0;
- hci_ctrl.hci_in_buf[i].l2cap_len =3D 0;
- hci_ctrl.hci_in_buf[i].empty =3D TRUE;
- }
-=09
- for (i =3D 0; i < MAX_NBR_OF_CONNECTIONS; i ++) {
- hci_ctrl.con[i].state =3D NOT_CONNECTED;
- hci_ctrl.con[i].con_hdl =3D -1;
- }
-
-/* Here we set the buffer sizes to zero, just to avoid that they should get
- undefined values if the initiating read buffersize fails */
-
- hci_ctrl.hc_buf.acl_len =3D 0;
- hci_ctrl.hc_buf.sco_len =3D 0;
- hci_ctrl.hc_buf.acl_num =3D 0;
- hci_ctrl.hc_buf.sco_num =3D 0;
-
- init_cmd_buf();
-
- hci_ctrl.nbr_of_connections =3D 0;
- hci_ctrl.hc_buf.cmd_num =3D 1;
-
-#ifdef __KERNEL__
- send_data_task.routine =3D (void*)send_acl_data_task;
- send_data_task.data =3D NULL;
-#endif
-
- /* always... */
- DSYS(__FUNCTION__", Reading buffer sizes in the module...\n");
- hci_read_buffer_size(HCI_BLOCK);
-
- hci_read_firmware_rev_info();
-
-// hci_read_stored_link_key(NULL,1);
-
- //hci_write_authentication_enable(1);
-#ifdef HOST_FLOW_CTRL
- DSYS(__FUNCTION__", Host flow control enabled\n");
-#else
- DSYS(__FUNCTION__", Host flow control not enabled\n");
-#endif
-=09
- hci_set_host_controller_flow_control(TRUE);
-
- hci_host_buffer_size(HCI_ACL_LEN,HCI_SCO_LEN,HCI_ACL_NUM,HCI_SCO_NUM);
-
-#ifdef USE_NCPTIMER
- start_ncp_timer();=09
-#endif
-}
-
-void=20
hci_shutdown(void)
{
#ifdef USE_NCPTIMER
@@ -1664,6 +816,10 @@
#endif
}
=20
+/*************************************************************************=
***/
+/*************************** HCI Commands ********************************=
***/
+/*************************************************************************=
***/
+
/* Start of the definition of the functions performing all the different
HCI commands. The functions will be defined in the same order as they a=
re
described in the HCI specification, part H:1 of the bluetooh core
@@ -1672,57 +828,247 @@
=20
/* Definition of Link Control Commands */
=20
-/* This function will cause the Bluetooth device to enter Inquiry Mode. In=
quiry
- Mode is used to discover other nearby Bluetooth devices. The LAP input
- parameter contains the LAP from which the inquiry access code shall be
- derived when the inquiry procedure is made. The Inquiry_length parameter
- specifies the total duration of the Inquiry Mode and, when this time=20
- expires, Inquiry will be halted. The Num_Responses parameter specifies=
=20
- the number of responses that can be received before the Inquiry is halt=
ed.*/
+#ifdef CONFIG_BLUETOOTH_HCI_INQUIRY /************************************=
***/
+// Adds about 1k
=20
-inquiry_results*=20
-hci_inquiry(u8 *lap, u8 inq_len, u8 num_resp)
+// See [BSC] Appendix VIII 1.1
+static const u8 GIAC[] =3D { 0x9e, 0x8b, 0x33 };
+static const u8 LIAC[] =3D { 0x9e, 0x8b, 0x00 };
+
+static struct inquiry_results *pending_inq_res =3D NULL;
+static u32 hci_inq_pending =3D 0;
+
+#ifdef __KERNEL__
+static struct timer_list hci_inq_timer;
+DECLARE_SEMAPHORE(hci_inq_semaphore);
+static void hci_inquiry_init(void)
{
- s32 tmp;
+ INIT_SEMAPHORE(hci_inq_semaphore, 1);
+}
+static void inq_timeout(unsigned long ptr)
+{
+ /* The command timed out, then we reset the command buffer counter to
+ 1 again */
+ /* FIX ME: What to do here !! */
+/* hci_ctrl.hc_buf.cmd_num =3D 1;*/
+ printk(__FUNCTION__", Timeout when waiting for inquiry response\n");
+ hci_inq_pending =3D 0;
+ wake_up_interruptible(&inq_wq);
+}
+static void start_inq_timer(void)
+{
+ D_CMD(__FUNCTION__"\n");
+ init_timer(&hci_inq_timer);
+ hci_inq_timer.function =3D inq_timeout;
+ hci_inq_timer.data =3D 0;
+ hci_inq_timer.expires =3D jiffies + 10*HZ;
+ add_timer(&hci_inq_timer);
+}
+static void release_inq_timer(void)
+{
+ D_CMD(__FUNCTION__"\n");
+ del_timer(&hci_inq_timer);
+ hci_inq_pending =3D 0;
+}
+#else
+#define inq_timeour(ptr)
+#define start_inq_timer()
+#define release_inq_timer()
+#endif // __KERNEL__
+//------------------------------------------------------------------------=
-----
+// hci_inquiry -- find other Bluetooth devices
+//
+// "This function will cause the Bluetooth device to enter Inquiry=
=20
+// Mode. Inquiry Mode is used to discover other nearby Bluetooth=
=20
+// devices. The LAP input parameter contains the LAP from which t=
he=20
+// inquiry access code shall be derived when the inquiry procedur=
e is=20
+// made. The Inquiry_length parameter specifies the total duratio=
n of=20
+// the Inquiry Mode and, when this time expires, Inquiry will be=
=20
+// halted. The Num_Responses parameter specifies the number of=20
+// responses that can be received before the Inquiry is halted."
+// [BCS] 4.5.1 p=
542
+//
+// This routine blocks the calling process until a) we receive the
+// Inquiry Complete event b) the Command Status returns an error c)
+// we time out waiting for Command Status or d) we timeout waiting
+// for the Inquiry Complete event.
+//
+// Also, if another process has already started an HCI Inquiry then
+// the calling process will proceed only after that inquiry comple=
tes.
+//
+// PARMS
+// lap Specifies the Inquiry Access Code (IAC) we'll use. All
+// devices in range will respond to the General Inquiry Ac=
cess
+// Code (GIAC) (LAP =3D 0x9e8b33). The only other legal va=
lue as
+// of [BCS] is the Limited Dedicated Inquiry Access Code=
=20
+// (LIAC) (LAP=3D0x9e8b00).
+//
+// inq_len
+// The maximum amount of time spent before the h/w stops t=
he
+// inquiry. Units are 1.28 sec. Range: 0x01 - 0x30.
+// REFERENCES
+// [BCS] 4.2.1, 13.1, Appendix VIII 1.1
+//------------------------------------------------------------------------=
-----
+int hci_inquiry(u8 *lap, u8 inq_len, u8 num_resp, inquiry_results *inq_res)
+{
+ int ret =3D 0;
=20
- D_CMD(__FUNCTION__", Sending inquiry()\n");
+#ifdef __KERNEL__
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+ struct wait_queue wait =3D { current, NULL};
+#else
+ DECLARE_WAITQUEUE(wait, current);
+#endif
+#endif
=20
- /* FIXME: Check if lap is valid first */
- /* Set default lap */
- lap[0] =3D 0x33;
- lap[1] =3D 0x8b;
- lap[2] =3D 0x9e;
+ D_CMD(__FUNCTION__ "\n");
=20
- /* Free any previous response */
- kfree(inq_res);
+ // Check for a valid LAP.
+ if (!memcmp(lap, GIAC, 3) && !memcmp(lap, LIAC, 3))
+ return -EINVAL;=09
=20
- inq_res =3D (inquiry_results*) kmalloc(sizeof(inquiry_results)
- + 6 * num_resp, GFP_ATOMIC);
- if (!inq_res)
- return NULL;
+#ifdef __KERNEL__
+ // Become the pending inquiry...
+ down(&hci_inq_semaphore);
+ pending_inq_res =3D inq_res;
+ hci_inq_pending =3D 1;=09
+#endif
=20
inq_res->nbr_of_units =3D 0;
=20
c_pkt.type =3D CMD_PKT;
c_pkt.opcode =3D hci_put_opcode(INQUIRY, HCI_LC) ;
-
memcpy(c_pkt.data, lap, 3);
c_pkt.data[3] =3D inq_len;
c_pkt.data[4] =3D num_resp;
c_pkt.len =3D 5;
=20
- print_data("hci_inquiry", (u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN + HCI_HDR=
_LEN);
+ PRINTPKT(__FUNCTION__, (u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN +=20
+ HCI_HDR_LEN);
=20
- tmp =3D send_inq_cmd_block((u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN + HCI_HD=
R_LEN);
+ // Send the command and wait for the Command Status event
+ if ((ret =3D send_cmd_block((u8*)&c_pkt, c_pkt.len + CMD_HDR_LEN +=20
+ HCI_HDR_LEN)) < 0)
+ goto exit;
=20
- if (tmp < 0) {
- kfree(inq_res);
- inq_res =3D NULL;
+#ifdef __KERNEL__
+ // Now, if we didn't time out or cancel, we'll wait for the Inquiry=20
+ // Complete event (or an inquiry result time out).
+ if (!hci_cmd_timeout && hci_inq_pending) {
+ add_wait_queue(&inq_wq, &wait);
+ current->state =3D TASK_INTERRUPTIBLE;=09=09
+ start_inq_timer();
+
+ while (hci_inq_pending)
+ schedule();=09=09
+
+ remove_wait_queue(&inq_wq, &wait);
+ } else {
+ ret =3D -EAGAIN;
}
+ pending_inq_res =3D NULL;
+ up(&hci_inq_semaphore);
+#endif
=20
- return inq_res;
+ exit:
+ return ret;
+}
+//------------------------------------------------------------------------=
-----
+// inquiry_complete_handler
+//=20=20=20=20=20=20=20=20=20
+// "The Inquiry Complete event indicates that the Inquiry is finis=
hed."
+// --Bluetooth Core Spec 1.0B
+//
+// We're done. Wake the process up.
+//
+// buf[0] =3D Status
+// buf[1] =3D Num_Responses
+//------------------------------------------------------------------------=
-----
+static void inquiry_complete_handler(u8 *buf, u32 len)
+{
+ D_CMD(__FUNCTION__":%s\n", get_err_msg(buf[0]));
+ release_inq_timer();
+ wake_up_interruptible(&inq_wq);
}
+//------------------------------------------------------------------------=
-----
+// inquiry_result_handler
+//
+// "The Inquiry Result event indicates that a Bluetooth device or
+// multiple Bluetooth devices have responded so far during the
+// current Inquiry process." --Bluetooth Core Spec 1.0B
+//
+// We'll add the information to our pending inquiry data structure.
+//
+// buf[0] =3D Num_Responses
+// buf[1-6] =3D BD_ADDR[0]
+// buf[7] =3D Page_Scan_Repitition_Mode[0]
+// buf[8] =3D Page_Scan_Period_Mode[0]
+// buf[9] =3D Page_Scan_Mode[0]
+// buf[10-12] =3D Class_Of_Device[0]
+// buf[13] =3D Clock_Offset[0]
+// buf[14] =3D BD_ADDR[1]
+// ... (etc for the remaining responses)
+//
+// REVISIT We're ignoring all the information except for the BD=20
+// address. Presumably apps will want the rest of the info,
+// to...
+//
+//------------------------------------------------------------------------=
-----
+static void inquiry_result_handler(u8 *buf, u32 len)
+{
+
+ s32 i, j;
+ u8 tmp_bd[6];
+=09
+ D_CMD(__FUNCTION__"\n");
+
+ // for each response address in the result...
+ for(i =3D 1; i < (buf[0] * 14) + 1; i +=3D 14) {
+=09=09=09
+ // reverse the address into a tmp buffer
+ for (j =3D 0; j < 6; j++) tmp_bd[5-j] =3D buf[i + j];
+
+ // check if we already have that address listed
+ for (j =3D 0; j < pending_inq_res->nbr_of_units; j++) {
+ if (!memcmp(pending_inq_res->bd_addr +=20
+ pending_inq_res->nbr_of_units * 6, tmp_bd,
+ 6)) {
+ j =3D pending_inq_res->nbr_of_units;
+ }
+ }
=20
+ // if not then add it to the back of the list
+ if (j >=3D pending_inq_res->nbr_of_units) {
+ memcpy(pending_inq_res->bd_addr +=20
+ pending_inq_res->nbr_of_units * 6, tmp_bd, 6);
+ pending_inq_res->nbr_of_units +=3D 1;
+ }
+ }
+}
+//------------------------------------------------------------------------=
-----
+// inquiry_status_handler
+//
+// The Host Controller has started the Inquiry or determined that =
it
+// can't due to some error. If there was an error then we need to
+// wake the inquiring process up.
+//
+//------------------------------------------------------------------------=
-----
+static void inquiry_status_handler(u8 *buf)
+{
+ if (buf[0]) {
+ D_ERR(__FUNCTION__ ":%s\n", get_err_msg(buf[0]));
+ hci_inq_pending =3D 0;
+ wake_up_interruptible(&inq_wq);
+ }
+}
+#else
+#define hci_inquiry_init()
+#define inquiry_complete_handler NULL
+#define inquiry_result_handler NULL
+#define inquiry_status_handler NULL
+#endif /* CONFIG_BLUETOOTH_INQUIRY **************************************=
***/
+
+
/* This function will cause the Link Manager to create a connection to the
Bluetooth device with the BD_ADDR specified by the function parameters.
This function causes the local Bluetooth device to begin the Page proce=
ss
@@ -1750,10 +1096,9 @@
=20
return send_cmd((u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN);=20=
=20
}
-
=20
-s32
-hci_add_sco_connection(u32 hci_hdl)
+#ifdef CONFIG_BLUETOOTH_SCO /* Add_SCO_Connection ************************=
***/
+int hci_add_sco_connection(u32 hci_hdl)
{
D_CMD(__FUNCTION__"\n");
c_pkt.type =3D CMD_PKT;
@@ -1767,6 +1112,7 @@
=20
return send_cmd_block((u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN=
);
}
+#endif /* Add_SCO_Connection *********************************************=
***/
=20
/* The Hci_Disconnect function is used to terminate an existing connection.
The Connection_Handle function parameter indicates which connection is =
to be
@@ -2539,7 +1885,6 @@
s32 tmp;
=20=09
D_CMD(__FUNCTION__", hci_hdl:0x%x, for %d packets\n", hci_hdl,nbr_of_pack=
ets);
-
c_pkt.type =3D CMD_PKT;
c_pkt.opcode =3D hci_put_opcode(HOST_NUMBER_OF_COMPLETED_PACKETS, HCI_HC)=
;
=20
@@ -2550,7 +1895,6 @@
c_pkt.data[4] =3D ((nbr_of_packets >> 8) & 0xff);
c_pkt.len =3D 5;
=20
-=09
/*FIXME Risk for race against sending acl packets ? */
//printk("Host pkt start\n");
tmp =3D bt_write_lower_driver((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI=
_HDR_LEN);
@@ -2624,7 +1968,6 @@
{
/* Consider changing bd to BD_ADDR */
s32 tmp;
-
D_CMD(__FUNCTION__"\n");
c_pkt.type =3D CMD_PKT;
c_pkt.opcode =3D hci_put_opcode(READ_BD_ADDR, HCI_IP) ;
@@ -2812,7 +2155,9 @@
=20
#ifdef __KERNEL__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+ printk(__FUNCTION__ ": queueing task...\n"); // gjm
queue_task(&send_data_task, &tq_scheduler);
+ printk(__FUNCTION__ ": ...done queueing task\n"); // gjm
#else
queue_task(&send_data_task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
@@ -3300,7 +2645,7 @@
queue_task(&send_cmd_task, &tq_immediate);
mark_bh(IMMEDIATE_BH);
#endif /* LINUX_VERSION_CODE */
-#else
+#else /* __KERNEL__ */
send_cmd_queue();
#ifdef HCI_EMULATION
hci_cmd_pending =3D 0;
@@ -3416,11 +2761,18 @@
start_cmd_timer(void)
{
#ifdef __KERNEL__
+ // NOTE The caller should have locked out interrupts.
+
D_CTRL(__FUNCTION__"\n");
init_timer(&hci_cmd_timer);
hci_cmd_timer.function =3D cmd_timeout;
hci_cmd_timer.data =3D 0;
hci_cmd_timer.expires =3D jiffies + 3*HZ;
+
+ if (cmd_timer_active)=20
+ D_ERR(__FUNCTION__":cmd_timer_active still set!\n");
+ cmd_timer_active =3D 1;
+
add_timer(&hci_cmd_timer);
#endif
}
@@ -3430,7 +2782,14 @@
release_cmd_timer(void)
{
#ifdef __KERNEL__
+ // NOTE The caller should have locked out interrupts.
+
D_CTRL(__FUNCTION__"\n");
+
+ if (!cmd_timer_active)=20
+ D_ERR(__FUNCTION__":cmd_timer_active not set!\n");
+ cmd_timer_active =3D 0;
+
del_timer(&hci_cmd_timer);
#endif
hci_cmd_pending =3D 0;
@@ -3446,56 +2805,24 @@
=20=09
printk(__FUNCTION__", Timeout when waiting for command response\n");
hci_cmd_pending =3D 0;
- wake_up_interruptible(&hci_wq);
-}
-#endif
=20
-#ifdef USE_INQTIMER
-static void
+ if (!cmd_timer_active)=20
+ D_ERR(__FUNCTION__":cmd_timer_active not set!\n");
+ cli();
+ cmd_timer_active =3D 0;
+ sti();
=20
-start_inq_timer(void)
-{
-#ifdef __KERNEL__
- D_CMD(__FUNCTION__"\n");
- init_timer(&hci_inq_timer);
- hci_inq_timer.function =3D inq_timeout;
- hci_inq_timer.data =3D 0;
- hci_inq_timer.expires =3D jiffies + 10*HZ;
- add_timer(&hci_inq_timer);
-#endif
+ hci_cmd_timeout =3D 1;
+ wake_up_interruptible(&hci_wq);
}
-
-static void
-release_inq_timer(void)
-{
-#ifdef __KERNEL__
- D_CMD(__FUNCTION__"\n");
- del_timer(&hci_inq_timer);
#endif
- hci_inq_pending =3D 0;
-}
=20
-#ifdef __KERNEL__
-static void
-inq_timeout(unsigned long ptr)
-{
- /* The command timed out, then we reset the command buffer counter to
- 1 again */
- /* FIX ME: What to do here !! */
-/* hci_ctrl.hc_buf.cmd_num =3D 1;*/
=20
- printk(__FUNCTION__", Timeout when waiting for inquiry response\n");
- hci_inq_pending =3D 0;
- wake_up_interruptible(&inq_wq);
-}
-#endif
-#endif /* USE_INQTIMER */
-
=20
s32=20
send_cmd_block(u8 *cmd, u8 len)
{
- u32 tmp;
+ s32 tmp;
=20
#ifdef __KERNEL__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
@@ -3508,12 +2835,15 @@
=20
add_wait_queue(&hci_wq, &wait);
current->state =3D TASK_INTERRUPTIBLE;
+ hci_cmd_timeout =3D 0;
=20
-#endif
+#endif /* __ KERNEL__ */
hci_cmd_pending =3D 1;
=20=20=20
- start_cmd_timer();
tmp =3D send_cmd(cmd, len);
+ cli();
+ start_cmd_timer();
+ sti();
=20=20=20
#ifdef __KERNEL__
while (hci_cmd_pending)
@@ -3529,38 +2859,6 @@
return tmp;
}
=20
-s32=20
-send_inq_cmd_block(u8 *cmd, u8 len)
-{
- u32 tmp;
-#ifdef __KERNEL__
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
- struct wait_queue wait =3D { current, NULL};
-#else
- DECLARE_WAITQUEUE(wait, current);
-#endif
-
- down(&hci_inq_semaphore);
-
- add_wait_queue(&inq_wq, &wait);
- current->state =3D TASK_INTERRUPTIBLE;
-
- hci_inq_pending =3D 1;
-#endif
-
- /*FIXME: currently we have no timer for inquiry */
- tmp =3D send_cmd(cmd, len);
-=20=20
-#ifdef __KERNEL__
- while (hci_inq_pending)
- schedule();
-
- remove_wait_queue(&inq_wq, &wait);
-
- up(&hci_inq_semaphore);
-#endif
- return tmp;
-}
=20
#if 0
/* Used for testing */
@@ -3581,5 +2879,960 @@
printk("------------------------------------------\n");
}
#endif
+
+//------------------------------------------------------------------------=
-----
+// Command Complete Parameter Handlers
+// process_return_param() calls these functions when we receive a
+// Command Complete Event. It first uses the OGF of the command op=
code
+// to index into the OGF handler table. Then each OGF handler uses=
the
+// OCF of the opcode to pick an OCF handler.
+//
+// In all cases the 'buf' argument to the param handlers is the st=
art
+// of the Return_Parameters section of the HCI packet.
+//
+// REVISIT Investigate consolidating all the OGF handlers into one routine.
+//------------------------------------------------------------------------=
-----
+
+typedef void (*param_handler_t)(u8 *buf);
+
+static void default_param_handler(u8 *buf)
+{
+ // buf[0] =3D Status
+
+ D_CMD(__FUNCTION__ ": %s\n", get_err_msg(buf[0]));=09
+ result_param =3D - buf[0];
+}
+
+static void null_param_handler(u8 *buf) {}
+
+
+//------------------------------------------------------------------------=
-----
+// Link Control Command Result Param handlers
+//------------------------------------------------------------------------=
-----
+#define inquiry_cancel_param_handler NULL // command never sent
+#define periodic_inquiry_mod_param_handler NULL // command never sent
+#define exit_periodic_inquiry_mod_param_handler NULL // command never sent
+#define create_connection_param_handler null_param_handler
+#define disconnect_param_handler null_param_handler
+#define add_sco_connection_param_handler null_param_handler
+#define accept_connection_request_param_handler null_param_handler
+#define reject_connection_request_param_handler null_param_handler
+#define link_key_request_reply_param_handler default_param_handler
+#define link_key_request_negative_reply_param_handler default_param_handler
+#define pin_code_request_reply_param_handler default_param_handler
+#define pin_code_request_negative_reply_param_handler default_param_handler
+#define change_connection_packet_type_param_handler null_param_handler
+#define authentication_requested_param_handler null_param_handler
+#define set_connection_encryption_param_handler null_param_handler
+#define change_connection_link_key_param_handler NULL // command never sent
+#define master_link_key_param_handler NULL // command never sent
+#define remote_name_request_param_handler null_param_handler
+#define read_remote_supported_features_param_handler NULL // co...
[truncated message content] |