diff options
| author | Marcel Holtmann <marcel@holtmann.org> | 2005-11-10 20:23:47 +0000 | 
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2005-11-10 20:23:47 +0000 | 
| commit | 2ba0839002159cd293bb1a3d85645f04010cf33b (patch) | |
| tree | f03e03afa2dc6ea774315bb116b177016623fdba | |
| parent | 9fb18057b298238f576aa57a95fed56e1743a3e9 (diff) | |
Add USB transport to the bccmd utility
| -rw-r--r-- | acinclude.m4 | 2 | ||||
| -rw-r--r-- | tools/Makefile.am | 4 | ||||
| -rw-r--r-- | tools/bccmd.c | 465 | ||||
| -rw-r--r-- | tools/csr.c | 4 | ||||
| -rw-r--r-- | tools/csr.h | 12 | ||||
| -rw-r--r-- | tools/csr_hci.c | 160 | ||||
| -rw-r--r-- | tools/csr_usb.c | 173 | 
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); +} | 
