3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2011-2012 Intel Corporation
6 * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
39 #include <bluetooth/bluetooth.h>
40 #include <bluetooth/hci.h>
41 #include <bluetooth/hci_lib.h>
47 static unsigned long filter_mask = 0;
49 void packet_set_filter(unsigned long filter)
54 static void print_channel_header(struct timeval *tv, uint16_t index,
57 if (filter_mask & PACKET_FILTER_SHOW_INDEX) {
59 case HCI_CHANNEL_CONTROL:
60 printf("{hci%d} ", index);
62 case HCI_CHANNEL_MONITOR:
63 printf("[hci%d] ", index);
69 time_t t = tv->tv_sec;
74 if (filter_mask & PACKET_FILTER_SHOW_DATE)
75 printf("%04d-%02d-%02d ", tm.tm_year + 1900,
76 tm.tm_mon + 1, tm.tm_mday);
78 if (filter_mask & PACKET_FILTER_SHOW_TIME)
79 printf("%02d:%02d:%02d.%06lu ", tm.tm_hour,
80 tm.tm_min, tm.tm_sec, tv->tv_usec);
84 static void print_header(struct timeval *tv, uint16_t index)
86 print_channel_header(tv, index, HCI_CHANNEL_MONITOR);
89 void packet_hexdump(const unsigned char *buf, uint16_t len)
91 static const char hexdigits[] = "0123456789abcdef";
98 for (i = 0; i < len; i++) {
99 str[((i % 16) * 3) + 0] = hexdigits[buf[i] >> 4];
100 str[((i % 16) * 3) + 1] = hexdigits[buf[i] & 0xf];
101 str[((i % 16) * 3) + 2] = ' ';
102 str[(i % 16) + 49] = isprint(buf[i]) ? buf[i] : '.';
104 if ((i + 1) % 16 == 0) {
108 printf("%-12c%s\n", ' ', str);
115 for (j = (i % 16); j < 16; j++) {
116 str[(j * 3) + 0] = ' ';
117 str[(j * 3) + 1] = ' ';
118 str[(j * 3) + 2] = ' ';
124 printf("%-12c%s\n", ' ', str);
128 void packet_control(struct timeval *tv, uint16_t index, uint16_t opcode,
129 const void *data, uint16_t size)
131 print_channel_header(tv, index, HCI_CHANNEL_CONTROL);
133 control_message(opcode, data, size);
136 #define MONITOR_NEW_INDEX 0
137 #define MONITOR_DEL_INDEX 1
138 #define MONITOR_COMMAND_PKT 2
139 #define MONITOR_EVENT_PKT 3
140 #define MONITOR_ACL_TX_PKT 4
141 #define MONITOR_ACL_RX_PKT 5
142 #define MONITOR_SCO_TX_PKT 6
143 #define MONITOR_SCO_RX_PKT 7
145 struct monitor_new_index {
150 } __attribute__((packed));
152 #define MONITOR_NEW_INDEX_SIZE 16
154 #define MONITOR_DEL_INDEX_SIZE 0
158 static struct monitor_new_index index_list[MAX_INDEX];
160 void packet_monitor(struct timeval *tv, uint16_t index, uint16_t opcode,
161 const void *data, uint16_t size)
163 const struct monitor_new_index *ni;
167 case MONITOR_NEW_INDEX:
170 if (index < MAX_INDEX)
171 memcpy(&index_list[index], ni, MONITOR_NEW_INDEX_SIZE);
173 ba2str(&ni->bdaddr, str);
174 packet_new_index(tv, index, str, ni->type, ni->bus, ni->name);
176 case MONITOR_DEL_INDEX:
177 if (index < MAX_INDEX)
178 ba2str(&index_list[index].bdaddr, str);
180 ba2str(BDADDR_ANY, str);
182 packet_del_index(tv, index, str);
184 case MONITOR_COMMAND_PKT:
185 packet_hci_command(tv, index, data, size);
187 case MONITOR_EVENT_PKT:
188 packet_hci_event(tv, index, data, size);
190 case MONITOR_ACL_TX_PKT:
191 packet_hci_acldata(tv, index, false, data, size);
193 case MONITOR_ACL_RX_PKT:
194 packet_hci_acldata(tv, index, true, data, size);
196 case MONITOR_SCO_TX_PKT:
197 packet_hci_scodata(tv, index, false, data, size);
199 case MONITOR_SCO_RX_PKT:
200 packet_hci_scodata(tv, index, true, data, size);
203 print_header(tv, index);
204 printf("* Unknown packet (code %d len %d)\n", opcode, size);
205 packet_hexdump(data, size);
210 static const struct {
213 } opcode2str_table[] = {
214 /* OGF 1 - Link Control */
215 { 0x0401, "Inquiry" },
216 { 0x0402, "Inquiry Cancel" },
217 { 0x0403, "Periodic Inquiry Mode" },
218 { 0x0404, "Exit Periodic Inquiry Mode" },
219 { 0x0405, "Create Connection" },
220 { 0x0406, "Disconnect" },
221 { 0x0407, "Add SCO Connection" },
222 { 0x0408, "Create Connection Cancel" },
223 { 0x0409, "Accept Connection Request" },
224 { 0x040a, "Reject Connection Request" },
225 { 0x040b, "Link Key Request Reply" },
226 { 0x040c, "Link Key Request Negative Reply" },
227 { 0x040d, "PIN Code Request Reply" },
228 { 0x040e, "PIN Code Request Negative Reply" },
229 { 0x040f, "Change Connection Packet Type" },
230 /* reserved command */
231 { 0x0411, "Authentication Requested" },
232 /* reserved command */
233 { 0x0413, "Set Connection Encryption" },
234 /* reserved command */
235 { 0x0415, "Change Connection Link Key" },
236 /* reserved command */
237 { 0x0417, "Master Link Key" },
238 /* reserved command */
239 { 0x0419, "Remote Name Request" },
240 { 0x041a, "Remote Name Request Cancel" },
241 { 0x041b, "Read Remote Supported Features" },
242 { 0x041c, "Read Remote Extended Features" },
243 { 0x041d, "Read Remote Version Information" },
244 /* reserved command */
245 { 0x041f, "Read Clock Offset" },
246 { 0x0420, "Read LMP Handle" },
247 /* reserved commands */
248 { 0x0428, "Setup Synchronous Connection" },
249 { 0x0429, "Accept Synchronous Connection" },
250 { 0x042a, "Reject Synchronous Connection" },
251 { 0x042b, "IO Capability Request Reply" },
252 { 0x042c, "User Confirmation Request Reply" },
253 { 0x042d, "User Confirmation Request Neg Reply" },
254 { 0x042e, "User Passkey Request Reply" },
255 { 0x042f, "User Passkey Request Negative Reply" },
256 { 0x0430, "Remote OOB Data Request Reply" },
257 /* reserved commands */
258 { 0x0433, "Remote OOB Data Request Neg Reply" },
259 { 0x0434, "IO Capability Request Negative Reply"},
260 { 0x0435, "Create Physical Link" },
261 { 0x0436, "Accept Physical Link" },
262 { 0x0437, "Disconnect Physical Link" },
263 { 0x0438, "Create Logical Link" },
264 { 0x0439, "Accept Logical Link" },
265 { 0x043a, "Disconnect Logical Link" },
266 { 0x043b, "Logical Link Cancel" },
267 { 0x043c, "Flow Specifcation Modify" },
269 /* OGF 2 - Link Policy */
270 { 0x0801, "Holde Mode" },
271 /* reserved command */
272 { 0x0803, "Sniff Mode" },
273 { 0x0804, "Exit Sniff Mode" },
274 { 0x0805, "Park State" },
275 { 0x0806, "Exit Park State" },
276 { 0x0807, "QoS Setup" },
277 /* reserved command */
278 { 0x0809, "Role Discovery" },
279 /* reserved command */
280 { 0x080b, "Switch Role" },
281 { 0x080c, "Read Link Policy Settings" },
282 { 0x080d, "Write Link Policy Settings" },
283 { 0x080e, "Read Default Link Policy Settings" },
284 { 0x080f, "Write Default Link Policy Settings" },
285 { 0x0810, "Flow Specification" },
286 { 0x0811, "Sniff Subrating" },
288 /* OGF 3 - Host Control */
289 { 0x0c01, "Set Event Mask" },
290 /* reserved command */
292 /* reserved command */
293 { 0x0c05, "Set Event Filter" },
294 /* reserved commands */
296 { 0x0c09, "Read PIN Type" },
297 { 0x0c0a, "Write PIN Type" },
298 { 0x0c0b, "Create New Unit Key" },
299 /* reserved command */
300 { 0x0c0d, "Read Stored Link Key" },
301 /* reserved commands */
302 { 0x0c11, "Write Stored Link Key" },
303 { 0x0c12, "Delete Stored Link Key" },
304 { 0x0c13, "Write Local Name" },
305 { 0x0c14, "Read Local Name" },
306 { 0x0c15, "Read Connection Accept Timeout" },
307 { 0x0c16, "Write Connection Accept Timeout" },
308 { 0x0c17, "Read Page Timeout" },
309 { 0x0c18, "Write Page Timeout" },
310 { 0x0c19, "Read Scan Enable" },
311 { 0x0c1a, "Write Scan Enable" },
312 { 0x0c1b, "Read Page Scan Activity" },
313 { 0x0c1c, "Write Page Scan Activity" },
314 { 0x0c1d, "Read Inquiry Scan Activity" },
315 { 0x0c1e, "Write Inquiry Scan Activity" },
316 { 0x0c1f, "Read Authentication Enable" },
317 { 0x0c20, "Write Authentication Enable" },
318 { 0x0c21, "Read Encryption Mode" },
319 { 0x0c22, "Write Encryption Mode" },
320 { 0x0c23, "Read Class of Device" },
321 { 0x0c24, "Write Class of Device" },
322 { 0x0c25, "Read Voice Setting" },
323 { 0x0c26, "Write Voice Setting" },
324 { 0x0c27, "Read Automatic Flush Timeout" },
325 { 0x0c28, "Write Automatic Flush Timeout" },
326 { 0x0c29, "Read Num Broadcast Retransmissions" },
327 { 0x0c2a, "Write Num Broadcast Retransmissions" },
328 { 0x0c2b, "Read Hold Mode Activity" },
329 { 0x0c2c, "Write Hold Mode Activity" },
330 { 0x0c2d, "Read Transmit Power Level" },
331 { 0x0c2e, "Read Sync Flow Control Enable" },
332 { 0x0c2f, "Write Sync Flow Control Enable" },
333 /* reserved command */
334 { 0x0c31, "Set Host Controller To Host Flow" },
335 /* reserved command */
336 { 0x0c33, "Host Buffer Size" },
337 /* reserved command */
338 { 0x0c35, "Host Number of Completed Packets" },
339 { 0x0c36, "Read Link Supervision Timeout" },
340 { 0x0c37, "Write Link Supervision Timeout" },
341 { 0x0c38, "Read Number of Supported IAC" },
342 { 0x0c39, "Read Current IAC LAP" },
343 { 0x0c3a, "Write Current IAC LAP" },
344 { 0x0c3b, "Read Page Scan Period Mode" },
345 { 0x0c3c, "Write Page Scan Period Mode" },
346 { 0x0c3d, "Read Page Scan Mode" },
347 { 0x0c3e, "Write Page Scan Mode" },
348 { 0x0c3f, "Set AFH Host Channel Classification" },
349 /* reserved commands */
350 { 0x0c42, "Read Inquiry Scan Type" },
351 { 0x0c43, "Write Inquiry Scan Type" },
352 { 0x0c44, "Read Inquiry Mode" },
353 { 0x0c45, "Write Inquiry Mode" },
354 { 0x0c46, "Read Page Scan Type" },
355 { 0x0c47, "Write Page Scan Type" },
356 { 0x0c48, "Read AFH Channel Assessment Mode" },
357 { 0x0c49, "Write AFH Channel Assessment Mode" },
358 /* reserved commands */
359 { 0x0c51, "Read Extended Inquiry Response" },
360 { 0x0c52, "Write Extended Inquiry Response" },
361 { 0x0c53, "Refresh Encryption Key" },
362 /* reserved command */
363 { 0x0c55, "Read Simple Pairing Mode" },
364 { 0x0c56, "Write Simple Pairing Mode" },
365 { 0x0c57, "Read Local OOB Data" },
366 { 0x0c58, "Read Inquiry Response TX Power Level"},
367 { 0x0c59, "Write Inquiry Transmit Power Level" },
368 { 0x0c5a, "Read Default Erroneous Reporting" },
369 { 0x0c5b, "Write Default Erroneous Reporting" },
370 /* reserved commands */
371 { 0x0c5f, "Enhanced Flush" },
372 /* reserved command */
373 { 0x0c61, "Read Logical Link Accept Timeout" },
374 { 0x0c62, "Write Logical Link Accept Timeout" },
375 { 0x0c63, "Set Event Mask Page 2" },
376 { 0x0c64, "Read Location Data" },
377 { 0x0c65, "Write Location Data" },
378 { 0x0c66, "Read Flow Control Mode" },
379 { 0x0c67, "Write Flow Control Mode" },
380 { 0x0c68, "Read Enhanced Transmit Power Level" },
381 { 0x0c69, "Read Best Effort Flush Timeout" },
382 { 0x0c6a, "Write Best Effort Flush Timeout" },
383 { 0x0c6b, "Short Range Mode" },
384 { 0x0c6c, "Read LE Host Supported" },
385 { 0x0c6d, "Write LE Host Supported" },
387 /* OGF 4 - Information Parameter */
388 { 0x1001, "Read Local Version Information" },
389 { 0x1002, "Read Local Supported Commands" },
390 { 0x1003, "Read Local Supported Features" },
391 { 0x1004, "Read Local Extended Features" },
392 { 0x1005, "Read Buffer Size" },
393 /* reserved command */
394 { 0x1007, "Read Country Code" },
395 /* reserved command */
396 { 0x1009, "Read BD ADDR" },
397 { 0x100a, "Read Data Block Size" },
399 /* OGF 5 - Status Parameter */
400 { 0x1401, "Read Failed Contact Counter" },
401 { 0x1402, "Reset Failed Contact Counter" },
402 { 0x1403, "Read Link Quality" },
403 /* reserved command */
404 { 0x1405, "Read RSSI" },
405 { 0x1406, "Read AFH Channel Map" },
406 { 0x1407, "Read Clock" },
407 { 0x1408, "Read Encryption Key Size" },
408 { 0x1409, "Read Local AMP Info" },
409 { 0x140a, "Read Local AMP ASSOC" },
410 { 0x140b, "Write Remote AMP ASSOC" },
412 /* OGF 8 - LE Control */
413 { 0x2001, "LE Set Event Mask" },
414 { 0x2002, "LE Read Buffer Size" },
415 { 0x2003, "LE Read Local Supported Features" },
416 /* reserved command */
417 { 0x2005, "LE Set Random Address" },
418 { 0x2006, "LE Set Advertising Parameters" },
419 { 0x2007, "LE Read Advertising Channel TX Power"},
420 { 0x2008, "LE Set Advertising Data" },
421 { 0x2009, "LE Set Scan Response Data" },
422 { 0x200a, "LE Set Advertise Enable" },
423 { 0x200b, "LE Set Scan Parameters" },
424 { 0x200c, "LE Set Scan Enable" },
425 { 0x200d, "LE Create Connection" },
426 { 0x200e, "LE Create Connection Cancel" },
427 { 0x200f, "LE Read White List Size" },
428 { 0x2010, "LE Clear White List" },
429 { 0x2011, "LE Add Device To White List" },
430 { 0x2012, "LE Remove Device From White List" },
431 { 0x2013, "LE Connection Update" },
432 { 0x2014, "LE Set Host Channel Classification" },
433 { 0x2015, "LE Read Channel Map" },
434 { 0x2016, "LE Read Remote Used Features" },
435 { 0x2017, "LE Encrypt" },
436 { 0x2018, "LE Rand" },
437 { 0x2019, "LE Start Encryption" },
438 { 0x201a, "LE Long Term Key Request Reply" },
439 { 0x201b, "LE Long Term Key Request Neg Reply" },
440 { 0x201c, "LE Read Supported States" },
441 { 0x201d, "LE Receiver Test" },
442 { 0x201e, "LE Transmitter Test" },
443 { 0x201f, "LE Test End" },
447 static const char *opcode2str(uint16_t opcode)
451 for (i = 0; opcode2str_table[i].str; i++) {
452 if (opcode2str_table[i].opcode == opcode)
453 return opcode2str_table[i].str;
459 static const struct {
462 } event2str_table[] = {
463 { 0x01, "Inquiry Complete" },
464 { 0x02, "Inquiry Result" },
465 { 0x03, "Connect Complete" },
466 { 0x04, "Connect Request" },
467 { 0x05, "Disconn Complete" },
468 { 0x06, "Auth Complete" },
469 { 0x07, "Remote Name Req Complete" },
470 { 0x08, "Encrypt Change" },
471 { 0x09, "Change Connection Link Key Complete" },
472 { 0x0a, "Master Link Key Complete" },
473 { 0x0b, "Read Remote Supported Features" },
474 { 0x0c, "Read Remote Version Complete" },
475 { 0x0d, "QoS Setup Complete" },
476 { 0x0e, "Command Complete" },
477 { 0x0f, "Command Status" },
478 { 0x10, "Hardware Error" },
479 { 0x11, "Flush Occurred" },
480 { 0x12, "Role Change" },
481 { 0x13, "Number of Completed Packets" },
482 { 0x14, "Mode Change" },
483 { 0x15, "Return Link Keys" },
484 { 0x16, "PIN Code Request" },
485 { 0x17, "Link Key Request" },
486 { 0x18, "Link Key Notification" },
487 { 0x19, "Loopback Command" },
488 { 0x1a, "Data Buffer Overflow" },
489 { 0x1b, "Max Slots Change" },
490 { 0x1c, "Read Clock Offset Complete" },
491 { 0x1d, "Connection Packet Type Changed" },
492 { 0x1e, "QoS Violation" },
493 { 0x1f, "Page Scan Mode Change" },
494 { 0x20, "Page Scan Repetition Mode Change" },
495 { 0x21, "Flow Specification Complete" },
496 { 0x22, "Inquiry Result with RSSI" },
497 { 0x23, "Read Remote Extended Features" },
498 /* reserved events */
499 { 0x2c, "Synchronous Connect Complete" },
500 { 0x2d, "Synchronous Connect Changed" },
501 { 0x2e, "Sniff Subrate" },
502 { 0x2f, "Extended Inquiry Result" },
503 { 0x30, "Encryption Key Refresh Complete" },
504 { 0x31, "IO Capability Request" },
505 { 0x32, "IO Capability Response" },
506 { 0x33, "User Confirmation Request" },
507 { 0x34, "User Passkey Request" },
508 { 0x35, "Remote OOB Data Request" },
509 { 0x36, "Simple Pairing Complete" },
511 { 0x38, "Link Supervision Timeout Change" },
512 { 0x39, "Enhanced Flush Complete" },
514 { 0x3b, "User Passkey Notification" },
515 { 0x3c, "Keypress Notification" },
516 { 0x3d, "Remote Host Supported Features" },
517 { 0x3e, "LE Meta Event" },
519 { 0x40, "Physical Link Complete" },
520 { 0x41, "Channel Selected" },
521 { 0x42, "Disconn Physical Link Complete" },
522 { 0x43, "Physical Link Loss Early Warning" },
523 { 0x44, "Physical Link Recovery" },
524 { 0x45, "Logical Link Complete" },
525 { 0x46, "Disconn Logical Link Complete" },
526 { 0x47, "Flow Spec Modify Complete" },
527 { 0x48, "Number Of Completed Data Blocks" },
528 { 0x49, "AMP Start Test" },
529 { 0x4a, "AMP Test End" },
530 { 0x4b, "AMP Receiver Report" },
531 { 0x4c, "Short Range Mode Change Complete" },
532 { 0x4d, "AMP Status Change" },
538 static const char *event2str(uint8_t event)
542 for (i = 0; event2str_table[i].str; i++) {
543 if (event2str_table[i].event == event)
544 return event2str_table[i].str;
550 void packet_new_index(struct timeval *tv, uint16_t index, const char *label,
551 uint8_t type, uint8_t bus, const char *name)
553 print_header(tv, index);
555 printf("= New Index: %s (%s,%s,%s)\n", label,
556 hci_typetostr(type), hci_bustostr(bus), name);
559 void packet_del_index(struct timeval *tv, uint16_t index, const char *label)
561 print_header(tv, index);
563 printf("= Delete Index: %s\n", label);
566 void packet_hci_command(struct timeval *tv, uint16_t index,
567 const void *data, uint16_t size)
569 const hci_command_hdr *hdr = data;
570 uint16_t opcode = btohs(hdr->opcode);
571 uint16_t ogf = cmd_opcode_ogf(opcode);
572 uint16_t ocf = cmd_opcode_ocf(opcode);
574 btsnoop_write(tv, index, 0x02, data, size);
576 print_header(tv, index);
578 if (size < HCI_COMMAND_HDR_SIZE) {
579 printf("* Malformed HCI Command packet\n");
583 printf("< HCI Command: %s (0x%2.2x|0x%4.4x) plen %d\n",
584 opcode2str(opcode), ogf, ocf, hdr->plen);
586 data += HCI_COMMAND_HDR_SIZE;
587 size -= HCI_COMMAND_HDR_SIZE;
589 packet_hexdump(data, size);
592 void packet_hci_event(struct timeval *tv, uint16_t index,
593 const void *data, uint16_t size)
595 const hci_event_hdr *hdr = data;
597 btsnoop_write(tv, index, 0x03, data, size);
599 print_header(tv, index);
601 if (size < HCI_EVENT_HDR_SIZE) {
602 printf("* Malformed HCI Event packet\n");
606 printf("> HCI Event: %s (0x%2.2x) plen %d\n",
607 event2str(hdr->evt), hdr->evt, hdr->plen);
609 data += HCI_EVENT_HDR_SIZE;
610 size -= HCI_EVENT_HDR_SIZE;
612 packet_hexdump(data, size);
615 void packet_hci_acldata(struct timeval *tv, uint16_t index, bool in,
616 const void *data, uint16_t size)
618 const hci_acl_hdr *hdr = data;
619 uint16_t handle = btohs(hdr->handle);
620 uint16_t dlen = btohs(hdr->dlen);
621 uint8_t flags = acl_flags(handle);
623 btsnoop_write(tv, index, in ? 0x01 : 0x00, data, size);
625 print_header(tv, index);
627 if (size < HCI_ACL_HDR_SIZE) {
628 printf("* Malformed ACL Data %s packet\n", in ? "RX" : "TX");
632 printf("%c ACL Data: handle %d flags 0x%2.2x dlen %d\n",
633 in ? '>' : '<', acl_handle(handle), flags, dlen);
635 data += HCI_ACL_HDR_SIZE;
636 size -= HCI_ACL_HDR_SIZE;
638 if (filter_mask & PACKET_FILTER_SHOW_ACL_DATA)
639 packet_hexdump(data, size);
642 void packet_hci_scodata(struct timeval *tv, uint16_t index, bool in,
643 const void *data, uint16_t size)
645 const hci_sco_hdr *hdr = data;
646 uint16_t handle = btohs(hdr->handle);
647 uint8_t flags = acl_flags(handle);
649 print_header(tv, index);
651 if (size < HCI_SCO_HDR_SIZE) {
652 printf("* Malformed SCO Data %s packet\n", in ? "RX" : "TX");
656 printf("%c SCO Data: handle %d flags 0x%2.2x dlen %d\n",
657 in ? '>' : '<', acl_handle(handle), flags, hdr->dlen);
659 data += HCI_SCO_HDR_SIZE;
660 size -= HCI_SCO_HDR_SIZE;
662 if (filter_mask & PACKET_FILTER_SHOW_SCO_DATA)
663 packet_hexdump(data, size);