|
Lines 69-74
Link Here
|
| 69 |
static int le_remove_device_from_white_list(int s, int argc, char *argv[]); |
69 |
static int le_remove_device_from_white_list(int s, int argc, char *argv[]); |
| 70 |
static int le_connect(int s, int argc, char *argv[]); |
70 |
static int le_connect(int s, int argc, char *argv[]); |
| 71 |
static void handle_le_connection_event(ng_hci_event_pkt_t* e, bool verbose); |
71 |
static void handle_le_connection_event(ng_hci_event_pkt_t* e, bool verbose); |
|
|
72 |
static int le_read_channel_map(int s, int argc, char *argv[]); |
| 73 |
static void handle_le_remote_features_event(ng_hci_event_pkt_t* e); |
| 72 |
|
74 |
|
| 73 |
static int |
75 |
static int |
| 74 |
le_set_scan_param(int s, int argc, char *argv[]) |
76 |
le_set_scan_param(int s, int argc, char *argv[]) |
|
Lines 1086-1091
Link Here
|
| 1086 |
return; |
1088 |
return; |
| 1087 |
} |
1089 |
} |
| 1088 |
|
1090 |
|
|
|
1091 |
static int |
| 1092 |
le_read_channel_map(int s, int argc, char *argv[]) |
| 1093 |
{ |
| 1094 |
ng_hci_le_read_channel_map_cp cp; |
| 1095 |
ng_hci_le_read_channel_map_rp rp; |
| 1096 |
int n; |
| 1097 |
char buffer[2048]; |
| 1098 |
|
| 1099 |
/* parse command parameters */ |
| 1100 |
switch (argc) { |
| 1101 |
case 1: |
| 1102 |
/* connection handle */ |
| 1103 |
if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff) |
| 1104 |
return (USAGE); |
| 1105 |
|
| 1106 |
cp.connection_handle = (uint16_t) (n & 0x0fff); |
| 1107 |
cp.connection_handle = htole16(cp.connection_handle); |
| 1108 |
break; |
| 1109 |
|
| 1110 |
default: |
| 1111 |
return (USAGE); |
| 1112 |
} |
| 1113 |
|
| 1114 |
n = sizeof(rp); |
| 1115 |
if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, |
| 1116 |
NG_HCI_OCF_LE_READ_CHANNEL_MAP), |
| 1117 |
(void *)&cp, sizeof(cp), (void *)&rp, &n) == ERROR) |
| 1118 |
return (ERROR); |
| 1119 |
|
| 1120 |
if (rp.status != 0x00) { |
| 1121 |
fprintf(stdout, |
| 1122 |
"Read channel map failed. Status: %s [%#02x]\n", |
| 1123 |
hci_status2str(rp.status), rp.status); |
| 1124 |
return (FAILED); |
| 1125 |
} |
| 1126 |
|
| 1127 |
fprintf(stdout, "Connection handle: %d\n", |
| 1128 |
le16toh(rp.connection_handle)); |
| 1129 |
fprintf(stdout, "Used channels:\n"); |
| 1130 |
fprintf(stdout, "\n%s\n", hci_le_chanmap2str(rp.le_channel_map, |
| 1131 |
buffer, sizeof(buffer))); |
| 1132 |
|
| 1133 |
return (OK); |
| 1134 |
} /* le_read_channel_map */ |
| 1135 |
|
| 1136 |
static int |
| 1137 |
le_read_remote_features(int s, int argc, char *argv[]) |
| 1138 |
{ |
| 1139 |
ng_hci_le_read_remote_used_features_cp cp; |
| 1140 |
ng_hci_status_rp rp; |
| 1141 |
int n, bufsize; |
| 1142 |
char b[512]; |
| 1143 |
|
| 1144 |
ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; |
| 1145 |
|
| 1146 |
/* parse command parameters */ |
| 1147 |
switch (argc) { |
| 1148 |
case 1: |
| 1149 |
/* connection handle */ |
| 1150 |
if (sscanf(argv[0], "%d", &n) != 1 || n <= 0 || n > 0x0eff) |
| 1151 |
return (USAGE); |
| 1152 |
|
| 1153 |
cp.connection_handle = (uint16_t) (n & 0x0fff); |
| 1154 |
cp.connection_handle = htole16(cp.connection_handle); |
| 1155 |
break; |
| 1156 |
|
| 1157 |
default: |
| 1158 |
return (USAGE); |
| 1159 |
} |
| 1160 |
|
| 1161 |
n = sizeof(rp); |
| 1162 |
if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_LE, |
| 1163 |
NG_HCI_OCF_LE_READ_REMOTE_USED_FEATURES), |
| 1164 |
(void *)&cp, sizeof(cp), (void *)&rp, &n) == ERROR) |
| 1165 |
return (ERROR); |
| 1166 |
|
| 1167 |
if (rp.status != 0x00) { |
| 1168 |
fprintf(stdout, |
| 1169 |
"Read remote features failed. Status: %s [%#02x]\n", |
| 1170 |
hci_status2str(rp.status), rp.status); |
| 1171 |
return (FAILED); |
| 1172 |
} |
| 1173 |
|
| 1174 |
/* wait for connection events */ |
| 1175 |
bufsize = sizeof(b); |
| 1176 |
if (hci_recv(s, b, &bufsize) == ERROR) { |
| 1177 |
return (ERROR); |
| 1178 |
} |
| 1179 |
|
| 1180 |
if (bufsize < sizeof(*e)) { |
| 1181 |
errno = EIO; |
| 1182 |
return (ERROR); |
| 1183 |
} |
| 1184 |
if (e->event == NG_HCI_EVENT_LE) { |
| 1185 |
handle_le_remote_features_event(e); |
| 1186 |
} |
| 1187 |
|
| 1188 |
return (OK); |
| 1189 |
} /* le_read_remote_features */ |
| 1190 |
|
| 1191 |
static void handle_le_remote_features_event(ng_hci_event_pkt_t* e) |
| 1192 |
{ |
| 1193 |
ng_hci_le_ep *ev_pkt; |
| 1194 |
ng_hci_le_read_remote_features_ep *feat_event; |
| 1195 |
char buffer[2048]; |
| 1196 |
|
| 1197 |
ev_pkt = (ng_hci_le_ep *)(e + 1); |
| 1198 |
|
| 1199 |
if (ev_pkt->subevent_code == NG_HCI_LEEV_READ_REMOTE_FEATURES_COMPL) { |
| 1200 |
feat_event =(ng_hci_le_read_remote_features_ep *)(ev_pkt + 1); |
| 1201 |
fprintf(stdout, "Handle: %d\n", |
| 1202 |
le16toh(feat_event->connection_handle)); |
| 1203 |
fprintf(stdout, |
| 1204 |
"Status: %s\n", |
| 1205 |
hci_status2str(feat_event->status)); |
| 1206 |
fprintf(stdout, "Features:\n%s\n", |
| 1207 |
hci_le_features2str(feat_event->features, |
| 1208 |
buffer, sizeof(buffer))); |
| 1209 |
} |
| 1210 |
|
| 1211 |
return; |
| 1212 |
} /* handle_le_remote_features_event */ |
| 1213 |
|
| 1214 |
|
| 1215 |
|
| 1089 |
struct hci_command le_commands[] = { |
1216 |
struct hci_command le_commands[] = { |
| 1090 |
{ |
1217 |
{ |
| 1091 |
"le_enable", |
1218 |
"le_enable", |
|
Lines 1196-1199
Link Here
|
| 1196 |
"Connect to an LE device", |
1323 |
"Connect to an LE device", |
| 1197 |
&le_connect |
1324 |
&le_connect |
| 1198 |
}, |
1325 |
}, |
|
|
1326 |
{ |
| 1327 |
"le_read_channel_map", |
| 1328 |
"le_read_channel_map <connection_handle>\n" |
| 1329 |
"Read the channel map for a connection", |
| 1330 |
&le_read_channel_map |
| 1331 |
}, |
| 1332 |
{ |
| 1333 |
"le_read_remote_features", |
| 1334 |
"le_read_remote_features <connection_handle>\n" |
| 1335 |
"Read supported features for the device\n" |
| 1336 |
"identified by the connection handle", |
| 1337 |
&le_read_remote_features |
| 1338 |
}, |
| 1199 |
}; |
1339 |
}; |