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,7 +242,8 @@ static void btusb_intr_complete(struct urb *urb) ...@@ -239,7 +242,8 @@ 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) {
BT_ERR("%s urb %p failed to resubmit (%d)", if (err != -EPERM)
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,7 +327,8 @@ static void btusb_bulk_complete(struct urb *urb) ...@@ -323,7 +327,8 @@ 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) {
BT_ERR("%s urb %p failed to resubmit (%d)", if (err != -EPERM)
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,7 +417,8 @@ static void btusb_isoc_complete(struct urb *urb) ...@@ -412,7 +417,8 @@ 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) {
BT_ERR("%s urb %p failed to resubmit (%d)", if (err != -EPERM)
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);
} }
......
/* /*
BlueZ - Bluetooth protocol stack for Linux BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated Copyright (C) 2000-2001 Qualcomm Incorporated
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED. SOFTWARE IS DISCLAIMED.
*/ */
...@@ -489,7 +489,7 @@ struct hci_rp_read_local_name { ...@@ -489,7 +489,7 @@ struct hci_rp_read_local_name {
#define HCI_OP_WRITE_PG_TIMEOUT 0x0c18 #define HCI_OP_WRITE_PG_TIMEOUT 0x0c18
#define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a #define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a
#define SCAN_DISABLED 0x00 #define SCAN_DISABLED 0x00
#define SCAN_INQUIRY 0x01 #define SCAN_INQUIRY 0x01
#define SCAN_PAGE 0x02 #define SCAN_PAGE 0x02
...@@ -874,7 +874,7 @@ struct hci_ev_si_security { ...@@ -874,7 +874,7 @@ struct hci_ev_si_security {
struct hci_command_hdr { struct hci_command_hdr {
__le16 opcode; /* OCF & OGF */ __le16 opcode; /* OCF & OGF */
__u8 plen; __u8 plen;
} __packed; } __packed;
struct hci_event_hdr { struct hci_event_hdr {
......
...@@ -44,15 +44,15 @@ struct inquiry_data { ...@@ -44,15 +44,15 @@ struct inquiry_data {
}; };
struct inquiry_entry { struct inquiry_entry {
struct inquiry_entry *next; struct inquiry_entry *next;
__u32 timestamp; __u32 timestamp;
struct inquiry_data data; struct inquiry_data data;
}; };
struct inquiry_cache { struct inquiry_cache {
spinlock_t lock; spinlock_t lock;
__u32 timestamp; __u32 timestamp;
struct inquiry_entry *list; struct inquiry_entry *list;
}; };
struct hci_conn_hash { struct hci_conn_hash {
...@@ -141,7 +141,7 @@ struct hci_dev { ...@@ -141,7 +141,7 @@ struct hci_dev {
void *driver_data; void *driver_data;
void *core_data; void *core_data;
atomic_t promisc; atomic_t promisc;
struct dentry *debugfs; struct dentry *debugfs;
...@@ -150,7 +150,7 @@ struct hci_dev { ...@@ -150,7 +150,7 @@ struct hci_dev {
struct rfkill *rfkill; struct rfkill *rfkill;
struct module *owner; struct module *owner;
int (*open)(struct hci_dev *hdev); int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev);
...@@ -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)
......
/* /*
BlueZ - Bluetooth protocol stack for Linux BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated Copyright (C) 2000-2001 Qualcomm Incorporated
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org> Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
...@@ -14,13 +14,13 @@ ...@@ -14,13 +14,13 @@
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED. SOFTWARE IS DISCLAIMED.
*/ */
...@@ -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>
...@@ -11,13 +11,13 @@ ...@@ -11,13 +11,13 @@
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED. SOFTWARE IS DISCLAIMED.
*/ */
...@@ -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 {
...@@ -228,7 +228,7 @@ struct rfcomm_dlc { ...@@ -228,7 +228,7 @@ struct rfcomm_dlc {
/* ---- RFCOMM SEND RPN ---- */ /* ---- RFCOMM SEND RPN ---- */
int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci, int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
u8 bit_rate, u8 data_bits, u8 stop_bits, u8 bit_rate, u8 data_bits, u8 stop_bits,
u8 parity, u8 flow_ctrl_settings, u8 parity, u8 flow_ctrl_settings,
u8 xon_char, u8 xoff_char, u16 param_mask); u8 xon_char, u8 xoff_char, u16 param_mask);
/* ---- RFCOMM DLCs (channels) ---- */ /* ---- RFCOMM DLCs (channels) ---- */
......
/* /*
BlueZ - Bluetooth protocol stack for Linux BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2000-2001 Qualcomm Incorporated Copyright (C) 2000-2001 Qualcomm Incorporated
...@@ -12,13 +12,13 @@ ...@@ -12,13 +12,13 @@
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED. SOFTWARE IS DISCLAIMED.
*/ */
...@@ -55,11 +55,11 @@ struct sco_conninfo { ...@@ -55,11 +55,11 @@ struct sco_conninfo {
struct sco_conn { struct sco_conn {
struct hci_conn *hcon; struct hci_conn *hcon;
bdaddr_t *dst; bdaddr_t *dst;
bdaddr_t *src; bdaddr_t *src;
spinlock_t lock; spinlock_t lock;
struct sock *sk; struct sock *sk;
unsigned int mtu; unsigned int mtu;
}; };
......
...@@ -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;
} }
...@@ -422,16 +425,20 @@ int hci_inquiry(void __user *arg) ...@@ -422,16 +425,20 @@ int hci_inquiry(void __user *arg)
hci_dev_lock_bh(hdev); hci_dev_lock_bh(hdev);
if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
inquiry_cache_empty(hdev) || inquiry_cache_empty(hdev) ||
ir.flags & IREQ_CACHE_FLUSH) { ir.flags & IREQ_CACHE_FLUSH) {
inquiry_cache_flush(hdev); inquiry_cache_flush(hdev);
do_inquiry = 1; do_inquiry = 1;
} }
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)
goto done; if (do_inquiry) {
err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo);
if (err < 0)
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)
if (!ev->status) goto unlock;
memcpy(conn->features, ev->features, 8);
if (conn->state == BT_CONFIG) { if (!ev->status)
if (!ev->status && lmp_ssp_capable(hdev) && memcpy(conn->features, ev->features, 8);
lmp_ssp_capable(conn)) {
struct hci_cp_read_remote_ext_features cp; if (conn->state != BT_CONFIG)
cp.handle = ev->handle; goto unlock;
cp.page = 0x01;
hci_send_cmd(hdev, if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
HCI_OP_READ_REMOTE_EXT_FEATURES, struct hci_cp_read_remote_ext_features cp;
sizeof(cp), &cp); cp.handle = ev->handle;
} else if (!ev->status && conn->out && cp.page = 0x01;
conn->sec_level == BT_SECURITY_HIGH) { hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
struct hci_cp_auth_requested cp;
cp.handle = ev->handle;
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
sizeof(cp), &cp); sizeof(cp), &cp);
} else { goto unlock;
conn->state = BT_CONNECTED; }
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn); if (!ev->status) {
} struct hci_cp_remote_name_req cp;
} memset(&cp, 0, sizeof(cp));
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;
hci_proto_connect_cfm(conn, ev->status);
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)
if (!ev->status && ev->page == 0x01) { goto unlock;
struct inquiry_entry *ie;
if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) if (!ev->status && ev->page == 0x01) {
ie->data.ssp_mode = (ev->features[0] & 0x01); struct inquiry_entry *ie;
conn->ssp_mode = (ev->features[0] & 0x01); ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
} if (ie)
ie->data.ssp_mode = (ev->features[0] & 0x01);
if (conn->state == BT_CONFIG) { conn->ssp_mode = (ev->features[0] & 0x01);
if (!ev->status && hdev->ssp_mode > 0 &&
conn->ssp_mode > 0 && conn->out &&
conn->sec_level != BT_SECURITY_SDP) {
struct hci_cp_auth_requested cp;
cp.handle = ev->handle;
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
sizeof(cp), &cp);
} else {
conn->state = BT_CONNECTED;
hci_proto_connect_cfm(conn, ev->status);
hci_conn_put(conn);
}
}
} }
if (conn->state != BT_CONFIG)
goto unlock;
if (!ev->status) {
struct hci_cp_remote_name_req cp;
memset(&cp, 0, sizeof(cp));
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;
hci_proto_connect_cfm(conn, ev->status);
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,11 +4162,10 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) ...@@ -4134,11 +4162,10 @@ 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);
}
} }
} }
...@@ -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);
......
...@@ -58,9 +58,9 @@ struct rfcomm_dev { ...@@ -58,9 +58,9 @@ struct rfcomm_dev {
bdaddr_t src; bdaddr_t src;
bdaddr_t dst; bdaddr_t dst;
u8 channel; u8 channel;
uint modem_status; uint modem_status;
struct rfcomm_dlc *dlc; struct rfcomm_dlc *dlc;
struct tty_struct *tty; struct tty_struct *tty;
...@@ -69,7 +69,7 @@ struct rfcomm_dev { ...@@ -69,7 +69,7 @@ struct rfcomm_dev {
struct device *tty_dev; struct device *tty_dev;
atomic_t wmem_alloc; atomic_t wmem_alloc;
struct sk_buff_head pending; struct sk_buff_head pending;
}; };
...@@ -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