Commit c30ae138 authored by John W. Linville's avatar John W. Linville
parents 78b85956 be21871f
...@@ -35,6 +35,10 @@ ...@@ -35,6 +35,10 @@
static struct usb_device_id ath3k_table[] = { static struct usb_device_id ath3k_table[] = {
/* Atheros AR3011 */ /* Atheros AR3011 */
{ USB_DEVICE(0x0CF3, 0x3000) }, { USB_DEVICE(0x0CF3, 0x3000) },
/* Atheros AR3011 with sflash firmware*/
{ USB_DEVICE(0x0CF3, 0x3002) },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
......
...@@ -99,6 +99,9 @@ static struct usb_device_id blacklist_table[] = { ...@@ -99,6 +99,9 @@ static struct usb_device_id blacklist_table[] = {
/* Broadcom BCM2033 without firmware */ /* Broadcom BCM2033 without firmware */
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
/* Atheros 3011 with sflash firmware */
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
/* Broadcom BCM2035 */ /* Broadcom BCM2035 */
{ USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
{ USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU },
...@@ -239,6 +242,7 @@ static void btusb_intr_complete(struct urb *urb) ...@@ -239,6 +242,7 @@ static void btusb_intr_complete(struct urb *urb)
err = usb_submit_urb(urb, GFP_ATOMIC); err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) { if (err < 0) {
if (err != -EPERM)
BT_ERR("%s urb %p failed to resubmit (%d)", BT_ERR("%s urb %p failed to resubmit (%d)",
hdev->name, urb, -err); hdev->name, urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
...@@ -323,6 +327,7 @@ static void btusb_bulk_complete(struct urb *urb) ...@@ -323,6 +327,7 @@ static void btusb_bulk_complete(struct urb *urb)
err = usb_submit_urb(urb, GFP_ATOMIC); err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) { if (err < 0) {
if (err != -EPERM)
BT_ERR("%s urb %p failed to resubmit (%d)", BT_ERR("%s urb %p failed to resubmit (%d)",
hdev->name, urb, -err); hdev->name, urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
...@@ -412,6 +417,7 @@ static void btusb_isoc_complete(struct urb *urb) ...@@ -412,6 +417,7 @@ static void btusb_isoc_complete(struct urb *urb)
err = usb_submit_urb(urb, GFP_ATOMIC); err = usb_submit_urb(urb, GFP_ATOMIC);
if (err < 0) { if (err < 0) {
if (err != -EPERM)
BT_ERR("%s urb %p failed to resubmit (%d)", BT_ERR("%s urb %p failed to resubmit (%d)",
hdev->name, urb, -err); hdev->name, urb, -err);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
......
...@@ -215,8 +215,8 @@ extern rwlock_t hci_dev_list_lock; ...@@ -215,8 +215,8 @@ extern rwlock_t hci_dev_list_lock;
extern rwlock_t hci_cb_list_lock; extern rwlock_t hci_cb_list_lock;
/* ----- Inquiry cache ----- */ /* ----- Inquiry cache ----- */
#define INQUIRY_CACHE_AGE_MAX (HZ*30) // 30 seconds #define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */
#define INQUIRY_ENTRY_AGE_MAX (HZ*60) // 60 seconds #define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */
#define inquiry_cache_lock(c) spin_lock(&c->lock) #define inquiry_cache_lock(c) spin_lock(&c->lock)
#define inquiry_cache_unlock(c) spin_unlock(&c->lock) #define inquiry_cache_unlock(c) spin_unlock(&c->lock)
......
...@@ -417,11 +417,11 @@ static inline int l2cap_tx_window_full(struct sock *sk) ...@@ -417,11 +417,11 @@ static inline int l2cap_tx_window_full(struct sock *sk)
return sub == pi->remote_tx_win; return sub == pi->remote_tx_win;
} }
#define __get_txseq(ctrl) ((ctrl) & L2CAP_CTRL_TXSEQ) >> 1 #define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1)
#define __get_reqseq(ctrl) ((ctrl) & L2CAP_CTRL_REQSEQ) >> 8 #define __get_reqseq(ctrl) (((ctrl) & L2CAP_CTRL_REQSEQ) >> 8)
#define __is_iframe(ctrl) !((ctrl) & L2CAP_CTRL_FRAME_TYPE) #define __is_iframe(ctrl) (!((ctrl) & L2CAP_CTRL_FRAME_TYPE))
#define __is_sframe(ctrl) (ctrl) & L2CAP_CTRL_FRAME_TYPE #define __is_sframe(ctrl) ((ctrl) & L2CAP_CTRL_FRAME_TYPE)
#define __is_sar_start(ctrl) ((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
void l2cap_load(void); void l2cap_load(void);
......
/* /*
RFCOMM implementation for Linux Bluetooth stack (BlueZ). RFCOMM implementation for Linux Bluetooth stack (BlueZ)
Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com> Copyright (C) 2002 Maxim Krasnyansky <maxk@qualcomm.com>
Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org> Copyright (C) 2002 Marcel Holtmann <marcel@holtmann.org>
...@@ -105,7 +105,7 @@ ...@@ -105,7 +105,7 @@
struct rfcomm_hdr { struct rfcomm_hdr {
u8 addr; u8 addr;
u8 ctrl; u8 ctrl;
u8 len; // Actual size can be 2 bytes u8 len; /* Actual size can be 2 bytes */
} __packed; } __packed;
struct rfcomm_cmd { struct rfcomm_cmd {
......
...@@ -648,6 +648,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) ...@@ -648,6 +648,7 @@ int bnep_del_connection(struct bnep_conndel_req *req)
static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s) static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
{ {
memset(ci, 0, sizeof(*ci));
memcpy(ci->dst, s->eh.h_source, ETH_ALEN); memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
strcpy(ci->device, s->dev->name); strcpy(ci->device, s->dev->name);
ci->flags = s->flags; ci->flags = s->flags;
......
...@@ -78,6 +78,7 @@ static void __cmtp_unlink_session(struct cmtp_session *session) ...@@ -78,6 +78,7 @@ static void __cmtp_unlink_session(struct cmtp_session *session)
static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci) static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci)
{ {
memset(ci, 0, sizeof(*ci));
bacpy(&ci->bdaddr, &session->bdaddr); bacpy(&ci->bdaddr, &session->bdaddr);
ci->flags = session->flags; ci->flags = session->flags;
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include <net/sock.h> #include <net/sock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -66,7 +66,8 @@ void hci_acl_connect(struct hci_conn *conn) ...@@ -66,7 +66,8 @@ void hci_acl_connect(struct hci_conn *conn)
bacpy(&cp.bdaddr, &conn->dst); bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x02; cp.pscan_rep_mode = 0x02;
if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
if (ie) {
if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) { if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) {
cp.pscan_rep_mode = ie->data.pscan_rep_mode; cp.pscan_rep_mode = ie->data.pscan_rep_mode;
cp.pscan_mode = ie->data.pscan_mode; cp.pscan_mode = ie->data.pscan_mode;
...@@ -368,8 +369,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 ...@@ -368,8 +369,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
BT_DBG("%s dst %s", hdev->name, batostr(dst)); BT_DBG("%s dst %s", hdev->name, batostr(dst));
if (!(acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst))) { acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
if (!(acl = hci_conn_add(hdev, ACL_LINK, dst))) if (!acl) {
acl = hci_conn_add(hdev, ACL_LINK, dst);
if (!acl)
return NULL; return NULL;
} }
...@@ -389,8 +392,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 ...@@ -389,8 +392,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
if (type == ACL_LINK) if (type == ACL_LINK)
return acl; return acl;
if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) { sco = hci_conn_hash_lookup_ba(hdev, type, dst);
if (!(sco = hci_conn_add(hdev, type, dst))) { if (!sco) {
sco = hci_conn_add(hdev, type, dst);
if (!sco) {
hci_conn_put(acl); hci_conn_put(acl);
return NULL; return NULL;
} }
...@@ -647,10 +652,12 @@ int hci_get_conn_list(void __user *arg) ...@@ -647,10 +652,12 @@ int hci_get_conn_list(void __user *arg)
size = sizeof(req) + req.conn_num * sizeof(*ci); size = sizeof(req) + req.conn_num * sizeof(*ci);
if (!(cl = kmalloc(size, GFP_KERNEL))) cl = kmalloc(size, GFP_KERNEL);
if (!cl)
return -ENOMEM; return -ENOMEM;
if (!(hdev = hci_dev_get(req.dev_id))) { hdev = hci_dev_get(req.dev_id);
if (!hdev) {
kfree(cl); kfree(cl);
return -ENODEV; return -ENODEV;
} }
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include <net/sock.h> #include <net/sock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -349,20 +349,23 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *b ...@@ -349,20 +349,23 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *b
void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data) void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data)
{ {
struct inquiry_cache *cache = &hdev->inq_cache; struct inquiry_cache *cache = &hdev->inq_cache;
struct inquiry_entry *e; struct inquiry_entry *ie;
BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr)); BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr));
if (!(e = hci_inquiry_cache_lookup(hdev, &data->bdaddr))) { ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr);
if (!ie) {
/* Entry not in the cache. Add new one. */ /* Entry not in the cache. Add new one. */
if (!(e = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC))) ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC);
if (!ie)
return; return;
e->next = cache->list;
cache->list = e; ie->next = cache->list;
cache->list = ie;
} }
memcpy(&e->data, data, sizeof(*data)); memcpy(&ie->data, data, sizeof(*data));
e->timestamp = jiffies; ie->timestamp = jiffies;
cache->timestamp = jiffies; cache->timestamp = jiffies;
} }
...@@ -430,8 +433,12 @@ int hci_inquiry(void __user *arg) ...@@ -430,8 +433,12 @@ int hci_inquiry(void __user *arg)
hci_dev_unlock_bh(hdev); hci_dev_unlock_bh(hdev);
timeo = ir.length * msecs_to_jiffies(2000); timeo = ir.length * msecs_to_jiffies(2000);
if (do_inquiry && (err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo)) < 0)
if (do_inquiry) {
err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo);
if (err < 0)
goto done; goto done;
}
/* for unlimited number of responses we will use buffer with 255 entries */ /* for unlimited number of responses we will use buffer with 255 entries */
max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp; max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp;
...@@ -439,7 +446,8 @@ int hci_inquiry(void __user *arg) ...@@ -439,7 +446,8 @@ int hci_inquiry(void __user *arg)
/* cache_dump can't sleep. Therefore we allocate temp buffer and then /* cache_dump can't sleep. Therefore we allocate temp buffer and then
* copy it to the user space. * copy it to the user space.
*/ */
if (!(buf = kmalloc(sizeof(struct inquiry_info) * max_rsp, GFP_KERNEL))) { buf = kmalloc(sizeof(struct inquiry_info) *max_rsp, GFP_KERNEL);
if (!buf) {
err = -ENOMEM; err = -ENOMEM;
goto done; goto done;
} }
...@@ -611,7 +619,8 @@ int hci_dev_close(__u16 dev) ...@@ -611,7 +619,8 @@ int hci_dev_close(__u16 dev)
struct hci_dev *hdev; struct hci_dev *hdev;
int err; int err;
if (!(hdev = hci_dev_get(dev))) hdev = hci_dev_get(dev);
if (!hdev)
return -ENODEV; return -ENODEV;
err = hci_dev_do_close(hdev); err = hci_dev_do_close(hdev);
hci_dev_put(hdev); hci_dev_put(hdev);
...@@ -623,7 +632,8 @@ int hci_dev_reset(__u16 dev) ...@@ -623,7 +632,8 @@ int hci_dev_reset(__u16 dev)
struct hci_dev *hdev; struct hci_dev *hdev;
int ret = 0; int ret = 0;
if (!(hdev = hci_dev_get(dev))) hdev = hci_dev_get(dev);
if (!hdev)
return -ENODEV; return -ENODEV;
hci_req_lock(hdev); hci_req_lock(hdev);
...@@ -663,7 +673,8 @@ int hci_dev_reset_stat(__u16 dev) ...@@ -663,7 +673,8 @@ int hci_dev_reset_stat(__u16 dev)
struct hci_dev *hdev; struct hci_dev *hdev;
int ret = 0; int ret = 0;
if (!(hdev = hci_dev_get(dev))) hdev = hci_dev_get(dev);
if (!hdev)
return -ENODEV; return -ENODEV;
memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
...@@ -682,7 +693,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) ...@@ -682,7 +693,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
if (copy_from_user(&dr, arg, sizeof(dr))) if (copy_from_user(&dr, arg, sizeof(dr)))
return -EFAULT; return -EFAULT;
if (!(hdev = hci_dev_get(dr.dev_id))) hdev = hci_dev_get(dr.dev_id);
if (!hdev)
return -ENODEV; return -ENODEV;
switch (cmd) { switch (cmd) {
...@@ -763,7 +775,8 @@ int hci_get_dev_list(void __user *arg) ...@@ -763,7 +775,8 @@ int hci_get_dev_list(void __user *arg)
size = sizeof(*dl) + dev_num * sizeof(*dr); size = sizeof(*dl) + dev_num * sizeof(*dr);
if (!(dl = kzalloc(size, GFP_KERNEL))) dl = kzalloc(size, GFP_KERNEL);
if (!dl)
return -ENOMEM; return -ENOMEM;
dr = dl->dev_req; dr = dl->dev_req;
...@@ -797,7 +810,8 @@ int hci_get_dev_info(void __user *arg) ...@@ -797,7 +810,8 @@ int hci_get_dev_info(void __user *arg)
if (copy_from_user(&di, arg, sizeof(di))) if (copy_from_user(&di, arg, sizeof(di)))
return -EFAULT; return -EFAULT;
if (!(hdev = hci_dev_get(di.dev_id))) hdev = hci_dev_get(di.dev_id);
if (!hdev)
return -ENODEV; return -ENODEV;
strcpy(di.name, hdev->name); strcpy(di.name, hdev->name);
...@@ -905,7 +919,7 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -905,7 +919,7 @@ int hci_register_dev(struct hci_dev *hdev)
hdev->sniff_max_interval = 800; hdev->sniff_max_interval = 800;
hdev->sniff_min_interval = 80; hdev->sniff_min_interval = 80;
tasklet_init(&hdev->cmd_task, hci_cmd_task,(unsigned long) hdev); tasklet_init(&hdev->cmd_task, hci_cmd_task, (unsigned long) hdev);
tasklet_init(&hdev->rx_task, hci_rx_task, (unsigned long) hdev); tasklet_init(&hdev->rx_task, hci_rx_task, (unsigned long) hdev);
tasklet_init(&hdev->tx_task, hci_tx_task, (unsigned long) hdev); tasklet_init(&hdev->tx_task, hci_tx_task, (unsigned long) hdev);
...@@ -1368,7 +1382,8 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) ...@@ -1368,7 +1382,8 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags)
bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
hci_add_acl_hdr(skb, conn->handle, flags | ACL_START); hci_add_acl_hdr(skb, conn->handle, flags | ACL_START);
if (!(list = skb_shinfo(skb)->frag_list)) { list = skb_shinfo(skb)->frag_list;
if (!list) {
/* Non fragmented */ /* Non fragmented */
BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len); BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len);
...@@ -1609,7 +1624,8 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1609,7 +1624,8 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb)
hci_conn_enter_active_mode(conn); hci_conn_enter_active_mode(conn);
/* Send to upper protocol */ /* Send to upper protocol */
if ((hp = hci_proto[HCI_PROTO_L2CAP]) && hp->recv_acldata) { hp = hci_proto[HCI_PROTO_L2CAP];
if (hp && hp->recv_acldata) {
hp->recv_acldata(conn, skb, flags); hp->recv_acldata(conn, skb, flags);
return; return;
} }
...@@ -1644,7 +1660,8 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1644,7 +1660,8 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
register struct hci_proto *hp; register struct hci_proto *hp;
/* Send to upper protocol */ /* Send to upper protocol */
if ((hp = hci_proto[HCI_PROTO_SCO]) && hp->recv_scodata) { hp = hci_proto[HCI_PROTO_SCO];
if (hp && hp->recv_scodata) {
hp->recv_scodata(conn, skb); hp->recv_scodata(conn, skb);
return; return;
} }
...@@ -1727,7 +1744,8 @@ static void hci_cmd_task(unsigned long arg) ...@@ -1727,7 +1744,8 @@ static void hci_cmd_task(unsigned long arg)
if (atomic_read(&hdev->cmd_cnt) && (skb = skb_dequeue(&hdev->cmd_q))) { if (atomic_read(&hdev->cmd_cnt) && (skb = skb_dequeue(&hdev->cmd_q))) {
kfree_skb(hdev->sent_cmd); kfree_skb(hdev->sent_cmd);
if ((hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC))) { hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC);
if (hdev->sent_cmd) {
atomic_dec(&hdev->cmd_cnt); atomic_dec(&hdev->cmd_cnt);
hci_send_frame(skb); hci_send_frame(skb);
hdev->cmd_last_tx = jiffies; hdev->cmd_last_tx = jiffies;
......
...@@ -39,7 +39,7 @@ ...@@ -39,7 +39,7 @@
#include <net/sock.h> #include <net/sock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -677,9 +677,50 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) ...@@ -677,9 +677,50 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
static int hci_outgoing_auth_needed(struct hci_dev *hdev,
struct hci_conn *conn)
{
if (conn->state != BT_CONFIG || !conn->out)
return 0;
if (conn->sec_level == BT_SECURITY_SDP)
return 0;
/* Only request authentication for SSP connections or non-SSP
* devices with sec_level HIGH */
if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) &&
conn->sec_level != BT_SECURITY_HIGH)
return 0;
return 1;
}
static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
{ {
struct hci_cp_remote_name_req *cp;
struct hci_conn *conn;
BT_DBG("%s status 0x%x", hdev->name, status); BT_DBG("%s status 0x%x", hdev->name, status);
/* If successful wait for the name req complete event before
* checking for the need to do authentication */
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (conn && hci_outgoing_auth_needed(hdev, conn)) {
struct hci_cp_auth_requested cp;
cp.handle = __cpu_to_le16(conn->handle);
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
}
hci_dev_unlock(hdev);
} }
static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
...@@ -955,12 +996,14 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk ...@@ -955,12 +996,14 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
hci_dev_lock(hdev); hci_dev_lock(hdev);
if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
if (ie)
memcpy(ie->data.dev_class, ev->dev_class, 3); memcpy(ie->data.dev_class, ev->dev_class, 3);
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
if (!conn) { if (!conn) {
if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr);
if (!conn) {
BT_ERR("No memory for new connection"); BT_ERR("No memory for new connection");
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return; return;
...@@ -1090,9 +1133,23 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s ...@@ -1090,9 +1133,23 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s
static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb)
{ {
struct hci_ev_remote_name *ev = (void *) skb->data;
struct hci_conn *conn;
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
hci_conn_check_pending(hdev); hci_conn_check_pending(hdev);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn && hci_outgoing_auth_needed(hdev, conn)) {
struct hci_cp_auth_requested cp;
cp.handle = __cpu_to_le16(conn->handle);
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
}
hci_dev_unlock(hdev);
} }
static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
...@@ -1162,33 +1219,39 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff ...@@ -1162,33 +1219,39 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
hci_dev_lock(hdev); hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) { if (!conn)
goto unlock;
if (!ev->status) if (!ev->status)
memcpy(conn->features, ev->features, 8); memcpy(conn->features, ev->features, 8);
if (conn->state == BT_CONFIG) { if (conn->state != BT_CONFIG)
if (!ev->status && lmp_ssp_capable(hdev) && goto unlock;
lmp_ssp_capable(conn)) {
if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
struct hci_cp_read_remote_ext_features cp; struct hci_cp_read_remote_ext_features cp;
cp.handle = ev->handle; cp.handle = ev->handle;
cp.page = 0x01; cp.page = 0x01;
hci_send_cmd(hdev, hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
HCI_OP_READ_REMOTE_EXT_FEATURES,
sizeof(cp), &cp); sizeof(cp), &cp);
} else if (!ev->status && conn->out && goto unlock;
conn->sec_level == BT_SECURITY_HIGH) { }
struct hci_cp_auth_requested cp;
cp.handle = ev->handle; if (!ev->status) {
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, struct hci_cp_remote_name_req cp;
sizeof(cp), &cp); memset(&cp, 0, sizeof(cp));
} else { bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x02;
hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
}
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED; conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status); hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn); hci_conn_put(conn);
} }
}
}
unlock:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
...@@ -1449,10 +1512,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s ...@@ -1449,10 +1512,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
conn->sent -= count; conn->sent -= count;
if (conn->type == ACL_LINK) { if (conn->type == ACL_LINK) {
if ((hdev->acl_cnt += count) > hdev->acl_pkts) hdev->acl_cnt += count;
if (hdev->acl_cnt > hdev->acl_pkts)
hdev->acl_cnt = hdev->acl_pkts; hdev->acl_cnt = hdev->acl_pkts;
} else { } else {
if ((hdev->sco_cnt += count) > hdev->sco_pkts) hdev->sco_cnt += count;
if (hdev->sco_cnt > hdev->sco_pkts)
hdev->sco_cnt = hdev->sco_pkts; hdev->sco_cnt = hdev->sco_pkts;
} }
} }
...@@ -1547,7 +1612,8 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk ...@@ -1547,7 +1612,8 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk
if (conn && !ev->status) { if (conn && !ev->status) {
struct inquiry_entry *ie; struct inquiry_entry *ie;
if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
if (ie) {
ie->data.clock_offset = ev->clock_offset; ie->data.clock_offset = ev->clock_offset;
ie->timestamp = jiffies; ie->timestamp = jiffies;
} }
...@@ -1581,7 +1647,8 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff * ...@@ -1581,7 +1647,8 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *
hci_dev_lock(hdev); hci_dev_lock(hdev);
if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) { ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
if (ie) {
ie->data.pscan_rep_mode = ev->pscan_rep_mode; ie->data.pscan_rep_mode = ev->pscan_rep_mode;
ie->timestamp = jiffies; ie->timestamp = jiffies;
} }
...@@ -1646,32 +1713,37 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b ...@@ -1646,32 +1713,37 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
hci_dev_lock(hdev); hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) { if (!conn)
goto unlock;
if (!ev->status && ev->page == 0x01) { if (!ev->status && ev->page == 0x01) {
struct inquiry_entry *ie; struct inquiry_entry *ie;
if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
if (ie)
ie->data.ssp_mode = (ev->features[0] & 0x01); ie->data.ssp_mode = (ev->features[0] & 0x01);
conn->ssp_mode = (ev->features[0] & 0x01); conn->ssp_mode = (ev->features[0] & 0x01);
} }
if (conn->state == BT_CONFIG) { if (conn->state != BT_CONFIG)
if (!ev->status && hdev->ssp_mode > 0 && goto unlock;
conn->ssp_mode > 0 && conn->out &&
conn->sec_level != BT_SECURITY_SDP) { if (!ev->status) {
struct hci_cp_auth_requested cp; struct hci_cp_remote_name_req cp;
cp.handle = ev->handle; memset(&cp, 0, sizeof(cp));
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, bacpy(&cp.bdaddr, &conn->dst);
sizeof(cp), &cp); cp.pscan_rep_mode = 0x02;
} else { hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
}
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED; conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status); hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn); hci_conn_put(conn);
} }
}
}
unlock:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
...@@ -1821,7 +1893,8 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_ ...@@ -1821,7 +1893,8 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_
hci_dev_lock(hdev); hci_dev_lock(hdev);
if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
if (ie)
ie->data.ssp_mode = (ev->features[0] & 0x01); ie->data.ssp_mode = (ev->features[0] & 0x01);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
#include <net/sock.h> #include <net/sock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -125,7 +125,8 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -125,7 +125,8 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
continue; continue;
} }
if (!(nskb = skb_clone(skb, GFP_ATOMIC))) nskb = skb_clone(skb, GFP_ATOMIC);
if (!nskb)
continue; continue;
/* Put type byte before the data */ /* Put type byte before the data */
...@@ -370,7 +371,8 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le ...@@ -370,7 +371,8 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le
} }
if (haddr->hci_dev != HCI_DEV_NONE) { if (haddr->hci_dev != HCI_DEV_NONE) {
if (!(hdev = hci_dev_get(haddr->hci_dev))) { hdev = hci_dev_get(haddr->hci_dev);
if (!hdev) {
err = -ENODEV; err = -ENODEV;
goto done; goto done;
} }
...@@ -457,7 +459,8 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -457,7 +459,8 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
if (sk->sk_state == BT_CLOSED) if (sk->sk_state == BT_CLOSED)
return 0; return 0;
if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb)
return err; return err;
msg->msg_namelen = 0; msg->msg_namelen = 0;
...@@ -499,7 +502,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -499,7 +502,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
lock_sock(sk); lock_sock(sk);
if (!(hdev = hci_pi(sk)->hdev)) { hdev = hci_pi(sk)->hdev;
if (!hdev) {
err = -EBADFD; err = -EBADFD;
goto done; goto done;
} }
...@@ -509,7 +513,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, ...@@ -509,7 +513,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
goto done; goto done;
} }
if (!(skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err);
if (!skb)
goto done; goto done;
if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
......
...@@ -107,6 +107,7 @@ static void __hidp_unlink_session(struct hidp_session *session) ...@@ -107,6 +107,7 @@ static void __hidp_unlink_session(struct hidp_session *session)
static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci) static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
{ {
memset(ci, 0, sizeof(*ci));
bacpy(&ci->bdaddr, &session->bdaddr); bacpy(&ci->bdaddr, &session->bdaddr);
ci->flags = session->flags; ci->flags = session->flags;
...@@ -115,7 +116,6 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin ...@@ -115,7 +116,6 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin
ci->vendor = 0x0000; ci->vendor = 0x0000;
ci->product = 0x0000; ci->product = 0x0000;
ci->version = 0x0000; ci->version = 0x0000;
memset(ci->name, 0, 128);
if (session->input) { if (session->input) {
ci->vendor = session->input->id.vendor; ci->vendor = session->input->id.vendor;
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
#define VERSION "2.15" #define VERSION "2.15"
static int disable_ertm = 0; static int disable_ertm;
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
static u8 l2cap_fixed_chan[8] = { 0x02, }; static u8 l2cap_fixed_chan[8] = { 0x02, };
...@@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, ...@@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb);
/* ---- L2CAP timers ---- */ /* ---- L2CAP timers ---- */
static void l2cap_sock_set_timer(struct sock *sk, long timeout)
{
BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
}
static void l2cap_sock_clear_timer(struct sock *sk)
{
BT_DBG("sock %p state %d", sk, sk->sk_state);
sk_stop_timer(sk, &sk->sk_timer);
}
static void l2cap_sock_timeout(unsigned long arg) static void l2cap_sock_timeout(unsigned long arg)
{ {
struct sock *sk = (struct sock *) arg; struct sock *sk = (struct sock *) arg;
...@@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg) ...@@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg)
bh_lock_sock(sk); bh_lock_sock(sk);
if (sock_owned_by_user(sk)) {
/* sk is owned by user. Try again later */
l2cap_sock_set_timer(sk, HZ / 5);
bh_unlock_sock(sk);
sock_put(sk);
return;
}
if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG)
reason = ECONNREFUSED; reason = ECONNREFUSED;
else if (sk->sk_state == BT_CONNECT && else if (sk->sk_state == BT_CONNECT &&
...@@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg) ...@@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg)
sock_put(sk); sock_put(sk);
} }
static void l2cap_sock_set_timer(struct sock *sk, long timeout)
{
BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout);
sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout);
}
static void l2cap_sock_clear_timer(struct sock *sk)
{
BT_DBG("sock %p state %d", sk, sk->sk_state);
sk_stop_timer(sk, &sk->sk_timer);
}
/* ---- L2CAP channels ---- */ /* ---- L2CAP channels ---- */
static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
{ {
...@@ -743,11 +751,13 @@ static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) ...@@ -743,11 +751,13 @@ static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src)
/* Find socket with psm and source bdaddr. /* Find socket with psm and source bdaddr.
* Returns closest match. * Returns closest match.
*/ */
static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
{ {
struct sock *sk = NULL, *sk1 = NULL; struct sock *sk = NULL, *sk1 = NULL;
struct hlist_node *node; struct hlist_node *node;
read_lock(&l2cap_sk_list.lock);
sk_for_each(sk, node, &l2cap_sk_list.head) { sk_for_each(sk, node, &l2cap_sk_list.head) {
if (state && sk->sk_state != state) if (state && sk->sk_state != state)
continue; continue;
...@@ -762,20 +772,10 @@ static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src ...@@ -762,20 +772,10 @@ static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src
sk1 = sk; sk1 = sk;
} }
} }
return node ? sk : sk1;
}
/* Find socket with given address (psm, src).
* Returns locked socket */
static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src)
{
struct sock *s;
read_lock(&l2cap_sk_list.lock);
s = __l2cap_get_sock_by_psm(state, psm, src);
if (s)
bh_lock_sock(s);
read_unlock(&l2cap_sk_list.lock); read_unlock(&l2cap_sk_list.lock);
return s;
return node ? sk : sk1;
} }
static void l2cap_sock_destruct(struct sock *sk) static void l2cap_sock_destruct(struct sock *sk)
...@@ -2926,6 +2926,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd ...@@ -2926,6 +2926,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
goto sendresp; goto sendresp;
} }
bh_lock_sock(parent);
/* Check if the ACL is secure enough (if not SDP) */ /* Check if the ACL is secure enough (if not SDP) */
if (psm != cpu_to_le16(0x0001) && if (psm != cpu_to_le16(0x0001) &&
!hci_conn_check_link_mode(conn->hcon)) { !hci_conn_check_link_mode(conn->hcon)) {
...@@ -3078,6 +3080,14 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd ...@@ -3078,6 +3080,14 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
break; break;
default: default:
/* don't delete l2cap channel if sk is owned by user */
if (sock_owned_by_user(sk)) {
sk->sk_state = BT_DISCONN;
l2cap_sock_clear_timer(sk);
l2cap_sock_set_timer(sk, HZ / 5);
break;
}
l2cap_chan_del(sk, ECONNREFUSED); l2cap_chan_del(sk, ECONNREFUSED);
break; break;
} }
...@@ -3283,6 +3293,15 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd ...@@ -3283,6 +3293,15 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
sk->sk_shutdown = SHUTDOWN_MASK; sk->sk_shutdown = SHUTDOWN_MASK;
/* don't delete l2cap channel if sk is owned by user */
if (sock_owned_by_user(sk)) {
sk->sk_state = BT_DISCONN;
l2cap_sock_clear_timer(sk);
l2cap_sock_set_timer(sk, HZ / 5);
bh_unlock_sock(sk);
return 0;
}
l2cap_chan_del(sk, ECONNRESET); l2cap_chan_del(sk, ECONNRESET);
bh_unlock_sock(sk); bh_unlock_sock(sk);
...@@ -3305,6 +3324,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd ...@@ -3305,6 +3324,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
if (!sk) if (!sk)
return 0; return 0;
/* don't delete l2cap channel if sk is owned by user */
if (sock_owned_by_user(sk)) {
sk->sk_state = BT_DISCONN;
l2cap_sock_clear_timer(sk);
l2cap_sock_set_timer(sk, HZ / 5);
bh_unlock_sock(sk);
return 0;
}
l2cap_chan_del(sk, 0); l2cap_chan_del(sk, 0);
bh_unlock_sock(sk); bh_unlock_sock(sk);
...@@ -4134,12 +4162,11 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) ...@@ -4134,12 +4162,11 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
__mod_retrans_timer(); __mod_retrans_timer();
pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY;
if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { if (pi->conn_state & L2CAP_CONN_SREJ_SENT)
l2cap_send_ack(pi); l2cap_send_ack(pi);
} else { else
l2cap_ertm_send(sk); l2cap_ertm_send(sk);
} }
}
} }
static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control) static inline void l2cap_data_channel_rejframe(struct sock *sk, u16 rx_control)
...@@ -4430,6 +4457,8 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str ...@@ -4430,6 +4457,8 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str
if (!sk) if (!sk)
goto drop; goto drop;
bh_lock_sock(sk);
BT_DBG("sk %p, len %d", sk, skb->len); BT_DBG("sk %p, len %d", sk, skb->len);
if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
...@@ -4841,8 +4870,10 @@ static int __init l2cap_init(void) ...@@ -4841,8 +4870,10 @@ static int __init l2cap_init(void)
return err; return err;
_busy_wq = create_singlethread_workqueue("l2cap"); _busy_wq = create_singlethread_workqueue("l2cap");
if (!_busy_wq) if (!_busy_wq) {
goto error; proto_unregister(&l2cap_proto);
return -ENOMEM;
}
err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
if (err < 0) { if (err < 0) {
...@@ -4870,6 +4901,7 @@ static int __init l2cap_init(void) ...@@ -4870,6 +4901,7 @@ static int __init l2cap_init(void)
return 0; return 0;
error: error:
destroy_workqueue(_busy_wq);
proto_unregister(&l2cap_proto); proto_unregister(&l2cap_proto);
return err; return err;
} }
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <net/sock.h> #include <net/sock.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -51,10 +51,10 @@ ...@@ -51,10 +51,10 @@
#define VERSION "1.11" #define VERSION "1.11"
static int disable_cfc = 0; static int disable_cfc;
static int l2cap_ertm;
static int channel_mtu = -1; static int channel_mtu = -1;
static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU; static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
static int l2cap_ertm = 0;
static struct task_struct *rfcomm_thread; static struct task_struct *rfcomm_thread;
...@@ -1901,7 +1901,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s) ...@@ -1901,7 +1901,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s)
BT_DBG("%p state %ld", s, s->state); BT_DBG("%p state %ld", s, s->state);
switch(sk->sk_state) { switch (sk->sk_state) {
case BT_CONNECTED: case BT_CONNECTED:
s->state = BT_CONNECT; s->state = BT_CONNECT;
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#include <net/sock.h> #include <net/sock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -140,11 +140,13 @@ static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src) ...@@ -140,11 +140,13 @@ static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src)
/* Find socket with channel and source bdaddr. /* Find socket with channel and source bdaddr.
* Returns closest match. * Returns closest match.
*/ */
static struct sock *__rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src) static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
{ {
struct sock *sk = NULL, *sk1 = NULL; struct sock *sk = NULL, *sk1 = NULL;
struct hlist_node *node; struct hlist_node *node;
read_lock(&rfcomm_sk_list.lock);
sk_for_each(sk, node, &rfcomm_sk_list.head) { sk_for_each(sk, node, &rfcomm_sk_list.head) {
if (state && sk->sk_state != state) if (state && sk->sk_state != state)
continue; continue;
...@@ -159,19 +161,10 @@ static struct sock *__rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t ...@@ -159,19 +161,10 @@ static struct sock *__rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t
sk1 = sk; sk1 = sk;
} }
} }
return node ? sk : sk1;
}
/* Find socket with given address (channel, src).
* Returns locked socket */
static inline struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
{
struct sock *s;
read_lock(&rfcomm_sk_list.lock);
s = __rfcomm_get_sock_by_channel(state, channel, src);
if (s) bh_lock_sock(s);
read_unlock(&rfcomm_sk_list.lock); read_unlock(&rfcomm_sk_list.lock);
return s;
return node ? sk : sk1;
} }
static void rfcomm_sock_destruct(struct sock *sk) static void rfcomm_sock_destruct(struct sock *sk)
...@@ -895,7 +888,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how) ...@@ -895,7 +888,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how)
BT_DBG("sock %p, sk %p", sock, sk); BT_DBG("sock %p, sk %p", sock, sk);
if (!sk) return 0; if (!sk)
return 0;
lock_sock(sk); lock_sock(sk);
if (!sk->sk_shutdown) { if (!sk->sk_shutdown) {
...@@ -945,6 +939,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * ...@@ -945,6 +939,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
if (!parent) if (!parent)
return 0; return 0;
bh_lock_sock(parent);
/* Check for backlog size */ /* Check for backlog size */
if (sk_acceptq_is_full(parent)) { if (sk_acceptq_is_full(parent)) {
BT_DBG("backlog full %d", parent->sk_ack_backlog); BT_DBG("backlog full %d", parent->sk_ack_backlog);
......
...@@ -431,7 +431,8 @@ static int rfcomm_release_dev(void __user *arg) ...@@ -431,7 +431,8 @@ static int rfcomm_release_dev(void __user *arg)
BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags); BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags);
if (!(dev = rfcomm_dev_get(req.dev_id))) dev = rfcomm_dev_get(req.dev_id);
if (!dev)
return -ENODEV; return -ENODEV;
if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) { if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) {
...@@ -470,7 +471,8 @@ static int rfcomm_get_dev_list(void __user *arg) ...@@ -470,7 +471,8 @@ static int rfcomm_get_dev_list(void __user *arg)
size = sizeof(*dl) + dev_num * sizeof(*di); size = sizeof(*dl) + dev_num * sizeof(*di);
if (!(dl = kmalloc(size, GFP_KERNEL))) dl = kmalloc(size, GFP_KERNEL);
if (!dl)
return -ENOMEM; return -ENOMEM;
di = dl->dev_info; di = dl->dev_info;
...@@ -513,7 +515,8 @@ static int rfcomm_get_dev_info(void __user *arg) ...@@ -513,7 +515,8 @@ static int rfcomm_get_dev_info(void __user *arg)
if (copy_from_user(&di, arg, sizeof(di))) if (copy_from_user(&di, arg, sizeof(di)))
return -EFAULT; return -EFAULT;
if (!(dev = rfcomm_dev_get(di.id))) dev = rfcomm_dev_get(di.id);
if (!dev)
return -ENODEV; return -ENODEV;
di.flags = dev->flags; di.flags = dev->flags;
...@@ -561,7 +564,8 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb) ...@@ -561,7 +564,8 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
return; return;
} }
if (!(tty = dev->tty) || !skb_queue_empty(&dev->pending)) { tty = dev->tty;
if (!tty || !skb_queue_empty(&dev->pending)) {
skb_queue_tail(&dev->pending, skb); skb_queue_tail(&dev->pending, skb);
return; return;
} }
...@@ -796,7 +800,8 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in ...@@ -796,7 +800,8 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in
memcpy(skb_put(skb, size), buf + sent, size); memcpy(skb_put(skb, size), buf + sent, size);
if ((err = rfcomm_dlc_send(dlc, skb)) < 0) { err = rfcomm_dlc_send(dlc, skb);
if (err < 0) {
kfree_skb(skb); kfree_skb(skb);
break; break;
} }
...@@ -892,7 +897,7 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) ...@@ -892,7 +897,7 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
/* Parity on/off and when on, odd/even */ /* Parity on/off and when on, odd/even */
if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) || if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) ||
((old->c_cflag & PARODD) != (new->c_cflag & PARODD)) ) { ((old->c_cflag & PARODD) != (new->c_cflag & PARODD))) {
changes |= RFCOMM_RPN_PM_PARITY; changes |= RFCOMM_RPN_PM_PARITY;
BT_DBG("Parity change detected."); BT_DBG("Parity change detected.");
} }
...@@ -937,11 +942,10 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) ...@@ -937,11 +942,10 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
/* POSIX does not support 1.5 stop bits and RFCOMM does not /* POSIX does not support 1.5 stop bits and RFCOMM does not
* support 2 stop bits. So a request for 2 stop bits gets * support 2 stop bits. So a request for 2 stop bits gets
* translated to 1.5 stop bits */ * translated to 1.5 stop bits */
if (new->c_cflag & CSTOPB) { if (new->c_cflag & CSTOPB)
stop_bits = RFCOMM_RPN_STOP_15; stop_bits = RFCOMM_RPN_STOP_15;
} else { else
stop_bits = RFCOMM_RPN_STOP_1; stop_bits = RFCOMM_RPN_STOP_1;
}
/* Handle number of data bits [5-8] */ /* Handle number of data bits [5-8] */
if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE)) if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE))
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include <net/sock.h> #include <net/sock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h> #include <linux/uaccess.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#define VERSION "0.6" #define VERSION "0.6"
static int disable_esco = 0; static int disable_esco;
static const struct proto_ops sco_sock_ops; static const struct proto_ops sco_sock_ops;
...@@ -138,16 +138,17 @@ static inline struct sock *sco_chan_get(struct sco_conn *conn) ...@@ -138,16 +138,17 @@ static inline struct sock *sco_chan_get(struct sco_conn *conn)
static int sco_conn_del(struct hci_conn *hcon, int err) static int sco_conn_del(struct hci_conn *hcon, int err)
{ {
struct sco_conn *conn; struct sco_conn *conn = hcon->sco_data;
struct sock *sk; struct sock *sk;
if (!(conn = hcon->sco_data)) if (!conn)
return 0; return 0;
BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
/* Kill socket */ /* Kill socket */
if ((sk = sco_chan_get(conn))) { sk = sco_chan_get(conn);
if (sk) {
bh_lock_sock(sk); bh_lock_sock(sk);
sco_sock_clear_timer(sk); sco_sock_clear_timer(sk);
sco_chan_del(sk, err); sco_chan_del(sk, err);
...@@ -185,7 +186,8 @@ static int sco_connect(struct sock *sk) ...@@ -185,7 +186,8 @@ static int sco_connect(struct sock *sk)
BT_DBG("%s -> %s", batostr(src), batostr(dst)); BT_DBG("%s -> %s", batostr(src), batostr(dst));
if (!(hdev = hci_get_route(dst, src))) hdev = hci_get_route(dst, src);
if (!hdev)
return -EHOSTUNREACH; return -EHOSTUNREACH;
hci_dev_lock_bh(hdev); hci_dev_lock_bh(hdev);
...@@ -510,7 +512,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen ...@@ -510,7 +512,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
/* Set destination address and psm */ /* Set destination address and psm */
bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr); bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr);
if ((err = sco_connect(sk))) err = sco_connect(sk);
if (err)
goto done; goto done;
err = bt_sock_wait_state(sk, BT_CONNECTED, err = bt_sock_wait_state(sk, BT_CONNECTED,
...@@ -828,13 +831,14 @@ static void sco_chan_del(struct sock *sk, int err) ...@@ -828,13 +831,14 @@ static void sco_chan_del(struct sock *sk, int err)
static void sco_conn_ready(struct sco_conn *conn) static void sco_conn_ready(struct sco_conn *conn)
{ {
struct sock *parent, *sk; struct sock *parent;
struct sock *sk = conn->sk;
BT_DBG("conn %p", conn); BT_DBG("conn %p", conn);
sco_conn_lock(conn); sco_conn_lock(conn);
if ((sk = conn->sk)) { if (sk) {
sco_sock_clear_timer(sk); sco_sock_clear_timer(sk);
bh_lock_sock(sk); bh_lock_sock(sk);
sk->sk_state = BT_CONNECTED; sk->sk_state = BT_CONNECTED;
...@@ -882,7 +886,7 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) ...@@ -882,7 +886,7 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
int lm = 0; int lm = 0;
if (type != SCO_LINK && type != ESCO_LINK) if (type != SCO_LINK && type != ESCO_LINK)
return 0; return -EINVAL;
BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr));
...@@ -908,7 +912,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) ...@@ -908,7 +912,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status)
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return 0; return -EINVAL;
if (!status) { if (!status) {
struct sco_conn *conn; struct sco_conn *conn;
...@@ -927,7 +931,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) ...@@ -927,7 +931,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
BT_DBG("hcon %p reason %d", hcon, reason); BT_DBG("hcon %p reason %d", hcon, reason);
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
return 0; return -EINVAL;
sco_conn_del(hcon, bt_err(reason)); sco_conn_del(hcon, bt_err(reason));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment