-
Notifications
You must be signed in to change notification settings - Fork 4
/
blue.c
165 lines (138 loc) · 3.1 KB
/
blue.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
// TODO: This works currently only on Linux
#if defined(LINUX) || defined(__linux__)
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#endif
#include "blue.h"
// This is not really thread-safe
bool error;
#if defined(LINUX) || defined(__linux__)
int findConn(int s, int dev_id, long arg) {
struct hci_conn_list_req *cl;
struct hci_conn_info *ci;
if ((cl = malloc(HCI_MAX_DEV * sizeof(*ci) + sizeof(*cl))) == NULL) {
perror("malloc");
error = true;
return 0;
}
cl->dev_id = dev_id;
cl->conn_num = HCI_MAX_DEV;
ci = cl->conn_info;
if (ioctl(s, HCIGETCONNLIST, (void *)cl)) {
perror("Could not get connection list");
error = true;
free(cl);
return 0;
}
int i;
for (i = 0; i < cl->conn_num; i++, ci++) {
if (!bacmp((bdaddr_t *)arg, &ci->bdaddr)) {
free(cl);
return 1;
}
}
free(cl);
return 0;
}
#endif
int rssi(char *address) {
#if defined(LINUX) || defined(__linux__)
struct hci_conn_info_req *cr;
int8_t rssi;
int dd, dev_id;
bdaddr_t bdaddr;
str2ba(address, &bdaddr);
error = false;
dev_id = hci_for_each_dev(HCI_UP, findConn, (long)&bdaddr);
if (dev_id < 0) {
if (error) {
return BLUE_ERROR;
}
else {
return BLUE_NOT_CONNECTED;
}
}
dd = hci_open_dev(dev_id);
if (dd < 0) {
perror("Could not open HCI device");
return BLUE_ERROR;
}
if ((cr = malloc(sizeof(struct hci_conn_info_req) + sizeof(struct hci_conn_info))) == NULL) {
perror("malloc");
hci_close_dev(dd);
return BLUE_ERROR;
}
bacpy(&cr->bdaddr, &bdaddr);
cr->type = ACL_LINK;
if (ioctl(dd, HCIGETCONNINFO, (unsigned long)cr) < 0) {
perror("Could not get connection info");
free(cr);
hci_close_dev(dd);
return BLUE_ERROR;
}
if (hci_read_rssi(dd, htobs(cr->conn_info->handle), &rssi, 1000) < 0) {
perror("Could not read RSSI");
free(cr);
hci_close_dev(dd);
return BLUE_ERROR;
}
free(cr);
hci_close_dev(dd);
return rssi;
#else
return BLUE_NOT_SUPPORTED;
#endif
}
int lq(char *address) {
#if defined(LINUX) || defined(__linux__)
struct hci_conn_info_req *cr;
uint8_t lq;
int dd, dev_id;
bdaddr_t bdaddr;
str2ba(address, &bdaddr);
dev_id = hci_for_each_dev(HCI_UP, findConn, (long)&bdaddr);
if (dev_id < 0) {
if (error) {
return BLUE_ERROR;
}
else {
return BLUE_NOT_CONNECTED;
}
}
dd = hci_open_dev(dev_id);
if (dd < 0) {
perror("Could not open HCI device");
return BLUE_ERROR;
}
if ((cr = malloc(sizeof(struct hci_conn_info_req) + sizeof(struct hci_conn_info))) == NULL) {
perror("malloc");
hci_close_dev(dd);
return BLUE_ERROR;
}
bacpy(&cr->bdaddr, &bdaddr);
cr->type = ACL_LINK;
if (ioctl(dd, HCIGETCONNINFO, (unsigned long)cr) < 0) {
perror("Could not get connection info");
free(cr);
hci_close_dev(dd);
return BLUE_ERROR;
}
if (hci_read_link_quality(dd, htobs(cr->conn_info->handle), &lq, 1000) < 0) {
perror("Could not read link quality");
free(cr);
hci_close_dev(dd);
return BLUE_ERROR;
}
free(cr);
hci_close_dev(dd);
return lq;
#else
return BLUE_NOT_SUPPORTED;
#endif
}