diff options
Diffstat (limited to 'tools/parser/csr.c')
-rw-r--r-- | tools/parser/csr.c | 625 |
1 files changed, 625 insertions, 0 deletions
diff --git a/tools/parser/csr.c b/tools/parser/csr.c new file mode 100644 index 00000000..1a63ae09 --- /dev/null +++ b/tools/parser/csr.c @@ -0,0 +1,625 @@ +/* + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2004-2011 Marcel Holtmann <marcel@holtmann.org> + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +#include "parser.h" + +#define CSR_U8(frm) (get_u8(frm)) +#define CSR_U16(frm) (btohs(htons(get_u16(frm)))) +#define CSR_U32(frm) ((CSR_U16(frm) << 16) + CSR_U16(frm)) +#define CSR_S16(frm) (btohs(htons(get_u16(frm)))) + +static char *type2str(uint16_t type) +{ + switch (type) { + case 0x0000: + return "Get req"; + case 0x0001: + return "Get rsp"; + case 0x0002: + return "Set req"; + default: + return "Reserved"; + } +} + +static inline void valueless_dump(int level, char *str, struct frame *frm) +{ + p_indent(level, frm); + printf("%s\n", str); +} + +static inline void complex_dump(int level, char *str, struct frame *frm) +{ + p_indent(level, frm); + printf("%s\n", str); + + raw_dump(level, frm); +} + +static inline void bool_dump(int level, char *str, struct frame *frm) +{ + uint16_t value; + + value = CSR_U16(frm); + + p_indent(level, frm); + printf("%s: value %s (%d)\n", str, value ? "TRUE" : "FALSE", value); +} + +static inline void int8_dump(int level, char *str, struct frame *frm) +{ + int16_t value; + + value = CSR_S16(frm); + + p_indent(level, frm); + printf("%s: value %d (0x%2.2x)\n", str, value, value); +} + +static inline void int16_dump(int level, char *str, struct frame *frm) +{ + int16_t value; + + value = CSR_S16(frm); + + p_indent(level, frm); + printf("%s: value %d (0x%2.2x)\n", str, value, value); +} + +static inline void uint16_dump(int level, char *str, struct frame *frm) +{ + uint16_t value; + + value = CSR_U16(frm); + + p_indent(level, frm); + printf("%s: value %d (0x%4.4x)\n", str, value, value); +} + +static inline void uint32_dump(int level, char *str, struct frame *frm) +{ + uint32_t value; + + value = CSR_U32(frm); + + p_indent(level, frm); + printf("%s: value %d (0x%4.4x)\n", str, value, value); +} + +static inline void bdaddr_dump(int level, char *str, struct frame *frm) +{ + char addr[18]; + + p_ba2str(frm->ptr, addr); + + p_indent(level, frm); + printf("%s: bdaddr %s\n", str, addr); +} + +static inline void features_dump(int level, char *str, struct frame *frm) +{ + unsigned char features[8]; + int i; + + memcpy(features, frm->ptr, 8); + + p_indent(level, frm); + printf("%s: features", str); + for (i = 0; i < 8; i++) + printf(" 0x%02x", features[i]); + printf("\n"); +} + +static inline void commands_dump(int level, char *str, struct frame *frm) +{ + unsigned char commands[64]; + unsigned int i; + + memcpy(commands, frm->ptr, frm->len); + + p_indent(level, frm); + printf("%s: commands", str); + for (i = 0; i < frm->len; i++) + printf(" 0x%02x", commands[i]); + printf("\n"); +} + +static inline void handle_length_dump(int level, char *str, struct frame *frm) +{ + uint16_t handle, length; + + handle = CSR_U16(frm); + length = CSR_U16(frm); + + p_indent(level, frm); + printf("%s: handle %d length %d\n", str, handle, length); +} + +static inline void handle_clock_dump(int level, char *str, struct frame *frm) +{ + uint16_t handle; + uint32_t clock; + + handle = CSR_U16(frm); + clock = CSR_U32(frm); + + p_indent(level, frm); + printf("%s: handle %d clock 0x%4.4x\n", str, handle, clock); +} + +static inline void radiotest_dump(int level, char *str, struct frame *frm) +{ + uint16_t testid; + + testid = CSR_U16(frm); + + p_indent(level, frm); + printf("%s: test id %d\n", str, testid); + + raw_dump(level, frm); +} + +static inline void psmemtype_dump(int level, char *str, struct frame *frm) +{ + uint16_t store, type; + + store = CSR_U16(frm); + type = CSR_U16(frm); + + p_indent(level, frm); + printf("%s: store 0x%4.4x type %d\n", str, store, type); +} + +static inline void psnext_dump(int level, char *str, struct frame *frm) +{ + uint16_t key, stores, next; + + key = CSR_U16(frm); + stores = CSR_U16(frm); + next = CSR_U16(frm); + + p_indent(level, frm); + printf("%s: key 0x%4.4x stores 0x%4.4x next 0x%4.4x\n", str, key, stores, next); +} + +static inline void pssize_dump(int level, char *str, struct frame *frm) +{ + uint16_t key, length; + + key = CSR_U16(frm); + length = CSR_U16(frm); + + p_indent(level, frm); + printf("%s: key 0x%4.4x %s 0x%4.4x\n", str, key, + frm->in ? "len" : "stores", length); +} + +static inline void psstores_dump(int level, char *str, struct frame *frm) +{ + uint16_t key, stores; + + key = CSR_U16(frm); + stores = CSR_U16(frm); + + p_indent(level, frm); + printf("%s: key 0x%4.4x stores 0x%4.4x\n", str, key, stores); +} + +static inline void pskey_dump(int level, struct frame *frm) +{ + uint16_t key, length, stores; + + key = CSR_U16(frm); + length = CSR_U16(frm); + stores = CSR_U16(frm); + + p_indent(level, frm); + printf("PSKEY: key 0x%4.4x len %d stores 0x%4.4x\n", key, length, stores); + + switch (key) { + case 0x0001: + bdaddr_dump(level + 1, "BDADDR", frm); + break; + case 0x0002: + uint16_dump(level + 1, "COUNTRYCODE", frm); + break; + case 0x0003: + uint32_dump(level + 1, "CLASSOFDEVICE", frm); + break; + case 0x0004: + uint16_dump(level + 1, "DEVICE_DRIFT", frm); + break; + case 0x0005: + uint16_dump(level + 1, "DEVICE_JITTER", frm); + break; + case 0x000d: + uint16_dump(level + 1, "MAX_ACLS", frm); + break; + case 0x000e: + uint16_dump(level + 1, "MAX_SCOS", frm); + break; + case 0x000f: + uint16_dump(level + 1, "MAX_REMOTE_MASTERS", frm); + break; + case 0x00da: + uint16_dump(level + 1, "ENC_KEY_LMIN", frm); + break; + case 0x00db: + uint16_dump(level + 1, "ENC_KEY_LMAX", frm); + break; + case 0x00ef: + features_dump(level + 1, "LOCAL_SUPPORTED_FEATURES", frm); + break; + case 0x0106: + commands_dump(level + 1, "LOCAL_SUPPORTED_COMMANDS", frm); + break; + case 0x010d: + uint16_dump(level + 1, "HCI_LMP_LOCAL_VERSION", frm); + break; + case 0x010e: + uint16_dump(level + 1, "LMP_REMOTE_VERSION", frm); + break; + case 0x01a5: + bool_dump(level + 1, "HOSTIO_USE_HCI_EXTN", frm); + break; + case 0x01ab: + bool_dump(level + 1, "HOSTIO_MAP_SCO_PCM", frm); + break; + case 0x01be: + uint16_dump(level + 1, "UART_BAUDRATE", frm); + break; + case 0x01f6: + uint16_dump(level + 1, "ANA_FTRIM", frm); + break; + case 0x01f9: + uint16_dump(level + 1, "HOST_INTERFACE", frm); + break; + case 0x01fe: + uint16_dump(level + 1, "ANA_FREQ", frm); + break; + case 0x02be: + uint16_dump(level + 1, "USB_VENDOR_ID", frm); + break; + case 0x02bf: + uint16_dump(level + 1, "USB_PRODUCT_ID", frm); + break; + case 0x02cb: + uint16_dump(level + 1, "USB_DFU_PRODUCT_ID", frm); + break; + case 0x03cd: + int16_dump(level + 1, "INITIAL_BOOTMODE", frm); + break; + default: + raw_dump(level + 1, frm); + break; + } +} + +static inline void bccmd_dump(int level, struct frame *frm) +{ + uint16_t type, length, seqno, varid, status; + + type = CSR_U16(frm); + length = CSR_U16(frm); + seqno = CSR_U16(frm); + varid = CSR_U16(frm); + status = CSR_U16(frm); + + p_indent(level, frm); + printf("BCCMD: %s: len %d seqno %d varid 0x%4.4x status %d\n", + type2str(type), length, seqno, varid, status); + + if (!(parser.flags & DUMP_VERBOSE)) { + raw_dump(level + 1, frm); + return; + } + + switch (varid) { + case 0x000b: + valueless_dump(level + 1, "PS_CLR_ALL", frm); + break; + case 0x000c: + valueless_dump(level + 1, "PS_FACTORY_SET", frm); + break; + case 0x082d: + uint16_dump(level + 1, "PS_CLR_ALL_STORES", frm); + break; + case 0x2801: + uint16_dump(level + 1, "BC01_STATUS", frm); + break; + case 0x2819: + uint16_dump(level + 1, "BUILDID", frm); + break; + case 0x281a: + uint16_dump(level + 1, "CHIPVER", frm); + break; + case 0x281b: + uint16_dump(level + 1, "CHIPREV", frm); + break; + case 0x2825: + uint16_dump(level + 1, "INTERFACE_VERSION", frm); + break; + case 0x282a: + uint16_dump(level + 1, "RAND", frm); + break; + case 0x282c: + uint16_dump(level + 1, "MAX_CRYPT_KEY_LENGTH", frm); + break; + case 0x2833: + uint16_dump(level + 1, "E2_APP_SIZE", frm); + break; + case 0x2836: + uint16_dump(level + 1, "CHIPANAREV", frm); + break; + case 0x2838: + uint16_dump(level + 1, "BUILDID_LOADER", frm); + break; + case 0x2c00: + uint32_dump(level + 1, "BT_CLOCK", frm); + break; + case 0x3005: + psnext_dump(level + 1, "PS_NEXT", frm); + break; + case 0x3006: + pssize_dump(level + 1, "PS_SIZE", frm); + break; + case 0x3008: + handle_length_dump(level + 1, "CRYPT_KEY_LENGTH", frm); + break; + case 0x3009: + handle_clock_dump(level + 1, "PICONET_INSTANCE", frm); + break; + case 0x300a: + complex_dump(level + 1, "GET_CLR_EVT", frm); + break; + case 0x300b: + complex_dump(level + 1, "GET_NEXT_BUILDDEF", frm); + break; + case 0x300e: + complex_dump(level + 1, "E2_DEVICE", frm); + break; + case 0x300f: + complex_dump(level + 1, "E2_APP_DATA", frm); + break; + case 0x3012: + psmemtype_dump(level + 1, "PS_MEMORY_TYPE", frm); + break; + case 0x301c: + complex_dump(level + 1, "READ_BUILD_NAME", frm); + break; + case 0x4001: + valueless_dump(level + 1, "COLD_RESET", frm); + break; + case 0x4002: + valueless_dump(level + 1, "WARM_RESET", frm); + break; + case 0x4003: + valueless_dump(level + 1, "COLD_HALT", frm); + break; + case 0x4004: + valueless_dump(level + 1, "WARM_HALT", frm); + break; + case 0x4005: + valueless_dump(level + 1, "INIT_BT_STACK", frm); + break; + case 0x4006: + valueless_dump(level + 1, "ACTIVATE_BT_STACK", frm); + break; + case 0x4007: + valueless_dump(level + 1, "ENABLE_TX", frm); + break; + case 0x4008: + valueless_dump(level + 1, "DISABLE_TX", frm); + break; + case 0x4009: + valueless_dump(level + 1, "RECAL", frm); + break; + case 0x400d: + valueless_dump(level + 1, "PS_FACTORY_RESTORE", frm); + break; + case 0x400e: + valueless_dump(level + 1, "PS_FACTORY_RESTORE_ALL", frm); + break; + case 0x400f: + valueless_dump(level + 1, "PS_DEFRAG_RESET", frm); + break; + case 0x4011: + valueless_dump(level + 1, "HOPPING_ON", frm); + break; + case 0x4012: + valueless_dump(level + 1, "CANCEL_PAGE", frm); + break; + case 0x4818: + uint16_dump(level + 1, "PS_CLR", frm); + break; + case 0x481c: + uint16_dump(level + 1, "MAP_SCO_PCM", frm); + break; + case 0x482e: + uint16_dump(level + 1, "SINGLE_CHAN", frm); + break; + case 0x5004: + radiotest_dump(level + 1, "RADIOTEST", frm); + break; + case 0x500c: + psstores_dump(level + 1, "PS_CLR_STORES", frm); + break; + case 0x6000: + valueless_dump(level + 1, "NO_VARIABLE", frm); + break; + case 0x6802: + uint16_dump(level + 1, "CONFIG_UART", frm); + break; + case 0x6805: + uint16_dump(level + 1, "PANIC_ARG", frm); + break; + case 0x6806: + uint16_dump(level + 1, "FAULT_ARG", frm); + break; + case 0x6827: + int8_dump(level + 1, "MAX_TX_POWER", frm); + break; + case 0x682b: + int8_dump(level + 1, "DEFAULT_TX_POWER", frm); + break; + case 0x7003: + pskey_dump(level + 1, frm); + break; + default: + raw_dump(level + 1, frm); + break; + } +} + +static char *cid2str(uint8_t cid) +{ + switch (cid & 0x3f) { + case 0: + return "BCSP Internal"; + case 1: + return "BCSP Link"; + case 2: + return "BCCMD"; + case 3: + return "HQ"; + case 4: + return "Device Mgt"; + case 5: + return "HCI Cmd/Evt"; + case 6: + return "HCI ACL"; + case 7: + return "HCI SCO"; + case 8: + return "L2CAP"; + case 9: + return "RFCOMM"; + case 10: + return "SDP"; + case 11: + return "Debug"; + case 12: + return "DFU"; + case 13: + return "VM"; + case 14: + return "Unused"; + case 15: + return "Reserved"; + default: + return "Unknown"; + } +} + +static char *frag2str(uint8_t frag) +{ + switch (frag & 0xc0) { + case 0x00: + return " middle fragment"; + case 0x40: + return " first fragment"; + case 0x80: + return " last fragment"; + default: + return ""; + } +} + +void csr_dump(int level, struct frame *frm) +{ + uint8_t desc, cid, type; + uint16_t handle, master, addr; + + desc = CSR_U8(frm); + + cid = desc & 0x3f; + + switch (cid) { + case 2: + bccmd_dump(level, frm); + break; + + case 20: + type = CSR_U8(frm); + + if (!p_filter(FILT_LMP)) { + switch (type) { + case 0x0f: + frm->handle = ((uint8_t *) frm->ptr)[17]; + frm->master = 0; + frm->len--; + lmp_dump(level, frm); + return; + case 0x10: + frm->handle = ((uint8_t *) frm->ptr)[17]; + frm->master = 1; + frm->len--; + lmp_dump(level, frm); + return; + case 0x12: + handle = CSR_U16(frm); + master = CSR_U16(frm); + addr = CSR_U16(frm); + p_indent(level, frm); + printf("FHS: handle %d addr %d (%s)\n", handle, + addr, master ? "master" : "slave"); + if (!master) { + char addr[18]; + p_ba2str((bdaddr_t *) frm->ptr, addr); + p_indent(level + 1, frm); + printf("bdaddr %s class " + "0x%2.2x%2.2x%2.2x\n", addr, + ((uint8_t *) frm->ptr)[8], + ((uint8_t *) frm->ptr)[7], + ((uint8_t *) frm->ptr)[6]); + } + return; + case 0x7b: + p_indent(level, frm); + printf("LMP(r): duplicate (same SEQN)\n"); + return; + } + } + + p_indent(level, frm); + printf("CSR: Debug (type 0x%2.2x)\n", type); + raw_dump(level, frm); + break; + + default: + p_indent(level, frm); + printf("CSR: %s (channel %d)%s\n", cid2str(cid), cid, frag2str(desc)); + raw_dump(level, frm); + break; + } +} |