You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
This commit is contained in:
@@ -73,6 +73,7 @@ struct btsdio_data {
|
||||
#define REG_CL_INTRD 0x13 /* Interrupt Clear */
|
||||
#define REG_EN_INTRD 0x14 /* Interrupt Enable */
|
||||
#define REG_MD_STAT 0x20 /* Bluetooth Mode Status */
|
||||
#define REG_MD_SET 0x20 /* Bluetooth Mode Set */
|
||||
|
||||
static int btsdio_tx_packet(struct btsdio_data *data, struct sk_buff *skb)
|
||||
{
|
||||
@@ -212,7 +213,7 @@ static int btsdio_open(struct hci_dev *hdev)
|
||||
}
|
||||
|
||||
if (data->func->class == SDIO_CLASS_BT_B)
|
||||
sdio_writeb(data->func, 0x00, REG_MD_STAT, NULL);
|
||||
sdio_writeb(data->func, 0x00, REG_MD_SET, NULL);
|
||||
|
||||
sdio_writeb(data->func, 0x01, REG_EN_INTRD, NULL);
|
||||
|
||||
@@ -333,6 +334,9 @@ static int btsdio_probe(struct sdio_func *func,
|
||||
hdev->flush = btsdio_flush;
|
||||
hdev->send = btsdio_send_frame;
|
||||
|
||||
if (func->vendor == 0x0104 && func->device == 0x00c5)
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
||||
err = hci_register_dev(hdev);
|
||||
if (err < 0) {
|
||||
hci_free_dev(hdev);
|
||||
|
||||
@@ -965,6 +965,45 @@ static int btusb_setup_bcm92035(struct hci_dev *hdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btusb_setup_csr(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_rp_read_local_version *rp;
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL,
|
||||
HCI_INIT_TIMEOUT);
|
||||
if (IS_ERR(skb)) {
|
||||
BT_ERR("Reading local version failed (%ld)", -PTR_ERR(skb));
|
||||
return -PTR_ERR(skb);
|
||||
}
|
||||
|
||||
rp = (struct hci_rp_read_local_version *) skb->data;
|
||||
|
||||
if (!rp->status) {
|
||||
if (le16_to_cpu(rp->manufacturer) != 10) {
|
||||
/* Clear the reset quirk since this is not an actual
|
||||
* early Bluetooth 1.1 device from CSR.
|
||||
*/
|
||||
clear_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
||||
/* These fake CSR controllers have all a broken
|
||||
* stored link key handling and so just disable it.
|
||||
*/
|
||||
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY,
|
||||
&hdev->quirks);
|
||||
}
|
||||
}
|
||||
|
||||
ret = -bt_to_errno(rp->status);
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct intel_version {
|
||||
u8 status;
|
||||
u8 hw_platform;
|
||||
@@ -1465,10 +1504,15 @@ static int btusb_probe(struct usb_interface *intf,
|
||||
|
||||
if (id->driver_info & BTUSB_CSR) {
|
||||
struct usb_device *udev = data->udev;
|
||||
u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);
|
||||
|
||||
/* Old firmware would otherwise execute USB reset */
|
||||
if (le16_to_cpu(udev->descriptor.bcdDevice) < 0x117)
|
||||
if (bcdDevice < 0x117)
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
||||
/* Fake CSR devices with broken commands */
|
||||
if (bcdDevice <= 0x100)
|
||||
hdev->setup = btusb_setup_csr;
|
||||
}
|
||||
|
||||
if (id->driver_info & BTUSB_SNIFFER) {
|
||||
|
||||
@@ -141,22 +141,28 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
|
||||
}
|
||||
|
||||
static inline ssize_t vhci_get_user(struct vhci_data *data,
|
||||
const char __user *buf, size_t count)
|
||||
const struct iovec *iov,
|
||||
unsigned long count)
|
||||
{
|
||||
size_t len = iov_length(iov, count);
|
||||
struct sk_buff *skb;
|
||||
__u8 pkt_type, dev_type;
|
||||
unsigned long i;
|
||||
int ret;
|
||||
|
||||
if (count < 2 || count > HCI_MAX_FRAME_SIZE)
|
||||
if (len < 2 || len > HCI_MAX_FRAME_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
skb = bt_skb_alloc(count, GFP_KERNEL);
|
||||
skb = bt_skb_alloc(len, GFP_KERNEL);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(skb_put(skb, count), buf, count)) {
|
||||
kfree_skb(skb);
|
||||
return -EFAULT;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (copy_from_user(skb_put(skb, iov[i].iov_len),
|
||||
iov[i].iov_base, iov[i].iov_len)) {
|
||||
kfree_skb(skb);
|
||||
return -EFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
pkt_type = *((__u8 *) skb->data);
|
||||
@@ -205,7 +211,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return (ret < 0) ? ret : count;
|
||||
return (ret < 0) ? ret : len;
|
||||
}
|
||||
|
||||
static inline ssize_t vhci_put_user(struct vhci_data *data,
|
||||
@@ -272,12 +278,13 @@ static ssize_t vhci_read(struct file *file,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t vhci_write(struct file *file,
|
||||
const char __user *buf, size_t count, loff_t *pos)
|
||||
static ssize_t vhci_write(struct kiocb *iocb, const struct iovec *iov,
|
||||
unsigned long count, loff_t pos)
|
||||
{
|
||||
struct file *file = iocb->ki_filp;
|
||||
struct vhci_data *data = file->private_data;
|
||||
|
||||
return vhci_get_user(data, buf, count);
|
||||
return vhci_get_user(data, iov, count);
|
||||
}
|
||||
|
||||
static unsigned int vhci_poll(struct file *file, poll_table *wait)
|
||||
@@ -342,7 +349,7 @@ static int vhci_release(struct inode *inode, struct file *file)
|
||||
static const struct file_operations vhci_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = vhci_read,
|
||||
.write = vhci_write,
|
||||
.aio_write = vhci_write,
|
||||
.poll = vhci_poll,
|
||||
.open = vhci_open,
|
||||
.release = vhci_release,
|
||||
|
||||
@@ -83,7 +83,8 @@
|
||||
enum {
|
||||
HCI_QUIRK_RESET_ON_CLOSE,
|
||||
HCI_QUIRK_RAW_DEVICE,
|
||||
HCI_QUIRK_FIXUP_BUFFER_SIZE
|
||||
HCI_QUIRK_FIXUP_BUFFER_SIZE,
|
||||
HCI_QUIRK_BROKEN_STORED_LINK_KEY,
|
||||
};
|
||||
|
||||
/* HCI device flags */
|
||||
@@ -131,6 +132,7 @@ enum {
|
||||
HCI_PERIODIC_INQ,
|
||||
HCI_FAST_CONNECTABLE,
|
||||
HCI_BREDR_ENABLED,
|
||||
HCI_6LOWPAN_ENABLED,
|
||||
};
|
||||
|
||||
/* A mask for the flags that are supposed to remain when a reset happens
|
||||
|
||||
@@ -448,6 +448,7 @@ enum {
|
||||
HCI_CONN_SSP_ENABLED,
|
||||
HCI_CONN_POWER_SAVE,
|
||||
HCI_CONN_REMOTE_OOB,
|
||||
HCI_CONN_6LOWPAN,
|
||||
};
|
||||
|
||||
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
|
||||
|
||||
@@ -136,6 +136,7 @@ struct l2cap_conninfo {
|
||||
#define L2CAP_FC_L2CAP 0x02
|
||||
#define L2CAP_FC_CONNLESS 0x04
|
||||
#define L2CAP_FC_A2MP 0x08
|
||||
#define L2CAP_FC_6LOWPAN 0x3e /* reserved and temporary value */
|
||||
|
||||
/* L2CAP Control Field bit masks */
|
||||
#define L2CAP_CTRL_SAR 0xC000
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
#define ARPHRD_CAIF 822 /* CAIF media type */
|
||||
#define ARPHRD_IP6GRE 823 /* GRE over IPv6 */
|
||||
#define ARPHRD_NETLINK 824 /* Netlink header */
|
||||
#define ARPHRD_6LOWPAN 825 /* IPv6 over LoWPAN */
|
||||
|
||||
#define ARPHRD_VOID 0xFFFF /* Void type, nothing is known */
|
||||
#define ARPHRD_NONE 0xFFFE /* zero header length */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
Copyright (c) 2013 Intel Corp.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 and
|
||||
only version 2 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#ifndef __6LOWPAN_H
|
||||
#define __6LOWPAN_H
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <net/bluetooth/l2cap.h>
|
||||
|
||||
int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb);
|
||||
int bt_6lowpan_add_conn(struct l2cap_conn *conn);
|
||||
int bt_6lowpan_del_conn(struct l2cap_conn *conn);
|
||||
int bt_6lowpan_init(void);
|
||||
void bt_6lowpan_cleanup(void);
|
||||
|
||||
#endif /* __6LOWPAN_H */
|
||||
@@ -10,6 +10,10 @@ obj-$(CONFIG_BT_HIDP) += hidp/
|
||||
|
||||
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
|
||||
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
|
||||
a2mp.o amp.o
|
||||
a2mp.o amp.o 6lowpan.o
|
||||
|
||||
ifeq ($(CONFIG_IEEE802154_6LOWPAN),)
|
||||
bluetooth-y += ../ieee802154/6lowpan_iphc.o
|
||||
endif
|
||||
|
||||
subdir-ccflags-y += -D__CHECK_ENDIAN__
|
||||
|
||||
@@ -636,6 +636,49 @@ static int conn_max_interval_get(void *data, u64 *val)
|
||||
DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get,
|
||||
conn_max_interval_set, "%llu\n");
|
||||
|
||||
static ssize_t lowpan_read(struct file *file, char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct hci_dev *hdev = file->private_data;
|
||||
char buf[3];
|
||||
|
||||
buf[0] = test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags) ? 'Y' : 'N';
|
||||
buf[1] = '\n';
|
||||
buf[2] = '\0';
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
|
||||
}
|
||||
|
||||
static ssize_t lowpan_write(struct file *fp, const char __user *user_buffer,
|
||||
size_t count, loff_t *position)
|
||||
{
|
||||
struct hci_dev *hdev = fp->private_data;
|
||||
bool enable;
|
||||
char buf[32];
|
||||
size_t buf_size = min(count, (sizeof(buf)-1));
|
||||
|
||||
if (copy_from_user(buf, user_buffer, buf_size))
|
||||
return -EFAULT;
|
||||
|
||||
buf[buf_size] = '\0';
|
||||
|
||||
if (strtobool(buf, &enable) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (enable == test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
|
||||
return -EALREADY;
|
||||
|
||||
change_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations lowpan_debugfs_fops = {
|
||||
.open = simple_open,
|
||||
.read = lowpan_read,
|
||||
.write = lowpan_write,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
/* ---- HCI requests ---- */
|
||||
|
||||
static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
|
||||
@@ -1261,8 +1304,13 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
||||
* as supported send it. If not supported assume that the controller
|
||||
* does not have actual support for stored link keys which makes this
|
||||
* command redundant anyway.
|
||||
*
|
||||
* Some controllers indicate that they support handling deleting
|
||||
* stored link keys, but they don't. The quirk lets a driver
|
||||
* just disable this command.
|
||||
*/
|
||||
if (hdev->commands[6] & 0x80) {
|
||||
if (hdev->commands[6] & 0x80 &&
|
||||
!test_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks)) {
|
||||
struct hci_cp_delete_stored_link_key cp;
|
||||
|
||||
bacpy(&cp.bdaddr, BDADDR_ANY);
|
||||
@@ -1406,6 +1454,8 @@ static int __hci_init(struct hci_dev *hdev)
|
||||
hdev, &conn_min_interval_fops);
|
||||
debugfs_create_file("conn_max_interval", 0644, hdev->debugfs,
|
||||
hdev, &conn_max_interval_fops);
|
||||
debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev,
|
||||
&lowpan_debugfs_fops);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -3533,6 +3533,9 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
conn->handle = __le16_to_cpu(ev->handle);
|
||||
conn->state = BT_CONNECTED;
|
||||
|
||||
if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags))
|
||||
set_bit(HCI_CONN_6LOWPAN, &conn->flags);
|
||||
|
||||
hci_conn_add_sysfs(conn);
|
||||
|
||||
hci_proto_connect_cfm(conn, ev->status);
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "smp.h"
|
||||
#include "a2mp.h"
|
||||
#include "amp.h"
|
||||
#include "6lowpan.h"
|
||||
|
||||
bool disable_ertm;
|
||||
|
||||
@@ -1468,6 +1469,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
bt_6lowpan_add_conn(conn);
|
||||
|
||||
/* Check if we have socket listening on cid */
|
||||
pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
|
||||
&hcon->src, &hcon->dst);
|
||||
@@ -7119,6 +7122,10 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
l2cap_conn_del(conn->hcon, EACCES);
|
||||
break;
|
||||
|
||||
case L2CAP_FC_6LOWPAN:
|
||||
bt_6lowpan_recv(conn, skb);
|
||||
break;
|
||||
|
||||
default:
|
||||
l2cap_data_channel(conn, cid, skb);
|
||||
break;
|
||||
@@ -7186,6 +7193,8 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
|
||||
{
|
||||
BT_DBG("hcon %p reason %d", hcon, reason);
|
||||
|
||||
bt_6lowpan_del_conn(hcon->l2cap_data);
|
||||
|
||||
l2cap_conn_del(hcon, bt_to_errno(reason));
|
||||
}
|
||||
|
||||
@@ -7467,11 +7476,14 @@ int __init l2cap_init(void)
|
||||
debugfs_create_u16("l2cap_le_default_mps", 0466, bt_debugfs,
|
||||
&le_default_mps);
|
||||
|
||||
bt_6lowpan_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void l2cap_exit(void)
|
||||
{
|
||||
bt_6lowpan_cleanup();
|
||||
debugfs_remove(l2cap_debugfs);
|
||||
l2cap_cleanup_sockets();
|
||||
}
|
||||
|
||||
@@ -147,6 +147,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
|
||||
__le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM)
|
||||
chan->sec_level = BT_SECURITY_SDP;
|
||||
break;
|
||||
case L2CAP_CHAN_RAW:
|
||||
chan->sec_level = BT_SECURITY_SDP;
|
||||
break;
|
||||
}
|
||||
|
||||
bacpy(&chan->src, &la.l2_bdaddr);
|
||||
|
||||
+66
-37
@@ -58,6 +58,7 @@ struct rfcomm_dev {
|
||||
uint modem_status;
|
||||
|
||||
struct rfcomm_dlc *dlc;
|
||||
wait_queue_head_t conn_wait;
|
||||
|
||||
struct device *tty_dev;
|
||||
|
||||
@@ -103,20 +104,60 @@ static void rfcomm_dev_destruct(struct tty_port *port)
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
struct hci_conn *conn;
|
||||
|
||||
hdev = hci_get_route(&dev->dst, &dev->src);
|
||||
if (!hdev)
|
||||
return NULL;
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
|
||||
|
||||
hci_dev_put(hdev);
|
||||
|
||||
return conn ? &conn->dev : NULL;
|
||||
}
|
||||
|
||||
/* device-specific initialization: open the dlc */
|
||||
static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty)
|
||||
{
|
||||
struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
|
||||
DEFINE_WAIT(wait);
|
||||
int err;
|
||||
|
||||
return rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
|
||||
}
|
||||
err = rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
/* we block the open until the dlc->state becomes BT_CONNECTED */
|
||||
static int rfcomm_dev_carrier_raised(struct tty_port *port)
|
||||
{
|
||||
struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port);
|
||||
while (1) {
|
||||
prepare_to_wait(&dev->conn_wait, &wait, TASK_INTERRUPTIBLE);
|
||||
|
||||
return (dev->dlc->state == BT_CONNECTED);
|
||||
if (dev->dlc->state == BT_CLOSED) {
|
||||
err = -dev->err;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dev->dlc->state == BT_CONNECTED)
|
||||
break;
|
||||
|
||||
if (signal_pending(current)) {
|
||||
err = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
|
||||
tty_unlock(tty);
|
||||
schedule();
|
||||
tty_lock(tty);
|
||||
}
|
||||
finish_wait(&dev->conn_wait, &wait);
|
||||
|
||||
if (!err)
|
||||
device_move(dev->tty_dev, rfcomm_get_device(dev),
|
||||
DPM_ORDER_DEV_AFTER_PARENT);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* device-specific cleanup: close the dlc */
|
||||
@@ -135,7 +176,6 @@ static const struct tty_port_operations rfcomm_port_ops = {
|
||||
.destruct = rfcomm_dev_destruct,
|
||||
.activate = rfcomm_dev_activate,
|
||||
.shutdown = rfcomm_dev_shutdown,
|
||||
.carrier_raised = rfcomm_dev_carrier_raised,
|
||||
};
|
||||
|
||||
static struct rfcomm_dev *__rfcomm_dev_get(int id)
|
||||
@@ -169,22 +209,6 @@ static struct rfcomm_dev *rfcomm_dev_get(int id)
|
||||
return dev;
|
||||
}
|
||||
|
||||
static struct device *rfcomm_get_device(struct rfcomm_dev *dev)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
struct hci_conn *conn;
|
||||
|
||||
hdev = hci_get_route(&dev->dst, &dev->src);
|
||||
if (!hdev)
|
||||
return NULL;
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst);
|
||||
|
||||
hci_dev_put(hdev);
|
||||
|
||||
return conn ? &conn->dev : NULL;
|
||||
}
|
||||
|
||||
static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
|
||||
@@ -258,6 +282,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc)
|
||||
|
||||
tty_port_init(&dev->port);
|
||||
dev->port.ops = &rfcomm_port_ops;
|
||||
init_waitqueue_head(&dev->conn_wait);
|
||||
|
||||
skb_queue_head_init(&dev->pending);
|
||||
|
||||
@@ -437,7 +462,8 @@ static int rfcomm_release_dev(void __user *arg)
|
||||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
if (!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
|
||||
if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
|
||||
!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
|
||||
tty_port_put(&dev->port);
|
||||
|
||||
tty_port_put(&dev->port);
|
||||
@@ -575,12 +601,9 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err)
|
||||
BT_DBG("dlc %p dev %p err %d", dlc, dev, err);
|
||||
|
||||
dev->err = err;
|
||||
if (dlc->state == BT_CONNECTED) {
|
||||
device_move(dev->tty_dev, rfcomm_get_device(dev),
|
||||
DPM_ORDER_DEV_AFTER_PARENT);
|
||||
wake_up_interruptible(&dev->conn_wait);
|
||||
|
||||
wake_up_interruptible(&dev->port.open_wait);
|
||||
} else if (dlc->state == BT_CLOSED)
|
||||
if (dlc->state == BT_CLOSED)
|
||||
tty_port_tty_hangup(&dev->port, false);
|
||||
}
|
||||
|
||||
@@ -670,10 +693,20 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
|
||||
|
||||
/* install the tty_port */
|
||||
err = tty_port_install(&dev->port, driver, tty);
|
||||
if (err)
|
||||
if (err) {
|
||||
rfcomm_tty_cleanup(tty);
|
||||
return err;
|
||||
}
|
||||
|
||||
return err;
|
||||
/* take over the tty_port reference if the port was created with the
|
||||
* flag RFCOMM_RELEASE_ONHUP. This will force the release of the port
|
||||
* when the last process closes the tty. The behaviour is expected by
|
||||
* userspace.
|
||||
*/
|
||||
if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
|
||||
tty_port_put(&dev->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp)
|
||||
@@ -1010,10 +1043,6 @@ static void rfcomm_tty_hangup(struct tty_struct *tty)
|
||||
BT_DBG("tty %p dev %p", tty, dev);
|
||||
|
||||
tty_port_hangup(&dev->port);
|
||||
|
||||
if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
|
||||
!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
|
||||
tty_port_put(&dev->port);
|
||||
}
|
||||
|
||||
static int rfcomm_tty_tiocmget(struct tty_struct *tty)
|
||||
@@ -1096,7 +1125,7 @@ int __init rfcomm_init_ttys(void)
|
||||
rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL;
|
||||
rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
|
||||
rfcomm_tty_driver->init_termios = tty_std_termios;
|
||||
rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
|
||||
rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
|
||||
rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON;
|
||||
tty_set_operations(rfcomm_tty_driver, &rfcomm_ops);
|
||||
|
||||
|
||||
+40
-756
File diff suppressed because it is too large
Load Diff
@@ -231,6 +231,61 @@
|
||||
#define LOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline,
|
||||
dest = 16 bit inline */
|
||||
#define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */
|
||||
#define LOWPAN_NHC_UDP_CS_C 0x04 /* checksum elided */
|
||||
|
||||
#ifdef DEBUG
|
||||
/* print data in line */
|
||||
static inline void raw_dump_inline(const char *caller, char *msg,
|
||||
unsigned char *buf, int len)
|
||||
{
|
||||
if (msg)
|
||||
pr_debug("%s():%s: ", caller, msg);
|
||||
|
||||
print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, buf, len, false);
|
||||
}
|
||||
|
||||
/* print data in a table format:
|
||||
*
|
||||
* addr: xx xx xx xx xx xx
|
||||
* addr: xx xx xx xx xx xx
|
||||
* ...
|
||||
*/
|
||||
static inline void raw_dump_table(const char *caller, char *msg,
|
||||
unsigned char *buf, int len)
|
||||
{
|
||||
if (msg)
|
||||
pr_debug("%s():%s:\n", caller, msg);
|
||||
|
||||
print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET, 16, 1, buf, len, false);
|
||||
}
|
||||
#else
|
||||
static inline void raw_dump_table(const char *caller, char *msg,
|
||||
unsigned char *buf, int len) { }
|
||||
static inline void raw_dump_inline(const char *caller, char *msg,
|
||||
unsigned char *buf, int len) { }
|
||||
#endif
|
||||
|
||||
static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val)
|
||||
{
|
||||
if (unlikely(!pskb_may_pull(skb, 1)))
|
||||
return -EINVAL;
|
||||
|
||||
*val = skb->data[0];
|
||||
skb_pull(skb, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val)
|
||||
{
|
||||
if (unlikely(!pskb_may_pull(skb, 2)))
|
||||
return -EINVAL;
|
||||
|
||||
*val = (skb->data[0] << 8) | skb->data[1];
|
||||
skb_pull(skb, 2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool lowpan_fetch_skb(struct sk_buff *skb,
|
||||
void *data, const unsigned int len)
|
||||
@@ -244,4 +299,21 @@ static inline bool lowpan_fetch_skb(struct sk_buff *skb,
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data,
|
||||
const size_t len)
|
||||
{
|
||||
memcpy(*hc_ptr, data, len);
|
||||
*hc_ptr += len;
|
||||
}
|
||||
|
||||
typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
|
||||
|
||||
int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
|
||||
const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
|
||||
const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
|
||||
u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
|
||||
int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
|
||||
unsigned short type, const void *_daddr,
|
||||
const void *_saddr, unsigned int len);
|
||||
|
||||
#endif /* __6LOWPAN_H__ */
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o
|
||||
obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o
|
||||
obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o 6lowpan_iphc.o
|
||||
|
||||
ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o
|
||||
af_802154-y := af_ieee802154.o raw.o dgram.o
|
||||
|
||||
+3
-1
@@ -1816,6 +1816,7 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
|
||||
return addrconf_ifid_sit(eui, dev);
|
||||
case ARPHRD_IPGRE:
|
||||
return addrconf_ifid_gre(eui, dev);
|
||||
case ARPHRD_6LOWPAN:
|
||||
case ARPHRD_IEEE802154:
|
||||
return addrconf_ifid_eui64(eui, dev);
|
||||
case ARPHRD_IEEE1394:
|
||||
@@ -2658,7 +2659,8 @@ static void addrconf_dev_config(struct net_device *dev)
|
||||
(dev->type != ARPHRD_INFINIBAND) &&
|
||||
(dev->type != ARPHRD_IEEE802154) &&
|
||||
(dev->type != ARPHRD_IEEE1394) &&
|
||||
(dev->type != ARPHRD_TUNNEL6)) {
|
||||
(dev->type != ARPHRD_TUNNEL6) &&
|
||||
(dev->type != ARPHRD_6LOWPAN)) {
|
||||
/* Alas, we support only Ethernet autoconfiguration. */
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user