summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2005-11-10 20:23:47 +0000
committerMarcel Holtmann <marcel@holtmann.org>2005-11-10 20:23:47 +0000
commit2ba0839002159cd293bb1a3d85645f04010cf33b (patch)
treef03e03afa2dc6ea774315bb116b177016623fdba
parent9fb18057b298238f576aa57a95fed56e1743a3e9 (diff)
Add USB transport to the bccmd utility
-rw-r--r--acinclude.m42
-rw-r--r--tools/Makefile.am4
-rw-r--r--tools/bccmd.c465
-rw-r--r--tools/csr.c4
-rw-r--r--tools/csr.h12
-rw-r--r--tools/csr_hci.c160
-rw-r--r--tools/csr_usb.c173
7 files changed, 597 insertions, 223 deletions
diff --git a/acinclude.m4 b/acinclude.m4
index 65ae27b3..8334785c 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -410,7 +410,7 @@ AC_DEFUN([AC_ARG_BLUEZ], [
AM_CONDITIONAL(CUPS, test "${cups_enable}" = "yes")
AM_CONDITIONAL(PCMCIA, test "${pcmcia_enable}" = "yes")
AM_CONDITIONAL(INITSCRIPTS, test "${initscripts_enable}" = "yes")
- AM_CONDITIONAL(BCCMD, test "${bccmd_enable}" = "yes")
+ AM_CONDITIONAL(BCCMD, test "${bccmd_enable}" = "yes" && test "${usb_found}" = "yes")
AM_CONDITIONAL(AVCTRL, test "${avctrl_enable}" = "yes" && test "${usb_found}" = "yes")
AM_CONDITIONAL(HID2HCI, test "${hid2hci_enable}" = "yes" && test "${usb_found}" = "yes")
AM_CONDITIONAL(DFUTOOL, test "${dfutool_enable}" = "yes" && test "${usb_found}" = "yes")
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 238a2df1..9d7065b2 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -52,8 +52,8 @@ ciptool_LDADD = @BLUEZ_LIBS@
ppporc_LDADD = @BLUEZ_LIBS@
if BCCMD
-bccmd_SOURCES = bccmd.c csr.h csr.c
-bccmd_LDADD = @BLUEZ_LIBS@
+bccmd_SOURCES = bccmd.c csr.h csr.c csr_hci.c csr_usb.c
+bccmd_LDADD = @USB_LIBS@ @BLUEZ_LIBS@
endif
if AVCTRL
diff --git a/tools/bccmd.c b/tools/bccmd.c
index 357620f5..f39686eb 100644
--- a/tools/bccmd.c
+++ b/tools/bccmd.c
@@ -59,7 +59,56 @@
#define CSR_TYPE_ARRAY CSR_TYPE_COMPLEX
#define CSR_TYPE_BDADDR CSR_TYPE_COMPLEX
-static uint16_t seqnum = 0x0000;
+static inline int transport_open(int transport, char *device)
+{
+ switch (transport) {
+ case CSR_TRANSPORT_HCI:
+ return csr_open_hci(device);
+ case CSR_TRANSPORT_USB:
+ return csr_open_usb(device);
+ default:
+ fprintf(stderr, "Unsupported transport\n");
+ return -1;
+ }
+}
+
+static inline void transport_close(int transport)
+{
+ switch (transport) {
+ case CSR_TRANSPORT_HCI:
+ csr_close_hci();
+ break;
+ case CSR_TRANSPORT_USB:
+ csr_close_usb();
+ break;
+ }
+}
+
+static inline int transport_read(int transport, uint16_t varid, uint8_t *value, uint16_t length)
+{
+ switch (transport) {
+ case CSR_TRANSPORT_HCI:
+ return csr_read_hci(varid, value, length);
+ case CSR_TRANSPORT_USB:
+ return csr_read_usb(varid, value, length);
+ default:
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+}
+
+static inline int transport_write(int transport, uint16_t varid, uint8_t *value, uint16_t length)
+{
+ switch (transport) {
+ case CSR_TRANSPORT_HCI:
+ return csr_write_hci(varid, value, length);
+ case CSR_TRANSPORT_USB:
+ return csr_write_usb(varid, value, length);
+ default:
+ errno = EOPNOTSUPP;
+ return -1;
+ }
+}
static struct {
uint16_t pskey;
@@ -89,20 +138,6 @@ static struct {
{ 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) {
@@ -167,9 +202,9 @@ static int opt_help(int argc, char *argv[], int *help)
argc -= optind; argv += optind; optind = 0; \
OPT_RANGE((range))
-static int cmd_builddef(int dd, int argc, char *argv[])
+static int cmd_builddef(int transport, int argc, char *argv[])
{
- uint8_t buf[8];
+ uint8_t array[8];
uint16_t def = 0x0000, nextdef = 0x0000;
int err = 0;
@@ -178,18 +213,17 @@ static int cmd_builddef(int dd, int argc, char *argv[])
printf("Build definitions:\n");
while (1) {
- memset(buf, 0, sizeof(buf));
- buf[0] = def & 0xff;
- buf[1] = def >> 8;
+ memset(array, 0, sizeof(array));
+ array[0] = def & 0xff;
+ array[1] = def >> 8;
- err = csr_read_varid_complex(dd, seqnum++,
- CSR_VARID_GET_NEXT_BUILDDEF, buf, sizeof(buf));
+ err = transport_read(transport, CSR_VARID_GET_NEXT_BUILDDEF, array, 8);
if (err < 0) {
errno = -err;
break;
}
- nextdef = buf[2] | (buf[3] << 8);
+ nextdef = array[2] | (array[3] << 8);
if (nextdef == 0x0000)
break;
@@ -202,9 +236,9 @@ static int cmd_builddef(int dd, int argc, char *argv[])
return err;
}
-static int cmd_keylen(int dd, int argc, char *argv[])
+static int cmd_keylen(int transport, int argc, char *argv[])
{
- uint8_t buf[8];
+ uint8_t array[8];
uint16_t handle, keylen;
int err;
@@ -212,120 +246,139 @@ static int cmd_keylen(int dd, int argc, char *argv[])
handle = atoi(argv[0]);
- memset(buf, 0, sizeof(buf));
- buf[0] = handle & 0xff;
- buf[1] = handle >> 8;
+ memset(array, 0, sizeof(array));
+ array[0] = handle & 0xff;
+ array[1] = handle >> 8;
- err = csr_read_varid_complex(dd, seqnum++,
- CSR_VARID_CRYPT_KEY_LENGTH, buf, sizeof(buf));
+ err = transport_read(transport, CSR_VARID_CRYPT_KEY_LENGTH, array, 8);
if (err < 0) {
errno = -err;
return -1;
}
- handle = buf[0] | (buf[1] << 8);
- keylen = buf[2] | (buf[3] << 8);
+ handle = array[0] | (array[1] << 8);
+ keylen = array[2] | (array[3] << 8);
printf("Crypt key length: %d bit\n", keylen * 8);
return 0;
}
-static int cmd_clock(int dd, int argc, char *argv[])
+static int cmd_clock(int transport, int argc, char *argv[])
{
- uint32_t clock = 0;
+ uint8_t array[8];
+ uint32_t clock;
int err;
OPT_HELP(0, NULL);
- err = csr_read_varid_uint32(dd, seqnum++, CSR_VARID_BT_CLOCK, &clock);
+ memset(array, 0, sizeof(array));
+
+ err = transport_read(transport, CSR_VARID_BT_CLOCK, array, 8);
if (err < 0) {
errno = -err;
return -1;
}
+ clock = array[2] | (array[3] << 8) | (array[0] << 16) | (array[1] << 24);
+
printf("Bluetooth clock: 0x%04x (%d)\n", clock, clock);
return 0;
}
-static int cmd_rand(int dd, int argc, char *argv[])
+static int cmd_rand(int transport, int argc, char *argv[])
{
- uint16_t rand = 0;
+ uint8_t array[8];
+ uint16_t rand;
int err;
OPT_HELP(0, NULL);
- err = csr_read_varid_uint16(dd, seqnum++, CSR_VARID_RAND, &rand);
+ memset(array, 0, sizeof(array));
+
+ err = transport_read(transport, CSR_VARID_RAND, array, 8);
if (err < 0) {
errno = -err;
return -1;
}
+ rand = array[0] | (array[1] << 8);
+
printf("Random number: 0x%02x (%d)\n", rand, rand);
return 0;
}
-static int cmd_panicarg(int dd, int argc, char *argv[])
+static int cmd_panicarg(int transport, int argc, char *argv[])
{
- uint16_t error = 0;
+ uint8_t array[8];
+ uint16_t error;
int err;
OPT_HELP(0, NULL);
- err = csr_read_varid_uint16(dd, seqnum++, CSR_VARID_PANIC_ARG, &error);
+ memset(array, 0, sizeof(array));
+
+ err = transport_read(transport, CSR_VARID_PANIC_ARG, array, 8);
if (err < 0) {
errno = -err;
return -1;
}
+ error = array[0] | (array[1] << 8);
+
printf("Panic code: 0x%02x (%s)\n", error,
error < 0x100 ? "valid" : "invalid");
return 0;
}
-static int cmd_faultarg(int dd, int argc, char *argv[])
+static int cmd_faultarg(int transport, int argc, char *argv[])
{
- uint16_t error = 0;
+ uint8_t array[8];
+ uint16_t error;
int err;
OPT_HELP(0, NULL);
- err = csr_read_varid_uint16(dd, seqnum++, CSR_VARID_FAULT_ARG, &error);
+ memset(array, 0, sizeof(array));
+
+ err = transport_read(transport, CSR_VARID_FAULT_ARG, array, 8);
if (err < 0) {
errno = -err;
return -1;
}
+ error = array[0] | (array[1] << 8);
+
printf("Fault code: 0x%02x (%s)\n", error,
error < 0x100 ? "valid" : "invalid");
return 0;
}
-static int cmd_coldreset(int dd, int argc, char *argv[])
+static int cmd_coldreset(int transport, int argc, char *argv[])
{
- return csr_write_varid_valueless(dd, seqnum++, CSR_VARID_COLD_RESET);
+ return transport_write(transport, CSR_VARID_COLD_RESET, NULL, 0);
}
-static int cmd_warmreset(int dd, int argc, char *argv[])
+static int cmd_warmreset(int transport, int argc, char *argv[])
{
- return csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+ return transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
}
-static int cmd_disabletx(int dd, int argc, char *argv[])
+static int cmd_disabletx(int transport, int argc, char *argv[])
{
- return csr_write_varid_valueless(dd, seqnum++, CSR_VARID_DISABLE_TX);
+ return transport_write(transport, CSR_VARID_DISABLE_TX, NULL, 0);
}
-static int cmd_enabletx(int dd, int argc, char *argv[])
+static int cmd_enabletx(int transport, int argc, char *argv[])
{
- return csr_write_varid_valueless(dd, seqnum++, CSR_VARID_ENABLE_TX);
+ return transport_write(transport, CSR_VARID_ENABLE_TX, NULL, 0);
}
-static int cmd_memtypes(int dd, int argc, char *argv[])
+static int cmd_memtypes(int transport, int argc, char *argv[])
{
uint8_t array[8];
uint16_t type, stores[4] = { 0x0001, 0x0002, 0x0004, 0x0008 };
@@ -338,8 +391,7 @@ static int cmd_memtypes(int dd, int argc, char *argv[])
array[0] = stores[i] & 0xff;
array[1] = stores[i] >> 8;
- err = csr_read_varid_complex(dd, seqnum++,
- CSR_VARID_PS_MEMORY_TYPE, array, sizeof(array));
+ err = transport_read(transport, CSR_VARID_PS_MEMORY_TYPE, array, 8);
if (err < 0)
continue;
@@ -412,12 +464,12 @@ static int opt_pskey(int argc, char *argv[], uint16_t *stores, int *reset, int *
argc -= optind; argv += optind; optind = 0; \
OPT_RANGE((range))
-static int cmd_psget(int dd, int argc, char *argv[])
+static int cmd_psget(int transport, int argc, char *argv[])
{
- uint8_t array[64];
+ uint8_t array[128];
uint16_t pskey, length, value, stores = CSR_STORES_DEFAULT;
uint32_t val32;
- int i, err, size, reset = 0, type = CSR_TYPE_NULL;
+ int i, err, reset = 0;
memset(array, 0, sizeof(array));
@@ -425,87 +477,74 @@ static int cmd_psget(int dd, int argc, char *argv[])
if (strncasecmp(argv[0], "0x", 2)) {
pskey = atoi(argv[0]);
- type = CSR_TYPE_COMPLEX;
- size = sizeof(array);
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;
}
- } else {
+ } 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;
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = stores & 0xff;
+ array[3] = stores >> 8;
- err = csr_read_pskey_complex(dd, seqnum++, pskey, stores,
- array, length * 2);
- if (err < 0)
- return err;
+ err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
+ 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;
+ length = array[2] + (array[3] << 8);
+ if (length + 6 > sizeof(array) / 2)
+ return -EIO;
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = length & 0xff;
+ array[3] = length >> 8;
+ array[4] = stores & 0xff;
+ array[5] = stores >> 8;
+
+ err = transport_read(transport, CSR_VARID_PS, array, (length + 3) * 2);
+ if (err < 0)
+ return err;
+
+ switch (length) {
+ case 1:
+ value = array[6] | (array[7] << 8);
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;
-
+ case 2:
+ val32 = array[8] | (array[9] << 8) | (array[6] << 16) | (array[7] << 24);
printf("%s: 0x%08x (%d)\n", csr_pskeytostr(pskey), val32, val32);
break;
default:
- errno = EFAULT;
- err = -1;
+ printf("%s:", csr_pskeytostr(pskey));
+ for (i = 0; i < length; i++)
+ printf(" 0x%02x%02x", array[(i * 2) + 6], array[(i * 2) + 7]);
+ printf("\n");
break;
}
- if (!err && reset)
- csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+ if (reset)
+ transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
return err;
}
-static int cmd_psset(int dd, int argc, char *argv[])
+static int cmd_psset(int transport, int argc, char *argv[])
{
- uint8_t array[64];
- uint16_t pskey, value, stores = CSR_STORES_PSRAM;
+ uint8_t array[128];
+ uint16_t pskey, length, value, stores = CSR_STORES_PSRAM;
uint32_t val32;
- int i, err, size, reset = 0, type = CSR_TYPE_NULL;
+ int i, err, reset = 0;
memset(array, 0, sizeof(array));
@@ -513,48 +552,44 @@ static int cmd_psset(int dd, int argc, char *argv[])
if (strncasecmp(argv[0], "0x", 2)) {
pskey = atoi(argv[0]);
- type = CSR_TYPE_COMPLEX;
- size = sizeof(array);
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;
}
- } else {
+ } else
pskey = strtol(argv[0] + 2, NULL, 16);
- type = CSR_TYPE_COMPLEX;
- size = sizeof(array);
- }
- argc--;
- argv++;
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = stores & 0xff;
+ array[3] = stores >> 8;
- switch (type) {
- case CSR_TYPE_COMPLEX:
- size = pskey_size(pskey);
+ err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
+ if (err < 0)
+ return err;
- if (argc != size) {
- errno = EINVAL;
- return -1;
- }
+ length = array[2] + (array[3] << 8);
+ if (length + 6 > sizeof(array) / 2)
+ return -EIO;
- 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]);
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = length & 0xff;
+ array[3] = length >> 8;
+ array[4] = stores & 0xff;
+ array[5] = stores >> 8;
- err = csr_write_pskey_complex(dd, seqnum++, pskey,
- stores, array, size);
- break;
+ argc--;
+ argv++;
- case CSR_TYPE_UINT8:
- case CSR_TYPE_UINT16:
+ switch (length) {
+ case 1:
if (argc != 1) {
errno = E2BIG;
return -1;
@@ -565,10 +600,11 @@ static int cmd_psset(int dd, int argc, char *argv[])
else
value = atoi(argv[0]);
- err = csr_write_pskey_uint16(dd, seqnum++, pskey, stores, value);
+ array[6] = value & 0xff;
+ array[7] = value >> 8;
break;
- case CSR_TYPE_UINT32:
+ case 2:
if (argc != 1) {
errno = E2BIG;
return -1;
@@ -579,22 +615,37 @@ static int cmd_psset(int dd, int argc, char *argv[])
else
val32 = atoi(argv[0]);
- err = csr_write_pskey_uint32(dd, seqnum++, pskey, stores, val32);
+ array[6] = (val32 & 0xff0000) >> 16;
+ array[7] = val32 >> 24;
+ array[8] = val32 & 0xff;
+ array[9] = (val32 & 0xff00) >> 8;
break;
default:
- errno = EFAULT;
- err = -1;
+ if (argc != length * 2) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ for (i = 0; i < length * 2; i++)
+ if (!strncasecmp(argv[0], "0x", 2))
+ array[i + 6] = strtol(argv[i] + 2, NULL, 16);
+ else
+ array[i + 6] = atoi(argv[i]);
break;
}
- if (!err && reset)
- csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+ err = transport_write(transport, CSR_VARID_PS, array, (length + 3) * 2);
+ if (err < 0)
+ return err;
+
+ if (reset)
+ transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
return err;
}
-static int cmd_psclr(int dd, int argc, char *argv[])
+static int cmd_psclr(int transport, int argc, char *argv[])
{
uint8_t array[8];
uint16_t pskey, stores = CSR_STORES_PSRAM;
@@ -621,16 +672,17 @@ static int cmd_psclr(int dd, int argc, char *argv[])
array[2] = stores & 0xff;
array[3] = stores >> 8;
- err = csr_write_varid_complex(dd, seqnum++,
- CSR_VARID_PS_CLR_STORES, array, sizeof(array));
+ err = transport_write(transport, CSR_VARID_PS_CLR_STORES, array, 8);
+ if (err < 0)
+ return err;
- if (!err && reset)
- csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+ if (reset)
+ transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
return err;
}
-static int cmd_pslist(int dd, int argc, char *argv[])
+static int cmd_pslist(int transport, int argc, char *argv[])
{
uint8_t array[8];
uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT;
@@ -645,8 +697,7 @@ static int cmd_pslist(int dd, int argc, char *argv[])
array[2] = stores & 0xff;
array[3] = stores >> 8;
- err = csr_read_varid_complex(dd, seqnum++,
- CSR_VARID_PS_NEXT, array, sizeof(array));
+ err = transport_read(transport, CSR_VARID_PS_NEXT, array, 8);
if (err < 0)
break;
@@ -660,8 +711,7 @@ static int cmd_pslist(int dd, int argc, char *argv[])
array[2] = stores & 0xff;
array[3] = stores >> 8;
- err = csr_read_varid_complex(dd, seqnum++,
- CSR_VARID_PS_SIZE, array, sizeof(array));
+ err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
if (err < 0)
continue;
@@ -672,12 +722,12 @@ static int cmd_pslist(int dd, int argc, char *argv[])
}
if (reset)
- csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+ transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
return 0;
}
-static int cmd_psread(int dd, int argc, char *argv[])
+static int cmd_psread(int transport, int argc, char *argv[])
{
uint8_t array[256];
uint16_t pskey = 0x0000, length, stores = CSR_STORES_DEFAULT;
@@ -693,8 +743,7 @@ static int cmd_psread(int dd, int argc, char *argv[])
array[2] = stores & 0xff;
array[3] = stores >> 8;
- err = csr_read_varid_complex(dd, seqnum++,
- CSR_VARID_PS_NEXT, array, 8);
+ err = transport_read(transport, CSR_VARID_PS_NEXT, array, 8);
if (err < 0)
break;
@@ -708,17 +757,23 @@ static int cmd_psread(int dd, int argc, char *argv[])
array[2] = stores & 0xff;
array[3] = stores >> 8;
- err = csr_read_varid_complex(dd, seqnum++,
- CSR_VARID_PS_SIZE, array, 8);
+ err = transport_read(transport, CSR_VARID_PS_SIZE, array, 8);
if (err < 0)
continue;
length = array[2] + (array[3] << 8);
- if (length > sizeof(array) / 2)
+ if (length + 6 > sizeof(array) / 2)
continue;
- err = csr_read_pskey_complex(dd, seqnum++, pskey,
- stores, array, length * 2);
+ memset(array, 0, sizeof(array));
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = length & 0xff;
+ array[3] = length >> 8;
+ array[4] = stores & 0xff;
+ array[5] = stores >> 8;
+
+ err = transport_read(transport, CSR_VARID_PS, array, (length + 3) * 2);
if (err < 0)
continue;
@@ -731,20 +786,20 @@ static int cmd_psread(int dd, int argc, char *argv[])
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(" %02x%02x", array[(i * 2) + 7], array[(i * 2) + 6]);
printf("\n");
}
if (reset)
- csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+ transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
return 0;
}
-static int cmd_psload(int dd, int argc, char *argv[])
+static int cmd_psload(int transport, int argc, char *argv[])
{
uint8_t array[256];
- uint16_t pskey, size, stores = CSR_STORES_PSRAM;
+ uint16_t pskey, length, size, stores = CSR_STORES_PSRAM;
char *str, val[7];
int err, reset = 0;
@@ -752,7 +807,10 @@ static int cmd_psload(int dd, int argc, char *argv[])
psr_read(argv[0]);
- while (psr_get(&pskey, array, &size) == 0) {
+ memset(array, 0, sizeof(array));
+ size = sizeof(array) - 6;
+
+ while (psr_get(&pskey, array + 6, &size) == 0) {
str = csr_pskeytoval(pskey);
if (!strcasecmp(str, "UNKNOWN")) {
sprintf(val, "0x%04x", pskey);
@@ -763,19 +821,30 @@ static int cmd_psload(int dd, int argc, char *argv[])
str ? str : val);
fflush(stdout);
- err = csr_write_pskey_complex(dd, seqnum++, pskey,
- stores, array, size);
+ length = size / 2;
+
+ array[0] = pskey & 0xff;
+ array[1] = pskey >> 8;
+ array[2] = length & 0xff;
+ array[3] = length >> 8;
+ array[4] = stores & 0xff;
+ array[5] = stores >> 8;
+
+ err = transport_write(transport, CSR_VARID_PS, array, size + 6);
printf("%s\n", err < 0 ? "failed" : "done");
+
+ memset(array, 0, sizeof(array));
+ size = sizeof(array) - 6;
}
if (reset)
- csr_write_varid_valueless(dd, seqnum++, CSR_VARID_WARM_RESET);
+ transport_write(transport, CSR_VARID_WARM_RESET, NULL, 0);
return 0;
}
-static int cmd_pscheck(int dd, int argc, char *argv[])
+static int cmd_pscheck(int transport, int argc, char *argv[])
{
uint8_t array[256];
uint16_t pskey, size;
@@ -797,7 +866,7 @@ static int cmd_pscheck(int dd, int argc, char *argv[])
static struct {
char *str;
- int (*func)(int dd, int argc, char *argv[]);
+ int (*func)(int transport, int argc, char *argv[]);
char *arg;
char *doc;
} commands[] = {
@@ -864,10 +933,8 @@ static struct option main_options[] = {
int main(int argc, char *argv[])
{
- struct hci_dev_info di;
- struct hci_version ver;
char *device = NULL;
- int i, err, opt, dd, dev, transport = CSR_TRANSPORT_HCI;
+ int i, err, opt, transport = CSR_TRANSPORT_HCI;
while ((opt=getopt_long(argc, argv, "+t:d:i:h", main_options, NULL)) != EOF) {
switch (opt) {
@@ -911,55 +978,19 @@ int main(int argc, char *argv[])
exit(1);
}
- if (transport != CSR_TRANSPORT_HCI) {
- fprintf(stderr, "Unsupported transport\n");
+ if (transport_open(transport, device) < 0)
exit(1);
- }
- if (device) {
- dev = hci_devid(device);
- if (dev < 0) {
- fprintf(stderr, "Device not available\n");
- exit(1);
- }
+ if (device)
free(device);
- } else
- dev = 0;
-
- dd = hci_open_dev(dev);
- if (dd < 0) {
- fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
- dev, strerror(errno), errno);
- exit(1);
- }
-
- if (hci_devinfo(dev, &di) < 0) {
- fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n",
- dev, strerror(errno), errno);
- hci_close_dev(dd);
- exit(1);
- }
-
- if (hci_read_local_version(dd, &ver, 1000) < 0) {
- fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n",
- dev, strerror(errno), errno);
- hci_close_dev(dd);
- exit(1);
- }
-
- if (ver.manufacturer != 10) {
- fprintf(stderr, "Unsupported manufacturer\n");
- hci_close_dev(dd);
- exit(1);
- }
for (i = 0; commands[i].str; i++) {
if (strcasecmp(commands[i].str, argv[0]))
continue;
- err = commands[i].func(dd, argc, argv);
+ err = commands[i].func(transport, argc, argv);
- hci_close_dev(dd);
+ transport_close(transport);
if (err < 0) {
fprintf(stderr, "Can't execute command: %s (%d)\n",
@@ -972,7 +1003,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Unsupported command\n");
- hci_close_dev(dd);
+ transport_close(transport);
exit(1);
}
diff --git a/tools/csr.c b/tools/csr.c
index c101422b..10856749 100644
--- a/tools/csr.c
+++ b/tools/csr.c
@@ -2354,7 +2354,7 @@ int csr_write_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *va
rq.ocf = 0x00;
rq.event = EVT_VENDOR;
rq.cparam = cp;
- rq.clen = sizeof(cmd) + 1;
+ rq.clen = sizeof(cmd) + length + 1;
rq.rparam = rp;
rq.rlen = sizeof(rp);
@@ -2393,7 +2393,7 @@ int csr_read_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *val
rq.ocf = 0x00;
rq.event = EVT_VENDOR;
rq.cparam = cp;
- rq.clen = sizeof(cmd) + 1;
+ rq.clen = sizeof(cmd) + length + 1;
rq.rparam = rp;
rq.rlen = sizeof(rp);
diff --git a/tools/csr.h b/tools/csr.h
index cd807c38..ec066b81 100644
--- a/tools/csr.h
+++ b/tools/csr.h
@@ -63,7 +63,7 @@
#define CSR_VARID_FAULT_ARG 0x6806 /* uint16 */
#define CSR_VARID_MAX_TX_POWER 0x6827 /* int8 */
#define CSR_VARID_DEFAULT_TX_POWER 0x682b /* int8 */
-#define CSR_VARID_PS 0x7002 /* complex */
+#define CSR_VARID_PS 0x7003 /* complex */
#define CSR_PSKEY_BDADDR 0x0001 /* bdaddr / uint16[] = { 0x00A5A5, 0x5b, 0x0002 } */
#define CSR_PSKEY_COUNTRYCODE 0x0002 /* uint16 */
@@ -502,6 +502,16 @@ char *csr_chipvertostr(uint16_t ver, uint16_t rev);
char *csr_pskeytostr(uint16_t pskey);
char *csr_pskeytoval(uint16_t pskey);
+int csr_open_hci(char *device);
+int csr_read_hci(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_hci(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_hci(void);
+
+int csr_open_usb(char *device);
+int csr_read_usb(uint16_t varid, uint8_t *value, uint16_t length);
+int csr_write_usb(uint16_t varid, uint8_t *value, uint16_t length);
+void csr_close_usb(void);
+
int csr_write_varid_valueless(int dd, uint16_t seqnum, uint16_t varid);
int csr_write_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length);
int csr_read_varid_complex(int dd, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length);
diff --git a/tools/csr_hci.c b/tools/csr_hci.c
new file mode 100644
index 00000000..ebeb8aa7
--- /dev/null
+++ b/tools/csr_hci.c
@@ -0,0 +1,160 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2004-2005 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 <string.h>
+#include <sys/socket.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+
+#include "csr.h"
+
+static uint16_t seqnum = 0x0000;
+
+static int dd = -1;
+
+int csr_open_hci(char *device)
+{
+ struct hci_dev_info di;
+ struct hci_version ver;
+ int dev = 0;
+
+ if (device) {
+ dev = hci_devid(device);
+ if (dev < 0) {
+ fprintf(stderr, "Device not available\n");
+ return -1;
+ }
+ }
+
+ dd = hci_open_dev(dev);
+ if (dd < 0) {
+ fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
+ dev, strerror(errno), errno);
+ return -1;
+ }
+
+ if (hci_devinfo(dev, &di) < 0) {
+ fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n",
+ dev, strerror(errno), errno);
+ hci_close_dev(dd);
+ return -1;
+ }
+
+ if (hci_read_local_version(dd, &ver, 1000) < 0) {
+ fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n",
+ dev, strerror(errno), errno);
+ hci_close_dev(dd);
+ return -1;
+ }
+
+ if (ver.manufacturer != 10) {
+ fprintf(stderr, "Unsupported manufacturer\n");
+ hci_close_dev(dd);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int do_command(uint16_t command, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length)
+{
+ unsigned char cp[254], rp[254];
+ struct hci_request rq;
+ uint8_t cmd[10];
+ uint16_t size;
+
+ size = (length < 8) ? 9 : ((length + 1) / 2) + 5;
+
+ cmd[0] = command & 0xff;
+ cmd[1] = command >> 8;
+ cmd[2] = size & 0xff;
+ cmd[3] = size >> 8;
+ cmd[4] = seqnum & 0xff;
+ cmd[5] = seqnum >> 8;
+ cmd[6] = varid & 0xff;
+ cmd[7] = varid >> 8;
+ cmd[8] = 0x00;
+ cmd[9] = 0x00;
+
+ memset(cp, 0, sizeof(cp));
+ cp[0] = 0xc2;
+ memcpy(cp + 1, cmd, sizeof(cmd));
+ memcpy(cp + 11, value, length);
+
+ switch (varid) {
+ case CSR_VARID_COLD_RESET:
+ case CSR_VARID_WARM_RESET:
+ case CSR_VARID_COLD_HALT:
+ case CSR_VARID_WARM_HALT:
+ return hci_send_cmd(dd, OGF_VENDOR_CMD, 0x00, (size * 2) + 1, cp);
+ }
+
+ memset(&rq, 0, sizeof(rq));
+ rq.ogf = OGF_VENDOR_CMD;
+ rq.ocf = 0x00;
+ rq.event = EVT_VENDOR;
+ rq.cparam = cp;
+ rq.clen = (size * 2) + 1;
+ rq.rparam = rp;
+ rq.rlen = sizeof(rp);
+
+ if (hci_send_req(dd, &rq, 2000) < 0)
+ return -1;
+
+ if (rp[0] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[9] + (rp[10] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ memcpy(value, rp + 11, length);
+
+ return 0;
+}
+
+int csr_read_hci(uint16_t varid, uint8_t *value, uint16_t length)
+{
+ return do_command(0x0000, seqnum++, varid, value, length);
+}
+
+int csr_write_hci(uint16_t varid, uint8_t *value, uint16_t length)
+{
+ return do_command(0x0002, seqnum++, varid, value, length);
+}
+
+void csr_close_hci(void)
+{
+ hci_close_dev(dd);
+}
diff --git a/tools/csr_usb.c b/tools/csr_usb.c
new file mode 100644
index 00000000..2c29251f
--- /dev/null
+++ b/tools/csr_usb.c
@@ -0,0 +1,173 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2004-2005 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 <string.h>
+
+#include <usb.h>
+
+#include "csr.h"
+
+#ifdef NEED_USB_GET_BUSSES
+static inline struct usb_bus *usb_get_busses(void)
+{
+ return usb_busses;
+}
+#endif
+
+#ifndef USB_DIR_OUT
+#define USB_DIR_OUT 0x00
+#endif
+
+static uint16_t seqnum = 0x0000;
+
+static struct usb_dev_handle *udev = NULL;
+
+int csr_open_usb(char *device)
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+
+ usb_init();
+
+ usb_find_busses();
+ usb_find_devices();
+
+ for (bus = usb_get_busses(); bus; bus = bus->next) {
+ for (dev = bus->devices; dev; dev = dev->next) {
+ if (dev->descriptor.bDeviceClass == USB_CLASS_HUB)
+ continue;
+
+ if (dev->descriptor.idVendor != 0x0a12 ||
+ dev->descriptor.idProduct != 0x0001)
+ continue;
+
+ goto found;
+ }
+ }
+
+ fprintf(stderr, "Device not available\n");
+
+ return -1;
+
+found:
+ udev = usb_open(dev);
+ if (!udev) {
+ fprintf(stderr, "Can't open device: %s (%d)\n",
+ strerror(errno), errno);
+ return -1;
+ }
+
+ if (usb_claim_interface(udev, 0) < 0) {
+ fprintf(stderr, "Can't claim interface: %s (%d)\n",
+ strerror(errno), errno);
+ usb_close(udev);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int do_command(uint16_t command, uint16_t seqnum, uint16_t varid, uint8_t *value, uint16_t length)
+{
+ unsigned char cp[254], rp[254];
+ uint8_t cmd[10];
+ uint16_t size;
+ int len, offset = 0;
+
+ size = (length < 8) ? 9 : ((length + 1) / 2) + 5;
+
+ cmd[0] = command & 0xff;
+ cmd[1] = command >> 8;
+ cmd[2] = size & 0xff;
+ cmd[3] = size >> 8;
+ cmd[4] = seqnum & 0xff;
+ cmd[5] = seqnum >> 8;
+ cmd[6] = varid & 0xff;
+ cmd[7] = varid >> 8;
+ cmd[8] = 0x00;
+ cmd[9] = 0x00;
+
+ memset(cp, 0, sizeof(cp));
+ cp[0] = 0x00;
+ cp[1] = 0xfc;
+ cp[2] = (size * 2) + 1;
+ cp[3] = 0xc2;
+ memcpy(cp + 4, cmd, sizeof(cmd));
+ memcpy(cp + 14, value, length);
+
+ usb_interrupt_read(udev, 0x81, (void *) rp, sizeof(rp), 2);
+
+ if (usb_control_msg(udev, USB_TYPE_CLASS | USB_DIR_OUT | USB_RECIP_DEVICE,
+ 0, 0, 0, (void *) cp, (size * 2) + 4, 1000) < 0)
+ return -1;
+
+ switch (varid) {
+ case CSR_VARID_COLD_RESET:
+ case CSR_VARID_WARM_RESET:
+ case CSR_VARID_COLD_HALT:
+ case CSR_VARID_WARM_HALT:
+ return 0;
+ }
+
+ do {
+ len = usb_interrupt_read(udev, 0x81,
+ (void *) (rp + offset), sizeof(rp), 10);
+ offset += len;
+ } while (len > 0);
+
+ if (rp[0] != 0xff || rp[2] != 0xc2) {
+ errno = EIO;
+ return -1;
+ }
+
+ if ((rp[11] + (rp[12] << 8)) != 0) {
+ errno = ENXIO;
+ return -1;
+ }
+
+ memcpy(value, rp + 13, length);
+
+ return 0;
+}
+
+int csr_read_usb(uint16_t varid, uint8_t *value, uint16_t length)
+{
+ return do_command(0x0000, seqnum++, varid, value, length);
+}
+
+int csr_write_usb(uint16_t varid, uint8_t *value, uint16_t length)
+{
+ return do_command(0x0002, seqnum++, varid, value, length);
+}
+
+void csr_close_usb(void)
+{
+ usb_release_interface(udev, 0);
+ usb_close(udev);
+}