|
From: Gordon M. <gm...@us...> - 2001-04-18 00:54:07
|
The following files were modified in linux/drivers/char/bluetooth:
Name Old version New version Comment
---- ----------- ----------- -------
bluetooth.c 1.166 1.167=20=20=20=20=20=20=20=20=20=20=20
hci.c 1.139 1.140=20=20=20=20=20=20=20=20=20=20=20
The accompanying log:
Fixed the hci_inquiry hang (hopefully).
The diff of the modified file(s):
--- bluetooth.c 2001/04/17 23:50:26 1.166
+++ bluetooth.c 2001/04/18 00:53:37 1.167
@@ -706,7 +706,7 @@
extern void test_process_cmd(unsigned char *cmd, s32 size);
u8 cmd[size];
copy_from_user(cmd, (s32*)arg, size);
- printk("TEST_COMMAND %d %d\n", cmd, size);
+ printk("TEST_COMMAND %d %d\n", (int)cmd, (int)size);
test_process_cmd(cmd, size);
}
=20
@@ -719,13 +719,31 @@
inquiry_results *inq_res;
s32 in_param[2];
u8 lap[3];
+ 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])))
- return -ENOMEM;
- copy_to_user((s32*)arg, inq_res, size + 6 * inq_res->nbr_of_units);
+
+ if ((inq_res =3D=20
+ (inquiry_results*) kmalloc(sizeof(inquiry_results)
+ + 6 * in_param[0],=20
+ GFP_ATOMIC)) < 0) {
+ ret =3D -ENOMEM;
+ goto hci_inq_exit0;
+ }
+
+ if ((ret =3D hci_inquiry(lap, in_param[1], in_param[0],
+ inq_res)) < 0)
+ goto hci_inq_exit1;
+
+ copy_to_user((s32*)arg, inq_res, size + 6 *=20
+ inq_res->nbr_of_units);
+=09=09
+ hci_inq_exit1:
+ kfree(inq_res);=09=09
+ hci_inq_exit0:
+ return ret;
break;
}
=20=09
--- hci.c 2001/04/17 12:04:00 1.139
+++ hci.c 2001/04/18 00:53:37 1.140
@@ -191,7 +191,7 @@
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);
+static s32 send_inq_cmd_block(u8 *cmd, u8 len, u8 inq_len);
#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
static u8* get_bd(u16 con_hdl);
#endif
@@ -229,8 +229,9 @@
static void release_ncp_timer(void);
#endif
=20
+#define USE_INQTIMER 1
#ifdef USE_INQTIMER
-static void start_inq_timer(void);
+static void start_inq_timer(u8 inq_len);
static void release_inq_timer(void);
#endif
=20
@@ -303,6 +304,7 @@
=20
static u32 hci_cmd_pending =3D 0;
static u32 hci_inq_pending =3D 0;
+static u8 hci_inq_aborted =3D 0;
=20
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
struct wait_queue *hci_wq =3D NULL;
@@ -640,6 +642,9 @@
case INQUIRY_COMPLETE:
D_CMD("INQUIRY_COMPLETE\n");
hci_inq_pending =3D 0;
+#if USE_INQTIMER
+ release_inq_timer();
+#endif
wake_up_interruptible(&inq_wq);
#ifndef __KERNEL__
for (i =3D 0; i < inq_res->nbr_of_units; i++) {
@@ -665,12 +670,15 @@
}
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)) {
+ if (!memcmp(inq_res->bd_addr +=20
+ 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);
+ memcpy(inq_res->bd_addr +=20
+ inq_res->nbr_of_units * 6, tmp_bd, 6);
inq_res->nbr_of_units +=3D 1;
}
}
@@ -843,6 +851,10 @@
=20=09=09
if (buf[0]) {
D_ERR(__FUNCTION__", COMMAND_STATUS: %s\n",get_err_msg(buf[0]));
+#ifdef USE_INQTIMER
+ if (hci_inq_pending)
+ release_inq_timer();
+#endif
}
=20=09=09
update_nhcp(buf[1]);
@@ -1750,27 +1762,23 @@
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.*/
=20
-inquiry_results*=20
-hci_inquiry(u8 *lap, u8 inq_len, u8 num_resp)
+int hci_inquiry(u8 *lap, u8 inq_len, u8 num_resp, inquiry_results *results)
{
s32 tmp;
=20
D_CMD(__FUNCTION__", Sending inquiry()\n");
=20
+ if (!results)
+ return -EINVAL;
+
+ inq_res =3D results;
+
/* FIXME: Check if lap is valid first */
/* Set default lap */
lap[0] =3D 0x33;
lap[1] =3D 0x8b;
lap[2] =3D 0x9e;
=20
- /* Free any previous response */
- kfree(inq_res);
-=09
- inq_res =3D (inquiry_results*) kmalloc(sizeof(inquiry_results)
- + 6 * num_resp, GFP_ATOMIC);
- if (!inq_res)
- return NULL;
-
inq_res->nbr_of_units =3D 0;
=20
c_pkt.type =3D CMD_PKT;
@@ -1785,14 +1793,10 @@
c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN);
=20
tmp =3D send_inq_cmd_block((u8*) &c_pkt,=20
- c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN);
-
- if (tmp < 0) {
- kfree(inq_res);
- inq_res =3D NULL;
- }
+ c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN,
+ inq_len);
=20
- return inq_res;
+ return tmp;
}
=20
/* This function will cause the Link Manager to create a connection to the
@@ -3556,14 +3560,15 @@
#ifdef USE_INQTIMER
static void
=20
-start_inq_timer(void)
+start_inq_timer(u8 inq_len)
{
#ifdef __KERNEL__
+#define INQ_FUDGE_FACTOR (2 * HZ)
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;
+ hci_inq_timer.expires =3D jiffies + inq_len * INQ_FUDGE_FACTOR;
add_timer(&hci_inq_timer);
#endif
}
@@ -3590,6 +3595,7 @@
=20
printk(__FUNCTION__", Timeout when waiting for inquiry response\n");
hci_inq_pending =3D 0;
+ hci_inq_aborted =3D 1;
wake_up_interruptible(&inq_wq);
}
#endif
@@ -3633,9 +3639,10 @@
}
=20
s32=20
-send_inq_cmd_block(u8 *cmd, u8 len)
+send_inq_cmd_block(u8 *cmd, u8 len, u8 inq_len)
{
u32 tmp;
+
#ifdef __KERNEL__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
struct wait_queue wait =3D { current, NULL};
@@ -3644,24 +3651,35 @@
#endif
=20
down(&hci_inq_semaphore);
-
add_wait_queue(&inq_wq, &wait);
current->state =3D TASK_INTERRUPTIBLE;
-
hci_inq_pending =3D 1;
-#endif
=20
- /*FIXME: currently we have no timer for inquiry */
- tmp =3D send_cmd(cmd, len);
+ if ((tmp =3D send_cmd(cmd, len)) < 0)
+ goto inq_done;
=20=20=20
-#ifdef __KERNEL__
+#ifdef USE_INQTIMER
+ hci_inq_aborted =3D 0;
+ start_inq_timer(inq_len);
+#endif
while (hci_inq_pending)
schedule();
=20
- remove_wait_queue(&inq_wq, &wait);
+#ifdef USE_INQTIMER
+ if (hci_inq_aborted)
+ tmp =3D -ETIME;
+#endif
=20
+ inq_done:
+ remove_wait_queue(&inq_wq, &wait);
up(&hci_inq_semaphore);
-#endif
+
+#else /* __KERNEL__ */
+
+ tmp =3D send_cmd(cmd, len);
+
+#endif /* __KERNEL__ */
+
return tmp;
}
=20
|