blob: 6d9185e1531aa41fe985d2d05b989b32d2d3da0f [file] [log] [blame]
/*
*
* BlueZ - Bluetooth protocol stack for Linux
*
* Copyright (C) 2003-2004 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 version 2 as
* published by the Free Software Foundation;
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
* IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
* CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
* COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
* SOFTWARE IS DISCLAIMED.
*
*
* $Id$
*/
#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 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" },
{ 1168, "HCI 18.1" },
{ 1169, "HCI 18.1" },
{ 1392, "HCI 18.2" },
{ 1393, "HCI 18.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;
}