Upgrade bluez5_37 :Merge the code from private
[platform/upstream/bluez.git] / monitor / broadcom.c
1 /*
2  *
3  *  BlueZ - Bluetooth protocol stack for Linux
4  *
5  *  Copyright (C) 2011-2014  Intel Corporation
6  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
7  *
8  *
9  *  This library is free software; you can redistribute it and/or
10  *  modify it under the terms of the GNU Lesser General Public
11  *  License as published by the Free Software Foundation; either
12  *  version 2.1 of the License, or (at your option) any later version.
13  *
14  *  This library 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 GNU
17  *  Lesser General Public License for more details.
18  *
19  *  You should have received a copy of the GNU Lesser General Public
20  *  License along with this library; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdio.h>
30
31 #include "src/shared/util.h"
32 #include "display.h"
33 #include "packet.h"
34 #include "lmp.h"
35 #include "ll.h"
36 #include "vendor.h"
37 #include "broadcom.h"
38
39 static void print_status(uint8_t status)
40 {
41         packet_print_error("Status", status);
42 }
43
44 static void null_cmd(const void *data, uint8_t size)
45 {
46 }
47
48 static void status_rsp(const void *data, uint8_t size)
49 {
50         uint8_t status = get_u8(data);
51
52         print_status(status);
53 }
54
55 static void write_bd_addr_cmd(const void *data, uint8_t size)
56 {
57         packet_print_addr("Address", data, false);
58 }
59
60 static void enable_usb_hid_emulation_cmd(const void *data, uint8_t size)
61 {
62         uint8_t enable = get_u8(data);
63         const char *str;
64
65         switch (enable) {
66         case 0x00:
67                 str = "Bluetooth mode";
68                 break;
69         case 0x01:
70                 str = "HID Mode";
71                 break;
72         default:
73                 str = "Reserved";
74                 break;
75         }
76
77         print_field("Enable: %s (0x%2.2x)", str, enable);
78 }
79
80 static void write_ram_cmd(const void *data, uint8_t size)
81 {
82         uint32_t addr = get_le32(data);
83
84         print_field("Address: 0x%8.8x", addr);
85
86         packet_hexdump(data + 4, size - 4);
87 }
88
89 static void launch_ram_cmd(const void *data, uint8_t size)
90 {
91         uint32_t addr = get_le32(data);
92
93         print_field("Address: 0x%8.8x", addr);
94 }
95
96 static void read_vid_pid_rsp(const void *data, uint8_t size)
97 {
98         uint8_t status = get_u8(data);
99         uint16_t vid = get_le16(data + 1);
100         uint16_t pid = get_le16(data + 3);
101
102         print_status(status);
103         print_field("Product: %4.4x:%4.4x", vid, pid);
104 }
105
106 static void read_verbose_version_info_rsp(const void *data, uint8_t size)
107 {
108         uint8_t status = get_u8(data);
109         uint8_t chip_id = get_u8(data + 1);
110         uint8_t target_id = get_u8(data + 2);
111         uint16_t build_base = get_le16(data + 3);
112         uint16_t build_num = get_le16(data + 5);
113         const char *str;
114
115         print_status(status);
116         print_field("Chip ID: %u (0x%2.2x)", chip_id, chip_id);
117
118         switch (target_id) {
119         case 254:
120                 str = "Invalid";
121                 break;
122         case 255:
123                 str = "Undefined";
124                 break;
125         default:
126                 str = "Reserved";
127                 break;
128         }
129
130         print_field("Build target: %s (%u)", str, target_id);
131         print_field("Build baseline: %u (0x%4.4x)", build_base, build_base);
132         print_field("Build number: %u (0x%4.4x)", build_num, build_num);
133 }
134
135 static const struct vendor_ocf vendor_ocf_table[] = {
136         { 0x001, "Write BD ADDR",
137                         write_bd_addr_cmd, 6, true,
138                         status_rsp, 1, true },
139         { 0x018, "Update UART Baud Rate" },
140         { 0x027, "Set Sleepmode Param" },
141         { 0x02e, "Download Minidriver",
142                         null_cmd, 0, true,
143                         status_rsp, 1, true },
144         { 0x03b, "Enable USB HID Emulation",
145                         enable_usb_hid_emulation_cmd, 1, true,
146                         status_rsp, 1, true },
147         { 0x045, "Write UART Clock Setting" },
148         { 0x04c, "Write RAM",
149                         write_ram_cmd, 4, false,
150                         status_rsp, 1, true },
151         { 0x04e, "Launch RAM",
152                         launch_ram_cmd, 4, true,
153                         status_rsp, 1, true },
154         { 0x05a, "Read VID PID",
155                         null_cmd, 0, true,
156                         read_vid_pid_rsp, 5, true },
157         { 0x079, "Read Verbose Config Version Info",
158                         null_cmd, 0, true,
159                         read_verbose_version_info_rsp, 7, true },
160         { }
161 };
162
163 const struct vendor_ocf *broadcom_vendor_ocf(uint16_t ocf)
164 {
165         int i;
166
167         for (i = 0; vendor_ocf_table[i].str; i++) {
168                 if (vendor_ocf_table[i].ocf == ocf)
169                         return &vendor_ocf_table[i];
170         }
171
172         return NULL;
173 }
174
175 void broadcom_lm_diag(const void *data, uint8_t size)
176 {
177         uint8_t type;
178         uint32_t clock;
179         const uint8_t *addr;
180         const char *str;
181
182         if (size != 63) {
183                 packet_hexdump(data, size);
184                 return;
185         }
186
187         type = *((uint8_t *) data);
188         clock = get_be32(data + 1);
189
190         switch (type) {
191         case 0x00:
192                 str = "LMP sent";
193                 break;
194         case 0x01:
195                 str = "LMP receive";
196                 break;
197         case 0x80:
198                 str = "LL sent";
199                 break;
200         case 0x81:
201                 str = "LL receive";
202                 break;
203         default:
204                 str = "Unknown";
205                 break;
206         }
207
208         print_field("Type: %s (%u)", str, type);
209         print_field("Clock: 0x%8.8x", clock);
210
211         switch (type) {
212         case 0x00:
213                 addr = data + 5;
214                 print_field("Address: --:--:%2.2X:%2.2X:%2.2X:%2.2X",
215                                         addr[0], addr[1], addr[2], addr[3]);
216                 packet_hexdump(data + 9, 1);
217                 lmp_packet(data + 10, size - 10, true);
218                 break;
219         case 0x01:
220                 addr = data + 5;
221                 print_field("Address: --:--:%2.2X:%2.2X:%2.2X:%2.2X",
222                                         addr[0], addr[1], addr[2], addr[3]);
223                 packet_hexdump(data + 9, 4);
224                 lmp_packet(data + 13, size - 13, true);
225                 break;
226         case 0x80:
227         case 0x81:
228                 packet_hexdump(data + 5, 7);
229                 llcp_packet(data + 12, size - 12, true);
230                 break;
231         default:
232                 packet_hexdump(data + 9, size - 9);
233                 break;
234         }
235 }
236
237 static const struct vendor_evt vendor_evt_table[] = {
238         { }
239 };
240
241 const struct vendor_evt *broadcom_vendor_evt(uint8_t evt)
242 {
243         int i;
244
245         for (i = 0; vendor_evt_table[i].str; i++) {
246                 if (vendor_evt_table[i].evt == evt)
247                         return &vendor_evt_table[i];
248         }
249
250         return NULL;
251 }