Created
May 1, 2017 23:01
-
-
Save andersson/259c25e9c6a00386c19e707e0ac14cc4 to your computer and use it in GitHub Desktop.
"btmgmt public-address"-alternative
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <sys/socket.h> | |
#include <err.h> | |
#include <errno.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <unistd.h> | |
struct sockaddr_hci { | |
sa_family_t hci_family; | |
unsigned short hci_dev; | |
unsigned short hci_channel; | |
}; | |
#define BTPROTO_HCI 1 | |
#define HCI_DEV_NONE 0xffff | |
#define HCI_CHANNEL_CONTROL 3 | |
struct hci_set_public_address { | |
uint16_t cmd; | |
uint16_t dev; | |
uint16_t len; | |
uint8_t addr[6]; | |
}; | |
struct hci_response { | |
uint16_t event; | |
uint16_t dev; | |
uint16_t len; | |
uint16_t cmd; | |
uint8_t status; | |
}; | |
static int hci_set_public_address(uint8_t mac_addr[6]) | |
{ | |
struct hci_set_public_address pub_addr; | |
struct hci_response resp; | |
struct sockaddr_hci addr; | |
int ret; | |
int fd; | |
int i; | |
pub_addr.cmd = 57; | |
pub_addr.dev = 0; | |
pub_addr.len = 6; | |
for (i = 0; i < 6; i++) | |
pub_addr.addr[i] = mac_addr[5-i]; | |
fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); | |
if (fd < 0) | |
err(1, "failed to create bt hci socket"); | |
memset(&addr, 0, sizeof(addr)); | |
addr.hci_family = AF_BLUETOOTH; | |
addr.hci_dev = HCI_DEV_NONE; | |
addr.hci_channel = HCI_CHANNEL_CONTROL; | |
if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) | |
err(1, "failed to bind to hci control channel"); | |
ret = send(fd, &pub_addr, sizeof(pub_addr), 0); | |
if (ret < 0) | |
err(1, "failed to send public address request"); | |
for (;;) { | |
ret = read(fd, &resp, sizeof(resp)); | |
if (ret < 0) | |
err(1, "failed to read response from hci mgmt"); | |
switch (resp.event) { | |
case 1: | |
case 2: | |
if (resp.cmd != 57) | |
continue; | |
close(fd); | |
switch (resp.status) { | |
case 0x0a: | |
return -EBUSY; | |
case 0x14: | |
return -EPERM; | |
default: | |
return -resp.status; | |
} | |
default: | |
printf("unknown %d\n", resp.event); | |
break; | |
} | |
} | |
close(fd); | |
return -ENXIO; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment