summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/hci.h154
-rw-r--r--include/hci_lib.h3
-rw-r--r--src/hci.c107
3 files changed, 248 insertions, 16 deletions
diff --git a/include/hci.h b/include/hci.h
index eaab3964..a4f88146 100644
--- a/include/hci.h
+++ b/include/hci.h
@@ -188,6 +188,8 @@ enum {
#define HCI_SLOT_VIOLATION 0x34
#define HCI_ROLE_SWITCH_FAILED 0x35
#define HCI_EIR_TOO_LARGE 0x36
+#define HCI_SIMPLE_PAIRING_NOT_SUPPORTED 0x37
+#define HCI_HOST_BUSY_PAIRING 0x38
/* ACL flags */
#define ACL_CONT 0x01
@@ -249,6 +251,8 @@ enum {
#define LMP_EDR_3S_ESCO 0x80
#define LMP_EXT_INQ 0x01
+#define LMP_SIMPLE_PAIR 0x08
+#define LMP_ENCAPS_PDU 0x10
#define LMP_ERR_DAT_REP 0x20
#define LMP_NFLUSH_PKTS 0x40
@@ -473,6 +477,49 @@ typedef struct {
} __attribute__ ((packed)) reject_sync_conn_req_cp;
#define REJECT_SYNC_CONN_REQ_CP_SIZE 7
+#define OCF_IO_CAPABILITY_REPLY 0x002B
+typedef struct {
+ bdaddr_t bdaddr;
+ uint8_t capability;
+ uint8_t oob_data;
+ uint8_t authentication;
+} __attribute__ ((packed)) io_capability_reply_cp;
+#define IO_CAPABILITY_REPLY_CP_SIZE 9
+
+#define OCF_USER_CONFIRM_REPLY 0x002C
+typedef struct {
+ bdaddr_t bdaddr;
+} __attribute__ ((packed)) user_confirm_reply_cp;
+#define USER_CONFIRM_REPLY_CP_SIZE 6
+
+#define OCF_USER_CONFIRM_NEG_REPLY 0x002D
+
+#define OCF_USER_PASSKEY_REPLY 0x002E
+typedef struct {
+ bdaddr_t bdaddr;
+ uint32_t passkey;
+} __attribute__ ((packed)) user_passkey_reply_cp;
+#define USER_PASSKEY_REPLY_CP_SIZE 10
+
+#define OCF_USER_PASSKEY_NEG_REPLY 0x002F
+
+#define OCF_REMOTE_OOB_DATA_REPLY 0x0030
+typedef struct {
+ bdaddr_t bdaddr;
+ uint8_t hash[16];
+ uint8_t randomizer[16];
+} __attribute__ ((packed)) remote_oob_data_reply_cp;
+#define REMOTE_OOB_DATA_REPLY_CP_SIZE 38
+
+#define OCF_REMOTE_OOB_DATA_NEG_REPLY 0x0033
+
+#define OCF_IO_CAPABILITY_NEG_REPLY 0x0034
+typedef struct {
+ bdaddr_t bdaddr;
+ uint8_t reason;
+} __attribute__ ((packed)) io_capability_neg_reply_cp;
+#define IO_CAPABILITY_NEG_REPLY_CP_SIZE 7
+
/* Link Policy */
#define OGF_LINK_POLICY 0x02
@@ -980,6 +1027,31 @@ typedef struct {
} __attribute__ ((packed)) refresh_encryption_key_rp;
#define REFRESH_ENCRYPTION_KEY_RP_SIZE 1
+#define OCF_READ_SIMPLE_PAIRING_MODE 0x0055
+typedef struct {
+ uint8_t status;
+ uint8_t mode;
+} __attribute__ ((packed)) read_simple_pairing_mode_rp;
+#define READ_SIMPLE_PAIRING_MODE_RP_SIZE 2
+
+#define OCF_WRITE_SIMPLE_PAIRING_MODE 0x0056
+typedef struct {
+ uint8_t mode;
+} __attribute__ ((packed)) write_simple_pairing_mode_cp;
+#define WRITE_SIMPLE_PAIRING_MODE_CP_SIZE 1
+typedef struct {
+ uint8_t status;
+} __attribute__ ((packed)) write_simple_pairing_mode_rp;
+#define WRITE_SIMPLE_PAIRING_MODE_RP_SIZE 1
+
+#define OCF_READ_LOCAL_OOB_DATA 0x0057
+typedef struct {
+ uint8_t status;
+ uint8_t hash[16];
+ uint8_t randomizer[16];
+} __attribute__ ((packed)) read_local_oob_data_rp;
+#define READ_LOCAL_OOB_DATA_RP_SIZE 33
+
#define OCF_READ_INQUIRY_TRANSMIT_POWER_LEVEL 0x0058
typedef struct {
uint8_t status;
@@ -1021,6 +1093,17 @@ typedef struct {
} __attribute__ ((packed)) enhanced_flush_cp;
#define ENHANCED_FLUSH_CP_SIZE 3
+#define OCF_SEND_KEYPRESS_NOTIFY 0x0060
+typedef struct {
+ bdaddr_t bdaddr;
+ uint8_t type;
+} __attribute__ ((packed)) send_keypress_notify_cp;
+#define SEND_KEYPRESS_NOTIFY_CP_SIZE 7
+typedef struct {
+ uint8_t status;
+} __attribute__ ((packed)) send_keypress_notify_rp;
+#define SEND_KEYPRESS_NOTIFY_RP_SIZE 1
+
/* Informational Parameters */
#define OGF_INFO_PARAM 0x04
@@ -1141,6 +1224,22 @@ typedef struct {
/* Testing commands */
#define OGF_TESTING_CMD 0x3e
+#define OCF_READ_LOOPBACK_MODE 0x0001
+
+#define OCF_WRITE_LOOPBACK_MODE 0x0002
+
+#define OCF_ENABLE_DEVICE_UNDER_TEST_MODE 0x0003
+
+#define OCF_WRITE_SIMPLE_PAIRING_DEBUG_MODE 0x0004
+typedef struct {
+ uint8_t mode;
+} __attribute__ ((packed)) write_simple_pairing_debug_mode_cp;
+#define WRITE_SIMPLE_PAIRING_DEBUG_MODE_CP_SIZE 1
+typedef struct {
+ uint8_t status;
+} __attribute__ ((packed)) write_simple_pairing_debug_mode_rp;
+#define WRITE_SIMPLE_PAIRING_DEBUG_MODE_RP_SIZE 1
+
/* Vendor specific commands */
#define OGF_VENDOR_CMD 0x3f
@@ -1468,6 +1567,47 @@ typedef struct {
} __attribute__ ((packed)) evt_encryption_key_refresh_complete;
#define EVT_ENCRYPTION_KEY_REFRESH_COMPLETE_SIZE 3
+#define EVT_IO_CAPABILITY_REQUEST 0x31
+typedef struct {
+ bdaddr_t bdaddr;
+} __attribute__ ((packed)) evt_io_capability_request;
+#define EVT_IO_CAPABILITY_REQUEST_SIZE 6
+
+#define EVT_IO_CAPABILITY_RESPONSE 0x32
+typedef struct {
+ bdaddr_t bdaddr;
+ uint8_t capability;
+ uint8_t oob_data;
+ uint8_t authentication;
+} __attribute__ ((packed)) evt_io_capability_response;
+#define EVT_IO_CAPABILITY_RESPONSE_SIZE 9
+
+#define EVT_USER_CONFIRM_REQUEST 0x33
+typedef struct {
+ bdaddr_t bdaddr;
+ uint32_t passkey;
+} __attribute__ ((packed)) evt_user_confirm_request;
+#define EVT_USER_CONFIRM_REQUEST_SIZE 10
+
+#define EVT_USER_PASSKEY_REQUEST 0x34
+typedef struct {
+ bdaddr_t bdaddr;
+} __attribute__ ((packed)) evt_user_passkey_request;
+#define EVT_USER_PASSKEY_REQUEST_SIZE 6
+
+#define EVT_REMOTE_OOB_DATA_REQUEST 0x35
+typedef struct {
+ bdaddr_t bdaddr;
+} __attribute__ ((packed)) evt_remote_oob_data_request;
+#define EVT_REMOTE_OOB_DATA_REQUEST_SIZE 6
+
+#define EVT_SIMPLE_PAIRING_COMPLETE 0x36
+typedef struct {
+ uint8_t status;
+ bdaddr_t bdaddr;
+} __attribute__ ((packed)) evt_simple_pairing_complete;
+#define EVT_SIMPLE_PAIRING_COMPLETE_SIZE 7
+
#define EVT_LINK_SUPERVISION_TIMEOUT_CHANGED 0x38
typedef struct {
uint16_t handle;
@@ -1481,6 +1621,20 @@ typedef struct {
} __attribute__ ((packed)) evt_enhanced_flush_complete;
#define EVT_ENHANCED_FLUSH_COMPLETE_SIZE 2
+#define EVT_USER_PASSKEY_NOTIFY 0x3B
+typedef struct {
+ bdaddr_t bdaddr;
+ uint32_t passkey;
+} __attribute__ ((packed)) evt_user_passkey_notify;
+#define EVT_USER_PASSKEY_NOTIFY_SIZE 10
+
+#define EVT_KEYPRESS_NOTIFY 0x3C
+typedef struct {
+ bdaddr_t bdaddr;
+ uint8_t type;
+} __attribute__ ((packed)) evt_keypress_notify;
+#define EVT_KEYPRESS_NOTIFY_SIZE 7
+
#define EVT_REMOTE_HOST_FEATURES_NOTIFY 0x3D
typedef struct {
bdaddr_t bdaddr;
diff --git a/include/hci_lib.h b/include/hci_lib.h
index a784a08b..1215a62f 100644
--- a/include/hci_lib.h
+++ b/include/hci_lib.h
@@ -98,6 +98,9 @@ int hci_read_afh_mode(int dd, uint8_t *mode, int to);
int hci_write_afh_mode(int dd, uint8_t mode, int to);
int hci_read_ext_inquiry_response(int dd, uint8_t *fec, uint8_t *data, int to);
int hci_write_ext_inquiry_response(int dd, uint8_t fec, uint8_t *data, int to);
+int hci_read_simple_pairing_mode(int dd, uint8_t *mode, int to);
+int hci_write_simple_pairing_mode(int dd, uint8_t mode, int to);
+int hci_read_local_oob_data(int dd, uint8_t *hash, uint8_t *randomizer, int to);
int hci_read_transmit_power_level(int dd, uint16_t handle, uint8_t type, int8_t *level, int to);
int hci_read_link_supervision_timeout(int dd, uint16_t handle, uint16_t *timeout, int to);
int hci_write_link_supervision_timeout(int dd, uint16_t handle, uint16_t timeout, int to);
diff --git a/src/hci.c b/src/hci.c
index 04da6de5..d3e81d2c 100644
--- a/src/hci.c
+++ b/src/hci.c
@@ -467,9 +467,9 @@ static hci_map commands_map[] = {
{ "Refresh Encryption Key", 138 },
{ "Reserved", 139 },
{ "Sniff Subrating", 140 },
- { "Unknown", 141 },
- { "Unknown", 142 },
- { "Unknown", 143 },
+ { "Read Simple Pairing Mode", 141 },
+ { "Write Simple Pairing Mode", 142 },
+ { "Read Local OOB Data", 143 },
{ "Read Inquiry Transmit Power Level", 144 },
{ "Write Inquiry Transmit Power Level", 145 },
@@ -478,21 +478,21 @@ static hci_map commands_map[] = {
{ "Reserved", 148 },
{ "Reserved", 149 },
{ "Reserved", 150 },
- { "Unknown", 151 },
-
- { "Unknown", 152 },
- { "Unknown", 153 },
- { "Unknown", 154 },
- { "Unknown", 155 },
- { "Unknown", 156 },
- { "Unknown", 157 },
+ { "IO Capability Request Reply", 151 },
+
+ { "User Confirmation Request Reply", 152 },
+ { "User Confirmation Request Negative Reply", 153 },
+ { "User Passkey Request Reply", 154 },
+ { "User Passkey Request Negative Reply", 155 },
+ { "Remote OOB Data Request Reply", 156 },
+ { "Write Simple Pairing Debug Mode", 157 },
{ "Enhanced Flush", 158 },
- { "Unknown", 159 },
+ { "Remote OOB Data Request Negative Reply", 159 },
{ "Reserved", 160 },
{ "Reserved", 161 },
- { "Unknown", 162 },
- { "Unknown", 163 },
+ { "Send Keypress Notification", 162 },
+ { "IO Capabilities Response Negative Reply", 163 },
{ "Reserved", 164 },
{ "Reserved", 165 },
{ "Reserved", 166 },
@@ -646,8 +646,8 @@ static hci_map lmp_features_map[8][9] = {
{ "<extended inquiry>", LMP_EXT_INQ }, /* Bit 0 */
{ "<no. 49>", 0x02 }, /* Bit 1 */
{ "<no. 50>", 0x04 }, /* Bit 2 */
- { "<no. 51>", 0x08 }, /* Bit 3 */
- { "<no. 52>", 0x10 }, /* Bit 4 */
+ { "<simple pairing>", LMP_SIMPLE_PAIR }, /* Bit 3 */
+ { "<encapsulated PDU>", LMP_ENCAPS_PDU }, /* Bit 4 */
{ "<err. data report>", LMP_ERR_DAT_REP }, /* Bit 5 */
{ "<non-flush flag>", LMP_NFLUSH_PKTS }, /* Bit 6 */
{ "<no. 55>", 0x80 }, /* Bit 7 */
@@ -2060,6 +2060,81 @@ int hci_write_ext_inquiry_response(int dd, uint8_t fec, uint8_t *data, int to)
return 0;
}
+int hci_read_simple_pairing_mode(int dd, uint8_t *mode, int to)
+{
+ read_simple_pairing_mode_rp rp;
+ struct hci_request rq;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_READ_SIMPLE_PAIRING_MODE;
+ rq.rparam = &rp;
+ rq.rlen = READ_SIMPLE_PAIRING_MODE_RP_SIZE;
+
+ if (hci_send_req(dd, &rq, to) < 0)
+ return -1;
+
+ if (rp.status) {
+ errno = EIO;
+ return -1;
+ }
+
+ *mode = rp.mode;
+ return 0;
+}
+
+int hci_write_simple_pairing_mode(int dd, uint8_t mode, int to)
+{
+ write_simple_pairing_mode_cp cp;
+ write_simple_pairing_mode_rp rp;
+ struct hci_request rq;
+
+ memset(&cp, 0, sizeof(cp));
+ cp.mode = mode;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_WRITE_SIMPLE_PAIRING_MODE;
+ rq.cparam = &cp;
+ rq.clen = WRITE_SIMPLE_PAIRING_MODE_CP_SIZE;
+ rq.rparam = &rp;
+ rq.rlen = WRITE_SIMPLE_PAIRING_MODE_RP_SIZE;
+
+ if (hci_send_req(dd, &rq, to) < 0)
+ return -1;
+
+ if (rp.status) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+int hci_read_local_oob_data(int dd, uint8_t *hash, uint8_t *randomizer, int to)
+{
+ read_local_oob_data_rp rp;
+ struct hci_request rq;
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_HOST_CTL;
+ rq.ocf = OCF_READ_LOCAL_OOB_DATA;
+ rq.rparam = &rp;
+ rq.rlen = READ_LOCAL_OOB_DATA_RP_SIZE;
+
+ if (hci_send_req(dd, &rq, to) < 0)
+ return -1;
+
+ if (rp.status) {
+ errno = EIO;
+ return -1;
+ }
+
+ memcpy(hash, rp.hash, 16);
+ memcpy(randomizer, rp.randomizer, 16);
+ return 0;
+}
+
int hci_read_transmit_power_level(int dd, uint16_t handle, uint8_t type, int8_t *level, int to)
{
read_transmit_power_level_cp cp;