csr.c revision e435ed5cf8b7c352b607cb8601a2eefdb7bfc17d
1/* 2 * 3 * Bluetooth packet analyzer - CSR parser 4 * 5 * Copyright (C) 2004-2005 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 * 23 * $Id$ 24 */ 25 26#include <stdio.h> 27#include <stdlib.h> 28#include <unistd.h> 29#include <errno.h> 30#include <string.h> 31 32#include <sys/types.h> 33#include <netinet/in.h> 34 35#include "parser.h" 36 37#define CSR_U8(frm) (get_u8(frm)) 38#define CSR_U16(frm) (btohs(htons(get_u16(frm)))) 39#define CSR_U32(frm) (btohl(htonl(get_u32(frm)))) 40 41static char *type2str(uint16_t type) 42{ 43 switch (type) { 44 case 0x0000: 45 return "Get req"; 46 case 0x0001: 47 return "Get rsp"; 48 case 0x0002: 49 return "Set req"; 50 default: 51 return "Reserved"; 52 } 53} 54 55static inline void uint16_dump(int level, char *str, struct frame *frm) 56{ 57 uint16_t value; 58 59 value = CSR_U16(frm); 60 61 p_indent(level, frm); 62 printf("%s: value %d (0x%4.4x)\n", str, value, value); 63} 64 65static inline void uint32_dump(int level, char *str, struct frame *frm) 66{ 67 uint32_t value; 68 69 value = CSR_U32(frm); 70 71 p_indent(level, frm); 72 printf("%s: value %d (0x%4.4x)\n", str, value, value); 73} 74 75static inline void bdaddr_dump(int level, char *str, struct frame *frm) 76{ 77 char addr[18]; 78 79 ba2str(frm->ptr, addr); 80 81 p_indent(level, frm); 82 printf("%s: bdaddr %s\n", str, addr); 83} 84 85static inline void features_dump(int level, char *str, struct frame *frm) 86{ 87 unsigned char features[8]; 88 int i; 89 90 memcpy(features, frm->ptr, 8); 91 92 p_indent(level, frm); 93 printf("%s: features", str); 94 for (i = 0; i < 8; i++) 95 printf(" 0x%02x", features[i]); 96 printf("\n"); 97} 98 99static inline void handle_length_dump(int level, char *str, struct frame *frm) 100{ 101 uint16_t handle, length; 102 103 handle = CSR_U16(frm); 104 length = CSR_U16(frm); 105 106 p_indent(level, frm); 107 printf("%s: handle %d length %d\n", str, handle, length); 108} 109 110static inline void pskey_dump(int level, struct frame *frm) 111{ 112 uint16_t key, length, stores; 113 114 key = CSR_U16(frm); 115 length = CSR_U16(frm); 116 stores = CSR_U16(frm); 117 118 p_indent(level, frm); 119 printf("PSKEY: key 0x%4.4x len %d stores %d\n", key, length, stores); 120 121 switch (key) { 122 case 0x0001: 123 bdaddr_dump(level + 1, "BDADDR", frm); 124 break; 125 case 0x00da: 126 uint16_dump(level + 1, "ENC_KEY_LMIN", frm); 127 break; 128 case 0x00db: 129 uint16_dump(level + 1, "ENC_KEY_LMAX", frm); 130 break; 131 case 0x00ef: 132 features_dump(level + 1, "LOCAL_SUPPORTED_FEATURES", frm); 133 break; 134 case 0x010d: 135 uint16_dump(level + 1, "HCI_LMP_LOCAL_VERSION", frm); 136 break; 137 case 0x010e: 138 uint16_dump(level + 1, "LMP_REMOTE_VERSION", frm); 139 break; 140 case 0x01ab: 141 uint16_dump(level + 1, "HOSTIO_MAP_SCO_PCM", frm); 142 break; 143 case 0x01be: 144 uint16_dump(level + 1, "UART_BAUDRATE", frm); 145 break; 146 case 0x01f9: 147 uint16_dump(level + 1, "HOST_INTERFACE", frm); 148 break; 149 case 0x02be: 150 uint16_dump(level + 1, "USB_VENDOR_ID", frm); 151 break; 152 case 0x02bf: 153 uint16_dump(level + 1, "USB_PRODUCT_ID", frm); 154 break; 155 case 0x02cb: 156 uint16_dump(level + 1, "USB_DFU_PRODUCT_ID", frm); 157 break; 158 case 0x03cd: 159 uint16_dump(level + 1, "INITIAL_BOOTMODE", frm); 160 break; 161 default: 162 raw_dump(level + 1, frm); 163 break; 164 } 165} 166 167static inline void bccmd_dump(int level, struct frame *frm) 168{ 169 uint16_t type, length, seqno, varid, status; 170 171 type = CSR_U16(frm); 172 length = CSR_U16(frm); 173 seqno = CSR_U16(frm); 174 varid = CSR_U16(frm); 175 status = CSR_U16(frm); 176 177 p_indent(level, frm); 178 printf("BCCMD: %s: len %d seqno %d varid 0x%4.4x status %d\n", 179 type2str(type), length, seqno, varid, status); 180 181 if (!(parser.flags & DUMP_VERBOSE)) { 182 raw_dump(level + 1, frm); 183 return; 184 } 185 186 switch (varid) { 187 case 0x2819: 188 uint16_dump(level + 1, "BUILDID", frm); 189 break; 190 case 0x281a: 191 uint16_dump(level + 1, "CHIPVER", frm); 192 break; 193 case 0x281b: 194 uint16_dump(level + 1, "CHIPREV", frm); 195 break; 196 case 0x2825: 197 uint16_dump(level + 1, "INTERFACE_VERSION", frm); 198 break; 199 case 0x282a: 200 uint16_dump(level + 1, "RAND", frm); 201 break; 202 case 0x282c: 203 uint16_dump(level + 1, "MAX_CRYPT_KEY_LENGTH", frm); 204 break; 205 case 0x2836: 206 uint16_dump(level + 1, "CHIPANAREV", frm); 207 break; 208 case 0x2838: 209 uint16_dump(level + 1, "BUILDID_LOADER", frm); 210 break; 211 case 0x2c00: 212 uint32_dump(level + 1, "BT_CLOCK", frm); 213 break; 214 case 0x3008: 215 handle_length_dump(level + 1, "CRYPT_KEY_LENGTH", frm); 216 break; 217 case 0x481c: 218 uint16_dump(level + 1, "MAP_SCO_PCM", frm); 219 break; 220 case 0x6802: 221 uint16_dump(level + 1, "CONFIG_UART", frm); 222 break; 223 case 0x6805: 224 uint16_dump(level + 1, "PANIC_ARG", frm); 225 break; 226 case 0x6806: 227 uint16_dump(level + 1, "FAULT_ARG", frm); 228 break; 229 case 0x7003: 230 pskey_dump(level + 1, frm); 231 break; 232 default: 233 raw_dump(level + 1, frm); 234 break; 235 } 236} 237 238static char *cid2str(uint8_t cid) 239{ 240 switch (cid & 0x3f) { 241 case 0: 242 return "BCSP Internal"; 243 case 1: 244 return "BCSP Link"; 245 case 2: 246 return "BCCMD"; 247 case 3: 248 return "HQ"; 249 case 4: 250 return "Device Mgt"; 251 case 5: 252 return "HCI Cmd/Evt"; 253 case 6: 254 return "HCI ACL"; 255 case 7: 256 return "HCI SCO"; 257 case 8: 258 return "L2CAP"; 259 case 9: 260 return "RFCOMM"; 261 case 10: 262 return "SDP"; 263 case 11: 264 return "Debug"; 265 case 12: 266 return "DFU"; 267 case 13: 268 return "VM"; 269 case 14: 270 return "Unused"; 271 case 15: 272 return "Reserved"; 273 default: 274 return "Unknown"; 275 } 276} 277 278static char *frag2str(uint8_t frag) 279{ 280 switch (frag & 0xc0) { 281 case 0x00: 282 return " middle fragment"; 283 case 0x40: 284 return " first fragment"; 285 case 0x80: 286 return " last fragment"; 287 default: 288 return ""; 289 } 290} 291 292void csr_dump(int level, struct frame *frm) 293{ 294 uint8_t desc, cid, type; 295 uint16_t handle, master, addr; 296 297 desc = CSR_U8(frm); 298 299 cid = desc & 0x3f; 300 301 switch (cid) { 302 case 2: 303 bccmd_dump(level, frm); 304 break; 305 306 case 20: 307 type = CSR_U8(frm); 308 309 if (!p_filter(FILT_LMP)) { 310 switch (type) { 311 case 0x0f: 312 frm->handle = ((uint8_t *) frm->ptr)[17]; 313 frm->master = 0; 314 frm->len--; 315 lmp_dump(level, frm); 316 return; 317 case 0x10: 318 frm->handle = ((uint8_t *) frm->ptr)[17]; 319 frm->master = 1; 320 frm->len--; 321 lmp_dump(level, frm); 322 return; 323 case 0x12: 324 handle = CSR_U16(frm); 325 master = CSR_U16(frm); 326 addr = CSR_U16(frm); 327 p_indent(level, frm); 328 printf("FHS: handle %d addr %d (%s)\n", handle, 329 addr, master ? "master" : "slave"); 330 if (!master) 331 raw_dump(level, frm); 332 return; 333 case 0x7b: 334 p_indent(level, frm); 335 printf("LMP(r): duplicate (same SEQN)\n"); 336 return; 337 } 338 } 339 340 p_indent(level, frm); 341 printf("CSR: Debug (type 0x%2.2x)\n", type); 342 raw_dump(level, frm); 343 break; 344 345 default: 346 p_indent(level, frm); 347 printf("CSR: %s (channel %d)%s\n", cid2str(cid), cid, frag2str(desc)); 348 raw_dump(level, frm); 349 break; 350 } 351} 352