From 7a8167b24cec8edbd2fe5357f669e8e1f82ed421 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 1 May 2003 04:29:54 +0200 Subject: [Bluetooth] Compile fix for URB_ZERO_PACKET This patch fixes the compile problem with URB_ZERO_PACKET. --- drivers/bluetooth/hci_usb.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index 2b173dfe5f9e..a0ccbd05dfcf 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -64,8 +64,8 @@ #endif #ifndef CONFIG_BT_USB_ZERO_PACKET -#undef USB_ZERO_PACKET -#define USB_ZERO_PACKET 0 +#undef URB_ZERO_PACKET +#define URB_ZERO_PACKET 0 #endif static struct usb_driver hci_usb_driver; @@ -458,7 +458,7 @@ static inline int hci_usb_send_bulk(struct hci_usb *husb, struct sk_buff *skb) pipe = usb_sndbulkpipe(husb->udev, husb->bulk_out_ep->desc.bEndpointAddress); usb_fill_bulk_urb(urb, husb->udev, pipe, skb->data, skb->len, hci_usb_tx_complete, husb); - urb->transfer_flags = USB_ZERO_PACKET; + urb->transfer_flags = URB_ZERO_PACKET; BT_DBG("%s skb %p len %d", husb->hdev.name, skb, skb->len); -- cgit v1.2.3 From d89da5d861a181b860b00807ca8eba284ceffff5 Mon Sep 17 00:00:00 2001 From: Maksim Krasnyanskiy Date: Thu, 8 May 2003 02:38:41 -0700 Subject: [Bluetooth] Add required infrastructure for socket module refcounting. Initialize ->owner fields in Bluetooth protocols and drivers. --- drivers/bluetooth/hci_ldisc.c | 1 + include/net/bluetooth/l2cap.h | 2 ++ net/bluetooth/af_bluetooth.c | 13 ++++++++----- net/bluetooth/bnep/core.c | 11 ++++++++--- net/bluetooth/bnep/sock.c | 7 +------ net/bluetooth/l2cap.c | 20 +++++++++++--------- net/bluetooth/rfcomm/core.c | 13 +++++++++---- net/bluetooth/rfcomm/sock.c | 6 ++---- net/bluetooth/rfcomm/tty.c | 9 ++++++--- net/bluetooth/sco.c | 10 ++-------- 10 files changed, 50 insertions(+), 42 deletions(-) diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 54996f2b7573..dfd1e73e611a 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -535,6 +535,7 @@ int __init hci_uart_init(void) hci_uart_ldisc.receive_room= hci_uart_tty_room; hci_uart_ldisc.receive_buf = hci_uart_tty_receive; hci_uart_ldisc.write_wakeup= hci_uart_tty_wakeup; + hci_uart_ldisc.owner = THIS_MODULE; if ((err = tty_register_ldisc(N_HCI, &hci_uart_ldisc))) { BT_ERR("HCI line discipline registration failed. (%d)", err); diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index cd9ab609d354..4b78aeb4398a 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -235,4 +235,6 @@ struct l2cap_pinfo { #define CONF_INPUT_DONE 0x02 #define CONF_OUTPUT_DONE 0x04 +void l2cap_load(void); + #endif /* __L2CAP_H */ diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 991a0fd7b23b..4f7b19226a30 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -92,6 +92,8 @@ int bt_sock_unregister(int proto) static int bt_sock_create(struct socket *sock, int proto) { + int err = 0; + if (proto >= BT_MAX_PROTO) return -EINVAL; @@ -102,11 +104,12 @@ static int bt_sock_create(struct socket *sock, int proto) request_module(module_name); } #endif - - if (!bt_proto[proto]) - return -ENOENT; - - return bt_proto[proto]->create(sock, proto); + err = -EPROTONOSUPPORT; + if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) { + err = bt_proto[proto]->create(sock, proto); + module_put(bt_proto[proto]->owner); + } + return err; } struct sock *bt_sock_alloc(struct socket *sock, int proto, int pi_size, int prio) diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index ff3fea9cc4ce..c2e49a273b4b 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -85,14 +85,17 @@ static struct bnep_session *__bnep_get_session(u8 *dst) static void __bnep_link_session(struct bnep_session *s) { - MOD_INC_USE_COUNT; + /* It's safe to call __module_get() here because sessions are added + by the socket layer which has to hold the refference to this module. + */ + __module_get(THIS_MODULE); list_add(&s->list, &bnep_session_list); } static void __bnep_unlink_session(struct bnep_session *s) { list_del(&s->list); - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); } static int bnep_send(struct bnep_session *s, void *data, size_t len) @@ -677,7 +680,9 @@ int bnep_get_conninfo(struct bnep_conninfo *ci) static int __init bnep_init_module(void) { - char flt[50] = ""; + char flt[50] = ""; + + l2cap_load(); #ifdef CONFIG_BT_BNEP_PROTO_FILTER strcat(flt, "protocol "); diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 60d22f5e5820..609fe3da8d4d 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c @@ -67,8 +67,6 @@ static int bnep_sock_release(struct socket *sock) sock_orphan(sk); sock_put(sk); - - MOD_DEC_USE_COUNT; return 0; } @@ -179,13 +177,10 @@ static int bnep_sock_create(struct socket *sock, int protocol) return -ENOMEM; sock->ops = &bnep_sock_ops; - MOD_INC_USE_COUNT; - - sock->state = SS_UNCONNECTED; + sock->state = SS_UNCONNECTED; sk->destruct = NULL; sk->protocol = protocol; - return 0; } diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index fe811355a735..2316732431d1 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -145,8 +145,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) conn->chan_list.lock = RW_LOCK_UNLOCKED; BT_DBG("hcon %p conn %p", hcon, conn); - - MOD_INC_USE_COUNT; return conn; } @@ -173,8 +171,6 @@ static int l2cap_conn_del(struct hci_conn *hcon, int err) hcon->l2cap_data = NULL; kfree(conn); - - MOD_DEC_USE_COUNT; return 0; } @@ -242,8 +238,6 @@ static void l2cap_sock_destruct(struct sock *sk) if (sk->protinfo) kfree(sk->protinfo); - - MOD_DEC_USE_COUNT; } static void l2cap_sock_cleanup_listen(struct sock *parent) @@ -356,6 +350,8 @@ static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio) if (!sk) return NULL; + sk_set_owner(sk, THIS_MODULE); + sk->destruct = l2cap_sock_destruct; sk->sndtimeo = L2CAP_CONN_TIMEOUT; @@ -365,8 +361,6 @@ static struct sock *l2cap_sock_alloc(struct socket *sock, int proto, int prio) l2cap_sock_init_timer(sk); bt_sock_link(&l2cap_sk_list, sk); - - MOD_INC_USE_COUNT; return sk; } @@ -2133,7 +2127,6 @@ int __init l2cap_init(void) return err; } - l2cap_proc_init(); BT_INFO("L2CAP ver %s", VERSION); @@ -2154,6 +2147,15 @@ void __exit l2cap_cleanup(void) BT_ERR("L2CAP protocol unregistration failed"); } +void l2cap_load(void) +{ + /* Dummy function to trigger automatic L2CAP module loading by + other modules that use L2CAP sockets but don not use any other + symbols from it. */ + return; +} +EXPORT_SYMBOL(l2cap_load); + module_init(l2cap_init); module_exit(l2cap_cleanup); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index c193d77b6e57..5052460f946f 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -52,7 +52,7 @@ #include #include -#define VERSION "0.3" +#define VERSION "1.0" #ifndef CONFIG_BT_RFCOMM_DEBUG #undef BT_DBG @@ -481,9 +481,12 @@ struct rfcomm_session *rfcomm_session_add(struct socket *sock, int state) list_add(&s->list, &session_list); /* Do not increment module usage count for listeting sessions. - * Otherwise we won't be able to unload the module. */ + * Otherwise we won't be able to unload the module. + * Non listening session are added either by a socket or a TTYs + * which means that we already hold refcount to this module. + */ if (state != BT_LISTEN) - MOD_INC_USE_COUNT; + __module_get(THIS_MODULE); return s; } @@ -502,7 +505,7 @@ void rfcomm_session_del(struct rfcomm_session *s) kfree(s); if (state != BT_LISTEN) - MOD_DEC_USE_COUNT; + module_put(THIS_MODULE); } struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) @@ -1868,6 +1871,8 @@ static void __exit rfcomm_proc_cleanup(void) /* ---- Initialization ---- */ int __init rfcomm_init(void) { + l2cap_load(); + kernel_thread(rfcomm_run, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND); BT_INFO("RFCOMM ver %s", VERSION); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 81bdda3ce9bd..827a0d936e59 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -182,8 +182,6 @@ static void rfcomm_sock_destruct(struct sock *sk) if (sk->protinfo) kfree(sk->protinfo); - - MOD_DEC_USE_COUNT; } static void rfcomm_sock_cleanup_listen(struct sock *parent) @@ -265,6 +263,8 @@ static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio) if (!sk) return NULL; + sk_set_owner(sk, THIS_MODULE); + d = rfcomm_dlc_alloc(prio); if (!d) { sk_free(sk); @@ -288,8 +288,6 @@ static struct sock *rfcomm_sock_alloc(struct socket *sock, int proto, int prio) bt_sock_link(&rfcomm_sk_list, sk); BT_DBG("sk %p", sk); - - MOD_INC_USE_COUNT; return sk; } diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 85a6f3983ae3..99e947050ea9 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -99,7 +99,9 @@ static void rfcomm_dev_destruct(struct rfcomm_dev *dev) rfcomm_dlc_put(dlc); kfree(dev); - MOD_DEC_USE_COUNT; + /* It's safe to call module_put() here because socket still + holds refference to this module. */ + module_put(THIS_MODULE); } static inline void rfcomm_dev_hold(struct rfcomm_dev *dev) @@ -211,8 +213,9 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) dev->dlc = dlc; rfcomm_dlc_unlock(dlc); - MOD_INC_USE_COUNT; - + /* It's safe to call __module_get() here because socket already + holds refference to this module. */ + __module_get(THIS_MODULE); out: write_unlock_bh(&rfcomm_dev_lock); diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 02ac269362f1..31dfe0b2384d 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -145,8 +145,6 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon, __u8 status) conn->mtu = 60; BT_DBG("hcon %p conn %p", hcon, conn); - - MOD_INC_USE_COUNT; return conn; } @@ -180,8 +178,6 @@ static int sco_conn_del(struct hci_conn *hcon, int err) hcon->sco_data = NULL; kfree(conn); - - MOD_DEC_USE_COUNT; return 0; } @@ -347,8 +343,6 @@ static void sco_sock_destruct(struct sock *sk) if (sk->protinfo) kfree(sk->protinfo); - - MOD_DEC_USE_COUNT; } static void sco_sock_cleanup_listen(struct sock *parent) @@ -434,6 +428,8 @@ static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio) if (!sk) return NULL; + sk_set_owner(sk, THIS_MODULE); + sk->destruct = sco_sock_destruct; sk->sndtimeo = SCO_CONN_TIMEOUT; sk->state = BT_OPEN; @@ -441,8 +437,6 @@ static struct sock *sco_sock_alloc(struct socket *sock, int proto, int prio) sco_sock_init_timer(sk); bt_sock_link(&sco_sk_list, sk); - - MOD_INC_USE_COUNT; return sk; } -- cgit v1.2.3 From cb75e1ffff54fec2ebe9a13ea4a9d1fe28360761 Mon Sep 17 00:00:00 2001 From: Maksim Krasnyanskiy Date: Thu, 8 May 2003 22:01:26 -0700 Subject: [Bluetooth] L2CAP config req/rsp fixes. We have to set continuation flag in config rsp if it was set in req. --- include/net/bluetooth/l2cap.h | 6 +++--- net/bluetooth/l2cap.c | 19 +++++++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 4b78aeb4398a..3758bc57d7b8 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -231,9 +231,9 @@ struct l2cap_pinfo { struct sock *prev_c; }; -#define CONF_REQ_SENT 0x01 -#define CONF_INPUT_DONE 0x02 -#define CONF_OUTPUT_DONE 0x04 +#define L2CAP_CONF_REQ_SENT 0x01 +#define L2CAP_CONF_INPUT_DONE 0x02 +#define L2CAP_CONF_OUTPUT_DONE 0x04 void l2cap_load(void); diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index 2316732431d1..dbef19fa5cbc 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1313,15 +1313,18 @@ static int l2cap_build_conf_rsp(struct sock *sk, void *data, int *result) { struct l2cap_conf_rsp *rsp = data; void *ptr = rsp->data; + u16 flags = 0; BT_DBG("sk %p complete %d", sk, result ? 1 : 0); if (result) *result = l2cap_conf_output(sk, &ptr); + else + flags = 0x0001; rsp->scid = __cpu_to_le16(l2cap_pi(sk)->dcid); rsp->result = __cpu_to_le16(result ? *result : 0); - rsp->flags = __cpu_to_le16(0); + rsp->flags = __cpu_to_le16(flags); return ptr - data; } @@ -1434,7 +1437,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd case L2CAP_CR_SUCCESS: sk->state = BT_CONFIG; l2cap_pi(sk)->dcid = dcid; - l2cap_pi(sk)->conf_state |= CONF_REQ_SENT; + l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT; l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req); break; @@ -1469,7 +1472,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr l2cap_parse_conf_req(sk, req->data, cmd->len - sizeof(*req)); - if (flags & 0x01) { + if (flags & 0x0001) { /* Incomplete config. Send empty response. */ l2cap_send_rsp(conn, cmd->ident, L2CAP_CONF_RSP, l2cap_build_conf_rsp(sk, rsp, NULL), rsp); goto unlock; @@ -1482,12 +1485,12 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr goto unlock; /* Output config done */ - l2cap_pi(sk)->conf_state |= CONF_OUTPUT_DONE; + l2cap_pi(sk)->conf_state |= L2CAP_CONF_OUTPUT_DONE; - if (l2cap_pi(sk)->conf_state & CONF_INPUT_DONE) { + if (l2cap_pi(sk)->conf_state & L2CAP_CONF_INPUT_DONE) { sk->state = BT_CONNECTED; l2cap_chan_ready(sk); - } else if (!(l2cap_pi(sk)->conf_state & CONF_REQ_SENT)) { + } else if (!(l2cap_pi(sk)->conf_state & L2CAP_CONF_REQ_SENT)) { u8 req[64]; l2cap_send_req(conn, L2CAP_CONF_REQ, l2cap_build_conf_req(sk, req), req); } @@ -1532,9 +1535,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr goto done; /* Input config done */ - l2cap_pi(sk)->conf_state |= CONF_INPUT_DONE; + l2cap_pi(sk)->conf_state |= L2CAP_CONF_INPUT_DONE; - if (l2cap_pi(sk)->conf_state & CONF_OUTPUT_DONE) { + if (l2cap_pi(sk)->conf_state & L2CAP_CONF_OUTPUT_DONE) { sk->state = BT_CONNECTED; l2cap_chan_ready(sk); } -- cgit v1.2.3 From 318ce727e708f608c84f50b64c4bd8e35d393415 Mon Sep 17 00:00:00 2001 From: Maksim Krasnyanskiy Date: Fri, 9 May 2003 02:47:56 -0700 Subject: [Bluetooth] Detect and log error condition when first L2CAP fragment is too long. --- net/bluetooth/l2cap.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index dbef19fa5cbc..dfbfbff07b64 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -1940,21 +1940,27 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl } if (skb->len < 2) { - BT_ERR("Frame is too small (len %d)", skb->len); + BT_ERR("Frame is too short (len %d)", skb->len); goto drop; } hdr = (struct l2cap_hdr *) skb->data; len = __le16_to_cpu(hdr->len) + L2CAP_HDR_SIZE; - BT_DBG("Start: total len %d, frag len %d", len, skb->len); - if (len == skb->len) { /* Complete frame received */ l2cap_recv_frame(conn, skb); return 0; } + BT_DBG("Start: total len %d, frag len %d", len, skb->len); + + if (skb->len > len) { + BT_ERR("Frame is too long (len %d, expected len %d)", + skb->len, len); + goto drop; + } + /* Allocate skb for the complete frame (with header) */ if (!(conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC))) goto drop; @@ -1970,7 +1976,7 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl } if (skb->len > conn->rx_len) { - BT_ERR("Fragment is too large (len %d, expect %d)", + BT_ERR("Fragment is too long (len %d, expected %d)", skb->len, conn->rx_len); kfree_skb(conn->rx_skb); conn->rx_skb = NULL; -- cgit v1.2.3 From 0247c40ab512d9706fea20df2bd35b851c44aa67 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 9 May 2003 23:57:20 +0200 Subject: [Bluetooth] Send the correct values in RPN response This patch fixes a bug in rfcomm_recv_rpn(), which do not set the correct values for xon_char, xoff_char and flow_ctrl. --- net/bluetooth/rfcomm/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 5795735a4f08..4f544b80a1d4 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1229,21 +1229,21 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_ if (rpn->param_mask & RFCOMM_RPN_PM_FLOW) { if (rpn->flow_ctrl != RFCOMM_RPN_FLOW_NONE) { BT_DBG("RPN flow ctrl mismatch 0x%x", rpn->flow_ctrl); - rpn->flow_ctrl = RFCOMM_RPN_FLOW_NONE; + flow_ctrl = RFCOMM_RPN_FLOW_NONE; rpn_mask ^= RFCOMM_RPN_PM_FLOW; } } if (rpn->param_mask & RFCOMM_RPN_PM_XON) { if (rpn->xon_char != RFCOMM_RPN_XON_CHAR) { BT_DBG("RPN XON char mismatch 0x%x", rpn->xon_char); - rpn->xon_char = RFCOMM_RPN_XON_CHAR; + xon_char = RFCOMM_RPN_XON_CHAR; rpn_mask ^= RFCOMM_RPN_PM_XON; } } if (rpn->param_mask & RFCOMM_RPN_PM_XOFF) { if (rpn->xoff_char != RFCOMM_RPN_XOFF_CHAR) { BT_DBG("RPN XOFF char mismatch 0x%x", rpn->xoff_char); - rpn->xoff_char = RFCOMM_RPN_XOFF_CHAR; + xoff_char = RFCOMM_RPN_XOFF_CHAR; rpn_mask ^= RFCOMM_RPN_PM_XOFF; } } -- cgit v1.2.3 From 761cb06c11e126ac626256d5621462a8f64a2521 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 9 May 2003 23:58:47 +0200 Subject: [Bluetooth] Handle priority bits in parameter negotiation The PN response have to return the same value for the priority bits as in the request. The priority value is now also stored in the rfcomm_dlc structure and the default value is 7. --- include/net/bluetooth/rfcomm.h | 1 + net/bluetooth/rfcomm/core.c | 23 ++++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 3393e95c7e0f..2b32b43cd0a8 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -185,6 +185,7 @@ struct rfcomm_dlc { atomic_t refcnt; u8 dlci; u8 addr; + u8 priority; uint mtu; u8 v24_sig; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 4f544b80a1d4..68a0f50f217f 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -304,10 +304,11 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, rfcomm_dlc_clear_state(d); - d->dlci = dlci; - d->addr = __addr(s->initiator, dlci); + d->dlci = dlci; + d->addr = __addr(s->initiator, dlci); + d->priority = 7; - d->state = BT_CONFIG; + d->state = BT_CONFIG; rfcomm_dlc_link(s, d); d->mtu = s->mtu; @@ -741,7 +742,7 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d pn = (void *) ptr; ptr += sizeof(*pn); pn->dlci = d->dlci; - pn->priority = 0; + pn->priority = d->priority; pn->ack_timer = 0; pn->max_retrans = 0; @@ -1099,8 +1100,6 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) set_bit(RFCOMM_TX_THROTTLED, &d->flags); d->credits = 0; } - - d->mtu = btohs(pn->mtu); } else { if (pn->flow_ctrl == 0xe0) { d->tx_credits = pn->credits; @@ -1108,10 +1107,12 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) set_bit(RFCOMM_TX_THROTTLED, &d->flags); d->credits = 0; } - - d->mtu = btohs(pn->mtu); } + d->priority = pn->priority; + + d->mtu = btohs(pn->mtu); + return 0; } @@ -1137,7 +1138,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb) switch (d->state) { case BT_CONFIG: rfcomm_apply_pn(d, cr, pn); - + d->state = BT_CONNECT; rfcomm_send_sabm(s, d->dlci); break; @@ -1148,7 +1149,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb) if (!cr) return 0; - + /* PN request for non existing DLC. * Assume incomming connection. */ if (rfcomm_connect_ind(s, channel, &d)) { @@ -1157,7 +1158,7 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb) rfcomm_dlc_link(s, d); rfcomm_apply_pn(d, cr, pn); - + d->state = BT_OPEN; rfcomm_send_pn(s, 0, d); } else { -- cgit v1.2.3 From 1a6fe614e48085db50b1fb2701eeb922453a40ff Mon Sep 17 00:00:00 2001 From: Maksim Krasnyanskiy Date: Fri, 9 May 2003 07:43:10 -0700 Subject: [Bluetooth] RFCOMM must wait for MSC exchange to complete before sending data. --- include/net/bluetooth/rfcomm.h | 9 +++++++-- net/bluetooth/rfcomm/core.c | 16 +++++++++++----- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index cbe41e680019..c2a2098b4369 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -186,10 +186,10 @@ struct rfcomm_dlc { u8 dlci; u8 addr; u8 priority; - - uint mtu; u8 v24_sig; + u8 mscex; + uint mtu; uint credits; uint rx_credits; uint tx_credits; @@ -214,6 +214,11 @@ struct rfcomm_dlc { #define RFCOMM_SCHED_TIMEO 3 #define RFCOMM_SCHED_WAKEUP 31 +/* MSC exchange flags */ +#define RFCOMM_MSCEX_TX 1 +#define RFCOMM_MSCEX_RX 2 +#define RFCOMM_MSCEX_OK (RFCOMM_MSCEX_TX + RFCOMM_MSCEX_RX) + extern struct task_struct *rfcomm_thread; extern unsigned long rfcomm_event; diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 112c46a9060c..7496f445463d 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -203,6 +203,7 @@ static void rfcomm_dlc_clear_state(struct rfcomm_dlc *d) d->state = BT_OPEN; d->flags = 0; + d->mscex = 0; d->mtu = RFCOMM_DEFAULT_MTU; d->v24_sig = RFCOMM_V24_RTC | RFCOMM_V24_RTR | RFCOMM_V24_DV; @@ -1288,11 +1289,11 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig); - if (!cr) + d = rfcomm_dlc_get(s, dlci); + if (!d) return 0; - d = rfcomm_dlc_get(s, dlci); - if (d) { + if (cr) { if (msc->v24_sig & RFCOMM_V24_FC && !d->credits) set_bit(RFCOMM_TX_THROTTLED, &d->flags); else @@ -1304,7 +1305,11 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb rfcomm_dlc_unlock(d); rfcomm_send_msc(s, 0, dlci, msc->v24_sig); - } + + d->mscex |= RFCOMM_MSCEX_RX; + } else + d->mscex |= RFCOMM_MSCEX_TX; + return 0; } @@ -1528,7 +1533,8 @@ static inline void rfcomm_process_dlcs(struct rfcomm_session *s) continue; } - if (d->state == BT_CONNECTED || d->state == BT_DISCONN) + if ((d->state == BT_CONNECTED || d->state == BT_DISCONN) && + d->mscex == RFCOMM_MSCEX_OK) rfcomm_process_tx(d); } } -- cgit v1.2.3