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 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/padovan/bluetooth-next-2.6
This commit is contained in:
@@ -71,6 +71,9 @@ static struct usb_device_id btusb_table[] = {
|
||||
/* Apple MacBookAir3,1, MacBookAir3,2 */
|
||||
{ USB_DEVICE(0x05ac, 0x821b) },
|
||||
|
||||
/* Apple MacBookPro8,2 */
|
||||
{ USB_DEVICE(0x05ac, 0x821a) },
|
||||
|
||||
/* AVM BlueFRITZ! USB v2.0 */
|
||||
{ USB_DEVICE(0x057c, 0x3800) },
|
||||
|
||||
@@ -690,7 +693,8 @@ static int btusb_send_frame(struct sk_buff *skb)
|
||||
break;
|
||||
|
||||
case HCI_ACLDATA_PKT:
|
||||
if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1)
|
||||
if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 &&
|
||||
hdev->conn_hash.le_num < 1))
|
||||
return -ENODEV;
|
||||
|
||||
urb = usb_alloc_urb(0, GFP_ATOMIC);
|
||||
|
||||
@@ -84,6 +84,8 @@ enum {
|
||||
HCI_SERVICE_CACHE,
|
||||
HCI_LINK_KEYS,
|
||||
HCI_DEBUG_KEYS,
|
||||
|
||||
HCI_RESET,
|
||||
};
|
||||
|
||||
/* HCI ioctl defines */
|
||||
@@ -426,6 +428,18 @@ struct hci_rp_user_confirm_reply {
|
||||
|
||||
#define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d
|
||||
|
||||
#define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430
|
||||
struct hci_cp_remote_oob_data_reply {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 hash[16];
|
||||
__u8 randomizer[16];
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_REMOTE_OOB_DATA_NEG_REPLY 0x0433
|
||||
struct hci_cp_remote_oob_data_neg_reply {
|
||||
bdaddr_t bdaddr;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_IO_CAPABILITY_NEG_REPLY 0x0434
|
||||
struct hci_cp_io_capability_neg_reply {
|
||||
bdaddr_t bdaddr;
|
||||
@@ -535,15 +549,17 @@ struct hci_cp_delete_stored_link_key {
|
||||
__u8 delete_all;
|
||||
} __packed;
|
||||
|
||||
#define HCI_MAX_NAME_LENGTH 248
|
||||
|
||||
#define HCI_OP_WRITE_LOCAL_NAME 0x0c13
|
||||
struct hci_cp_write_local_name {
|
||||
__u8 name[248];
|
||||
__u8 name[HCI_MAX_NAME_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_LOCAL_NAME 0x0c14
|
||||
struct hci_rp_read_local_name {
|
||||
__u8 status;
|
||||
__u8 name[248];
|
||||
__u8 name[HCI_MAX_NAME_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_WRITE_CA_TIMEOUT 0x0c16
|
||||
@@ -600,6 +616,14 @@ struct hci_cp_host_buffer_size {
|
||||
|
||||
#define HCI_OP_WRITE_INQUIRY_MODE 0x0c45
|
||||
|
||||
#define HCI_MAX_EIR_LENGTH 240
|
||||
|
||||
#define HCI_OP_WRITE_EIR 0x0c52
|
||||
struct hci_cp_write_eir {
|
||||
uint8_t fec;
|
||||
uint8_t data[HCI_MAX_EIR_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_SSP_MODE 0x0c55
|
||||
struct hci_rp_read_ssp_mode {
|
||||
__u8 status;
|
||||
@@ -611,6 +635,13 @@ struct hci_cp_write_ssp_mode {
|
||||
__u8 mode;
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_LOCAL_OOB_DATA 0x0c57
|
||||
struct hci_rp_read_local_oob_data {
|
||||
__u8 status;
|
||||
__u8 hash[16];
|
||||
__u8 randomizer[16];
|
||||
} __packed;
|
||||
|
||||
#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58
|
||||
|
||||
#define HCI_OP_READ_LOCAL_VERSION 0x1001
|
||||
@@ -745,7 +776,7 @@ struct hci_ev_auth_complete {
|
||||
struct hci_ev_remote_name {
|
||||
__u8 status;
|
||||
bdaddr_t bdaddr;
|
||||
__u8 name[248];
|
||||
__u8 name[HCI_MAX_NAME_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_ENCRYPT_CHANGE 0x08
|
||||
@@ -953,6 +984,11 @@ struct hci_ev_user_confirm_req {
|
||||
__le32 passkey;
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35
|
||||
struct hci_ev_remote_oob_data_request {
|
||||
bdaddr_t bdaddr;
|
||||
} __packed;
|
||||
|
||||
#define HCI_EV_SIMPLE_PAIR_COMPLETE 0x36
|
||||
struct hci_ev_simple_pair_complete {
|
||||
__u8 status;
|
||||
|
||||
@@ -82,6 +82,13 @@ struct link_key {
|
||||
u8 pin_len;
|
||||
};
|
||||
|
||||
struct oob_data {
|
||||
struct list_head list;
|
||||
bdaddr_t bdaddr;
|
||||
u8 hash[16];
|
||||
u8 randomizer[16];
|
||||
};
|
||||
|
||||
#define NUM_REASSEMBLY 4
|
||||
struct hci_dev {
|
||||
struct list_head list;
|
||||
@@ -94,7 +101,8 @@ struct hci_dev {
|
||||
__u8 bus;
|
||||
__u8 dev_type;
|
||||
bdaddr_t bdaddr;
|
||||
__u8 dev_name[248];
|
||||
__u8 dev_name[HCI_MAX_NAME_LENGTH];
|
||||
__u8 eir[HCI_MAX_EIR_LENGTH];
|
||||
__u8 dev_class[3];
|
||||
__u8 major_class;
|
||||
__u8 minor_class;
|
||||
@@ -169,6 +177,8 @@ struct hci_dev {
|
||||
|
||||
struct list_head link_keys;
|
||||
|
||||
struct list_head remote_oob_data;
|
||||
|
||||
struct hci_dev_stats stat;
|
||||
|
||||
struct sk_buff_head driver_init;
|
||||
@@ -505,6 +515,13 @@ int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
|
||||
u8 *key, u8 type, u8 pin_len);
|
||||
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
||||
|
||||
int hci_remote_oob_data_clear(struct hci_dev *hdev);
|
||||
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
|
||||
bdaddr_t *bdaddr);
|
||||
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
|
||||
u8 *randomizer);
|
||||
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
|
||||
|
||||
void hci_del_off_timer(struct hci_dev *hdev);
|
||||
|
||||
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
|
||||
@@ -767,6 +784,12 @@ int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
|
||||
int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr,
|
||||
u8 status);
|
||||
int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status);
|
||||
int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status);
|
||||
int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
|
||||
u8 status);
|
||||
int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
|
||||
u8 *eir);
|
||||
int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
|
||||
|
||||
/* HCI info for socket */
|
||||
#define hci_pi(sk) ((struct hci_pinfo *) sk)
|
||||
|
||||
@@ -280,7 +280,6 @@ struct l2cap_conn_param_update_rsp {
|
||||
struct l2cap_chan_list {
|
||||
struct sock *head;
|
||||
rwlock_t lock;
|
||||
long num;
|
||||
};
|
||||
|
||||
struct l2cap_conn {
|
||||
@@ -302,7 +301,6 @@ struct l2cap_conn {
|
||||
|
||||
struct sk_buff *rx_skb;
|
||||
__u32 rx_len;
|
||||
__u8 rx_ident;
|
||||
__u8 tx_ident;
|
||||
|
||||
__u8 disc_reason;
|
||||
|
||||
@@ -41,6 +41,10 @@ struct mgmt_rp_read_index_list {
|
||||
__le16 index[0];
|
||||
} __packed;
|
||||
|
||||
/* Reserve one extra byte for names in management messages so that they
|
||||
* are always guaranteed to be nul-terminated */
|
||||
#define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1)
|
||||
|
||||
#define MGMT_OP_READ_INFO 0x0004
|
||||
struct mgmt_rp_read_info {
|
||||
__u8 type;
|
||||
@@ -55,6 +59,7 @@ struct mgmt_rp_read_info {
|
||||
__u16 manufacturer;
|
||||
__u8 hci_ver;
|
||||
__u16 hci_rev;
|
||||
__u8 name[MGMT_MAX_NAME_LENGTH];
|
||||
} __packed;
|
||||
|
||||
struct mgmt_mode {
|
||||
@@ -167,6 +172,29 @@ struct mgmt_rp_user_confirm_reply {
|
||||
|
||||
#define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016
|
||||
|
||||
#define MGMT_OP_SET_LOCAL_NAME 0x0017
|
||||
struct mgmt_cp_set_local_name {
|
||||
__u8 name[MGMT_MAX_NAME_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018
|
||||
struct mgmt_rp_read_local_oob_data {
|
||||
__u8 hash[16];
|
||||
__u8 randomizer[16];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0019
|
||||
struct mgmt_cp_add_remote_oob_data {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 hash[16];
|
||||
__u8 randomizer[16];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x001A
|
||||
struct mgmt_cp_remove_remote_oob_data {
|
||||
bdaddr_t bdaddr;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_CMD_COMPLETE 0x0001
|
||||
struct mgmt_ev_cmd_complete {
|
||||
__le16 opcode;
|
||||
@@ -234,3 +262,22 @@ struct mgmt_ev_auth_failed {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 status;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_LOCAL_NAME_CHANGED 0x0011
|
||||
struct mgmt_ev_local_name_changed {
|
||||
__u8 name[MGMT_MAX_NAME_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_DEVICE_FOUND 0x0012
|
||||
struct mgmt_ev_device_found {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 dev_class[3];
|
||||
__s8 rssi;
|
||||
__u8 eir[HCI_MAX_EIR_LENGTH];
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_REMOTE_NAME 0x0013
|
||||
struct mgmt_ev_remote_name {
|
||||
bdaddr_t bdaddr;
|
||||
__u8 name[MGMT_MAX_NAME_LENGTH];
|
||||
} __packed;
|
||||
|
||||
+64
-64
@@ -23,88 +23,88 @@
|
||||
#include <linux/crc32.h>
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
|
||||
// Limits
|
||||
#define BNEP_MAX_PROTO_FILTERS 5
|
||||
#define BNEP_MAX_MULTICAST_FILTERS 20
|
||||
/* Limits */
|
||||
#define BNEP_MAX_PROTO_FILTERS 5
|
||||
#define BNEP_MAX_MULTICAST_FILTERS 20
|
||||
|
||||
// UUIDs
|
||||
#define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB
|
||||
#define BNEP_UUID16 0x02
|
||||
#define BNEP_UUID32 0x04
|
||||
#define BNEP_UUID128 0x16
|
||||
/* UUIDs */
|
||||
#define BNEP_BASE_UUID 0x0000000000001000800000805F9B34FB
|
||||
#define BNEP_UUID16 0x02
|
||||
#define BNEP_UUID32 0x04
|
||||
#define BNEP_UUID128 0x16
|
||||
|
||||
#define BNEP_SVC_PANU 0x1115
|
||||
#define BNEP_SVC_NAP 0x1116
|
||||
#define BNEP_SVC_GN 0x1117
|
||||
#define BNEP_SVC_PANU 0x1115
|
||||
#define BNEP_SVC_NAP 0x1116
|
||||
#define BNEP_SVC_GN 0x1117
|
||||
|
||||
// Packet types
|
||||
#define BNEP_GENERAL 0x00
|
||||
#define BNEP_CONTROL 0x01
|
||||
#define BNEP_COMPRESSED 0x02
|
||||
#define BNEP_COMPRESSED_SRC_ONLY 0x03
|
||||
#define BNEP_COMPRESSED_DST_ONLY 0x04
|
||||
/* Packet types */
|
||||
#define BNEP_GENERAL 0x00
|
||||
#define BNEP_CONTROL 0x01
|
||||
#define BNEP_COMPRESSED 0x02
|
||||
#define BNEP_COMPRESSED_SRC_ONLY 0x03
|
||||
#define BNEP_COMPRESSED_DST_ONLY 0x04
|
||||
|
||||
// Control types
|
||||
#define BNEP_CMD_NOT_UNDERSTOOD 0x00
|
||||
#define BNEP_SETUP_CONN_REQ 0x01
|
||||
#define BNEP_SETUP_CONN_RSP 0x02
|
||||
#define BNEP_FILTER_NET_TYPE_SET 0x03
|
||||
#define BNEP_FILTER_NET_TYPE_RSP 0x04
|
||||
#define BNEP_FILTER_MULTI_ADDR_SET 0x05
|
||||
#define BNEP_FILTER_MULTI_ADDR_RSP 0x06
|
||||
/* Control types */
|
||||
#define BNEP_CMD_NOT_UNDERSTOOD 0x00
|
||||
#define BNEP_SETUP_CONN_REQ 0x01
|
||||
#define BNEP_SETUP_CONN_RSP 0x02
|
||||
#define BNEP_FILTER_NET_TYPE_SET 0x03
|
||||
#define BNEP_FILTER_NET_TYPE_RSP 0x04
|
||||
#define BNEP_FILTER_MULTI_ADDR_SET 0x05
|
||||
#define BNEP_FILTER_MULTI_ADDR_RSP 0x06
|
||||
|
||||
// Extension types
|
||||
#define BNEP_EXT_CONTROL 0x00
|
||||
/* Extension types */
|
||||
#define BNEP_EXT_CONTROL 0x00
|
||||
|
||||
// Response messages
|
||||
#define BNEP_SUCCESS 0x00
|
||||
/* Response messages */
|
||||
#define BNEP_SUCCESS 0x00
|
||||
|
||||
#define BNEP_CONN_INVALID_DST 0x01
|
||||
#define BNEP_CONN_INVALID_SRC 0x02
|
||||
#define BNEP_CONN_INVALID_SVC 0x03
|
||||
#define BNEP_CONN_NOT_ALLOWED 0x04
|
||||
#define BNEP_CONN_INVALID_DST 0x01
|
||||
#define BNEP_CONN_INVALID_SRC 0x02
|
||||
#define BNEP_CONN_INVALID_SVC 0x03
|
||||
#define BNEP_CONN_NOT_ALLOWED 0x04
|
||||
|
||||
#define BNEP_FILTER_UNSUPPORTED_REQ 0x01
|
||||
#define BNEP_FILTER_INVALID_RANGE 0x02
|
||||
#define BNEP_FILTER_INVALID_MCADDR 0x02
|
||||
#define BNEP_FILTER_LIMIT_REACHED 0x03
|
||||
#define BNEP_FILTER_DENIED_SECURITY 0x04
|
||||
#define BNEP_FILTER_UNSUPPORTED_REQ 0x01
|
||||
#define BNEP_FILTER_INVALID_RANGE 0x02
|
||||
#define BNEP_FILTER_INVALID_MCADDR 0x02
|
||||
#define BNEP_FILTER_LIMIT_REACHED 0x03
|
||||
#define BNEP_FILTER_DENIED_SECURITY 0x04
|
||||
|
||||
// L2CAP settings
|
||||
#define BNEP_MTU 1691
|
||||
#define BNEP_PSM 0x0f
|
||||
#define BNEP_FLUSH_TO 0xffff
|
||||
#define BNEP_CONNECT_TO 15
|
||||
#define BNEP_FILTER_TO 15
|
||||
/* L2CAP settings */
|
||||
#define BNEP_MTU 1691
|
||||
#define BNEP_PSM 0x0f
|
||||
#define BNEP_FLUSH_TO 0xffff
|
||||
#define BNEP_CONNECT_TO 15
|
||||
#define BNEP_FILTER_TO 15
|
||||
|
||||
// Headers
|
||||
#define BNEP_TYPE_MASK 0x7f
|
||||
#define BNEP_EXT_HEADER 0x80
|
||||
/* Headers */
|
||||
#define BNEP_TYPE_MASK 0x7f
|
||||
#define BNEP_EXT_HEADER 0x80
|
||||
|
||||
struct bnep_setup_conn_req {
|
||||
__u8 type;
|
||||
__u8 ctrl;
|
||||
__u8 uuid_size;
|
||||
__u8 service[0];
|
||||
__u8 type;
|
||||
__u8 ctrl;
|
||||
__u8 uuid_size;
|
||||
__u8 service[0];
|
||||
} __packed;
|
||||
|
||||
struct bnep_set_filter_req {
|
||||
__u8 type;
|
||||
__u8 ctrl;
|
||||
__u8 type;
|
||||
__u8 ctrl;
|
||||
__be16 len;
|
||||
__u8 list[0];
|
||||
__u8 list[0];
|
||||
} __packed;
|
||||
|
||||
struct bnep_control_rsp {
|
||||
__u8 type;
|
||||
__u8 ctrl;
|
||||
__u8 type;
|
||||
__u8 ctrl;
|
||||
__be16 resp;
|
||||
} __packed;
|
||||
|
||||
struct bnep_ext_hdr {
|
||||
__u8 type;
|
||||
__u8 len;
|
||||
__u8 data[0];
|
||||
__u8 type;
|
||||
__u8 len;
|
||||
__u8 data[0];
|
||||
} __packed;
|
||||
|
||||
/* BNEP ioctl defines */
|
||||
@@ -114,10 +114,10 @@ struct bnep_ext_hdr {
|
||||
#define BNEPGETCONNINFO _IOR('B', 211, int)
|
||||
|
||||
struct bnep_connadd_req {
|
||||
int sock; // Connected socket
|
||||
int sock; /* Connected socket */
|
||||
__u32 flags;
|
||||
__u16 role;
|
||||
char device[16]; // Name of the Ethernet device
|
||||
char device[16]; /* Name of the Ethernet device */
|
||||
};
|
||||
|
||||
struct bnep_conndel_req {
|
||||
@@ -148,14 +148,14 @@ int bnep_del_connection(struct bnep_conndel_req *req);
|
||||
int bnep_get_connlist(struct bnep_connlist_req *req);
|
||||
int bnep_get_conninfo(struct bnep_conninfo *ci);
|
||||
|
||||
// BNEP sessions
|
||||
/* BNEP sessions */
|
||||
struct bnep_session {
|
||||
struct list_head list;
|
||||
|
||||
unsigned int role;
|
||||
unsigned long state;
|
||||
unsigned long flags;
|
||||
atomic_t killed;
|
||||
struct task_struct *task;
|
||||
|
||||
struct ethhdr eh;
|
||||
struct msghdr msg;
|
||||
@@ -173,7 +173,7 @@ void bnep_sock_cleanup(void);
|
||||
|
||||
static inline int bnep_mc_hash(__u8 *addr)
|
||||
{
|
||||
return (crc32_be(~0, addr, ETH_ALEN) >> 26);
|
||||
return crc32_be(~0, addr, ETH_ALEN) >> 26;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+37
-34
@@ -36,6 +36,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <linux/socket.h>
|
||||
@@ -131,7 +132,8 @@ static int bnep_ctrl_set_netfilter(struct bnep_session *s, __be16 *data, int len
|
||||
return -EILSEQ;
|
||||
|
||||
n = get_unaligned_be16(data);
|
||||
data++; len -= 2;
|
||||
data++;
|
||||
len -= 2;
|
||||
|
||||
if (len < n)
|
||||
return -EILSEQ;
|
||||
@@ -176,7 +178,8 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
|
||||
return -EILSEQ;
|
||||
|
||||
n = get_unaligned_be16(data);
|
||||
data += 2; len -= 2;
|
||||
data += 2;
|
||||
len -= 2;
|
||||
|
||||
if (len < n)
|
||||
return -EILSEQ;
|
||||
@@ -187,6 +190,8 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
|
||||
n /= (ETH_ALEN * 2);
|
||||
|
||||
if (n > 0) {
|
||||
int i;
|
||||
|
||||
s->mc_filter = 0;
|
||||
|
||||
/* Always send broadcast */
|
||||
@@ -196,18 +201,22 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
|
||||
for (; n > 0; n--) {
|
||||
u8 a1[6], *a2;
|
||||
|
||||
memcpy(a1, data, ETH_ALEN); data += ETH_ALEN;
|
||||
a2 = data; data += ETH_ALEN;
|
||||
memcpy(a1, data, ETH_ALEN);
|
||||
data += ETH_ALEN;
|
||||
a2 = data;
|
||||
data += ETH_ALEN;
|
||||
|
||||
BT_DBG("mc filter %s -> %s",
|
||||
batostr((void *) a1), batostr((void *) a2));
|
||||
|
||||
#define INCA(a) { int i = 5; while (i >=0 && ++a[i--] == 0); }
|
||||
|
||||
/* Iterate from a1 to a2 */
|
||||
set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
|
||||
while (memcmp(a1, a2, 6) < 0 && s->mc_filter != ~0LL) {
|
||||
INCA(a1);
|
||||
/* Increment a1 */
|
||||
i = 5;
|
||||
while (i >= 0 && ++a1[i--] == 0)
|
||||
;
|
||||
|
||||
set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter);
|
||||
}
|
||||
}
|
||||
@@ -227,7 +236,8 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
|
||||
u8 cmd = *(u8 *)data;
|
||||
int err = 0;
|
||||
|
||||
data++; len--;
|
||||
data++;
|
||||
len--;
|
||||
|
||||
switch (cmd) {
|
||||
case BNEP_CMD_NOT_UNDERSTOOD:
|
||||
@@ -302,7 +312,6 @@ static u8 __bnep_rx_hlen[] = {
|
||||
ETH_ALEN + 2, /* BNEP_COMPRESSED_SRC_ONLY */
|
||||
ETH_ALEN + 2 /* BNEP_COMPRESSED_DST_ONLY */
|
||||
};
|
||||
#define BNEP_RX_TYPES (sizeof(__bnep_rx_hlen) - 1)
|
||||
|
||||
static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
|
||||
{
|
||||
@@ -312,9 +321,10 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
|
||||
|
||||
dev->stats.rx_bytes += skb->len;
|
||||
|
||||
type = *(u8 *) skb->data; skb_pull(skb, 1);
|
||||
type = *(u8 *) skb->data;
|
||||
skb_pull(skb, 1);
|
||||
|
||||
if ((type & BNEP_TYPE_MASK) > BNEP_RX_TYPES)
|
||||
if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
|
||||
goto badframe;
|
||||
|
||||
if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
|
||||
@@ -367,14 +377,14 @@ static inline int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
|
||||
|
||||
case BNEP_COMPRESSED_DST_ONLY:
|
||||
memcpy(__skb_put(nskb, ETH_ALEN), skb_mac_header(skb),
|
||||
ETH_ALEN);
|
||||
ETH_ALEN);
|
||||
memcpy(__skb_put(nskb, ETH_ALEN + 2), s->eh.h_source,
|
||||
ETH_ALEN + 2);
|
||||
ETH_ALEN + 2);
|
||||
break;
|
||||
|
||||
case BNEP_GENERAL:
|
||||
memcpy(__skb_put(nskb, ETH_ALEN * 2), skb_mac_header(skb),
|
||||
ETH_ALEN * 2);
|
||||
ETH_ALEN * 2);
|
||||
put_unaligned(s->eh.h_proto, (__be16 *) __skb_put(nskb, 2));
|
||||
break;
|
||||
}
|
||||
@@ -470,15 +480,14 @@ static int bnep_session(void *arg)
|
||||
|
||||
BT_DBG("");
|
||||
|
||||
daemonize("kbnepd %s", dev->name);
|
||||
set_user_nice(current, -15);
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(sk_sleep(sk), &wait);
|
||||
while (!atomic_read(&s->killed)) {
|
||||
while (!kthread_should_stop()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
// RX
|
||||
/* RX */
|
||||
while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
|
||||
skb_orphan(skb);
|
||||
bnep_rx_frame(s, skb);
|
||||
@@ -487,7 +496,7 @@ static int bnep_session(void *arg)
|
||||
if (sk->sk_state != BT_CONNECTED)
|
||||
break;
|
||||
|
||||
// TX
|
||||
/* TX */
|
||||
while ((skb = skb_dequeue(&sk->sk_write_queue)))
|
||||
if (bnep_tx_frame(s, skb))
|
||||
break;
|
||||
@@ -555,8 +564,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
|
||||
|
||||
/* session struct allocated as private part of net_device */
|
||||
dev = alloc_netdev(sizeof(struct bnep_session),
|
||||
(*req->device) ? req->device : "bnep%d",
|
||||
bnep_net_setup);
|
||||
(*req->device) ? req->device : "bnep%d",
|
||||
bnep_net_setup);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -571,7 +580,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
|
||||
s = netdev_priv(dev);
|
||||
|
||||
/* This is rx header therefore addresses are swapped.
|
||||
* ie eh.h_dest is our local address. */
|
||||
* ie. eh.h_dest is our local address. */
|
||||
memcpy(s->eh.h_dest, &src, ETH_ALEN);
|
||||
memcpy(s->eh.h_source, &dst, ETH_ALEN);
|
||||
memcpy(dev->dev_addr, s->eh.h_dest, ETH_ALEN);
|
||||
@@ -597,17 +606,17 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
|
||||
SET_NETDEV_DEVTYPE(dev, &bnep_type);
|
||||
|
||||
err = register_netdev(dev);
|
||||
if (err) {
|
||||
if (err)
|
||||
goto failed;
|
||||
}
|
||||
|
||||
__bnep_link_session(s);
|
||||
|
||||
err = kernel_thread(bnep_session, s, CLONE_KERNEL);
|
||||
if (err < 0) {
|
||||
s->task = kthread_run(bnep_session, s, "kbnepd %s", dev->name);
|
||||
if (IS_ERR(s->task)) {
|
||||
/* Session thread start failed, gotta cleanup. */
|
||||
unregister_netdev(dev);
|
||||
__bnep_unlink_session(s);
|
||||
err = PTR_ERR(s->task);
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@@ -631,15 +640,9 @@ int bnep_del_connection(struct bnep_conndel_req *req)
|
||||
down_read(&bnep_session_sem);
|
||||
|
||||
s = __bnep_get_session(req->dst);
|
||||
if (s) {
|
||||
/* Wakeup user-space which is polling for socket errors.
|
||||
* This is temporary hack until we have shutdown in L2CAP */
|
||||
s->sock->sk->sk_err = EUNATCH;
|
||||
|
||||
/* Kill session thread */
|
||||
atomic_inc(&s->killed);
|
||||
wake_up_interruptible(sk_sleep(s->sock->sk));
|
||||
} else
|
||||
if (s)
|
||||
kthread_stop(s->task);
|
||||
else
|
||||
err = -ENOENT;
|
||||
|
||||
up_read(&bnep_session_sem);
|
||||
|
||||
@@ -39,10 +39,10 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "bnep.h"
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <linux/isdn/capilli.h>
|
||||
@@ -143,7 +144,7 @@ static void cmtp_send_capimsg(struct cmtp_session *session, struct sk_buff *skb)
|
||||
|
||||
skb_queue_tail(&session->transmit, skb);
|
||||
|
||||
cmtp_schedule(session);
|
||||
wake_up_interruptible(sk_sleep(session->sock->sk));
|
||||
}
|
||||
|
||||
static void cmtp_send_interopmsg(struct cmtp_session *session,
|
||||
@@ -386,8 +387,7 @@ static void cmtp_reset_ctr(struct capi_ctr *ctrl)
|
||||
|
||||
capi_ctr_down(ctrl);
|
||||
|
||||
atomic_inc(&session->terminate);
|
||||
cmtp_schedule(session);
|
||||
kthread_stop(session->task);
|
||||
}
|
||||
|
||||
static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp)
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#define CMTP_LOOPBACK 0
|
||||
|
||||
struct cmtp_connadd_req {
|
||||
int sock; // Connected socket
|
||||
int sock; /* Connected socket */
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
@@ -81,7 +81,7 @@ struct cmtp_session {
|
||||
|
||||
char name[BTNAMSIZ];
|
||||
|
||||
atomic_t terminate;
|
||||
struct task_struct *task;
|
||||
|
||||
wait_queue_head_t wait;
|
||||
|
||||
@@ -121,13 +121,6 @@ void cmtp_detach_device(struct cmtp_session *session);
|
||||
|
||||
void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb);
|
||||
|
||||
static inline void cmtp_schedule(struct cmtp_session *session)
|
||||
{
|
||||
struct sock *sk = session->sock->sk;
|
||||
|
||||
wake_up_interruptible(sk_sleep(sk));
|
||||
}
|
||||
|
||||
/* CMTP init defines */
|
||||
int cmtp_init_sockets(void);
|
||||
void cmtp_cleanup_sockets(void);
|
||||
|
||||
+15
-10
@@ -35,6 +35,7 @@
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/file.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <linux/isdn/capilli.h>
|
||||
@@ -235,9 +236,12 @@ static void cmtp_process_transmit(struct cmtp_session *session)
|
||||
|
||||
size = min_t(uint, ((tail < 258) ? (tail - 2) : (tail - 3)), skb->len);
|
||||
|
||||
if ((scb->id < 0) && ((scb->id = cmtp_alloc_block_id(session)) < 0)) {
|
||||
skb_queue_head(&session->transmit, skb);
|
||||
break;
|
||||
if (scb->id < 0) {
|
||||
scb->id = cmtp_alloc_block_id(session);
|
||||
if (scb->id < 0) {
|
||||
skb_queue_head(&session->transmit, skb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (size < 256) {
|
||||
@@ -284,12 +288,11 @@ static int cmtp_session(void *arg)
|
||||
|
||||
BT_DBG("session %p", session);
|
||||
|
||||
daemonize("kcmtpd_ctr_%d", session->num);
|
||||
set_user_nice(current, -15);
|
||||
|
||||
init_waitqueue_entry(&wait, current);
|
||||
add_wait_queue(sk_sleep(sk), &wait);
|
||||
while (!atomic_read(&session->terminate)) {
|
||||
while (!kthread_should_stop()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (sk->sk_state != BT_CONNECTED)
|
||||
@@ -367,9 +370,12 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
|
||||
|
||||
__cmtp_link_session(session);
|
||||
|
||||
err = kernel_thread(cmtp_session, session, CLONE_KERNEL);
|
||||
if (err < 0)
|
||||
session->task = kthread_run(cmtp_session, session, "kcmtpd_ctr_%d",
|
||||
session->num);
|
||||
if (IS_ERR(session->task)) {
|
||||
err = PTR_ERR(session->task);
|
||||
goto unlink;
|
||||
}
|
||||
|
||||
if (!(session->flags & (1 << CMTP_LOOPBACK))) {
|
||||
err = cmtp_attach_device(session);
|
||||
@@ -406,9 +412,8 @@ int cmtp_del_connection(struct cmtp_conndel_req *req)
|
||||
/* Flush the transmit queue */
|
||||
skb_queue_purge(&session->transmit);
|
||||
|
||||
/* Kill session thread */
|
||||
atomic_inc(&session->terminate);
|
||||
cmtp_schedule(session);
|
||||
/* Stop session thread */
|
||||
kthread_stop(session->task);
|
||||
} else
|
||||
err = -ENOENT;
|
||||
|
||||
|
||||
@@ -34,12 +34,12 @@
|
||||
#include <linux/file.h>
|
||||
#include <linux/compat.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <linux/isdn/capilli.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
#include "cmtp.h"
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@
|
||||
static void hci_cmd_task(unsigned long arg);
|
||||
static void hci_rx_task(unsigned long arg);
|
||||
static void hci_tx_task(unsigned long arg);
|
||||
static void hci_notify(struct hci_dev *hdev, int event);
|
||||
|
||||
static DEFINE_RWLOCK(hci_task_lock);
|
||||
|
||||
@@ -186,6 +185,7 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
|
||||
BT_DBG("%s %ld", hdev->name, opt);
|
||||
|
||||
/* Reset device */
|
||||
set_bit(HCI_RESET, &hdev->flags);
|
||||
hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
|
||||
}
|
||||
|
||||
@@ -213,8 +213,10 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
|
||||
/* Mandatory initialization */
|
||||
|
||||
/* Reset */
|
||||
if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks))
|
||||
if (!test_bit(HCI_QUIRK_NO_RESET, &hdev->quirks)) {
|
||||
set_bit(HCI_RESET, &hdev->flags);
|
||||
hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL);
|
||||
}
|
||||
|
||||
/* Read Local Supported Features */
|
||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
|
||||
@@ -584,6 +586,9 @@ static int hci_dev_do_close(struct hci_dev *hdev)
|
||||
hci_req_cancel(hdev, ENODEV);
|
||||
hci_req_lock(hdev);
|
||||
|
||||
/* Stop timer, it might be running */
|
||||
del_timer_sync(&hdev->cmd_timer);
|
||||
|
||||
if (!test_and_clear_bit(HCI_UP, &hdev->flags)) {
|
||||
hci_req_unlock(hdev);
|
||||
return 0;
|
||||
@@ -623,7 +628,6 @@ static int hci_dev_do_close(struct hci_dev *hdev)
|
||||
|
||||
/* Drop last sent command */
|
||||
if (hdev->sent_cmd) {
|
||||
del_timer_sync(&hdev->cmd_timer);
|
||||
kfree_skb(hdev->sent_cmd);
|
||||
hdev->sent_cmd = NULL;
|
||||
}
|
||||
@@ -1074,9 +1078,74 @@ static void hci_cmd_timer(unsigned long arg)
|
||||
|
||||
BT_ERR("%s command tx timeout", hdev->name);
|
||||
atomic_set(&hdev->cmd_cnt, 1);
|
||||
clear_bit(HCI_RESET, &hdev->flags);
|
||||
tasklet_schedule(&hdev->cmd_task);
|
||||
}
|
||||
|
||||
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
|
||||
bdaddr_t *bdaddr)
|
||||
{
|
||||
struct oob_data *data;
|
||||
|
||||
list_for_each_entry(data, &hdev->remote_oob_data, list)
|
||||
if (bacmp(bdaddr, &data->bdaddr) == 0)
|
||||
return data;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr)
|
||||
{
|
||||
struct oob_data *data;
|
||||
|
||||
data = hci_find_remote_oob_data(hdev, bdaddr);
|
||||
if (!data)
|
||||
return -ENOENT;
|
||||
|
||||
BT_DBG("%s removing %s", hdev->name, batostr(bdaddr));
|
||||
|
||||
list_del(&data->list);
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hci_remote_oob_data_clear(struct hci_dev *hdev)
|
||||
{
|
||||
struct oob_data *data, *n;
|
||||
|
||||
list_for_each_entry_safe(data, n, &hdev->remote_oob_data, list) {
|
||||
list_del(&data->list);
|
||||
kfree(data);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
|
||||
u8 *randomizer)
|
||||
{
|
||||
struct oob_data *data;
|
||||
|
||||
data = hci_find_remote_oob_data(hdev, bdaddr);
|
||||
|
||||
if (!data) {
|
||||
data = kmalloc(sizeof(*data), GFP_ATOMIC);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
bacpy(&data->bdaddr, bdaddr);
|
||||
list_add(&data->list, &hdev->remote_oob_data);
|
||||
}
|
||||
|
||||
memcpy(data->hash, hash, sizeof(data->hash));
|
||||
memcpy(data->randomizer, randomizer, sizeof(data->randomizer));
|
||||
|
||||
BT_DBG("%s for %s", hdev->name, batostr(bdaddr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Register HCI device */
|
||||
int hci_register_dev(struct hci_dev *hdev)
|
||||
{
|
||||
@@ -1141,6 +1210,8 @@ int hci_register_dev(struct hci_dev *hdev)
|
||||
|
||||
INIT_LIST_HEAD(&hdev->link_keys);
|
||||
|
||||
INIT_LIST_HEAD(&hdev->remote_oob_data);
|
||||
|
||||
INIT_WORK(&hdev->power_on, hci_power_on);
|
||||
INIT_WORK(&hdev->power_off, hci_power_off);
|
||||
setup_timer(&hdev->off_timer, hci_auto_off, (unsigned long) hdev);
|
||||
@@ -1220,6 +1291,7 @@ int hci_unregister_dev(struct hci_dev *hdev)
|
||||
hci_blacklist_clear(hdev);
|
||||
hci_uuids_clear(hdev);
|
||||
hci_link_keys_clear(hdev);
|
||||
hci_remote_oob_data_clear(hdev);
|
||||
hci_dev_unlock_bh(hdev);
|
||||
|
||||
__hci_dev_put(hdev);
|
||||
@@ -1269,7 +1341,7 @@ int hci_recv_frame(struct sk_buff *skb)
|
||||
EXPORT_SYMBOL(hci_recv_frame);
|
||||
|
||||
static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
|
||||
int count, __u8 index, gfp_t gfp_mask)
|
||||
int count, __u8 index)
|
||||
{
|
||||
int len = 0;
|
||||
int hlen = 0;
|
||||
@@ -1299,7 +1371,7 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data,
|
||||
break;
|
||||
}
|
||||
|
||||
skb = bt_skb_alloc(len, gfp_mask);
|
||||
skb = bt_skb_alloc(len, GFP_ATOMIC);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
@@ -1385,8 +1457,7 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count)
|
||||
return -EILSEQ;
|
||||
|
||||
while (count) {
|
||||
rem = hci_reassembly(hdev, type, data, count,
|
||||
type - 1, GFP_ATOMIC);
|
||||
rem = hci_reassembly(hdev, type, data, count, type - 1);
|
||||
if (rem < 0)
|
||||
return rem;
|
||||
|
||||
@@ -1420,8 +1491,8 @@ int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count)
|
||||
} else
|
||||
type = bt_cb(skb)->pkt_type;
|
||||
|
||||
rem = hci_reassembly(hdev, type, data,
|
||||
count, STREAM_REASSEMBLY, GFP_ATOMIC);
|
||||
rem = hci_reassembly(hdev, type, data, count,
|
||||
STREAM_REASSEMBLY);
|
||||
if (rem < 0)
|
||||
return rem;
|
||||
|
||||
|
||||
+84
-15
@@ -183,6 +183,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
BT_DBG("%s status 0x%x", hdev->name, status);
|
||||
|
||||
clear_bit(HCI_RESET, &hdev->flags);
|
||||
|
||||
hci_req_complete(hdev, HCI_OP_RESET, status);
|
||||
}
|
||||
|
||||
@@ -193,14 +195,17 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
|
||||
BT_DBG("%s status 0x%x", hdev->name, status);
|
||||
|
||||
if (status)
|
||||
return;
|
||||
|
||||
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
|
||||
if (!sent)
|
||||
return;
|
||||
|
||||
memcpy(hdev->dev_name, sent, 248);
|
||||
if (test_bit(HCI_MGMT, &hdev->flags))
|
||||
mgmt_set_local_name_complete(hdev->id, sent, status);
|
||||
|
||||
if (status)
|
||||
return;
|
||||
|
||||
memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
|
||||
}
|
||||
|
||||
static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@@ -212,7 +217,7 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
if (rp->status)
|
||||
return;
|
||||
|
||||
memcpy(hdev->dev_name, rp->name, 248);
|
||||
memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
|
||||
}
|
||||
|
||||
static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
@@ -819,6 +824,17 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev,
|
||||
rp->status);
|
||||
}
|
||||
|
||||
static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
|
||||
|
||||
BT_DBG("%s status 0x%x", hdev->name, rp->status);
|
||||
|
||||
mgmt_read_local_oob_data_reply_complete(hdev->id, rp->hash,
|
||||
rp->randomizer, rp->status);
|
||||
}
|
||||
|
||||
static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
|
||||
{
|
||||
BT_DBG("%s status 0x%x", hdev->name, status);
|
||||
@@ -1212,7 +1228,7 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
for (; num_rsp; num_rsp--) {
|
||||
for (; num_rsp; num_rsp--, info++) {
|
||||
bacpy(&data.bdaddr, &info->bdaddr);
|
||||
data.pscan_rep_mode = info->pscan_rep_mode;
|
||||
data.pscan_period_mode = info->pscan_period_mode;
|
||||
@@ -1221,8 +1237,9 @@ static inline void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *
|
||||
data.clock_offset = info->clock_offset;
|
||||
data.rssi = 0x00;
|
||||
data.ssp_mode = 0x00;
|
||||
info++;
|
||||
hci_inquiry_cache_update(hdev, &data);
|
||||
mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class, 0,
|
||||
NULL);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
@@ -1480,6 +1497,9 @@ static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
if (ev->status == 0 && test_bit(HCI_MGMT, &hdev->flags))
|
||||
mgmt_remote_name(hdev->id, &ev->bdaddr, ev->name);
|
||||
|
||||
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
|
||||
if (conn && hci_outgoing_auth_needed(hdev, conn)) {
|
||||
struct hci_cp_auth_requested cp;
|
||||
@@ -1749,6 +1769,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk
|
||||
hci_cc_pin_code_neg_reply(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_READ_LOCAL_OOB_DATA:
|
||||
hci_cc_read_local_oob_data_reply(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_OP_LE_READ_BUFFER_SIZE:
|
||||
hci_cc_le_read_buffer_size(hdev, skb);
|
||||
break;
|
||||
@@ -1847,7 +1871,7 @@ static inline void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
if (ev->opcode != HCI_OP_NOP)
|
||||
del_timer(&hdev->cmd_timer);
|
||||
|
||||
if (ev->ncmd) {
|
||||
if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
|
||||
atomic_set(&hdev->cmd_cnt, 1);
|
||||
if (!skb_queue_empty(&hdev->cmd_q))
|
||||
tasklet_schedule(&hdev->cmd_task);
|
||||
@@ -2138,7 +2162,7 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
|
||||
struct inquiry_info_with_rssi_and_pscan_mode *info;
|
||||
info = (void *) (skb->data + 1);
|
||||
|
||||
for (; num_rsp; num_rsp--) {
|
||||
for (; num_rsp; num_rsp--, info++) {
|
||||
bacpy(&data.bdaddr, &info->bdaddr);
|
||||
data.pscan_rep_mode = info->pscan_rep_mode;
|
||||
data.pscan_period_mode = info->pscan_period_mode;
|
||||
@@ -2147,13 +2171,15 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
|
||||
data.clock_offset = info->clock_offset;
|
||||
data.rssi = info->rssi;
|
||||
data.ssp_mode = 0x00;
|
||||
info++;
|
||||
hci_inquiry_cache_update(hdev, &data);
|
||||
mgmt_device_found(hdev->id, &info->bdaddr,
|
||||
info->dev_class, info->rssi,
|
||||
NULL);
|
||||
}
|
||||
} else {
|
||||
struct inquiry_info_with_rssi *info = (void *) (skb->data + 1);
|
||||
|
||||
for (; num_rsp; num_rsp--) {
|
||||
for (; num_rsp; num_rsp--, info++) {
|
||||
bacpy(&data.bdaddr, &info->bdaddr);
|
||||
data.pscan_rep_mode = info->pscan_rep_mode;
|
||||
data.pscan_period_mode = info->pscan_period_mode;
|
||||
@@ -2162,8 +2188,10 @@ static inline void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct
|
||||
data.clock_offset = info->clock_offset;
|
||||
data.rssi = info->rssi;
|
||||
data.ssp_mode = 0x00;
|
||||
info++;
|
||||
hci_inquiry_cache_update(hdev, &data);
|
||||
mgmt_device_found(hdev->id, &info->bdaddr,
|
||||
info->dev_class, info->rssi,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2294,7 +2322,7 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
for (; num_rsp; num_rsp--) {
|
||||
for (; num_rsp; num_rsp--, info++) {
|
||||
bacpy(&data.bdaddr, &info->bdaddr);
|
||||
data.pscan_rep_mode = info->pscan_rep_mode;
|
||||
data.pscan_period_mode = info->pscan_period_mode;
|
||||
@@ -2303,8 +2331,9 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct
|
||||
data.clock_offset = info->clock_offset;
|
||||
data.rssi = info->rssi;
|
||||
data.ssp_mode = 0x01;
|
||||
info++;
|
||||
hci_inquiry_cache_update(hdev, &data);
|
||||
mgmt_device_found(hdev->id, &info->bdaddr, info->dev_class,
|
||||
info->rssi, info->data);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
@@ -2353,9 +2382,14 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
cp.capability = conn->io_capability;
|
||||
cp.oob_data = 0;
|
||||
cp.authentication = hci_get_auth_req(conn);
|
||||
|
||||
if ((conn->out == 0x01 || conn->remote_oob == 0x01) &&
|
||||
hci_find_remote_oob_data(hdev, &conn->dst))
|
||||
cp.oob_data = 0x01;
|
||||
else
|
||||
cp.oob_data = 0x00;
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
|
||||
sizeof(cp), &cp);
|
||||
} else {
|
||||
@@ -2453,6 +2487,37 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static inline void hci_remote_oob_data_request_evt(struct hci_dev *hdev,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_remote_oob_data_request *ev = (void *) skb->data;
|
||||
struct oob_data *data;
|
||||
|
||||
BT_DBG("%s", hdev->name);
|
||||
|
||||
hci_dev_lock(hdev);
|
||||
|
||||
data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
|
||||
if (data) {
|
||||
struct hci_cp_remote_oob_data_reply cp;
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
memcpy(cp.hash, data->hash, sizeof(cp.hash));
|
||||
memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer));
|
||||
|
||||
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp),
|
||||
&cp);
|
||||
} else {
|
||||
struct hci_cp_remote_oob_data_neg_reply cp;
|
||||
|
||||
bacpy(&cp.bdaddr, &ev->bdaddr);
|
||||
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp),
|
||||
&cp);
|
||||
}
|
||||
|
||||
hci_dev_unlock(hdev);
|
||||
}
|
||||
|
||||
static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
{
|
||||
struct hci_ev_le_conn_complete *ev = (void *) skb->data;
|
||||
@@ -2655,6 +2720,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
|
||||
hci_le_meta_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
case HCI_EV_REMOTE_OOB_DATA_REQUEST:
|
||||
hci_remote_oob_data_request_evt(hdev, skb);
|
||||
break;
|
||||
|
||||
default:
|
||||
BT_DBG("%s event 0x%x", hdev->name, event);
|
||||
break;
|
||||
|
||||
+20
-20
@@ -216,13 +216,13 @@ static ssize_t show_type(struct device *dev, struct device_attribute *attr, char
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct hci_dev *hdev = dev_get_drvdata(dev);
|
||||
char name[249];
|
||||
char name[HCI_MAX_NAME_LENGTH + 1];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 248; i++)
|
||||
for (i = 0; i < HCI_MAX_NAME_LENGTH; i++)
|
||||
name[i] = hdev->dev_name[i];
|
||||
|
||||
name[248] = '\0';
|
||||
name[HCI_MAX_NAME_LENGTH] = '\0';
|
||||
return sprintf(buf, "%s\n", name);
|
||||
}
|
||||
|
||||
@@ -277,10 +277,12 @@ static ssize_t show_idle_timeout(struct device *dev, struct device_attribute *at
|
||||
static ssize_t store_idle_timeout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct hci_dev *hdev = dev_get_drvdata(dev);
|
||||
unsigned long val;
|
||||
unsigned int val;
|
||||
int rv;
|
||||
|
||||
if (strict_strtoul(buf, 0, &val) < 0)
|
||||
return -EINVAL;
|
||||
rv = kstrtouint(buf, 0, &val);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
if (val != 0 && (val < 500 || val > 3600000))
|
||||
return -EINVAL;
|
||||
@@ -299,15 +301,14 @@ static ssize_t show_sniff_max_interval(struct device *dev, struct device_attribu
|
||||
static ssize_t store_sniff_max_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct hci_dev *hdev = dev_get_drvdata(dev);
|
||||
unsigned long val;
|
||||
u16 val;
|
||||
int rv;
|
||||
|
||||
if (strict_strtoul(buf, 0, &val) < 0)
|
||||
return -EINVAL;
|
||||
rv = kstrtou16(buf, 0, &val);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
if (val < 0x0002 || val > 0xFFFE || val % 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (val < hdev->sniff_min_interval)
|
||||
if (val == 0 || val % 2 || val < hdev->sniff_min_interval)
|
||||
return -EINVAL;
|
||||
|
||||
hdev->sniff_max_interval = val;
|
||||
@@ -324,15 +325,14 @@ static ssize_t show_sniff_min_interval(struct device *dev, struct device_attribu
|
||||
static ssize_t store_sniff_min_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct hci_dev *hdev = dev_get_drvdata(dev);
|
||||
unsigned long val;
|
||||
u16 val;
|
||||
int rv;
|
||||
|
||||
if (strict_strtoul(buf, 0, &val) < 0)
|
||||
return -EINVAL;
|
||||
rv = kstrtou16(buf, 0, &val);
|
||||
if (rv < 0)
|
||||
return rv;
|
||||
|
||||
if (val < 0x0002 || val > 0xFFFE || val % 2)
|
||||
return -EINVAL;
|
||||
|
||||
if (val > hdev->sniff_max_interval)
|
||||
if (val == 0 || val % 2 || val > hdev->sniff_max_interval)
|
||||
return -EINVAL;
|
||||
|
||||
hdev->sniff_min_interval = val;
|
||||
|
||||
+44
-46
@@ -37,6 +37,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <net/sock.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
@@ -55,22 +56,24 @@ static DECLARE_RWSEM(hidp_session_sem);
|
||||
static LIST_HEAD(hidp_session_list);
|
||||
|
||||
static unsigned char hidp_keycode[256] = {
|
||||
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
|
||||
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
|
||||
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
|
||||
27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
|
||||
65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
|
||||
105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
|
||||
72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
|
||||
191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
|
||||
115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
|
||||
122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
|
||||
150,158,159,128,136,177,178,176,142,152,173,140
|
||||
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36,
|
||||
37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45,
|
||||
21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1,
|
||||
14, 15, 57, 12, 13, 26, 27, 43, 43, 39, 40, 41, 51, 52,
|
||||
53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 87, 88,
|
||||
99, 70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103, 69,
|
||||
98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73,
|
||||
82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190,
|
||||
191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135,
|
||||
136, 113, 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94,
|
||||
95, 0, 0, 0, 122, 123, 90, 91, 85, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115,
|
||||
114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140
|
||||
};
|
||||
|
||||
static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
|
||||
@@ -461,8 +464,7 @@ static void hidp_idle_timeout(unsigned long arg)
|
||||
{
|
||||
struct hidp_session *session = (struct hidp_session *) arg;
|
||||
|
||||
atomic_inc(&session->terminate);
|
||||
hidp_schedule(session);
|
||||
kthread_stop(session->task);
|
||||
}
|
||||
|
||||
static void hidp_set_timer(struct hidp_session *session)
|
||||
@@ -533,9 +535,7 @@ static void hidp_process_hid_control(struct hidp_session *session,
|
||||
skb_queue_purge(&session->ctrl_transmit);
|
||||
skb_queue_purge(&session->intr_transmit);
|
||||
|
||||
/* Kill session thread */
|
||||
atomic_inc(&session->terminate);
|
||||
hidp_schedule(session);
|
||||
kthread_stop(session->task);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,22 +694,10 @@ static int hidp_session(void *arg)
|
||||
struct sock *ctrl_sk = session->ctrl_sock->sk;
|
||||
struct sock *intr_sk = session->intr_sock->sk;
|
||||
struct sk_buff *skb;
|
||||
int vendor = 0x0000, product = 0x0000;
|
||||
wait_queue_t ctrl_wait, intr_wait;
|
||||
|
||||
BT_DBG("session %p", session);
|
||||
|
||||
if (session->input) {
|
||||
vendor = session->input->id.vendor;
|
||||
product = session->input->id.product;
|
||||
}
|
||||
|
||||
if (session->hid) {
|
||||
vendor = session->hid->vendor;
|
||||
product = session->hid->product;
|
||||
}
|
||||
|
||||
daemonize("khidpd_%04x%04x", vendor, product);
|
||||
set_user_nice(current, -15);
|
||||
|
||||
init_waitqueue_entry(&ctrl_wait, current);
|
||||
@@ -718,10 +706,11 @@ static int hidp_session(void *arg)
|
||||
add_wait_queue(sk_sleep(intr_sk), &intr_wait);
|
||||
session->waiting_for_startup = 0;
|
||||
wake_up_interruptible(&session->startup_queue);
|
||||
while (!atomic_read(&session->terminate)) {
|
||||
while (!kthread_should_stop()) {
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
|
||||
if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED)
|
||||
if (ctrl_sk->sk_state != BT_CONNECTED ||
|
||||
intr_sk->sk_state != BT_CONNECTED)
|
||||
break;
|
||||
|
||||
while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
|
||||
@@ -965,6 +954,7 @@ fault:
|
||||
int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
|
||||
{
|
||||
struct hidp_session *session, *s;
|
||||
int vendor, product;
|
||||
int err;
|
||||
|
||||
BT_DBG("");
|
||||
@@ -1026,9 +1016,24 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
|
||||
|
||||
hidp_set_timer(session);
|
||||
|
||||
err = kernel_thread(hidp_session, session, CLONE_KERNEL);
|
||||
if (err < 0)
|
||||
if (session->hid) {
|
||||
vendor = session->hid->vendor;
|
||||
product = session->hid->product;
|
||||
} else if (session->input) {
|
||||
vendor = session->input->id.vendor;
|
||||
product = session->input->id.product;
|
||||
} else {
|
||||
vendor = 0x0000;
|
||||
product = 0x0000;
|
||||
}
|
||||
|
||||
session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
|
||||
vendor, product);
|
||||
if (IS_ERR(session->task)) {
|
||||
err = PTR_ERR(session->task);
|
||||
goto unlink;
|
||||
}
|
||||
|
||||
while (session->waiting_for_startup) {
|
||||
wait_event_interruptible(session->startup_queue,
|
||||
!session->waiting_for_startup);
|
||||
@@ -1053,8 +1058,7 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
|
||||
err_add_device:
|
||||
hid_destroy_device(session->hid);
|
||||
session->hid = NULL;
|
||||
atomic_inc(&session->terminate);
|
||||
hidp_schedule(session);
|
||||
kthread_stop(session->task);
|
||||
|
||||
unlink:
|
||||
hidp_del_timer(session);
|
||||
@@ -1105,13 +1109,7 @@ int hidp_del_connection(struct hidp_conndel_req *req)
|
||||
skb_queue_purge(&session->ctrl_transmit);
|
||||
skb_queue_purge(&session->intr_transmit);
|
||||
|
||||
/* Wakeup user-space polling for socket errors */
|
||||
session->intr_sock->sk->sk_err = EUNATCH;
|
||||
session->ctrl_sock->sk->sk_err = EUNATCH;
|
||||
|
||||
/* Kill session thread */
|
||||
atomic_inc(&session->terminate);
|
||||
hidp_schedule(session);
|
||||
kthread_stop(session->task);
|
||||
}
|
||||
} else
|
||||
err = -ENOENT;
|
||||
|
||||
@@ -84,8 +84,8 @@
|
||||
#define HIDP_WAITING_FOR_SEND_ACK 11
|
||||
|
||||
struct hidp_connadd_req {
|
||||
int ctrl_sock; // Connected control socket
|
||||
int intr_sock; // Connteted interrupt socket
|
||||
int ctrl_sock; /* Connected control socket */
|
||||
int intr_sock; /* Connected interrupt socket */
|
||||
__u16 parser;
|
||||
__u16 rd_size;
|
||||
__u8 __user *rd_data;
|
||||
@@ -142,7 +142,7 @@ struct hidp_session {
|
||||
uint ctrl_mtu;
|
||||
uint intr_mtu;
|
||||
|
||||
atomic_t terminate;
|
||||
struct task_struct *task;
|
||||
|
||||
unsigned char keys[8];
|
||||
unsigned char leds;
|
||||
|
||||
@@ -85,7 +85,8 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
|
||||
return err;
|
||||
}
|
||||
|
||||
if (csock->sk->sk_state != BT_CONNECTED || isock->sk->sk_state != BT_CONNECTED) {
|
||||
if (csock->sk->sk_state != BT_CONNECTED ||
|
||||
isock->sk->sk_state != BT_CONNECTED) {
|
||||
sockfd_put(csock);
|
||||
sockfd_put(isock);
|
||||
return -EBADFD;
|
||||
@@ -140,8 +141,8 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
struct compat_hidp_connadd_req {
|
||||
int ctrl_sock; // Connected control socket
|
||||
int intr_sock; // Connteted interrupt socket
|
||||
int ctrl_sock; /* Connected control socket */
|
||||
int intr_sock; /* Connected interrupt socket */
|
||||
__u16 parser;
|
||||
__u16 rd_size;
|
||||
compat_uptr_t rd_data;
|
||||
|
||||
+20
-11
@@ -169,7 +169,7 @@ static inline void l2cap_chan_unlink(struct l2cap_chan_list *l, struct sock *sk)
|
||||
__sock_put(sk);
|
||||
}
|
||||
|
||||
static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
|
||||
static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk)
|
||||
{
|
||||
struct l2cap_chan_list *l = &conn->chan_list;
|
||||
|
||||
@@ -204,9 +204,6 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct so
|
||||
}
|
||||
|
||||
__l2cap_chan_link(l, sk);
|
||||
|
||||
if (parent)
|
||||
bt_accept_enqueue(parent, sk);
|
||||
}
|
||||
|
||||
/* Delete channel.
|
||||
@@ -652,7 +649,9 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
|
||||
bacpy(&bt_sk(sk)->src, conn->src);
|
||||
bacpy(&bt_sk(sk)->dst, conn->dst);
|
||||
|
||||
__l2cap_chan_add(conn, sk, parent);
|
||||
bt_accept_enqueue(parent, sk);
|
||||
|
||||
__l2cap_chan_add(conn, sk);
|
||||
|
||||
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
|
||||
|
||||
@@ -793,11 +792,11 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err)
|
||||
kfree(conn);
|
||||
}
|
||||
|
||||
static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk, struct sock *parent)
|
||||
static inline void l2cap_chan_add(struct l2cap_conn *conn, struct sock *sk)
|
||||
{
|
||||
struct l2cap_chan_list *l = &conn->chan_list;
|
||||
write_lock_bh(&l->lock);
|
||||
__l2cap_chan_add(conn, sk, parent);
|
||||
__l2cap_chan_add(conn, sk);
|
||||
write_unlock_bh(&l->lock);
|
||||
}
|
||||
|
||||
@@ -876,7 +875,7 @@ int l2cap_do_connect(struct sock *sk)
|
||||
/* Update source addr of the socket */
|
||||
bacpy(src, conn->src);
|
||||
|
||||
l2cap_chan_add(conn, sk, NULL);
|
||||
l2cap_chan_add(conn, sk);
|
||||
|
||||
sk->sk_state = BT_CONNECT;
|
||||
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
|
||||
@@ -1116,7 +1115,9 @@ int l2cap_ertm_send(struct sock *sk)
|
||||
bt_cb(skb)->tx_seq = pi->next_tx_seq;
|
||||
pi->next_tx_seq = (pi->next_tx_seq + 1) % 64;
|
||||
|
||||
pi->unacked_frames++;
|
||||
if (bt_cb(skb)->retries == 1)
|
||||
pi->unacked_frames++;
|
||||
|
||||
pi->frames_sent++;
|
||||
|
||||
if (skb_queue_is_last(TX_QUEUE(sk), skb))
|
||||
@@ -2030,7 +2031,9 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
|
||||
l2cap_pi(sk)->psm = psm;
|
||||
l2cap_pi(sk)->dcid = scid;
|
||||
|
||||
__l2cap_chan_add(conn, sk, parent);
|
||||
bt_accept_enqueue(parent, sk);
|
||||
|
||||
__l2cap_chan_add(conn, sk);
|
||||
dcid = l2cap_pi(sk)->scid;
|
||||
|
||||
l2cap_sock_set_timer(sk, sk->sk_sndtimeo);
|
||||
@@ -2460,6 +2463,11 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm
|
||||
|
||||
BT_DBG("type 0x%4.4x result 0x%2.2x", type, result);
|
||||
|
||||
/* L2CAP Info req/rsp are unbound to channels, add extra checks */
|
||||
if (cmd->ident != conn->info_ident ||
|
||||
conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)
|
||||
return 0;
|
||||
|
||||
del_timer(&conn->info_timer);
|
||||
|
||||
if (result != L2CAP_IR_SUCCESS) {
|
||||
@@ -2670,7 +2678,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
|
||||
|
||||
if (err) {
|
||||
struct l2cap_cmd_rej rej;
|
||||
BT_DBG("error %d", err);
|
||||
|
||||
BT_ERR("Wrong link type (%d)", err);
|
||||
|
||||
/* FIXME: Map err to a valid reason */
|
||||
rej.reason = cpu_to_le16(0);
|
||||
|
||||
@@ -923,8 +923,9 @@ void __l2cap_sock_close(struct sock *sk, int reason)
|
||||
rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
|
||||
l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
|
||||
L2CAP_CONN_RSP, sizeof(rsp), &rsp);
|
||||
} else
|
||||
l2cap_chan_del(sk, reason);
|
||||
}
|
||||
|
||||
l2cap_chan_del(sk, reason);
|
||||
break;
|
||||
|
||||
case BT_CONNECT:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user