Commit bb400801 authored by David S. Miller's avatar David S. Miller
parents 130aa61a 611b30f7
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#define VERSION "1.2" #define VERSION "1.3"
static int minor = MISC_DYNAMIC_MINOR; static int minor = MISC_DYNAMIC_MINOR;
...@@ -51,14 +51,8 @@ struct vhci_data { ...@@ -51,14 +51,8 @@ struct vhci_data {
wait_queue_head_t read_wait; wait_queue_head_t read_wait;
struct sk_buff_head readq; struct sk_buff_head readq;
struct fasync_struct *fasync;
}; };
#define VHCI_FASYNC 0x0010
static struct miscdevice vhci_miscdev;
static int vhci_open_dev(struct hci_dev *hdev) static int vhci_open_dev(struct hci_dev *hdev)
{ {
set_bit(HCI_RUNNING, &hdev->flags); set_bit(HCI_RUNNING, &hdev->flags);
...@@ -105,9 +99,6 @@ static int vhci_send_frame(struct sk_buff *skb) ...@@ -105,9 +99,6 @@ static int vhci_send_frame(struct sk_buff *skb)
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&data->readq, skb); skb_queue_tail(&data->readq, skb);
if (data->flags & VHCI_FASYNC)
kill_fasync(&data->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&data->read_wait); wake_up_interruptible(&data->read_wait);
return 0; return 0;
...@@ -179,41 +170,31 @@ static inline ssize_t vhci_put_user(struct vhci_data *data, ...@@ -179,41 +170,31 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,
static ssize_t vhci_read(struct file *file, static ssize_t vhci_read(struct file *file,
char __user *buf, size_t count, loff_t *pos) char __user *buf, size_t count, loff_t *pos)
{ {
DECLARE_WAITQUEUE(wait, current);
struct vhci_data *data = file->private_data; struct vhci_data *data = file->private_data;
struct sk_buff *skb; struct sk_buff *skb;
ssize_t ret = 0; ssize_t ret = 0;
add_wait_queue(&data->read_wait, &wait);
while (count) { while (count) {
set_current_state(TASK_INTERRUPTIBLE);
skb = skb_dequeue(&data->readq); skb = skb_dequeue(&data->readq);
if (!skb) { if (skb) {
if (file->f_flags & O_NONBLOCK) { ret = vhci_put_user(data, skb, buf, count);
ret = -EAGAIN; if (ret < 0)
break; skb_queue_head(&data->readq, skb);
} else
kfree_skb(skb);
if (signal_pending(current)) { break;
ret = -ERESTARTSYS;
break;
}
schedule();
continue;
} }
if (access_ok(VERIFY_WRITE, buf, count)) if (file->f_flags & O_NONBLOCK) {
ret = vhci_put_user(data, skb, buf, count); ret = -EAGAIN;
else break;
ret = -EFAULT; }
kfree_skb(skb); ret = wait_event_interruptible(data->read_wait,
break; !skb_queue_empty(&data->readq));
if (ret < 0)
break;
} }
set_current_state(TASK_RUNNING);
remove_wait_queue(&data->read_wait, &wait);
return ret; return ret;
} }
...@@ -223,9 +204,6 @@ static ssize_t vhci_write(struct file *file, ...@@ -223,9 +204,6 @@ static ssize_t vhci_write(struct file *file,
{ {
struct vhci_data *data = file->private_data; struct vhci_data *data = file->private_data;
if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
return vhci_get_user(data, buf, count); return vhci_get_user(data, buf, count);
} }
...@@ -259,11 +237,9 @@ static int vhci_open(struct inode *inode, struct file *file) ...@@ -259,11 +237,9 @@ static int vhci_open(struct inode *inode, struct file *file)
skb_queue_head_init(&data->readq); skb_queue_head_init(&data->readq);
init_waitqueue_head(&data->read_wait); init_waitqueue_head(&data->read_wait);
lock_kernel();
hdev = hci_alloc_dev(); hdev = hci_alloc_dev();
if (!hdev) { if (!hdev) {
kfree(data); kfree(data);
unlock_kernel();
return -ENOMEM; return -ENOMEM;
} }
...@@ -284,12 +260,10 @@ static int vhci_open(struct inode *inode, struct file *file) ...@@ -284,12 +260,10 @@ static int vhci_open(struct inode *inode, struct file *file)
BT_ERR("Can't register HCI device"); BT_ERR("Can't register HCI device");
kfree(data); kfree(data);
hci_free_dev(hdev); hci_free_dev(hdev);
unlock_kernel();
return -EBUSY; return -EBUSY;
} }
file->private_data = data; file->private_data = data;
unlock_kernel();
return nonseekable_open(inode, file); return nonseekable_open(inode, file);
} }
...@@ -310,48 +284,25 @@ static int vhci_release(struct inode *inode, struct file *file) ...@@ -310,48 +284,25 @@ static int vhci_release(struct inode *inode, struct file *file)
return 0; return 0;
} }
static int vhci_fasync(int fd, struct file *file, int on)
{
struct vhci_data *data = file->private_data;
int err = 0;
lock_kernel();
err = fasync_helper(fd, file, on, &data->fasync);
if (err < 0)
goto out;
if (on)
data->flags |= VHCI_FASYNC;
else
data->flags &= ~VHCI_FASYNC;
out:
unlock_kernel();
return err;
}
static const struct file_operations vhci_fops = { static const struct file_operations vhci_fops = {
.owner = THIS_MODULE,
.read = vhci_read, .read = vhci_read,
.write = vhci_write, .write = vhci_write,
.poll = vhci_poll, .poll = vhci_poll,
.ioctl = vhci_ioctl, .ioctl = vhci_ioctl,
.open = vhci_open, .open = vhci_open,
.release = vhci_release, .release = vhci_release,
.fasync = vhci_fasync,
}; };
static struct miscdevice vhci_miscdev= { static struct miscdevice vhci_miscdev= {
.name = "vhci", .name = "vhci",
.fops = &vhci_fops, .fops = &vhci_fops,
.minor = MISC_DYNAMIC_MINOR,
}; };
static int __init vhci_init(void) static int __init vhci_init(void)
{ {
BT_INFO("Virtual HCI driver ver %s", VERSION); BT_INFO("Virtual HCI driver ver %s", VERSION);
vhci_miscdev.minor = minor;
if (misc_register(&vhci_miscdev) < 0) { if (misc_register(&vhci_miscdev) < 0) {
BT_ERR("Can't register misc device with minor %d", minor); BT_ERR("Can't register misc device with minor %d", minor);
return -EIO; return -EIO;
...@@ -369,9 +320,6 @@ static void __exit vhci_exit(void) ...@@ -369,9 +320,6 @@ static void __exit vhci_exit(void)
module_init(vhci_init); module_init(vhci_init);
module_exit(vhci_exit); module_exit(vhci_exit);
module_param(minor, int, 0444);
MODULE_PARM_DESC(minor, "Miscellaneous minor device number");
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
MODULE_VERSION(VERSION); MODULE_VERSION(VERSION);
......
...@@ -81,12 +81,6 @@ enum { ...@@ -81,12 +81,6 @@ enum {
BT_CLOSED BT_CLOSED
}; };
/* Endianness conversions */
#define htobs(a) __cpu_to_le16(a)
#define htobl(a) __cpu_to_le32(a)
#define btohs(a) __le16_to_cpu(a)
#define btohl(a) __le32_to_cpu(a)
/* BD Address */ /* BD Address */
typedef struct { typedef struct {
__u8 b[6]; __u8 b[6];
......
...@@ -137,6 +137,8 @@ struct hci_dev { ...@@ -137,6 +137,8 @@ struct hci_dev {
struct device *parent; struct device *parent;
struct device dev; struct device dev;
struct rfkill *rfkill;
struct module *owner; struct module *owner;
int (*open)(struct hci_dev *hdev); int (*open)(struct hci_dev *hdev);
......
...@@ -26,8 +26,13 @@ ...@@ -26,8 +26,13 @@
#define __L2CAP_H #define __L2CAP_H
/* L2CAP defaults */ /* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672 #define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF #define L2CAP_DEFAULT_FLUSH_TO 0xffff
#define L2CAP_DEFAULT_RX_WINDOW 1
#define L2CAP_DEFAULT_MAX_RECEIVE 1
#define L2CAP_DEFAULT_RETRANS_TO 300 /* 300 milliseconds */
#define L2CAP_DEFAULT_MONITOR_TO 1000 /* 1 second */
#define L2CAP_DEFAULT_MAX_RX_APDU 0xfff7
#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */ #define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */
#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */ #define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */
...@@ -64,17 +69,29 @@ struct l2cap_conninfo { ...@@ -64,17 +69,29 @@ struct l2cap_conninfo {
#define L2CAP_LM_SECURE 0x0020 #define L2CAP_LM_SECURE 0x0020
/* L2CAP command codes */ /* L2CAP command codes */
#define L2CAP_COMMAND_REJ 0x01 #define L2CAP_COMMAND_REJ 0x01
#define L2CAP_CONN_REQ 0x02 #define L2CAP_CONN_REQ 0x02
#define L2CAP_CONN_RSP 0x03 #define L2CAP_CONN_RSP 0x03
#define L2CAP_CONF_REQ 0x04 #define L2CAP_CONF_REQ 0x04
#define L2CAP_CONF_RSP 0x05 #define L2CAP_CONF_RSP 0x05
#define L2CAP_DISCONN_REQ 0x06 #define L2CAP_DISCONN_REQ 0x06
#define L2CAP_DISCONN_RSP 0x07 #define L2CAP_DISCONN_RSP 0x07
#define L2CAP_ECHO_REQ 0x08 #define L2CAP_ECHO_REQ 0x08
#define L2CAP_ECHO_RSP 0x09 #define L2CAP_ECHO_RSP 0x09
#define L2CAP_INFO_REQ 0x0a #define L2CAP_INFO_REQ 0x0a
#define L2CAP_INFO_RSP 0x0b #define L2CAP_INFO_RSP 0x0b
/* L2CAP feature mask */
#define L2CAP_FEAT_FLOWCTL 0x00000001
#define L2CAP_FEAT_RETRANS 0x00000002
#define L2CAP_FEAT_ERTM 0x00000008
#define L2CAP_FEAT_STREAMING 0x00000010
#define L2CAP_FEAT_FCS 0x00000020
#define L2CAP_FEAT_FIXED_CHAN 0x00000080
/* L2CAP checksum option */
#define L2CAP_FCS_NONE 0x00
#define L2CAP_FCS_CRC16 0x01
/* L2CAP structures */ /* L2CAP structures */
struct l2cap_hdr { struct l2cap_hdr {
...@@ -106,17 +123,23 @@ struct l2cap_conn_rsp { ...@@ -106,17 +123,23 @@ struct l2cap_conn_rsp {
__le16 status; __le16 status;
} __attribute__ ((packed)); } __attribute__ ((packed));
/* channel indentifier */
#define L2CAP_CID_SIGNALING 0x0001
#define L2CAP_CID_CONN_LESS 0x0002
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff
/* connect result */ /* connect result */
#define L2CAP_CR_SUCCESS 0x0000 #define L2CAP_CR_SUCCESS 0x0000
#define L2CAP_CR_PEND 0x0001 #define L2CAP_CR_PEND 0x0001
#define L2CAP_CR_BAD_PSM 0x0002 #define L2CAP_CR_BAD_PSM 0x0002
#define L2CAP_CR_SEC_BLOCK 0x0003 #define L2CAP_CR_SEC_BLOCK 0x0003
#define L2CAP_CR_NO_MEM 0x0004 #define L2CAP_CR_NO_MEM 0x0004
/* connect status */ /* connect status */
#define L2CAP_CS_NO_INFO 0x0000 #define L2CAP_CS_NO_INFO 0x0000
#define L2CAP_CS_AUTHEN_PEND 0x0001 #define L2CAP_CS_AUTHEN_PEND 0x0001
#define L2CAP_CS_AUTHOR_PEND 0x0002 #define L2CAP_CS_AUTHOR_PEND 0x0002
struct l2cap_conf_req { struct l2cap_conf_req {
__le16 dcid; __le16 dcid;
...@@ -143,10 +166,14 @@ struct l2cap_conf_opt { ...@@ -143,10 +166,14 @@ struct l2cap_conf_opt {
} __attribute__ ((packed)); } __attribute__ ((packed));
#define L2CAP_CONF_OPT_SIZE 2 #define L2CAP_CONF_OPT_SIZE 2
#define L2CAP_CONF_HINT 0x80
#define L2CAP_CONF_MASK 0x7f
#define L2CAP_CONF_MTU 0x01 #define L2CAP_CONF_MTU 0x01
#define L2CAP_CONF_FLUSH_TO 0x02 #define L2CAP_CONF_FLUSH_TO 0x02
#define L2CAP_CONF_QOS 0x03 #define L2CAP_CONF_QOS 0x03
#define L2CAP_CONF_RFC 0x04 #define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_FCS 0x05
#define L2CAP_CONF_MAX_SIZE 22 #define L2CAP_CONF_MAX_SIZE 22
...@@ -162,6 +189,8 @@ struct l2cap_conf_rfc { ...@@ -162,6 +189,8 @@ struct l2cap_conf_rfc {
#define L2CAP_MODE_BASIC 0x00 #define L2CAP_MODE_BASIC 0x00
#define L2CAP_MODE_RETRANS 0x01 #define L2CAP_MODE_RETRANS 0x01
#define L2CAP_MODE_FLOWCTL 0x02 #define L2CAP_MODE_FLOWCTL 0x02
#define L2CAP_MODE_ERTM 0x03
#define L2CAP_MODE_STREAM 0x04
struct l2cap_disconn_req { struct l2cap_disconn_req {
__le16 dcid; __le16 dcid;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/rfkill.h>
#include <net/sock.h> #include <net/sock.h>
#include <asm/system.h> #include <asm/system.h>
...@@ -476,6 +477,11 @@ int hci_dev_open(__u16 dev) ...@@ -476,6 +477,11 @@ int hci_dev_open(__u16 dev)
hci_req_lock(hdev); hci_req_lock(hdev);
if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
ret = -ERFKILL;
goto done;
}
if (test_bit(HCI_UP, &hdev->flags)) { if (test_bit(HCI_UP, &hdev->flags)) {
ret = -EALREADY; ret = -EALREADY;
goto done; goto done;
...@@ -813,6 +819,24 @@ int hci_get_dev_info(void __user *arg) ...@@ -813,6 +819,24 @@ int hci_get_dev_info(void __user *arg)
/* ---- Interface to HCI drivers ---- */ /* ---- Interface to HCI drivers ---- */
static int hci_rfkill_set_block(void *data, bool blocked)
{
struct hci_dev *hdev = data;
BT_DBG("%p name %s blocked %d", hdev, hdev->name, blocked);
if (!blocked)
return 0;
hci_dev_do_close(hdev);
return 0;
}
static const struct rfkill_ops hci_rfkill_ops = {
.set_block = hci_rfkill_set_block,
};
/* Alloc HCI device */ /* Alloc HCI device */
struct hci_dev *hci_alloc_dev(void) struct hci_dev *hci_alloc_dev(void)
{ {
...@@ -844,7 +868,8 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -844,7 +868,8 @@ int hci_register_dev(struct hci_dev *hdev)
struct list_head *head = &hci_dev_list, *p; struct list_head *head = &hci_dev_list, *p;
int i, id = 0; int i, id = 0;
BT_DBG("%p name %s type %d owner %p", hdev, hdev->name, hdev->type, hdev->owner); BT_DBG("%p name %s type %d owner %p", hdev, hdev->name,
hdev->type, hdev->owner);
if (!hdev->open || !hdev->close || !hdev->destruct) if (!hdev->open || !hdev->close || !hdev->destruct)
return -EINVAL; return -EINVAL;
...@@ -900,6 +925,15 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -900,6 +925,15 @@ int hci_register_dev(struct hci_dev *hdev)
hci_register_sysfs(hdev); hci_register_sysfs(hdev);
hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, hdev);
if (hdev->rfkill) {
if (rfkill_register(hdev->rfkill) < 0) {
rfkill_destroy(hdev->rfkill);
hdev->rfkill = NULL;
}
}
hci_notify(hdev, HCI_DEV_REG); hci_notify(hdev, HCI_DEV_REG);
return id; return id;
...@@ -924,6 +958,11 @@ int hci_unregister_dev(struct hci_dev *hdev) ...@@ -924,6 +958,11 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_notify(hdev, HCI_DEV_UNREG); hci_notify(hdev, HCI_DEV_UNREG);
if (hdev->rfkill) {
rfkill_unregister(hdev->rfkill);
rfkill_destroy(hdev->rfkill);
}
hci_unregister_sysfs(hdev); hci_unregister_sysfs(hdev);
__hci_dev_put(hdev); __hci_dev_put(hdev);
......
...@@ -40,10 +40,10 @@ ...@@ -40,10 +40,10 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/uaccess.h>
#include <net/sock.h> #include <net/sock.h>
#include <asm/system.h> #include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
#define VERSION "2.13" #define VERSION "2.13"
static u32 l2cap_feat_mask = 0x0080; static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN;
static u8 l2cap_fixed_chan[8] = { 0x02, }; static u8 l2cap_fixed_chan[8] = { 0x02, };
static const struct proto_ops l2cap_sock_ops; static const struct proto_ops l2cap_sock_ops;
...@@ -134,7 +134,8 @@ static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16 ...@@ -134,7 +134,8 @@ static inline struct sock *l2cap_get_chan_by_scid(struct l2cap_chan_list *l, u16
struct sock *s; struct sock *s;
read_lock(&l->lock); read_lock(&l->lock);
s = __l2cap_get_chan_by_scid(l, cid); s = __l2cap_get_chan_by_scid(l, cid);
if (s) bh_lock_sock(s); if (s)
bh_lock_sock(s);
read_unlock(&l->lock); read_unlock(&l->lock);
return s; return s;
} }
...@@ -154,17 +155,18 @@ static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8 ...@@ -154,17 +155,18 @@ static inline struct sock *l2cap_get_chan_by_ident(struct l2cap_chan_list *l, u8
struct sock *s; struct sock *s;
read_lock(&l->lock); read_lock(&l->lock);
s = __l2cap_get_chan_by_ident(l, ident); s = __l2cap_get_chan_by_ident(l, ident);
if (s) bh_lock_sock(s); if (s)
bh_lock_sock(s);
read_unlock(&l->lock); read_unlock(&l->lock);
return s; return s;
} }
static u16 l2cap_alloc_cid(struct l2cap_chan_list *l) static u16 l2cap_alloc_cid(struct l2cap_chan_list *l)
{ {
u16 cid = 0x0040; u16 cid = L2CAP_CID_DYN_START;
for (; cid < 0xffff; cid++) { for (; cid < L2CAP_CID_DYN_END; cid++) {
if(!__l2cap_get_chan_by_scid(l, cid)) if (!__l2cap_get_chan_by_scid(l, cid))
return cid; return cid;
} }
...@@ -204,7 +206,8 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so ...@@ -204,7 +206,8 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so
{ {
struct l2cap_chan_list *l = &conn->chan_list; struct l2cap_chan_list *l = &conn->chan_list;
BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid); BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn,
l2cap_pi(sk)->psm, l2cap_pi(sk)->dcid);
conn->disc_reason = 0x13; conn->disc_reason = 0x13;
...@@ -215,13 +218,13 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so ...@@ -215,13 +218,13 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so
l2cap_pi(sk)->scid = l2cap_alloc_cid(l); l2cap_pi(sk)->scid = l2cap_alloc_cid(l);
} else if (sk->sk_type == SOCK_DGRAM) { } else if (sk->sk_type == SOCK_DGRAM) {
/* Connectionless socket */ /* Connectionless socket */
l2cap_pi(sk)->scid = 0x0002; l2cap_pi(sk)->scid = L2CAP_CID_CONN_LESS;
l2cap_pi(sk)->dcid = 0x0002; l2cap_pi(sk)->dcid = L2CAP_CID_CONN_LESS;
l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
} else { } else {
/* Raw socket can send/recv signalling messages only */ /* Raw socket can send/recv signalling messages only */
l2cap_pi(sk)->scid = 0x0001; l2cap_pi(sk)->scid = L2CAP_CID_SIGNALING;
l2cap_pi(sk)->dcid = 0x0001; l2cap_pi(sk)->dcid = L2CAP_CID_SIGNALING;
l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU; l2cap_pi(sk)->omtu = L2CAP_DEFAULT_MTU;
} }
...@@ -272,7 +275,7 @@ static inline int l2cap_check_security(struct sock *sk) ...@@ -272,7 +275,7 @@ static inline int l2cap_check_security(struct sock *sk)
if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH) if (l2cap_pi(sk)->sec_level == BT_SECURITY_HIGH)
auth_type = HCI_AT_NO_BONDING_MITM; auth_type = HCI_AT_NO_BONDING_MITM;
else else
auth_type = HCI_AT_NO_BONDING; auth_type = HCI_AT_NO_BONDING;
if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW) if (l2cap_pi(sk)->sec_level == BT_SECURITY_LOW)
l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
...@@ -588,7 +591,8 @@ static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t ...@@ -588,7 +591,8 @@ static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t
struct sock *s; struct sock *s;
read_lock(&l2cap_sk_list.lock); read_lock(&l2cap_sk_list.lock);
s = __l2cap_get_sock_by_psm(state, psm, src); s = __l2cap_get_sock_by_psm(state, psm, src);
if (s) bh_lock_sock(s); if (s)
bh_lock_sock(s);
read_unlock(&l2cap_sk_list.lock); read_unlock(&l2cap_sk_list.lock);
return s; return s;
} }
...@@ -808,7 +812,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) ...@@ -808,7 +812,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
goto done; goto done;
} }
if (la.l2_psm && btohs(la.l2_psm) < 0x1001 && if (la.l2_psm && __le16_to_cpu(la.l2_psm) < 0x1001 &&
!capable(CAP_NET_BIND_SERVICE)) { !capable(CAP_NET_BIND_SERVICE)) {
err = -EACCES; err = -EACCES;
goto done; goto done;
...@@ -825,7 +829,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) ...@@ -825,7 +829,8 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
l2cap_pi(sk)->sport = la.l2_psm; l2cap_pi(sk)->sport = la.l2_psm;
sk->sk_state = BT_BOUND; sk->sk_state = BT_BOUND;
if (btohs(la.l2_psm) == 0x0001 || btohs(la.l2_psm) == 0x0003) if (__le16_to_cpu(la.l2_psm) == 0x0001 ||
__le16_to_cpu(la.l2_psm) == 0x0003)
l2cap_pi(sk)->sec_level = BT_SECURITY_SDP; l2cap_pi(sk)->sec_level = BT_SECURITY_SDP;
} }
...@@ -844,12 +849,13 @@ static int l2cap_do_connect(struct sock *sk) ...@@ -844,12 +849,13 @@ static int l2cap_do_connect(struct sock *sk)
struct hci_conn *hcon; struct hci_conn *hcon;
struct hci_dev *hdev; struct hci_dev *hdev;
__u8 auth_type; __u8 auth_type;
int err = 0; int err;
BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst),
l2cap_pi(sk)->psm); l2cap_pi(sk)->psm);
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);
...@@ -950,7 +956,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al ...@@ -950,7 +956,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
goto done; goto done;
} }
switch(sk->sk_state) { switch (sk->sk_state) {
case BT_CONNECT: case BT_CONNECT:
case BT_CONNECT2: case BT_CONNECT2:
case BT_CONFIG: case BT_CONFIG:
...@@ -975,7 +981,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al ...@@ -975,7 +981,8 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al
bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr); bacpy(&bt_sk(sk)->dst, &la.l2_bdaddr);
l2cap_pi(sk)->psm = la.l2_psm; l2cap_pi(sk)->psm = la.l2_psm;
if ((err = l2cap_do_connect(sk))) err = l2cap_do_connect(sk);
if (err)
goto done; goto done;
wait: wait:
...@@ -1009,9 +1016,9 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) ...@@ -1009,9 +1016,9 @@ static int l2cap_sock_listen(struct socket *sock, int backlog)
write_lock_bh(&l2cap_sk_list.lock); write_lock_bh(&l2cap_sk_list.lock);
for (psm = 0x1001; psm < 0x1100; psm += 2) for (psm = 0x1001; psm < 0x1100; psm += 2)
if (!__l2cap_get_sock_by_addr(htobs(psm), src)) { if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) {
l2cap_pi(sk)->psm = htobs(psm); l2cap_pi(sk)->psm = cpu_to_le16(psm);
l2cap_pi(sk)->sport = htobs(psm); l2cap_pi(sk)->sport = cpu_to_le16(psm);
err = 0; err = 0;
break; break;
} }
...@@ -1100,11 +1107,11 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l ...@@ -1100,11 +1107,11 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l
if (peer) { if (peer) {
la->l2_psm = l2cap_pi(sk)->psm; la->l2_psm = l2cap_pi(sk)->psm;
bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst); bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst);
la->l2_cid = htobs(l2cap_pi(sk)->dcid); la->l2_cid = cpu_to_le16(l2cap_pi(sk)->dcid);
} else { } else {
la->l2_psm = l2cap_pi(sk)->sport; la->l2_psm = l2cap_pi(sk)->sport;
bacpy(&la->l2_bdaddr, &bt_sk(sk)->src); bacpy(&la->l2_bdaddr, &bt_sk(sk)->src);
la->l2_cid = htobs(l2cap_pi(sk)->scid); la->l2_cid = cpu_to_le16(l2cap_pi(sk)->scid);
} }
return 0; return 0;
...@@ -1114,7 +1121,7 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len) ...@@ -1114,7 +1121,7 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
{ {
struct l2cap_conn *conn = l2cap_pi(sk)->conn; struct l2cap_conn *conn = l2cap_pi(sk)->conn;
struct sk_buff *skb, **frag; struct sk_buff *skb, **frag;
int err, hlen, count, sent=0; int err, hlen, count, sent = 0;
struct l2cap_hdr *lh; struct l2cap_hdr *lh;
BT_DBG("sk %p len %d", sk, len); BT_DBG("sk %p len %d", sk, len);
...@@ -1167,8 +1174,8 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len) ...@@ -1167,8 +1174,8 @@ static inline int l2cap_do_send(struct sock *sk, struct msghdr *msg, int len)
frag = &(*frag)->next; frag = &(*frag)->next;
} }
err = hci_send_acl(conn->hcon, skb, 0);
if ((err = hci_send_acl(conn->hcon, skb, 0)) < 0) if (err < 0)
goto fail; goto fail;
return sent; return sent;
...@@ -1556,7 +1563,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -1556,7 +1563,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
{ {
struct l2cap_chan_list *l = &conn->chan_list; struct l2cap_chan_list *l = &conn->chan_list;
struct sk_buff *nskb; struct sk_buff *nskb;
struct sock * sk; struct sock *sk;
BT_DBG("conn %p", conn); BT_DBG("conn %p", conn);
...@@ -1568,8 +1575,8 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -1568,8 +1575,8 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
/* Don't send frame to the socket it came from */ /* Don't send frame to the socket it came from */
if (skb->sk == sk) if (skb->sk == sk)
continue; continue;
nskb = skb_clone(skb, GFP_ATOMIC);
if (!(nskb = skb_clone(skb, GFP_ATOMIC))) if (!nskb)
continue; continue;
if (sock_queue_rcv_skb(sk, nskb)) if (sock_queue_rcv_skb(sk, nskb))
...@@ -1587,7 +1594,8 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, ...@@ -1587,7 +1594,8 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
struct l2cap_hdr *lh; struct l2cap_hdr *lh;
int len, count; int len, count;
BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d", conn, code, ident, dlen); BT_DBG("conn %p, code 0x%2.2x, ident 0x%2.2x, len %d",
conn, code, ident, dlen);
len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen;
count = min_t(unsigned int, conn->mtu, len); count = min_t(unsigned int, conn->mtu, len);
...@@ -1598,7 +1606,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, ...@@ -1598,7 +1606,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE);
lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen);
lh->cid = cpu_to_le16(0x0001); lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING);
cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE);
cmd->code = code; cmd->code = code;
...@@ -1739,8 +1747,8 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data) ...@@ -1739,8 +1747,8 @@ static int l2cap_parse_conf_req(struct sock *sk, void *data)
while (len >= L2CAP_CONF_OPT_SIZE) { while (len >= L2CAP_CONF_OPT_SIZE) {
len -= l2cap_get_conf_opt(&req, &type, &olen, &val); len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
hint = type & 0x80; hint = type & L2CAP_CONF_HINT;
type &= 0x7f; type &= L2CAP_CONF_MASK;
switch (type) { switch (type) {
case L2CAP_CONF_MTU: case L2CAP_CONF_MTU:
...@@ -1966,10 +1974,12 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd ...@@ -1966,10 +1974,12 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd
BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status); BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", dcid, scid, result, status);
if (scid) { if (scid) {
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid))) sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
if (!sk)
return 0; return 0;
} else { } else {
if (!(sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident))) sk = l2cap_get_chan_by_ident(&conn->chan_list, cmd->ident);
if (!sk)
return 0; return 0;
} }
...@@ -2012,7 +2022,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr ...@@ -2012,7 +2022,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr
BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid))) sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
if (!sk)
return -ENOENT; return -ENOENT;
if (sk->sk_state == BT_DISCONN) if (sk->sk_state == BT_DISCONN)
...@@ -2079,9 +2090,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr ...@@ -2079,9 +2090,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr
flags = __le16_to_cpu(rsp->flags); flags = __le16_to_cpu(rsp->flags);
result = __le16_to_cpu(rsp->result); result = __le16_to_cpu(rsp->result);
BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x", scid, flags, result); BT_DBG("scid 0x%4.4x flags 0x%2.2x result 0x%2.2x",
scid, flags, result);
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid))) sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
if (!sk)
return 0; return 0;
switch (result) { switch (result) {
...@@ -2142,7 +2155,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd ...@@ -2142,7 +2155,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd
BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid); BT_DBG("scid 0x%4.4x dcid 0x%4.4x", scid, dcid);
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid))) sk = l2cap_get_chan_by_scid(&conn->chan_list, dcid);
if (!sk)
return 0; return 0;
rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid); rsp.dcid = cpu_to_le16(l2cap_pi(sk)->scid);
...@@ -2169,7 +2183,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd ...@@ -2169,7 +2183,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd
BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid); BT_DBG("dcid 0x%4.4x scid 0x%4.4x", dcid, scid);
if (!(sk = l2cap_get_chan_by_scid(&conn->chan_list, scid))) sk = l2cap_get_chan_by_scid(&conn->chan_list, scid);
if (!sk)
return 0; return 0;
l2cap_chan_del(sk, 0); l2cap_chan_del(sk, 0);
...@@ -2230,7 +2245,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm ...@@ -2230,7 +2245,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
if (type == L2CAP_IT_FEAT_MASK) { if (type == L2CAP_IT_FEAT_MASK) {
conn->feat_mask = get_unaligned_le32(rsp->data); conn->feat_mask = get_unaligned_le32(rsp->data);
if (conn->feat_mask & 0x0080) { if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) {
struct l2cap_info_req req; struct l2cap_info_req req;
req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
...@@ -2403,7 +2418,8 @@ drop: ...@@ -2403,7 +2418,8 @@ drop:
kfree_skb(skb); kfree_skb(skb);
done: done:
if (sk) bh_unlock_sock(sk); if (sk)
bh_unlock_sock(sk);
return 0; return 0;
} }
...@@ -2420,11 +2436,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -2420,11 +2436,11 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
BT_DBG("len %d, cid 0x%4.4x", len, cid); BT_DBG("len %d, cid 0x%4.4x", len, cid);
switch (cid) { switch (cid) {
case 0x0001: case L2CAP_CID_SIGNALING:
l2cap_sig_channel(conn, skb); l2cap_sig_channel(conn, skb);
break; break;
case 0x0002: case L2CAP_CID_CONN_LESS:
psm = get_unaligned((__le16 *) skb->data); psm = get_unaligned((__le16 *) skb->data);
skb_pull(skb, 2); skb_pull(skb, 2);
l2cap_conless_channel(conn, psm, skb); l2cap_conless_channel(conn, psm, skb);
...@@ -2650,7 +2666,8 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl ...@@ -2650,7 +2666,8 @@ static int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 fl
} }
/* Allocate skb for the complete frame (with header) */ /* Allocate skb for the complete frame (with header) */
if (!(conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC))) conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC);
if (!conn->rx_skb)
goto drop; goto drop;
skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len),
...@@ -2704,13 +2721,13 @@ static ssize_t l2cap_sysfs_show(struct class *dev, char *buf) ...@@ -2704,13 +2721,13 @@ static ssize_t l2cap_sysfs_show(struct class *dev, char *buf)
str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n", str += sprintf(str, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d\n",
batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst),
sk->sk_state, btohs(pi->psm), pi->scid, pi->dcid, sk->sk_state, __le16_to_cpu(pi->psm), pi->scid,
pi->imtu, pi->omtu, pi->sec_level); pi->dcid, pi->imtu, pi->omtu, pi->sec_level);
} }
read_unlock_bh(&l2cap_sk_list.lock); read_unlock_bh(&l2cap_sk_list.lock);
return (str - buf); return str - buf;
} }
static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL); static CLASS_ATTR(l2cap, S_IRUGO, l2cap_sysfs_show, NULL);
......
...@@ -679,7 +679,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst ...@@ -679,7 +679,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
bacpy(&addr.l2_bdaddr, dst); bacpy(&addr.l2_bdaddr, dst);
addr.l2_family = AF_BLUETOOTH; addr.l2_family = AF_BLUETOOTH;
addr.l2_psm = htobs(RFCOMM_PSM); addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
addr.l2_cid = 0; addr.l2_cid = 0;
*err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
if (*err == 0 || *err == -EINPROGRESS) if (*err == 0 || *err == -EINPROGRESS)
...@@ -852,9 +852,9 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d ...@@ -852,9 +852,9 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
} }
if (cr && channel_mtu >= 0) if (cr && channel_mtu >= 0)
pn->mtu = htobs(channel_mtu); pn->mtu = cpu_to_le16(channel_mtu);
else else
pn->mtu = htobs(d->mtu); pn->mtu = cpu_to_le16(d->mtu);
*ptr = __fcs(buf); ptr++; *ptr = __fcs(buf); ptr++;
...@@ -1056,7 +1056,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr) ...@@ -1056,7 +1056,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
if (len > 127) { if (len > 127) {
hdr = (void *) skb_push(skb, 4); hdr = (void *) skb_push(skb, 4);
put_unaligned(htobs(__len16(len)), (__le16 *) &hdr->len); put_unaligned(cpu_to_le16(__len16(len)), (__le16 *) &hdr->len);
} else { } else {
hdr = (void *) skb_push(skb, 3); hdr = (void *) skb_push(skb, 3);
hdr->len = __len8(len); hdr->len = __len8(len);
...@@ -1289,7 +1289,7 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) ...@@ -1289,7 +1289,7 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
d->priority = pn->priority; d->priority = pn->priority;
d->mtu = btohs(pn->mtu); d->mtu = __le16_to_cpu(pn->mtu);
if (cr && d->mtu > s->mtu) if (cr && d->mtu > s->mtu)
d->mtu = s->mtu; d->mtu = s->mtu;
...@@ -1922,7 +1922,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) ...@@ -1922,7 +1922,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Bind socket */ /* Bind socket */
bacpy(&addr.l2_bdaddr, ba); bacpy(&addr.l2_bdaddr, ba);
addr.l2_family = AF_BLUETOOTH; addr.l2_family = AF_BLUETOOTH;
addr.l2_psm = htobs(RFCOMM_PSM); addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
addr.l2_cid = 0; addr.l2_cid = 0;
err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
if (err < 0) { if (err < 0) {
......
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