626 lines
13 KiB
C
626 lines
13 KiB
C
|
/*
|
||
|
*
|
||
|
* 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;
|
||
|
}
|
||
|
}
|