csr.c revision 703086ed0bfa159fa2ba9e5fcfb6484865036cf2
1/*
2 *
3 *  BlueZ - Bluetooth protocol stack for Linux
4 *
5 *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org>
6 *
7 *
8 *  This program is free software; you can redistribute it and/or modify
9 *  it under the terms of the GNU General Public License as published by
10 *  the Free Software Foundation; either version 2 of the License, or
11 *  (at your option) any later version.
12 *
13 *  This program is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *  GNU General Public License for more details.
17 *
18 *  You should have received a copy of the GNU General Public License
19 *  along with this program; if not, write to the Free Software
20 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 *
22 */
23
24#ifdef HAVE_CONFIG_H
25#include <config.h>
26#endif
27
28#include <stdio.h>
29#include <errno.h>
30#include <unistd.h>
31#include <stdlib.h>
32#include <string.h>
33
34#include <sys/types.h>
35#include <netinet/in.h>
36
37#include "parser.h"
38
39#define CSR_U8(frm)  (get_u8(frm))
40#define CSR_U16(frm) (btohs(htons(get_u16(frm))))
41#define CSR_U32(frm) ((CSR_U16(frm) << 16) + CSR_U16(frm))
42#define CSR_S16(frm) (btohs(htons(get_u16(frm))))
43
44static char *type2str(uint16_t type)
45{
46	switch (type) {
47	case 0x0000:
48		return "Get req";
49	case 0x0001:
50		return "Get rsp";
51	case 0x0002:
52		return "Set req";
53	default:
54		return "Reserved";
55	}
56}
57
58static inline void valueless_dump(int level, char *str, struct frame *frm)
59{
60	p_indent(level, frm);
61	printf("%s\n", str);
62}
63
64static inline void complex_dump(int level, char *str, struct frame *frm)
65{
66	p_indent(level, frm);
67	printf("%s\n", str);
68
69	raw_dump(level, frm);
70}
71
72static inline void bool_dump(int level, char *str, struct frame *frm)
73{
74	uint16_t value;
75
76	value = CSR_U16(frm);
77
78	p_indent(level, frm);
79	printf("%s: value %s (%d)\n", str, value ? "TRUE" : "FALSE", value);
80}
81
82static inline void int8_dump(int level, char *str, struct frame *frm)
83{
84	int16_t value;
85
86	value = CSR_S16(frm);
87
88	p_indent(level, frm);
89	printf("%s: value %d (0x%2.2x)\n", str, value, value);
90}
91
92static inline void int16_dump(int level, char *str, struct frame *frm)
93{
94	int16_t value;
95
96	value = CSR_S16(frm);
97
98	p_indent(level, frm);
99	printf("%s: value %d (0x%2.2x)\n", str, value, value);
100}
101
102static inline void uint16_dump(int level, char *str, struct frame *frm)
103{
104	uint16_t value;
105
106	value = CSR_U16(frm);
107
108	p_indent(level, frm);
109	printf("%s: value %d (0x%4.4x)\n", str, value, value);
110}
111
112static inline void uint32_dump(int level, char *str, struct frame *frm)
113{
114	uint32_t value;
115
116	value = CSR_U32(frm);
117
118	p_indent(level, frm);
119	printf("%s: value %d (0x%4.4x)\n", str, value, value);
120}
121
122static inline void bdaddr_dump(int level, char *str, struct frame *frm)
123{
124	char addr[18];
125
126	p_ba2str(frm->ptr, addr);
127
128	p_indent(level, frm);
129	printf("%s: bdaddr %s\n", str, addr);
130}
131
132static inline void features_dump(int level, char *str, struct frame *frm)
133{
134	unsigned char features[8];
135	int i;
136
137	memcpy(features, frm->ptr, 8);
138
139	p_indent(level, frm);
140	printf("%s: features", str);
141	for (i = 0; i < 8; i++)
142		printf(" 0x%02x", features[i]);
143	printf("\n");
144}
145
146static inline void commands_dump(int level, char *str, struct frame *frm)
147{
148	unsigned char commands[64];
149	int i;
150
151	memcpy(commands, frm->ptr, frm->len);
152
153	p_indent(level, frm);
154	printf("%s: commands", str);
155	for (i = 0; i < frm->len; i++)
156		printf(" 0x%02x", commands[i]);
157	printf("\n");
158}
159
160static inline void handle_length_dump(int level, char *str, struct frame *frm)
161{
162	uint16_t handle, length;
163
164	handle = CSR_U16(frm);
165	length = CSR_U16(frm);
166
167	p_indent(level, frm);
168	printf("%s: handle %d length %d\n", str, handle, length);
169}
170
171static inline void handle_clock_dump(int level, char *str, struct frame *frm)
172{
173	uint16_t handle;
174	uint32_t clock;
175
176	handle = CSR_U16(frm);
177	clock  = CSR_U32(frm);
178
179	p_indent(level, frm);
180	printf("%s: handle %d clock 0x%4.4x\n", str, handle, clock);
181}
182
183static inline void radiotest_dump(int level, char *str, struct frame *frm)
184{
185	uint16_t testid;
186
187	testid = CSR_U16(frm);
188
189	p_indent(level, frm);
190	printf("%s: test id %d\n", str, testid);
191
192	raw_dump(level, frm);
193}
194
195static inline void psmemtype_dump(int level, char *str, struct frame *frm)
196{
197	uint16_t store, type;
198
199	store = CSR_U16(frm);
200	type  = CSR_U16(frm);
201
202	p_indent(level, frm);
203	printf("%s: store 0x%4.4x type %d\n", str, store, type);
204}
205
206static inline void psnext_dump(int level, char *str, struct frame *frm)
207{
208	uint16_t key, stores, next;
209
210	key    = CSR_U16(frm);
211	stores = CSR_U16(frm);
212	next   = CSR_U16(frm);
213
214	p_indent(level, frm);
215	printf("%s: key 0x%4.4x stores 0x%4.4x next 0x%4.4x\n", str, key, stores, next);
216}
217
218static inline void pssize_dump(int level, char *str, struct frame *frm)
219{
220	uint16_t key, length;
221
222	key    = CSR_U16(frm);
223	length = CSR_U16(frm);
224
225	p_indent(level, frm);
226	printf("%s: key 0x%4.4x %s 0x%4.4x\n", str, key,
227				frm->in ? "len" : "stores", length);
228}
229
230static inline void psstores_dump(int level, char *str, struct frame *frm)
231{
232	uint16_t key, stores;
233
234	key    = CSR_U16(frm);
235	stores = CSR_U16(frm);
236
237	p_indent(level, frm);
238	printf("%s: key 0x%4.4x stores 0x%4.4x\n", str, key, stores);
239}
240
241static inline void pskey_dump(int level, struct frame *frm)
242{
243	uint16_t key, length, stores;
244
245	key    = CSR_U16(frm);
246	length = CSR_U16(frm);
247	stores = CSR_U16(frm);
248
249	p_indent(level, frm);
250	printf("PSKEY: key 0x%4.4x len %d stores 0x%4.4x\n", key, length, stores);
251
252	switch (key) {
253	case 0x0001:
254		bdaddr_dump(level + 1, "BDADDR", frm);
255		break;
256	case 0x0002:
257		uint16_dump(level + 1, "COUNTRYCODE", frm);
258		break;
259	case 0x0003:
260		uint32_dump(level + 1, "CLASSOFDEVICE", frm);
261		break;
262	case 0x0004:
263		uint16_dump(level + 1, "DEVICE_DRIFT", frm);
264		break;
265	case 0x0005:
266		uint16_dump(level + 1, "DEVICE_JITTER", frm);
267		break;
268	case 0x000d:
269		uint16_dump(level + 1, "MAX_ACLS", frm);
270		break;
271	case 0x000e:
272		uint16_dump(level + 1, "MAX_SCOS", frm);
273		break;
274	case 0x000f:
275		uint16_dump(level + 1, "MAX_REMOTE_MASTERS", frm);
276		break;
277	case 0x00da:
278		uint16_dump(level + 1, "ENC_KEY_LMIN", frm);
279		break;
280	case 0x00db:
281		uint16_dump(level + 1, "ENC_KEY_LMAX", frm);
282		break;
283	case 0x00ef:
284		features_dump(level + 1, "LOCAL_SUPPORTED_FEATURES", frm);
285		break;
286	case 0x0106:
287		commands_dump(level + 1, "LOCAL_SUPPORTED_COMMANDS", frm);
288		break;
289	case 0x010d:
290		uint16_dump(level + 1, "HCI_LMP_LOCAL_VERSION", frm);
291		break;
292	case 0x010e:
293		uint16_dump(level + 1, "LMP_REMOTE_VERSION", frm);
294		break;
295	case 0x01a5:
296		bool_dump(level + 1, "HOSTIO_USE_HCI_EXTN", frm);
297		break;
298	case 0x01ab:
299		bool_dump(level + 1, "HOSTIO_MAP_SCO_PCM", frm);
300		break;
301	case 0x01be:
302		uint16_dump(level + 1, "UART_BAUDRATE", frm);
303		break;
304	case 0x01f6:
305		uint16_dump(level + 1, "ANA_FTRIM", frm);
306		break;
307	case 0x01f9:
308		uint16_dump(level + 1, "HOST_INTERFACE", frm);
309		break;
310	case 0x01fe:
311		uint16_dump(level + 1, "ANA_FREQ", frm);
312		break;
313	case 0x02be:
314		uint16_dump(level + 1, "USB_VENDOR_ID", frm);
315		break;
316	case 0x02bf:
317		uint16_dump(level + 1, "USB_PRODUCT_ID", frm);
318		break;
319	case 0x02cb:
320		uint16_dump(level + 1, "USB_DFU_PRODUCT_ID", frm);
321		break;
322	case 0x03cd:
323		int16_dump(level + 1, "INITIAL_BOOTMODE", frm);
324		break;
325	default:
326		raw_dump(level + 1, frm);
327		break;
328	}
329}
330
331static inline void bccmd_dump(int level, struct frame *frm)
332{
333	uint16_t type, length, seqno, varid, status;
334
335	type   = CSR_U16(frm);
336	length = CSR_U16(frm);
337	seqno  = CSR_U16(frm);
338	varid  = CSR_U16(frm);
339	status = CSR_U16(frm);
340
341	p_indent(level, frm);
342	printf("BCCMD: %s: len %d seqno %d varid 0x%4.4x status %d\n",
343			type2str(type), length, seqno, varid, status);
344
345	if (!(parser.flags & DUMP_VERBOSE)) {
346		raw_dump(level + 1, frm);
347		return;
348	}
349
350	switch (varid) {
351	case 0x000b:
352		valueless_dump(level + 1, "PS_CLR_ALL", frm);
353		break;
354	case 0x000c:
355		valueless_dump(level + 1, "PS_FACTORY_SET", frm);
356		break;
357	case 0x082d:
358		uint16_dump(level + 1, "PS_CLR_ALL_STORES", frm);
359		break;
360	case 0x2801:
361		uint16_dump(level + 1, "BC01_STATUS", frm);
362		break;
363	case 0x2819:
364		uint16_dump(level + 1, "BUILDID", frm);
365		break;
366	case 0x281a:
367		uint16_dump(level + 1, "CHIPVER", frm);
368		break;
369	case 0x281b:
370		uint16_dump(level + 1, "CHIPREV", frm);
371		break;
372	case 0x2825:
373		uint16_dump(level + 1, "INTERFACE_VERSION", frm);
374		break;
375	case 0x282a:
376		uint16_dump(level + 1, "RAND", frm);
377		break;
378	case 0x282c:
379		uint16_dump(level + 1, "MAX_CRYPT_KEY_LENGTH", frm);
380		break;
381	case 0x2833:
382		uint16_dump(level + 1, "E2_APP_SIZE", frm);
383		break;
384	case 0x2836:
385		uint16_dump(level + 1, "CHIPANAREV", frm);
386		break;
387	case 0x2838:
388		uint16_dump(level + 1, "BUILDID_LOADER", frm);
389		break;
390	case 0x2c00:
391		uint32_dump(level + 1, "BT_CLOCK", frm);
392		break;
393	case 0x3005:
394		psnext_dump(level + 1, "PS_NEXT", frm);
395		break;
396	case 0x3006:
397		pssize_dump(level + 1, "PS_SIZE", frm);
398		break;
399	case 0x3008:
400		handle_length_dump(level + 1, "CRYPT_KEY_LENGTH", frm);
401		break;
402	case 0x3009:
403		handle_clock_dump(level + 1, "PICONET_INSTANCE", frm);
404		break;
405	case 0x300a:
406		complex_dump(level + 1, "GET_CLR_EVT", frm);
407		break;
408	case 0x300b:
409		complex_dump(level + 1, "GET_NEXT_BUILDDEF", frm);
410		break;
411	case 0x300e:
412		complex_dump(level + 1, "E2_DEVICE", frm);
413		break;
414	case 0x300f:
415		complex_dump(level + 1, "E2_APP_DATA", frm);
416		break;
417	case 0x3012:
418		psmemtype_dump(level + 1, "PS_MEMORY_TYPE", frm);
419		break;
420	case 0x301c:
421		complex_dump(level + 1, "READ_BUILD_NAME", frm);
422		break;
423	case 0x4001:
424		valueless_dump(level + 1, "COLD_RESET", frm);
425		break;
426	case 0x4002:
427		valueless_dump(level + 1, "WARM_RESET", frm);
428		break;
429	case 0x4003:
430		valueless_dump(level + 1, "COLD_HALT", frm);
431		break;
432	case 0x4004:
433		valueless_dump(level + 1, "WARM_HALT", frm);
434		break;
435	case 0x4005:
436		valueless_dump(level + 1, "INIT_BT_STACK", frm);
437		break;
438	case 0x4006:
439		valueless_dump(level + 1, "ACTIVATE_BT_STACK", frm);
440		break;
441	case 0x4007:
442		valueless_dump(level + 1, "ENABLE_TX", frm);
443		break;
444	case 0x4008:
445		valueless_dump(level + 1, "DISABLE_TX", frm);
446		break;
447	case 0x4009:
448		valueless_dump(level + 1, "RECAL", frm);
449		break;
450	case 0x400d:
451		valueless_dump(level + 1, "PS_FACTORY_RESTORE", frm);
452		break;
453	case 0x400e:
454		valueless_dump(level + 1, "PS_FACTORY_RESTORE_ALL", frm);
455		break;
456	case 0x400f:
457		valueless_dump(level + 1, "PS_DEFRAG_RESET", frm);
458		break;
459	case 0x4011:
460		valueless_dump(level + 1, "HOPPING_ON", frm);
461		break;
462	case 0x4012:
463		valueless_dump(level + 1, "CANCEL_PAGE", frm);
464		break;
465	case 0x4818:
466		uint16_dump(level + 1, "PS_CLR", frm);
467		break;
468	case 0x481c:
469		uint16_dump(level + 1, "MAP_SCO_PCM", frm);
470		break;
471	case 0x482e:
472		uint16_dump(level + 1, "SINGLE_CHAN", frm);
473		break;
474	case 0x5004:
475		radiotest_dump(level + 1, "RADIOTEST", frm);
476		break;
477	case 0x500c:
478		psstores_dump(level + 1, "PS_CLR_STORES", frm);
479		break;
480	case 0x6000:
481		valueless_dump(level + 1, "NO_VARIABLE", frm);
482		break;
483	case 0x6802:
484		uint16_dump(level + 1, "CONFIG_UART", frm);
485		break;
486	case 0x6805:
487		uint16_dump(level + 1, "PANIC_ARG", frm);
488		break;
489	case 0x6806:
490		uint16_dump(level + 1, "FAULT_ARG", frm);
491		break;
492	case 0x6827:
493		int8_dump(level + 1, "MAX_TX_POWER", frm);
494		break;
495	case 0x682b:
496		int8_dump(level + 1, "DEFAULT_TX_POWER", frm);
497		break;
498	case 0x7003:
499		pskey_dump(level + 1, frm);
500		break;
501	default:
502		raw_dump(level + 1, frm);
503		break;
504	}
505}
506
507static char *cid2str(uint8_t cid)
508{
509	switch (cid & 0x3f) {
510	case 0:
511		return "BCSP Internal";
512	case 1:
513		return "BCSP Link";
514	case 2:
515		return "BCCMD";
516	case 3:
517		return "HQ";
518	case 4:
519		return "Device Mgt";
520	case 5:
521		return "HCI Cmd/Evt";
522	case 6:
523		return "HCI ACL";
524	case 7:
525		return "HCI SCO";
526	case 8:
527		return "L2CAP";
528	case 9:
529		return "RFCOMM";
530	case 10:
531		return "SDP";
532	case 11:
533		return "Debug";
534	case 12:
535		return "DFU";
536	case 13:
537		return "VM";
538	case 14:
539		return "Unused";
540	case 15:
541		return "Reserved";
542	default:
543		return "Unknown";
544	}
545}
546
547static char *frag2str(uint8_t frag)
548{
549	switch (frag & 0xc0) {
550	case 0x00:
551		return " middle fragment";
552	case 0x40:
553		return " first fragment";
554	case 0x80:
555		return " last fragment";
556	default:
557		return "";
558	}
559}
560
561void csr_dump(int level, struct frame *frm)
562{
563	uint8_t desc, cid, type;
564	uint16_t handle, master, addr;
565
566	desc = CSR_U8(frm);
567
568	cid = desc & 0x3f;
569
570	switch (cid) {
571	case 2:
572		bccmd_dump(level, frm);
573		break;
574
575	case 20:
576		type = CSR_U8(frm);
577
578		if (!p_filter(FILT_LMP)) {
579			switch (type) {
580			case 0x0f:
581				frm->handle =  ((uint8_t *) frm->ptr)[17];
582				frm->master = 0;
583				frm->len--;
584				lmp_dump(level, frm);
585				return;
586			case 0x10:
587				frm->handle = ((uint8_t *) frm->ptr)[17];
588				frm->master = 1;
589				frm->len--;
590				lmp_dump(level, frm);
591				return;
592			case 0x12:
593				handle = CSR_U16(frm);
594				master = CSR_U16(frm);
595				addr = CSR_U16(frm);
596				p_indent(level, frm);
597				printf("FHS: handle %d addr %d (%s)\n", handle,
598					addr, master ? "master" : "slave");
599				if (!master) {
600					char addr[18];
601					p_ba2str((bdaddr_t *) frm->ptr, addr);
602					p_indent(level + 1, frm);
603					printf("bdaddr %s class "
604						"0x%2.2x%2.2x%2.2x\n", addr,
605						((uint8_t *) frm->ptr)[8],
606						((uint8_t *) frm->ptr)[7],
607						((uint8_t *) frm->ptr)[6]);
608				}
609				return;
610			case 0x7b:
611				p_indent(level, frm);
612				printf("LMP(r): duplicate (same SEQN)\n");
613				return;
614			}
615		}
616
617		p_indent(level, frm);
618		printf("CSR: Debug (type 0x%2.2x)\n", type);
619		raw_dump(level, frm);
620		break;
621
622	default:
623		p_indent(level, frm);
624		printf("CSR: %s (channel %d)%s\n", cid2str(cid), cid, frag2str(desc));
625		raw_dump(level, frm);
626		break;
627	}
628}
629