summaryrefslogtreecommitdiffstats
path: root/tools/idevicebtlogger.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/idevicebtlogger.c')
-rw-r--r--tools/idevicebtlogger.c106
1 files changed, 93 insertions, 13 deletions
diff --git a/tools/idevicebtlogger.c b/tools/idevicebtlogger.c
index b73d958..c780143 100644
--- a/tools/idevicebtlogger.c
+++ b/tools/idevicebtlogger.c
@@ -32,6 +32,8 @@
32#include <stdlib.h> 32#include <stdlib.h>
33#include <unistd.h> 33#include <unistd.h>
34#include <getopt.h> 34#include <getopt.h>
35#include <assert.h>
36#include <fcntl.h>
35 37
36#ifdef WIN32 38#ifdef WIN32
37#include <windows.h> 39#include <windows.h>
@@ -57,7 +59,14 @@ static idevice_t device = NULL;
57static bt_packet_logger_client_t bt_packet_logger = NULL; 59static bt_packet_logger_client_t bt_packet_logger = NULL;
58static int use_network = 0; 60static int use_network = 0;
59static char* out_filename = NULL; 61static char* out_filename = NULL;
60static pcap_dumper_t * dump; 62static char* log_format_string = NULL;
63static pcap_dumper_t * pcap_dumper = NULL;
64static int packetlogger_fd = -1;
65
66static enum {
67 LOG_FORMAT_PACKETLOGGER,
68 LOG_FORMAT_PCAP
69} log_format = LOG_FORMAT_PACKETLOGGER;
61 70
62typedef enum { 71typedef enum {
63 HCI_COMMAND = 0x00, 72 HCI_COMMAND = 0x00,
@@ -67,9 +76,17 @@ typedef enum {
67} PacketLoggerPacketType; 76} PacketLoggerPacketType;
68 77
69/** 78/**
79 * Callback from the packet logger service to handle packets and log to PacketLoggger format
80 */
81static void bt_packet_logger_callback_packetlogger(uint8_t * data, uint16_t len, void *user_data)
82{
83 write(packetlogger_fd, data, len);
84}
85
86/**
70 * Callback from the packet logger service to handle packets and log to pcap 87 * Callback from the packet logger service to handle packets and log to pcap
71 */ 88 */
72static void bt_packet_logger_callback(uint8_t * data, uint16_t len, void *user_data) 89static void bt_packet_logger_callback_pcap(uint8_t * data, uint16_t len, void *user_data)
73{ 90{
74 bt_packet_logger_header_t * header = (bt_packet_logger_header_t *)data; 91 bt_packet_logger_header_t * header = (bt_packet_logger_header_t *)data;
75 uint16_t offset = sizeof(bt_packet_logger_header_t); 92 uint16_t offset = sizeof(bt_packet_logger_header_t);
@@ -126,8 +143,8 @@ static void bt_packet_logger_callback(uint8_t * data, uint16_t len, void *user_d
126 // having to memcpy things around. 143 // having to memcpy things around.
127 offset -= sizeof(uint32_t); 144 offset -= sizeof(uint32_t);
128 *(uint32_t*)&data[offset] = direction; 145 *(uint32_t*)&data[offset] = direction;
129 pcap_dump((unsigned char*)dump, &pcap_header, &data[offset]); 146 pcap_dump((unsigned char*)pcap_dumper, &pcap_header, &data[offset]);
130 pcap_dump_flush(dump); 147 pcap_dump_flush(pcap_dumper);
131 } 148 }
132} 149}
133 150
@@ -173,7 +190,19 @@ static int start_logging(void)
173 bt_packet_logger_client_start_service(device, &bt_packet_logger, TOOL_NAME); 190 bt_packet_logger_client_start_service(device, &bt_packet_logger, TOOL_NAME);
174 191
175 /* start capturing bt_packet_logger */ 192 /* start capturing bt_packet_logger */
176 bt_packet_logger_error_t serr = bt_packet_logger_start_capture(bt_packet_logger, bt_packet_logger_callback, NULL); 193 void (*callback)(uint8_t * data, uint16_t len, void *user_data);
194 switch (log_format){
195 case LOG_FORMAT_PCAP:
196 callback = bt_packet_logger_callback_pcap;
197 break;
198 case LOG_FORMAT_PACKETLOGGER:
199 callback = bt_packet_logger_callback_packetlogger;
200 break;
201 default:
202 assert(0);
203 return 0;
204 }
205 bt_packet_logger_error_t serr = bt_packet_logger_start_capture(bt_packet_logger, callback, NULL);
177 if (serr != BT_PACKET_LOGGER_E_SUCCESS) { 206 if (serr != BT_PACKET_LOGGER_E_SUCCESS) {
178 fprintf(stderr, "ERROR: Unable to start capturing bt_packet_logger.\n"); 207 fprintf(stderr, "ERROR: Unable to start capturing bt_packet_logger.\n");
179 bt_packet_logger_client_free(bt_packet_logger); 208 bt_packet_logger_client_free(bt_packet_logger);
@@ -243,12 +272,13 @@ static void print_usage(int argc, char **argv, int is_error)
243 "Capture HCI packets from a connected device.\n" \ 272 "Capture HCI packets from a connected device.\n" \
244 "\n" \ 273 "\n" \
245 "OPTIONS:\n" \ 274 "OPTIONS:\n" \
246 " -u, --udid UDID target specific device by UDID\n" \ 275 " -u, --udid UDID target specific device by UDID\n" \
247 " -n, --network connect to network device\n" \ 276 " -n, --network connect to network device\n" \
248 " -x, --exit exit when device disconnects\n" \ 277 " -f, --format FORMAT logging format: packetlogger (default) or pcap\n" \
249 " -h, --help prints usage information\n" \ 278 " -x, --exit exit when device disconnects\n" \
250 " -d, --debug enable communication debugging\n" \ 279 " -h, --help prints usage information\n" \
251 " -v, --version prints version information\n" \ 280 " -d, --debug enable communication debugging\n" \
281 " -v, --version prints version information\n" \
252 "\n" \ 282 "\n" \
253 "Homepage: <" PACKAGE_URL ">\n" 283 "Homepage: <" PACKAGE_URL ">\n"
254 "Bug Reports: <" PACKAGE_BUGREPORT ">\n" 284 "Bug Reports: <" PACKAGE_BUGREPORT ">\n"
@@ -265,6 +295,7 @@ int main(int argc, char *argv[])
265 { "debug", no_argument, NULL, 'd' }, 295 { "debug", no_argument, NULL, 'd' },
266 { "help", no_argument, NULL, 'h' }, 296 { "help", no_argument, NULL, 'h' },
267 { "udid", required_argument, NULL, 'u' }, 297 { "udid", required_argument, NULL, 'u' },
298 { "format", required_argument, NULL, 'f' },
268 { "network", no_argument, NULL, 'n' }, 299 { "network", no_argument, NULL, 'n' },
269 { "exit", no_argument, NULL, 'x' }, 300 { "exit", no_argument, NULL, 'x' },
270 { "version", no_argument, NULL, 'v' }, 301 { "version", no_argument, NULL, 'v' },
@@ -278,7 +309,7 @@ int main(int argc, char *argv[])
278 signal(SIGPIPE, SIG_IGN); 309 signal(SIGPIPE, SIG_IGN);
279#endif 310#endif
280 311
281 while ((c = getopt_long(argc, argv, "dhu:nxv", longopts, NULL)) != -1) { 312 while ((c = getopt_long(argc, argv, "dhu:f:nxv", longopts, NULL)) != -1) {
282 switch (c) { 313 switch (c) {
283 case 'd': 314 case 'd':
284 idevice_set_debug_level(1); 315 idevice_set_debug_level(1);
@@ -292,6 +323,15 @@ int main(int argc, char *argv[])
292 free(udid); 323 free(udid);
293 udid = strdup(optarg); 324 udid = strdup(optarg);
294 break; 325 break;
326 case 'f':
327 if (!*optarg) {
328 fprintf(stderr, "ERROR: FORMAT must not be empty!\n");
329 print_usage(argc, argv, 1);
330 return 2;
331 }
332 free(log_format_string);
333 log_format_string = strdup(optarg);
334 break;
295 case 'n': 335 case 'n':
296 use_network = 1; 336 use_network = 1;
297 break; 337 break;
@@ -319,10 +359,23 @@ int main(int argc, char *argv[])
319 return 2; 359 return 2;
320 } 360 }
321 361
362 if (log_format_string != NULL){
363 if (strcmp("packetlogger", log_format_string) == 0){
364 log_format = LOG_FORMAT_PACKETLOGGER;
365 } else if (strcmp("pcap", log_format_string) == 0){
366 log_format = LOG_FORMAT_PCAP;
367 } else {
368 printf("Unknown logging format: '%s'\n", log_format_string);
369 print_usage(argc, argv, 1);
370 return 2;
371 }
372 }
373
322 int num = 0; 374 int num = 0;
323 idevice_info_t *devices = NULL; 375 idevice_info_t *devices = NULL;
324 idevice_get_device_list_extended(&devices, &num); 376 idevice_get_device_list_extended(&devices, &num);
325 idevice_device_list_extended_free(devices); 377 idevice_device_list_extended_free(devices);
378 int oflags;
326 if (num == 0) { 379 if (num == 0) {
327 if (!udid) { 380 if (!udid) {
328 fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n"); 381 fprintf(stderr, "No device found. Plug in a device or pass UDID with -u to wait for device to be available.\n");
@@ -332,7 +385,27 @@ int main(int argc, char *argv[])
332 } 385 }
333 } 386 }
334 387
335 dump = pcap_dump_open(pcap_open_dead(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, BT_MAX_PACKET_SIZE), out_filename); 388 switch (log_format){
389 case LOG_FORMAT_PCAP:
390 printf("Output Format: PCAP\n");
391 pcap_dumper = pcap_dump_open(pcap_open_dead(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, BT_MAX_PACKET_SIZE), out_filename);
392 break;
393 case LOG_FORMAT_PACKETLOGGER:
394 printf("Output Format: PacketLogger\n");
395 oflags = O_WRONLY | O_CREAT | O_TRUNC;
396#ifdef WIN32
397 default_oflags |= O_BINARY;
398#endif
399 packetlogger_fd = open(out_filename, oflags);
400 if (packetlogger_fd < 0){
401 fprintf(stderr, "Failed to open file %s, errno = %d\n", out_filename, errno);
402 return -2;
403 }
404 break;
405 default:
406 assert(0);
407 return -2;
408 }
336 idevice_event_subscribe(device_event_cb, NULL); 409 idevice_event_subscribe(device_event_cb, NULL);
337 410
338 while (!quit_flag) { 411 while (!quit_flag) {
@@ -342,6 +415,13 @@ int main(int argc, char *argv[])
342 idevice_event_unsubscribe(); 415 idevice_event_unsubscribe();
343 stop_logging(); 416 stop_logging();
344 417
418 if (pcap_dumper) {
419 pcap_dump_close(pcap_dumper);
420 }
421 if (packetlogger_fd >= 0){
422 close(packetlogger_fd);
423 }
424
345 free(udid); 425 free(udid);
346 426
347 return 0; 427 return 0;