device: Set disconnect timer to zero for fast disconnection
[platform/upstream/bluez.git] / monitor / broadcom.c
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3  *
4  *  BlueZ - Bluetooth protocol stack for Linux
5  *
6  *  Copyright (C) 2011-2014  Intel Corporation
7  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
8  *
9  *
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include <config.h>
14 #endif
15
16 #include <stdio.h>
17 #include <inttypes.h>
18
19 #include "src/shared/util.h"
20 #include "display.h"
21 #include "packet.h"
22 #include "lmp.h"
23 #include "ll.h"
24 #include "vendor.h"
25 #include "broadcom.h"
26
27 #define COLOR_UNKNOWN_FEATURE_BIT       COLOR_WHITE_BG
28
29 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
30 #include "uuid.h"
31 #endif
32
33 static void print_status(uint8_t status)
34 {
35         packet_print_error("Status", status);
36 }
37
38 static void print_handle(uint16_t handle)
39 {
40         packet_print_handle(handle);
41 }
42
43 static void print_rssi(int8_t rssi)
44 {
45         packet_print_rssi("RSSI", rssi);
46 }
47
48 static void print_sco_routing(uint8_t routing)
49 {
50         const char *str;
51
52         switch (routing) {
53         case 0x00:
54                 str = "PCM";
55                 break;
56         case 0x01:
57                 str = "Transport";
58                 break;
59         case 0x02:
60                 str = "Codec";
61                 break;
62         case 0x03:
63                 str = "I2S";
64                 break;
65         default:
66                 str = "Reserved";
67                 break;
68         }
69
70         print_field("SCO routing: %s (0x%2.2x)", str, routing);
71 }
72
73 static void print_pcm_interface_rate(uint8_t rate)
74 {
75         const char *str;
76
77         switch (rate) {
78         case 0x00:
79                 str = "128 KBps";
80                 break;
81         case 0x01:
82                 str = "256 KBps";
83                 break;
84         case 0x02:
85                 str = "512 KBps";
86                 break;
87         case 0x03:
88                 str = "1024 KBps";
89                 break;
90         case 0x04:
91                 str = "2048 KBps";
92                 break;
93         default:
94                 str = "Reserved";
95                 break;
96         }
97
98         print_field("PCM interface rate: %s (0x%2.2x)", str, rate);
99 }
100
101 static void print_frame_type(uint8_t type)
102 {
103         const char *str;
104
105         switch (type) {
106         case 0x00:
107                 str = "Short";
108                 break;
109         case 0x01:
110                 str = "Long";
111                 break;
112         default:
113                 str = "Reserved";
114                 break;
115         }
116
117         print_field("Frame type: %s (0x%2.2x)", str, type);
118 }
119
120 static void print_sync_mode(uint8_t mode)
121 {
122         const char *str;
123
124         switch (mode) {
125         case 0x00:
126                 str = "Peripheral";
127                 break;
128         case 0x01:
129                 str = "Central";
130                 break;
131         default:
132                 str = "Reserved";
133                 break;
134         }
135
136         print_field("Sync mode: %s (0x%2.2x)", str, mode);
137 }
138
139 static void print_clock_mode(uint8_t mode)
140 {
141         const char *str;
142
143         switch (mode) {
144         case 0x00:
145                 str = "Peripheral";
146                 break;
147         case 0x01:
148                 str = "Central";
149                 break;
150         default:
151                 str = "Reserved";
152                 break;
153         }
154
155         print_field("Clock mode: %s (0x%2.2x)", str, mode);
156 }
157
158 static void print_sleep_mode(uint8_t mode)
159 {
160         const char *str;
161
162         switch (mode) {
163         case 0x00:
164                 str = "No sleep mode";
165                 break;
166         case 0x01:
167                 str = "UART";
168                 break;
169         case 0x02:
170                 str = "UART with messaging";
171                 break;
172         case 0x03:
173                 str = "USB";
174                 break;
175         case 0x04:
176                 str = "H4IBSS";
177                 break;
178         case 0x05:
179                 str = "USB with Host wake";
180                 break;
181         case 0x06:
182                 str = "SDIO";
183                 break;
184         case 0x07:
185                 str = "UART CS-N";
186                 break;
187         case 0x08:
188                 str = "SPI";
189                 break;
190         case 0x09:
191                 str = "H5";
192                 break;
193         case 0x0a:
194                 str = "H4DS";
195                 break;
196         case 0x0c:
197                 str = "UART with BREAK";
198                 break;
199         default:
200                 str = "Reserved";
201                 break;
202         }
203
204         print_field("Sleep mode: %s (0x%2.2x)", str, mode);
205 }
206
207 static void print_clock_setting(uint8_t clock)
208 {
209         const char *str;
210
211         switch (clock) {
212         case 0x01:
213                 str = "48 Mhz";
214                 break;
215         case 0x02:
216                 str = "24 Mhz";
217                 break;
218         default:
219                 str = "Reserved";
220                 break;
221         }
222
223         print_field("UART clock: %s (0x%2.2x)", str, clock);
224 }
225
226 static void null_cmd(uint16_t index, const void *data, uint8_t size)
227 {
228 }
229
230 static void null_cmd_without_index(const void *data, uint8_t size)
231 {
232 }
233
234 static void status_rsp(uint16_t index, const void *data, uint8_t size)
235 {
236         uint8_t status = get_u8(data);
237
238         print_status(status);
239 }
240
241 static void write_bd_addr_cmd(uint16_t index, const void *data, uint8_t size)
242 {
243         packet_print_addr("Address", data, 0x00);
244 }
245
246 static void update_uart_baud_rate_cmd(uint16_t index, const void *data,
247                                                         uint8_t size)
248 {
249         uint16_t enc_rate = get_le16(data);
250         uint32_t exp_rate = get_le32(data + 2);
251
252         if (enc_rate == 0x0000)
253                 print_field("Encoded baud rate: Not used (0x0000)");
254         else
255                 print_field("Encoded baud rate: 0x%4.4x", enc_rate);
256
257         print_field("Explicit baud rate: %u Mbps", exp_rate);
258 }
259
260 static void write_sco_pcm_int_param_cmd(uint16_t index, const void *data,
261                                                         uint8_t size)
262 {
263         uint8_t routing = get_u8(data);
264         uint8_t rate = get_u8(data + 1);
265         uint8_t frame_type = get_u8(data + 2);
266         uint8_t sync_mode = get_u8(data + 3);
267         uint8_t clock_mode = get_u8(data + 4);
268
269         print_sco_routing(routing);
270         print_pcm_interface_rate(rate);
271         print_frame_type(frame_type);
272         print_sync_mode(sync_mode);
273         print_clock_mode(clock_mode);
274 }
275
276 static void read_sco_pcm_int_param_rsp(uint16_t index, const void *data,
277                                                         uint8_t size)
278 {
279         uint8_t status = get_u8(data);
280         uint8_t routing = get_u8(data + 1);
281         uint8_t rate = get_u8(data + 2);
282         uint8_t frame_type = get_u8(data + 3);
283         uint8_t sync_mode = get_u8(data + 4);
284         uint8_t clock_mode = get_u8(data + 5);
285
286         print_status(status);
287         print_sco_routing(routing);
288         print_pcm_interface_rate(rate);
289         print_frame_type(frame_type);
290         print_sync_mode(sync_mode);
291         print_clock_mode(clock_mode);
292 }
293
294 static void set_sleepmode_param_cmd(uint16_t index, const void *data,
295                                                         uint8_t size)
296 {
297         uint8_t mode = get_u8(data);
298
299         print_sleep_mode(mode);
300
301         packet_hexdump(data + 1, size - 1);
302 }
303
304 static void read_sleepmode_param_rsp(uint16_t index, const void *data,
305                                                         uint8_t size)
306 {
307         uint8_t status = get_u8(data);
308         uint8_t mode = get_u8(data + 1);
309
310         print_status(status);
311         print_sleep_mode(mode);
312
313         packet_hexdump(data + 2, size - 2);
314 }
315
316 static void enable_radio_cmd(uint16_t index, const void *data,
317                                                         uint8_t size)
318 {
319         uint8_t mode = get_u8(data);
320         const char *str;
321
322         switch (mode) {
323         case 0x00:
324                 str = "Disable the radio";
325                 break;
326         case 0x01:
327                 str = "Enable the radio";
328                 break;
329         default:
330                 str = "Reserved";
331                 break;
332         }
333
334         print_field("Mode: %s (0x%2.2x)", str, mode);
335 }
336
337 static void enable_usb_hid_emulation_cmd(uint16_t index, const void *data,
338                                                         uint8_t size)
339 {
340         uint8_t enable = get_u8(data);
341         const char *str;
342
343         switch (enable) {
344         case 0x00:
345                 str = "Bluetooth mode";
346                 break;
347         case 0x01:
348                 str = "HID Mode";
349                 break;
350         default:
351                 str = "Reserved";
352                 break;
353         }
354
355         print_field("Enable: %s (0x%2.2x)", str, enable);
356 }
357
358 static void read_uart_clock_setting_rsp(uint16_t index, const void *data,
359                                                         uint8_t size)
360 {
361         uint8_t status = get_u8(data);
362         uint8_t clock = get_u8(data + 1);
363
364         print_status(status);
365         print_clock_setting(clock);
366 }
367
368 static void write_uart_clock_setting_cmd(uint16_t index, const void *data,
369                                                         uint8_t size)
370 {
371         uint8_t clock = get_u8(data);
372
373         print_clock_setting(clock);
374 }
375
376 static void read_raw_rssi_cmd(uint16_t index, const void *data, uint8_t size)
377 {
378         uint16_t handle = get_le16(data);
379
380         print_handle(handle);
381 }
382
383 static void read_raw_rssi_rsp(uint16_t index, const void *data, uint8_t size)
384 {
385         uint8_t status = get_u8(data);
386         uint16_t handle = get_le16(data + 1);
387         int8_t rssi = get_s8(data + 3);
388
389         print_status(status);
390         print_handle(handle);
391         print_rssi(rssi);
392 }
393
394 static void write_ram_cmd(uint16_t index, const void *data, uint8_t size)
395 {
396         uint32_t addr = get_le32(data);
397
398         print_field("Address: 0x%8.8x", addr);
399
400         packet_hexdump(data + 4, size - 4);
401 }
402
403 static void read_ram_cmd(uint16_t index, const void *data, uint8_t size)
404 {
405         uint32_t addr = get_le32(data);
406         uint8_t length = get_u8(data + 4);
407
408         print_field("Address: 0x%8.8x", addr);
409         print_field("Length: %u", length);
410 }
411
412 static void read_ram_rsp(uint16_t index, const void *data, uint8_t size)
413 {
414         uint8_t status = get_u8(data);
415
416         print_status(status);
417
418         packet_hexdump(data + 1, size - 1);
419 }
420
421 static void launch_ram_cmd(uint16_t index, const void *data, uint8_t size)
422 {
423         uint32_t addr = get_le32(data);
424
425         print_field("Address: 0x%8.8x", addr);
426 }
427
428 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
429 static void set_advt_param_multi_subcmd(const void *data, uint8_t size)
430 {
431         uint8_t adv_instance = get_u8(data + size - 2);
432         int8_t tx_power = *((int8_t *)(data + size - 1));
433
434         print_le_set_adv_parameters_cmd(data, size - 2);
435
436         print_field("Advertising Instance: %u", adv_instance);
437         print_field("TX Power: %d", tx_power);
438 }
439
440 static void set_advt_data_subcmd(const void *data, uint8_t size)
441 {
442         uint8_t adv_instance = get_u8(data + size - 1);
443
444         print_le_set_adv_data_cmd(data, size - 1);
445
446         print_field("Advertising Instance: %u", adv_instance);
447 }
448
449 static void set_scan_rsp_data_multi_subcmd(const void *data, uint8_t size)
450 {
451         uint8_t adv_instance = get_u8(data + size - 1);
452
453         print_le_set_scan_rsp_data_cmd(data, size - 1);
454
455         print_field("Advertising Instance: %u", adv_instance);
456 }
457
458 static void set_random_addr_multi_subcmd(const void *data, uint8_t size)
459 {
460         uint8_t adv_instance = get_u8(data + size - 1);
461
462         print_le_set_random_address_cmd(data, size - 1);
463
464         print_field("Advertising Instance: %u", adv_instance);
465 }
466
467 static void set_adv_enable_multi_subcmd(const void *data, uint8_t size)
468 {
469         uint8_t adv_instance = get_u8(data + size - 1);
470
471         print_le_set_adv_enable_cmd(data, size - 1);
472
473         print_field("Advertising Instance: %u", adv_instance);
474 }
475
476 static void enable_custom_feature_subcmd(const void *data, uint8_t size)
477 {
478         uint8_t enable = get_u8(data);
479         const char *str;
480
481         switch (enable) {
482         case 0x00:
483                 str = "Disable";
484                 break;
485         case 0x01:
486                 str = "Enable";
487                 break;
488         default:
489                 str = "Reserved";
490                 break;
491         }
492
493         print_field("%s offloaded RPA feature (0x%2.2x)", str, enable);
494 }
495
496 static void add_irk_to_list_subcmd(const void *data, uint8_t size)
497 {
498         uint8_t addr_type = get_u8(data + 16);
499         const uint8_t *addr = data + 17;
500         const char *str;
501
502         print_field("LE IRK (1st byte LSB)");
503         packet_hexdump(data, 16);
504
505         switch (addr_type) {
506         case 0x00:
507                 str = "Public Address";
508                 break;
509         case 0x01:
510                 str = "Random Address";
511                 break;
512         default:
513                 str = "Reserved";
514                 break;
515         }
516
517         print_field("Address type : %s (0x%2.2x)", str, addr_type);
518         print_field("Address : %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
519                         addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
520 }
521
522 static void remove_irk_from_list_subcmd(const void *data, uint8_t size)
523 {
524         uint8_t addr_type = get_u8(data);
525         const uint8_t *addr = data + 1;
526         const char *str;
527
528         switch (addr_type) {
529         case 0x00:
530                 str = "Public Address";
531                 break;
532         case 0x01:
533                 str = "Random Address";
534                 break;
535         default:
536                 str = "Reserved";
537                 break;
538         }
539
540         print_field("Address type : %s (0x%2.2x)", str, addr_type);
541         print_field("Address : %2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
542                         addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
543 }
544
545 static void read_irk_list_entry_subcmd(const void *data, uint8_t size)
546 {
547         uint8_t index = get_u8(data);
548
549         print_field("LE Read IRK List entry index : %u", index);
550 }
551
552 static void apcf_enable_subcmd(const void *data, uint8_t size)
553 {
554         uint8_t enable = get_u8(data);
555         const char *str;
556
557         switch (enable) {
558         case 0x00:
559                 str = "Disable";
560                 break;
561         case 0x01:
562                 str = "Enable";
563                 break;
564         default:
565                 str = "Reserved";
566                 break;
567         }
568
569         print_field("%s APCF feature (0x%2.2x)", str, enable);
570 }
571
572 static const struct {
573         uint8_t bit;
574         const char *str;
575 } apcf_feature_table[] = {
576         {  0, "Broadcast Address filter"        },
577         {  1, "Service Data Change filter"      },
578         {  2, "Service UUID check"              },
579         {  3, "Service Solicitation UUID check" },
580         {  4, "Local Name check"                },
581         {  5, "Manufacturer Data check"         },
582         {  6, "Service Data check"              },
583         { }
584 };
585
586 static void print_apcf_feature(const char *label, uint16_t feature)
587 {
588         int i;
589         uint16_t mask;
590
591         mask = feature;
592
593         print_field("%s", label);
594
595         for (i = 0; apcf_feature_table[i].str; i++) {
596                 if (feature & (1 << apcf_feature_table[i].bit)) {
597                         print_field("   %s", apcf_feature_table[i].str);
598                         mask &= ~(1 << apcf_feature_table[i].bit);
599                 }
600         }
601
602         if (mask)
603                 print_field("   Unknown features (0x%4.4x)", mask);
604 }
605
606 static void apcf_set_filtering_param_subcmd(const void *data, uint8_t size)
607 {
608         uint8_t add = get_u8(data);
609         uint8_t index = get_u8(data + 1);
610         uint16_t feature_selection = get_le16(data + 2);
611         uint16_t list_logic = get_le16(data + 4);
612         uint16_t filter_logic = get_u8(data + 6);
613         uint8_t rssi_high = get_u8(data + 8);
614         uint8_t delivery_mode = get_u8(data + 9);
615         uint16_t onfound_timeout = get_le16(data + 10);
616         uint8_t onfound_timeout_cnt = get_u8(data + 12);
617         uint8_t rssi_low = get_u8(data + 13);
618         uint16_t onlost_timeout = get_le16(data + 14);
619         uint16_t no_of_tracking_entries;
620         const char *str;
621
622         switch (add) {
623         case 0x00:
624                 str = "Add";
625                 break;
626         case 0x01:
627                 str = "Delete";
628                 break;
629         case 0x02:
630                 str = "Clear";
631                 break;
632         default:
633                 str = "Reserved";
634                 break;
635         }
636
637         print_field("Action : %s for filter [%d]", str, index);
638
639         print_apcf_feature("Feature Selection", feature_selection);
640         print_apcf_feature("List Logic Type (OR)", ~list_logic);
641         print_apcf_feature("List Logic Type (AND)", list_logic);
642         print_apcf_feature("Filter Logic Type (OR)", ~(filter_logic << 3));
643         print_apcf_feature("Filter Logic Type (AND)", filter_logic << 3);
644         print_field("RSSI High Threshold : %d dBm", rssi_high);
645
646         switch (delivery_mode) {
647         case 0x00:
648                 str = "Immediate";
649                 break;
650         case 0x01:
651                 str = "On Found";
652                 break;
653         case 0x02:
654                 str = "Batched";
655                 break;
656         default:
657                 str = "Reserved";
658                 break;
659         }
660
661         print_field("Delivery_mode : %s", str);
662         print_field("On Found Timeout : %d miliseconds", onfound_timeout);
663         print_field("On Found Timeout Count : %d", onfound_timeout_cnt);
664         print_field("RSSI Low Threshold : %d dBm", rssi_low);
665         print_field("On Lost Timeout : %d miliseconds", onlost_timeout);
666
667         if (size >= 18) {
668                 no_of_tracking_entries = get_le16(data + 16);
669                 print_field("Number of Tracking Entries : %d",
670                                 no_of_tracking_entries);
671         }
672 }
673
674 static void apcf_broadcaster_addr_subcmd(const void *data, uint8_t size)
675 {
676         uint8_t add = get_u8(data);
677         uint8_t index = get_u8(data + 1);
678         uint8_t type = get_u8(data + 7);
679         char *str;
680
681         switch (add) {
682         case 0x00:
683                 str = "Add";
684                 break;
685         case 0x01:
686                 str = "Delete";
687                 break;
688         case 0x02:
689                 str = "Clear";
690                 break;
691         default:
692                 str = "Reserved";
693                 break;
694         }
695
696         print_field("Action : %s for filter [%d]", str, index);
697         packet_print_addr("Address", data + 2, type == 0x00 ? false : true);
698 }
699
700 static void apcf_service_uuid_subcmd(const void *data, uint8_t size)
701 {
702         uint8_t add = get_u8(data);
703         uint8_t index = get_u8(data + 1);
704         char *str;
705         const uint8_t *uuid;
706         uint16_t uuid16;
707         uint32_t uuid32;
708
709
710         switch (add) {
711         case 0x00:
712                 str = "Add";
713                 break;
714         case 0x01:
715                 str = "Delete";
716                 break;
717         case 0x02:
718                 str = "Clear";
719                 break;
720         default:
721                 str = "Reserved";
722                 break;
723         }
724
725         print_field("Action : %s for filter [%d]", str, index);
726
727         switch ((size - 2) / 2) {
728         case 2:
729                 uuid16 = get_le16(data + 2);
730                 print_field("  UUID     : %s (0x%4.4x)",
731                                 uuid16_to_str(uuid16), uuid16);
732
733                 uuid16 = get_le16(data + 4);
734                 print_field("  UUID Mask: %s (0x%4.4x)",
735                                 uuid16_to_str(uuid16), uuid16);
736                 break;
737         case 4:
738                 uuid32 = get_le32(data + 2);
739                 print_field("  UUID     :%s (0x%8.8x)",
740                                 uuid32_to_str(uuid32), uuid32);
741
742                 uuid32 = get_le32(data + 6);
743                 print_field("  UUID Mask:%s (0x%8.8x)",
744                                 uuid32_to_str(uuid32), uuid32);
745                 break;
746         case 16:
747                 uuid = data + 2;
748                 print_field("  UUID     :%8.8x-%4.4x-%4.4x-%4.4x-%8.8x%4.4x",
749                                 get_le32(&uuid[12]), get_le16(&uuid[10]),
750                                 get_le16(&uuid[8]), get_le16(&uuid[6]),
751                                 get_le32(&uuid[2]), get_le16(&uuid[0]));
752                 uuid = data + 18;
753                 print_field("  UUID     :%8.8x-%4.4x-%4.4x-%4.4x-%8.8x%4.4x",
754                                 get_le32(&uuid[12]), get_le16(&uuid[10]),
755                                 get_le16(&uuid[8]), get_le16(&uuid[6]),
756                                 get_le32(&uuid[2]), get_le16(&uuid[0]));
757                 break;
758         default:
759                 print_field("Invalid UUIDs");
760                 packet_hexdump(data + 2, size - 2);
761                 break;
762         }
763
764         return;
765 }
766
767 static void apcf_service_solicitation_uuid_subcmd(const void *data, uint8_t size)
768 {
769         apcf_service_uuid_subcmd(data, size);
770 }
771
772 static void apcf_local_name_subcmd(const void *data, uint8_t size)
773 {
774         uint8_t add = get_u8(data);
775         uint8_t index = get_u8(data + 1);
776         char *str;
777         char name[30] = { 0 };
778
779         switch (add) {
780         case 0x00:
781                 str = "Add";
782                 break;
783         case 0x01:
784                 str = "Delete";
785                 break;
786         case 0x02:
787                 str = "Clear";
788                 break;
789         default:
790                 str = "Reserved";
791                 break;
792         }
793
794         print_field("Action : %s for filter [%d]", str, index);
795
796         memcpy(name, data + 2, size - 2 < 29 ? size - 2 : 29);
797         print_field("Local Name : %s", name);
798 }
799
800 static void apcf_manufacturer_data_subcmd(const void *data, uint8_t size)
801 {
802         uint8_t add = get_u8(data);
803         uint8_t index = get_u8(data + 1);
804         char *str;
805
806         switch (add) {
807         case 0x00:
808                 str = "Add";
809                 break;
810         case 0x01:
811                 str = "Delete";
812                 break;
813         case 0x02:
814                 str = "Clear";
815                 break;
816         default:
817                 str = "Reserved";
818                 break;
819         }
820
821         print_field("Action : %s for filter [%d]", str, index);
822
823         print_field("Manufacturer data");
824         packet_hexdump(data + 2, (size - 2 ) / 2);
825
826         print_field("Manufacturer data Mask");
827         packet_hexdump(data + 2 + (size - 2) / 2, (size - 2 ) / 2);
828 }
829
830 static void apcf_service_data_subcmd(const void *data, uint8_t size)
831 {
832         uint8_t add = get_u8(data);
833         uint8_t index = get_u8(data + 1);
834         char *str;
835
836         switch (add) {
837         case 0x00:
838                 str = "Add";
839                 break;
840         case 0x01:
841                 str = "Delete";
842                 break;
843         case 0x02:
844                 str = "Clear";
845                 break;
846         default:
847                 str = "Reserved";
848                 break;
849         }
850
851         print_field("Action : %s for filter [%d]", str, index);
852
853         print_field("Service data");
854         packet_hexdump(data + 2, (size - 2 ) / 2);
855
856         print_field("Service data Mask");
857         packet_hexdump(data + 2 + (size - 2) / 2, (size - 2 ) / 2);
858 }
859
860 struct subcmd_data {
861         uint8_t subcmd;
862         const char *str;
863         void (*cmd_func) (const void *data, uint8_t size);
864         uint8_t cmd_size;
865         bool cmd_fixed;
866 };
867
868 static void print_subcmd(const struct subcmd_data *subcmd_data,
869                                         const void *data, uint8_t size)
870 {
871         const char *subcmd_color;
872
873         if (subcmd_data->cmd_func)
874                 subcmd_color = COLOR_BLUE;
875         else
876                 subcmd_color = COLOR_WHITE_BG;
877
878         print_indent(6, subcmd_color, "", subcmd_data->str, COLOR_OFF,
879                                         " (0x%2.2x)", subcmd_data->subcmd);
880
881         if (!subcmd_data->cmd_func) {
882                 packet_hexdump(data, size);
883                 return;
884         }
885
886         if (subcmd_data->cmd_fixed) {
887                 if (size != subcmd_data->cmd_size) {
888                         print_text(COLOR_ERROR, "invalid packet size");
889                         packet_hexdump(data, size);
890                         return;
891                 }
892         } else {
893                 if (size < subcmd_data->cmd_size) {
894                         print_text(COLOR_ERROR, "too short packet");
895                         packet_hexdump(data, size);
896                         return;
897                 }
898         }
899
900         subcmd_data->cmd_func(data, size);
901 }
902
903 static const struct subcmd_data le_multi_advt_table[] = {
904         { 0x01, "LE Set Advertising Parameters Multi Sub Command",
905                 set_advt_param_multi_subcmd, 23, true },
906         { 0x02, "LE Set Advertising Data Multi Sub Command",
907                 set_advt_data_subcmd, 33, false },
908         { 0x03, "LE Set Scan Response Data Multi Sub Command",
909                 set_scan_rsp_data_multi_subcmd, 33, false },
910         { 0x04, "LE Set Random Address Multi Sub Command",
911                 set_random_addr_multi_subcmd, 7, true },
912         { 0x05, "LE Set Advertise Enable Multi Sub Command",
913                 set_adv_enable_multi_subcmd, 2, true },
914         { }
915 };
916
917 static void le_multi_advt_cmd(uint16_t index, const void *data, uint8_t size)
918 {
919         uint8_t subcmd = *((const uint8_t *)data);
920         struct subcmd_data unknown;
921         const struct subcmd_data *subcmd_data = &unknown;
922         int i;
923
924         unknown.subcmd = subcmd;
925         unknown.str = "Unknown Sub Command";
926         unknown.cmd_func = NULL;
927         unknown.cmd_size = 0;
928         unknown.cmd_fixed = true;
929
930         for (i = 0; le_multi_advt_table[i].str; i++) {
931                 if (le_multi_advt_table[i].subcmd == subcmd) {
932                         subcmd_data = &le_multi_advt_table[i];
933                         break;
934                 }
935         }
936
937         print_subcmd(subcmd_data, data + 1, size - 1);
938 }
939
940 static const struct subcmd_data le_rpa_offload_table[] = {
941         { 0x01, "Enable customer specific feature",
942                 enable_custom_feature_subcmd, 1, true },
943         { 0x02, "Add IRK to the list",
944                 add_irk_to_list_subcmd, 23, true },
945         { 0x03, "Remove IRK from the list",
946                 remove_irk_from_list_subcmd, 7, true },
947         { 0x04, "Clear IRK list",
948                 null_cmd_without_index, 0, true },
949         { 0x05, "Read IRK list entry",
950                 read_irk_list_entry_subcmd, 1, true },
951         { }
952 };
953
954 static void le_rpa_offload_cmd(uint16_t index, const void *data, uint8_t size)
955 {
956         uint8_t subcmd = *((const uint8_t *)data);
957         struct subcmd_data unknown;
958         const struct subcmd_data *subcmd_data = &unknown;
959         int i;
960
961         unknown.subcmd = subcmd;
962         unknown.str = "Unknown Sub Command";
963         unknown.cmd_func = NULL;
964         unknown.cmd_size = 0;
965         unknown.cmd_fixed = true;
966
967         for (i = 0; le_rpa_offload_table[i].str; i++) {
968                 if (le_rpa_offload_table[i].subcmd == subcmd) {
969                         subcmd_data = &le_rpa_offload_table[i];
970                         break;
971                 }
972         }
973
974         print_subcmd(subcmd_data, data + 1, size - 1);
975 }
976
977 static const struct subcmd_data le_apcf_table[] = {
978         { 0x00, "APCF Enable",
979                 apcf_enable_subcmd, 1, true },
980         { 0x01, "APCF Set Filtering Parameters",
981                 apcf_set_filtering_param_subcmd, 15, false },
982         { 0x02, "APCF Broadcaster Address",
983                 apcf_broadcaster_addr_subcmd, 9, true },
984         { 0x03, "APCF Service UUID",
985                 apcf_service_uuid_subcmd, 2, false },
986         { 0x04, "APCF Service Solicitation UUID",
987                 apcf_service_solicitation_uuid_subcmd, 2, false },
988         { 0x05, "APCF Local Name",
989                 apcf_local_name_subcmd, 2, false },
990         { 0x06, "APCF Manufacturer Data",
991                 apcf_manufacturer_data_subcmd, 2, false },
992         { 0x07, "APCF Service Data",
993                 apcf_service_data_subcmd, 2, false },
994         { }
995 };
996
997 static void le_apcf_cmd(uint16_t index, const void *data, uint8_t size)
998 {
999         uint8_t subcmd = *((const uint8_t *)data);
1000         struct subcmd_data unknown;
1001         const struct subcmd_data *subcmd_data = &unknown;
1002         int i;
1003
1004         unknown.subcmd = subcmd;
1005         unknown.str = "Unknown Sub Command";
1006         unknown.cmd_func = NULL;
1007         unknown.cmd_size = 0;
1008         unknown.cmd_fixed = true;
1009
1010         for (i = 0; le_apcf_table[i].str; i++) {
1011                 if (le_apcf_table[i].subcmd == subcmd) {
1012                         subcmd_data = &le_apcf_table[i];
1013                         break;
1014                 }
1015         }
1016
1017         print_subcmd(subcmd_data, data + 1, size - 1);
1018 }
1019 #endif
1020
1021 static void read_vid_pid_rsp(uint16_t index, const void *data, uint8_t size)
1022 {
1023         uint8_t status = get_u8(data);
1024         uint16_t vid = get_le16(data + 1);
1025         uint16_t pid = get_le16(data + 3);
1026
1027         print_status(status);
1028         print_field("Product: %4.4x:%4.4x", vid, pid);
1029 }
1030
1031 static void write_high_priority_connection_cmd(uint16_t index, const void *data,
1032                                                         uint8_t size)
1033 {
1034         uint16_t handle = get_le16(data);
1035         uint8_t priority = get_u8(data + 2);
1036         const char *str;
1037
1038         print_handle(handle);
1039
1040         switch (priority) {
1041         case 0x00:
1042                 str = "Low";
1043                 break;
1044         case 0x01:
1045                 str = "High";
1046                 break;
1047         default:
1048                 str = "Reserved";
1049                 break;
1050         }
1051
1052         print_field("Priority: %s (0x%2.2x)", str, priority);
1053 }
1054
1055 static const struct {
1056         uint8_t bit;
1057         const char *str;
1058 } features_table[] = {
1059         {  0, "Multi-AV transport bandwidth reducer"    },
1060         {  1, "WBS SBC"                                 },
1061         {  2, "FW LC-PLC"                               },
1062         {  3, "FM SBC internal stack"                   },
1063         { }
1064 };
1065
1066 static void print_features(const uint8_t *features_array)
1067 {
1068         uint64_t mask, features = 0;
1069         char str[41];
1070         int i;
1071
1072         for (i = 0; i < 8; i++) {
1073                 sprintf(str + (i * 5), " 0x%2.2x", features_array[i]);
1074                 features |= ((uint64_t) features_array[i]) << (i * 8);
1075         }
1076
1077         print_field("Features:%s", str);
1078
1079         mask = features;
1080
1081         for (i = 0; features_table[i].str; i++) {
1082                 if (features & (((uint64_t) 1) << features_table[i].bit)) {
1083                         print_field("  %s", features_table[i].str);
1084                         mask &= ~(((uint64_t) 1) << features_table[i].bit);
1085                 }
1086         }
1087
1088         if (mask)
1089                 print_text(COLOR_UNKNOWN_FEATURE_BIT, "  Unknown features "
1090                                                 "(0x%16.16" PRIx64 ")", mask);
1091 }
1092
1093 static void read_controller_features_rsp(uint16_t index, const void *data,
1094                                                         uint8_t size)
1095 {
1096         uint8_t status = get_u8(data);
1097
1098         print_status(status);
1099         print_features(data + 1);
1100 }
1101
1102 static void read_verbose_version_info_rsp(uint16_t index, const void *data,
1103                                                         uint8_t size)
1104 {
1105         uint8_t status = get_u8(data);
1106         uint8_t chip_id = get_u8(data + 1);
1107         uint8_t target_id = get_u8(data + 2);
1108         uint16_t build_base = get_le16(data + 3);
1109         uint16_t build_num = get_le16(data + 5);
1110         const char *str;
1111
1112         print_status(status);
1113         print_field("Chip ID: %u (0x%2.2x)", chip_id, chip_id);
1114
1115         switch (target_id) {
1116         case 254:
1117                 str = "Invalid";
1118                 break;
1119         case 255:
1120                 str = "Undefined";
1121                 break;
1122         default:
1123                 str = "Reserved";
1124                 break;
1125         }
1126
1127         print_field("Build target: %s (%u)", str, target_id);
1128         print_field("Build baseline: %u (0x%4.4x)", build_base, build_base);
1129         print_field("Build number: %u (0x%4.4x)", build_num, build_num);
1130 }
1131
1132 static void enable_wbs_cmd(uint16_t index, const void *data, uint8_t size)
1133 {
1134         uint8_t mode = get_u8(data);
1135         uint16_t codec = get_le16(data + 1);
1136         const char *str;
1137
1138         switch (mode) {
1139                 case 0x00:
1140                         str = "Disable WBS";
1141                         break;
1142                 case 0x01:
1143                         str = "Enable WBS";
1144                         break;
1145                 default:
1146                         str = "Reserved";
1147                         break;
1148         }
1149
1150         print_field("Mode: %s (0x%2.2x)", str, mode);
1151
1152         switch (codec) {
1153                 case 0x0000:
1154                         str = "None";
1155                         break;
1156                 case 0x0001:
1157                         str = "CVSD";
1158                         break;
1159                 case 0x0002:
1160                         str = "mSBC";
1161                         break;
1162                 default:
1163                         str = "Reserved";
1164                         break;
1165         }
1166
1167         print_field("Codec: %s (0x%4.4x)", str, codec);
1168 }
1169
1170 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1171 static void get_vendor_capabilities_rsp(uint16_t index,  const void *data, uint8_t size)
1172 {
1173         uint8_t status = get_u8(data);
1174         uint8_t max_advt_instances = get_u8(data + 1);
1175         uint8_t offloaded_resolution_of_private_address = get_u8(data + 2);
1176         uint16_t total_scan_results_storage = get_le16(data + 3);
1177         uint8_t max_irk_list_sz = get_u8(data + 5);
1178         uint8_t filtering_support = get_u8(data + 6);
1179         uint8_t max_filter = get_u8(data + 7);
1180         uint8_t activity_energy_info_support = get_u8(data + 8);
1181         uint8_t onlost_follow_per_filter = get_u8(data + 9);
1182
1183         print_status(status);
1184         print_field("The Number of advertisement instances supported: %u",
1185                         max_advt_instances);
1186         print_field("BT chip capability of RPA: %s",
1187                         offloaded_resolution_of_private_address ?
1188                         "Capable" : "Not Capable");
1189         print_field("Storage for scan results: %u bytes",
1190                         total_scan_results_storage);
1191         print_field("The Number of IRK entries supported: %u", max_irk_list_sz);
1192         print_field("Support Filtering in BT chip: %s",
1193                         filtering_support ? "Supported" : "Not Supported");
1194         print_field("The Number of filters supported: %u", max_filter);
1195         print_field("Supports reporting of activity and energy info: %s",
1196                         activity_energy_info_support ?
1197                         "Capable" : "Not Capable");
1198         print_field("The Number of advertisers that can be analysed for "
1199                         "onlost per filter: %u", onlost_follow_per_filter);
1200 }
1201
1202 static void le_multi_advt_rsp(uint16_t index, const void *data, uint8_t size)
1203 {
1204         uint8_t status = get_u8(data);
1205         uint8_t subcmd = get_u8(data + 1);
1206         int i;
1207         const char *str = "Unknown Sub Command";
1208
1209         print_status(status);
1210
1211         for (i = 0; le_multi_advt_table[i].str; i++) {
1212                 if (le_multi_advt_table[i].subcmd == subcmd) {
1213                         str = le_multi_advt_table[i].str;
1214                         break;
1215                 }
1216         }
1217
1218         print_field("Multi Advertise OPcode: %s (%u)", str, subcmd);
1219 }
1220
1221 static void le_rpa_offload_rsp(uint16_t index, const void *data, uint8_t size)
1222 {
1223         uint8_t status = get_u8(data);
1224         uint8_t subcmd = get_u8(data + 1);
1225         int i;
1226         const char *str = "Unknown Sub Command";
1227
1228         print_status(status);
1229
1230         for (i = 0; le_rpa_offload_table[i].str; i++) {
1231                 if (le_rpa_offload_table[i].subcmd == subcmd) {
1232                         str = le_rpa_offload_table[i].str;
1233                         break;
1234                 }
1235         }
1236
1237         print_field("RPA Offload OPcode: %s (%u)", str, subcmd);
1238 }
1239
1240 static void le_apcf_rsp(uint16_t index, const void *data, uint8_t size)
1241 {
1242         uint8_t status = get_u8(data);
1243         uint8_t subcmd = get_u8(data + 1);
1244         int i;
1245         const char *str = "Unknown Sub Command";
1246
1247         print_status(status);
1248
1249         for (i = 0; le_apcf_table[i].str; i++) {
1250                 if (le_apcf_table[i].subcmd == subcmd) {
1251                         str = le_apcf_table[i].str;
1252                         break;
1253                 }
1254         }
1255
1256         print_field("Advertising Packet Content Filter OPcode: %s (%u)",
1257                         str, subcmd);
1258 }
1259 #endif
1260
1261 static const struct vendor_ocf vendor_ocf_table[] = {
1262         { 0x001, "Write BD ADDR",
1263                         write_bd_addr_cmd, 6, true,
1264                         status_rsp, 1, true },
1265         { 0x018, "Update UART Baud Rate",
1266                         update_uart_baud_rate_cmd, 6, true,
1267                         status_rsp, 1, true },
1268         { 0x01c, "Write SCO PCM Int Param",
1269                         write_sco_pcm_int_param_cmd, 5, true,
1270                         status_rsp, 1, true },
1271         { 0x01d, "Read SCO PCM Int Param",
1272                         null_cmd, 0, true,
1273                         read_sco_pcm_int_param_rsp, 6, true },
1274         { 0x027, "Set Sleepmode Param",
1275                         set_sleepmode_param_cmd, 12, true,
1276                         status_rsp, 1, true },
1277         { 0x028, "Read Sleepmode Param",
1278                         null_cmd, 0, true,
1279                         read_sleepmode_param_rsp, 13, true },
1280         { 0x02e, "Download Minidriver",
1281                         null_cmd, 0, true,
1282                         status_rsp, 1, true },
1283         { 0x034, "Enable Radio",
1284                         enable_radio_cmd, 1, true,
1285                         status_rsp, 1, true },
1286         { 0x03b, "Enable USB HID Emulation",
1287                         enable_usb_hid_emulation_cmd, 1, true,
1288                         status_rsp, 1, true },
1289         { 0x044, "Read UART Clock Setting",
1290                         null_cmd, 0, true,
1291                         read_uart_clock_setting_rsp, 1, true },
1292         { 0x045, "Write UART Clock Setting",
1293                         write_uart_clock_setting_cmd, 1, true,
1294                         status_rsp, 1, true },
1295         { 0x048, "Read Raw RSSI",
1296                         read_raw_rssi_cmd, 2, true,
1297                         read_raw_rssi_rsp, 4, true },
1298         { 0x04c, "Write RAM",
1299                         write_ram_cmd, 4, false,
1300                         status_rsp, 1, true },
1301         { 0x04d, "Read RAM",
1302                         read_ram_cmd, 5, true,
1303                         read_ram_rsp, 1, false },
1304         { 0x04e, "Launch RAM",
1305                         launch_ram_cmd, 4, true,
1306                         status_rsp, 1, true },
1307         { 0x05a, "Read VID PID",
1308                         null_cmd, 0, true,
1309                         read_vid_pid_rsp, 5, true },
1310         { 0x057, "Write High Priority Connection",
1311                         write_high_priority_connection_cmd, 3, true,
1312                         status_rsp, 1, true },
1313         { 0x06d, "Write I2SPCM Interface Param" },
1314         { 0x06e, "Read Controller Features",
1315                         null_cmd, 0, true,
1316                         read_controller_features_rsp, 9, true },
1317         { 0x079, "Read Verbose Config Version Info",
1318                         null_cmd, 0, true,
1319                         read_verbose_version_info_rsp, 7, true },
1320         { 0x07e, "Enable WBS",
1321                         enable_wbs_cmd, 3, true,
1322                         status_rsp, 1, true },
1323 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1324         { 0x0153, "LE Get Vendor Capabilities",
1325                         null_cmd, 0, true,
1326                         get_vendor_capabilities_rsp, 10, false },
1327         { 0x0154, "LE Multi Advertise",
1328                         le_multi_advt_cmd, 1, false,
1329                         le_multi_advt_rsp, 2, true },
1330         { 0x0155, "LE RPA Offload",
1331                         le_rpa_offload_cmd, 1, false,
1332                         le_rpa_offload_rsp, 2, false },
1333 #if 0
1334         { 0x0156, "LE Batch Scan",
1335                         le_batch_scan_cmd, 1, false,
1336                         le_batch_scan_rsp, 2, true },
1337 #endif
1338         { 0x0157, "LE APCF",
1339                         le_apcf_cmd, 1, false,
1340                         le_apcf_rsp, 2, false },
1341 #endif
1342         { }
1343 };
1344
1345 const struct vendor_ocf *broadcom_vendor_ocf(uint16_t ocf)
1346 {
1347         int i;
1348
1349         for (i = 0; vendor_ocf_table[i].str; i++) {
1350                 if (vendor_ocf_table[i].ocf == ocf)
1351                         return &vendor_ocf_table[i];
1352         }
1353
1354         return NULL;
1355 }
1356
1357 void broadcom_lm_diag(const void *data, uint8_t size)
1358 {
1359         uint8_t type;
1360         uint32_t clock;
1361         const uint8_t *addr;
1362         const char *str;
1363
1364         if (size != 63) {
1365                 packet_hexdump(data, size);
1366                 return;
1367         }
1368
1369         type = *((uint8_t *) data);
1370         clock = get_be32(data + 1);
1371
1372         switch (type) {
1373         case 0x00:
1374                 str = "LMP sent";
1375                 break;
1376         case 0x01:
1377                 str = "LMP receive";
1378                 break;
1379         case 0x80:
1380                 str = "LL sent";
1381                 break;
1382         case 0x81:
1383                 str = "LL receive";
1384                 break;
1385         default:
1386                 str = "Unknown";
1387                 break;
1388         }
1389
1390         print_field("Type: %s (%u)", str, type);
1391         print_field("Clock: 0x%8.8x", clock);
1392
1393         switch (type) {
1394         case 0x00:
1395                 addr = data + 5;
1396                 print_field("Address: --:--:%2.2X:%2.2X:%2.2X:%2.2X",
1397                                         addr[0], addr[1], addr[2], addr[3]);
1398                 packet_hexdump(data + 9, 1);
1399                 lmp_packet(data + 10, size - 10, true);
1400                 break;
1401         case 0x01:
1402                 addr = data + 5;
1403                 print_field("Address: --:--:%2.2X:%2.2X:%2.2X:%2.2X",
1404                                         addr[0], addr[1], addr[2], addr[3]);
1405                 packet_hexdump(data + 9, 4);
1406                 lmp_packet(data + 13, size - 13, true);
1407                 break;
1408         case 0x80:
1409         case 0x81:
1410                 packet_hexdump(data + 5, 7);
1411                 llcp_packet(data + 12, size - 12, true);
1412                 break;
1413         default:
1414                 packet_hexdump(data + 9, size - 9);
1415                 break;
1416         }
1417 }
1418
1419 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1420 struct hci_vse_sec_brcm_link_loss_dbg_info{
1421         unsigned char   linklost_status;
1422         unsigned char   conn_handle;
1423         char    trans_pwr;
1424         char    rssi;
1425         unsigned char   ch_map[10];
1426         unsigned char   lmp_cmd[4];
1427 } __packed;
1428
1429 static void linkloss_evt(struct timeval *tv, uint16_t index,
1430                                  const void *data, uint8_t size)
1431 {
1432
1433          struct hci_vse_sec_brcm_link_loss_dbg_info *ev = (void *) data;
1434          char *status = NULL;
1435          switch (ev->linklost_status) {
1436          case 0:
1437                  status = "BT_Link_Supervision_Timeout";
1438                  break;
1439          case 1:
1440                  status = "LE_Link_Supervision_Timeout";
1441                  break;
1442          case 2:
1443                  status = "BT_LMP_Timeout_Local";
1444                  break;
1445          case 3:
1446                  status = "BT_LMP_Timeout_Remote";
1447                  break;
1448          case 4:
1449                  status = "LE_LMP_Timeout";
1450                  break;
1451          case 5:
1452                  status = "Page_Timeout";
1453                  break;
1454          default :
1455                  break;
1456          }
1457
1458         print_field("Status:%s,Handle:%02x,Trans_Pwr:%d,RSSI:%d"
1459                 " Ch_map:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
1460                 " LMP_cmd:0x%x%x%x%x",
1461                 status, ev->conn_handle, ev->trans_pwr, ev->rssi,
1462                 ev->ch_map[0], ev->ch_map[1], ev->ch_map[2], ev->ch_map[3],
1463                 ev->ch_map[4], ev->ch_map[5], ev->ch_map[6], ev->ch_map[7],
1464                 ev->ch_map[8], ev->ch_map[9], ev->lmp_cmd[0], ev->lmp_cmd[1],
1465                 ev->lmp_cmd[2], ev->lmp_cmd[3]);
1466 }
1467 #endif
1468
1469 static void lm_diag_evt(struct timeval *tv, uint16_t index,
1470                                 const void *data, uint8_t size)
1471 {
1472         broadcom_lm_diag(data, 63);
1473 }
1474
1475 static const struct vendor_evt vendor_evt_table[] = {
1476 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
1477         { 0x76, "SEC Link Loss", linkloss_evt,  18, true },
1478 #endif
1479         { 0xb4, "LM Diag", lm_diag_evt, 64, true },
1480         { }
1481 };
1482
1483 const struct vendor_evt *broadcom_vendor_evt(uint8_t evt)
1484 {
1485         int i;
1486
1487         for (i = 0; vendor_evt_table[i].str; i++) {
1488                 if (vendor_evt_table[i].evt == evt)
1489                         return &vendor_evt_table[i];
1490         }
1491
1492         return NULL;
1493 }