diff options
| -rw-r--r-- | tools/Makefile.am | 2 | ||||
| -rw-r--r-- | tools/csr.c | 347 | ||||
| -rw-r--r-- | tools/csr.h | 35 | ||||
| -rw-r--r-- | tools/hciconfig.c | 126 | 
4 files changed, 442 insertions, 68 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am index 0513c83b..180c0cc1 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -7,6 +7,8 @@ mandir = $(prefix)/usr/share/man  sbin_PROGRAMS = hciattach hciconfig  bin_PROGRAMS  = hcitool l2ping +hciconfig_SOURCES = hciconfig.c csr.h csr.c +  man_MANS      = hciattach.8 hciconfig.8 hcitool.1 l2ping.1  noinst_PROGRAMS	= ppporc diff --git a/tools/csr.c b/tools/csr.c new file mode 100644 index 00000000..e2069cd7 --- /dev/null +++ b/tools/csr.c @@ -0,0 +1,347 @@ +/* + * + *  CSR BlueCore specific functions + * + *  Copyright (C) 2003  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#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 struct { +	uint16_t id; +	char *str; +} csr_map[] = { +	{  111,	"HCI 11.0"	}, +	{  112,	"HCI 11.1"	}, +	{  114,	"HCI 11.2"	}, +	{  115,	"HCI 11.3"	}, +	{  117,	"HCI 12.0"	}, +	{  119,	"HCI 12.1"	}, +	{  133,	"HCI 12.2"	}, +	{  134,	"HCI 12.3"	}, +	{  162,	"HCI 12.4"	}, +	{  165,	"HCI 12.5"	}, +	{  169,	"HCI 12.6"	}, +	{  188,	"HCI 12.7"	}, +	{  218,	"HCI 12.8"	}, +	{  283,	"HCI 12.9"	}, +	{  203,	"HCI 13.2"	}, +	{  204,	"HCI 13.2"	}, +	{  210,	"HCI 13.3"	}, +	{  211,	"HCI 13.3"	}, +	{  213,	"HCI 13.4"	}, +	{  214,	"HCI 13.4"	}, +	{  225,	"HCI 13.5"	}, +	{  226,	"HCI 13.5"	}, +	{  237,	"HCI 13.6"	}, +	{  238,	"HCI 13.6"	}, +	{  242,	"HCI 14.0"	}, +	{  243,	"HCI 14.0"	}, +	{  244,	"HCI 14.0"	}, +	{  245,	"HCI 14.0"	}, +	{  254,	"HCI 13.7"	}, +	{  255,	"HCI 13.7"	}, +	{  264,	"HCI 14.1"	}, +	{  265,	"HCI 14.1"	}, +	{  267,	"HCI 14.2"	}, +	{  268,	"HCI 14.2"	}, +	{  272,	"HCI 14.3"	}, +	{  273,	"HCI 14.3"	}, +	{  274,	"HCI 13.8"	}, +	{  275,	"HCI 13.8"	}, +	{  286,	"HCI 13.9"	}, +	{  287,	"HCI 13.9"	}, +	{  309,	"HCI 13.10"	}, +	{  310,	"HCI 13.10"	}, +	{  313,	"HCI 14.4"	}, +	{  314,	"HCI 14.4"	}, +	{  323,	"HCI 14.5"	}, +	{  324,	"HCI 14.5"	}, +	{  336,	"HCI 14.6"	}, +	{  337,	"HCI 14.6"	}, +	{  351,	"HCI 13.11"	}, +	{  352,	"HCI 13.11"	}, +	{  362,	"HCI 15.0"	}, +	{  363,	"HCI 15.0"	}, +	{  364,	"HCI 15.0"	}, +	{  365,	"HCI 15.0"	}, +	{  373,	"HCI 14.7"	}, +	{  374,	"HCI 14.7"	}, +	{  379,	"HCI 15.1"	}, +	{  380,	"HCI 15.1"	}, +	{  381,	"HCI 15.1"	}, +	{  382,	"HCI 15.1"	}, +	{  392,	"HCI 15.2"	}, +	{  393,	"HCI 15.2"	}, +	{  394,	"HCI 15.2"	}, +	{  395,	"HCI 15.2"	}, +	{  436,	"HCI 16.0"	}, +	{  437,	"HCI 16.0"	}, +	{  438,	"HCI 16.0"	}, +	{  439,	"HCI 16.0"	}, +	{  443,	"HCI 15.3"	}, +	{  444,	"HCI 15.3"	}, +	{  465,	"HCI 16.1"	}, +	{  466,	"HCI 16.1"	}, +	{  467,	"HCI 16.1"	}, +	{  468,	"HCI 16.1"	}, +	{  487,	"HCI 14.8"	}, +	{  488,	"HCI 14.8"	}, +	{  492,	"HCI 16.2"	}, +	{  493,	"HCI 16.2"	}, +	{  495,	"HCI 16.2"	}, +	{  496,	"HCI 16.2"	}, +	{  502,	"HCI 16.1.1"	}, +	{  503,	"HCI 16.1.1"	}, +	{  504,	"HCI 16.1.1"	}, +	{  505,	"HCI 16.1.1"	}, +	{  506,	"HCI 16.1.2"	}, +	{  507,	"HCI 16.1.2"	}, +	{  508,	"HCI 16.1.2"	}, +	{  509,	"HCI 16.1.2"	}, +	{  516,	"HCI 16.3"	}, +	{  517,	"HCI 16.3"	}, +	{  518,	"HCI 16.3"	}, +	{  519,	"HCI 16.3"	}, +	{  523,	"HCI 16.4"	}, +	{  524,	"HCI 16.4"	}, +	{  525,	"HCI 16.4"	}, +	{  526,	"HCI 16.4"	}, +	{  553,	"HCI 15.3"	}, +	{  554,	"HCI 15.3"	}, +	{  562,	"HCI 16.5"	}, +	{  563,	"HCI 16.5"	}, +	{  564,	"HCI 16.5"	}, +	{  565,	"HCI 16.5"	}, +	{  593,	"HCI 17.0"	}, +	{  594,	"HCI 17.0"	}, +	{  595,	"HCI 17.0"	}, +	{  599,	"HCI 17.0"	}, +	{  600,	"HCI 17.0"	}, +	{  608,	"HCI 13.10.1"	}, +	{  609,	"HCI 13.10.1"	}, +	{  613,	"HCI 17.1"	}, +	{  614,	"HCI 17.1"	}, +	{  615,	"HCI 17.1"	}, +	{  616,	"HCI 17.1"	}, +	{  618,	"HCI 17.1"	}, +	{  624,	"HCI 17.2"	}, +	{  625,	"HCI 17.2"	}, +	{  626,	"HCI 17.2"	}, +	{  627,	"HCI 17.2"	}, +	{  637,	"HCI 16.6"	}, +	{  638,	"HCI 16.6"	}, +	{  639,	"HCI 16.6"	}, +	{  640,	"HCI 16.6"	}, +	{  642,	"HCI 13.10.2"	}, +	{  643,	"HCI 13.10.2"	}, +	{  644,	"HCI 13.10.3"	}, +	{  645,	"HCI 13.10.3"	}, +	{  668,	"HCI 13.10.4"	}, +	{  669,	"HCI 13.10.4"	}, +	{  681,	"HCI 16.7"	}, +	{  682,	"HCI 16.7"	}, +	{  683,	"HCI 16.7"	}, +	{  684,	"HCI 16.7"	}, +	{  704,	"HCI 16.8"	}, +	{  718,	"HCI 16.4.1"	}, +	{  719,	"HCI 16.4.1"	}, +	{  720,	"HCI 16.4.1"	}, +	{  721,	"HCI 16.4.1"	}, +	{  722,	"HCI 16.7.1"	}, +	{  723,	"HCI 16.7.1"	}, +	{  724,	"HCI 16.7.1"	}, +	{  725,	"HCI 16.7.1"	}, +	{  731,	"HCI 16.7.2"	}, +	{  732,	"HCI 16.7.2"	}, +	{  733,	"HCI 16.7.2"	}, +	{  734,	"HCI 16.7.2"	}, +	{  735,	"HCI 16.4.2"	}, +	{  736,	"HCI 16.4.2"	}, +	{  737,	"HCI 16.4.2"	}, +	{  738,	"HCI 16.4.2"	}, +	{  750,	"HCI 16.7.3"	}, +	{  751,	"HCI 16.7.3"	}, +	{  752,	"HCI 16.7.3"	}, +	{  753,	"HCI 16.7.3"	}, +	{  760,	"HCI 16.7.4"	}, +	{  761,	"HCI 16.7.4"	}, +	{  762,	"HCI 16.7.4"	}, +	{  763,	"HCI 16.7.4"	}, +	{  770,	"HCI 16.9"	}, +	{  771,	"HCI 16.9"	}, +	{  772,	"HCI 16.9"	}, +	{  773,	"HCI 16.9"	}, +	{  774,	"HCI 17.3"	}, +	{  775,	"HCI 17.3"	}, +	{  776,	"HCI 17.3"	}, +	{  777,	"HCI 17.3"	}, +	{  781,	"HCI 16.7.5"	}, +	{  786,	"HCI 16.10"	}, +	{  787,	"HCI 16.10"	}, +	{  788,	"HCI 16.10"	}, +	{  789,	"HCI 16.10"	}, +	{  791,	"HCI 16.4.3"	}, +	{  792,	"HCI 16.4.3"	}, +	{  793,	"HCI 16.4.3"	}, +	{  794,	"HCI 16.4.3"	}, +	{  798,	"HCI 16.11"	}, +	{  799,	"HCI 16.11"	}, +	{  800,	"HCI 16.11"	}, +	{  801,	"HCI 16.11"	}, +	{  806,	"HCI 16.7.5"	}, +	{  807,	"HCI 16.12"	}, +	{  808,	"HCI 16.12"	}, +	{  809,	"HCI 16.12"	}, +	{  810,	"HCI 16.12"	}, +	{  817,	"HCI 16.13"	}, +	{  818,	"HCI 16.13"	}, +	{  819,	"HCI 16.13"	}, +	{  820,	"HCI 16.13"	}, +	{  823,	"HCI 13.10.5"	}, +	{  824,	"HCI 13.10.5"	}, +	{  826,	"HCI 16.14"	}, +	{  827,	"HCI 16.14"	}, +	{  828,	"HCI 16.14"	}, +	{  829,	"HCI 16.14"	}, +	{  843,	"HCI 17.3.1"	}, +	{  856,	"HCI 17.3.2"	}, +	{  857,	"HCI 17.3.2"	}, +	{  858,	"HCI 17.3.2"	}, +	{    0, } +}; + +char *csr_buildidtostr(uint16_t id) +{ +	static char str[12]; +	int i; + +	for (i = 0; csr_map[i].id; i++) +		if (csr_map[i].id == id) +			return csr_map[i].str; + +	snprintf(str, 11, "Build %d", id); +	return str; +} + +char *csr_chipvertostr(uint16_t ver, uint16_t rev) +{ +	switch (ver) { +	case 0x00: +		return "BlueCore01a"; +	case 0x01: +		if (rev == 0x64) +			return "BlueCore01b (ES)"; +		else +			return "BlueCore01b"; +	case 0x02: +		if (rev == 0x89) +			return "BlueCore02 (ES2)"; +		else +			return "BlueCore02"; +	default: +		return "Unknown"; +	} +} + +int csr_read_varid_uint16(int dd, uint16_t seqnum, uint16_t varid, uint16_t *value) +{ +	unsigned char cmd[] = { 0x00, 0x00, 0x09, 0x00, +				seqnum & 0xff, seqnum >> 8, varid & 0xff, varid >> 8, 0x00, 0x00, +				0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +	unsigned char cp[254], rp[254]; +	struct hci_request rq; + +	memset(&cp, 0, sizeof(cp)); +	cp[0] = 0xc2; +	memcpy(cp + 1, cmd, sizeof(cmd)); + +	memset(&rq, 0, sizeof(rq)); +	rq.ogf    = OGF_VENDOR_CMD; +	rq.ocf    = 0x00; +	rq.event  = EVT_VENDOR; +	rq.cparam = cp; +	rq.clen   = sizeof(cmd) + 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) +		return -1; + +	*value = rp[11] + (rp[12] << 8); + +	return 0; +} + +int csr_read_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t *value) +{ +	unsigned char cmd[] = { 0x00, 0x00, 0x09, 0x00, +				seqnum & 0xff, seqnum >> 8, 0x03, 0x70, 0x00, 0x00, +				pskey & 0xff, pskey >> 8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +	unsigned char cp[254], rp[254]; +	struct hci_request rq; + +	memset(&cp, 0, sizeof(cp)); +	cp[0] = 0xc2; +	memcpy(cp + 1, cmd, sizeof(cmd)); + +	memset(&rq, 0, sizeof(rq)); +	rq.ogf    = OGF_VENDOR_CMD; +	rq.ocf    = 0x00; +	rq.event  = EVT_VENDOR; +	rq.cparam = cp; +	rq.clen   = sizeof(cmd) + 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) +		return -1; + +	*value = rp[17] + (rp[18] << 8); + +	return 0; +} diff --git a/tools/csr.h b/tools/csr.h new file mode 100644 index 00000000..254f108e --- /dev/null +++ b/tools/csr.h @@ -0,0 +1,35 @@ +/* + * + *  CSR BlueCore specific functions + * + *  Copyright (C) 2003  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#define CSR_VARID_BUILDID		0x2819 +#define CSR_VARID_CHIPVER		0x281a +#define CSR_VARID_CHIPREV		0x281b +#define CSR_VARID_MAX_CRYPT_KEY_LENGTH	0x282c + +#define CSR_PSKEY_HOSTIO_MAP_SCO_PCM	0x01ab + +char *csr_buildidtostr(uint16_t id); +char *csr_chipvertostr(uint16_t ver, uint16_t rev); + +int csr_read_varid_uint16(int dd, uint16_t seqnum, uint16_t varid, uint16_t *value); +int csr_read_pskey_uint16(int dd, uint16_t seqnum, uint16_t pskey, uint16_t *value); diff --git a/tools/hciconfig.c b/tools/hciconfig.c index 538e03bc..aa3d9ab4 100644 --- a/tools/hciconfig.c +++ b/tools/hciconfig.c @@ -43,6 +43,8 @@  #include <bluetooth/hci.h>  #include <bluetooth/hci_lib.h> +#include "csr.h" +  extern int optind,opterr,optopt;  extern char *optarg; @@ -268,7 +270,7 @@ void cmd_aclmtu(int ctl, int hdev, char *opt)  	*((uint16_t *)&dr.dev_opt + 1) = mtu;  	*((uint16_t *)&dr.dev_opt + 0) = mpkt; -	 +  	if (ioctl(ctl, HCISETACLMTU, (unsigned long)&dr) < 0) {  		printf("Can't set ACL mtu on hci%d. %s(%d)\n",   				hdev, strerror(errno), errno); @@ -608,21 +610,21 @@ void cmd_inq_parms(int ctl, int hdev, char *opt)  			printf("Invalid argument format\n");  			exit(1);  		} -			 +  		rq.ogf = OGF_HOST_CTL;  		rq.ocf = OCF_WRITE_INQ_ACTIVITY;  		rq.cparam = &cp;  		rq.clen = WRITE_INQ_ACTIVITY_CP_SIZE; -		 +  		cp.window = htobs((uint16_t)window);  		cp.interval = htobs((uint16_t)interval); -		 +  		if (window < 0x12 || window > 0x1000)  			printf("Warning: inquiry window out of range!\n"); -		 +  		if (interval < 0x12 || interval > 0x1000)  			printf("Warning: inquiry interval out of range!\n"); -		 +  		if (hci_send_req(s, &rq, 1000) < 0) {  			printf("Can't set inquiry parameters name on hci%d. %s(%d)\n",  						hdev, strerror(errno), errno); @@ -631,12 +633,12 @@ void cmd_inq_parms(int ctl, int hdev, char *opt)  	} else {  		uint16_t window, interval;  		read_inq_activity_rp rp; -		 +  		rq.ogf = OGF_HOST_CTL;  		rq.ocf = OCF_READ_INQ_ACTIVITY;  		rq.rparam = &rp;  		rq.rlen = READ_INQ_ACTIVITY_RP_SIZE; -		       +  		if (hci_send_req(s, &rq, 1000) < 0) {  			printf("Can't read inquiry parameters on hci%d. %s(%d)\n",   							hdev, strerror(errno), errno); @@ -648,7 +650,7 @@ void cmd_inq_parms(int ctl, int hdev, char *opt)  			exit(1);  		}  		print_dev_hdr(&di); -		 +  		window   = btohs(rp.window);  		interval = btohs(rp.interval);  		printf("\tInquiry interval: %u slots (%.2f ms), window: %u slots (%.2f ms)\n", @@ -675,21 +677,21 @@ void cmd_page_parms(int ctl, int hdev, char *opt)  			printf("Invalid argument format\n");  			exit(1);  		} -			 +  		rq.ogf = OGF_HOST_CTL;  		rq.ocf = OCF_WRITE_PAGE_ACTIVITY;  		rq.cparam = &cp;  		rq.clen = WRITE_PAGE_ACTIVITY_CP_SIZE; -		 +  		cp.window = htobs((uint16_t)window);  		cp.interval = htobs((uint16_t)interval); -		 +  		if (window < 0x12 || window > 0x1000)  			printf("Warning: page window out of range!\n"); -		 +  		if (interval < 0x12 || interval > 0x1000)  			printf("Warning: page interval out of range!\n"); -		 +  		if (hci_send_req(s, &rq, 1000) < 0) {  			printf("Can't set page parameters name on hci%d. %s(%d)\n",  						hdev, strerror(errno), errno); @@ -698,12 +700,12 @@ void cmd_page_parms(int ctl, int hdev, char *opt)  	} else {  		uint16_t window, interval;  		read_page_activity_rp rp; -		 +  		rq.ogf = OGF_HOST_CTL;  		rq.ocf = OCF_READ_PAGE_ACTIVITY;  		rq.rparam = &rp;  		rq.rlen = READ_PAGE_ACTIVITY_RP_SIZE; -		       +  		if (hci_send_req(s, &rq, 1000) < 0) {  			printf("Can't read page parameters on hci%d. %s(%d)\n",   							hdev, strerror(errno), errno); @@ -715,12 +717,12 @@ void cmd_page_parms(int ctl, int hdev, char *opt)  			exit(1);  		}  		print_dev_hdr(&di); -		 +  		window   = btohs(rp.window);  		interval = btohs(rp.interval);  		printf("\tPage interval: %u slots (%.2f ms), window: %u slots (%.2f ms)\n",  				interval, (float)interval * 0.625, window, (float)window * 0.625); -        } +	}  }  void cmd_page_to(int ctl, int hdev, char *opt) @@ -742,17 +744,17 @@ void cmd_page_to(int ctl, int hdev, char *opt)  			printf("Invalid argument format\n");  			exit(1);  		} -			 +  		rq.ogf = OGF_HOST_CTL;  		rq.ocf = OCF_WRITE_PAGE_TIMEOUT;  		rq.cparam = &cp;  		rq.clen = WRITE_PAGE_TIMEOUT_CP_SIZE; -		 +  		cp.timeout = htobs((uint16_t)timeout); -		 +  		if (timeout < 0x01 || timeout > 0xFFFF)  			printf("Warning: page timeout out of range!\n"); -		 +  		if (hci_send_req(s, &rq, 1000) < 0) {  			printf("Can't set page timeout on hci%d. %s(%d)\n",  						hdev, strerror(errno), errno); @@ -761,12 +763,12 @@ void cmd_page_to(int ctl, int hdev, char *opt)  	} else {  		uint16_t timeout;  		read_page_timeout_rp rp; -		 +  		rq.ogf = OGF_HOST_CTL;  		rq.ocf = OCF_READ_PAGE_TIMEOUT;  		rq.rparam = &rp;  		rq.rlen = READ_PAGE_TIMEOUT_RP_SIZE; -		       +  		if (hci_send_req(s, &rq, 1000) < 0) {  			printf("Can't read page timeout on hci%d. %s(%d)\n",   							hdev, strerror(errno), errno); @@ -782,7 +784,7 @@ void cmd_page_to(int ctl, int hdev, char *opt)  		timeout = btohs(rp.timeout);  		printf("\tPage timeout: %u slots (%.2f ms)\n",  				timeout, (float)timeout * 0.625); -        } +	}  }  static void print_rev_ericsson(int dd) @@ -791,12 +793,12 @@ static void print_rev_ericsson(int dd)  	unsigned char buf[102];  	memset(&rq, 0, sizeof(rq)); -	rq.ogf = 0x3f; -	rq.ocf = 0x000f; +	rq.ogf    = 0x3f; +	rq.ocf    = 0x000f;  	rq.cparam = NULL; -	rq.clen = 0; +	rq.clen   = 0;  	rq.rparam = &buf; -	rq.rlen = sizeof(buf); +	rq.rlen   = sizeof(buf);  	if (hci_send_req(dd, &rq, 1000) < 0) {  		printf("\n Can't read revision info. %s(%d)\n", strerror(errno), errno); @@ -806,40 +808,28 @@ static void print_rev_ericsson(int dd)  	printf("\t%s\n", buf + 1);  } -static struct { -	char  *str; -	uint16_t rev; -} csr_map[] = { -	{ "HCI 11.2 (bc01b)",	114 }, -	{ "HCI 11.3 (bc01b)",   115 }, -	{ "HCI 12.1 (bc01b)",	119 }, -	{ "HCI 12.3 (bc01b)",	134 }, -	{ "HCI 12.7 (bc01b)",	188 }, -	{ "HCI 12.8 (bc01b)",	218 }, -	{ "HCI 12.9 (bc01b)",	283 }, -	{ "HCI 13.10 (bc01b)",	309 }, -	{ "HCI 13.11 (bc01b)",	351 }, -	{ "HCI 16.4 (bc01b)",	523 }, -	{ "HCI 14.3 (bc02x)",	272 }, -	{ "HCI 14.6 (bc02x)",	336 }, -	{ "HCI 14.7 (bc02x)",	373 }, -	{ "HCI 14.8 (bc02x)",	487 }, -	{ "HCI 15.3 (bc02x)",	443 }, -	{ "HCI 16.4 (bc02x)",	525 }, -	{ NULL } -}; - -static void print_rev_csr(uint16_t rev) +static void print_rev_csr(int dd, uint16_t rev)  { -	int i; +	uint16_t buildid, chipver, chiprev, maxkeylen, mapsco; -	for (i = 0; csr_map[i].str; i++) -		if (csr_map[i].rev == rev) { -			printf("\t%s\n", csr_map[i].str); -			return; -		} +	if (csr_read_varid_uint16(dd, 0, CSR_VARID_BUILDID, &buildid) < 0) { +		printf("\t%s\n", csr_buildidtostr(rev)); +		return; +	} + +	printf("\t%s\n", csr_buildidtostr(buildid)); + +	if (!csr_read_varid_uint16(dd, 1, CSR_VARID_CHIPVER, &chipver)) { +		if (csr_read_varid_uint16(dd, 2, CSR_VARID_CHIPREV, &chiprev) < 0) +			chiprev = 0; +		printf("\tChip version: %s\n", csr_chipvertostr(chipver, chiprev)); +	} + +	if (!csr_read_varid_uint16(dd, 3, CSR_VARID_MAX_CRYPT_KEY_LENGTH, &maxkeylen)) +		printf("\tMax key size: %d bit\n", maxkeylen * 8); -	printf("\tUnknown firmware\n"); +	if (!csr_read_pskey_uint16(dd, 4, CSR_PSKEY_HOSTIO_MAP_SCO_PCM, &mapsco)) +		printf("\tSCO mapping:  %s\n", mapsco ? "PCM" : "HCI");  }  static void print_rev_avm(uint16_t rev) @@ -870,7 +860,7 @@ static void cmd_revision(int ctl, int hdev, char *opt)  		print_rev_ericsson(dd);  		break;  	case 10: -		print_rev_csr(ver.hci_rev); +		print_rev_csr(dd, ver.hci_rev);  		break;  	case 31:  		print_rev_avm(ver.hci_rev); @@ -890,13 +880,13 @@ void print_dev_hdr(struct hci_dev_info *di)  	if (hdr == di->dev_id)  		return;  	hdr = di->dev_id; -	 +  	baswap(&bdaddr, &di->bdaddr);  	printf("%s:\tType: %s\n", di->name, hci_dtypetostr(di->type) );  	printf("\tBD Address: %s ACL MTU: %d:%d  SCO MTU: %d:%d\n", -	       batostr(&bdaddr), di->acl_mtu, di->acl_pkts, -	       di->sco_mtu, di->sco_pkts); +		batostr(&bdaddr), di->acl_mtu, di->acl_pkts, +		di->sco_mtu, di->sco_pkts);  }  void print_dev_info(int ctl, struct hci_dev_info *di) @@ -908,10 +898,10 @@ void print_dev_info(int ctl, struct hci_dev_info *di)  	printf("\t%s\n", hci_dflagstostr(di->flags) );  	printf("\tRX bytes:%d acl:%d sco:%d events:%d errors:%d\n", -	       st->byte_rx, st->acl_rx, st->sco_rx, st->evt_rx, st->err_rx); +		st->byte_rx, st->acl_rx, st->sco_rx, st->evt_rx, st->err_rx);  	printf("\tTX bytes:%d acl:%d sco:%d commands:%d errors:%d\n", -	       st->byte_tx, st->acl_tx, st->sco_tx, st->cmd_tx, st->err_tx); +		st->byte_tx, st->acl_tx, st->sco_tx, st->cmd_tx, st->err_tx);  	if (all) {  		print_dev_features(di, 0); @@ -925,7 +915,7 @@ void print_dev_info(int ctl, struct hci_dev_info *di)  			cmd_version(ctl, di->dev_id, NULL);  		}  	} -		 +  	printf("\n");  } @@ -1033,7 +1023,7 @@ int main(int argc, char **argv, char **env)  			if (command[i].opt) {  				argc--; argv++;  			} -			 +  			command[i].func(ctl, di.dev_id, *argv);  			cmd = 1;  			break;  | 
