Initial Contribution
msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142
Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h
new file mode 100644
index 0000000..4b08079
--- /dev/null
+++ b/include/net/bluetooth/amp.h
@@ -0,0 +1,296 @@
+/*
+ Copyright (c) 2010-2011 Code Aurora Forum. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License version 2 and
+ only version 2 as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+*/
+
+#ifndef __AMP_H
+#define __AMP_H
+
+/* AMP defaults */
+
+#define A2MP_RSP_TIMEOUT (20000) /* 20 seconds */
+
+/* A2MP Protocol */
+
+/* A2MP command codes */
+#define A2MP_COMMAND_REJ 0x01
+#define A2MP_DISCOVER_REQ 0x02
+#define A2MP_DISCOVER_RSP 0x03
+#define A2MP_CHANGE_NOTIFY 0x04
+#define A2MP_CHANGE_RSP 0x05
+#define A2MP_GETINFO_REQ 0x06
+#define A2MP_GETINFO_RSP 0x07
+#define A2MP_GETAMPASSOC_REQ 0x08
+#define A2MP_GETAMPASSOC_RSP 0x09
+#define A2MP_CREATEPHYSLINK_REQ 0x0A
+#define A2MP_CREATEPHYSLINK_RSP 0x0B
+#define A2MP_DISCONNPHYSLINK_REQ 0x0C
+#define A2MP_DISCONNPHYSLINK_RSP 0x0D
+
+struct a2mp_cmd_hdr {
+ __u8 code;
+ __u8 ident;
+ __le16 len;
+} __packed;
+
+struct a2mp_cmd_rej {
+ __le16 reason;
+} __packed;
+
+#define HCI_A2MP_ID(id) ((id)+0x10) /* convert HCI dev index to AMP ID */
+#define A2MP_HCI_ID(id) ((id)-0x10) /* convert AMP ID to HCI dev index */
+
+struct a2mp_discover_req {
+ __le16 mtu;
+ __le16 ext_feat;
+} __packed;
+
+struct a2mp_cl {
+ __u8 id;
+ __u8 type;
+ __u8 status;
+} __packed;
+
+struct a2mp_discover_rsp {
+ __le16 mtu;
+ __le16 ext_feat;
+ struct a2mp_cl cl[0];
+} __packed;
+
+struct a2mp_getinfo_req {
+ __u8 id;
+} __packed;
+
+struct a2mp_getinfo_rsp {
+ __u8 id;
+ __u8 status;
+ __le32 total_bw;
+ __le32 max_bw;
+ __le32 min_latency;
+ __le16 pal_cap;
+ __le16 assoc_size;
+} __packed;
+
+struct a2mp_getampassoc_req {
+ __u8 id;
+} __packed;
+
+struct a2mp_getampassoc_rsp {
+ __u8 id;
+ __u8 status;
+ __u8 amp_assoc[0];
+} __packed;
+
+struct a2mp_createphyslink_req {
+ __u8 local_id;
+ __u8 remote_id;
+ __u8 amp_assoc[0];
+} __packed;
+
+struct a2mp_createphyslink_rsp {
+ __u8 local_id;
+ __u8 remote_id;
+ __u8 status;
+} __packed;
+
+struct a2mp_disconnphyslink_req {
+ __u8 local_id;
+ __u8 remote_id;
+} __packed;
+
+struct a2mp_disconnphyslink_rsp {
+ __u8 local_id;
+ __u8 remote_id;
+ __u8 status;
+} __packed;
+
+
+/* L2CAP-AMP module interface */
+int amp_init(void);
+void amp_exit(void);
+
+/* L2CAP-AMP fixed channel interface */
+void amp_conn_ind(struct l2cap_conn *conn, struct sk_buff *skb);
+
+/* L2CAP-AMP link interface */
+void amp_create_physical(struct l2cap_conn *conn, struct sock *sk);
+void amp_accept_physical(struct l2cap_conn *conn, u8 id, struct sock *sk);
+
+/* AMP manager internals */
+struct amp_ctrl {
+ struct amp_mgr *mgr;
+ __u8 id;
+ __u8 type;
+ __u8 status;
+ __u32 total_bw;
+ __u32 max_bw;
+ __u32 min_latency;
+ __u16 pal_cap;
+ __u16 max_assoc_size;
+};
+
+struct amp_mgr {
+ struct list_head list;
+ __u8 discovered;
+ __u8 next_ident;
+ struct l2cap_conn *l2cap_conn;
+ struct socket *a2mp_sock;
+ struct list_head ctx_list;
+ rwlock_t ctx_list_lock;
+ struct amp_ctrl *ctrls; /* @@ TODO s.b. list of controllers */
+ struct sk_buff *skb;
+ __u8 connected;
+};
+
+/* AMP Manager signalling contexts */
+#define AMP_GETAMPASSOC 1
+#define AMP_CREATEPHYSLINK 2
+#define AMP_ACCEPTPHYSLINK 3
+#define AMP_CREATELOGLINK 4
+#define AMP_ACCEPTLOGLINK 5
+
+/* Get AMP Assoc sequence */
+#define AMP_GAA_INIT 0
+#define AMP_GAA_RLAA_COMPLETE 1
+struct amp_gaa_state {
+ __u8 req_ident;
+ __u16 len_so_far;
+ __u8 *assoc;
+};
+
+/* Create Physical Link sequence */
+#define AMP_CPL_INIT 0
+#define AMP_CPL_DISC_RSP 1
+#define AMP_CPL_GETINFO_RSP 2
+#define AMP_CPL_GAA_RSP 3
+#define AMP_CPL_CPL_STATUS 4
+#define AMP_CPL_WRA_COMPLETE 5
+#define AMP_CPL_CHANNEL_SELECT 6
+#define AMP_CPL_RLA_COMPLETE 7
+#define AMP_CPL_PL_COMPLETE 8
+#define AMP_CPL_PL_CANCEL 9
+struct amp_cpl_state {
+ __u8 remote_id;
+ __u16 max_len;
+ __u8 *remote_assoc;
+ __u8 *local_assoc;
+ __u16 len_so_far;
+ __u16 rem_len;
+ __u8 phy_handle;
+};
+
+/* Accept Physical Link sequence */
+#define AMP_APL_INIT 0
+#define AMP_APL_APL_STATUS 1
+#define AMP_APL_WRA_COMPLETE 2
+#define AMP_APL_PL_COMPLETE 3
+struct amp_apl_state {
+ __u8 remote_id;
+ __u8 req_ident;
+ __u8 *remote_assoc;
+ __u16 len_so_far;
+ __u16 rem_len;
+ __u8 phy_handle;
+};
+
+/* Create/Accept Logical Link sequence */
+#define AMP_LOG_INIT 0
+#define AMP_LOG_LL_STATUS 1
+#define AMP_LOG_LL_COMPLETE 2
+struct amp_log_state {
+ __u8 remote_id;
+};
+
+/* Possible event types a context may wait for */
+#define AMP_INIT 0x01
+#define AMP_HCI_EVENT 0x02
+#define AMP_HCI_CMD_CMPLT 0x04
+#define AMP_HCI_CMD_STATUS 0x08
+#define AMP_A2MP_RSP 0x10
+#define AMP_KILLED 0x20
+#define AMP_CANCEL 0x40
+struct amp_ctx {
+ struct list_head list;
+ struct amp_mgr *mgr;
+ struct hci_dev *hdev;
+ __u8 type;
+ __u8 state;
+ union {
+ struct amp_gaa_state gaa;
+ struct amp_cpl_state cpl;
+ struct amp_apl_state apl;
+ } d;
+ __u8 evt_type;
+ __u8 evt_code;
+ __u16 opcode;
+ __u8 id;
+ __u8 rsp_ident;
+
+ struct sock *sk;
+ struct amp_ctx *deferred;
+ struct timer_list timer;
+};
+
+/* AMP work */
+struct amp_work_pl_timeout {
+ struct work_struct work;
+ struct amp_ctrl *ctrl;
+};
+struct amp_work_ctx_timeout {
+ struct work_struct work;
+ struct amp_ctx *ctx;
+};
+struct amp_work_data_ready {
+ struct work_struct work;
+ struct sock *sk;
+ int bytes;
+};
+struct amp_work_state_change {
+ struct work_struct work;
+ struct sock *sk;
+};
+struct amp_work_conn_ind {
+ struct work_struct work;
+ struct l2cap_conn *conn;
+ struct sk_buff *skb;
+};
+struct amp_work_create_physical {
+ struct work_struct work;
+ struct l2cap_conn *conn;
+ u8 id;
+ struct sock *sk;
+};
+struct amp_work_accept_physical {
+ struct work_struct work;
+ struct l2cap_conn *conn;
+ u8 id;
+ struct sock *sk;
+};
+struct amp_work_cmd_cmplt {
+ struct work_struct work;
+ struct hci_dev *hdev;
+ u16 opcode;
+ struct sk_buff *skb;
+};
+struct amp_work_cmd_status {
+ struct work_struct work;
+ struct hci_dev *hdev;
+ u16 opcode;
+ u8 status;
+};
+struct amp_work_event {
+ struct work_struct work;
+ struct hci_dev *hdev;
+ u8 event;
+ struct sk_buff *skb;
+};
+
+#endif /* __AMP_H */
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index e727555..643a497 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -1,6 +1,6 @@
-/*
+/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2000-2001, 2010-2011 Code Aurora Forum. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -12,20 +12,20 @@
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
+ 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
+ ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
+ COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
SOFTWARE IS DISCLAIMED.
*/
#ifndef __BLUETOOTH_H
#define __BLUETOOTH_H
-#include <asm/types.h>
+#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/list.h>
#include <linux/poll.h>
@@ -38,6 +38,7 @@
/* Reserv for core and drivers use */
#define BT_SKB_RESERVE 8
+#define BT_SKB_RESERVE_80211 32
#define BTPROTO_L2CAP 0
#define BTPROTO_HCI 1
@@ -65,24 +66,41 @@
#define BT_DEFER_SETUP 7
-#define BT_FLUSHABLE 8
-
-#define BT_FLUSHABLE_OFF 0
-#define BT_FLUSHABLE_ON 1
-
-#define BT_POWER 9
+#define BT_POWER 8
struct bt_power {
__u8 force_active;
};
-#define BT_POWER_FORCE_ACTIVE_OFF 0
-#define BT_POWER_FORCE_ACTIVE_ON 1
-__attribute__((format (printf, 2, 3)))
-int bt_printk(const char *level, const char *fmt, ...);
+#define BT_AMP_POLICY 9
-#define BT_INFO(fmt, arg...) bt_printk(KERN_INFO, pr_fmt(fmt), ##arg)
-#define BT_ERR(fmt, arg...) bt_printk(KERN_ERR, pr_fmt(fmt), ##arg)
-#define BT_DBG(fmt, arg...) pr_debug(fmt "\n", ##arg)
+/* Require BR/EDR (default policy)
+ * AMP controllers cannot be used
+ * Channel move requests from the remote device are denied
+ * If the L2CAP channel is currently using AMP, move the channel to BR/EDR
+ */
+#define BT_AMP_POLICY_REQUIRE_BR_EDR 0
+
+/* Prefer AMP
+ * Allow use of AMP controllers
+ * If the L2CAP channel is currently on BR/EDR and AMP controller
+ * resources are available, initiate a channel move to AMP
+ * Channel move requests from the remote device are allowed
+ * If the L2CAP socket has not been connected yet, try to create
+ * and configure the channel directly on an AMP controller rather
+ * than BR/EDR
+ */
+#define BT_AMP_POLICY_PREFER_AMP 1
+
+/* Prefer BR/EDR
+ * Allow use of AMP controllers
+ * If the L2CAP channel is currently on AMP, move it to BR/EDR
+ * Channel move requests from the remote device are allowed
+ */
+#define BT_AMP_POLICY_PREFER_BR_EDR 2
+
+#define BT_INFO(fmt, arg...) printk(KERN_INFO "Bluetooth: " fmt "\n" , ## arg)
+#define BT_ERR(fmt, arg...) printk(KERN_ERR "%s: " fmt "\n" , __func__ , ## arg)
+#define BT_DBG(fmt, arg...) pr_debug("%s: " fmt "\n" , __func__ , ## arg)
/* Connection and socket states */
enum {
@@ -102,8 +120,8 @@
__u8 b[6];
} __packed bdaddr_t;
-#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
-#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
+#define BDADDR_ANY (&(bdaddr_t) {{0, 0, 0, 0, 0, 0} })
+#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff} })
/* Copy, swap, convert BD Address */
static inline int bacmp(bdaddr_t *ba1, bdaddr_t *ba2)
@@ -145,7 +163,7 @@
struct msghdr *msg, size_t len, int flags);
int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len, int flags);
-uint bt_sock_poll(struct file * file, struct socket *sock, poll_table *wait);
+uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait);
int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo);
@@ -154,15 +172,25 @@
struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock);
/* Skb helpers */
+struct bt_l2cap_control {
+ __u8 frame_type;
+ __u8 final;
+ __u8 sar;
+ __u8 super;
+ __u16 reqseq;
+ __u16 txseq;
+ __u8 poll;
+ __u8 fcs;
+};
+
struct bt_skb_cb {
__u8 pkt_type;
__u8 incoming;
__u16 expect;
- __u8 tx_seq;
__u8 retries;
- __u8 sar;
- unsigned short channel;
__u8 force_active;
+ unsigned short channel;
+ struct bt_l2cap_control control;
};
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))
@@ -170,7 +198,8 @@
{
struct sk_buff *skb;
- if ((skb = alloc_skb(len + BT_SKB_RESERVE, how))) {
+ skb = alloc_skb(len + BT_SKB_RESERVE, how);
+ if (skb) {
skb_reserve(skb, BT_SKB_RESERVE);
bt_cb(skb)->incoming = 0;
}
@@ -183,7 +212,8 @@
struct sk_buff *skb;
release_sock(sk);
- if ((skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err))) {
+ skb = sock_alloc_send_skb(sk, len + BT_SKB_RESERVE, nb, err);
+ if (skb) {
skb_reserve(skb, BT_SKB_RESERVE);
bt_cb(skb)->incoming = 0;
}
@@ -208,7 +238,7 @@
return NULL;
}
-int bt_to_errno(__u16 code);
+int bt_err(__u16 code);
extern int hci_sock_init(void);
extern void hci_sock_cleanup(void);
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 0489b8b..3466efa 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2000-2001, 2010-2011 Code Aurora Forum. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -25,7 +25,7 @@
#ifndef __HCI_H
#define __HCI_H
-#define HCI_MAX_ACL_SIZE 1024
+#define HCI_MAX_ACL_SIZE 1500
#define HCI_MAX_SCO_SIZE 255
#define HCI_MAX_EVENT_SIZE 260
#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
@@ -37,6 +37,7 @@
#define HCI_DEV_DOWN 4
#define HCI_DEV_SUSPEND 5
#define HCI_DEV_RESUME 6
+#define HCI_DEV_WRITE 7
/* HCI notify events */
#define HCI_NOTIFY_CONN_ADD 1
@@ -51,6 +52,7 @@
#define HCI_RS232 4
#define HCI_PCI 5
#define HCI_SDIO 6
+#define HCI_SMD 7
/* HCI controller types */
#define HCI_BREDR 0x00
@@ -99,6 +101,7 @@
#define HCIGETCONNLIST _IOR('H', 212, int)
#define HCIGETCONNINFO _IOR('H', 213, int)
#define HCIGETAUTHINFO _IOR('H', 215, int)
+#define HCISETAUTHINFO _IOR('H', 216, int)
#define HCISETRAW _IOW('H', 220, int)
#define HCISETSCAN _IOW('H', 221, int)
@@ -166,9 +169,12 @@
#define ACL_START_NO_FLUSH 0x00
#define ACL_CONT 0x01
#define ACL_START 0x02
+#define ACL_COMPLETE 0x03
#define ACL_ACTIVE_BCAST 0x04
#define ACL_PICO_BCAST 0x08
+#define ACL_PB_MASK (ACL_CONT | ACL_START)
+
/* Baseband links */
#define SCO_LINK 0x00
#define ACL_LINK 0x01
@@ -213,16 +219,11 @@
#define LMP_EDR_3S_ESCO 0x80
#define LMP_EXT_INQ 0x01
-#define LMP_SIMUL_LE_BR 0x02
#define LMP_SIMPLE_PAIR 0x08
#define LMP_NO_FLUSH 0x40
#define LMP_LSTO 0x01
#define LMP_INQ_TX_PWR 0x02
-#define LMP_EXTFEATURES 0x80
-
-/* Extended LMP features */
-#define LMP_HOST_LE 0x02
/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
@@ -253,18 +254,9 @@
#define HCI_AT_GENERAL_BONDING 0x04
#define HCI_AT_GENERAL_BONDING_MITM 0x05
-/* Link Key types */
-#define HCI_LK_COMBINATION 0x00
-#define HCI_LK_LOCAL_UNIT 0x01
-#define HCI_LK_REMOTE_UNIT 0x02
-#define HCI_LK_DEBUG_COMBINATION 0x03
-#define HCI_LK_UNAUTH_COMBINATION 0x04
-#define HCI_LK_AUTH_COMBINATION 0x05
-#define HCI_LK_CHANGED_COMBINATION 0x06
-/* The spec doesn't define types for SMP keys */
-#define HCI_LK_SMP_LTK 0x81
-#define HCI_LK_SMP_IRK 0x82
-#define HCI_LK_SMP_CSRK 0x83
+/* Flow control modes */
+#define HCI_PACKET_BASED_FLOW_CTL_MODE 0x00
+#define HCI_BLOCK_BASED_FLOW_CTL_MODE 0x01
/* ----- HCI Commands ---- */
#define HCI_OP_NOP 0x0000
@@ -325,6 +317,11 @@
__u8 link_key[16];
} __packed;
+struct hci_rp_link_key_reply {
+ __u8 status;
+ bdaddr_t bdaddr;
+} __packed;
+
#define HCI_OP_LINK_KEY_NEG_REPLY 0x040c
struct hci_cp_link_key_neg_reply {
bdaddr_t bdaddr;
@@ -466,6 +463,69 @@
__u8 reason;
} __packed;
+#define HCI_OP_CREATE_PHYS_LINK 0x0435
+struct hci_cp_create_phys_link {
+ __u8 phy_handle;
+ __u8 key_len;
+ __u8 type;
+ __u8 data[32];
+} __packed;
+
+#define HCI_OP_ACCEPT_PHYS_LINK 0x0436
+struct hci_cp_accept_phys_link {
+ __u8 phy_handle;
+ __u8 key_len;
+ __u8 type;
+ __u8 data[32];
+} __packed;
+
+#define HCI_OP_DISCONN_PHYS_LINK 0x0437
+struct hci_cp_disconn_phys_link {
+ __u8 phy_handle;
+ __u8 reason;
+} __packed;
+
+struct hci_ext_fs {
+ __u8 id;
+ __u8 type;
+ __le16 max_sdu;
+ __le32 sdu_arr_time;
+ __le32 acc_latency;
+ __le32 flush_to;
+} __packed;
+
+#define HCI_OP_CREATE_LOGICAL_LINK 0x0438
+#define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439
+struct hci_cp_create_logical_link {
+ __u8 phy_handle;
+ struct hci_ext_fs tx_fs;
+ struct hci_ext_fs rx_fs;
+} __packed;
+
+#define HCI_OP_DISCONN_LOGICAL_LINK 0x043a
+struct hci_cp_disconn_logical_link {
+ __le16 log_handle;
+} __packed;
+
+#define HCI_OP_LOGICAL_LINK_CANCEL 0x043b
+struct hci_cp_logical_link_cancel {
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
+struct hci_rp_logical_link_cancel {
+ __u8 status;
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
+#define HCI_OP_FLOW_SPEC_MODIFY 0x043c
+struct hci_cp_flow_spec_modify {
+ __le16 log_handle;
+ struct hci_ext_fs tx_fs;
+ struct hci_ext_fs rx_fs;
+} __packed;
+
#define HCI_OP_SNIFF_MODE 0x0803
struct hci_cp_sniff_mode {
__le16 handle;
@@ -664,10 +724,70 @@
#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58
-#define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d
-struct hci_cp_write_le_host_supported {
- __u8 le;
- __u8 simul;
+#define HCI_OP_READ_LL_TIMEOUT 0x0c61
+struct hci_rp_read_ll_timeout {
+ __u8 status;
+ __le16 timeout;
+} __packed;
+
+#define HCI_OP_WRITE_LL_TIMEOUT 0x0c62
+struct hci_cp_write_ll_timeout {
+ __le16 timeout;
+} __packed;
+
+#define HCI_OP_SET_EVENT_MASK_PAGE2 0x0c63
+struct hci_cp_set_event_mask_page2 {
+ __u8 mask[8];
+} __packed;
+
+#define HCI_OP_READ_LOCATION_DATA 0x0c64
+struct hci_rp_read_location_data {
+ __u8 status;
+ __u8 loc_dom_aware;
+ __u8 loc_dom;
+ __u8 loc_dom_opts;
+ __u8 loc_opts;
+} __packed;
+
+#define HCI_OP_WRITE_LOCATION_DATA 0x0c65
+struct hci_cp_write_location_data {
+ __u8 loc_dom_aware;
+ __u8 loc_dom;
+ __u8 loc_dom_opts;
+ __u8 loc_opts;
+} __packed;
+
+#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66
+struct hci_rp_read_flow_control_mode {
+ __u8 status;
+ __u8 mode;
+} __packed;
+
+#define HCI_OP_WRITE_FLOW_CONTROL_MODE 0x0c67
+struct hci_cp_write_flow_control_mode {
+ __u8 mode;
+} __packed;
+
+#define HCI_OP_READ_BE_FLUSH_TIMEOUT 0x0c69
+struct hci_cp_read_be_flush_timeout {
+ __le16 log_handle;
+} __packed;
+
+struct hci_rp_read_be_flush_timeout {
+ __u8 status;
+ __le32 timeout;
+} __packed;
+
+#define HCI_OP_WRITE_BE_FLUSH_TIMEOUT 0x0c6a
+struct hci_cp_write_be_flush_timeout {
+ __le16 log_handle;
+ __le32 timeout;
+} __packed;
+
+#define HCI_OP_SHORT_RANGE_MODE 0x0c6b
+struct hci_cp_short_range_mode {
+ __u8 phy_handle;
+ __u8 mode;
} __packed;
#define HCI_OP_READ_LOCAL_VERSION 0x1001
@@ -693,9 +813,6 @@
} __packed;
#define HCI_OP_READ_LOCAL_EXT_FEATURES 0x1004
-struct hci_cp_read_local_ext_features {
- __u8 page;
-} __packed;
struct hci_rp_read_local_ext_features {
__u8 status;
__u8 page;
@@ -718,6 +835,56 @@
bdaddr_t bdaddr;
} __packed;
+#define HCI_OP_READ_DATA_BLOCK_SIZE 0x100a
+struct hci_rp_read_data_block_size {
+ __u8 status;
+ __le16 max_acl_len;
+ __le16 data_block_len;
+ __le16 num_blocks;
+} __packed;
+
+#define HCI_OP_READ_LOCAL_AMP_INFO 0x1409
+struct hci_rp_read_local_amp_info {
+ __u8 status;
+ __u8 amp_status;
+ __le32 total_bw;
+ __le32 max_bw;
+ __le32 min_latency;
+ __le32 max_pdu;
+ __u8 amp_type;
+ __le16 pal_cap;
+ __le16 max_assoc_size;
+ __le32 max_flush_to;
+ __le32 be_flush_to;
+} __packed;
+
+#define HCI_OP_READ_LOCAL_AMP_ASSOC 0x140a
+struct hci_cp_read_local_amp_assoc {
+ __u8 phy_handle;
+ __le16 len_so_far;
+ __le16 max_len;
+} __packed;
+
+struct hci_rp_read_local_amp_assoc {
+ __u8 status;
+ __u8 phy_handle;
+ __le16 rem_len;
+ __u8 frag[248];
+} __packed;
+
+#define HCI_OP_WRITE_REMOTE_AMP_ASSOC 0x140b
+struct hci_cp_write_remote_amp_assoc {
+ __u8 phy_handle;
+ __le16 len_so_far;
+ __le16 rem_len;
+ __u8 frag[248];
+} __packed;
+
+struct hci_rp_write_remote_amp_assoc {
+ __u8 status;
+ __u8 phy_handle;
+} __packed;
+
#define HCI_OP_LE_SET_EVENT_MASK 0x2001
struct hci_cp_le_set_event_mask {
__u8 mask[8];
@@ -731,10 +898,6 @@
} __packed;
#define HCI_OP_LE_SET_SCAN_ENABLE 0x200c
-struct hci_cp_le_set_scan_enable {
- __u8 enable;
- __u8 filter_dup;
-} __packed;
#define HCI_OP_LE_CREATE_CONN 0x200d
struct hci_cp_le_create_conn {
@@ -1082,14 +1245,6 @@
__u8 clk_accurancy;
} __packed;
-#define HCI_EV_LE_LTK_REQ 0x05
-struct hci_ev_le_ltk_req {
- __le16 handle;
- __u8 random[8];
- __le16 ediv;
-} __packed;
-
-/* Advertising report event types */
#define ADV_IND 0x00
#define ADV_DIRECT_IND 0x01
#define ADV_SCAN_IND 0x02
@@ -1108,6 +1263,72 @@
__u8 data[0];
} __packed;
+#define HCI_EV_LE_LTK_REQ 0x05
+struct hci_ev_le_ltk_req {
+ __le16 handle;
+ __u8 random[8];
+ __le16 ediv;
+} __packed;
+
+#define HCI_EV_PHYS_LINK_COMPLETE 0x40
+struct hci_ev_phys_link_complete {
+ __u8 status;
+ __u8 phy_handle;
+} __packed;
+
+#define HCI_EV_CHANNEL_SELECTED 0x41
+struct hci_ev_channel_selected {
+ __u8 phy_handle;
+} __packed;
+
+#define HCI_EV_DISCONN_PHYS_LINK_COMPLETE 0x42
+struct hci_ev_disconn_phys_link_complete {
+ __u8 status;
+ __u8 phy_handle;
+ __u8 reason;
+} __packed;
+
+#define HCI_EV_LOG_LINK_COMPLETE 0x45
+struct hci_ev_log_link_complete {
+ __u8 status;
+ __le16 log_handle;
+ __u8 phy_handle;
+ __u8 flow_spec_id;
+} __packed;
+
+#define HCI_EV_DISCONN_LOG_LINK_COMPLETE 0x46
+struct hci_ev_disconn_log_link_complete {
+ __u8 status;
+ __le16 log_handle;
+ __u8 reason;
+} __packed;
+
+#define HCI_EV_FLOW_SPEC_MODIFY_COMPLETE 0x47
+struct hci_ev_flow_spec_modify_complete {
+ __u8 status;
+ __le16 log_handle;
+} __packed;
+
+#define HCI_EV_NUM_COMP_BLOCKS 0x48
+struct hci_ev_num_comp_blocks {
+ __le16 total_num_blocks;
+ __u8 num_hndl;
+ /* variable length part */
+} __packed;
+
+#define HCI_EV_SHORT_RANGE_MODE_COMPLETE 0x4c
+struct hci_ev_short_range_mode_complete {
+ __u8 status;
+ __u8 phy_handle;
+ __u8 mode;
+} __packed;
+
+#define HCI_EV_AMP_STATUS_CHANGE 0x4d
+struct hci_ev_amp_status_change {
+ __u8 status;
+ __u8 amp_status;
+} __packed;
+
/* Internal events generated by Bluetooth stack */
#define HCI_EV_STACK_INTERNAL 0xfd
struct hci_ev_stack_internal {
@@ -1155,6 +1376,7 @@
__u8 dlen;
} __packed;
+#ifdef __KERNEL__
#include <linux/skbuff.h>
static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb)
{
@@ -1170,6 +1392,7 @@
{
return (struct hci_sco_hdr *) skb->data;
}
+#endif
/* Command opcode pack/unpack */
#define hci_opcode_pack(ogf, ocf) (__u16) ((ocf & 0x03ff)|(ogf << 10))
@@ -1266,6 +1489,8 @@
__u32 mtu;
__u32 cnt;
__u32 pkts;
+ __u8 pending_sec_level;
+ __u8 ssp_mode;
};
struct hci_dev_req {
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 27e1b36..7e0e151 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
+ Copyright (c) 2000-2001, 2010-2011, Code Aurora Forum. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
@@ -63,6 +63,11 @@
unsigned int le_num;
};
+struct hci_chan_list {
+ struct list_head list;
+ spinlock_t lock;
+};
+
struct bdaddr_list {
struct list_head list;
bdaddr_t bdaddr;
@@ -79,6 +84,10 @@
u8 rand[8];
} __packed;
+#define KEY_TYPE_LTK 0x11
+#define KEY_TYPE_IRK 0x12
+#define KEY_TYPE_CSRK 0x13
+
struct link_key_data {
bdaddr_t bdaddr;
u8 type;
@@ -129,7 +138,6 @@
__u8 major_class;
__u8 minor_class;
__u8 features[8];
- __u8 extfeatures[8];
__u8 commands[64];
__u8 ssp_mode;
__u8 hci_ver;
@@ -149,7 +157,16 @@
__u16 sniff_min_interval;
__u16 sniff_max_interval;
- unsigned int auto_accept_delay;
+ __u8 amp_status;
+ __u32 amp_total_bw;
+ __u32 amp_max_bw;
+ __u32 amp_min_latency;
+ __u32 amp_max_pdu;
+ __u8 amp_type;
+ __u16 amp_pal_cap;
+ __u16 amp_assoc_size;
+ __u32 amp_max_flush_to;
+ __u32 amp_be_flush_to;
unsigned long quirks;
@@ -158,6 +175,8 @@
unsigned int sco_cnt;
unsigned int le_cnt;
+ __u8 flow_ctl_mode;
+
unsigned int acl_mtu;
unsigned int sco_mtu;
unsigned int le_mtu;
@@ -165,6 +184,8 @@
unsigned int sco_pkts;
unsigned int le_pkts;
+ unsigned int data_block_len;
+
unsigned long acl_last_tx;
unsigned long sco_last_tx;
unsigned long le_last_tx;
@@ -198,6 +219,7 @@
struct inquiry_cache inq_cache;
struct hci_conn_hash conn_hash;
+ struct hci_chan_list chan_list;
struct list_head blacklist;
struct list_head uuids;
@@ -207,6 +229,7 @@
struct list_head remote_oob_data;
struct list_head adv_entries;
+ rwlock_t adv_entries_lock;
struct timer_list adv_timer;
struct hci_dev_stats stat;
@@ -240,9 +263,11 @@
struct list_head list;
atomic_t refcnt;
+ spinlock_t lock;
bdaddr_t dst;
- __u8 dst_type;
+ __u8 dst_id;
+ __u8 dst_type;
__u16 handle;
__u16 state;
__u8 mode;
@@ -256,7 +281,6 @@
__u16 pkt_type;
__u16 link_policy;
__u32 link_mode;
- __u8 key_type;
__u8 auth_type;
__u8 sec_level;
__u8 pending_sec_level;
@@ -277,7 +301,6 @@
struct timer_list disc_timer;
struct timer_list idle_timer;
- struct timer_list auto_accept_timer;
struct work_struct work_add;
struct work_struct work_del;
@@ -288,6 +311,10 @@
struct hci_dev *hdev;
void *l2cap_data;
void *sco_data;
+ void *priv;
+
+ __u8 link_key[16];
+ __u8 key_type;
struct hci_conn *link;
@@ -296,6 +323,18 @@
void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason);
};
+struct hci_chan {
+ struct list_head list;
+ struct hci_dev *hdev;
+ __u16 state;
+ atomic_t refcnt;
+ __u16 ll_handle;
+ struct hci_ext_fs tx_fs;
+ struct hci_ext_fs rx_fs;
+ struct hci_conn *conn;
+ void *l2cap_sk;
+};
+
extern struct hci_proto *hci_proto[];
extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list;
@@ -335,14 +374,12 @@
return jiffies - e->timestamp;
}
-struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
- bdaddr_t *bdaddr);
+struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
/* ----- HCI Connections ----- */
enum {
HCI_CONN_AUTH_PEND,
- HCI_CONN_REAUTH_PEND,
HCI_CONN_ENCRYPT_PEND,
HCI_CONN_RSWITCH_PEND,
HCI_CONN_MODE_CHANGE_PEND,
@@ -409,6 +446,13 @@
return NULL;
}
+static inline void hci_chan_list_init(struct hci_dev *hdev)
+{
+ struct hci_chan_list *h = &hdev->chan_list;
+ INIT_LIST_HEAD(&h->list);
+ spin_lock_init(&h->lock);
+}
+
static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
__u8 type, bdaddr_t *ba)
{
@@ -424,6 +468,21 @@
return NULL;
}
+static inline struct hci_conn *hci_conn_hash_lookup_id(struct hci_dev *hdev,
+ bdaddr_t *ba, __u8 id)
+{
+ struct hci_conn_hash *h = &hdev->conn_hash;
+ struct list_head *p;
+ struct hci_conn *c;
+
+ list_for_each(p, &h->list) {
+ c = list_entry(p, struct hci_conn, list);
+ if (!bacmp(&c->dst, ba) && (c->dst_id == id))
+ return c;
+ }
+ return NULL;
+}
+
static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
__u8 type, __u16 state)
{
@@ -439,6 +498,36 @@
return NULL;
}
+static inline struct hci_chan *hci_chan_list_lookup_handle(struct hci_dev *hdev,
+ __u16 handle)
+{
+ struct hci_chan_list *l = &hdev->chan_list;
+ struct list_head *p;
+ struct hci_chan *c;
+
+ list_for_each(p, &l->list) {
+ c = list_entry(p, struct hci_chan, list);
+ if (c->ll_handle == handle)
+ return c;
+ }
+ return NULL;
+}
+
+static inline struct hci_chan *hci_chan_list_lookup_id(struct hci_dev *hdev,
+ __u8 handle)
+{
+ struct hci_chan_list *l = &hdev->chan_list;
+ struct list_head *p;
+ struct hci_chan *c;
+
+ list_for_each(p, &l->list) {
+ c = list_entry(p, struct hci_chan, list);
+ if (c->conn->handle == handle)
+ return c;
+ }
+ return NULL;
+}
+
void hci_acl_connect(struct hci_conn *conn);
void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
void hci_add_sco(struct hci_conn *conn, __u16 handle);
@@ -447,18 +536,39 @@
struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type,
__u16 pkt_type, bdaddr_t *dst);
+struct hci_conn *hci_le_conn_add(struct hci_dev *hdev, bdaddr_t *dst,
+ __u8 addr_type);
int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
+struct hci_chan *hci_chan_add(struct hci_dev *hdev);
+int hci_chan_del(struct hci_chan *chan);
+static inline void hci_chan_hold(struct hci_chan *chan)
+{
+ atomic_inc(&chan->refcnt);
+}
+void hci_chan_put(struct hci_chan *chan);
+
+struct hci_chan *hci_chan_accept(struct hci_conn *hcon,
+ struct hci_ext_fs *tx_fs,
+ struct hci_ext_fs *rx_fs);
+struct hci_chan *hci_chan_create(struct hci_conn *hcon,
+ struct hci_ext_fs *tx_fs,
+ struct hci_ext_fs *rx_fs);
+void hci_chan_modify(struct hci_chan *chan,
+ struct hci_ext_fs *tx_fs,
+ struct hci_ext_fs *rx_fs);
+
struct hci_conn *hci_connect(struct hci_dev *hdev, int type,
- __u16 pkt_type, bdaddr_t *dst,
- __u8 sec_level, __u8 auth_type);
+ __u16 pkt_type, bdaddr_t *dst,
+ __u8 sec_level, __u8 auth_type);
int hci_conn_check_link_mode(struct hci_conn *conn);
-int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
int hci_conn_change_link_key(struct hci_conn *conn);
int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
+void hci_disconnect(struct hci_conn *conn, __u8 reason);
+void hci_disconnect_amp(struct hci_conn *conn, __u8 reason);
void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
void hci_conn_enter_sniff_mode(struct hci_conn *conn);
@@ -482,12 +592,10 @@
timeo = msecs_to_jiffies(conn->disc_timeout);
if (!conn->out)
timeo *= 20;
- } else {
+ } else
timeo = msecs_to_jiffies(10);
- }
- } else {
+ } else
timeo = msecs_to_jiffies(10);
- }
mod_timer(&conn->disc_timer, jiffies + timeo);
}
}
@@ -525,6 +633,7 @@
struct hci_dev *hci_dev_get(int index);
struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
+struct hci_dev *hci_dev_get_type(__u8 amp_type);
struct hci_dev *hci_alloc_dev(void);
void hci_free_dev(struct hci_dev *hdev);
@@ -542,19 +651,18 @@
int hci_get_conn_list(void __user *arg);
int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
+int hci_set_auth_info(struct hci_dev *hdev, void __user *arg);
int hci_inquiry(void __user *arg);
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_blacklist_clear(struct hci_dev *hdev);
-int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr);
-int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr);
int hci_uuids_clear(struct hci_dev *hdev);
int hci_link_keys_clear(struct hci_dev *hdev);
struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
-int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
- bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
+int hci_add_link_key(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr,
+ u8 *key, u8 type, u8 pin_len);
struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]);
struct link_key *hci_find_link_key_type(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 type);
@@ -601,9 +709,6 @@
#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
-/* ----- Extended LMP capabilities ----- */
-#define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE)
-
/* ----- HCI protocols ----- */
struct hci_proto {
char *name;
@@ -612,20 +717,19 @@
void *priv;
- int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr,
- __u8 type);
+ int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type);
int (*connect_cfm) (struct hci_conn *conn, __u8 status);
int (*disconn_ind) (struct hci_conn *conn);
int (*disconn_cfm) (struct hci_conn *conn, __u8 reason);
- int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb,
- __u16 flags);
+ int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
- int (*security_cfm) (struct hci_conn *conn, __u8 status,
- __u8 encrypt);
+ int (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
+ int (*create_cfm) (struct hci_chan *chan, __u8 status);
+ int (*modify_cfm) (struct hci_chan *chan, __u8 status);
+ int (*destroy_cfm) (struct hci_chan *chan, __u8 status);
};
-static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
- __u8 type)
+static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type)
{
register struct hci_proto *hp;
int mask = 0;
@@ -711,8 +815,7 @@
conn->security_cfm_cb(conn, status);
}
-static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
- __u8 encrypt)
+static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
{
register struct hci_proto *hp;
@@ -728,6 +831,33 @@
conn->security_cfm_cb(conn, status);
}
+static inline void hci_proto_create_cfm(struct hci_chan *chan, __u8 status)
+{
+ register struct hci_proto *hp;
+
+ hp = hci_proto[HCI_PROTO_L2CAP];
+ if (hp && hp->create_cfm)
+ hp->create_cfm(chan, status);
+}
+
+static inline void hci_proto_modify_cfm(struct hci_chan *chan, __u8 status)
+{
+ register struct hci_proto *hp;
+
+ hp = hci_proto[HCI_PROTO_L2CAP];
+ if (hp && hp->modify_cfm)
+ hp->modify_cfm(chan, status);
+}
+
+static inline void hci_proto_destroy_cfm(struct hci_chan *chan, __u8 status)
+{
+ register struct hci_proto *hp;
+
+ hp = hci_proto[HCI_PROTO_L2CAP];
+ if (hp && hp->destroy_cfm)
+ hp->destroy_cfm(chan, status);
+}
+
int hci_register_proto(struct hci_proto *hproto);
int hci_unregister_proto(struct hci_proto *hproto);
@@ -737,8 +867,7 @@
char *name;
- void (*security_cfm) (struct hci_conn *conn, __u8 status,
- __u8 encrypt);
+ void (*security_cfm) (struct hci_conn *conn, __u8 status, __u8 encrypt);
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
};
@@ -764,8 +893,7 @@
read_unlock_bh(&hci_cb_list_lock);
}
-static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
- __u8 encrypt)
+static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, __u8 encrypt)
{
struct list_head *p;
@@ -799,8 +927,7 @@
read_unlock_bh(&hci_cb_list_lock);
}
-static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
- __u8 role)
+static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, __u8 role)
{
struct list_head *p;
@@ -819,8 +946,29 @@
int hci_register_notifier(struct notifier_block *nb);
int hci_unregister_notifier(struct notifier_block *nb);
+/* AMP Manager event callbacks */
+struct amp_mgr_cb {
+ struct list_head list;
+ void (*amp_cmd_complete_event) (struct hci_dev *hdev, __u16 opcode,
+ struct sk_buff *skb);
+ void (*amp_cmd_status_event) (struct hci_dev *hdev, __u16 opcode,
+ __u8 status);
+ void (*amp_event) (struct hci_dev *hdev, __u8 ev_code,
+ struct sk_buff *skb);
+};
+
+void hci_amp_cmd_complete(struct hci_dev *hdev, __u16 opcode,
+ struct sk_buff *skb);
+void hci_amp_cmd_status(struct hci_dev *hdev, __u16 opcode, __u8 status);
+void hci_amp_event_packet(struct hci_dev *hdev, __u8 ev_code,
+ struct sk_buff *skb);
+
+int hci_register_amp(struct amp_mgr_cb *acb);
+int hci_unregister_amp(struct amp_mgr_cb *acb);
+
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
-void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
+void hci_send_acl(struct hci_conn *conn, struct hci_chan *chan,
+ struct sk_buff *skb, __u16 flags);
void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
@@ -838,16 +986,15 @@
int mgmt_powered(u16 index, u8 powered);
int mgmt_discoverable(u16 index, u8 discoverable);
int mgmt_connectable(u16 index, u8 connectable);
-int mgmt_new_key(u16 index, struct link_key *key, u8 persistent);
+int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type);
int mgmt_connected(u16 index, bdaddr_t *bdaddr);
int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
int mgmt_disconnect_failed(u16 index);
int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure);
+int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr);
int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
-int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value,
- u8 confirm_hint);
+int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value);
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);
@@ -858,7 +1005,6 @@
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);
-int mgmt_discovering(u16 index, u8 discovering);
/* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk)
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 578545a..be2147e 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -1,6 +1,6 @@
/*
BlueZ - Bluetooth protocol stack for Linux
- Copyright (C) 2000-2001 Qualcomm Incorporated
+ Copyright (c) 2000-2001, 2010-2011 Code Aurora Forum. All rights reserved.
Copyright (C) 2009-2010 Gustavo F. Padovan <gustavo@padovan.org>
Copyright (C) 2010 Google Inc.
@@ -30,17 +30,28 @@
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
#define L2CAP_DEFAULT_MIN_MTU 48
+#define L2CAP_DEFAULT_MAX_SDU_SIZE 0xffff
#define L2CAP_DEFAULT_FLUSH_TO 0xffff
#define L2CAP_DEFAULT_TX_WINDOW 63
#define L2CAP_DEFAULT_MAX_TX 3
#define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */
#define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */
-#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */
+#define L2CAP_DEFAULT_MAX_PDU_SIZE 1482 /* Sized for AMP or BR/EDR */
#define L2CAP_DEFAULT_ACK_TO 200
+#define L2CAP_BREDR_MAX_PAYLOAD 1019 /* 3-DH5 packet */
+#define L2CAP_MAX_ERTM_QUEUED 5
+#define L2CAP_MIN_ERTM_QUEUED 2
+
+#define L2CAP_A2MP_DEFAULT_MTU 670
+
+#define L2CAP_TX_WIN_MAX_ENHANCED 0x3f
+#define L2CAP_TX_WIN_MAX_EXTENDED 0x3fff
#define L2CAP_LE_DEFAULT_MTU 23
#define L2CAP_CONN_TIMEOUT (40000) /* 40 seconds */
#define L2CAP_INFO_TIMEOUT (4000) /* 4 seconds */
+#define L2CAP_MOVE_TIMEOUT (2*HZ) /* 2 seconds */
+#define L2CAP_MOVE_ERTX_TIMEOUT (60*HZ) /* 60 seconds */
/* L2CAP socket address */
struct sockaddr_l2 {
@@ -75,19 +86,26 @@
#define L2CAP_LM_TRUSTED 0x0008
#define L2CAP_LM_RELIABLE 0x0010
#define L2CAP_LM_SECURE 0x0020
+#define L2CAP_LM_FLUSHABLE 0x0040
/* L2CAP command codes */
-#define L2CAP_COMMAND_REJ 0x01
-#define L2CAP_CONN_REQ 0x02
-#define L2CAP_CONN_RSP 0x03
-#define L2CAP_CONF_REQ 0x04
-#define L2CAP_CONF_RSP 0x05
-#define L2CAP_DISCONN_REQ 0x06
-#define L2CAP_DISCONN_RSP 0x07
-#define L2CAP_ECHO_REQ 0x08
-#define L2CAP_ECHO_RSP 0x09
-#define L2CAP_INFO_REQ 0x0a
-#define L2CAP_INFO_RSP 0x0b
+#define L2CAP_COMMAND_REJ 0x01
+#define L2CAP_CONN_REQ 0x02
+#define L2CAP_CONN_RSP 0x03
+#define L2CAP_CONF_REQ 0x04
+#define L2CAP_CONF_RSP 0x05
+#define L2CAP_DISCONN_REQ 0x06
+#define L2CAP_DISCONN_RSP 0x07
+#define L2CAP_ECHO_REQ 0x08
+#define L2CAP_ECHO_RSP 0x09
+#define L2CAP_INFO_REQ 0x0a
+#define L2CAP_INFO_RSP 0x0b
+#define L2CAP_CREATE_CHAN_REQ 0x0c
+#define L2CAP_CREATE_CHAN_RSP 0x0d
+#define L2CAP_MOVE_CHAN_REQ 0x0e
+#define L2CAP_MOVE_CHAN_RSP 0x0f
+#define L2CAP_MOVE_CHAN_CFM 0x10
+#define L2CAP_MOVE_CHAN_CFM_RSP 0x11
#define L2CAP_CONN_PARAM_UPDATE_REQ 0x12
#define L2CAP_CONN_PARAM_UPDATE_RSP 0x13
@@ -98,36 +116,63 @@
#define L2CAP_FEAT_STREAMING 0x00000010
#define L2CAP_FEAT_FCS 0x00000020
#define L2CAP_FEAT_FIXED_CHAN 0x00000080
+#define L2CAP_FEAT_EXT_WINDOW 0x00000100
+#define L2CAP_FEAT_UCD 0x00000200
/* L2CAP checksum option */
#define L2CAP_FCS_NONE 0x00
#define L2CAP_FCS_CRC16 0x01
-/* L2CAP Control Field bit masks */
+/* L2CAP fixed channels */
+#define L2CAP_FC_L2CAP 0x02
+#define L2CAP_FC_A2MP 0x08
+
+/* L2CAP Control Field */
#define L2CAP_CTRL_SAR 0xC000
#define L2CAP_CTRL_REQSEQ 0x3F00
#define L2CAP_CTRL_TXSEQ 0x007E
-#define L2CAP_CTRL_RETRANS 0x0080
#define L2CAP_CTRL_FINAL 0x0080
#define L2CAP_CTRL_POLL 0x0010
#define L2CAP_CTRL_SUPERVISE 0x000C
#define L2CAP_CTRL_FRAME_TYPE 0x0001 /* I- or S-Frame */
#define L2CAP_CTRL_TXSEQ_SHIFT 1
+#define L2CAP_CTRL_SUPERVISE_SHIFT 2
+#define L2CAP_CTRL_POLL_SHIFT 4
+#define L2CAP_CTRL_FINAL_SHIFT 7
#define L2CAP_CTRL_REQSEQ_SHIFT 8
#define L2CAP_CTRL_SAR_SHIFT 14
-/* L2CAP Supervisory Function */
-#define L2CAP_SUPER_RCV_READY 0x0000
-#define L2CAP_SUPER_REJECT 0x0004
-#define L2CAP_SUPER_RCV_NOT_READY 0x0008
-#define L2CAP_SUPER_SELECT_REJECT 0x000C
+#define L2CAP_EXT_CTRL_SAR 0x00030000
+#define L2CAP_EXT_CTRL_REQSEQ 0x0000FFFC
+#define L2CAP_EXT_CTRL_TXSEQ 0xFFFC0000
+#define L2CAP_EXT_CTRL_FINAL 0x00000002
+#define L2CAP_EXT_CTRL_POLL 0x00040000
+#define L2CAP_EXT_CTRL_SUPERVISE 0x00030000
+#define L2CAP_EXT_CTRL_FRAME_TYPE 0x00000001 /* I- or S-Frame */
+
+#define L2CAP_EXT_CTRL_FINAL_SHIFT 1
+#define L2CAP_EXT_CTRL_REQSEQ_SHIFT 2
+#define L2CAP_EXT_CTRL_SAR_SHIFT 16
+#define L2CAP_EXT_CTRL_SUPERVISE_SHIFT 16
+#define L2CAP_EXT_CTRL_POLL_SHIFT 18
+#define L2CAP_EXT_CTRL_TXSEQ_SHIFT 18
+
+/* L2CAP Supervisory Frame Types */
+#define L2CAP_SFRAME_RR 0x00
+#define L2CAP_SFRAME_REJ 0x01
+#define L2CAP_SFRAME_RNR 0x02
+#define L2CAP_SFRAME_SREJ 0x03
/* L2CAP Segmentation and Reassembly */
-#define L2CAP_SDU_UNSEGMENTED 0x0000
-#define L2CAP_SDU_START 0x4000
-#define L2CAP_SDU_END 0x8000
-#define L2CAP_SDU_CONTINUE 0xC000
+#define L2CAP_SAR_UNSEGMENTED 0x00
+#define L2CAP_SAR_START 0x01
+#define L2CAP_SAR_END 0x02
+#define L2CAP_SAR_CONTINUE 0x03
+
+/* L2CAP ERTM / Streaming extra field lengths */
+#define L2CAP_SDULEN_SIZE 2
+#define L2CAP_FCS_SIZE 2
/* L2CAP structures */
struct l2cap_hdr {
@@ -135,6 +180,8 @@
__le16 cid;
} __packed;
#define L2CAP_HDR_SIZE 4
+#define L2CAP_ENHANCED_HDR_SIZE 6
+#define L2CAP_EXTENDED_HDR_SIZE 8
struct l2cap_cmd_hdr {
__u8 code;
@@ -162,6 +209,7 @@
/* channel indentifier */
#define L2CAP_CID_SIGNALING 0x0001
#define L2CAP_CID_CONN_LESS 0x0002
+#define L2CAP_CID_A2MP 0x0003
#define L2CAP_CID_LE_DATA 0x0004
#define L2CAP_CID_LE_SIGNALING 0x0005
#define L2CAP_CID_SMP 0x0006
@@ -197,6 +245,8 @@
#define L2CAP_CONF_UNACCEPT 0x0001
#define L2CAP_CONF_REJECT 0x0002
#define L2CAP_CONF_UNKNOWN 0x0003
+#define L2CAP_CONF_PENDING 0x0004
+#define L2CAP_CONF_FLOW_SPEC_REJECT 0x0005
struct l2cap_conf_opt {
__u8 type;
@@ -213,6 +263,13 @@
#define L2CAP_CONF_QOS 0x03
#define L2CAP_CONF_RFC 0x04
#define L2CAP_CONF_FCS 0x05
+#define L2CAP_CONF_EXT_FS 0x06
+#define L2CAP_CONF_EXT_WINDOW 0x07
+
+/* QOS Service type */
+#define L2CAP_SERVICE_NO_TRAFFIC 0x00
+#define L2CAP_SERVICE_BEST_EFFORT 0x01
+#define L2CAP_SERVICE_GUARANTEED 0x02
#define L2CAP_CONF_MAX_SIZE 22
@@ -225,6 +282,22 @@
__le16 max_pdu_size;
} __packed;
+struct l2cap_conf_ext_fs {
+ __u8 id;
+ __u8 type;
+ __le16 max_sdu;
+ __le32 sdu_arr_time;
+ __le32 acc_latency;
+ __le32 flush_to;
+} __packed;
+
+struct l2cap_conf_prm {
+ __u8 fcs;
+ __le16 retrans_timeout;
+ __le16 monitor_timeout;
+ __le32 flush_to;
+};
+
#define L2CAP_MODE_BASIC 0x00
#define L2CAP_MODE_RETRANS 0x01
#define L2CAP_MODE_FLOWCTL 0x02
@@ -251,6 +324,79 @@
__u8 data[0];
} __packed;
+struct l2cap_create_chan_req {
+ __le16 psm;
+ __le16 scid;
+ __u8 amp_id;
+} __attribute__ ((packed));
+
+struct l2cap_create_chan_rsp {
+ __le16 dcid;
+ __le16 scid;
+ __le16 result;
+ __le16 status;
+} __attribute__ ((packed));
+
+#define L2CAP_CREATE_CHAN_SUCCESS (0x0000)
+#define L2CAP_CREATE_CHAN_PENDING (0x0001)
+#define L2CAP_CREATE_CHAN_REFUSED_PSM (0x0002)
+#define L2CAP_CREATE_CHAN_REFUSED_SECURITY (0x0003)
+#define L2CAP_CREATE_CHAN_REFUSED_RESOURCES (0x0004)
+#define L2CAP_CREATE_CHAN_REFUSED_CONTROLLER (0x0005)
+
+#define L2CAP_CREATE_CHAN_STATUS_NONE (0x0000)
+#define L2CAP_CREATE_CHAN_STATUS_AUTHENTICATION (0x0001)
+#define L2CAP_CREATE_CHAN_STATUS_AUTHORIZATION (0x0002)
+
+struct l2cap_move_chan_req {
+ __le16 icid;
+ __u8 dest_amp_id;
+} __attribute__ ((packed));
+
+struct l2cap_move_chan_rsp {
+ __le16 icid;
+ __le16 result;
+} __attribute__ ((packed));
+
+#define L2CAP_MOVE_CHAN_SUCCESS (0x0000)
+#define L2CAP_MOVE_CHAN_PENDING (0x0001)
+#define L2CAP_MOVE_CHAN_REFUSED_CONTROLLER (0x0002)
+#define L2CAP_MOVE_CHAN_REFUSED_SAME_ID (0x0003)
+#define L2CAP_MOVE_CHAN_REFUSED_CONFIG (0x0004)
+#define L2CAP_MOVE_CHAN_REFUSED_COLLISION (0x0005)
+#define L2CAP_MOVE_CHAN_REFUSED_NOT_ALLOWED (0x0006)
+
+struct l2cap_move_chan_cfm {
+ __le16 icid;
+ __le16 result;
+} __attribute__ ((packed));
+
+#define L2CAP_MOVE_CHAN_CONFIRMED (0x0000)
+#define L2CAP_MOVE_CHAN_UNCONFIRMED (0x0001)
+
+struct l2cap_move_chan_cfm_rsp {
+ __le16 icid;
+} __attribute__ ((packed));
+
+struct l2cap_amp_signal_work {
+ struct work_struct work;
+ struct l2cap_cmd_hdr cmd;
+ struct l2cap_conn *conn;
+ struct sk_buff *skb;
+ u8 *data;
+};
+
+struct l2cap_resegment_work {
+ struct work_struct work;
+ struct sock *sk;
+};
+
+struct l2cap_logical_link_work {
+ struct work_struct work;
+ struct hci_chan *chan;
+ u8 status;
+};
+
/* info type */
#define L2CAP_IT_CL_MTU 0x0001
#define L2CAP_IT_FEAT_MASK 0x0002
@@ -275,98 +421,10 @@
#define L2CAP_CONN_PARAM_ACCEPTED 0x0000
#define L2CAP_CONN_PARAM_REJECTED 0x0001
-/* ----- L2CAP channels and connections ----- */
-struct srej_list {
- __u8 tx_seq;
- struct list_head list;
-};
-
-struct l2cap_chan {
- struct sock *sk;
-
- struct l2cap_conn *conn;
-
- __u8 state;
-
- atomic_t refcnt;
-
- __le16 psm;
- __u16 dcid;
- __u16 scid;
-
- __u16 imtu;
- __u16 omtu;
- __u16 flush_to;
- __u8 mode;
- __u8 chan_type;
-
- __le16 sport;
-
- __u8 sec_level;
- __u8 role_switch;
- __u8 force_reliable;
- __u8 flushable;
- __u8 force_active;
-
- __u8 ident;
-
- __u8 conf_req[64];
- __u8 conf_len;
- __u8 num_conf_req;
- __u8 num_conf_rsp;
-
- __u8 fcs;
-
- __u8 tx_win;
- __u8 max_tx;
- __u16 retrans_timeout;
- __u16 monitor_timeout;
- __u16 mps;
-
- unsigned long conf_state;
- unsigned long conn_state;
-
- __u8 next_tx_seq;
- __u8 expected_ack_seq;
- __u8 expected_tx_seq;
- __u8 buffer_seq;
- __u8 buffer_seq_srej;
- __u8 srej_save_reqseq;
- __u8 frames_sent;
- __u8 unacked_frames;
- __u8 retry_count;
- __u8 num_acked;
- __u16 sdu_len;
- __u16 partial_sdu_len;
- struct sk_buff *sdu;
-
- __u8 remote_tx_win;
- __u8 remote_max_tx;
- __u16 remote_mps;
-
- struct timer_list chan_timer;
- struct timer_list retrans_timer;
- struct timer_list monitor_timer;
- struct timer_list ack_timer;
- struct sk_buff *tx_send_head;
- struct sk_buff_head tx_q;
- struct sk_buff_head srej_q;
- struct list_head srej_l;
-
- struct list_head list;
- struct list_head global_l;
-
- void *data;
- struct l2cap_ops *ops;
-};
-
-struct l2cap_ops {
- char *name;
-
- struct l2cap_chan *(*new_connection) (void *data);
- int (*recv) (void *data, struct sk_buff *skb);
- void (*close) (void *data);
- void (*state_change) (void *data, int state);
+/* ----- L2CAP connections ----- */
+struct l2cap_chan_list {
+ struct sock *head;
+ rwlock_t lock;
};
struct l2cap_conn {
@@ -378,6 +436,8 @@
unsigned int mtu;
__u32 feat_mask;
+ __u8 fc_mask;
+ struct amp_mgr *mgr;
__u8 info_state;
__u8 info_ident;
@@ -401,100 +461,258 @@
struct timer_list security_timer;
- struct list_head chan_l;
- rwlock_t chan_lock;
+ struct l2cap_chan_list chan_list;
+};
+
+struct sock_del_list {
+ struct sock *sk;
+ struct list_head list;
};
#define L2CAP_INFO_CL_MTU_REQ_SENT 0x01
#define L2CAP_INFO_FEAT_MASK_REQ_SENT 0x04
#define L2CAP_INFO_FEAT_MASK_REQ_DONE 0x08
-#define L2CAP_CHAN_RAW 1
-#define L2CAP_CHAN_CONN_LESS 2
-#define L2CAP_CHAN_CONN_ORIENTED 3
-
-/* ----- L2CAP socket info ----- */
+/* ----- L2CAP channel and socket info ----- */
#define l2cap_pi(sk) ((struct l2cap_pinfo *) sk)
+#define TX_QUEUE(sk) (&l2cap_pi(sk)->tx_queue)
+#define SREJ_QUEUE(sk) (&l2cap_pi(sk)->srej_queue)
+
+struct l2cap_seq_list {
+ __u16 head;
+ __u16 tail;
+ __u16 size;
+ __u16 mask;
+ __u16 *list;
+};
struct l2cap_pinfo {
struct bt_sock bt;
- struct l2cap_chan *chan;
- struct sk_buff *rx_busy_skb;
+ __le16 psm;
+ __u16 dcid;
+ __u16 scid;
+
+ __u16 imtu;
+ __u16 omtu;
+ __u16 flush_to;
+ __u8 mode;
+ __u8 fixed_channel;
+ __u8 num_conf_req;
+ __u8 num_conf_rsp;
+
+ __u8 fcs;
+ __u8 sec_level;
+ __u8 role_switch;
+ __u8 force_reliable;
+ __u8 flushable;
+ __u8 force_active;
+
+ __u8 conf_req[64];
+ __u8 conf_len;
+ __u8 conf_ident;
+ __u16 conf_state;
+ __u8 conn_state;
+ __u8 tx_state;
+ __u8 rx_state;
+ __u8 reconf_state;
+
+ __u8 amp_id;
+ __u8 amp_move_id;
+ __u8 amp_move_state;
+ __u8 amp_move_role;
+ __u8 amp_move_cmd_ident;
+ __u16 amp_move_reqseq;
+ __u16 amp_move_event;
+
+ __u16 next_tx_seq;
+ __u16 expected_ack_seq;
+ __u16 expected_tx_seq;
+ __u16 buffer_seq;
+ __u16 srej_save_reqseq;
+ __u16 last_acked_seq;
+ __u32 frames_sent;
+ __u16 unacked_frames;
+ __u8 retry_count;
+ __u16 srej_queue_next;
+ __u16 sdu_len;
+ struct sk_buff *sdu;
+ struct sk_buff *sdu_last_frag;
+ atomic_t ertm_queued;
+
+ __u8 ident;
+
+ __u16 tx_win;
+ __u16 tx_win_max;
+ __u8 max_tx;
+ __u8 amp_pref;
+ __u16 remote_tx_win;
+ __u8 remote_max_tx;
+ __u8 extended_control;
+ __u16 retrans_timeout;
+ __u16 monitor_timeout;
+ __u16 remote_mps;
+ __u16 mps;
+
+ __le16 sport;
+
+ struct delayed_work retrans_work;
+ struct delayed_work monitor_work;
+ struct delayed_work ack_work;
+ struct work_struct tx_work;
+ struct sk_buff_head tx_queue;
+ struct sk_buff_head srej_queue;
+ struct l2cap_seq_list srej_list;
+ struct l2cap_seq_list retrans_list;
+ struct hci_conn *ampcon;
+ struct hci_chan *ampchan;
+ struct l2cap_conn *conn;
+ struct l2cap_conf_prm local_conf;
+ struct l2cap_conf_prm remote_conf;
+ struct l2cap_conf_ext_fs local_fs;
+ struct l2cap_conf_ext_fs remote_fs;
+ struct sock *next_c;
+ struct sock *prev_c;
};
-enum {
- CONF_REQ_SENT,
- CONF_INPUT_DONE,
- CONF_OUTPUT_DONE,
- CONF_MTU_DONE,
- CONF_MODE_DONE,
- CONF_CONNECT_PEND,
- CONF_NO_FCS_RECV,
- CONF_STATE2_DEVICE,
-};
+#define L2CAP_CONF_REQ_SENT 0x0001
+#define L2CAP_CONF_INPUT_DONE 0x0002
+#define L2CAP_CONF_OUTPUT_DONE 0x0004
+#define L2CAP_CONF_MTU_DONE 0x0008
+#define L2CAP_CONF_MODE_DONE 0x0010
+#define L2CAP_CONF_CONNECT_PEND 0x0020
+#define L2CAP_CONF_NO_FCS_RECV 0x0040
+#define L2CAP_CONF_STATE2_DEVICE 0x0080
+#define L2CAP_CONF_EXT_WIN_RECV 0x0100
+#define L2CAP_CONF_LOCKSTEP 0x0200
+#define L2CAP_CONF_LOCKSTEP_PEND 0x0400
+#define L2CAP_CONF_PEND_SENT 0x0800
+#define L2CAP_CONF_EFS_RECV 0x1000
#define L2CAP_CONF_MAX_CONF_REQ 2
#define L2CAP_CONF_MAX_CONF_RSP 2
-enum {
- CONN_SAR_SDU,
- CONN_SREJ_SENT,
- CONN_WAIT_F,
- CONN_SREJ_ACT,
- CONN_SEND_PBIT,
- CONN_REMOTE_BUSY,
- CONN_LOCAL_BUSY,
- CONN_REJ_ACT,
- CONN_SEND_FBIT,
- CONN_RNR_SENT,
-};
+#define L2CAP_RECONF_NONE 0x00
+#define L2CAP_RECONF_INT 0x01
+#define L2CAP_RECONF_ACC 0x02
-#define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t))
-#define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer)
-#define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \
- L2CAP_DEFAULT_RETRANS_TO);
-#define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer)
-#define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \
- L2CAP_DEFAULT_MONITOR_TO);
-#define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer)
-#define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \
- L2CAP_DEFAULT_ACK_TO);
-#define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer)
+#define L2CAP_CONN_SREJ_ACT 0x01
+#define L2CAP_CONN_REJ_ACT 0x02
+#define L2CAP_CONN_REMOTE_BUSY 0x04
+#define L2CAP_CONN_LOCAL_BUSY 0x08
+#define L2CAP_CONN_SEND_FBIT 0x10
+#define L2CAP_CONN_SENT_RNR 0x20
-static inline int l2cap_tx_window_full(struct l2cap_chan *ch)
-{
- int sub;
+#define L2CAP_SEQ_LIST_CLEAR 0xFFFF
+#define L2CAP_SEQ_LIST_TAIL 0x8000
- sub = (ch->next_tx_seq - ch->expected_ack_seq) % 64;
+#define L2CAP_ERTM_TX_STATE_XMIT 0x01
+#define L2CAP_ERTM_TX_STATE_WAIT_F 0x02
- if (sub < 0)
- sub += 64;
+#define L2CAP_ERTM_RX_STATE_RECV 0x01
+#define L2CAP_ERTM_RX_STATE_SREJ_SENT 0x02
+#define L2CAP_ERTM_RX_STATE_AMP_MOVE 0x03
+#define L2CAP_ERTM_RX_STATE_WAIT_P_FLAG 0x04
+#define L2CAP_ERTM_RX_STATE_WAIT_P_FLAG_RECONFIGURE 0x05
+#define L2CAP_ERTM_RX_STATE_WAIT_F_FLAG 0x06
- return sub == ch->remote_tx_win;
-}
+#define L2CAP_ERTM_TXSEQ_EXPECTED 0x00
+#define L2CAP_ERTM_TXSEQ_EXPECTED_SREJ 0x01
+#define L2CAP_ERTM_TXSEQ_UNEXPECTED 0x02
+#define L2CAP_ERTM_TXSEQ_UNEXPECTED_SREJ 0x03
+#define L2CAP_ERTM_TXSEQ_DUPLICATE 0x04
+#define L2CAP_ERTM_TXSEQ_DUPLICATE_SREJ 0x05
+#define L2CAP_ERTM_TXSEQ_INVALID 0x06
+#define L2CAP_ERTM_TXSEQ_INVALID_IGNORE 0x07
-#define __get_txseq(ctrl) (((ctrl) & L2CAP_CTRL_TXSEQ) >> 1)
-#define __get_reqseq(ctrl) (((ctrl) & L2CAP_CTRL_REQSEQ) >> 8)
-#define __is_iframe(ctrl) (!((ctrl) & L2CAP_CTRL_FRAME_TYPE))
-#define __is_sframe(ctrl) ((ctrl) & L2CAP_CTRL_FRAME_TYPE)
-#define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START)
+#define L2CAP_ERTM_EVENT_DATA_REQUEST 0x01
+#define L2CAP_ERTM_EVENT_LOCAL_BUSY_DETECTED 0x02
+#define L2CAP_ERTM_EVENT_LOCAL_BUSY_CLEAR 0x03
+#define L2CAP_ERTM_EVENT_RECV_REQSEQ_AND_FBIT 0x04
+#define L2CAP_ERTM_EVENT_RECV_FBIT 0x05
+#define L2CAP_ERTM_EVENT_RETRANS_TIMER_EXPIRES 0x06
+#define L2CAP_ERTM_EVENT_MONITOR_TIMER_EXPIRES 0x07
+#define L2CAP_ERTM_EVENT_EXPLICIT_POLL 0x08
+#define L2CAP_ERTM_EVENT_RECV_IFRAME 0x09
+#define L2CAP_ERTM_EVENT_RECV_RR 0x0a
+#define L2CAP_ERTM_EVENT_RECV_REJ 0x0b
+#define L2CAP_ERTM_EVENT_RECV_RNR 0x0c
+#define L2CAP_ERTM_EVENT_RECV_SREJ 0x0d
+#define L2CAP_ERTM_EVENT_RECV_FRAME 0x0e
+
+#define L2CAP_AMP_MOVE_NONE 0
+#define L2CAP_AMP_MOVE_INITIATOR 1
+#define L2CAP_AMP_MOVE_RESPONDER 2
+
+#define L2CAP_AMP_STATE_STABLE 0
+#define L2CAP_AMP_STATE_WAIT_CREATE 1
+#define L2CAP_AMP_STATE_WAIT_CREATE_RSP 2
+#define L2CAP_AMP_STATE_WAIT_MOVE 3
+#define L2CAP_AMP_STATE_WAIT_MOVE_RSP 4
+#define L2CAP_AMP_STATE_WAIT_MOVE_RSP_SUCCESS 5
+#define L2CAP_AMP_STATE_WAIT_MOVE_CONFIRM 6
+#define L2CAP_AMP_STATE_WAIT_MOVE_CONFIRM_RSP 7
+#define L2CAP_AMP_STATE_WAIT_LOGICAL_COMPLETE 8
+#define L2CAP_AMP_STATE_WAIT_LOGICAL_CONFIRM 9
+#define L2CAP_AMP_STATE_WAIT_LOCAL_BUSY 10
+#define L2CAP_AMP_STATE_WAIT_PREPARE 11
+#define L2CAP_AMP_STATE_RESEGMENT 12
+
+#define __delta_seq(x, y, pi) ((x) >= (y) ? (x) - (y) : \
+ (pi)->tx_win_max + 1 - (y) + (x))
+#define __next_seq(x, pi) ((x + 1) & ((pi)->tx_win_max))
extern int disable_ertm;
+extern const struct proto_ops l2cap_sock_ops;
+extern struct bt_sock_list l2cap_sk_list;
int l2cap_init_sockets(void);
void l2cap_cleanup_sockets(void);
-void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
+u8 l2cap_get_ident(struct l2cap_conn *conn);
+void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
+int l2cap_build_conf_req(struct sock *sk, void *data);
int __l2cap_wait_ack(struct sock *sk);
-int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
-int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
+struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len);
+struct sk_buff *l2cap_create_basic_pdu(struct sock *sk, struct msghdr *msg, size_t len);
+struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, struct msghdr *msg,
+ size_t len, u16 sdulen, int reseg);
+int l2cap_segment_sdu(struct sock *sk, struct sk_buff_head* seg_queue,
+ struct msghdr *msg, size_t len, int reseg);
+int l2cap_resegment_queue(struct sock *sk, struct sk_buff_head *queue);
+void l2cap_do_send(struct sock *sk, struct sk_buff *skb);
+void l2cap_streaming_send(struct sock *sk);
+int l2cap_ertm_send(struct sock *sk);
+int l2cap_strm_tx(struct sock *sk, struct sk_buff_head *skbs);
+int l2cap_ertm_tx(struct sock *sk, struct bt_l2cap_control *control,
+ struct sk_buff_head *skbs, u8 event);
-struct l2cap_chan *l2cap_chan_create(struct sock *sk);
-void l2cap_chan_close(struct l2cap_chan *chan, int reason);
-void l2cap_chan_destroy(struct l2cap_chan *chan);
-int l2cap_chan_connect(struct l2cap_chan *chan);
-int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len);
-void l2cap_chan_busy(struct l2cap_chan *chan, int busy);
+void l2cap_sock_set_timer(struct sock *sk, long timeout);
+void l2cap_sock_clear_timer(struct sock *sk);
+void __l2cap_sock_close(struct sock *sk, int reason);
+void l2cap_sock_kill(struct sock *sk);
+void l2cap_sock_init(struct sock *sk, struct sock *parent);
+struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
+ int proto, gfp_t prio);
+void l2cap_send_disconn_req(struct l2cap_conn *conn, struct sock *sk, int err);
+void l2cap_chan_del(struct sock *sk, int err);
+int l2cap_do_connect(struct sock *sk);
+int l2cap_data_channel(struct sock *sk, struct sk_buff *skb);
+void l2cap_amp_move_init(struct sock *sk);
+void l2cap_ertm_destruct(struct sock *sk);
+void l2cap_ertm_shutdown(struct sock *sk);
+void l2cap_ertm_recv_done(struct sock *sk);
+
+void l2cap_fixed_channel_config(struct sock *sk, struct l2cap_options *opt);
+
+void l2cap_recv_deferred_frame(struct sock *sk, struct sk_buff *skb);
+
+void l2cap_amp_physical_complete(int result, u8 remote_id, u8 local_id,
+ struct sock *sk);
+
+void l2cap_amp_logical_complete(int result, struct hci_conn *ampcon,
+ struct hci_chan *ampchan, struct sock *sk);
+
+void l2cap_amp_logical_destroyed(struct hci_conn *ampcon);
#endif /* __L2CAP_H */
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 5428fd3..f4ef131 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -197,20 +197,6 @@
bdaddr_t bdaddr;
} __packed;
-#define MGMT_OP_START_DISCOVERY 0x001B
-
-#define MGMT_OP_STOP_DISCOVERY 0x001C
-
-#define MGMT_OP_BLOCK_DEVICE 0x001D
-struct mgmt_cp_block_device {
- bdaddr_t bdaddr;
-} __packed;
-
-#define MGMT_OP_UNBLOCK_DEVICE 0x001E
-struct mgmt_cp_unblock_device {
- bdaddr_t bdaddr;
-} __packed;
-
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
@@ -242,7 +228,7 @@
#define MGMT_EV_NEW_KEY 0x000A
struct mgmt_ev_new_key {
- __u8 store_hint;
+ __u8 old_key_type;
struct mgmt_key_info key;
} __packed;
@@ -265,13 +251,11 @@
#define MGMT_EV_PIN_CODE_REQUEST 0x000E
struct mgmt_ev_pin_code_request {
bdaddr_t bdaddr;
- __u8 secure;
} __packed;
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
struct mgmt_ev_user_confirm_request {
bdaddr_t bdaddr;
- __u8 confirm_hint;
__le32 value;
} __packed;
@@ -299,5 +283,3 @@
bdaddr_t bdaddr;
__u8 name[MGMT_MAX_NAME_LENGTH];
} __packed;
-
-#define MGMT_EV_DISCOVERING 0x0014
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index d5eee20..6eac4a7 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -234,8 +234,7 @@
/* ---- RFCOMM DLCs (channels) ---- */
struct rfcomm_dlc *rfcomm_dlc_alloc(gfp_t prio);
void rfcomm_dlc_free(struct rfcomm_dlc *d);
-int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
- u8 channel);
+int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel);
int rfcomm_dlc_close(struct rfcomm_dlc *d, int reason);
int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
@@ -272,8 +271,7 @@
}
/* ---- RFCOMM sessions ---- */
-void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src,
- bdaddr_t *dst);
+void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst);
static inline void rfcomm_session_hold(struct rfcomm_session *s)
{
@@ -314,8 +312,7 @@
int rfcomm_init_sockets(void);
void rfcomm_cleanup_sockets(void);
-int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
- struct rfcomm_dlc **d);
+int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc **d);
/* ---- RFCOMM TTY ---- */
#define RFCOMM_MAX_DEV 256