mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-16 16:54:20 +08:00
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
This commit is contained in:
commit
fd29d2cdd5
@ -148,6 +148,13 @@ L: linux-scsi@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/scsi/53c700*
|
||||
|
||||
6LOWPAN GENERIC (BTLE/IEEE 802.15.4)
|
||||
M: Alexander Aring <alex.aring@gmail.com>
|
||||
L: linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers)
|
||||
L: linux-bluetooth@vger.kernel.org
|
||||
S: Maintained
|
||||
F: net/6lowpan/
|
||||
|
||||
6PACK NETWORK DRIVER FOR AX.25
|
||||
M: Andreas Koensgen <ajk@comnets.uni-bremen.de>
|
||||
L: linux-hams@vger.kernel.org
|
||||
|
@ -431,6 +431,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)
|
||||
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
|
||||
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
|
||||
|
||||
if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags))
|
||||
set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
|
||||
|
||||
if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
|
||||
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
|
||||
|
||||
@ -477,6 +480,22 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags)
|
||||
{
|
||||
unsigned long valid_flags = BIT(HCI_UART_RAW_DEVICE) |
|
||||
BIT(HCI_UART_RESET_ON_INIT) |
|
||||
BIT(HCI_UART_CREATE_AMP) |
|
||||
BIT(HCI_UART_INIT_PENDING) |
|
||||
BIT(HCI_UART_EXT_CONFIG);
|
||||
|
||||
if ((flags & ~valid_flags))
|
||||
return -EINVAL;
|
||||
|
||||
hu->hdev_flags = flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* hci_uart_tty_ioctl()
|
||||
*
|
||||
* Process IOCTL system call for the tty device.
|
||||
@ -520,14 +539,16 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
|
||||
return -EUNATCH;
|
||||
|
||||
case HCIUARTGETDEVICE:
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
|
||||
return hu->hdev->id;
|
||||
return -EUNATCH;
|
||||
|
||||
case HCIUARTSETFLAGS:
|
||||
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
|
||||
return -EBUSY;
|
||||
hu->hdev_flags = arg;
|
||||
err = hci_uart_set_flags(hu, arg);
|
||||
if (err)
|
||||
return err;
|
||||
break;
|
||||
|
||||
case HCIUARTGETFLAGS:
|
||||
|
@ -48,6 +48,7 @@
|
||||
#define HCI_UART_RESET_ON_INIT 1
|
||||
#define HCI_UART_CREATE_AMP 2
|
||||
#define HCI_UART_INIT_PENDING 3
|
||||
#define HCI_UART_EXT_CONFIG 4
|
||||
|
||||
struct hci_uart;
|
||||
|
||||
|
@ -59,7 +59,7 @@
|
||||
#include <linux/gfp.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci.h>
|
||||
#include <net/bluetooth/hci_sock.h>
|
||||
#include <net/bluetooth/rfcomm.h>
|
||||
|
||||
#include <linux/capi.h>
|
||||
|
@ -202,33 +202,6 @@ enum {
|
||||
#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \
|
||||
BIT(HCI_FAST_CONNECTABLE) | BIT(HCI_LE_ADV))
|
||||
|
||||
/* HCI ioctl defines */
|
||||
#define HCIDEVUP _IOW('H', 201, int)
|
||||
#define HCIDEVDOWN _IOW('H', 202, int)
|
||||
#define HCIDEVRESET _IOW('H', 203, int)
|
||||
#define HCIDEVRESTAT _IOW('H', 204, int)
|
||||
|
||||
#define HCIGETDEVLIST _IOR('H', 210, int)
|
||||
#define HCIGETDEVINFO _IOR('H', 211, int)
|
||||
#define HCIGETCONNLIST _IOR('H', 212, int)
|
||||
#define HCIGETCONNINFO _IOR('H', 213, int)
|
||||
#define HCIGETAUTHINFO _IOR('H', 215, int)
|
||||
|
||||
#define HCISETRAW _IOW('H', 220, int)
|
||||
#define HCISETSCAN _IOW('H', 221, int)
|
||||
#define HCISETAUTH _IOW('H', 222, int)
|
||||
#define HCISETENCRYPT _IOW('H', 223, int)
|
||||
#define HCISETPTYPE _IOW('H', 224, int)
|
||||
#define HCISETLINKPOL _IOW('H', 225, int)
|
||||
#define HCISETLINKMODE _IOW('H', 226, int)
|
||||
#define HCISETACLMTU _IOW('H', 227, int)
|
||||
#define HCISETSCOMTU _IOW('H', 228, int)
|
||||
|
||||
#define HCIBLOCKADDR _IOW('H', 230, int)
|
||||
#define HCIUNBLOCKADDR _IOW('H', 231, int)
|
||||
|
||||
#define HCIINQUIRY _IOR('H', 240, int)
|
||||
|
||||
/* HCI timeouts */
|
||||
#define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */
|
||||
#define HCI_PAIRING_TIMEOUT msecs_to_jiffies(60000) /* 60 seconds */
|
||||
@ -356,6 +329,7 @@ enum {
|
||||
#define LMP_HOST_SC 0x08
|
||||
|
||||
/* LE features */
|
||||
#define HCI_LE_ENCRYPTION 0x01
|
||||
#define HCI_LE_CONN_PARAM_REQ_PROC 0x02
|
||||
#define HCI_LE_PING 0x10
|
||||
|
||||
@ -1871,126 +1845,4 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb)
|
||||
#define hci_handle(h) (h & 0x0fff)
|
||||
#define hci_flags(h) (h >> 12)
|
||||
|
||||
/* ---- HCI Sockets ---- */
|
||||
|
||||
/* Socket options */
|
||||
#define HCI_DATA_DIR 1
|
||||
#define HCI_FILTER 2
|
||||
#define HCI_TIME_STAMP 3
|
||||
|
||||
/* CMSG flags */
|
||||
#define HCI_CMSG_DIR 0x0001
|
||||
#define HCI_CMSG_TSTAMP 0x0002
|
||||
|
||||
struct sockaddr_hci {
|
||||
sa_family_t hci_family;
|
||||
unsigned short hci_dev;
|
||||
unsigned short hci_channel;
|
||||
};
|
||||
#define HCI_DEV_NONE 0xffff
|
||||
|
||||
#define HCI_CHANNEL_RAW 0
|
||||
#define HCI_CHANNEL_USER 1
|
||||
#define HCI_CHANNEL_MONITOR 2
|
||||
#define HCI_CHANNEL_CONTROL 3
|
||||
|
||||
struct hci_filter {
|
||||
unsigned long type_mask;
|
||||
unsigned long event_mask[2];
|
||||
__le16 opcode;
|
||||
};
|
||||
|
||||
struct hci_ufilter {
|
||||
__u32 type_mask;
|
||||
__u32 event_mask[2];
|
||||
__le16 opcode;
|
||||
};
|
||||
|
||||
#define HCI_FLT_TYPE_BITS 31
|
||||
#define HCI_FLT_EVENT_BITS 63
|
||||
#define HCI_FLT_OGF_BITS 63
|
||||
#define HCI_FLT_OCF_BITS 127
|
||||
|
||||
/* ---- HCI Ioctl requests structures ---- */
|
||||
struct hci_dev_stats {
|
||||
__u32 err_rx;
|
||||
__u32 err_tx;
|
||||
__u32 cmd_tx;
|
||||
__u32 evt_rx;
|
||||
__u32 acl_tx;
|
||||
__u32 acl_rx;
|
||||
__u32 sco_tx;
|
||||
__u32 sco_rx;
|
||||
__u32 byte_rx;
|
||||
__u32 byte_tx;
|
||||
};
|
||||
|
||||
struct hci_dev_info {
|
||||
__u16 dev_id;
|
||||
char name[8];
|
||||
|
||||
bdaddr_t bdaddr;
|
||||
|
||||
__u32 flags;
|
||||
__u8 type;
|
||||
|
||||
__u8 features[8];
|
||||
|
||||
__u32 pkt_type;
|
||||
__u32 link_policy;
|
||||
__u32 link_mode;
|
||||
|
||||
__u16 acl_mtu;
|
||||
__u16 acl_pkts;
|
||||
__u16 sco_mtu;
|
||||
__u16 sco_pkts;
|
||||
|
||||
struct hci_dev_stats stat;
|
||||
};
|
||||
|
||||
struct hci_conn_info {
|
||||
__u16 handle;
|
||||
bdaddr_t bdaddr;
|
||||
__u8 type;
|
||||
__u8 out;
|
||||
__u16 state;
|
||||
__u32 link_mode;
|
||||
};
|
||||
|
||||
struct hci_dev_req {
|
||||
__u16 dev_id;
|
||||
__u32 dev_opt;
|
||||
};
|
||||
|
||||
struct hci_dev_list_req {
|
||||
__u16 dev_num;
|
||||
struct hci_dev_req dev_req[0]; /* hci_dev_req structures */
|
||||
};
|
||||
|
||||
struct hci_conn_list_req {
|
||||
__u16 dev_id;
|
||||
__u16 conn_num;
|
||||
struct hci_conn_info conn_info[0];
|
||||
};
|
||||
|
||||
struct hci_conn_info_req {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 type;
|
||||
struct hci_conn_info conn_info[0];
|
||||
};
|
||||
|
||||
struct hci_auth_info_req {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 type;
|
||||
};
|
||||
|
||||
struct hci_inquiry_req {
|
||||
__u16 dev_id;
|
||||
__u16 flags;
|
||||
__u8 lap[3];
|
||||
__u8 length;
|
||||
__u8 num_rsp;
|
||||
};
|
||||
#define IREQ_CACHE_FLUSH 0x0001
|
||||
|
||||
#endif /* __HCI_H */
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define __HCI_CORE_H
|
||||
|
||||
#include <net/bluetooth/hci.h>
|
||||
#include <net/bluetooth/hci_sock.h>
|
||||
|
||||
/* HCI priority */
|
||||
#define HCI_PRIO_MAX 7
|
||||
@ -1239,6 +1240,7 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,
|
||||
void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
|
||||
const void *param, u8 event);
|
||||
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
|
||||
bool hci_req_pending(struct hci_dev *hdev);
|
||||
|
||||
void hci_req_add_le_scan_disable(struct hci_request *req);
|
||||
void hci_req_add_le_passive_scan(struct hci_request *req);
|
||||
@ -1286,10 +1288,8 @@ void mgmt_index_added(struct hci_dev *hdev);
|
||||
void mgmt_index_removed(struct hci_dev *hdev);
|
||||
void mgmt_set_powered_failed(struct hci_dev *hdev, int err);
|
||||
int mgmt_powered(struct hci_dev *hdev, u8 powered);
|
||||
int mgmt_update_adv_data(struct hci_dev *hdev);
|
||||
void mgmt_discoverable_timeout(struct hci_dev *hdev);
|
||||
void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
|
||||
void mgmt_connectable(struct hci_dev *hdev, u8 connectable);
|
||||
void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
|
||||
void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
|
||||
bool persistent);
|
||||
void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
|
||||
@ -1350,34 +1350,6 @@ void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
|
||||
void mgmt_reenable_advertising(struct hci_dev *hdev);
|
||||
void mgmt_smp_complete(struct hci_conn *conn, bool complete);
|
||||
|
||||
/* HCI info for socket */
|
||||
#define hci_pi(sk) ((struct hci_pinfo *) sk)
|
||||
|
||||
struct hci_pinfo {
|
||||
struct bt_sock bt;
|
||||
struct hci_dev *hdev;
|
||||
struct hci_filter filter;
|
||||
__u32 cmsg_mask;
|
||||
unsigned short channel;
|
||||
};
|
||||
|
||||
/* HCI security filter */
|
||||
#define HCI_SFLT_MAX_OGF 5
|
||||
|
||||
struct hci_sec_filter {
|
||||
__u32 type_mask;
|
||||
__u32 event_mask[2];
|
||||
__u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4];
|
||||
};
|
||||
|
||||
/* ----- HCI requests ----- */
|
||||
#define HCI_REQ_DONE 0
|
||||
#define HCI_REQ_PEND 1
|
||||
#define HCI_REQ_CANCELED 2
|
||||
|
||||
#define hci_req_lock(d) mutex_lock(&d->req_lock)
|
||||
#define hci_req_unlock(d) mutex_unlock(&d->req_lock)
|
||||
|
||||
u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency,
|
||||
u16 to_multiplier);
|
||||
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand,
|
||||
|
175
include/net/bluetooth/hci_sock.h
Normal file
175
include/net/bluetooth/hci_sock.h
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
BlueZ - Bluetooth protocol stack for Linux
|
||||
Copyright (C) 2000-2001 Qualcomm Incorporated
|
||||
|
||||
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License version 2 as
|
||||
published by the Free Software Foundation;
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
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
|
||||
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
|
||||
SOFTWARE IS DISCLAIMED.
|
||||
*/
|
||||
|
||||
#ifndef __HCI_SOCK_H
|
||||
#define __HCI_SOCK_H
|
||||
|
||||
/* Socket options */
|
||||
#define HCI_DATA_DIR 1
|
||||
#define HCI_FILTER 2
|
||||
#define HCI_TIME_STAMP 3
|
||||
|
||||
/* CMSG flags */
|
||||
#define HCI_CMSG_DIR 0x0001
|
||||
#define HCI_CMSG_TSTAMP 0x0002
|
||||
|
||||
struct sockaddr_hci {
|
||||
sa_family_t hci_family;
|
||||
unsigned short hci_dev;
|
||||
unsigned short hci_channel;
|
||||
};
|
||||
#define HCI_DEV_NONE 0xffff
|
||||
|
||||
#define HCI_CHANNEL_RAW 0
|
||||
#define HCI_CHANNEL_USER 1
|
||||
#define HCI_CHANNEL_MONITOR 2
|
||||
#define HCI_CHANNEL_CONTROL 3
|
||||
|
||||
struct hci_filter {
|
||||
unsigned long type_mask;
|
||||
unsigned long event_mask[2];
|
||||
__le16 opcode;
|
||||
};
|
||||
|
||||
struct hci_ufilter {
|
||||
__u32 type_mask;
|
||||
__u32 event_mask[2];
|
||||
__le16 opcode;
|
||||
};
|
||||
|
||||
#define HCI_FLT_TYPE_BITS 31
|
||||
#define HCI_FLT_EVENT_BITS 63
|
||||
#define HCI_FLT_OGF_BITS 63
|
||||
#define HCI_FLT_OCF_BITS 127
|
||||
|
||||
/* Ioctl defines */
|
||||
#define HCIDEVUP _IOW('H', 201, int)
|
||||
#define HCIDEVDOWN _IOW('H', 202, int)
|
||||
#define HCIDEVRESET _IOW('H', 203, int)
|
||||
#define HCIDEVRESTAT _IOW('H', 204, int)
|
||||
|
||||
#define HCIGETDEVLIST _IOR('H', 210, int)
|
||||
#define HCIGETDEVINFO _IOR('H', 211, int)
|
||||
#define HCIGETCONNLIST _IOR('H', 212, int)
|
||||
#define HCIGETCONNINFO _IOR('H', 213, int)
|
||||
#define HCIGETAUTHINFO _IOR('H', 215, int)
|
||||
|
||||
#define HCISETRAW _IOW('H', 220, int)
|
||||
#define HCISETSCAN _IOW('H', 221, int)
|
||||
#define HCISETAUTH _IOW('H', 222, int)
|
||||
#define HCISETENCRYPT _IOW('H', 223, int)
|
||||
#define HCISETPTYPE _IOW('H', 224, int)
|
||||
#define HCISETLINKPOL _IOW('H', 225, int)
|
||||
#define HCISETLINKMODE _IOW('H', 226, int)
|
||||
#define HCISETACLMTU _IOW('H', 227, int)
|
||||
#define HCISETSCOMTU _IOW('H', 228, int)
|
||||
|
||||
#define HCIBLOCKADDR _IOW('H', 230, int)
|
||||
#define HCIUNBLOCKADDR _IOW('H', 231, int)
|
||||
|
||||
#define HCIINQUIRY _IOR('H', 240, int)
|
||||
|
||||
/* Ioctl requests structures */
|
||||
struct hci_dev_stats {
|
||||
__u32 err_rx;
|
||||
__u32 err_tx;
|
||||
__u32 cmd_tx;
|
||||
__u32 evt_rx;
|
||||
__u32 acl_tx;
|
||||
__u32 acl_rx;
|
||||
__u32 sco_tx;
|
||||
__u32 sco_rx;
|
||||
__u32 byte_rx;
|
||||
__u32 byte_tx;
|
||||
};
|
||||
|
||||
struct hci_dev_info {
|
||||
__u16 dev_id;
|
||||
char name[8];
|
||||
|
||||
bdaddr_t bdaddr;
|
||||
|
||||
__u32 flags;
|
||||
__u8 type;
|
||||
|
||||
__u8 features[8];
|
||||
|
||||
__u32 pkt_type;
|
||||
__u32 link_policy;
|
||||
__u32 link_mode;
|
||||
|
||||
__u16 acl_mtu;
|
||||
__u16 acl_pkts;
|
||||
__u16 sco_mtu;
|
||||
__u16 sco_pkts;
|
||||
|
||||
struct hci_dev_stats stat;
|
||||
};
|
||||
|
||||
struct hci_conn_info {
|
||||
__u16 handle;
|
||||
bdaddr_t bdaddr;
|
||||
__u8 type;
|
||||
__u8 out;
|
||||
__u16 state;
|
||||
__u32 link_mode;
|
||||
};
|
||||
|
||||
struct hci_dev_req {
|
||||
__u16 dev_id;
|
||||
__u32 dev_opt;
|
||||
};
|
||||
|
||||
struct hci_dev_list_req {
|
||||
__u16 dev_num;
|
||||
struct hci_dev_req dev_req[0]; /* hci_dev_req structures */
|
||||
};
|
||||
|
||||
struct hci_conn_list_req {
|
||||
__u16 dev_id;
|
||||
__u16 conn_num;
|
||||
struct hci_conn_info conn_info[0];
|
||||
};
|
||||
|
||||
struct hci_conn_info_req {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 type;
|
||||
struct hci_conn_info conn_info[0];
|
||||
};
|
||||
|
||||
struct hci_auth_info_req {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 type;
|
||||
};
|
||||
|
||||
struct hci_inquiry_req {
|
||||
__u16 dev_id;
|
||||
__u16 flags;
|
||||
__u8 lap[3];
|
||||
__u8 length;
|
||||
__u8 num_rsp;
|
||||
};
|
||||
#define IREQ_CACHE_FLUSH 0x0001
|
||||
|
||||
#endif /* __HCI_SOCK_H */
|
@ -134,9 +134,12 @@ struct l2cap_conninfo {
|
||||
#define L2CAP_FCS_CRC16 0x01
|
||||
|
||||
/* L2CAP fixed channels */
|
||||
#define L2CAP_FC_L2CAP 0x02
|
||||
#define L2CAP_FC_SIG_BREDR 0x02
|
||||
#define L2CAP_FC_CONNLESS 0x04
|
||||
#define L2CAP_FC_A2MP 0x08
|
||||
#define L2CAP_FC_ATT 0x10
|
||||
#define L2CAP_FC_SIG_LE 0x20
|
||||
#define L2CAP_FC_SMP_LE 0x40
|
||||
|
||||
/* L2CAP Control Field bit masks */
|
||||
#define L2CAP_CTRL_SAR 0xC000
|
||||
@ -622,11 +625,10 @@ struct l2cap_conn {
|
||||
|
||||
struct delayed_work info_timer;
|
||||
|
||||
spinlock_t lock;
|
||||
|
||||
struct sk_buff *rx_skb;
|
||||
__u32 rx_len;
|
||||
__u8 tx_ident;
|
||||
struct mutex ident_lock;
|
||||
|
||||
struct sk_buff_head pending_rx;
|
||||
struct work_struct pending_rx_work;
|
||||
|
@ -27,11 +27,6 @@
|
||||
|
||||
/* SCO defaults */
|
||||
#define SCO_DEFAULT_MTU 500
|
||||
#define SCO_DEFAULT_FLUSH_TO 0xFFFF
|
||||
|
||||
#define SCO_CONN_TIMEOUT (HZ * 40)
|
||||
#define SCO_DISCONN_TIMEOUT (HZ * 2)
|
||||
#define SCO_CONN_IDLE_TIMEOUT (HZ * 60)
|
||||
|
||||
/* SCO socket address */
|
||||
struct sockaddr_sco {
|
||||
@ -51,29 +46,4 @@ struct sco_conninfo {
|
||||
__u8 dev_class[3];
|
||||
};
|
||||
|
||||
/* ---- SCO connections ---- */
|
||||
struct sco_conn {
|
||||
struct hci_conn *hcon;
|
||||
|
||||
spinlock_t lock;
|
||||
struct sock *sk;
|
||||
|
||||
unsigned int mtu;
|
||||
};
|
||||
|
||||
#define sco_conn_lock(c) spin_lock(&c->lock);
|
||||
#define sco_conn_unlock(c) spin_unlock(&c->lock);
|
||||
|
||||
/* ----- SCO socket info ----- */
|
||||
#define sco_pi(sk) ((struct sco_pinfo *) sk)
|
||||
|
||||
struct sco_pinfo {
|
||||
struct bt_sock bt;
|
||||
bdaddr_t src;
|
||||
bdaddr_t dst;
|
||||
__u32 flags;
|
||||
__u16 setting;
|
||||
struct sco_conn *conn;
|
||||
};
|
||||
|
||||
#endif /* __SCO_H */
|
||||
|
6
net/6lowpan/Kconfig
Normal file
6
net/6lowpan/Kconfig
Normal file
@ -0,0 +1,6 @@
|
||||
config 6LOWPAN
|
||||
bool "6LoWPAN Support"
|
||||
depends on IPV6
|
||||
---help---
|
||||
This enables IPv6 over Low power Wireless Personal Area Network -
|
||||
"6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks.
|
3
net/6lowpan/Makefile
Normal file
3
net/6lowpan/Makefile
Normal file
@ -0,0 +1,3 @@
|
||||
obj-$(CONFIG_6LOWPAN) := 6lowpan.o
|
||||
|
||||
6lowpan-y := iphc.o
|
@ -214,6 +214,7 @@ source "drivers/net/appletalk/Kconfig"
|
||||
source "net/x25/Kconfig"
|
||||
source "net/lapb/Kconfig"
|
||||
source "net/phonet/Kconfig"
|
||||
source "net/6lowpan/Kconfig"
|
||||
source "net/ieee802154/Kconfig"
|
||||
source "net/mac802154/Kconfig"
|
||||
source "net/sched/Kconfig"
|
||||
|
@ -57,7 +57,8 @@ obj-$(CONFIG_CAIF) += caif/
|
||||
ifneq ($(CONFIG_DCB),)
|
||||
obj-y += dcb/
|
||||
endif
|
||||
obj-y += ieee802154/
|
||||
obj-$(CONFIG_6LOWPAN) += 6lowpan/
|
||||
obj-$(CONFIG_IEEE802154) += ieee802154/
|
||||
obj-$(CONFIG_MAC802154) += mac802154/
|
||||
|
||||
ifeq ($(CONFIG_NET),y)
|
||||
|
@ -41,8 +41,7 @@ menuconfig BT
|
||||
|
||||
config BT_6LOWPAN
|
||||
tristate "Bluetooth 6LoWPAN support"
|
||||
depends on BT && IPV6
|
||||
select 6LOWPAN_IPHC if BT_6LOWPAN
|
||||
depends on BT && 6LOWPAN
|
||||
help
|
||||
IPv6 compression over Bluetooth Low Energy.
|
||||
|
||||
|
@ -362,12 +362,6 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
|
||||
CAPIMSG_SETCONTROL(skb->data, contr);
|
||||
}
|
||||
|
||||
if (!ctrl) {
|
||||
BT_ERR("Can't find controller %d for message", session->num);
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
capi_ctr_handle_message(ctrl, appl, skb);
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,15 @@ DEFINE_RWLOCK(hci_cb_list_lock);
|
||||
/* HCI ID Numbering */
|
||||
static DEFINE_IDA(hci_index_ida);
|
||||
|
||||
/* ----- HCI requests ----- */
|
||||
|
||||
#define HCI_REQ_DONE 0
|
||||
#define HCI_REQ_PEND 1
|
||||
#define HCI_REQ_CANCELED 2
|
||||
|
||||
#define hci_req_lock(d) mutex_lock(&d->req_lock)
|
||||
#define hci_req_unlock(d) mutex_unlock(&d->req_lock)
|
||||
|
||||
/* ---- HCI notifications ---- */
|
||||
|
||||
static void hci_notify(struct hci_dev *hdev, int event)
|
||||
@ -1339,9 +1348,6 @@ static void le_setup(struct hci_request *req)
|
||||
/* Read LE Supported States */
|
||||
hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL);
|
||||
|
||||
/* Read LE Advertising Channel TX Power */
|
||||
hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
|
||||
|
||||
/* Read LE White List Size */
|
||||
hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL);
|
||||
|
||||
@ -1416,14 +1422,17 @@ static void hci_setup_event_mask(struct hci_request *req)
|
||||
/* Use a different default for LE-only devices */
|
||||
memset(events, 0, sizeof(events));
|
||||
events[0] |= 0x10; /* Disconnection Complete */
|
||||
events[0] |= 0x80; /* Encryption Change */
|
||||
events[1] |= 0x08; /* Read Remote Version Information Complete */
|
||||
events[1] |= 0x20; /* Command Complete */
|
||||
events[1] |= 0x40; /* Command Status */
|
||||
events[1] |= 0x80; /* Hardware Error */
|
||||
events[2] |= 0x04; /* Number of Completed Packets */
|
||||
events[3] |= 0x02; /* Data Buffer Overflow */
|
||||
events[5] |= 0x80; /* Encryption Key Refresh Complete */
|
||||
|
||||
if (hdev->le_features[0] & HCI_LE_ENCRYPTION) {
|
||||
events[0] |= 0x80; /* Encryption Change */
|
||||
events[5] |= 0x80; /* Encryption Key Refresh Complete */
|
||||
}
|
||||
}
|
||||
|
||||
if (lmp_inq_rssi_capable(hdev))
|
||||
@ -1476,8 +1485,6 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
|
||||
if (lmp_le_capable(hdev))
|
||||
le_setup(req);
|
||||
|
||||
hci_setup_event_mask(req);
|
||||
|
||||
/* AVM Berlin (31), aka "BlueFRITZ!", doesn't support the read
|
||||
* local supported commands HCI command.
|
||||
*/
|
||||
@ -1605,6 +1612,8 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
||||
struct hci_dev *hdev = req->hdev;
|
||||
u8 p;
|
||||
|
||||
hci_setup_event_mask(req);
|
||||
|
||||
/* Some Broadcom based Bluetooth controllers do not support the
|
||||
* Delete Stored Link Key command. They are clearly indicating its
|
||||
* absence in the bit mask of supported commands.
|
||||
@ -1635,7 +1644,10 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
||||
u8 events[8];
|
||||
|
||||
memset(events, 0, sizeof(events));
|
||||
events[0] = 0x1f;
|
||||
events[0] = 0x0f;
|
||||
|
||||
if (hdev->le_features[0] & HCI_LE_ENCRYPTION)
|
||||
events[0] |= 0x10; /* LE Long Term Key Request */
|
||||
|
||||
/* If controller supports the Connection Parameters Request
|
||||
* Link Layer Procedure, enable the corresponding event.
|
||||
@ -1648,6 +1660,11 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
|
||||
hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
|
||||
events);
|
||||
|
||||
if (hdev->commands[25] & 0x40) {
|
||||
/* Read LE Advertising Channel TX Power */
|
||||
hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL);
|
||||
}
|
||||
|
||||
hci_set_le_support(req);
|
||||
}
|
||||
|
||||
@ -2071,7 +2088,7 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data,
|
||||
}
|
||||
|
||||
/* Entry not in the cache. Add new one. */
|
||||
ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC);
|
||||
ie = kzalloc(sizeof(struct inquiry_entry), GFP_KERNEL);
|
||||
if (!ie) {
|
||||
flags |= MGMT_DEV_FOUND_CONFIRM_NAME;
|
||||
goto done;
|
||||
@ -2435,6 +2452,16 @@ int hci_dev_open(__u16 dev)
|
||||
*/
|
||||
flush_workqueue(hdev->req_workqueue);
|
||||
|
||||
/* For controllers not using the management interface and that
|
||||
* are brought up using legacy ioctl, set the HCI_PAIRABLE bit
|
||||
* so that pairing works for them. Once the management interface
|
||||
* is in use this bit will be cleared again and userspace has
|
||||
* to explicitly enable it.
|
||||
*/
|
||||
if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) &&
|
||||
!test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||
set_bit(HCI_PAIRABLE, &hdev->dev_flags);
|
||||
|
||||
err = hci_dev_do_open(hdev);
|
||||
|
||||
done:
|
||||
@ -2655,6 +2682,42 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hci_update_scan_state(struct hci_dev *hdev, u8 scan)
|
||||
{
|
||||
bool conn_changed, discov_changed;
|
||||
|
||||
BT_DBG("%s scan 0x%02x", hdev->name, scan);
|
||||
|
||||
if ((scan & SCAN_PAGE))
|
||||
conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
|
||||
&hdev->dev_flags);
|
||||
else
|
||||
conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
|
||||
&hdev->dev_flags);
|
||||
|
||||
if ((scan & SCAN_INQUIRY)) {
|
||||
discov_changed = !test_and_set_bit(HCI_DISCOVERABLE,
|
||||
&hdev->dev_flags);
|
||||
} else {
|
||||
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
|
||||
discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
|
||||
&hdev->dev_flags);
|
||||
}
|
||||
|
||||
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||
return;
|
||||
|
||||
if (conn_changed || discov_changed) {
|
||||
/* In case this was disabled through mgmt */
|
||||
set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
|
||||
|
||||
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
|
||||
mgmt_update_adv_data(hdev);
|
||||
|
||||
mgmt_new_settings(hdev);
|
||||
}
|
||||
}
|
||||
|
||||
int hci_dev_cmd(unsigned int cmd, void __user *arg)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
@ -2716,22 +2779,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg)
|
||||
err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt,
|
||||
HCI_INIT_TIMEOUT);
|
||||
|
||||
/* Ensure that the connectable state gets correctly
|
||||
* notified if the whitelist is in use.
|
||||
/* Ensure that the connectable and discoverable states
|
||||
* get correctly modified as this was a non-mgmt change.
|
||||
*/
|
||||
if (!err && !list_empty(&hdev->whitelist)) {
|
||||
bool changed;
|
||||
|
||||
if ((dr.dev_opt & SCAN_PAGE))
|
||||
changed = !test_and_set_bit(HCI_CONNECTABLE,
|
||||
&hdev->dev_flags);
|
||||
else
|
||||
changed = test_and_set_bit(HCI_CONNECTABLE,
|
||||
&hdev->dev_flags);
|
||||
|
||||
if (changed)
|
||||
mgmt_new_settings(hdev);
|
||||
}
|
||||
if (!err)
|
||||
hci_update_scan_state(hdev, dr.dev_opt);
|
||||
break;
|
||||
|
||||
case HCISETLINKPOL:
|
||||
@ -2792,14 +2844,17 @@ int hci_get_dev_list(void __user *arg)
|
||||
|
||||
read_lock(&hci_dev_list_lock);
|
||||
list_for_each_entry(hdev, &hci_dev_list, list) {
|
||||
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
||||
cancel_delayed_work(&hdev->power_off);
|
||||
unsigned long flags = hdev->flags;
|
||||
|
||||
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||
set_bit(HCI_PAIRABLE, &hdev->dev_flags);
|
||||
/* When the auto-off is configured it means the transport
|
||||
* is running, but in that case still indicate that the
|
||||
* device is actually down.
|
||||
*/
|
||||
if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
||||
flags &= ~BIT(HCI_UP);
|
||||
|
||||
(dr + n)->dev_id = hdev->id;
|
||||
(dr + n)->dev_opt = hdev->flags;
|
||||
(dr + n)->dev_opt = flags;
|
||||
|
||||
if (++n >= dev_num)
|
||||
break;
|
||||
@ -2819,6 +2874,7 @@ int hci_get_dev_info(void __user *arg)
|
||||
{
|
||||
struct hci_dev *hdev;
|
||||
struct hci_dev_info di;
|
||||
unsigned long flags;
|
||||
int err = 0;
|
||||
|
||||
if (copy_from_user(&di, arg, sizeof(di)))
|
||||
@ -2828,16 +2884,19 @@ int hci_get_dev_info(void __user *arg)
|
||||
if (!hdev)
|
||||
return -ENODEV;
|
||||
|
||||
if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
||||
cancel_delayed_work_sync(&hdev->power_off);
|
||||
|
||||
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
|
||||
set_bit(HCI_PAIRABLE, &hdev->dev_flags);
|
||||
/* When the auto-off is configured it means the transport
|
||||
* is running, but in that case still indicate that the
|
||||
* device is actually down.
|
||||
*/
|
||||
if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
|
||||
flags = hdev->flags & ~BIT(HCI_UP);
|
||||
else
|
||||
flags = hdev->flags;
|
||||
|
||||
strcpy(di.name, hdev->name);
|
||||
di.bdaddr = hdev->bdaddr;
|
||||
di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4);
|
||||
di.flags = hdev->flags;
|
||||
di.flags = flags;
|
||||
di.pkt_type = hdev->pkt_type;
|
||||
if (lmp_bredr_capable(hdev)) {
|
||||
di.acl_mtu = hdev->acl_mtu;
|
||||
@ -4390,6 +4449,11 @@ int hci_req_run(struct hci_request *req, hci_req_complete_t complete)
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool hci_req_pending(struct hci_dev *hdev)
|
||||
{
|
||||
return (hdev->req_status == HCI_REQ_PEND);
|
||||
}
|
||||
|
||||
static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode,
|
||||
u32 plen, const void *param)
|
||||
{
|
||||
|
@ -296,7 +296,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
__u8 status = *((__u8 *) skb->data);
|
||||
__u8 param;
|
||||
int old_pscan, old_iscan;
|
||||
void *sent;
|
||||
|
||||
BT_DBG("%s status 0x%2.2x", hdev->name, status);
|
||||
@ -310,32 +309,19 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (status) {
|
||||
mgmt_write_scan_failed(hdev, param, status);
|
||||
hdev->discov_timeout = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* We need to ensure that we set this back on if someone changed
|
||||
* the scan mode through a raw HCI socket.
|
||||
*/
|
||||
set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
|
||||
|
||||
old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags);
|
||||
old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags);
|
||||
|
||||
if (param & SCAN_INQUIRY) {
|
||||
if (param & SCAN_INQUIRY)
|
||||
set_bit(HCI_ISCAN, &hdev->flags);
|
||||
if (!old_iscan)
|
||||
mgmt_discoverable(hdev, 1);
|
||||
} else if (old_iscan)
|
||||
mgmt_discoverable(hdev, 0);
|
||||
else
|
||||
clear_bit(HCI_ISCAN, &hdev->flags);
|
||||
|
||||
if (param & SCAN_PAGE) {
|
||||
if (param & SCAN_PAGE)
|
||||
set_bit(HCI_PSCAN, &hdev->flags);
|
||||
if (!old_pscan)
|
||||
mgmt_connectable(hdev, 1);
|
||||
} else if (old_pscan)
|
||||
mgmt_connectable(hdev, 0);
|
||||
else
|
||||
clear_bit(HCI_ISCAN, &hdev->flags);
|
||||
|
||||
done:
|
||||
hci_dev_unlock(hdev);
|
||||
@ -3678,18 +3664,14 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
/* If we are initiators, there is no remote information yet */
|
||||
if (conn->remote_auth == 0xff) {
|
||||
cp.authentication = conn->auth_type;
|
||||
|
||||
/* Request MITM protection if our IO caps allow it
|
||||
* except for the no-bonding case.
|
||||
* conn->auth_type is not updated here since
|
||||
* that might cause the user confirmation to be
|
||||
* rejected in case the remote doesn't have the
|
||||
* IO capabilities for MITM.
|
||||
*/
|
||||
if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
|
||||
cp.authentication != HCI_AT_NO_BONDING)
|
||||
cp.authentication |= 0x01;
|
||||
conn->auth_type |= 0x01;
|
||||
|
||||
cp.authentication = conn->auth_type;
|
||||
} else {
|
||||
conn->auth_type = hci_get_auth_req(conn);
|
||||
cp.authentication = conn->auth_type;
|
||||
@ -3761,9 +3743,12 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
|
||||
rem_mitm = (conn->remote_auth & 0x01);
|
||||
|
||||
/* If we require MITM but the remote device can't provide that
|
||||
* (it has NoInputNoOutput) then reject the confirmation request
|
||||
* (it has NoInputNoOutput) then reject the confirmation
|
||||
* request. We check the security level here since it doesn't
|
||||
* necessarily match conn->auth_type.
|
||||
*/
|
||||
if (loc_mitm && conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
|
||||
if (conn->pending_sec_level > BT_SECURITY_MEDIUM &&
|
||||
conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
|
||||
BT_DBG("Rejecting request: remote device can't provide MITM");
|
||||
hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
|
||||
sizeof(ev->bdaddr), &ev->bdaddr);
|
||||
@ -4638,7 +4623,7 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
/* Received events are (currently) only needed when a request is
|
||||
* ongoing so avoid unnecessary memory allocation.
|
||||
*/
|
||||
if (hdev->req_status == HCI_REQ_PEND) {
|
||||
if (hci_req_pending(hdev)) {
|
||||
kfree_skb(hdev->recv_evt);
|
||||
hdev->recv_evt = skb_clone(skb, GFP_KERNEL);
|
||||
}
|
||||
|
@ -35,13 +35,32 @@ static atomic_t monitor_promisc = ATOMIC_INIT(0);
|
||||
|
||||
/* ----- HCI socket interface ----- */
|
||||
|
||||
/* Socket info */
|
||||
#define hci_pi(sk) ((struct hci_pinfo *) sk)
|
||||
|
||||
struct hci_pinfo {
|
||||
struct bt_sock bt;
|
||||
struct hci_dev *hdev;
|
||||
struct hci_filter filter;
|
||||
__u32 cmsg_mask;
|
||||
unsigned short channel;
|
||||
};
|
||||
|
||||
static inline int hci_test_bit(int nr, void *addr)
|
||||
{
|
||||
return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31));
|
||||
}
|
||||
|
||||
/* Security filter */
|
||||
static struct hci_sec_filter hci_sec_filter = {
|
||||
#define HCI_SFLT_MAX_OGF 5
|
||||
|
||||
struct hci_sec_filter {
|
||||
__u32 type_mask;
|
||||
__u32 event_mask[2];
|
||||
__u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4];
|
||||
};
|
||||
|
||||
static const struct hci_sec_filter hci_sec_filter = {
|
||||
/* Packet types */
|
||||
0x10,
|
||||
/* Events */
|
||||
|
@ -46,7 +46,7 @@
|
||||
bool disable_ertm;
|
||||
|
||||
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
|
||||
static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, };
|
||||
static u8 l2cap_fixed_chan[8] = { L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS, };
|
||||
|
||||
static LIST_HEAD(chan_list);
|
||||
static DEFINE_RWLOCK(chan_list_lock);
|
||||
@ -798,14 +798,14 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn)
|
||||
* 200 - 254 are used by utilities like l2ping, etc.
|
||||
*/
|
||||
|
||||
spin_lock(&conn->lock);
|
||||
mutex_lock(&conn->ident_lock);
|
||||
|
||||
if (++conn->tx_ident > 128)
|
||||
conn->tx_ident = 1;
|
||||
|
||||
id = conn->tx_ident;
|
||||
|
||||
spin_unlock(&conn->lock);
|
||||
mutex_unlock(&conn->ident_lock);
|
||||
|
||||
return id;
|
||||
}
|
||||
@ -7016,7 +7016,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon)
|
||||
conn->hs_enabled = test_bit(HCI_HS_ENABLED,
|
||||
&hcon->hdev->dev_flags);
|
||||
|
||||
spin_lock_init(&conn->lock);
|
||||
mutex_init(&conn->ident_lock);
|
||||
mutex_init(&conn->chan_lock);
|
||||
|
||||
INIT_LIST_HEAD(&conn->chan_l);
|
||||
|
@ -906,6 +906,16 @@ static void update_adv_data(struct hci_request *req)
|
||||
hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
|
||||
}
|
||||
|
||||
int mgmt_update_adv_data(struct hci_dev *hdev)
|
||||
{
|
||||
struct hci_request req;
|
||||
|
||||
hci_req_init(&req, hdev);
|
||||
update_adv_data(&req);
|
||||
|
||||
return hci_req_run(&req, NULL);
|
||||
}
|
||||
|
||||
static void create_eir(struct hci_dev *hdev, u8 *data)
|
||||
{
|
||||
u8 *ptr = data;
|
||||
@ -1743,7 +1753,7 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status)
|
||||
{
|
||||
struct pending_cmd *cmd;
|
||||
struct mgmt_mode *cp;
|
||||
bool changed;
|
||||
bool conn_changed, discov_changed;
|
||||
|
||||
BT_DBG("status 0x%02x", status);
|
||||
|
||||
@ -1760,15 +1770,23 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status)
|
||||
}
|
||||
|
||||
cp = cmd->param;
|
||||
if (cp->val)
|
||||
changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
|
||||
else
|
||||
changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
|
||||
if (cp->val) {
|
||||
conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
|
||||
&hdev->dev_flags);
|
||||
discov_changed = false;
|
||||
} else {
|
||||
conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
|
||||
&hdev->dev_flags);
|
||||
discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
|
||||
&hdev->dev_flags);
|
||||
}
|
||||
|
||||
send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
|
||||
|
||||
if (changed) {
|
||||
if (conn_changed || discov_changed) {
|
||||
new_settings(hdev, cmd->sk);
|
||||
if (discov_changed)
|
||||
mgmt_update_adv_data(hdev);
|
||||
hci_update_background_scan(hdev);
|
||||
}
|
||||
|
||||
@ -1882,8 +1900,8 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
|
||||
if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
|
||||
write_fast_connectable(&req, false);
|
||||
|
||||
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
|
||||
!test_bit(HCI_LE_ADV, &hdev->dev_flags))
|
||||
/* Update the advertising parameters if necessary */
|
||||
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
|
||||
enable_advertising(&req);
|
||||
|
||||
err = hci_req_run(&req, set_connectable_complete);
|
||||
@ -6031,88 +6049,6 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev)
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
|
||||
{
|
||||
bool changed;
|
||||
|
||||
/* Nothing needed here if there's a pending command since that
|
||||
* commands request completion callback takes care of everything
|
||||
* necessary.
|
||||
*/
|
||||
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
|
||||
return;
|
||||
|
||||
/* Powering off may clear the scan mode - don't let that interfere */
|
||||
if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
|
||||
return;
|
||||
|
||||
if (discoverable) {
|
||||
changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
|
||||
} else {
|
||||
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
|
||||
changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
struct hci_request req;
|
||||
|
||||
/* In case this change in discoverable was triggered by
|
||||
* a disabling of connectable there could be a need to
|
||||
* update the advertising flags.
|
||||
*/
|
||||
hci_req_init(&req, hdev);
|
||||
update_adv_data(&req);
|
||||
hci_req_run(&req, NULL);
|
||||
|
||||
new_settings(hdev, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
|
||||
{
|
||||
bool changed;
|
||||
|
||||
/* Nothing needed here if there's a pending command since that
|
||||
* commands request completion callback takes care of everything
|
||||
* necessary.
|
||||
*/
|
||||
if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
|
||||
return;
|
||||
|
||||
/* Powering off may clear the scan mode - don't let that interfere */
|
||||
if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
|
||||
return;
|
||||
|
||||
/* If something else than mgmt changed the page scan state we
|
||||
* can't differentiate this from a change triggered by adding
|
||||
* the first element to the whitelist. Therefore, avoid
|
||||
* incorrectly setting HCI_CONNECTABLE.
|
||||
*/
|
||||
if (connectable && !list_empty(&hdev->whitelist))
|
||||
return;
|
||||
|
||||
if (connectable)
|
||||
changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
|
||||
else
|
||||
changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
|
||||
|
||||
if (changed)
|
||||
new_settings(hdev, NULL);
|
||||
}
|
||||
|
||||
void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
|
||||
{
|
||||
u8 mgmt_err = mgmt_status(status);
|
||||
|
||||
if (scan & SCAN_PAGE)
|
||||
mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
|
||||
cmd_status_rsp, &mgmt_err);
|
||||
|
||||
if (scan & SCAN_INQUIRY)
|
||||
mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
|
||||
cmd_status_rsp, &mgmt_err);
|
||||
}
|
||||
|
||||
void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
|
||||
bool persistent)
|
||||
{
|
||||
|
@ -40,13 +40,38 @@ static struct bt_sock_list sco_sk_list = {
|
||||
.lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock)
|
||||
};
|
||||
|
||||
static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent);
|
||||
static void sco_chan_del(struct sock *sk, int err);
|
||||
/* ---- SCO connections ---- */
|
||||
struct sco_conn {
|
||||
struct hci_conn *hcon;
|
||||
|
||||
spinlock_t lock;
|
||||
struct sock *sk;
|
||||
|
||||
unsigned int mtu;
|
||||
};
|
||||
|
||||
#define sco_conn_lock(c) spin_lock(&c->lock);
|
||||
#define sco_conn_unlock(c) spin_unlock(&c->lock);
|
||||
|
||||
static void sco_sock_close(struct sock *sk);
|
||||
static void sco_sock_kill(struct sock *sk);
|
||||
|
||||
/* ----- SCO socket info ----- */
|
||||
#define sco_pi(sk) ((struct sco_pinfo *) sk)
|
||||
|
||||
struct sco_pinfo {
|
||||
struct bt_sock bt;
|
||||
bdaddr_t src;
|
||||
bdaddr_t dst;
|
||||
__u32 flags;
|
||||
__u16 setting;
|
||||
struct sco_conn *conn;
|
||||
};
|
||||
|
||||
/* ---- SCO timers ---- */
|
||||
#define SCO_CONN_TIMEOUT (HZ * 40)
|
||||
#define SCO_DISCONN_TIMEOUT (HZ * 2)
|
||||
|
||||
static void sco_sock_timeout(unsigned long arg)
|
||||
{
|
||||
struct sock *sk = (struct sock *) arg;
|
||||
@ -102,13 +127,31 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
|
||||
return conn;
|
||||
}
|
||||
|
||||
static struct sock *sco_chan_get(struct sco_conn *conn)
|
||||
/* Delete channel.
|
||||
* Must be called on the locked socket. */
|
||||
static void sco_chan_del(struct sock *sk, int err)
|
||||
{
|
||||
struct sock *sk = NULL;
|
||||
sco_conn_lock(conn);
|
||||
sk = conn->sk;
|
||||
sco_conn_unlock(conn);
|
||||
return sk;
|
||||
struct sco_conn *conn;
|
||||
|
||||
conn = sco_pi(sk)->conn;
|
||||
|
||||
BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
|
||||
|
||||
if (conn) {
|
||||
sco_conn_lock(conn);
|
||||
conn->sk = NULL;
|
||||
sco_pi(sk)->conn = NULL;
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (conn->hcon)
|
||||
hci_conn_drop(conn->hcon);
|
||||
}
|
||||
|
||||
sk->sk_state = BT_CLOSED;
|
||||
sk->sk_err = err;
|
||||
sk->sk_state_change(sk);
|
||||
|
||||
sock_set_flag(sk, SOCK_ZAPPED);
|
||||
}
|
||||
|
||||
static int sco_conn_del(struct hci_conn *hcon, int err)
|
||||
@ -122,7 +165,10 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
|
||||
BT_DBG("hcon %p conn %p, err %d", hcon, conn, err);
|
||||
|
||||
/* Kill socket */
|
||||
sk = sco_chan_get(conn);
|
||||
sco_conn_lock(conn);
|
||||
sk = conn->sk;
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (sk) {
|
||||
bh_lock_sock(sk);
|
||||
sco_sock_clear_timer(sk);
|
||||
@ -136,6 +182,17 @@ static int sco_conn_del(struct hci_conn *hcon, int err)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
|
||||
{
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
sco_pi(sk)->conn = conn;
|
||||
conn->sk = sk;
|
||||
|
||||
if (parent)
|
||||
bt_accept_enqueue(parent, sk);
|
||||
}
|
||||
|
||||
static int sco_chan_add(struct sco_conn *conn, struct sock *sk,
|
||||
struct sock *parent)
|
||||
{
|
||||
@ -240,7 +297,11 @@ static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len)
|
||||
|
||||
static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb)
|
||||
{
|
||||
struct sock *sk = sco_chan_get(conn);
|
||||
struct sock *sk;
|
||||
|
||||
sco_conn_lock(conn);
|
||||
sk = conn->sk;
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (!sk)
|
||||
goto drop;
|
||||
@ -940,44 +1001,6 @@ static int sco_sock_release(struct socket *sock)
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent)
|
||||
{
|
||||
BT_DBG("conn %p", conn);
|
||||
|
||||
sco_pi(sk)->conn = conn;
|
||||
conn->sk = sk;
|
||||
|
||||
if (parent)
|
||||
bt_accept_enqueue(parent, sk);
|
||||
}
|
||||
|
||||
/* Delete channel.
|
||||
* Must be called on the locked socket. */
|
||||
static void sco_chan_del(struct sock *sk, int err)
|
||||
{
|
||||
struct sco_conn *conn;
|
||||
|
||||
conn = sco_pi(sk)->conn;
|
||||
|
||||
BT_DBG("sk %p, conn %p, err %d", sk, conn, err);
|
||||
|
||||
if (conn) {
|
||||
sco_conn_lock(conn);
|
||||
conn->sk = NULL;
|
||||
sco_pi(sk)->conn = NULL;
|
||||
sco_conn_unlock(conn);
|
||||
|
||||
if (conn->hcon)
|
||||
hci_conn_drop(conn->hcon);
|
||||
}
|
||||
|
||||
sk->sk_state = BT_CLOSED;
|
||||
sk->sk_err = err;
|
||||
sk->sk_state_change(sk);
|
||||
|
||||
sock_set_flag(sk, SOCK_ZAPPED);
|
||||
}
|
||||
|
||||
static void sco_conn_ready(struct sco_conn *conn)
|
||||
{
|
||||
struct sock *parent;
|
||||
|
@ -391,10 +391,12 @@ static const u8 gen_method[5][5] = {
|
||||
|
||||
static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io)
|
||||
{
|
||||
/* If either side has unknown io_caps, use JUST WORKS */
|
||||
/* If either side has unknown io_caps, use JUST_CFM (which gets
|
||||
* converted later to JUST_WORKS if we're initiators.
|
||||
*/
|
||||
if (local_io > SMP_IO_KEYBOARD_DISPLAY ||
|
||||
remote_io > SMP_IO_KEYBOARD_DISPLAY)
|
||||
return JUST_WORKS;
|
||||
return JUST_CFM;
|
||||
|
||||
return gen_method[remote_io][local_io];
|
||||
}
|
||||
@ -414,17 +416,17 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth,
|
||||
|
||||
BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io);
|
||||
|
||||
/* If neither side wants MITM, use JUST WORKS */
|
||||
/* Otherwise, look up method from the table */
|
||||
/* If neither side wants MITM, either "just" confirm an incoming
|
||||
* request or use just-works for outgoing ones. The JUST_CFM
|
||||
* will be converted to JUST_WORKS if necessary later in this
|
||||
* function. If either side has MITM look up the method from the
|
||||
* table.
|
||||
*/
|
||||
if (!(auth & SMP_AUTH_MITM))
|
||||
method = JUST_WORKS;
|
||||
method = JUST_CFM;
|
||||
else
|
||||
method = get_auth_method(smp, local_io, remote_io);
|
||||
|
||||
/* If not bonding, don't ask user to confirm a Zero TK */
|
||||
if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM)
|
||||
method = JUST_WORKS;
|
||||
|
||||
/* Don't confirm locally initiated pairing attempts */
|
||||
if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
|
||||
method = JUST_WORKS;
|
||||
@ -674,6 +676,7 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
|
||||
static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
{
|
||||
struct smp_cmd_pairing rsp, *req = (void *) skb->data;
|
||||
struct hci_dev *hdev = conn->hcon->hdev;
|
||||
struct smp_chan *smp;
|
||||
u8 key_size, auth, sec_level;
|
||||
int ret;
|
||||
@ -694,6 +697,10 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
if (!smp)
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags) &&
|
||||
(req->auth_req & SMP_AUTH_BONDING))
|
||||
return SMP_PAIRING_NOTSUPP;
|
||||
|
||||
smp->preq[0] = SMP_CMD_PAIRING_REQ;
|
||||
memcpy(&smp->preq[1], req, sizeof(*req));
|
||||
skb_pull(skb, sizeof(*req));
|
||||
@ -733,8 +740,6 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
if (ret)
|
||||
return SMP_UNSPECIFIED;
|
||||
|
||||
clear_bit(SMP_FLAG_INITIATOR, &smp->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -871,9 +876,12 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
|
||||
/* If we're encrypted with an STK always claim insufficient
|
||||
* security. This way we allow the connection to be re-encrypted
|
||||
* with an LTK, even if the LTK provides the same level of
|
||||
* security.
|
||||
* security. Only exception is if we don't have an LTK (e.g.
|
||||
* because of key distribution bits).
|
||||
*/
|
||||
if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags))
|
||||
if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
|
||||
hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
|
||||
hcon->out))
|
||||
return false;
|
||||
|
||||
if (hcon->sec_level >= sec_level)
|
||||
@ -911,6 +919,10 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags))
|
||||
return 0;
|
||||
|
||||
if (!test_bit(HCI_PAIRABLE, &hcon->hdev->dev_flags) &&
|
||||
(rp->auth_req & SMP_AUTH_BONDING))
|
||||
return SMP_PAIRING_NOTSUPP;
|
||||
|
||||
smp = smp_chan_create(conn);
|
||||
if (!smp)
|
||||
return SMP_UNSPECIFIED;
|
||||
@ -925,8 +937,6 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
|
||||
|
||||
smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp);
|
||||
|
||||
clear_bit(SMP_FLAG_INITIATOR, &smp->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -12,13 +12,6 @@ config IEEE802154
|
||||
|
||||
config IEEE802154_6LOWPAN
|
||||
tristate "6lowpan support over IEEE 802.15.4"
|
||||
depends on IEEE802154 && IPV6
|
||||
select 6LOWPAN_IPHC
|
||||
depends on IEEE802154 && 6LOWPAN
|
||||
---help---
|
||||
IPv6 compression over IEEE 802.15.4.
|
||||
|
||||
config 6LOWPAN_IPHC
|
||||
tristate
|
||||
---help---
|
||||
6lowpan compression code which is shared between IEEE 802.15.4 and Bluetooth
|
||||
stacks.
|
||||
|
@ -1,8 +1,7 @@
|
||||
obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o
|
||||
obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o
|
||||
obj-$(CONFIG_6LOWPAN_IPHC) += 6lowpan_iphc.o
|
||||
obj-$(CONFIG_IEEE802154_6LOWPAN) += ieee802154_6lowpan.o
|
||||
|
||||
6lowpan-y := 6lowpan_rtnl.o reassembly.o
|
||||
ieee802154_6lowpan-y := 6lowpan_rtnl.o reassembly.o
|
||||
ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o \
|
||||
header_ops.o
|
||||
af_802154-y := af_ieee802154.o raw.o dgram.o
|
||||
|
Loading…
Reference in New Issue
Block a user