summaryrefslogtreecommitdiffstats
path: root/tools/bccmd.c
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2005-11-06 21:00:58 +0000
committerMarcel Holtmann <marcel@holtmann.org>2005-11-06 21:00:58 +0000
commit50a8cc8a256f3ef56a6144cabd2ae6ee5848e46d (patch)
treee87bce02680dea3e05c51f2c727d91b6805cf726 /tools/bccmd.c
parent9410c612d365b3aabf13da966e6782225068954f (diff)
Update to the new BCCMD interface utility
Diffstat (limited to 'tools/bccmd.c')
-rw-r--r--tools/bccmd.c749
1 files changed, 704 insertions, 45 deletions
diff --git a/tools/bccmd.c b/tools/bccmd.c
index 46cc2be1..e41f08f5 100644
--- a/tools/bccmd.c
+++ b/tools/bccmd.c
@@ -37,12 +37,144 @@
#include "csr.h"
+#define CSR_TRANSPORT_UNKNOWN 0
+#define CSR_TRANSPORT_HCI 1
+#define CSR_TRANSPORT_USB 2
+#define CSR_TRANSPORT_BCSP 3
+#define CSR_TRANSPORT_H4 4
+#define CSR_TRANSPORT_3WIRE 5
+
+#define CSR_STORES_PSI (0x0001)
+#define CSR_STORES_PSF (0x0002)
+#define CSR_STORES_PSROM (0x0004)
+#define CSR_STORES_PSRAM (0x0008)
+#define CSR_STORES_DEFAULT (CSR_STORES_PSI | CSR_STORES_PSF | CSR_STORES_PSRAM)
+
+#define CSR_TYPE_NULL 0
+#define CSR_TYPE_COMPLEX 1
+#define CSR_TYPE_UINT8 2
+#define CSR_TYPE_UINT16 3
+#define CSR_TYPE_UINT32 4
+
+#define CSR_TYPE_ARRAY CSR_TYPE_COMPLEX
+#define CSR_TYPE_BDADDR CSR_TYPE_COMPLEX
+
+static uint16_t seqnum = 0x0000;
+
+static struct {
+ uint16_t pskey;
+ int type;
+ int size;
+ char *str;
+} storage[] = {
+ { CSR_PSKEY_BDADDR, CSR_TYPE_BDADDR, 8, "bdaddr" },
+ { CSR_PSKEY_COUNTRYCODE, CSR_TYPE_UINT16, 0, "country" },
+ { CSR_PSKEY_CLASSOFDEVICE, CSR_TYPE_UINT32, 0, "devclass" },
+ { CSR_PSKEY_ENC_KEY_LMIN, CSR_TYPE_UINT16, 0, "keymin" },
+ { CSR_PSKEY_ENC_KEY_LMAX, CSR_TYPE_UINT16, 0, "keymax" },
+ { CSR_PSKEY_LOCAL_SUPPORTED_FEATURES, CSR_TYPE_ARRAY, 8, "features" },
+ { CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS, CSR_TYPE_ARRAY, 18, "commands" },
+ { CSR_PSKEY_HCI_LMP_LOCAL_VERSION, CSR_TYPE_UINT16, 0, "version" },
+ { CSR_PSKEY_LMP_REMOTE_VERSION, CSR_TYPE_UINT8, 0, "remver" },
+ { CSR_PSKEY_HOSTIO_USE_HCI_EXTN, CSR_TYPE_UINT16, 0, "hciextn" },
+ { CSR_PSKEY_HOSTIO_MAP_SCO_PCM, CSR_TYPE_UINT16, 0, "mapsco" },
+ { CSR_PSKEY_UART_BAUDRATE, CSR_TYPE_UINT16, 0, "baudrate" },
+ { CSR_PSKEY_HOST_INTERFACE, CSR_TYPE_UINT16, 0, "hostintf" },
+ { CSR_PSKEY_ANA_FREQ, CSR_TYPE_UINT16, 0, "anafreq" },
+ { CSR_PSKEY_ANA_FTRIM, CSR_TYPE_UINT16, 0, "anaftrim" },
+ { CSR_PSKEY_USB_VENDOR_ID, CSR_TYPE_UINT16, 0, "usbvid" },
+ { CSR_PSKEY_USB_PRODUCT_ID, CSR_TYPE_UINT16, 0, "usbpid" },
+ { CSR_PSKEY_USB_DFU_PRODUCT_ID, CSR_TYPE_UINT16, 0, "dfupid" },
+ { CSR_PSKEY_INITIAL_BOOTMODE, CSR_TYPE_UINT16, 0, "bootmode" },
+ { 0x0000 },
+};
+
+static int pskey_size(uint16_t pskey)
+{
+ switch (pskey) {
+ case CSR_PSKEY_BDADDR:
+ return 8;
+ case CSR_PSKEY_LOCAL_SUPPORTED_FEATURES:
+ return 8;
+ case CSR_PSKEY_LOCAL_SUPPORTED_COMMANDS:
+ return 18;
+ default:
+ return 64;
+ }
+}
+
+static char *storestostr(uint16_t stores)
+{
+ switch (stores) {
+ case 0x0000:
+ return "Default";
+ case 0x0001:
+ return "psi";
+ case 0x0002:
+ return "psf";
+ case 0x0004:
+ return "psrom";
+ case 0x0008:
+ return "psram";
+ default:
+ return "Unknown";
+ }
+}
+
+static char *memorytostr(uint16_t type)
+{
+ switch (type) {
+ case 0x0000:
+ return "Flash memory";
+ case 0x0001:
+ return "EEPROM";
+ case 0x0002:
+ return "RAM (transient)";
+ case 0x0003:
+ return "ROM (or \"read-only\" flash memory)";
+ default:
+ return "Unknown";
+ }
+}
+
+#define OPT_RANGE(range) \
+ if (argc < (range)) { errno = EINVAL; return -1; } \
+ if (argc > (range)) { errno = E2BIG; return -1; }
+
+static struct option help_options[] = {
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static int opt_help(int argc, char *argv[], int *help)
+{
+ int opt;
+
+ while ((opt=getopt_long(argc, argv, "+h", help_options, NULL)) != EOF) {
+ switch (opt) {
+ case 'h':
+ if (help)
+ *help = 1;
+ break;
+ }
+ }
+
+ return optind;
+}
+
+#define OPT_HELP(range, help) \
+ opt_help(argc, argv, (help)); \
+ argc -= optind; argv += optind; optind = 0; \
+ OPT_RANGE((range))
+
static int cmd_builddef(int dd, int argc, char *argv[])
{
uint8_t buf[8];
- uint16_t seqnum = 0x4711, def = 0x0000, nextdef = 0x0000;
+ uint16_t def = 0x0000, nextdef = 0x0000;
int err = 0;
+ OPT_HELP(0, NULL);
+
printf("Build definitions:\n");
while (1) {
@@ -76,15 +208,7 @@ static int cmd_keylen(int dd, int argc, char *argv[])
uint16_t handle, keylen;
int err;
- if (argc < 1) {
- errno = EINVAL;
- return -1;
- }
-
- if (argc > 1) {
- errno = E2BIG;
- return -1;
- }
+ OPT_HELP(1, NULL);
handle = atoi(argv[0]);
@@ -92,7 +216,7 @@ static int cmd_keylen(int dd, int argc, char *argv[])
buf[0] = handle & 0xff;
buf[1] = handle >> 8;
- err = csr_read_varid_complex(dd, 0x4711,
+ err = csr_read_varid_complex(dd, seqnum++,
CSR_VARID_CRYPT_KEY_LENGTH, buf, sizeof(buf));
if (err < 0) {
errno = -err;
@@ -112,7 +236,9 @@ static int cmd_clock(int dd, int argc, char *argv[])
uint32_t clock = 0;
int err;
- err = csr_read_varid_uint32(dd, 0x4711, CSR_VARID_BT_CLOCK, &clock);
+ OPT_HELP(0, NULL);
+
+ err = csr_read_varid_uint32(dd, seqnum++, CSR_VARID_BT_CLOCK, &clock);
if (err < 0) {
errno = -err;
return -1;
@@ -128,7 +254,9 @@ static int cmd_rand(int dd, int argc, char *argv[])
uint16_t rand = 0;
int err;
- err = csr_read_varid_uint16(dd, 5, CSR_VARID_RAND, &rand);
+ OPT_HELP(0, NULL);
+
+ err = csr_read_varid_uint16(dd, seqnum++, CSR_VARID_RAND, &rand);
if (err < 0) {
errno = -err;
return -1;
@@ -144,7 +272,9 @@ static int cmd_panicarg(int dd, int argc, char *argv[])
uint16_t error = 0;
int err;
- err = csr_read_varid_uint16(dd, 5, CSR_VARID_PANIC_ARG, &error);
+ OPT_HELP(0, NULL);
+
+ err = csr_read_varid_uint16(dd, seqnum++, CSR_VARID_PANIC_ARG, &error);
if (err < 0) {
errno = -err;
return -1;
@@ -161,7 +291,9 @@ static int cmd_faultarg(int dd, int argc, char *argv[])
uint16_t error = 0;
int err;
- err = csr_read_varid_uint16(dd, 5, CSR_VARID_FAULT_ARG, &error);
+ OPT_HELP(0, NULL);
+
+ err = csr_read_varid_uint16(dd, seqnum++, CSR_VARID_FAULT_ARG, &error);
if (err < 0) {
errno = -err;
return -1;
@@ -175,60 +307,555 @@ static int cmd_faultarg(int dd, int argc, char *argv[])
static int cmd_coldreset(int dd, int argc, char *argv[])
{
- return csr_write_varid_valueless(dd, 0, CSR_VARID_COLD_RESET);
+ return csr_write_varid_valueless(dd, seqnum++, CSR_VARID_COLD_RESET);
}
static int cmd_warmreset(int dd, int argc, char *argv[])
{
- return csr_write_varid_valueless(dd, 0, CSR_VARID_WARM_RESET);
+ return csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
}
static int cmd_disabletx(int dd, int argc, char *argv[])
{
- return csr_write_varid_valueless(dd, 0, CSR_VARID_DISABLE_TX);
+ return csr_write_varid_valueless(dd, seqnum++, CSR_VARID_DISABLE_TX);
}
static int cmd_enabletx(int dd, int argc, char *argv[])
{
- return csr_write_varid_valueless(dd, 0, CSR_VARID_ENABLE_TX);
+ return csr_write_varid_valueless(dd, seqnum++, CSR_VARID_ENABLE_TX);
+}
+
+static int cmd_memtypes(int dd, int argc, char *argv[])
+{
+ uint8_t array[8];
+ uint16_t type, stores[4] = { 0x0001, 0x0002, 0x0004, 0x0008 };
+ int i, err;
+
+ OPT_HELP(0, NULL);
+
+ for (i = 0; i < 4; i++) {
+ memset(array, 0, sizeof(array));
+ array[2] = stores[i] & 0xff;
+ array[3] = stores[i] >> 8;
+
+ err = csr_read_varid_complex(dd, seqnum++,
+ CSR_VARID_PS_MEMORY_TYPE, array, sizeof(array));
+ if (err < 0)
+ break;
+
+ type = array[4] + (array[5] << 8);
+
+ printf("%s (0x%04x) = %s (%d)\n", storestostr(stores[i]),
+ stores[i], memorytostr(type), type);
+ }
+
+ return err;
+}
+
+static struct option pskey_options[] = {
+ { "stores", 1, 0, 's' },
+ { "reset", 0, 0, 'r' },
+ { "help", 0, 0, 'h' },
+ { 0, 0, 0, 0 }
+};
+
+static int opt_pskey(int argc, char *argv[], uint16_t *stores, int *reset, int *help)
+{
+ int opt;
+
+ while ((opt=getopt_long(argc, argv, "+s:rh", pskey_options, NULL)) != EOF) {
+ switch (opt) {
+ case 's':
+ if (!stores)
+ break;
+ if (!strcasecmp(optarg, "default"))
+ *stores = 0x0000;
+ else if (!strcasecmp(optarg, "implementation"))
+ *stores = 0x0001;
+ else if (!strcasecmp(optarg, "factory"))
+ *stores = 0x0002;
+ else if (!strcasecmp(optarg, "rom"))
+ *stores = 0x0004;
+ else if (!strcasecmp(optarg, "ram"))
+ *stores = 0x0008;
+ else if (!strcasecmp(optarg, "psi"))
+ *stores = 0x0001;
+ else if (!strcasecmp(optarg, "psf"))
+ *stores = 0x0002;
+ else if (!strcasecmp(optarg, "psrom"))
+ *stores = 0x0004;
+ else if (!strcasecmp(optarg, "psram"))
+ *stores = 0x0008;
+ else if (!strncasecmp(optarg, "0x", 2))
+ *stores = strtol(optarg, NULL, 16);
+ else
+ *stores = atoi(optarg);
+ break;
+
+ case 'r':
+ if (reset)
+ *reset = 1;
+ break;
+
+ case 'h':
+ if (help)
+ *help = 1;
+ break;
+ }
+ }
+
+ return optind;
+}
+
+#define OPT_PSKEY(range, stores, reset, help) \
+ opt_pskey(argc, argv, (stores), (reset), (help)); \
+ argc -= optind; argv += optind; optind = 0; \
+ OPT_RANGE((range))
+
+static int cmd_psget(int dd, int argc, char *argv[])
+{
+ uint8_t array[64];
+ uint16_t pskey, length, value, stores = CSR_STORES_DEFAULT;
+ uint32_t val32;
+ int i, err, size, reset = 0, type = CSR_TYPE_NULL;
+
+ memset(array, 0, sizeof(array));
+
+ OPT_PSKEY(1, &stores, &reset, NULL);
+
+ if (strncasecmp(argv[0], "0x", 2)) {
+ for (i = 0; storage[i].pskey; i++) {
+ if (strcasecmp(storage[i].str, argv[0]))
+ continue;
+
+ pskey = storage[i].pskey;
+ type = storage[i].type;
+ size = storage[i].type;
+ break;
+ }
+ pskey = atoi(argv[0]);
+ type = CSR_TYPE_COMPLEX;
+ size = sizeof(array);
+ } else {
+ pskey = strtol(argv[0] + 2, NULL, 16);
+ type = CSR_TYPE_COMPLEX;
+ size = sizeof(array);
+ }
+
+ switch (type) {
+ case CSR_TYPE_COMPLEX:
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = stores & 0xff;
+ array[3] = stores >> 8;
+
+ err = csr_read_varid_complex(dd, seqnum++,
+ CSR_VARID_PS_SIZE, array, 8);
+ if (err < 0)
+ return err;
+
+ length = array[2] + (array[3] << 8);
+ if (length > sizeof(array) / 2)
+ return -EIO;
+
+ err = csr_read_pskey_complex(dd, seqnum++, pskey, stores,
+ array, length * 2);
+ if (err < 0)
+ return err;
+
+ printf("%s:", csr_pskeytostr(pskey));
+ for (i = 0; i < length; i++)
+ printf(" 0x%02x%02x", array[i * 2], array[(i * 2) + 1]);
+ printf("\n");
+ break;
+
+ case CSR_TYPE_UINT8:
+ case CSR_TYPE_UINT16:
+ err = csr_read_pskey_uint16(dd, seqnum++, pskey, stores, &value);
+ if (err < 0)
+ return err;
+
+ printf("%s: 0x%04x (%d)\n", csr_pskeytostr(pskey), value, value);
+ break;
+
+ case CSR_TYPE_UINT32:
+ err = csr_read_pskey_uint32(dd, seqnum++, pskey, stores, &val32);
+ if (err < 0)
+ return err;
+
+ printf("%s: 0x%08x (%d)\n", csr_pskeytostr(pskey), val32, val32);
+ break;
+
+ default:
+ errno = EFAULT;
+ err = -1;
+ break;
+ }
+
+ if (!err && reset)
+ csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+
+ return err;
+}
+
+static int cmd_psset(int dd, int argc, char *argv[])
+{
+ uint8_t array[64];
+ uint16_t pskey, value, stores = CSR_STORES_PSRAM;
+ uint32_t val32;
+ int i, err, size, reset = 0, type = CSR_TYPE_NULL;
+
+ memset(array, 0, sizeof(array));
+
+ OPT_PSKEY(2, &stores, &reset, NULL);
+
+ if (strncasecmp(argv[0], "0x", 2)) {
+ for (i = 0; storage[i].pskey; i++) {
+ if (strcasecmp(storage[i].str, argv[0]))
+ continue;
+
+ pskey = storage[i].pskey;
+ type = storage[i].type;
+ size = storage[i].type;
+ break;
+ }
+ pskey = atoi(argv[0]);
+ type = CSR_TYPE_COMPLEX;
+ size = sizeof(array);
+ } else {
+ pskey = strtol(argv[0] + 2, NULL, 16);
+ type = CSR_TYPE_COMPLEX;
+ size = sizeof(array);
+ }
+
+ argc--;
+ argv++;
+
+ switch (type) {
+ case CSR_TYPE_COMPLEX:
+ size = pskey_size(pskey);
+
+ if (argc != size) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (i = 0; i < size; i++)
+ if (!strncasecmp(argv[0], "0x", 2))
+ array[i] = strtol(argv[i] + 2, NULL, 16);
+ else
+ array[i] = atoi(argv[i]);
+
+ err = csr_write_pskey_complex(dd, seqnum++, pskey,
+ stores, array, size);
+ break;
+
+ case CSR_TYPE_UINT8:
+ case CSR_TYPE_UINT16:
+ if (argc != 1) {
+ errno = E2BIG;
+ return -1;
+ }
+
+ if (!strncasecmp(argv[0], "0x", 2))
+ value = strtol(argv[0] + 2, NULL, 16);
+ else
+ value = atoi(argv[0]);
+
+ err = csr_write_pskey_uint16(dd, seqnum++, pskey, stores, value);
+ break;
+
+ case CSR_TYPE_UINT32:
+ if (argc != 1) {
+ errno = E2BIG;
+ return -1;
+ }
+
+ if (!strncasecmp(argv[0], "0x", 2))
+ val32 = strtol(argv[0] + 2, NULL, 16);
+ else
+ val32 = atoi(argv[0]);
+
+ err = csr_write_pskey_uint32(dd, seqnum++, pskey, stores, val32);
+ break;
+
+ default:
+ errno = EFAULT;
+ err = -1;
+ break;
+ }
+
+ if (!err && reset)
+ csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+
+ return err;
+}
+
+static int cmd_psclr(int dd, int argc, char *argv[])
+{
+ uint8_t array[8];
+ uint16_t pskey, stores = CSR_STORES_PSRAM;
+ int i, err, reset = 0;
+
+ OPT_PSKEY(1, &stores, &reset, NULL);
+
+ if (strncasecmp(argv[0], "0x", 2)) {
+ for (i = 0; storage[i].pskey; i++) {
+ if (strcasecmp(storage[i].str, argv[0]))
+ continue;
+
+ pskey = storage[i].pskey;
+ break;
+ }
+ pskey = atoi(argv[0]);
+ } else
+ pskey = strtol(argv[0] + 2, NULL, 16);
+
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = stores & 0xff;
+ array[3] = stores >> 8;
+
+ err = csr_write_varid_complex(dd, seqnum++,
+ CSR_VARID_PS_CLR_STORES, array, sizeof(array));
+
+ if (!err && reset)
+ csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+
+ return err;
+}
+
+static int cmd_pslist(int dd, int argc, char *argv[])
+{
+ uint8_t array[8];
+ uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT;
+ int err, reset = 0;
+
+ OPT_PSKEY(0, &stores, &reset, NULL);
+
+ while (1) {
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = stores & 0xff;
+ array[3] = stores >> 8;
+
+ err = csr_read_varid_complex(dd, seqnum++,
+ CSR_VARID_PS_NEXT, array, sizeof(array));
+ if (err < 0)
+ break;
+
+ pskey = array[4] + (array[5] << 8);
+ if (pskey == 0x0000)
+ break;
+
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = stores & 0xff;
+ array[3] = stores >> 8;
+
+ err = csr_read_varid_complex(dd, seqnum++,
+ CSR_VARID_PS_SIZE, array, sizeof(array));
+ if (err < 0)
+ continue;
+
+ length = array[2] + (array[3] << 8);
+
+ printf("0x%04x - %s (%d bytes)\n", pskey,
+ csr_pskeytostr(pskey), length * 2);
+ }
+
+ if (reset)
+ csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+
+ return 0;
+}
+
+static int cmd_psread(int dd, int argc, char *argv[])
+{
+ uint8_t array[256];
+ uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT;
+ char *str, val[7];
+ int i, err, reset = 0;
+
+ OPT_PSKEY(0, &stores, &reset, NULL);
+
+ while (1) {
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = stores & 0xff;
+ array[3] = stores >> 8;
+
+ err = csr_read_varid_complex(dd, seqnum++,
+ CSR_VARID_PS_NEXT, array, 8);
+ if (err < 0)
+ break;
+
+ pskey = array[4] + (array[5] << 8);
+ if (pskey == 0x0000)
+ break;
+
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = stores & 0xff;
+ array[3] = stores >> 8;
+
+ err = csr_read_varid_complex(dd, seqnum++,
+ CSR_VARID_PS_SIZE, array, 8);
+ if (err < 0)
+ continue;
+
+ length = array[2] + (array[3] << 8);
+ if (length > sizeof(array) / 2)
+ continue;
+
+ err = csr_read_pskey_complex(dd, seqnum++, pskey,
+ stores, array, length * 2);
+ if (err < 0)
+ continue;
+
+ str = csr_pskeytoval(pskey);
+ if (!strcasecmp(str, "UNKNOWN")) {
+ sprintf(val, "0x%04x", pskey);
+ str = NULL;
+ }
+
+ printf("// %s%s\n&%04x =", str ? "PSKEY_" : "",
+ str ? str : val, pskey);
+ for (i = 0; i < length; i++)
+ printf(" %02x%02x", array[i * 2 + 1], array[i * 2]);
+ printf("\n");
+ }
+
+ if (reset)
+ csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+
+ return 0;
+}
+
+static int cmd_psload(int dd, int argc, char *argv[])
+{
+ uint8_t array[256];
+ uint16_t pskey, size, stores = CSR_STORES_PSRAM;
+ char *str, val[7];
+ int err, reset = 0;
+
+ OPT_PSKEY(1, &stores, &reset, NULL);
+
+ psr_read(argv[0]);
+
+ while (psr_get(&pskey, array, &size) == 0) {
+ str = csr_pskeytoval(pskey);
+ if (!strcasecmp(str, "UNKNOWN")) {
+ sprintf(val, "0x%04x", pskey);
+ str = NULL;
+ }
+
+ printf("Loading %s%s ... ", str ? "PSKEY_" : "",
+ str ? str : val);
+ fflush(stdout);
+
+ err = csr_write_pskey_complex(dd, seqnum++, pskey,
+ stores, array, size);
+
+ printf("%s\n", err < 0 ? "failed" : "done");
+ }
+
+ if (reset)
+ csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+
+ return 0;
+}
+
+static int cmd_pscheck(int dd, int argc, char *argv[])
+{
+ uint8_t array[256];
+ uint16_t pskey, size;
+ int i;
+
+ OPT_HELP(1, NULL);
+
+ psr_read(argv[0]);
+
+ while (psr_get(&pskey, array, &size) == 0) {
+ printf("0x%04x =", pskey);
+ for (i = 0; i < size; i++)
+ printf(" 0x%02x", array[i]);
+ printf("\n");
+ }
+
+ return 0;
}
static struct {
char *str;
- int (*func)(int dd, int argc, char **argv);
+ int (*func)(int dd, int argc, char *argv[]);
char *arg;
char *doc;
} commands[] = {
- { "builddef", cmd_builddef, "", "Get build definitions" },
- { "keylen", cmd_keylen, "<handle>", "Get current crypt key length" },
- { "clock", cmd_clock, "", "Get local Bluetooth clock" },
- { "rand", cmd_rand, "", "Get random number" },
- { "panicarg", cmd_panicarg, "", "Get panic code argument" },
- { "faultarg", cmd_faultarg, "", "Get fault code argument" },
- { "coldreset", cmd_coldreset, "", "Perform cold reset" },
- { "warmreset", cmd_warmreset, "", "Perform warm reset" },
- { "disabletx", cmd_disabletx, "", "Disable TX on the device" },
- { "enabletx", cmd_enabletx, "", "Enable TX on the device" },
- { NULL },
+ { "builddef", cmd_builddef, "", "Get build definitions" },
+ { "keylen", cmd_keylen, "<handle>", "Get current crypt key length" },
+ { "clock", cmd_clock, "", "Get local Bluetooth clock" },
+ { "rand", cmd_rand, "", "Get random number" },
+ { "panicarg", cmd_panicarg, "", "Get panic code argument" },
+ { "faultarg", cmd_faultarg, "", "Get fault code argument" },
+ { "coldreset", cmd_coldreset, "", "Perform cold reset" },
+ { "warmreset", cmd_warmreset, "", "Perform warm reset" },
+ { "disabletx", cmd_disabletx, "", "Disable TX on the device" },
+ { "enabletx", cmd_enabletx, "", "Enable TX on the device" },
+ { "memtypes", cmd_memtypes, NULL, "Get memory types" },
+ { "psget", cmd_psget, "<key>", "Get value for PS key" },
+ { "psset", cmd_psset, "<key> <value>", "Set value for PS key" },
+ { "psclr", cmd_psclr, "<key>", "Clear value for PS key" },
+ { "pslist", cmd_pslist, NULL, "List all PS keys" },
+ { "psread", cmd_psread, NULL, "Read all PS keys" },
+ { "psload", cmd_psload, "<file>", "Load all PS keys from PSR file" },
+ { "pscheck", cmd_pscheck, "<file>", "Check PSR file" },
+ { NULL }
};
static void usage(void)
{
- int i;
+ int i, pos = 0;
printf("bccmd - Utility for the CSR BCCMD interface\n\n");
printf("Usage:\n"
- "\tbccmd [-i <dev>] <command>\n\n");
+ "\tbccmd [options] <command>\n\n");
+
+ printf("Options:\n"
+ "\t-t <transport> Select the transport\n"
+ "\t-d <device> Select the device\n"
+ "\t-h, --help Display help\n"
+ "\n");
printf("Commands:\n");
- for (i = 0; commands[i].str; i++)
- printf("\t%-10s%-8s\t%s\n", commands[i].str,
- commands[i].arg, commands[i].doc);
+ for (i = 0; commands[i].str; i++)
+ printf("\t%-10s %-14s\t%s\n", commands[i].str,
+ commands[i].arg ? commands[i].arg : " ",
+ commands[i].doc);
+ printf("\n");
+
+ printf("Keys:\n\t");
+ for (i = 0; storage[i].pskey; i++) {
+ printf("%s ", storage[i].str);
+ pos += strlen(storage[i].str) + 1;
+ if (pos > 60) {
+ printf("\n\t");
+ pos = 0;
+ }
+ }
+ printf("\n");
}
static struct option main_options[] = {
+ { "transport", 1, 0, 't' },
+ { "device", 1, 0, 'd' },
{ "help", 0, 0, 'h' },
- { "device", 1, 0, 'i' },
{ 0, 0, 0, 0 }
};
@@ -236,16 +863,33 @@ int main(int argc, char *argv[])
{
struct hci_dev_info di;
struct hci_version ver;
- int i, err, dd, opt, dev = 0;
+ char *device = NULL;
+ int i, err, opt, dd, dev, transport = CSR_TRANSPORT_HCI;
- while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
+ while ((opt=getopt_long(argc, argv, "+t:d:i:h", main_options, NULL)) != EOF) {
switch (opt) {
+ case 't':
+ if (!strcasecmp(optarg, "hci"))
+ transport = CSR_TRANSPORT_HCI;
+ else if (!strcasecmp(optarg, "usb"))
+ transport = CSR_TRANSPORT_USB;
+ else if (!strcasecmp(optarg, "bcsp"))
+ transport = CSR_TRANSPORT_BCSP;
+ else if (!strcasecmp(optarg, "h4"))
+ transport = CSR_TRANSPORT_H4;
+ else if (!strcasecmp(optarg, "h5"))
+ transport = CSR_TRANSPORT_3WIRE;
+ else if (!strcasecmp(optarg, "3wire"))
+ transport = CSR_TRANSPORT_3WIRE;
+ else if (!strcasecmp(optarg, "twutl"))
+ transport = CSR_TRANSPORT_3WIRE;
+ else
+ transport = CSR_TRANSPORT_UNKNOWN;
+ break;
+
+ case 'd':
case 'i':
- dev = hci_devid(optarg);
- if (dev < 0) {
- perror("Invalid device");
- exit(1);
- }
+ device = strdup(optarg);
break;
case 'h':
@@ -264,6 +908,21 @@ int main(int argc, char *argv[])
exit(1);
}
+ if (transport != CSR_TRANSPORT_HCI) {
+ fprintf(stderr, "Unsupported transport\n");
+ exit(1);
+ }
+
+ if (device) {
+ dev = hci_devid(device);
+ if (dev < 0) {
+ fprintf(stderr, "Device not available\n");
+ exit(1);
+ }
+ free(device);
+ } else
+ dev = 0;
+
dd = hci_open_dev(dev);
if (dd < 0) {
fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
@@ -295,7 +954,7 @@ int main(int argc, char *argv[])
if (strcasecmp(commands[i].str, argv[0]))
continue;
- err = commands[i].func(dd, argc - 1, argv + 1);
+ err = commands[i].func(dd, argc, argv);
hci_close_dev(dd);