|
From: Mattias A. <mat...@us...> - 2001-03-30 11:30:46
|
The following file was modified in linux/drivers/char/bluetooth:
Name Old version New version Comment
---- ----------- ----------- -------
hci.c 1.134 1.135=20=20=20=20=20=20=20=20=20=20=20
The accompanying log:
* added functionality to handle master slave switch
* moved ACL link code into section only for ACL data (SCO links
were handled in an erronoeous way)
* removed role_discovery call in lp_connect_cfm, role is shown when=20
an m/s switch is performed anyway
* added hci_force_msswitch which forces m/s switch as server
* lots of minor changes
The diff of the modified file(s):
--- hci.c 2001/03/26 14:58:26 1.134
+++ hci.c 2001/03/30 11:30:44 1.135
@@ -53,11 +53,14 @@
#include <linux/bluetooth/btdebug.h>
#include <linux/bluetooth/bluetooth.h>
#include <linux/bluetooth/l2cap.h>
+#include <linux/bluetooth/l2cap_con.h>
#include <linux/bluetooth/tcs.h>
#include <linux/bluetooth/btmem.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/bluetooth/sec_client.h>
+#include <asm/io.h>
+
#else /* user mode */
#include <stdlib.h>
#include <string.h>
@@ -67,6 +70,7 @@
#include "include/hci_internal.h"
#include "include/btdebug.h"
#include "include/l2cap.h"
+#include "include/l2cap_con.h"
#include "include/btmem.h"
#include "include/tcs.h"
#include "include/sec_client.h"
@@ -121,7 +125,6 @@
=20
#define HCI_SYNC_FIX
=20
-
#ifdef HCI_EMULATION
#define ACL_NUM 10
#define ACL_LEN 800=20
@@ -214,7 +217,6 @@
=20
/* Informational Parameters (HCI_IP) */
=20
-
/* Other functions */
static s32 hci_read_buffer_size(s32 block);=20
static void set_hci_con(u8 *bd, s32 con_hdl);
@@ -252,7 +254,6 @@
#endif
=20
static void send_acl_data_task(void);
-
/****************** LOCAL VARIABLE DECLARATION SECTION *******************=
***/
=20
/* Struct used for sending command packets */
@@ -269,7 +270,9 @@
#ifdef USE_NCPTIMER
static struct timer_list hci_ncp_timer;
#endif
+
static struct timer_list hci_cmd_timer;
+
#ifdef USE_INQTIMER
static struct timer_list hci_inq_timer;
#endif
@@ -322,6 +325,10 @@
=20
static s32 test_hci_hdl;
=20
+/* temp solution to handle m/s switch */
+static s32 force_msswitch;
+static s32 i_am_initiator =3D 0;
+
/****************** FUNCTION DEFINITION SECTION **************************=
***/
=20
/*
@@ -460,11 +467,8 @@
}
}
=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 */
@@ -572,6 +576,7 @@
/* We've just been notified that the hardware has free buffers.
If we have any outstanding packets, send_acl_data_task will try
to send as many packets as possible. */
+
#ifdef __KERNEL__
if (buf_count()) {=09=20=20=20=20=20
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
@@ -660,24 +665,32 @@
=20
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);
- }
=20
#ifndef HCI_EMULATION
if (buf[0]) {
/* remove hci handle if connection failed */
- DSYS(__FUNCTION__", CONNECTION_COMPLETE %s\n", get_err_msg(buf[0]));
+ DSYS(__FUNCTION__", CONNECTION_COMPLETE %s\n",=20
+ 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);
+ change_connection_packet_type(hci_hdl,=20
+ DM1|DH1|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);
+
+ /* enable m/s switch */=20
+ write_link_policy_settings(hci_hdl, 0x01);
+
+ /* we demand role switch as server */
+ if (force_msswitch && !i_am_initiator) {
+ /* FIXME -- check return code */
+ hci_switch_role(buf + 3, 0);
+ }
+ /* reset variable again */
+ i_am_initiator =3D 0;
+=09=09=09=09=09=09
}
#endif /* HCI_EMULATION */
=20
@@ -685,6 +698,9 @@
test_wq_active =3D 0;
wake_up_interruptible(&test_wq);
}
+ } else {
+ tcs_add_sco_link(buf[0], hci_hdl);
+ }
=20=09=09
break;
}
@@ -701,7 +717,6 @@
=20
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
@@ -817,15 +832,17 @@
break;
=20
case ROLE_CHANGED:
- D_CMD(__FUNCTION__", ROLE_CHANGED\n");
+ DSYS(__FUNCTION__", ROLE_CHANGED\n");
=20
if (buf[0]) {=20
- D_ERR(__FUNCTION__", Role changed faild due to %s\n",
+ D_ERR(__FUNCTION__", Role changed failed 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]));
+ DSYS(__FUNCTION__", Current master is 0x%04x%08x\n",=20
+ CHAR2INT16(buf[6], buf[5]),=20
+ 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]));
+ DSYS(__FUNCTION__", Our role is master for BD Address 0x%04x%08x\n", CH=
AR2INT16(buf[6], buf[5]), CHAR2INT32(buf[4], buf[3], buf[2], buf[1]));
}
break;
=20
@@ -1027,8 +1044,9 @@
break;
=20=20=20=20=20=20=20=20=20=20=20
case HCI_HC: /* Host Controller commands */
+=09=09
release_cmd_timer();
-/* FIX ME : The correct timer should be released */
+ /* FIXME -- correct timer should be released */
=20=20=20=20=20=20=20=20=20=20=20
switch (ocf) {
=20=09=09=09
@@ -1045,7 +1063,7 @@
=20=09=09=09
=20=09=09=09
case READ_STORED_LINK_KEY:
- D_CMD(__FUNCTION__", READ_STORED_LINK_KEY\n");
+ DSYS(__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];
@@ -1054,9 +1072,9 @@
result_param =3D CHAR2INT32(r_val[4], r_val[3],
r_val[2], r_val[=
1]);
}
- D_CMD(__FUNCTION__", Max number of Linkkeys: %d\n",
+ DSYS(__FUNCTION__", Max number of Linkkeys: %d\n",
CHAR2INT16(r_val[2], r_val[1]));
- D_CMD(__FUNCTION__", Number of Linkkeys read: %d\n",
+ DSYS(__FUNCTION__", Number of Linkkeys read: %d\n",
CHAR2INT16(r_val[4], r_val[3]));
break;
=20
@@ -1267,6 +1285,26 @@
release_cmd_timer();
=20
switch (ocf) {
+
+ case READ_LOCAL_VERSION_INFORMATION:
+ D_CMD(__FUNCTION__", READ_LOCAL_VERSION_INFORMATION\n");
+ if (r_val[0]) {
+ D_ERR(__FUNCTION__", READ_LOCAL_VERSION_INFORMATION: %s\n",
+ get_err_msg(r_val[0]));
+ break;
+ }
+=09=09=09
+ 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);
+
+ break;
+
case READ_BUFFER_SIZE:
D_CMD(__FUNCTION__", READ_BUFFER_SIZE\n");
if (r_val[0]) {
@@ -1313,15 +1351,15 @@
=20
switch (ocf) {=20=20
case READ_LOOPBACK_MODE:
- D_CMD(__FUNCTION__", READ_LOOPBACK_MODE -- not impl\n");
+ D_ERR(__FUNCTION__", READ_LOOPBACK_MODE -- not impl\n");
break;
=20=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");
+ D_ERR(__FUNCTION__", WRITE_LOOPBACK_MODE -- not impl\n");
break;
=20=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");
+ DSYS(__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]));
@@ -1331,7 +1369,7 @@
break;
=20=20=20=20=20=20=20=20=20=20=20=20=20
default:
- D_CMD(__FUNCTION__", HCI_TC, ocf %d not recognised!\n", ocf);
+ D_ERR(__FUNCTION__", HCI_TC, ocf %d not recognised!\n", ocf);
break;
}
wake_up_interruptible(&hci_wq);
@@ -1633,28 +1671,32 @@
send_data_task.data =3D NULL;
#endif
=20
+ /* Disable parity bit and set to H4 IF + flow ctrl */
+ /* Not activated until after reset !!!! */
+
/* always... */
DSYS(__FUNCTION__", Reading buffer sizes in the module...\n");
hci_read_buffer_size(HCI_BLOCK);
=20
hci_read_firmware_rev_info();
=20
-// hci_read_stored_link_key(NULL,1);
-
- //hci_write_authentication_enable(1);
#ifdef HOST_FLOW_CTRL
DSYS(__FUNCTION__", Host flow control enabled\n");
+ hci_set_host_controller_flow_control(TRUE);
#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);
=20
#ifdef USE_NCPTIMER
start_ncp_timer();=09
#endif
+
+#ifdef CONFIG_BLUETOOTH_FORCE_MSSWITCH
+ hci_force_msswitch(1);
+#else
+ hci_force_msswitch(0);
+#endif=20=20=20=20=20=20=20
}
=20
void=20
@@ -1712,9 +1754,11 @@
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);
+ print_data("hci_inquiry", (u8*) &c_pkt ,
+ c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN);
=20
- tmp =3D send_inq_cmd_block((u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN + HCI_HD=
R_LEN);
+ tmp =3D send_inq_cmd_block((u8*) &c_pkt,=20
+ c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN);
=20
if (tmp < 0) {
kfree(inq_res);
@@ -2048,6 +2092,9 @@
return send_cmd_block((u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN=
);
}
=20
+
+/* fixme -- fix return code so we know whether role change was succesful=
=20
+ or not */
s32
hci_switch_role(u8 *bd, u8 role)
{
@@ -2552,10 +2599,8 @@
c_pkt.len =3D 5;
=20
=20=09
- /*FIXME Risk for race against sending acl packets ? */
- //printk("Host pkt start\n");
+ /*FIXME -- Risk for race against sending acl packets ? */
tmp =3D bt_write_lower_driver((u8*) &c_pkt, c_pkt.len + CMD_HDR_LEN + HCI=
_HDR_LEN);
- //printk("Host pkt stop\n");
return tmp;
#else
return 0;
@@ -2615,6 +2660,24 @@
return send_cmd((u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN);
}
=20
+#if 0
+s32
+hci_read_local_version_info(s32 block)
+{
+ D_CMD(__FUNCTION__"\n");
+=09
+ c_pkt.type =3D CMD_PKT;
+ c_pkt.ocf =3D READ_LOCAL_VERSION_INFORMATION;
+ c_pkt.ogf =3D HCI_IP;
+ c_pkt.len =3D 0;
+
+ if (block)
+ return send_cmd_block((u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN + HCI_HDR_LE=
N);
+ else
+ return send_cmd((u8*) &c_pkt ,c_pkt.len + CMD_HDR_LEN + HCI_HDR_LEN);
+}
+#endif
+
/*
* This command will read the value for the BD_ADDR parameter of the local
* unit, returns bd in little endian
@@ -2734,7 +2797,7 @@
}
=20
=20
-/* This function is used to send custom commands over the HCI interface. */
+/* This function is used to send custom commands/data over the HCI interfa=
ce. */
=20
s32
hci_send_raw_data(u8 *data, u8 len)
@@ -2744,20 +2807,31 @@
return bt_write_lower_driver(data ,len);
}
=20
-
s32
hci_test_connect_req(u8 *bd)
{
/* Must add a l2cap con to store bd address in !!! */
=20
+#ifdef CONFIG_BLUETOOTH_ENABLE_MSSWITCH
if (create_connection(bd, 0xcc18, 0x00, 0x00, 0x00, DONT_ALLOW_ROLE_SWITC=
H)) {
D_ERR("hci_test_connect_req, error sending command\n");
}
+#else
+ if (create_connection(bd, 0xcc18, 0x00, 0x00, 0x00, ALLOW_ROLE_SWITCH)) {
+ D_ERR("hci_test_connect_req, error sending command\n");
+ }
+#endif
test_wq_active =3D 1;
interruptible_sleep_on(&test_wq);
return test_hci_hdl;
}
=20
+void
+hci_force_msswitch(u8 enable)
+{
+ printk("Setting force_msswitch to %d\n", enable);
+ force_msswitch =3D enable;=20
+}
=20
/* Sends a connect request to the BT unit with the address bd_addr */
s32=20
@@ -2766,11 +2840,18 @@
PRINTPKT(__FUNCTION__", bd address is: ", bd_addr, 6);
/* FIXME, store the inparameters in the ctrl-block instead */
=20
-// if (!get_con(bd_addr, ANY_STATE))
-// l2cap_create_con(bd_addr);
+ if (!get_con(bd_addr, ANY_STATE))
+ l2cap_create_con(bd_addr);
=20=20=20
-// return create_connection(bd_addr, 0xcc18, 0x00, 0x00, 0x00, ALLOW_ROLE_=
SWITCH);
- return create_connection(bd_addr, 0xcc18, 0x00, 0x00, 0x00, DONT_ALLOW_RO=
LE_SWITCH);
+ i_am_initiator =3D 1;
+
+#ifdef CONFIG_BLUETOOTH_ENABLE_MSSWITCH
+ return create_connection(bd_addr, 0xcc18, 0x00, 0x00,=20
+ 0x00, ALLOW_ROLE_SWITCH);
+#else
+ return create_connection(bd_addr, 0xcc18, 0x00, 0x00,=20
+ 0x00, DONT_ALLOW_ROLE_SWITCH);
+#endif
}
=20
/* A response from L2CAP to a previous lp_connect_ind */
@@ -2779,7 +2860,6 @@
{=20
D_CMD(__FUNCTION__"Status:%d\n", cfm);
if (cfm) {
-// return accept_connection_request(bd_addr, MS_SWITCH_BECOME_MASTER);
return accept_connection_request(bd_addr, MS_SWITCH_REMAIN_SLAVE);
} else {
return reject_connection_request(bd_addr, 0x0d);
@@ -2793,8 +2873,7 @@
s32=20
lp_disconnect(u32 hci_hdl)
{
- return disconnect(hci_hdl, 0x14);
- /* FIXME: 0x14 =3D Low Resources store this somewhere else */
+ return disconnect(hci_hdl, DISCMSG_USER_ENDED_CONNECTION);
}
=20
=20
@@ -2810,7 +2889,6 @@
sends the data. */
tx_buf->pb_flag =3D L2CAP_FRAME_START;
=20=09=09
-
#ifdef __KERNEL__
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
queue_task(&send_data_task, &tq_scheduler);
@@ -2838,6 +2916,7 @@
tx_buf =3D get_bt_buf();
if (tx_buf) {
bytes2send =3D tx_buf->cur_len;
+ D_SND(__FUNCTION__", %d bytes \n", tx_buf->cur_len);
}
=20=09
D_SND(__FUNCTION__", %d bytes \n", bytes2send);
@@ -2851,7 +2930,6 @@
=20=09
cli();
while ((hci_ctrl.hc_buf.acl_num > 0) && bytes2send) {
-
hci_ctrl.hc_buf.acl_num--;
sti();
=20=09=09
@@ -2860,7 +2938,6 @@
D_QUEUE("<--%d (%d)\n", buf_byte_count(),=20
hci_ctrl.hc_buf.acl_num);
=20
-
if (bytes2send =3D=3D 0) {
/* The current frame has now been sent, check if more
data is waiting to be sent from the driver. */
@@ -2869,14 +2946,12 @@
if (tx_buf) {
bytes2send =3D tx_buf->cur_len;
}
-=09=09=09=09
}
cli();
}
sti();
}
=20
-
u32
send_acl_packet(bt_tx_buf *tx_buf)
{
@@ -2919,7 +2994,7 @@
/* bt_write_lower_driver checks in serial driver if there are room=20
in serial tx buffer, if 0 is returned there was insufficient=20
room */
- //printk("ACL start\n");
+
if (!bt_write_lower_driver(cur_data,=20
c + ACL_HDR_LEN + HCI_HDR_LEN)) {
=20=09=09
@@ -2930,7 +3005,6 @@
D_SND(__FUNCTION__", cannot send now, leave in buffers\n");
return 0;
}
- //printk("ACL stop\n");
#endif
/* We always set the next part to be a continous part of the packet */
tx_buf->pb_flag =3D L2CAP_FRAME_CONT;
@@ -3009,7 +3083,6 @@
case 0x22: return "LMP Response Timeout";
case 0x23: return "LMP Error Transaction Collision";
case 0x24: return "LMP PDU Not Allowed";
-
case 0x25: return "Encryption Mode Not Acceptable";
case 0x26: return "Unit Key Used";
case 0x27: return "QOS is Not Supported";
@@ -3208,6 +3281,7 @@
=20=20=20
while ((tmp =3D get_next_cmd()) !=3D NULL) {
kfree(tmp->data);
+ tmp->data =3D NULL;
}
=20=20=20
cmd_buf.first_free =3D 0;
@@ -3354,8 +3428,9 @@
#else
bt_write_lower_driver(tmp->data, tmp->len);
#endif
- D_QUEUE(__FUNCTION__", sent data..., freeing memory\n");
kfree(tmp->data);
+ tmp->data =3D NULL;
+
cli();
hci_ctrl.hc_buf.cmd_num -=3D 1;
}
@@ -3402,8 +3477,6 @@
=20
if (!hw.acl_num_count && /* no new buffers since last timeout */=20
hci_ctrl.hc_buf.acl_num !=3D hw.max_acl_num) {
-// printk("bt_feedstack from ncp_timeout [acl:%d]\n",=20
-// hci_ctrl.hc_buf.acl_num);
bt_feedstack();
}
=20
@@ -3411,6 +3484,7 @@
start_ncp_timer();
}
#endif
+
#endif /* USE_NCPTIMER */
=20
void
@@ -3426,13 +3500,12 @@
#endif
}
=20
-
void
release_cmd_timer(void)
{
#ifdef __KERNEL__
- D_CTRL(__FUNCTION__"\n");
del_timer(&hci_cmd_timer);
+ D_CMD(__FUNCTION__"\n");
#endif
hci_cmd_pending =3D 0;
}
@@ -3441,8 +3514,8 @@
static void
cmd_timeout(unsigned long ptr)
{
- /* The command timed out, then we reset the command buffer counter to
- 1 again */
+ /* The command timed out, then we reset the command buffer=20
+ counter to 1 again */
hci_ctrl.hc_buf.cmd_num =3D 1;
=20=09
printk(__FUNCTION__", Timeout when waiting for command response\n");
@@ -3480,9 +3553,10 @@
static void
inq_timeout(unsigned long ptr)
{
- /* The command timed out, then we reset the command buffer counter to
- 1 again */
+ /* The command timed out, then we reset the command buffer=20
+ 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");
@@ -3490,8 +3564,7 @@
wake_up_interruptible(&inq_wq);
}
#endif
-#endif /* USE_INQTIMER */
-
+#endif
=20
s32=20
send_cmd_block(u8 *cmd, u8 len)
|