|
From: Mattias A. <mat...@us...> - 2001-03-30 11:59:23
|
The following file was modified in linux/drivers/char/bluetooth:
Name Old version New version Comment
---- ----------- ----------- -------
l2cap.c 1.94 1.95=20=20=20=20=20=20=20=20=20=20=20=20
The accompanying log:
* added usage of l2ca_wait / l2ca_wakeup which blocks on a=20
connection until a response is received or the connection times out.
* removed do_cmd_backup, use blocking calls in calling function instead
* fixed l2cap_config_rsp with options / pending response /=20
not accepted config options
* fixed bug when sending back responses and con->hci_hdl not yet set
* added flags in l2cap_con struct to handle blocking calls and signalling/
result codes to upper layers.=20
* now handles conf resp flag (fragmented options)
* fixed RTX/ERTX timer handling
* removed l2cap_disconnect_wq
* added l2ca_timeoutind
* lots of minor changes and cleanup
The diff of the modified file(s):
--- l2cap.c 2001/03/27 19:32:28 1.94
+++ l2cap.c 2001/03/30 11:59:20 1.95
@@ -57,6 +57,7 @@
#include <linux/bluetooth/l2cap_internal.h>
#include <linux/bluetooth/l2cap_con.h>
#include <linux/bluetooth/l2cap_sec.h>
+#include <linux/bluetooth/bt_errno.h>
#else /* user mode */
#include <stdlib.h>
#include <string.h>
@@ -72,6 +73,7 @@
#include "include/test.h"
#include "include/btmem.h"
#include "include/local.h"
+#include "include/bt_errno.h"
#endif
=20
/****************** DEBUG CONSTANT AND MACRO SECTION *********************=
***/
@@ -208,28 +210,21 @@
=20
static s32 parse_options(l2cap_con* con, u8 *data, u32 len);
static void print_flow(flow *f);
-static s32 l2cap_echo_rsp(s32 hci_hdl, s32 id, u8 *opt_data, s32 opt_len);
static s32 l2cap_cmdrej(s32 hci_hdl, u8 reason, u8 *opt_data, s32 opt_len);
=20
void insert_upper(protocol_layer *upper_layer);
protocol_layer* get_upper(u32 psm);
void remove_all_upper(void);
=20
-#ifdef __KERNEL__
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
-static struct wait_queue *l2cap_disconnect_wq =3D NULL;
-#else
-static wait_queue_head_t l2cap_disconnect_wq;
-#endif /* LINUX_VERSION_CODE */
-#endif /* __KERNEL__ */
-
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
-#define MAX_NO_RTX 0
-#define RTX_TIMEOUT 5 /* sec */
+
+/* fixme -- calculate this using flush timeout */
+#define MAX_NO_RTX 3
+#define RTX_TIMEOUT 2 /* sec */
#define ERTX_TIMEOUT 60 /* sec */
=20
#ifdef __KERNEL__
-void start_rtx(l2cap_con *con, unsigned short timeout);
+void start_rtx(l2cap_con *con, unsigned short timeout, unsigned short acti=
on);
void disable_rtx(l2cap_con *con);
void start_ertx(l2cap_con *con, unsigned short timeout);
void disable_ertx(l2cap_con *con);
@@ -240,15 +235,11 @@
=20
l2cap_con *timeout_con =3D NULL;
s32 timer_cancelled =3D 0;
-void start_rtx(l2cap_con *con, s32 timeout);
+void start_rtx(l2cap_con *con, s32 timeout, u16 action);
void disable_rtx(l2cap_con *con);
void l2cap_rtx_timeout(void);
#endif
=20
-/* used to resend lost l2cap commands */
-void do_cmd_backup(l2cap_con *con, u8 type, u16 in_mtu,=20
- flow *outflow, u16 flush_timeout, u16 link_to,
- u16 info_type);
#endif
=20
/****************** GLOBAL VARIABLE DECLARATION SECTION ******************=
***/
@@ -308,13 +299,6 @@
DSYS("Local bd [%s]\n", bd_name);
}
=20
- /* Initialize the l2cap_disconnect_wq */
-#ifdef __KERNEL__
-#if LINUX_VERSION_CODE >=3D KERNEL_VERSION(2,4,0)
- init_waitqueue_head(&l2cap_disconnect_wq);
-#endif /* LINUX_VERSION_CODE */
-#endif /* __KERNEL__ */
-
#ifdef CONFIG_BLUETOOTH_USE_SECURITY_MANAGER
/* Initialize security */
l2cap_sec_man_init();
@@ -358,15 +342,23 @@
s32=20
l2cap_shutdown(void)
{
+ //l2cap_con *con =3D get_first_con();
+=20=20
DSYS("Shutting down L2CAP\n");
if (!l2cap->initiated)
{
D_ERR("L2CAP not initiated\n");
return -1;
}
-=09
- /* FIXME - Disconnect all open connections */
=20
+#if 0
+ /* Notify upper users, don't have time for real disconnect... */
+ while (con!=3D NULL) {
+ l2ca_disconnect_ind(con);
+ con =3D get_next_con(con);
+ }
+#endif
+ /* necessary ? */
free_list();
remove_all_upper();
=20
@@ -474,6 +466,7 @@
tmp_layer =3D l2cap->upper_layers;
l2cap->upper_layers =3D tmp_layer->next_layer;
kfree(tmp_layer);
+ tmp_layer =3D NULL;
}
}
=20
@@ -655,7 +648,6 @@
if (pos < len){
cmd =3D (struct sig_cmd *)(data + pos);
cmd->len =3D le16_to_cpu(cmd->len);
- printk("pos %d, len %d\n", pos, len);
DSYS("another command in same packet...(%d bytes)\n",
cmd->len);
}
@@ -767,13 +759,17 @@
req->len-4);
}
=20
+ /* Are we expecting more config requests ? */
+ con->remote_flags =3D confreq->flags;
+
if (result !=3D CONF_SUCCESS) {
/* we didn't like the options... */
DSYS("parse_options failed, send neg rsp\n");
=20
/* send back negative response */
- if (l2ca_config_rsp(con, result, STAT_NOINFO, 0) < 0) {
- D_ERR("Couldnt send conf rsp\n");
+ if (l2ca_config_rsp(con, result, STAT_NOINFO,=20
+ CONF_FAILURE) < 0) {
+ D_ERR("Couldn't send conf rsp\n");
}
return;
}
@@ -805,12 +801,17 @@
return;
}
=20=09=09=09
+ /* Are we expecting more config requests ? */
+ con->remote_flags =3D confreq->flags;
+
if (result !=3D RES_SUCCESS) {
=20=09=09=09=09
/* we didn't like the options... */
=20=09=09=09=09
/* send back negative response */
- if (l2ca_config_rsp(con, result, STAT_NOINFO, 0) < 0) {
+ if (l2ca_config_rsp(con, result,=20
+ STAT_NOINFO,=20
+ CONF_FAILURE) < 0) {
D_ERR("Couldnt send conf rsp\n");
}
return;
@@ -869,7 +870,7 @@
=20=20=20=20=20=20=20=20
case SIG_ECHOREQ: {
sig_echo_pkt* echo;
- D_STATE(FNC"echo request\n");
+ D_STATE(FNC"Echo request\n");
=20=09=09
echo =3D (sig_echo_pkt *)(req->data);=09=09
=20
@@ -881,7 +882,7 @@
case SIG_INFOREQ: {
/* Implementation specific */
sig_info_req *info;
- D_STATE(FNC"info request\n");
+ D_STATE(FNC"Info request\n");
=20=09=09
info =3D (sig_info_req*)(req->data);
info->type =3D le16_to_cpu(info->type);
@@ -896,7 +897,7 @@
=20
default:
D_ERR("Unknown info request : type 0x%x\n", info->type);
- l2cap_cmdrej(con->hci_hdl, CMDREJ_NOTUNDERSTOOD,
+ l2cap_cmdrej(hci_handle, CMDREJ_NOTUNDERSTOOD,
NULL, 0);
break;=09=09
}
@@ -910,7 +911,7 @@
default:
/* Not a valid command */
DSYS(FNC"Invalid command (code 0x%x)s\n", req->code);
- l2cap_cmdrej(con->hci_hdl, CMDREJ_NOTUNDERSTOOD, NULL, 0);
+ l2cap_cmdrej(hci_handle, CMDREJ_NOTUNDERSTOOD, NULL, 0);
break;
}
#undef FNC
@@ -939,7 +940,7 @@
switch (rsp->code) {
case SIG_CMDREJECT:
D_STATE(FNC"Command reject - \n");
-=20=20=20=20=20=20=20=20=20
+ DSYS("Got command reject\n");
cmdreject =3D (sig_cmdreject*)rsp->data;
cmdreject->reason =3D le16_to_cpu(cmdreject->reason);
opt_len =3D rsp->len - sizeof(sig_cmdreject);
@@ -964,6 +965,15 @@
if (opt_len > 0)
print_data(FNC"optional data : ",=20
cmdreject->data, rsp->len-2);
+
+ /* fixme -- set 'real' reason code */
+ con->c_status =3D CSTATUS_CMDREJECT;
+=09=09
+ l2ca_wakeup("l2cap cmd reject", con);
+
+#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS=09=09
+ disable_rtx(con);
+#endif
break;
=20=20=20=20=20=20=20=20
case SIG_CONRSP:
@@ -989,41 +999,40 @@
return;
}
=20=20=20=20=20=20=20=20=20=20
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
- disable_rtx(con);
-#endif
+ con->c_status =3D conrsp->result;=09=09
=20
switch (conrsp->result) {
case RES_SUCCESS:
+ l2ca_wakeup("l2cap_connect_rsp", con);
ENTERSTATE(con, CONFIG);
PRINTSTATE(con);
l2ca_connect_cfm(con, conrsp->result);
break;
=20=20=20=20=20=20=20=20=20=20=20=20
case RES_PENDING:
+
+ /* wake up when real con resp comes */
l2ca_connect_pnd(con, conrsp->status);
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
/* Disable RTX timer and start ERTX */
- //start_ertx();
+ disable_rtx(con);
+ start_ertx(con, ERTX_TIMEOUT);
#endif
- D_STATE(FNC"connection pending (fixme)\n");
+ D_STATE(FNC"connection pending\n");
break;
=20
case RES_PSMNEG:
- /* FIXME */
DSYS(FNC"connection refused, psm 0x%x not supp\n",=20
con->psm);
failure =3D 1;
break;
=20
case RES_SECNEG:
- /* FIXME */
DSYS(FNC"connection refused, security block\n");
failure =3D 1;
break;
=20=20=20=20=20=20=20=20=20=20=20=20
case RES_NOSRC:
- /* FIXME */
DSYS(FNC"connection refused, no resources\n");
failure =3D 1;
break;
@@ -1034,18 +1043,16 @@
}
=20=20=20=20=20=20=20=20=20=20
if (failure) {
- /* Connection refused=20
- FIXME -
- Disable RTX/ERTX timers
- (New state : CLOSED)
- */
+
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
disable_rtx(con);
- //disable_ertx(con);
+ disable_ertx(con);
#endif
=20
l2ca_connect_cfm(con, MSGCODE(MSG_LAYER_L2CAP, conrsp->result));
=20=09=09=09
+ l2ca_wakeup("Got connect rsp neg", con);
+=09=09=09
ENTERSTATE(con, CLOSED);
delete_con(con);
}
@@ -1079,19 +1086,15 @@
=20
switch (confrsp->result) {
case CONF_SUCCESS:
+
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
disable_rtx(con);
#endif
-
- /* FIXME - should check that we have received=20
- l2cap_config_req & replied pos. If we are server=20
- we can now proceed to OPEN (will do for now) */
-=20=20=20=20=20=20=20=20=20=20=20
con->conf_req_ready =3D TRUE;
=20
if (!con->conf_rsp_ready) {
/* Upper layers still haven't replied pos */
- DSYS("Still haven't replied pos on other sides conf req\n");
+ D_STATE("Still haven't replied pos on other sides conf req\n");
return ;
} else {=09=09=09=09
ENTERSTATE(con, OPEN);
@@ -1103,19 +1106,25 @@
/* notify upper layers that we successfully
opened a connection ! */
l2ca_config_cfm(con, confrsp->result);
- }
- return;
+ } return;
=20=09=09=09
case CONF_FAILURE:
+
+ /* store remote side configuration */
+ parse_options(con, confrsp->options, opt_len);
+
D_STATE(FNC"config failure, unacceptable params\n");
+ l2ca_config_cfm(con, confrsp->result);
break;
=20=20=20=20=20=20=20=20=20=20=20=20
case CONF_REJ:
D_STATE(FNC"connection refused, no reason\n");
+ l2ca_config_cfm(con, confrsp->result);
break;
=20=20=20=20=20=20=20=20=20=20=20=20
case CONF_UNKNOWN:
D_STATE(FNC"connection refused, unknown options\n");
+ l2ca_config_cfm(con, confrsp->result);
break;
=20=20=20=20=20=20=20=20=20=20=20=20=20
default:
@@ -1133,17 +1142,11 @@
D_ERR(FNC"SIG_CONFRSP invalid state\n");
PRINTSTATE(con);
=20
- /* FIXME - should stay in CONFIG state and renegotiate=20
- according to spec */
- printk("FIXME -- CONFIG failed, remain in CONFIG and renegotiate\n");
/* print failed options */
if (opt_len > 0)
print_data("Options not accepted\n", confrsp->options,=20
rsp->len - sizeof(sig_confrsp));
=20
- /* For now we simply disconnect if params failed */
- l2ca_config_cfm(con, confrsp->result);
- l2ca_disconnect_req(con);
break;
=20=20=20=20=20=20=20=20=20
case SIG_DISCRSP:
@@ -1165,15 +1168,17 @@
=20=09=20=20=20=20=20=20=20=09=20=20=20=20=20=20=20
/* match id with request */
if (!id_matched(con, rsp->id)) {
- D_ERR(FNC"ID doesn't match ! [%d:%d]\n", con->sig_id_sent, rsp->id);=09=
=09=09
+ D_ERR(FNC"ID doesn't match ! [%d:%d]\n",=20
+ con->sig_id_sent, rsp->id);
return;
}
=20
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
disable_rtx(con);
#endif=09
-
l2ca_disconnect_cfm(con);
+ con->c_result =3D RES_SUCCESS;
+ l2ca_wakeup("l2cap_disconnect_rsp", con);
break;
=20=20=20=20=20=20=20=20
case SIG_ECHORSP: {
@@ -1193,31 +1198,47 @@
PRINTPKT(FNC"optional data ",=20
echo->data, rsp->len-sizeof(sig_echo_pkt));
=20
- l2ca_ping_rsp(echo->data,=20=20
- rsp->len-sizeof(sig_echo_pkt),
- tempcon->remote_bd);
+#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
+ disable_rtx(tempcon);
+#endif
+ /* now wake up l2ca_ping */
=20
- /* for now we disconnect every time a successful=20
- ping was made if no others are using this handle */
+ tempcon->c_status =3D CSTATUS_SUCCESS;
+ tempcon->c_result =3D RES_SUCCESS;
+ l2ca_wakeup("echo resp received", tempcon);
=20=09=09
- if (count_con(hci_handle) =3D=3D 1) {
- printk("DO NOT disconnect after doing ping...\n");
- //lp_disconnect(hci_handle);
- }
break;
}=20=20=20=20
=20=20=20=20=20=20=20=20
- case SIG_INFORSP:
+ case SIG_INFORSP: {
+ l2cap_con *tempcon;
+
+ if ((tempcon =3D get_con_hcihdl(hci_handle))=3D=3DNULL) {
+ D_STATE("Echo rsp : could not find connection\n");
+ return;
+ }
+
info =3D (sig_info_rsp *)(rsp->data);
info->type =3D le16_to_cpu(info->type);
info->result =3D le16_to_cpu(info->result);
+=09=09
D_STATE(FNC"Got info response : result %d\n", info->result);
+
+#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
+ disable_rtx(tempcon);
+#endif
+ /* now wake up l2ca_ping */
+=09=09
+ tempcon->c_status =3D RES_SUCCESS;
+ l2ca_wakeup("info resp received", tempcon);
+=09=09
break;
+ }
=20=20=20=20=20=20=20=20
default:
/* Not a valid command */
DSYS(FNC"Invalid command 0x%x\n", rsp->code);
- l2cap_cmdrej(con->hci_hdl, CMDREJ_NOTUNDERSTOOD, NULL, 0);
+ l2cap_cmdrej(hci_handle, CMDREJ_NOTUNDERSTOOD, NULL, 0);
break;
}
=20=09
@@ -1305,17 +1326,16 @@
Confirms the request to establish a baseband connection
*/
=20
-/* FIXME - add passing authentication challenge if auth is required=20
- to establish the physical link */
-=20=20
void=20
lp_connect_cfm(u8 *bd_addr, u32 status, u16 con_hdl)
{
l2cap_con *con;
D_STATE("lp_connect_cfm: %s (hci_handle : %d)\n",=20
get_err_msg(status), con_hdl);
+ print_data("lp_connect_cfm BD", bd_addr, 6);
=20
- /* FIXME -- use bt session list to notify upper layers that con failed !!=
! */
+ /* FIXME -- use bt session list to notify upper layers that=20
+ con failed !!! */
=20
/* search for the corresponding l2cap connection */
if ((con =3D get_con(bd_addr, CLOSED)) =3D=3D NULL) {
@@ -1323,75 +1343,57 @@
return;
}
=20=09
+ con->c_status =3D status;
+=09
if (status =3D=3D 0) {
/* pos cfm */
con->hci_hdl =3D con_hdl;
con->link_up =3D TRUE;
=20
+ /* see if there is someone to wakeup */
+ l2ca_wakeup("lp_connect_cfm", con);
+=09=09
+ if (con->c_flags & FLAG_RETURNNOW)
+ {
+ printk("Return NOW\n");
+ /* clear flag & set status */
+ con->c_flags &=3D ~FLAG_RETURNNOW;
+ return;
+ }
#ifdef __CRIS__
bt_connections++;
#endif
=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20
- /* Check if a ping is to be sent */
- if (con->ping_sent) {
- D_STATE("baseband up, now send ping\n");
- l2cap_echo_req(con, NULL, 0);
- con->ping_sent=3D0; /* only send one / request */
- return; /* don't try to connect l2cap... */
- }
-
- /* Check if a info req is to be sent */
- if (con->inforeq_sent) {
- D_STATE("baseband up, now send info req\n");
- printk("info type %d\n", con->last_cmd.inforeq_type);
- l2cap_info_req(con, con->last_cmd.inforeq_type);
- con->inforeq_sent=3D0; /* only send one / request */
- return; /* don't try to connect l2cap... */
- }
-=09=09
if (!(con->initiator)) {=09=09
- D_STATE("we are server\n");
+ D_STATE("We are server\n");
/* now wait for a connection request */
} else {
- D_STATE("we are client\n");
+ D_STATE("We are client\n");
PRINTPKT("lp_connect_cfm : HCI connected to ",=20
bd_addr,6);
=20=20=20=20=20=20=20
ENTERSTATE(con, W4_L2CAP_CONNECT_RSP);
PRINTSTATE(con);
=20=09=09=09
-#ifdef BTD_USERSTACK
- /* wait for 3coms HW while they are doing=20
- write_link_policy ?!? */
- printk("sleeping 3 sec... (3com fix)\n");=09
- sleep(3);
-#endif
-
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
- do_cmd_backup(con, SIG_CONREQ, 0, NULL, 0, 0, 0);
-#endif
- /* baseband is up, now initiate l2cap */
- l2cap_connect_req(con, con->psm);
+ l2ca_wakeup("lp_connect_cfm", con);
}
} else {
/* neg cfm */
D_STATE("lp_connect_cfm : (neg) %s\n",get_err_msg(status));
con->link_up =3D FALSE;
=20=09=09
- /* don't notify upper layers if cfm originated from a ping */
- if (con->ping_sent=3D=3D1) {
- /* Remove connection object */
- delete_con(con);
+ l2ca_wakeup("lp_connect_cfm (neg)", con);
+=09=09
+ if (con->c_flags & FLAG_RETURNNOW)
+ {
+ con->c_flags &=3D ~FLAG_RETURNNOW;
return;
}
=20
/* only notify upper layers if we are initiator */
if (con->initiator)
- l2ca_connect_cfm(con, MSGCODE(MSG_LAYER_HCI, status));
-
- DSYS("ACL link failed for some reason, remove con object\n");
- /* Always remove connection object */
- delete_con(con);
+ l2ca_connect_cfm(con, MSGCODE(MSG_LAYER_HCI,=20
+ status));
}
}
=20=20
@@ -1422,7 +1424,7 @@
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
/* cancel any outstanding timers */
disable_rtx(con);
- //disable_ertx(con);
+ disable_ertx(con);
#endif
=20
/* if not connected yet simply remove it */
@@ -1560,20 +1562,46 @@
con->link_up =3D 1;
ENTERSTATE(con, W4_L2CAP_CONNECT_RSP);
PRINTSTATE(con);
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
- do_cmd_backup(con, SIG_CONREQ, 0, NULL, 0, 0, 0);
-#endif
+
l2cap_connect_req(con, psm);
=20
return 0;
} else {
D_STATE("l2ca_connect_req : create new baseband link\n");
- /* create baseband connection, l2cap_connect_req is called=20
- from lp_connect_cfm */
- return lp_connect_req(con->remote_bd);=20=20
+ lp_connect_req(con->remote_bd);=20=20
+
+ /* wait here until we received a lp_connect_cfm */
+ l2ca_wait("l2ca_connect_req : wait baseband", con);
+=09=09
+ if (con->c_status !=3D RES_SUCCESS) {
+ D_ERR("l2cap_connect_req failed !\n");
+ delete_con(con);
+ return -1;
}
}
=20
+ /* Now send connect req */
+ con->c_status =3D CSTATUS_RTX_TIMEOUT;
+
+ /* Leave loop when either status failed or success */
+ while (con->c_status =3D=3D CSTATUS_RTX_TIMEOUT)
+ {
+ /* baseband is up, now initiate send connect req */
+ l2cap_connect_req(con, con->psm);
+
+ /* wait until we received a response or after timeout */
+
+#ifdef BTD_USERSTACK
+ printk("Sleeping 2 sec\n");=09
+ sleep(2);
+#else
+ l2ca_wait("l2cap_connect_req : wait rsp", con);
+#endif
+ }
+
+ return con->c_result;
+}
+
/* params determines how we would like to receive data */
s32=20
l2ca_config_req(l2cap_con *con, u16 in_mtu, flow *outflow,=20
@@ -1592,10 +1620,6 @@
if (con->current_state =3D=3D CONFIG) {=20=20
/* local mtu is set in l2cap_config_req */
=20
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
- do_cmd_backup(con, SIG_CONFREQ, in_mtu, outflow,=20
- flush_timeout, link_to, 0);
-#endif=09=09
return l2cap_config_req(con, in_mtu, outflow,=20
flush_timeout, link_to);=20=20
=20
@@ -1616,10 +1640,7 @@
=20
con->conf_req_ready =3D FALSE;
con->conf_rsp_ready =3D FALSE;
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS=09=09
- do_cmd_backup(con, SIG_CONFREQ, in_mtu, outflow,=20
- flush_timeout, link_to, 0);
-#endif
+
return l2cap_config_req(con, in_mtu, outflow,=20
flush_timeout, link_to);=20=20
return -1;
@@ -1644,9 +1665,6 @@
=20
if (con->current_state =3D=3D OPEN || con->current_state =3D=3D CONFIG) {
=20
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
- do_cmd_backup(con, SIG_DISCREQ, 0, NULL,0, 0, 0);
-#endif
result =3D l2cap_disconnect_req(con);
=20
ENTERSTATE(con, W4_L2CAP_DISCONNECT_RSP);
@@ -1655,10 +1673,11 @@
D_ERR("l2ca_disconnect_req : Invalid state !\n");
return -1;=20=20=20=20
}
-#ifdef __KERNEL__
- interruptible_sleep_on(&l2cap_disconnect_wq);
-#endif
- return result;
+=09
+ /* wait here until we get a confirm */
+ l2ca_wait("l2ca_disconnect_req", con);
+
+ return con->c_result;
}
=20
=20
@@ -1691,7 +1710,7 @@
PRINTSTATE(con);
}=20
else if (response =3D=3D RES_PENDING) {
- /* remain in */
+ /* remain in same state */
}
else if (response >=3D RES_PSMNEG) {
/* 'l2ca_connect_rsp_neg()' */
@@ -1704,13 +1723,11 @@
return result;
}
=20
-
-/* fixme -- use inparams... */
s32=20
-l2ca_config_rsp(l2cap_con* con, u32 out_mtu, flow *in_flow, s32 ok)
+l2ca_config_rsp(l2cap_con* con, u32 out_mtu, flow *in_flow, s32 result)
{
#define FNC "l2ca_config_rsp : "
- s32 result;
+ s32 ret_val =3D -1;
=20
if (PARANOIA_CHECKCON(con)) {
D_ERR("%s l.%d NULL/magic failed\n", __FILE__, __LINE__);
@@ -1726,14 +1743,14 @@
return -1;
}
=20
- if (ok) {
+ if (result =3D=3D CONF_SUCCESS) {
/* upper layers responded OK */
con->conf_rsp_ready =3D TRUE;
=20
- result =3D l2cap_config_rsp(con, out_mtu, in_flow);
+ ret_val =3D l2cap_config_rsp(con, out_mtu, in_flow, result);
=20
/* check if we have sent a configure request yet */
- if (con->conf_req_ready) {
+ if (con->conf_req_ready && !con->remote_flags) {
/* all done, proceed to OPEN */
ENTERSTATE(con, OPEN);
PRINTSTATE(con);
@@ -1745,19 +1762,14 @@
l2ca_config_cfm(con, RES_SUCCESS);
=20
} else {
- DSYS(FNC"Not yet a pos rsp on config_req\n");
+ D_STATE(FNC"Conf not done or flags set\n");
}
} else {
- /* FIXME - send l2cap_config_rsp_neg */
- D_STATE(FNC"params not accepted by us (FIXME !!) !\n");
-=09=09
- /* add result parameter in l2cap_config_rsp (for neg rsp) */
-=09=09
- l2cap_config_rsp(con, out_mtu, in_flow);
- //l2ca_config_cfm(con, result);
- return -1;
+ D_STATE("We don't accepted remote options\n");
+ ret_val =3D l2cap_config_rsp(con, out_mtu, in_flow, result);
}
- return result;
+
+ return ret_val;
#undef FNC
}
=20
@@ -1809,10 +1821,114 @@
/* (E5) Timer events */
/********************/
=20
-/* FIXME !*/
-/* RTX */
-/* ERTX */
+#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
+
+void l2ca_timeoutind(l2cap_con *con)
+{
+ printk("l2ca_timeoutind\n");
+ con->c_status =3D CSTATUS_RTX_TIMEOUT;=09
+ l2ca_wakeup("l2ca_timeoutind ", con);
+}
+
+#ifdef __KERNEL__
+void
+l2cap_rtx_timeout(unsigned long ptr)
+{
+ l2cap_con *con =3D (l2cap_con*)ptr;
+#else /* usermode timer */
+void
+l2cap_rtx_timeout(void)
+{
+ l2cap_con *con =3D timeout_con;
+
+ if (timer_cancelled) {
+ D_TIM("RTX timer already cancelled\n");
+ return;
+ }
+#endif
+ /* do some paranoia checks */
+
+ if (PARANOIA_CHECKCON(con)) {
+ D_ERR("%s l.%d NULL/magic failed\n", __FILE__, __LINE__);
+ return;
+ }
+
+ D_TIM("l2cap_rtx_timeout (current no rtx : %d)\n",=20
+ con->timer.rtx_no);
+=20=20=20=20=20=20
+ con->timer.rtx_inuse =3D 0;
+=20=20
+ if (con->timer.rtx_no =3D=3D MAX_NO_RTX)
+ {
+ con->c_status =3D CSTATUS_MAX_NO_RTX;
+=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20
+ D_TIM("Connection unresponsive\n");
+=09=09
+ show_con("Connection unresponsive\n", con);
+=09=09
+ con->c_result =3D MSGCODE(MSG_LAYER_L2CAP,=20
+ L2CAP_CON_UNRESPONSIVE);
+=09=09
+ l2ca_wakeup("rtx_timeout", con);
+
+ /* reset rtx counter */
+ con->timer.rtx_no =3D 0;
+
+ if (con->timer.rtx_action =3D=3D RTX_ACTION_START_ERTX) {
+ /* start ertx timer */
+ D_TIM("Starting ERTX\n");
+ start_ertx(con, ERTX_TIMEOUT);
+ }
+ else if (con->timer.rtx_action =3D=3D RTX_ACTION_TERMINATE){
+ D_TIM("Removing connection\n");
+ l2ca_disconnect_ind(con);
+ ENTERSTATE(con, CLOSED);
+ delete_con(con);
+ }
+ }
+ else
+ {=20=20
+ con->timer.rtx_no++;
+ l2ca_timeoutind(con);=09
+ }
+=09
+=09
+#ifndef __KERNEL__
+ timeout_con =3D NULL;
+#endif
+}
=20
+void
+l2cap_ertx_timeout(unsigned long ptr)
+{
+ l2cap_con *con;
+ D_TIM("l2cap_ertx_timeout\n");
+ con =3D (l2cap_con*)ptr;
+
+ /* do paranoia check */
+ if (PARANOIA_CHECKCON(con)) {
+ D_ERR("%s l.%d NULL/magic failed\n", __FILE__, __LINE__);
+ return;
+ }
+
+ if (con->timer.ertx_action =3D=3D ERTX_ACTION_TERMINATE) {
+ D_TIM("Removing connection\n");
+ l2ca_disconnect_ind(con);
+ ENTERSTATE(con, CLOSED);
+ delete_con(con);
+ } else if (con->timer.ertx_action =3D=3D ERTX_ACTION_DISCONNECT) {
+=09=09
+ D_TIM("Disconnect connection\n");
+ /* set dont sleep flag so that we wont do sleep=20
+ when not running in usermode context */
+ con->c_flags |=3D FLAG_DONTSLEEP;
+ ENTERSTATE(con, CONFIG); /* CERT HACK ! */
+ l2ca_disconnect_req(con);
+ }
+}
+
+#endif /* CONFIG_BLUETOOTH_L2CAP_USE_TIMERS */
+
/*******************************************************************/
/*-------------------------- ACTIONS ------------------------------*/
/*******************************************************************/
@@ -1890,7 +2006,7 @@
=20=09
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
/* start retransmission timer */
- start_rtx(con, RTX_TIMEOUT);
+ start_rtx(con, RTX_TIMEOUT, RTX_ACTION_START_ERTX);
#endif
return hci_send_data(tx);
}
@@ -1951,14 +2067,13 @@
req =3D (sig_confreq*)(l2cap_buf->frame + L2CAP_HDRSIZE + SIGCMD_HDRSIZE);
=20=09
if (opt_len > 0) {
- printk("sending options...\n");
/* if the negotiated mtu differs from the current, send it */
=20=20=20=20=20=20=20=20=20=20=20
opt =3D (struct l2cap_option*)(l2cap_buf->frame+L2CAP_HDRSIZE +=20
SIGCMD_HDRSIZE + CONF_REQSIZE);
=20=20
if (in_mtu !=3D 0) {
- printk("sending in_mtu %d\n", in_mtu);
+ printk("Sending in_mtu %d\n", in_mtu);
opt->type =3D OPT_MTU;
opt->len =3D 2;
*(opt->option_data) =3D (u8)(in_mtu & 0x00ff);
@@ -1969,7 +2084,7 @@
}
=20=09=09
if (flush_timeout !=3D 0) {
- printk("sending flush_timeout %d\n", flush_timeout);
+ printk("Sending flush_timeout %d\n", flush_timeout);
opt->type =3D OPT_FLUSH;
opt->len =3D 2;
*(opt->option_data) =3D (u8)(flush_timeout & 0x00ff);
@@ -1980,7 +2095,7 @@
}
=20=09=09
if (outflow !=3D NULL){=20
- printk("sending conf req outflow %d\n", flush_timeout);
+ printk("Sending conf req outflow\n");
print_flow(outflow);
opt->type =3D OPT_QOS;
opt->len =3D sizeof(flow);
@@ -2011,7 +2126,7 @@
print_data("l2cap options : ", (char*)opt , opt_len);
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
/* start retransmission timer */
- start_rtx(con, RTX_TIMEOUT);
+ start_rtx(con, RTX_TIMEOUT, RTX_ACTION_START_ERTX);
#endif
return hci_send_data(tx);
}
@@ -2055,13 +2170,13 @@
=20
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
/* start retransmission timer */
- start_rtx(con, RTX_TIMEOUT);
+ start_rtx(con, RTX_TIMEOUT, RTX_ACTION_TERMINATE);
#endif
return hci_send_data(tx);
}
=20
s32=20
-l2cap_echo_req(l2cap_con *con, u8 *opt_data, s32 opt_len)
+l2cap_echo_req(l2cap_con *con, u8 *opt_data, u16 opt_len)
{
bt_tx_buf *tx;=20
l2cap_tx_buf *l2cap_buf; /* Entire l2cap frame + lower layer hdrs */
@@ -2098,16 +2213,18 @@
/* pb_flag is set from hci_send_data */
tx->hci_hdl =3D hci_hdl;
tx->bc_flag =3D NO_BROADCAST;
- tx->cur_len =3D L2CAP_HDRSIZE + payload_len; /* Increased when lower
- layers add header data */
+
+ /* Increased when lower layers add header data */
+ tx->cur_len =3D L2CAP_HDRSIZE + payload_len;
+
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
- start_rtx(con, RTX_TIMEOUT);
+ start_rtx(con, RTX_TIMEOUT, RTX_ACTION_DISCONNECT);
#endif
return hci_send_data(tx);
}
=20
s32=20
-l2cap_echo_rsp(s32 hci_hdl, s32 id, u8 *opt_data, s32 opt_len)
+l2cap_echo_rsp(s32 hci_hdl, s32 id, u8 *opt_data, u16 opt_len)
{
bt_tx_buf *tx;=20
l2cap_tx_buf *l2cap_buf; /* Entire l2cap frame + lower layer hdrs */
@@ -2186,7 +2303,7 @@
tx->cur_len =3D L2CAP_HDRSIZE + payload_len; /* Increased when lower
layers add header data */
#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
- start_rtx(con, RTX_TIMEOUT);
+ start_rtx(con, RTX_TIMEOUT, RTX_ACTION_TERMINATE);
#endif
return hci_send_data(tx);
}
@@ -2320,7 +2437,6 @@
if ((rsp->result =3D cpu_to_le16(response)) =3D=3D RES_PENDING)
rsp->status =3D cpu_to_le16(status);
else {
- printk("Result not pending, force status =3D no further info\n");
rsp->status =3D cpu_to_le16(STAT_NOINFO);
}
=20=09
@@ -2338,27 +2454,40 @@
return hci_send_data(tx);=20=20
}
=20=20
+
s32=20
-l2cap_config_rsp(l2cap_con* con, u32 out_mtu, flow *in_flow)
+l2cap_config_rsp(l2cap_con* con, u32 out_mtu, flow *in_flow, s32 result)
{
bt_tx_buf *tx;=20
l2cap_tx_buf *l2cap_buf; /* Entire l2cap frame + lower layer hdrs */
sig_cmd *cmd;
sig_confrsp *rsp;
u16 payload_len;
+ int opt_len =3D 0;
+ struct l2cap_option *opt;
=20
D_XMIT("l2cap_config_rsp : rcid : %d, out_mtu: %d \n",=20
con->remote_cid, out_mtu);
-#if 0
+
+ /* If negative, the accepted options are sent back */
if (result !=3D RES_SUCCESS) {
- /* FIXME -- send back negative response */
- DSYS("FIXME !!!!!!!!!!!!!!!!!!!!!!!! neg config rsp\n");
+
+ DSYS("Neg config rsp !\n");
+
+ if (out_mtu !=3D 0) {
+ con->remote_mtu =3D out_mtu;
+ opt_len+=3D4;
}
-#endif
+ if (in_flow !=3D NULL){
+ /* The accepted settings for incoming traffic */
+ opt_len +=3Dsizeof(flow);
+ }
+ }
=20
- payload_len =3D SIGCMD_HDRSIZE + CONF_RSPSIZE;
+ payload_len =3D SIGCMD_HDRSIZE + CONF_RSPSIZE + opt_len;
=20=20=20
- tx =3D subscribe_bt_buf(sizeof(l2cap_tx_buf) + L2CAP_HDRSIZE+payload_len);
+ tx =3D subscribe_bt_buf(sizeof(l2cap_tx_buf) +=20
+ L2CAP_HDRSIZE+payload_len);
if (!tx) {
D_ERR("l2cap_config_rsp : didn't get a valid tx buf\n");
return -1;
@@ -2367,29 +2496,57 @@
l2cap_buf =3D (l2cap_tx_buf *)(tx->data);
=20
cmd =3D (sig_cmd*)(l2cap_buf->frame + L2CAP_HDRSIZE);
- rsp =3D (sig_confrsp*)(l2cap_buf->frame + L2CAP_HDRSIZE + SIGCMD_HDRSIZE);
+ rsp =3D (sig_confrsp*)(l2cap_buf->frame + L2CAP_HDRSIZE +=20
+ SIGCMD_HDRSIZE);
=20=20=20
/* Now fill in header fields */=20=20
rsp->src_cid =3D cpu_to_le16(con->remote_cid);
+ rsp->flags =3D con->remote_flags;
+ rsp->result =3D cpu_to_le16((u16)result);
=20
- /* FIXME - WHERE ARE THIS DETERMINED ??? */
- rsp->flags =3D 0; /* No more config responses to follow */
+ /* Include unaccepted options if any */
+ if (opt_len)
+ {
+ opt =3D (struct l2cap_option*)(rsp + CONF_RSPSIZE);
=20
- rsp->result =3D cpu_to_le16(CONF_SUCCESS);
+ if (out_mtu !=3D 0) {
+ printk("Sending out_mtu %d\n", out_mtu);
+ opt->type =3D OPT_MTU;
+ opt->len =3D 2;
+ *(opt->option_data) =3D (u8)(out_mtu & 0x00ff);
+ *(opt->option_data+1) =3D (u8)(out_mtu>>8) & 0x00ff;
=20=20=20
+ /* forward pointer for other options */
+ opt =3D (struct l2cap_option*)((char *)opt + 4);
+ }
+=09=09
+ if (in_flow !=3D NULL){=20
+ printk("Sending conf req in_flow\n");
+ print_flow(in_flow);
+ opt->type =3D OPT_QOS;
+ opt->len =3D sizeof(flow);
+ memcpy((char*)opt+2, in_flow, sizeof(flow));
+ }
+ print_data("options : ", (u8*)rsp, opt_len + CONF_RSPSIZE);
+ }
+=09
cmd->code =3D SIG_CONFRSP;
- cmd->id =3D con->sig_id_rcv; /* Send back same id as received on request =
*/
- cmd->len =3D cpu_to_le16(CONF_RSPSIZE);
+ cmd->id =3D con->sig_id_rcv; /* Send back same id as received on=20
+ request */
=20
+ cmd->len =3D cpu_to_le16(CONF_RSPSIZE + opt_len);
=20
SET_L2CAP_HDR(l2cap_buf->frame, payload_len, CIDSIG);
=20
/* pb_flag is set from hci_send_data */
tx->hci_hdl =3D con->hci_hdl;
tx->bc_flag =3D NO_BROADCAST;
- tx->cur_len =3D L2CAP_HDRSIZE + payload_len; /* Increased when lower
- layers add header data */
- PRINTPKT("config rsp : ", l2cap_buf, L2CAP_HDRSIZE + payload_len);
+=09
+ /* Increased when lower layers add header data */
+ tx->cur_len =3D L2CAP_HDRSIZE + payload_len;
+
+ PRINTPKT("config rsp : ", (u8*)l2cap_buf,=20
+ L2CAP_HDRSIZE + payload_len);
return hci_send_data(tx);
}
=20
@@ -2516,6 +2673,8 @@
return;
}
=20=09
+ con->c_result =3D L2CAP_CON_PENDING;
+=09
get_upper(con->psm)->con_pnd(con, status);=20
}
=20
@@ -2580,33 +2739,33 @@
DSYS("l2cap channel (%d,%d) [%s] disconnected\n",=20
con->local_cid, con->remote_cid, psm2str(con->psm));
=20
+ /* remove l2cap connection */
+ delete_con(con);
+
+#ifdef __KERNEL__
+ l2ca_wakeup("l2ca_disconnect_cfm", con);
+#endif
+
/* fixme -- if we want to keep baseband connection we must=20
leave the l2cap connection which holds the hci handle=20
simply just clear l2cap params but keep hci handle ! */
=20=09
- /* remove l2cap connection */
- delete_con(con);
-
if (count_con(tmp_hdl) =3D=3D 0) {
DSYS("l2ca_disconnect_cfm : (C) no more l2cap connections\n");
DSYS("Shutdown baseband\n");
lp_disconnect(tmp_hdl);
}
-#ifdef __KERNEL__
- wake_up_interruptible(&l2cap_disconnect_wq);
-#endif
}
=20
-s32 l2ca_ping(BD_ADDR bd)
+s32 l2ca_ping(BD_ADDR bd, u8 *opt_data, u16 len)
{
l2cap_con *con;
s32 i ;
u8 rev_bd[6];
=20
D_XMIT("Sending ping\n");
- PRINTPKT("Ping destination : bd ", bd, 6) ;
+ print_data("Ping destination : bd ", bd, 6) ;
=20
- /* up3 --remove */
/* bd is big endian, reverse byte order to little endian */
for (i =3D 0; i < 6; i++) {
rev_bd[5-i] =3D bd[i];
@@ -2614,7 +2773,7 @@
=20=09
con =3D get_con(rev_bd, ANY_STATE);
=20
- if (!con) {
+ if (con =3D=3D NULL) {
D_STATE("l2ca_ping : create new baseband link\n");
con =3D create_con(0/* not yet set */,=20
get_cid(), 0/* not yet set */);
@@ -2625,38 +2784,56 @@
=20
memcpy(con->remote_bd, rev_bd, 6);
con->link_up =3D 0;
- con->ping_sent =3D 1;
con->initiator =3D 1;
insert_con(con);
- /* l2cap_echo_req is called in lp_connect_cfm */
- return lp_connect_req(con->remote_bd);
- } else {
- /* use existing handle */
- D_STATE("l2ca_ping : using existing handle\n");
- con->ping_sent=3D1;
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS=09=09
- do_cmd_backup(con, SIG_ECHOREQ, 0, NULL, 0, 0, 0);
-#endif
- l2cap_echo_req(con, NULL, 0);
- return 0 ;
+
+ /* c_flags used to not try to connect l2cap when=20
+ lp_connect_cfm arrives */
+ con->c_flags |=3D FLAG_RETURNNOW;
+
+ lp_connect_req(con->remote_bd);
+
+ /* wait here until we received a lp_connect_cfm */
+ l2ca_wait("l2ca_ping : wait baseband", con);
+=09=09
+
+ if (con->c_status =3D=3D RES_SUCCESS) {
+ /* check status */
+ printk("Now we got baseband, send echo req !\n");
+ }
+ else {
+ printk("Ping failed !\n");
+ delete_con(con);
+ return -1;
}
}
=20
-void l2ca_ping_rsp(u8 *data, u32 len, BD_ADDR remote_bd)
+ /* Now send echo req */=09
+
+ con->c_status =3D CSTATUS_RTX_TIMEOUT;
+
+ /* leave loop when either status failed or success */
+ while (con->c_status =3D=3D CSTATUS_RTX_TIMEOUT)
{
-#ifdef BTD_USERSTACK
- printf("Ping : got response from %02x:%02x:%02x:%02x:%02x:%02x\n\n",=20
- remote_bd[5], remote_bd[4],=20
- remote_bd[3], remote_bd[2],=20
- remote_bd[1], remote_bd[0]);
- if (len > 0)
- print_data("ping data : ", data, len);
-#else
- /* Fixme - indicate to usermode requester */
- D_STATE("ping : got response\n\n");
-#endif
+ printk("Sending echo req...\n");
+ l2cap_echo_req(con, opt_data, len);=09
+ /* wait until we received a response or after timeout */
+=09=09
+ printk("Waiting for response or timeout\n");
+
+ l2ca_wait("l2ca_ping wait echo resp", con);
+
+ printk("Woke up after sending echo req\n");
}
=20
+ if (con->c_status =3D=3D CSTATUS_MAX_NO_RTX)
+ {
+ /* max number reached, try to disconnect */
+ l2ca_disconnect_req(con);
+ }
+
+ return con->c_result;
+}
=20
s32 l2ca_getinfo(BD_ADDR bd, u16 infotype)
{
@@ -2673,7 +2850,7 @@
=20=09
con =3D get_con(rev_bd, ANY_STATE);
=20
- if (!con) {
+ if (con =3D=3D NULL) {
D_STATE("l2ca_getinfo : create new baseband link\n");
con =3D create_con(0/* not yet set */,=20
get_cid(), 0/* not yet set */);
@@ -2684,165 +2861,97 @@
=20
memcpy(con->remote_bd, rev_bd, 6);
con->link_up =3D 0;
- con->inforeq_sent =3D 1;
+
con->initiator =3D 1;
insert_con(con);
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS=09=09
- do_cmd_backup(con, SIG_INFOREQ, 0, NULL, 0, 0, infotype);
-#endif
- /* l2cap_echo_req is called in lp_connect_cfm */
- return lp_connect_req(con->remote_bd);
- } else {
- /* use existing handle */
- D_STATE("l2ca_getinfo : using existing handle\n");
- con->inforeq_sent =3D 1;
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS=09=09
- do_cmd_backup(con, SIG_INFOREQ, 0, NULL, 0, 0, infotype);
-#endif
- l2cap_info_req(con, infotype);
- return 0 ;
- }
-}
=20
-/*******************************************************************/
-/* (A5) setting timers */
-/***********************/
+ /* c_flags used to not try to connect l2cap when=20
+ lp_connect_cfm arrives */
+ con->c_flags |=3D FLAG_RETURNNOW;
=20
-/* used to resend lost l2cap commands */
+ lp_connect_req(con->remote_bd);
=20
-/* FIXME -- group different l2cap command options=20
- conreq/confreq/inforeq */
+ /* wait here until we received a lp_connect_cfm */
+ l2ca_wait("l2ca_getinfo : wait baseband", con);
=20
-void do_cmd_backup(l2cap_con *con, u8 type, u16 in_mtu,=20
- flow *outflow, u16 flush_timeout, u16 link_to,
- u16 inforeq_type)
-{
- D_TIM("do_cmd_backup !\n");
- con->last_cmd.type =3D type; /* type of request */=20
- con->last_cmd.nbr_resends =3D 0;
- con->last_cmd.in_mtu =3D in_mtu;
- con->last_cmd.flush_timeout =3D flush_timeout;
- con->last_cmd.link_to =3D link_to;
- con->last_cmd.outflow =3D outflow;
- con->last_cmd.inforeq_type =3D inforeq_type;
+ if (con->c_status =3D=3D RES_SUCCESS) {
+ /* check status */
+ printk("Now we got baseband, send info req !\n");
}
+ else {
+ printk("GetInfo failed ! [cstatus %d]\n",=20
+ con->c_status);
+ delete_con(con);
+ return -1;
+ }
+ }
=20
=20
-#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
-#ifdef __KERNEL__
-void
-l2cap_rtx_timeout(unsigned long ptr)
-{
- l2cap_con *con =3D (l2cap_con*)ptr;
-#else /* usermode timer */
-void
-l2cap_rtx_timeout(void)
-{
- l2cap_con *con =3D timeout_con;
+ /* Now send info req */=09
=20
- // return;
+ con->c_status =3D CSTATUS_RTX_TIMEOUT;
=20
- if (timer_cancelled) {
- D_TIM("RTX timer already cancelled\n");
- return;
- }
-#endif
+ /* leave loop when either status failed or success */
+ while (con->c_status =3D=3D CSTATUS_RTX_TIMEOUT)
+ {
+ printk("Sending info req...\n");
+ l2cap_info_req(con, infotype);=09
+ /* wait until we received a response or after timeout */
=20
- /* do some paranoia checks */
+ printk("Waiting for response or timeout\n");
=20
- if (PARANOIA_CHECKCON(con)) {
- D_ERR("%s l.%d NULL/magic failed\n", __FILE__, __LINE__);
- return;
+ l2ca_wait("l2ca_ping wait echo resp", con);
+
+ printk("Woke up after sending info req\n");
}
=20
- con->last_cmd.nbr_resends++;
+ return con->c_result;
+}
=20
- D_TIM("l2cap_rtx_timeout (no rtx : %d)\n", con->last_cmd.nbr_resends);
+/*******************************************************************/
+/* (A5) setting timers */
+/***********************/
=20
- printk("type %d, in_mtu %d, flush_timeout %d , link_to %d\n",=20
- con->last_cmd.type, con->last_cmd.in_mtu,=20
- con->last_cmd.flush_timeout,
- con->last_cmd.link_to);
- print_flow(con->last_cmd.outflow);
+/* used to resend lost l2cap commands */
=20
- /* FIXME -- send l2ca_timeoutind() */
+#ifdef CONFIG_BLUETOOTH_L2CAP_USE_TIMERS
=20
- if (MAX_NO_RTX =3D=3D 0) {
- /* no retransmissions, shutdown connection */
- printk("NO retransmissions, lets shutdown connection...\n");
- l2ca_disconnect_req(con);
- return;
- } else if (con->last_cmd.nbr_resends =3D=3D MAX_NO_RTX) {
- /* notify upper layers that link is going down */
+#ifdef __KERNEL__
=20
- /* FIXME l2ca_disconnect_ind */
- D_TIM("Connection unresponsive, free CID\n");
+/* Action is used when the sending function doesn't want
+ to handle the action it self */
+void
+start_rtx(l2cap_con *con, unsigned short timeout, u16 action)
+{
+ /* multiply by 2 each rtx */
+ timeout *=3D (2<<(con->timer.rtx_no));
=20
- show_con("Connection unresponsive, free CID\n", con);
+ /* FIXME -- use flush timeout to calculate number of
+ retransmissions */
=20
- /* the link is unresponsive, remove connection */
- ENTERSTATE(con, CLOSED);
+ D_TIM("Starting RTX timer (%d sec)\n", timeout);
=20
- /* remove connection */
- delete_con(con);
+ /* fixme -- add timer list for multiple calls */
+ if (con->timer.rtx_inuse)
+ {
+ D_ERR("start_rtx : timer already used\n");
return;
}
=20
- /* now resend command */
- switch(con->last_cmd.type) {
- case SIG_CONREQ:
- D_TIM("resending connection request\n");
- l2cap_connect_req(con, con->psm);
- break;
-
- case SIG_CONFREQ:
- D_TIM("resending configure request\n");
- l2cap_config_req(con,=20
- con->last_cmd.in_mtu,=20
- con->last_cmd.outflow,
- con->last_cmd.flush_timeout,=20
- con->last_cmd.link_to);=09=20=20
- break;
-
- case SIG_DISCREQ:
- D_TIM("resending disconnection request\n");
- l2cap_disconnect_req(con);
- break;
-
- case SIG_ECHOREQ:
- D_TIM("resending echo request NOT\n");
- /* FIXME */
- //l2cap_disconnect_req(con);
- break;
-
- case SIG_INFOREQ:
- /* FIXME */
- D_TIM("resending echo request NOT\n");
- break;
-
- default:
- D_WARN("l2cap_rtx_timeout : unknown !\n");
- break;
- }=20
-#ifndef __KERNEL__
- timeout_con =3D NULL;
-#endif
+ init_timer(&con->timer.rtx);
+ con->timer.rtx.function =3D l2cap_rtx_timeout;
+ con->timer.rtx.data =3D (unsigned long)con;
+ con->timer.rtx.expires =3D jiffies + timeout*HZ;
+ con->timer.rtx_inuse =3D 1;
+ con->timer.rtx_action =3D action;
+ add_timer(&con->timer.rtx);=20=20
}
=20
-#ifdef __KERNEL__
-void
-start_rtx(l2cap_con *con, unsigned short timeout)
-{
- D_TIM("Starting RTX timer (%d sec)\n", timeout);
=20
- init_timer(&con->rtx_timer);
- con->rtx_timer.function =3D l2cap_rtx_timeout;
- con->rtx_timer.data =3D (unsigned long)con;
- con->rtx_timer.expires =3D jiffies + timeout*HZ;
- add_timer(&con->rtx_timer);=20=20
-}
-#else
+#else /* USERSTACK */
=20
+/* FIXME -- Currently usermode stack and signal() doesn't work=20
+ since we are using threads */
void=20
start_rtx(l2cap_con *con, s32 timeout)
{
@@ -2855,7 +2964,7 @@
D_TIM("Starting RTX timer (%d sec)\n", timeout);
=20
if (timeout_con)
- D_TIM("Timer already in use !!!\n");
+ D_ERR("Timer already in use !!!\n");
=20
timeout_con =3D con;
=20
@@ -2869,49 +2978,60 @@
}
#endif /* __KERNEL__ */
=20
+
void
disable_rtx(l2cap_con *con)
{
D_TIM("Disabling RTX timer\n");
#ifdef __KERNEL__
- del_timer(&con->rtx_timer);
+ if (con->timer.rtx_inuse) {
+ del_timer(&con->timer.rtx);
+ con->timer.rtx_inuse =3D 0;
+ }
+ else
+ D_TIM("RTX never started\n");
#else
timer_cancelled =3D 1;
timeout_con =3D NULL;
#endif
}
=20
+
void
-l2cap_ertx_timeout(unsigned long ptr)
+start_ertx(l2cap_con *con, unsigned short timeout)
{
- l2cap_con *con;
- D_TIM("l2cap_ertx_timeout\n");
- con =3D (l2cap_con*)ptr;
+ D_TIM("Starting ERTX timer (%d sec)\n", timeout);
=20
- /* do paranoia check */
- if (PARANOIA_CHECKCON(con)) {
- D_ERR("%s l.%d NULL/magic failed\n", __FILE__, __LINE__);
+ if (con->timer.ertx_inuse)
+ {
+ D_TIM("start_ertx : timer already used\n");
return;
}
-
- /* send a new request or terminate ? */
-
- /* if sending new request start RTX again */
-
- /* terminate for now */
-}
=20
-void
-start_ertx(l2cap_con *con, unsigned short timeout)
-{
- D_TIM("Starting ERTX timer (%d sec)\n", timeout);
+ init_timer(&con->timer.ertx);
+ con->timer.ertx.function =3D l2cap_ertx_timeout;
+ con->timer.ertx.data =3D (unsigned long)con;
+ con->timer.ertx.expires =3D jiffies + timeout*HZ;
+ con->timer.ertx_inuse =3D 1;
+ add_timer(&con->timer.ertx);
}
=20
void
disable_ertx(l2cap_con *con)
{
D_TIM("Disabling ERTX timer\n");
+#ifdef __KERNEL__
+ if (con->timer.rtx_inuse){
+ del_timer(&con->timer.ertx);
+ con->timer.rtx_inuse =3D 0;
}
+ else
+ D_TIM("ERTX never started\n");
+#else
+ /* FIXME */
+ printk("disable_ertx FIXME\n");
+#endif
+}
#endif /* CONFIG_BLUETOOTH_L2CAP_USE_TIMERS */
=20
/***************************************************************/
@@ -2944,7 +3064,7 @@
D_RCV("parse_options : Storing remote options on rCID %d\n",=20
con->remote_cid);
=20
- print_data("parse_options : ", data, len);
+ PRINTPKT("parse_options : ", data, len);
=20
while (pos < len) {
opt =3D (l2cap_option*)(data + pos);
@@ -2979,8 +3099,6 @@
D_RCV("parse_options : flush timeout %d ms\n",=20
con->flush_timeout);
=20
- DSYS("parse_options : flush timeout %d ms\n",=20
- con->flush_timeout);
found_option =3D 1;
break;
=20=20=20=20=20=20=20
@@ -2991,7 +3109,6 @@
/* FIXME -- return error code if not accepted */
=20
D_RCV("parse_options : qos\n");
- DSYS("parse_options : qos\n");
print_flow(&con->remote_qos);
found_option =3D 1;
break;
@@ -3070,10 +3187,8 @@
void=20
print_flow(flow *f)
{
- printk("-------------------------------------------------------\n");
-
if (f =3D=3D NULL) {
- printk("NULL !\n");
+ printk(" flow: NULL\n");
return;
} else {
printk("flow:\n");
@@ -3083,8 +3198,6 @@
(int)f->bucket_size, (int)f->peak, (int)f->latency,=20
(int)f->delay);
}
-=09
- printk("-------------------------------------------------------\n");
}
=20
/* Returns a free cid in range 0x0040 - 0xffff */
|