Home | History | Annotate | Download | only in parser
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2004-2007  Marcel Holtmann <marcel (at) 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 
     44 static 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 
     58 static inline void valueless_dump(int level, char *str, struct frame *frm)
     59 {
     60 	p_indent(level, frm);
     61 	printf("%s\n", str);
     62 }
     63 
     64 static 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 
     72 static 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 
     82 static 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 
     92 static 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 
    102 static 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 
    112 static 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 
    122 static 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 
    132 static 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 
    146 static 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 
    160 static 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 
    171 static 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 
    183 static 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 
    195 static 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 
    206 static 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 
    218 static 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 
    230 static 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 
    241 static 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 
    331 static 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 
    507 static 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 
    547 static 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 
    561 void 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