Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
This commit is contained in:
commit
c30ae138aa
@ -35,6 +35,10 @@
|
||||
static struct usb_device_id ath3k_table[] = {
|
||||
/* Atheros AR3011 */
|
||||
{ USB_DEVICE(0x0CF3, 0x3000) },
|
||||
|
||||
/* Atheros AR3011 with sflash firmware*/
|
||||
{ USB_DEVICE(0x0CF3, 0x3002) },
|
||||
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
|
@ -99,6 +99,9 @@ static struct usb_device_id blacklist_table[] = {
|
||||
/* Broadcom BCM2033 without firmware */
|
||||
{ USB_DEVICE(0x0a5c, 0x2033), .driver_info = BTUSB_IGNORE },
|
||||
|
||||
/* Atheros 3011 with sflash firmware */
|
||||
{ USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE },
|
||||
|
||||
/* Broadcom BCM2035 */
|
||||
{ USB_DEVICE(0x0a5c, 0x2035), .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)
|
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
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);
|
||||
usb_unanchor_urb(urb);
|
||||
}
|
||||
@ -323,7 +327,8 @@ static void btusb_bulk_complete(struct urb *urb)
|
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
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);
|
||||
usb_unanchor_urb(urb);
|
||||
}
|
||||
@ -412,7 +417,8 @@ static void btusb_isoc_complete(struct urb *urb)
|
||||
|
||||
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||
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);
|
||||
usb_unanchor_urb(urb);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
BlueZ - Bluetooth protocol stack for Linux
|
||||
Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||
|
||||
@ -12,13 +12,13 @@
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
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
|
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
|
||||
SOFTWARE IS DISCLAIMED.
|
||||
*/
|
||||
|
||||
@ -489,7 +489,7 @@ struct hci_rp_read_local_name {
|
||||
|
||||
#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_INQUIRY 0x01
|
||||
#define SCAN_PAGE 0x02
|
||||
@ -874,7 +874,7 @@ struct hci_ev_si_security {
|
||||
|
||||
struct hci_command_hdr {
|
||||
__le16 opcode; /* OCF & OGF */
|
||||
__u8 plen;
|
||||
__u8 plen;
|
||||
} __packed;
|
||||
|
||||
struct hci_event_hdr {
|
||||
|
@ -44,15 +44,15 @@ struct inquiry_data {
|
||||
};
|
||||
|
||||
struct inquiry_entry {
|
||||
struct inquiry_entry *next;
|
||||
struct inquiry_entry *next;
|
||||
__u32 timestamp;
|
||||
struct inquiry_data data;
|
||||
};
|
||||
|
||||
struct inquiry_cache {
|
||||
spinlock_t lock;
|
||||
spinlock_t lock;
|
||||
__u32 timestamp;
|
||||
struct inquiry_entry *list;
|
||||
struct inquiry_entry *list;
|
||||
};
|
||||
|
||||
struct hci_conn_hash {
|
||||
@ -141,7 +141,7 @@ struct hci_dev {
|
||||
void *driver_data;
|
||||
void *core_data;
|
||||
|
||||
atomic_t promisc;
|
||||
atomic_t promisc;
|
||||
|
||||
struct dentry *debugfs;
|
||||
|
||||
@ -150,7 +150,7 @@ struct hci_dev {
|
||||
|
||||
struct rfkill *rfkill;
|
||||
|
||||
struct module *owner;
|
||||
struct module *owner;
|
||||
|
||||
int (*open)(struct hci_dev *hdev);
|
||||
int (*close)(struct hci_dev *hdev);
|
||||
@ -215,8 +215,8 @@ extern rwlock_t hci_dev_list_lock;
|
||||
extern rwlock_t hci_cb_list_lock;
|
||||
|
||||
/* ----- Inquiry cache ----- */
|
||||
#define INQUIRY_CACHE_AGE_MAX (HZ*30) // 30 seconds
|
||||
#define INQUIRY_ENTRY_AGE_MAX (HZ*60) // 60 seconds
|
||||
#define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */
|
||||
#define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */
|
||||
|
||||
#define inquiry_cache_lock(c) spin_lock(&c->lock)
|
||||
#define inquiry_cache_unlock(c) spin_unlock(&c->lock)
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
BlueZ - Bluetooth protocol stack for Linux
|
||||
Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
|
||||
@ -14,13 +14,13 @@
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
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
|
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
|
||||
SOFTWARE IS DISCLAIMED.
|
||||
*/
|
||||
|
||||
@ -417,11 +417,11 @@ static inline int l2cap_tx_window_full(struct sock *sk)
|
||||
return sub == pi->remote_tx_win;
|
||||
}
|
||||
|
||||
#define __get_txseq(ctrl) ((ctrl) & L2CAP_CTRL_TXSEQ) >> 1
|
||||
#define __get_reqseq(ctrl) ((ctrl) & L2CAP_CTRL_REQSEQ) >> 8
|
||||
#define __is_iframe(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 __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1)
|
||||
#define __get_reqseq(ctrl) (((ctrl) & L2CAP_CTRL_REQSEQ) >> 8)
|
||||
#define __is_iframe(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)
|
||||
|
||||
void l2cap_load(void);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
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 Marcel Holtmann <marcel@holtmann.org>
|
||||
|
||||
@ -11,13 +11,13 @@
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
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
|
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
|
||||
SOFTWARE IS DISCLAIMED.
|
||||
*/
|
||||
|
||||
@ -105,7 +105,7 @@
|
||||
struct rfcomm_hdr {
|
||||
u8 addr;
|
||||
u8 ctrl;
|
||||
u8 len; // Actual size can be 2 bytes
|
||||
u8 len; /* Actual size can be 2 bytes */
|
||||
} __packed;
|
||||
|
||||
struct rfcomm_cmd {
|
||||
@ -228,7 +228,7 @@ struct rfcomm_dlc {
|
||||
/* ---- RFCOMM SEND RPN ---- */
|
||||
int rfcomm_send_rpn(struct rfcomm_session *s, int cr, u8 dlci,
|
||||
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);
|
||||
|
||||
/* ---- RFCOMM DLCs (channels) ---- */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
BlueZ - Bluetooth protocol stack for Linux
|
||||
Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||
|
||||
@ -12,13 +12,13 @@
|
||||
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
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
|
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
|
||||
ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
|
||||
COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
|
||||
SOFTWARE IS DISCLAIMED.
|
||||
*/
|
||||
|
||||
@ -55,11 +55,11 @@ struct sco_conninfo {
|
||||
struct sco_conn {
|
||||
struct hci_conn *hcon;
|
||||
|
||||
bdaddr_t *dst;
|
||||
bdaddr_t *src;
|
||||
|
||||
bdaddr_t *dst;
|
||||
bdaddr_t *src;
|
||||
|
||||
spinlock_t lock;
|
||||
struct sock *sk;
|
||||
struct sock *sk;
|
||||
|
||||
unsigned int mtu;
|
||||
};
|
||||
|
@ -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)
|
||||
{
|
||||
memset(ci, 0, sizeof(*ci));
|
||||
memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
|
||||
strcpy(ci->device, s->dev->name);
|
||||
ci->flags = s->flags;
|
||||
|
@ -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)
|
||||
{
|
||||
memset(ci, 0, sizeof(*ci));
|
||||
bacpy(&ci->bdaddr, &session->bdaddr);
|
||||
|
||||
ci->flags = session->flags;
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
@ -66,7 +66,8 @@ void hci_acl_connect(struct hci_conn *conn)
|
||||
bacpy(&cp.bdaddr, &conn->dst);
|
||||
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) {
|
||||
cp.pscan_rep_mode = ie->data.pscan_rep_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
|
||||
|
||||
BT_DBG("%s dst %s", hdev->name, batostr(dst));
|
||||
|
||||
if (!(acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst))) {
|
||||
if (!(acl = hci_conn_add(hdev, ACL_LINK, dst)))
|
||||
acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
|
||||
if (!acl) {
|
||||
acl = hci_conn_add(hdev, ACL_LINK, dst);
|
||||
if (!acl)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -389,8 +392,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8
|
||||
if (type == ACL_LINK)
|
||||
return acl;
|
||||
|
||||
if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) {
|
||||
if (!(sco = hci_conn_add(hdev, type, dst))) {
|
||||
sco = hci_conn_hash_lookup_ba(hdev, type, dst);
|
||||
if (!sco) {
|
||||
sco = hci_conn_add(hdev, type, dst);
|
||||
if (!sco) {
|
||||
hci_conn_put(acl);
|
||||
return NULL;
|
||||
}
|
||||
@ -647,10 +652,12 @@ int hci_get_conn_list(void __user *arg)
|
||||
|
||||
size = sizeof(req) + req.conn_num * sizeof(*ci);
|
||||
|
||||
if (!(cl = kmalloc(size, GFP_KERNEL)))
|
||||
cl = kmalloc(size, GFP_KERNEL);
|
||||
if (!cl)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(hdev = hci_dev_get(req.dev_id))) {
|
||||
hdev = hci_dev_get(req.dev_id);
|
||||
if (!hdev) {
|
||||
kfree(cl);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
@ -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)
|
||||
{
|
||||
struct inquiry_cache *cache = &hdev->inq_cache;
|
||||
struct inquiry_entry *e;
|
||||
struct inquiry_entry *ie;
|
||||
|
||||
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. */
|
||||
if (!(e = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC)))
|
||||
ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC);
|
||||
if (!ie)
|
||||
return;
|
||||
e->next = cache->list;
|
||||
cache->list = e;
|
||||
|
||||
ie->next = cache->list;
|
||||
cache->list = ie;
|
||||
}
|
||||
|
||||
memcpy(&e->data, data, sizeof(*data));
|
||||
e->timestamp = jiffies;
|
||||
memcpy(&ie->data, data, sizeof(*data));
|
||||
ie->timestamp = jiffies;
|
||||
cache->timestamp = jiffies;
|
||||
}
|
||||
|
||||
@ -422,16 +425,20 @@ int hci_inquiry(void __user *arg)
|
||||
|
||||
hci_dev_lock_bh(hdev);
|
||||
if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX ||
|
||||
inquiry_cache_empty(hdev) ||
|
||||
ir.flags & IREQ_CACHE_FLUSH) {
|
||||
inquiry_cache_empty(hdev) ||
|
||||
ir.flags & IREQ_CACHE_FLUSH) {
|
||||
inquiry_cache_flush(hdev);
|
||||
do_inquiry = 1;
|
||||
}
|
||||
hci_dev_unlock_bh(hdev);
|
||||
|
||||
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 */
|
||||
max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp;
|
||||
@ -439,7 +446,8 @@ int hci_inquiry(void __user *arg)
|
||||
/* cache_dump can't sleep. Therefore we allocate temp buffer and then
|
||||
* 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;
|
||||
goto done;
|
||||
}
|
||||
@ -611,7 +619,8 @@ int hci_dev_close(__u16 dev)
|
||||
struct hci_dev *hdev;
|
||||
int err;
|
||||
|
||||
if (!(hdev = hci_dev_get(dev)))
|
||||
hdev = hci_dev_get(dev);
|
||||
if (!hdev)
|
||||
return -ENODEV;
|
||||
err = hci_dev_do_close(hdev);
|
||||
hci_dev_put(hdev);
|
||||
@ -623,7 +632,8 @@ int hci_dev_reset(__u16 dev)
|
||||
struct hci_dev *hdev;
|
||||
int ret = 0;
|
||||
|
||||
if (!(hdev = hci_dev_get(dev)))
|
||||
hdev = hci_dev_get(dev);
|
||||
if (!hdev)
|
||||
return -ENODEV;
|
||||
|
||||
hci_req_lock(hdev);
|
||||
@ -663,7 +673,8 @@ int hci_dev_reset_stat(__u16 dev)
|
||||
struct hci_dev *hdev;
|
||||
int ret = 0;
|
||||
|
||||
if (!(hdev = hci_dev_get(dev)))
|
||||
hdev = hci_dev_get(dev);
|
||||
if (!hdev)
|
||||
return -ENODEV;
|
||||
|
||||
memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
|
||||
@ -682,7 +693,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
|
||||
if (copy_from_user(&dr, arg, sizeof(dr)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!(hdev = hci_dev_get(dr.dev_id)))
|
||||
hdev = hci_dev_get(dr.dev_id);
|
||||
if (!hdev)
|
||||
return -ENODEV;
|
||||
|
||||
switch (cmd) {
|
||||
@ -763,7 +775,8 @@ int hci_get_dev_list(void __user *arg)
|
||||
|
||||
size = sizeof(*dl) + dev_num * sizeof(*dr);
|
||||
|
||||
if (!(dl = kzalloc(size, GFP_KERNEL)))
|
||||
dl = kzalloc(size, GFP_KERNEL);
|
||||
if (!dl)
|
||||
return -ENOMEM;
|
||||
|
||||
dr = dl->dev_req;
|
||||
@ -797,7 +810,8 @@ int hci_get_dev_info(void __user *arg)
|
||||
if (copy_from_user(&di, arg, sizeof(di)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!(hdev = hci_dev_get(di.dev_id)))
|
||||
hdev = hci_dev_get(di.dev_id);
|
||||
if (!hdev)
|
||||
return -ENODEV;
|
||||
|
||||
strcpy(di.name, hdev->name);
|
||||
@ -905,7 +919,7 @@ int hci_register_dev(struct hci_dev *hdev)
|
||||
hdev->sniff_max_interval = 800;
|
||||
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->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)
|
||||
bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT;
|
||||
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 */
|
||||
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)
|
||||
hci_conn_enter_active_mode(conn);
|
||||
|
||||
/* 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);
|
||||
return;
|
||||
}
|
||||
@ -1644,7 +1660,8 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
register struct hci_proto *hp;
|
||||
|
||||
/* 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);
|
||||
return;
|
||||
}
|
||||
@ -1727,7 +1744,8 @@ static void hci_cmd_task(unsigned long arg)
|
||||
if (atomic_read(&hdev->cmd_cnt) && (skb = skb_dequeue(&hdev->cmd_q))) {
|
||||
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);
|
||||
hci_send_frame(skb);
|
||||
hdev->cmd_last_tx = jiffies;
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
@ -677,9 +677,50 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
|
||||
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)
|
||||
{
|
||||
struct hci_cp_remote_name_req *cp;
|
||||
struct hci_conn *conn;
|
||||
|
||||
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)
|
||||
@ -955,12 +996,14 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk
|
||||
|
||||
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);
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
|
||||
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");
|
||||
hci_dev_unlock(hdev);
|
||||
return;
|
||||
@ -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)
|
||||
{
|
||||
struct hci_ev_remote_name *ev = (void *) skb->data;
|
||||
struct hci_conn *conn;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
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)
|
||||
@ -1162,33 +1219,39 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
|
||||
if (conn) {
|
||||
if (!ev->status)
|
||||
memcpy(conn->features, ev->features, 8);
|
||||
if (!conn)
|
||||
goto unlock;
|
||||
|
||||
if (conn->state == BT_CONFIG) {
|
||||
if (!ev->status && lmp_ssp_capable(hdev) &&
|
||||
lmp_ssp_capable(conn)) {
|
||||
struct hci_cp_read_remote_ext_features cp;
|
||||
cp.handle = ev->handle;
|
||||
cp.page = 0x01;
|
||||
hci_send_cmd(hdev,
|
||||
HCI_OP_READ_REMOTE_EXT_FEATURES,
|
||||
if (!ev->status)
|
||||
memcpy(conn->features, ev->features, 8);
|
||||
|
||||
if (conn->state != BT_CONFIG)
|
||||
goto unlock;
|
||||
|
||||
if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) {
|
||||
struct hci_cp_read_remote_ext_features cp;
|
||||
cp.handle = ev->handle;
|
||||
cp.page = 0x01;
|
||||
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
|
||||
sizeof(cp), &cp);
|
||||
} else if (!ev->status && conn->out &&
|
||||
conn->sec_level == BT_SECURITY_HIGH) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1449,10 +1512,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s
|
||||
conn->sent -= count;
|
||||
|
||||
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;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@ -1547,7 +1612,8 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk
|
||||
if (conn && !ev->status) {
|
||||
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->timestamp = jiffies;
|
||||
}
|
||||
@ -1581,7 +1647,8 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *
|
||||
|
||||
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->timestamp = jiffies;
|
||||
}
|
||||
@ -1646,32 +1713,37 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
|
||||
if (conn) {
|
||||
if (!ev->status && ev->page == 0x01) {
|
||||
struct inquiry_entry *ie;
|
||||
if (!conn)
|
||||
goto unlock;
|
||||
|
||||
if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst)))
|
||||
ie->data.ssp_mode = (ev->features[0] & 0x01);
|
||||
if (!ev->status && ev->page == 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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
conn->ssp_mode = (ev->features[0] & 0x01);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1821,7 +1893,8 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_
|
||||
|
||||
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);
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
|
@ -43,7 +43,7 @@
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
@ -125,7 +125,8 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(nskb = skb_clone(skb, GFP_ATOMIC)))
|
||||
nskb = skb_clone(skb, GFP_ATOMIC);
|
||||
if (!nskb)
|
||||
continue;
|
||||
|
||||
/* Put type byte before the data */
|
||||
@ -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 (!(hdev = hci_dev_get(haddr->hci_dev))) {
|
||||
hdev = hci_dev_get(haddr->hci_dev);
|
||||
if (!hdev) {
|
||||
err = -ENODEV;
|
||||
goto done;
|
||||
}
|
||||
@ -457,7 +459,8 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
if (sk->sk_state == BT_CLOSED)
|
||||
return 0;
|
||||
|
||||
if (!(skb = skb_recv_datagram(sk, flags, noblock, &err)))
|
||||
skb = skb_recv_datagram(sk, flags, noblock, &err);
|
||||
if (!skb)
|
||||
return err;
|
||||
|
||||
msg->msg_namelen = 0;
|
||||
@ -499,7 +502,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
if (!(hdev = hci_pi(sk)->hdev)) {
|
||||
hdev = hci_pi(sk)->hdev;
|
||||
if (!hdev) {
|
||||
err = -EBADFD;
|
||||
goto done;
|
||||
}
|
||||
@ -509,7 +513,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||
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;
|
||||
|
||||
if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
|
||||
|
@ -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)
|
||||
{
|
||||
memset(ci, 0, sizeof(*ci));
|
||||
bacpy(&ci->bdaddr, &session->bdaddr);
|
||||
|
||||
ci->flags = session->flags;
|
||||
@ -115,7 +116,6 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin
|
||||
ci->vendor = 0x0000;
|
||||
ci->product = 0x0000;
|
||||
ci->version = 0x0000;
|
||||
memset(ci->name, 0, 128);
|
||||
|
||||
if (session->input) {
|
||||
ci->vendor = session->input->id.vendor;
|
||||
|
@ -57,7 +57,7 @@
|
||||
|
||||
#define VERSION "2.15"
|
||||
|
||||
static int disable_ertm = 0;
|
||||
static int disable_ertm;
|
||||
|
||||
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
|
||||
static u8 l2cap_fixed_chan[8] = { 0x02, };
|
||||
@ -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);
|
||||
|
||||
/* ---- 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)
|
||||
{
|
||||
struct sock *sk = (struct sock *) arg;
|
||||
@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg)
|
||||
|
||||
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)
|
||||
reason = ECONNREFUSED;
|
||||
else if (sk->sk_state == BT_CONNECT &&
|
||||
@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg)
|
||||
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 ---- */
|
||||
static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid)
|
||||
{
|
||||
@ -743,11 +751,13 @@ found:
|
||||
/* Find socket with psm and source bdaddr.
|
||||
* 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 hlist_node *node;
|
||||
|
||||
read_lock(&l2cap_sk_list.lock);
|
||||
|
||||
sk_for_each(sk, node, &l2cap_sk_list.head) {
|
||||
if (state && sk->sk_state != state)
|
||||
continue;
|
||||
@ -762,20 +772,10 @@ static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src
|
||||
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);
|
||||
return s;
|
||||
|
||||
return node ? sk : sk1;
|
||||
}
|
||||
|
||||
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
|
||||
goto sendresp;
|
||||
}
|
||||
|
||||
bh_lock_sock(parent);
|
||||
|
||||
/* Check if the ACL is secure enough (if not SDP) */
|
||||
if (psm != cpu_to_le16(0x0001) &&
|
||||
!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
|
||||
break;
|
||||
|
||||
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);
|
||||
break;
|
||||
}
|
||||
@ -3283,6 +3293,15 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
|
||||
|
||||
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);
|
||||
bh_unlock_sock(sk);
|
||||
|
||||
@ -3305,6 +3324,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
|
||||
if (!sk)
|
||||
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);
|
||||
bh_unlock_sock(sk);
|
||||
|
||||
@ -4134,11 +4162,10 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control)
|
||||
__mod_retrans_timer();
|
||||
|
||||
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);
|
||||
} else {
|
||||
else
|
||||
l2cap_ertm_send(sk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4430,6 +4457,8 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str
|
||||
if (!sk)
|
||||
goto drop;
|
||||
|
||||
bh_lock_sock(sk);
|
||||
|
||||
BT_DBG("sk %p, len %d", sk, skb->len);
|
||||
|
||||
if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED)
|
||||
@ -4841,8 +4870,10 @@ static int __init l2cap_init(void)
|
||||
return err;
|
||||
|
||||
_busy_wq = create_singlethread_workqueue("l2cap");
|
||||
if (!_busy_wq)
|
||||
goto error;
|
||||
if (!_busy_wq) {
|
||||
proto_unregister(&l2cap_proto);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops);
|
||||
if (err < 0) {
|
||||
@ -4870,6 +4901,7 @@ static int __init l2cap_init(void)
|
||||
return 0;
|
||||
|
||||
error:
|
||||
destroy_workqueue(_busy_wq);
|
||||
proto_unregister(&l2cap_proto);
|
||||
return err;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <net/sock.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
@ -51,10 +51,10 @@
|
||||
|
||||
#define VERSION "1.11"
|
||||
|
||||
static int disable_cfc = 0;
|
||||
static int disable_cfc;
|
||||
static int l2cap_ertm;
|
||||
static int channel_mtu = -1;
|
||||
static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU;
|
||||
static int l2cap_ertm = 0;
|
||||
|
||||
static struct task_struct *rfcomm_thread;
|
||||
|
||||
@ -1901,7 +1901,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s)
|
||||
|
||||
BT_DBG("%p state %ld", s, s->state);
|
||||
|
||||
switch(sk->sk_state) {
|
||||
switch (sk->sk_state) {
|
||||
case BT_CONNECTED:
|
||||
s->state = BT_CONNECT;
|
||||
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
@ -140,11 +140,13 @@ static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src)
|
||||
/* Find socket with channel and source bdaddr.
|
||||
* 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 hlist_node *node;
|
||||
|
||||
read_lock(&rfcomm_sk_list.lock);
|
||||
|
||||
sk_for_each(sk, node, &rfcomm_sk_list.head) {
|
||||
if (state && sk->sk_state != state)
|
||||
continue;
|
||||
@ -159,19 +161,10 @@ static struct sock *__rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t
|
||||
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);
|
||||
return s;
|
||||
|
||||
return node ? sk : sk1;
|
||||
}
|
||||
|
||||
static void rfcomm_sock_destruct(struct sock *sk)
|
||||
@ -895,7 +888,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how)
|
||||
|
||||
BT_DBG("sock %p, sk %p", sock, sk);
|
||||
|
||||
if (!sk) return 0;
|
||||
if (!sk)
|
||||
return 0;
|
||||
|
||||
lock_sock(sk);
|
||||
if (!sk->sk_shutdown) {
|
||||
@ -945,6 +939,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
|
||||
if (!parent)
|
||||
return 0;
|
||||
|
||||
bh_lock_sock(parent);
|
||||
|
||||
/* Check for backlog size */
|
||||
if (sk_acceptq_is_full(parent)) {
|
||||
BT_DBG("backlog full %d", parent->sk_ack_backlog);
|
||||
|
@ -58,9 +58,9 @@ struct rfcomm_dev {
|
||||
|
||||
bdaddr_t src;
|
||||
bdaddr_t dst;
|
||||
u8 channel;
|
||||
u8 channel;
|
||||
|
||||
uint modem_status;
|
||||
uint modem_status;
|
||||
|
||||
struct rfcomm_dlc *dlc;
|
||||
struct tty_struct *tty;
|
||||
@ -69,7 +69,7 @@ struct rfcomm_dev {
|
||||
|
||||
struct device *tty_dev;
|
||||
|
||||
atomic_t wmem_alloc;
|
||||
atomic_t wmem_alloc;
|
||||
|
||||
struct sk_buff_head pending;
|
||||
};
|
||||
@ -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);
|
||||
|
||||
if (!(dev = rfcomm_dev_get(req.dev_id)))
|
||||
dev = rfcomm_dev_get(req.dev_id);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) {
|
||||
@ -470,7 +471,8 @@ static int rfcomm_get_dev_list(void __user *arg)
|
||||
|
||||
size = sizeof(*dl) + dev_num * sizeof(*di);
|
||||
|
||||
if (!(dl = kmalloc(size, GFP_KERNEL)))
|
||||
dl = kmalloc(size, GFP_KERNEL);
|
||||
if (!dl)
|
||||
return -ENOMEM;
|
||||
|
||||
di = dl->dev_info;
|
||||
@ -513,7 +515,8 @@ static int rfcomm_get_dev_info(void __user *arg)
|
||||
if (copy_from_user(&di, arg, sizeof(di)))
|
||||
return -EFAULT;
|
||||
|
||||
if (!(dev = rfcomm_dev_get(di.id)))
|
||||
dev = rfcomm_dev_get(di.id);
|
||||
if (!dev)
|
||||
return -ENODEV;
|
||||
|
||||
di.flags = dev->flags;
|
||||
@ -561,7 +564,8 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb)
|
||||
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);
|
||||
return;
|
||||
}
|
||||
@ -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);
|
||||
|
||||
if ((err = rfcomm_dlc_send(dlc, skb)) < 0) {
|
||||
err = rfcomm_dlc_send(dlc, skb);
|
||||
if (err < 0) {
|
||||
kfree_skb(skb);
|
||||
break;
|
||||
}
|
||||
@ -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 */
|
||||
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;
|
||||
BT_DBG("Parity change detected.");
|
||||
}
|
||||
@ -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
|
||||
* support 2 stop bits. So a request for 2 stop bits gets
|
||||
* translated to 1.5 stop bits */
|
||||
if (new->c_cflag & CSTOPB) {
|
||||
if (new->c_cflag & CSTOPB)
|
||||
stop_bits = RFCOMM_RPN_STOP_15;
|
||||
} else {
|
||||
else
|
||||
stop_bits = RFCOMM_RPN_STOP_1;
|
||||
}
|
||||
|
||||
/* Handle number of data bits [5-8] */
|
||||
if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE))
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
@ -52,7 +52,7 @@
|
||||
|
||||
#define VERSION "0.6"
|
||||
|
||||
static int disable_esco = 0;
|
||||
static int disable_esco;
|
||||
|
||||
static const struct proto_ops sco_sock_ops;
|
||||
|
||||
@ -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)
|
||||
{
|
||||
struct sco_conn *conn;
|
||||
struct sco_conn *conn = hcon->sco_data;
|
||||
struct sock *sk;
|
||||
|
||||
if (!(conn = hcon->sco_data))
|
||||
if (!conn)
|
||||
return 0;
|
||||
|
||||
BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
|
||||
|
||||
/* Kill socket */
|
||||
if ((sk = sco_chan_get(conn))) {
|
||||
sk = sco_chan_get(conn);
|
||||
if (sk) {
|
||||
bh_lock_sock(sk);
|
||||
sco_sock_clear_timer(sk);
|
||||
sco_chan_del(sk, err);
|
||||
@ -185,7 +186,8 @@ static int sco_connect(struct sock *sk)
|
||||
|
||||
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;
|
||||
|
||||
hci_dev_lock_bh(hdev);
|
||||
@ -510,7 +512,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen
|
||||
/* Set destination address and psm */
|
||||
bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr);
|
||||
|
||||
if ((err = sco_connect(sk)))
|
||||
err = sco_connect(sk);
|
||||
if (err)
|
||||
goto done;
|
||||
|
||||
err = bt_sock_wait_state(sk, BT_CONNECTED,
|
||||
@ -828,13 +831,14 @@ static void sco_chan_del(struct sock *sk, int err)
|
||||
|
||||
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);
|
||||
|
||||
sco_conn_lock(conn);
|
||||
|
||||
if ((sk = conn->sk)) {
|
||||
if (sk) {
|
||||
sco_sock_clear_timer(sk);
|
||||
bh_lock_sock(sk);
|
||||
sk->sk_state = BT_CONNECTED;
|
||||
@ -882,7 +886,7 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
|
||||
int lm = 0;
|
||||
|
||||
if (type != SCO_LINK && type != ESCO_LINK)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
|
||||
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)
|
||||
BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status);
|
||||
|
||||
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
|
||||
if (!status) {
|
||||
struct sco_conn *conn;
|
||||
@ -927,7 +931,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
|
||||
BT_DBG("hcon %p reason %d", hcon, reason);
|
||||
|
||||
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
|
||||
return 0;
|
||||
return -EINVAL;
|
||||
|
||||
sco_conn_del(hcon, bt_err(reason));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user