Commit bb400801 authored by David S. Miller's avatar David S. Miller
parents 130aa61a 611b30f7
......@@ -40,7 +40,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#define VERSION "1.2"
#define VERSION "1.3"
static int minor = MISC_DYNAMIC_MINOR;
......@@ -51,14 +51,8 @@ struct vhci_data {
wait_queue_head_t read_wait;
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)
{
set_bit(HCI_RUNNING, &hdev->flags);
......@@ -105,9 +99,6 @@ static int vhci_send_frame(struct sk_buff *skb)
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
skb_queue_tail(&data->readq, skb);
if (data->flags & VHCI_FASYNC)
kill_fasync(&data->fasync, SIGIO, POLL_IN);
wake_up_interruptible(&data->read_wait);
return 0;
......@@ -179,41 +170,31 @@ static inline ssize_t vhci_put_user(struct vhci_data *data,
static ssize_t vhci_read(struct file *file,
char __user *buf, size_t count, loff_t *pos)
{
DECLARE_WAITQUEUE(wait, current);
struct vhci_data *data = file->private_data;
struct sk_buff *skb;
ssize_t ret = 0;
add_wait_queue(&data->read_wait, &wait);
while (count) {
set_current_state(TASK_INTERRUPTIBLE);
skb = skb_dequeue(&data->readq);
if (!skb) {
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
if (skb) {
ret = vhci_put_user(data, skb, buf, count);
if (ret < 0)
skb_queue_head(&data->readq, skb);
else
kfree_skb(skb);
break;
}
if (signal_pending(current)) {
ret = -ERESTARTSYS;
if (file->f_flags & O_NONBLOCK) {
ret = -EAGAIN;
break;
}
schedule();
continue;
}
if (access_ok(VERIFY_WRITE, buf, count))
ret = vhci_put_user(data, skb, buf, count);
else
ret = -EFAULT;
kfree_skb(skb);
ret = wait_event_interruptible(data->read_wait,
!skb_queue_empty(&data->readq));
if (ret < 0)
break;
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&data->read_wait, &wait);
return ret;
}
......@@ -223,9 +204,6 @@ static ssize_t vhci_write(struct file *file,
{
struct vhci_data *data = file->private_data;
if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
return vhci_get_user(data, buf, count);
}
......@@ -259,11 +237,9 @@ static int vhci_open(struct inode *inode, struct file *file)
skb_queue_head_init(&data->readq);
init_waitqueue_head(&data->read_wait);
lock_kernel();
hdev = hci_alloc_dev();
if (!hdev) {
kfree(data);
unlock_kernel();
return -ENOMEM;
}
......@@ -284,12 +260,10 @@ static int vhci_open(struct inode *inode, struct file *file)
BT_ERR("Can't register HCI device");
kfree(data);
hci_free_dev(hdev);
unlock_kernel();
return -EBUSY;
}
file->private_data = data;
unlock_kernel();
return nonseekable_open(inode, file);
}
......@@ -310,48 +284,25 @@ static int vhci_release(struct inode *inode, struct file *file)
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 = {
.owner = THIS_MODULE,
.read = vhci_read,
.write = vhci_write,
.poll = vhci_poll,
.ioctl = vhci_ioctl,
.open = vhci_open,
.release = vhci_release,
.fasync = vhci_fasync,
};
static struct miscdevice vhci_miscdev= {
.name = "vhci",
.fops = &vhci_fops,
.minor = MISC_DYNAMIC_MINOR,
};
static int __init vhci_init(void)
{
BT_INFO("Virtual HCI driver ver %s", VERSION);
vhci_miscdev.minor = minor;
if (misc_register(&vhci_miscdev) < 0) {
BT_ERR("Can't register misc device with minor %d", minor);
return -EIO;
......@@ -369,9 +320,6 @@ static void __exit vhci_exit(void)
module_init(vhci_init);
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_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION);
MODULE_VERSION(VERSION);
......
......@@ -81,12 +81,6 @@ enum {
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 */
typedef struct {
__u8 b[6];
......
......@@ -137,6 +137,8 @@ struct hci_dev {
struct device *parent;
struct device dev;
struct rfkill *rfkill;
struct module *owner;
int (*open)(struct hci_dev *hdev);
......
......@@ -27,7 +27,12 @@
/* L2CAP defaults */
#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_INFO_TIMEOUT (4000) /* 4 seconds */
......@@ -76,6 +81,18 @@ struct l2cap_conninfo {
#define L2CAP_INFO_REQ 0x0a
#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 */
struct l2cap_hdr {
__le16 len;
......@@ -106,6 +123,12 @@ struct l2cap_conn_rsp {
__le16 status;
} __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 */
#define L2CAP_CR_SUCCESS 0x0000
#define L2CAP_CR_PEND 0x0001
......@@ -143,10 +166,14 @@ struct l2cap_conf_opt {
} __attribute__ ((packed));
#define L2CAP_CONF_OPT_SIZE 2
#define L2CAP_CONF_HINT 0x80
#define L2CAP_CONF_MASK 0x7f
#define L2CAP_CONF_MTU 0x01
#define L2CAP_CONF_FLUSH_TO 0x02
#define L2CAP_CONF_QOS 0x03
#define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_FCS 0x05
#define L2CAP_CONF_MAX_SIZE 22
......@@ -162,6 +189,8 @@ struct l2cap_conf_rfc {
#define L2CAP_MODE_BASIC 0x00
#define L2CAP_MODE_RETRANS 0x01
#define L2CAP_MODE_FLOWCTL 0x02
#define L2CAP_MODE_ERTM 0x03
#define L2CAP_MODE_STREAM 0x04
struct l2cap_disconn_req {
__le16 dcid;
......
......@@ -39,6 +39,7 @@
#include <linux/skbuff.h>
#include <linux/interrupt.h>
#include <linux/notifier.h>
#include <linux/rfkill.h>
#include <net/sock.h>
#include <asm/system.h>
......@@ -476,6 +477,11 @@ int hci_dev_open(__u16 dev)
hci_req_lock(hdev);
if (hdev->rfkill && rfkill_blocked(hdev->rfkill)) {
ret = -ERFKILL;
goto done;
}
if (test_bit(HCI_UP, &hdev->flags)) {
ret = -EALREADY;
goto done;
......@@ -813,6 +819,24 @@ int hci_get_dev_info(void __user *arg)
/* ---- 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 */
struct hci_dev *hci_alloc_dev(void)
{
......@@ -844,7 +868,8 @@ int hci_register_dev(struct hci_dev *hdev)
struct list_head *head = &hci_dev_list, *p;
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)
return -EINVAL;
......@@ -900,6 +925,15 @@ int hci_register_dev(struct hci_dev *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);
return id;
......@@ -924,6 +958,11 @@ int hci_unregister_dev(struct hci_dev *hdev)
hci_notify(hdev, HCI_DEV_UNREG);
if (hdev->rfkill) {
rfkill_unregister(hdev->rfkill);
rfkill_destroy(hdev->rfkill);
}
hci_unregister_sysfs(hdev);
__hci_dev_put(hdev);
......
This diff is collapsed.
......@@ -679,7 +679,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, bdaddr_t *dst
bacpy(&addr.l2_bdaddr, dst);
addr.l2_family = AF_BLUETOOTH;
addr.l2_psm = htobs(RFCOMM_PSM);
addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
addr.l2_cid = 0;
*err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK);
if (*err == 0 || *err == -EINPROGRESS)
......@@ -852,9 +852,9 @@ static int rfcomm_send_pn(struct rfcomm_session *s, int cr, struct rfcomm_dlc *d
}
if (cr && channel_mtu >= 0)
pn->mtu = htobs(channel_mtu);
pn->mtu = cpu_to_le16(channel_mtu);
else
pn->mtu = htobs(d->mtu);
pn->mtu = cpu_to_le16(d->mtu);
*ptr = __fcs(buf); ptr++;
......@@ -1056,7 +1056,7 @@ static void rfcomm_make_uih(struct sk_buff *skb, u8 addr)
if (len > 127) {
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 {
hdr = (void *) skb_push(skb, 3);
hdr->len = __len8(len);
......@@ -1289,7 +1289,7 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
d->priority = pn->priority;
d->mtu = btohs(pn->mtu);
d->mtu = __le16_to_cpu(pn->mtu);
if (cr && d->mtu > s->mtu)
d->mtu = s->mtu;
......@@ -1922,7 +1922,7 @@ static int rfcomm_add_listener(bdaddr_t *ba)
/* Bind socket */
bacpy(&addr.l2_bdaddr, ba);
addr.l2_family = AF_BLUETOOTH;
addr.l2_psm = htobs(RFCOMM_PSM);
addr.l2_psm = cpu_to_le16(RFCOMM_PSM);
addr.l2_cid = 0;
err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr));
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