diff options
| -rw-r--r-- | include/hci.h | 154 | ||||
| -rw-r--r-- | include/hci_lib.h | 3 | ||||
| -rw-r--r-- | src/hci.c | 107 | 
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); @@ -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; | 
