121308Sache/* 221308Sache * util.c 321308Sache * 421308Sache * Copyright (c) 2001 Maksim Yevmenkin <m_evmenkin@yahoo.com> 521308Sache * All rights reserved. 621308Sache * 721308Sache * Redistribution and use in source and binary forms, with or without 821308Sache * modification, are permitted provided that the following conditions 921308Sache * are met: 1058310Sache * 1. Redistributions of source code must retain the above copyright 1121308Sache * notice, this list of conditions and the following disclaimer. 1221308Sache * 2. Redistributions in binary form must reproduce the above copyright 1321308Sache * notice, this list of conditions and the following disclaimer in the 1421308Sache * documentation and/or other materials provided with the distribution. 1521308Sache * 1621308Sache * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1721308Sache * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1821308Sache * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1921308Sache * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2021308Sache * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2158310Sache * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2221308Sache * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2321308Sache * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2421308Sache * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2521308Sache * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2621308Sache * SUCH DAMAGE. 2721308Sache * 2821308Sache * $Id: util.c,v 1.2 2003/05/19 17:29:29 max Exp $ 2921308Sache * $FreeBSD: releng/10.3/usr.sbin/bluetooth/hccontrol/util.c 162495 2006-09-21 02:41:04Z emax $ 3021308Sache */ 3121308Sache 3221308Sache#include <sys/param.h> 3321308Sache#include <bluetooth.h> 3421308Sache#include <stdio.h> 3521308Sache#include <string.h> 3621308Sache 3721308Sache#define SIZE(x) (sizeof((x))/sizeof((x)[0])) 3821308Sache 3921308Sachechar const * 4021308Sachehci_link2str(int link_type) 4121308Sache{ 4221308Sache static char const * const t[] = { 4321308Sache /* NG_HCI_LINK_SCO */ "SCO", 4421308Sache /* NG_HCI_LINK_ACL */ "ACL" 4521308Sache }; 4621308Sache 4721308Sache return (link_type >= SIZE(t)? "?" : t[link_type]); 4821308Sache} /* hci_link2str */ 4921308Sache 5021308Sachechar const * 5121308Sachehci_pin2str(int type) 5221308Sache{ 5321308Sache static char const * const t[] = { 5421308Sache /* 0x00 */ "Variable PIN", 5521308Sache /* 0x01 */ "Fixed PIN" 5621308Sache }; 5721308Sache 5821308Sache return (type >= SIZE(t)? "?" : t[type]); 5921308Sache} /* hci_pin2str */ 6058310Sache 6158310Sachechar const * 6258310Sachehci_scan2str(int scan) 6358310Sache{ 6421308Sache static char const * const t[] = { 6521308Sache /* 0x00 */ "No Scan enabled", 6621308Sache /* 0x01 */ "Inquiry Scan enabled. Page Scan disabled", 6721308Sache /* 0x02 */ "Inquiry Scan disabled. Page Scan enabled", 6821308Sache /* 0x03 */ "Inquiry Scan enabled. Page Scan enabled" 6921308Sache }; 7021308Sache 71119610Sache return (scan >= SIZE(t)? "?" : t[scan]); 72119610Sache} /* hci_scan2str */ 73119610Sache 74119610Sachechar const * 75119610Sachehci_encrypt2str(int encrypt, int brief) 7621308Sache{ 7758310Sache static char const * const t[] = { 7821308Sache /* 0x00 */ "Disabled", 7958310Sache /* 0x01 */ "Only for point-to-point packets", 8058310Sache /* 0x02 */ "Both point-to-point and broadcast packets" 8121308Sache }; 8221308Sache 8321308Sache static char const * const t1[] = { 8421308Sache /* NG_HCI_ENCRYPTION_MODE_NONE */ "NONE", 8521308Sache /* NG_HCI_ENCRYPTION_MODE_P2P */ "P2P", 8621308Sache /* NG_HCI_ENCRYPTION_MODE_ALL */ "ALL", 8721308Sache }; 8875406Sache 8921308Sache if (brief) 9021308Sache return (encrypt >= SIZE(t1)? "?" : t1[encrypt]); 9121308Sache 9221308Sache return (encrypt >= SIZE(t)? "?" : t[encrypt]); 9375406Sache} /* hci_encrypt2str */ 9475406Sache 9521308Sachechar const * 9621308Sachehci_coding2str(int coding) 9721308Sache{ 9821308Sache static char const * const t[] = { 9921308Sache /* 0x00 */ "Linear", 10021308Sache /* 0x01 */ "u-law", 10121308Sache /* 0x02 */ "A-law", 10221308Sache /* 0x03 */ "Reserved" 10321308Sache }; 10421308Sache 10521308Sache return (coding >= SIZE(t)? "?" : t[coding]); 10621308Sache} /* hci_coding2str */ 10775406Sache 10821308Sachechar const * 10921308Sachehci_vdata2str(int data) 11021308Sache{ 11121308Sache static char const * const t[] = { 11221308Sache /* 0x00 */ "1's complement", 11321308Sache /* 0x01 */ "2's complement", 11421308Sache /* 0x02 */ "Sign-Magnitude", 11521308Sache /* 0x03 */ "Reserved" 11621308Sache }; 11721308Sache 11821308Sache return (data >= SIZE(t)? "?" : t[data]); 11921308Sache} /* hci_vdata2str */ 12021308Sache 12121308Sachechar const * 12221308Sachehci_hmode2str(int mode, char *buffer, int size) 12321308Sache{ 12421308Sache static char const * const t[] = { 12521308Sache /* 0x01 */ "Suspend Page Scan ", 12621308Sache /* 0x02 */ "Suspend Inquiry Scan ", 12721308Sache /* 0x04 */ "Suspend Periodic Inquiries " 12821308Sache }; 12921308Sache 13021308Sache if (buffer != NULL && size > 0) { 13121308Sache int n; 13221308Sache 13321308Sache memset(buffer, 0, size); 13421308Sache for (n = 0; n < SIZE(t); n++) { 13521308Sache int len = strlen(buffer); 13621308Sache 13721308Sache if (len >= size) 13875406Sache break; 13921308Sache if (mode & (1 << n)) 14021308Sache strncat(buffer, t[n], size - len); 14121308Sache } 14221308Sache } 14321308Sache 14421308Sache return (buffer); 14521308Sache} /* hci_hmode2str */ 14621308Sache 14721308Sachechar const * 14821308Sachehci_ver2str(int ver) 14921308Sache{ 15021308Sache static char const * const t[] = { 15121308Sache /* 0x00 */ "Bluetooth HCI Specification 1.0B", 15221308Sache /* 0x01 */ "Bluetooth HCI Specification 1.1", 15321308Sache /* 0x02 */ "Bluetooth HCI Specification 1.2", 15421308Sache /* 0x03 */ "Bluetooth HCI Specification 2.0" 15521308Sache }; 15621308Sache 15775406Sache return (ver >= SIZE(t)? "?" : t[ver]); 15821308Sache} /* hci_ver2str */ 15921308Sache 16021308Sachechar const * 16121308Sachehci_lmpver2str(int ver) 16221308Sache{ 16321308Sache static char const * const t[] = { 16421308Sache /* 0x00 */ "Bluetooth LMP 1.0", 16521308Sache /* 0x01 */ "Bluetooth LMP 1.1", 16621308Sache /* 0x02 */ "Bluetooth LMP 1.2", 16775406Sache /* 0x03 */ "Bluetooth LMP 2.0" 16821308Sache }; 16921308Sache 17035486Sache return (ver >= SIZE(t)? "?" : t[ver]); 17135486Sache} /* hci_lmpver2str */ 17235486Sache 17375406Sachechar const * 17435486Sachehci_manufacturer2str(int m) 17535486Sache{ 17647558Sache static char const * const t[] = { 17735486Sache /* 0000 */ "Ericsson Technology Licensing", 17847558Sache /* 0001 */ "Nokia Mobile Phones", 17935486Sache /* 0002 */ "Intel Corp.", 18035486Sache /* 0003 */ "IBM Corp.", 18147558Sache /* 0004 */ "Toshiba Corp.", 18275406Sache /* 0005 */ "3Com", 18347558Sache /* 0006 */ "Microsoft", 18447558Sache /* 0007 */ "Lucent", 18535486Sache /* 0008 */ "Motorola", 18647558Sache /* 0009 */ "Infineon Technologies AG", 18735486Sache /* 0010 */ "Cambridge Silicon Radio", 18835486Sache /* 0011 */ "Silicon Wave", 18935486Sache /* 0012 */ "Digianswer A/S", 19035486Sache /* 0013 */ "Texas Instruments Inc.", 19175406Sache /* 0014 */ "Parthus Technologies Inc.", 19235486Sache /* 0015 */ "Broadcom Corporation", 19335486Sache /* 0016 */ "Mitel Semiconductor", 19475406Sache /* 0017 */ "Widcomm, Inc.", 19535486Sache /* 0018 */ "Zeevo, Inc.", 19635486Sache /* 0019 */ "Atmel Corporation", 19735486Sache /* 0020 */ "Mitsubishi Electric Corporation", 19835486Sache /* 0021 */ "RTX Telecom A/S", 19935486Sache /* 0022 */ "KC Technology Inc.", 20035486Sache /* 0023 */ "Newlogic", 20135486Sache /* 0024 */ "Transilica, Inc.", 20221308Sache /* 0025 */ "Rohde & Schwartz GmbH & Co. KG", 20321308Sache /* 0026 */ "TTPCom Limited", 20421308Sache /* 0027 */ "Signia Technologies, Inc.", 20521308Sache /* 0028 */ "Conexant Systems Inc.", 20621308Sache /* 0029 */ "Qualcomm", 20775406Sache /* 0030 */ "Inventel", 20875406Sache /* 0031 */ "AVM Berlin", 20921308Sache /* 0032 */ "BandSpeed, Inc.", 21021308Sache /* 0033 */ "Mansella Ltd", 21126497Sache /* 0034 */ "NEC Corporation", 21221308Sache /* 0035 */ "WavePlus Technology Co., Ltd.", 21321308Sache /* 0036 */ "Alcatel", 21421308Sache /* 0037 */ "Philips Semiconductors", 21521308Sache /* 0038 */ "C Technologies", 21621308Sache /* 0039 */ "Open Interface", 21721308Sache /* 0040 */ "R F Micro Devices", 21821308Sache /* 0041 */ "Hitachi Ltd", 21975406Sache /* 0042 */ "Symbol Technologies, Inc.", 22021308Sache /* 0043 */ "Tenovis", 22121308Sache /* 0044 */ "Macronix International Co. Ltd.", 22221308Sache /* 0045 */ "GCT Semiconductor", 22321308Sache /* 0046 */ "Norwood Systems", 22421308Sache /* 0047 */ "MewTel Technology Inc.", 22521308Sache /* 0048 */ "ST Microelectronics", 22621308Sache /* 0049 */ "Synopsys", 22721308Sache /* 0050 */ "Red-M (Communications) Ltd", 22821308Sache /* 0051 */ "Commil Ltd", 22921308Sache /* 0052 */ "Computer Access Technology Corporation (CATC)", 23021308Sache /* 0053 */ "Eclipse (HQ Espana) S.L.", 23121308Sache /* 0054 */ "Renesas Technology Corp.", 23221308Sache /* 0055 */ "Mobilian Corporation", 23321308Sache /* 0056 */ "Terax", 23421308Sache /* 0057 */ "Integrated System Solution Corp.", 23521308Sache /* 0058 */ "Matsushita Electric Industrial Co., Ltd.", 23621308Sache /* 0059 */ "Gennum Corporation", 23721308Sache /* 0060 */ "Research In Motion", 23821308Sache /* 0061 */ "IPextreme, Inc.", 23921308Sache /* 0062 */ "Systems and Chips, Inc", 24021308Sache /* 0063 */ "Bluetooth SIG, Inc", 24121308Sache /* 0064 */ "Seiko Epson Corporation" 24221308Sache }; 24321308Sache 24475406Sache return (m >= SIZE(t)? "?" : t[m]); 24575406Sache} /* hci_manufacturer2str */ 24621308Sache 24721308Sachechar const * 24821308Sachehci_features2str(uint8_t *features, char *buffer, int size) 24921308Sache{ 25021308Sache static char const * const t[][8] = { 251119610Sache { /* byte 0 */ 25221308Sache /* 0 */ "<3-Slot> ", 253119610Sache /* 1 */ "<5-Slot> ", 254119610Sache /* 2 */ "<Encryption> ", 25521308Sache /* 3 */ "<Slot offset> ", 25621308Sache /* 4 */ "<Timing accuracy> ", 25721308Sache /* 5 */ "<Switch> ", 25821308Sache /* 6 */ "<Hold mode> ", 25921308Sache /* 7 */ "<Sniff mode> " 26021308Sache }, 26121308Sache { /* byte 1 */ 26221308Sache /* 0 */ "<Park mode> ", 263119610Sache /* 1 */ "<RSSI> ", 26421308Sache /* 2 */ "<Channel quality> ", 26521308Sache /* 3 */ "<SCO link> ", 26621308Sache /* 4 */ "<HV2 packets> ", 26721308Sache /* 5 */ "<HV3 packets> ", 26821308Sache /* 6 */ "<u-law log> ", 26921308Sache /* 7 */ "<A-law log> " 27021308Sache }, 27121308Sache { /* byte 2 */ 27221308Sache /* 0 */ "<CVSD> ", 27321308Sache /* 1 */ "<Paging scheme> ", 27421308Sache /* 2 */ "<Power control> ", 27521308Sache /* 3 */ "<Transparent SCO data> ", 27621308Sache /* 4 */ "<Flow control lag (bit0)> ", 277119610Sache /* 5 */ "<Flow control lag (bit1)> ", 278119610Sache /* 6 */ "<Flow control lag (bit2)> ", 27921308Sache /* 7 */ "<Unknown2.7> " 280119610Sache }}; 281119610Sache 282119610Sache if (buffer != NULL && size > 0) { 283119610Sache int n, i, len0, len1; 28421308Sache 28521308Sache memset(buffer, 0, size); 28621308Sache len1 = 0; 28721308Sache 28821308Sache for (n = 0; n < SIZE(t); n++) { 28921308Sache for (i = 0; i < SIZE(t[n]); i++) { 29021308Sache len0 = strlen(buffer); 29121308Sache if (len0 >= size) 29221308Sache goto done; 29321308Sache 29421308Sache if (features[n] & (1 << i)) { 295119610Sache if (len1 + strlen(t[n][i]) > 60) { 296119610Sache len1 = 0; 297119610Sache buffer[len0 - 1] = '\n'; 298119610Sache } 299119610Sache 300119610Sache len1 += strlen(t[n][i]); 301119610Sache strncat(buffer, t[n][i], size - len0); 302119610Sache } 30321308Sache } 30421308Sache } 30521308Sache } 30621308Sachedone: 30721308Sache return (buffer); 308119610Sache} /* hci_features2str */ 309119610Sache 310119610Sachechar const * 311119610Sachehci_cc2str(int cc) 312119610Sache{ 313119610Sache static char const * const t[] = { 314119610Sache /* 0x00 */ "North America, Europe, Japan", 315119610Sache /* 0x01 */ "France" 316119610Sache }; 317119610Sache 318119610Sache return (cc >= SIZE(t)? "?" : t[cc]); 31921308Sache} /* hci_cc2str */ 32021308Sache 32121308Sachechar const * 32221308Sachehci_con_state2str(int state) 32321308Sache{ 324119610Sache static char const * const t[] = { 325119610Sache /* NG_HCI_CON_CLOSED */ "CLOSED", 326119610Sache /* NG_HCI_CON_W4_LP_CON_RSP */ "W4_LP_CON_RSP", 327119610Sache /* NG_HCI_CON_W4_CONN_COMPLETE */ "W4_CONN_COMPLETE", 328119610Sache /* NG_HCI_CON_OPEN */ "OPEN" 32921308Sache }; 33021308Sache 33121308Sache return (state >= SIZE(t)? "UNKNOWN" : t[state]); 33221308Sache} /* hci_con_state2str */ 33321308Sache 33421308Sachechar const * 33521308Sachehci_status2str(int status) 33621308Sache{ 33721308Sache static char const * const t[] = { 33821308Sache /* 0x00 */ "No error", 33921308Sache /* 0x01 */ "Unknown HCI command", 34021308Sache /* 0x02 */ "No connection", 34121308Sache /* 0x03 */ "Hardware failure", 34221308Sache /* 0x04 */ "Page timeout", 34321308Sache /* 0x05 */ "Authentication failure", 34421308Sache /* 0x06 */ "Key missing", 34575406Sache /* 0x07 */ "Memory full", 34675406Sache /* 0x08 */ "Connection timeout", 34721308Sache /* 0x09 */ "Max number of connections", 34821308Sache /* 0x0a */ "Max number of SCO connections to a unit", 34935486Sache /* 0x0b */ "ACL connection already exists", 35021308Sache /* 0x0c */ "Command disallowed", 35121308Sache /* 0x0d */ "Host rejected due to limited resources", 35221308Sache /* 0x0e */ "Host rejected due to security reasons", 35321308Sache /* 0x0f */ "Host rejected due to remote unit is a personal unit", 35421308Sache /* 0x10 */ "Host timeout", 35521308Sache /* 0x11 */ "Unsupported feature or parameter value", 35621308Sache /* 0x12 */ "Invalid HCI command parameter", 35721308Sache /* 0x13 */ "Other end terminated connection: User ended connection", 35821308Sache /* 0x14 */ "Other end terminated connection: Low resources", 35921308Sache /* 0x15 */ "Other end terminated connection: About to power off", 36035486Sache /* 0x16 */ "Connection terminated by local host", 36135486Sache /* 0x17 */ "Repeated attempts", 36221308Sache /* 0x18 */ "Pairing not allowed", 36321308Sache /* 0x19 */ "Unknown LMP PDU", 36421308Sache /* 0x1a */ "Unsupported remote feature", 36521308Sache /* 0x1b */ "SCO offset rejected", 366119610Sache /* 0x1c */ "SCO interval rejected", 36721308Sache /* 0x1d */ "SCO air mode rejected", 36821308Sache /* 0x1e */ "Invalid LMP parameters", 36935486Sache /* 0x1f */ "Unspecified error", 37021308Sache /* 0x20 */ "Unsupported LMP parameter value", 37121308Sache /* 0x21 */ "Role change not allowed", 37235486Sache /* 0x22 */ "LMP response timeout", 37321308Sache /* 0x23 */ "LMP error transaction collision", 37421308Sache /* 0x24 */ "LMP PSU not allowed", 375119610Sache /* 0x25 */ "Encryption mode not acceptable", 37635486Sache /* 0x26 */ "Unit key used", 37735486Sache /* 0x27 */ "QoS is not supported", 37835486Sache /* 0x28 */ "Instant passed", 37921308Sache /* 0x29 */ "Pairing with unit key not supported" 38021308Sache }; 38121308Sache 38221308Sache return (status >= SIZE(t)? "Unknown error" : t[status]); 38335486Sache} /* hci_status2str */ 38435486Sache 38521308Sachechar const * 38635486Sachehci_bdaddr2str(bdaddr_t const *ba) 38735486Sache{ 38835486Sache extern int numeric_bdaddr; 38935486Sache static char buffer[MAXHOSTNAMELEN]; 39035486Sache struct hostent *he = NULL; 39135486Sache 39235486Sache if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) { 39335486Sache buffer[0] = '*'; 39435486Sache buffer[1] = 0; 39535486Sache 39635486Sache return (buffer); 39735486Sache } 39835486Sache 39935486Sache if (!numeric_bdaddr && 40035486Sache (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) { 40135486Sache strlcpy(buffer, he->h_name, sizeof(buffer)); 40235486Sache 40335486Sache return (buffer); 40435486Sache } 40535486Sache 40635486Sache bt_ntoa(ba, buffer); 40735486Sache 40835486Sache return (buffer); 40935486Sache} /* hci_bdaddr2str */ 41035486Sache 41135486Sache