/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2000-2001  Qualcomm Incorporated
 *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
 *  Copyright (C) 2002-2010  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 <ctype.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>

#include "bluetooth.h"
#include "hci.h"

void baswap(bdaddr_t *dst, const bdaddr_t *src)
{
	register unsigned char *d = (unsigned char *) dst;
	register const unsigned char *s = (const unsigned char *) src;
	register int i;

	for (i = 0; i < 6; i++)
		d[i] = s[5-i];
}

char *batostr(const bdaddr_t *ba)
{
	char *str = bt_malloc(18);
	if (!str)
		return NULL;

	sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
		ba->b[0], ba->b[1], ba->b[2],
		ba->b[3], ba->b[4], ba->b[5]);

	return str;
}

bdaddr_t *strtoba(const char *str)
{
	bdaddr_t b;
	bdaddr_t *ba = bt_malloc(sizeof(*ba));

	if (ba) {
		str2ba(str, &b);
		baswap(ba, &b);
	}

	return ba;
}

int ba2str(const bdaddr_t *ba, char *str)
{
	return sprintf(str, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X",
		ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
}

int str2ba(const char *str, bdaddr_t *ba)
{
	int i;

	if (bachk(str) < 0) {
		memset(ba, 0, sizeof(*ba));
		return -1;
	}

	for (i = 5; i >= 0; i--, str += 3)
		ba->b[i] = strtol(str, NULL, 16);

	return 0;
}

int ba2oui(const bdaddr_t *ba, char *str)
{
	return sprintf(str, "%2.2X-%2.2X-%2.2X", ba->b[5], ba->b[4], ba->b[3]);
}

int bachk(const char *str)
{
	if (!str)
		return -1;

	if (strlen(str) != 17)
		return -1;

	while (*str) {
		if (!isxdigit(*str++))
			return -1;

		if (!isxdigit(*str++))
			return -1;

		if (*str == 0)
			break;

		if (*str++ != ':')
			return -1;
	}

	return 0;
}

int baprintf(const char *format, ...)
{
	va_list ap;
	int len;

	va_start(ap, format);
	len = vprintf(format, ap);
	va_end(ap);

	return len;
}

int bafprintf(FILE *stream, const char *format, ...)
{
	va_list ap;
	int len;

	va_start(ap, format);
	len = vfprintf(stream, format, ap);
	va_end(ap);

	return len;
}

int basprintf(char *str, const char *format, ...)
{
	va_list ap;
	int len;

	va_start(ap, format);
	len = vsnprintf(str, (~0U) >> 1, format, ap);
	va_end(ap);

	return len;
}

int basnprintf(char *str, size_t size, const char *format, ...)
{
	va_list ap;
	int len;

	va_start(ap, format);
	len = vsnprintf(str, size, format, ap);
	va_end(ap);

	return len;
}

void *bt_malloc(size_t size)
{
	return malloc(size);
}

void bt_free(void *ptr)
{
	free(ptr);
}

/* Bluetooth error codes to Unix errno mapping */
int bt_error(uint16_t code)
{
	switch (code) {
	case 0:
		return 0;
	case HCI_UNKNOWN_COMMAND:
		return EBADRQC;
	case HCI_NO_CONNECTION:
		return ENOTCONN;
	case HCI_HARDWARE_FAILURE:
		return EIO;
	case HCI_PAGE_TIMEOUT:
		return EHOSTDOWN;
	case HCI_AUTHENTICATION_FAILURE:
		return EACCES;
	case HCI_PIN_OR_KEY_MISSING:
		return EINVAL;
	case HCI_MEMORY_FULL:
		return ENOMEM;
	case HCI_CONNECTION_TIMEOUT:
		return ETIMEDOUT;
	case HCI_MAX_NUMBER_OF_CONNECTIONS:
	case HCI_MAX_NUMBER_OF_SCO_CONNECTIONS:
		return EMLINK;
	case HCI_ACL_CONNECTION_EXISTS:
		return EALREADY;
	case HCI_COMMAND_DISALLOWED:
	case HCI_TRANSACTION_COLLISION:
	case HCI_ROLE_SWITCH_PENDING:
		return EBUSY;
	case HCI_REJECTED_LIMITED_RESOURCES:
	case HCI_REJECTED_PERSONAL:
	case HCI_QOS_REJECTED:
		return ECONNREFUSED;
	case HCI_HOST_TIMEOUT:
		return ETIMEDOUT;
	case HCI_UNSUPPORTED_FEATURE:
	case HCI_QOS_NOT_SUPPORTED:
	case HCI_PAIRING_NOT_SUPPORTED:
	case HCI_CLASSIFICATION_NOT_SUPPORTED:
	case HCI_UNSUPPORTED_LMP_PARAMETER_VALUE:
	case HCI_PARAMETER_OUT_OF_RANGE:
	case HCI_QOS_UNACCEPTABLE_PARAMETER:
		return EOPNOTSUPP;
	case HCI_INVALID_PARAMETERS:
	case HCI_SLOT_VIOLATION:
		return EINVAL;
	case HCI_OE_USER_ENDED_CONNECTION:
	case HCI_OE_LOW_RESOURCES:
	case HCI_OE_POWER_OFF:
		return ECONNRESET;
	case HCI_CONNECTION_TERMINATED:
		return ECONNABORTED;
	case HCI_REPEATED_ATTEMPTS:
		return ELOOP;
	case HCI_REJECTED_SECURITY:
	case HCI_PAIRING_NOT_ALLOWED:
	case HCI_INSUFFICIENT_SECURITY:
		return EACCES;
	case HCI_UNSUPPORTED_REMOTE_FEATURE:
		return EPROTONOSUPPORT;
	case HCI_SCO_OFFSET_REJECTED:
		return ECONNREFUSED;
	case HCI_UNKNOWN_LMP_PDU:
	case HCI_INVALID_LMP_PARAMETERS:
	case HCI_LMP_ERROR_TRANSACTION_COLLISION:
	case HCI_LMP_PDU_NOT_ALLOWED:
	case HCI_ENCRYPTION_MODE_NOT_ACCEPTED:
		return EPROTO;
	default:
		return ENOSYS;
	}
}

const char *bt_compidtostr(int compid)
{
	switch (compid) {
	case 0:
		return "Ericsson Technology Licensing";
	case 1:
		return "Nokia Mobile Phones";
	case 2:
		return "Intel Corp.";
	case 3:
		return "IBM Corp.";
	case 4:
		return "Toshiba Corp.";
	case 5:
		return "3Com";
	case 6:
		return "Microsoft";
	case 7:
		return "Lucent";
	case 8:
		return "Motorola";
	case 9:
		return "Infineon Technologies AG";
	case 10:
		return "Cambridge Silicon Radio";
	case 11:
		return "Silicon Wave";
	case 12:
		return "Digianswer A/S";
	case 13:
		return "Texas Instruments Inc.";
	case 14:
		return "Ceva, Inc. (formerly Parthus Technologies, Inc.)";
	case 15:
		return "Broadcom Corporation";
	case 16:
		return "Mitel Semiconductor";
	case 17:
		return "Widcomm, Inc";
	case 18:
		return "Zeevo, Inc.";
	case 19:
		return "Atmel Corporation";
	case 20:
		return "Mitsubishi Electric Corporation";
	case 21:
		return "RTX Telecom A/S";
	case 22:
		return "KC Technology Inc.";
	case 23:
		return "NewLogic";
	case 24:
		return "Transilica, Inc.";
	case 25:
		return "Rohde & Schwarz GmbH & Co. KG";
	case 26:
		return "TTPCom Limited";
	case 27:
		return "Signia Technologies, Inc.";
	case 28:
		return "Conexant Systems Inc.";
	case 29:
		return "Qualcomm";
	case 30:
		return "Inventel";
	case 31:
		return "AVM Berlin";
	case 32:
		return "BandSpeed, Inc.";
	case 33:
		return "Mansella Ltd";
	case 34:
		return "NEC Corporation";
	case 35:
		return "WavePlus Technology Co., Ltd.";
	case 36:
		return "Alcatel";
	case 37:
		return "Philips Semiconductors";
	case 38:
		return "C Technologies";
	case 39:
		return "Open Interface";
	case 40:
		return "R F Micro Devices";
	case 41:
		return "Hitachi Ltd";
	case 42:
		return "Symbol Technologies, Inc.";
	case 43:
		return "Tenovis";
	case 44:
		return "Macronix International Co. Ltd.";
	case 45:
		return "GCT Semiconductor";
	case 46:
		return "Norwood Systems";
	case 47:
		return "MewTel Technology Inc.";
	case 48:
		return "ST Microelectronics";
	case 49:
		return "Synopsis";
	case 50:
		return "Red-M (Communications) Ltd";
	case 51:
		return "Commil Ltd";
	case 52:
		return "Computer Access Technology Corporation (CATC)";
	case 53:
		return "Eclipse (HQ Espana) S.L.";
	case 54:
		return "Renesas Technology Corp.";
	case 55:
		return "Mobilian Corporation";
	case 56:
		return "Terax";
	case 57:
		return "Integrated System Solution Corp.";
	case 58:
		return "Matsushita Electric Industrial Co., Ltd.";
	case 59:
		return "Gennum Corporation";
	case 60:
		return "Research In Motion";
	case 61:
		return "IPextreme, Inc.";
	case 62:
		return "Systems and Chips, Inc.";
	case 63:
		return "Bluetooth SIG, Inc.";
	case 64:
		return "Seiko Epson Corporation";
	case 65:
		return "Integrated Silicon Solution Taiwan, Inc.";
	case 66:
		return "CONWISE Technology Corporation Ltd";
	case 67:
		return "PARROT SA";
	case 68:
		return "Socket Mobile";
	case 69:
		return "Atheros Communications, Inc.";
	case 70:
		return "MediaTek, Inc.";
	case 71:
		return "Bluegiga";
	case 72:
		return "Marvell Technology Group Ltd.";
	case 73:
		return "3DSP Corporation";
	case 74:
		return "Accel Semiconductor Ltd.";
	case 75:
		return "Continental Automotive Systems";
	case 76:
		return "Apple, Inc.";
	case 77:
		return "Staccato Communications, Inc.";
	case 78:
		return "Avago Technologies";
	case 79:
		return "APT Licensing Ltd.";
	case 80:
		return "SiRF Technology";
	case 81:
		return "Tzero Technologies, Inc.";
	case 82:
		return "J&M Corporation";
	case 83:
		return "Free2move AB";
	case 84:
		return "3DiJoy Corporation";
	case 85:
		return "Plantronics, Inc.";
	case 86:
		return "Sony Ericsson Mobile Communications";
	case 87:
		return "Harman International Industries, Inc.";
	case 88:
		return "Vizio, Inc.";
	case 89:
		return "Nordic Semiconductor ASA";
	case 90:
		return "EM Microelectronic-Marin SA";
	case 91:
		return "Ralink Technology Corporation";
	case 92:
		return "Belkin International, Inc.";
	case 93:
		return "Realtek Semiconductor Corporation";
	case 94:
		return "Stonestreet One, LLC";
	case 95:
		return "Wicentric, Inc.";
	case 96:
		return "RivieraWaves S.A.S";
	case 97:
		return "RDA Microelectronics";
	case 98:
		return "Gibson Guitars";
	case 99:
		return "MiCommand Inc.";
	case 100:
		return "Band XI International, LLC";
	case 101:
		return "Hewlett-Packard Company";
	case 102:
		return "9Solutions Oy";
	case 103:
		return "GN Netcom A/S";
	case 104:
		return "General Motors";
	case 105:
		return "A&D Engineering, Inc.";
	case 106:
		return "MindTree Ltd.";
	case 107:
		return "Polar Electro OY";
	case 108:
		return "Beautiful Enterprise Co., Ltd.";
	case 109:
		return "BriarTek, Inc.";
	case 110:
		return "Summit Data Communications, Inc.";
	case 111:
		return "Sound ID";
	case 112:
		return "Monster, LLC";
	case 113:
		return "connectBlue AB";
	case 114:
		return "ShangHai Super Smart Electronics Co. Ltd.";
	case 115:
		return "Group Sense Ltd.";
	case 116:
		return "Zomm, LLC";
	case 117:
		return "Samsung Electronics Co. Ltd.";
	case 118:
		return "Creative Technology Ltd.";
	case 119:
		return "Laird Technologies";
	case 120:
		return "Nike, Inc.";
	case 121:
		return "lesswire AG";
	case 122:
		return "MStar Semiconductor, Inc.";
	case 123:
		return "Hanlynn Technologies";
	case 124:
		return "A & R Cambridge";
	case 125:
		return "Seers Technology Co. Ltd";
	case 126:
		return "Sports Tracking Technologies Ltd.";
	case 127:
		return "Autonet Mobile";
	case 128:
		return "DeLorme Publishing Company, Inc.";
	case 129:
		return "WuXi Vimicro";
	case 130:
		return "Sennheiser Communications A/S";
	case 131:
		return "TimeKeeping Systems, Inc.";
	case 132:
		return "Ludus Helsinki Ltd.";
	case 133:
		return "BlueRadios, Inc.";
	case 134:
		return "equinox AG";
	case 135:
		return "Garmin International, Inc.";
	case 136:
		return "Ecotest";
	case 137:
		return "GN ReSound A/S";
	case 138:
		return "Jawbone";
	case 139:
		return "Topcorn Positioning Systems, LLC";
	case 140:
		return "Qualcomm Labs, Inc.";
	case 141:
		return "Zscan Software";
	case 142:
		return "Quintic Corp.";
	case 143:
		return "Stollman E+V GmbH";
	case 144:
		return "Funai Electric Co., Ltd.";
	case 145:
		return "Advanced PANMOBIL Systems GmbH & Co. KG";
	case 146:
		return "ThinkOptics, Inc.";
	case 147:
		return "Universal Electronics, Inc.";
	case 148:
		return "Airoha Technology Corp.";
	case 149:
		return "NEC Lighting, Ltd.";
	case 150:
		return "ODM Technology, Inc.";
	case 151:
		return "Bluetrek Technologies Limited";
	case 152:
		return "zer01.tv GmbH";
	case 153:
		return "i.Tech Dynamic Global Distribution Ltd.";
	case 154:
		return "Alpwise";
	case 155:
		return "Jiangsu Toppower Automotive Electronics Co., Ltd.";
	case 156:
		return "Colorfy, Inc.";
	case 157:
		return "Geoforce Inc.";
	case 158:
		return "Bose Corporation";
	case 159:
		return "Suunto Oy";
	case 160:
		return "Kensington Computer Products Group";
	case 161:
		return "SR-Medizinelektronik";
	case 162:
		return "Vertu Corporation Limited";
	case 163:
		return "Meta Watch Ltd.";
	case 164:
		return "LINAK A/S";
	case 165:
		return "OTL Dynamics LLC";
	case 166:
		return "Panda Ocean Inc.";
	case 167:
		return "Visteon Corporation";
	case 168:
		return "ARP Devices Limited";
	case 169:
		return "Magneti Marelli S.p.A";
	case 170:
		return "CAEN RFID srl";
	case 171:
		return "Ingenieur-Systemgruppe Zahn GmbH";
	case 172:
		return "Green Throttle Games";
	case 173:
		return "Peter Systemtechnik GmbH";
	case 174:
		return "Omegawave Oy";
	case 175:
		return "Cinetix";
	case 176:
		return "Passif Semiconductor Corp";
	case 177:
		return "Saris Cycling Group, Inc";
	case 178:
		return "Bekey A/S";
	case 179:
		return "Clarinox Technologies Pty. Ltd.";
	case 180:
		return "BDE Technology Co., Ltd.";
	case 181:
		return "Swirl Networks";
	case 182:
		return "Meso international";
	case 183:
		return "TreLab Ltd";
	case 184:
		return "Qualcomm Innovation Center, Inc. (QuIC)";
	case 185:
		return "Johnson Controls, Inc.";
	case 186:
		return "Starkey Laboratories Inc.";
	case 187:
		return "S-Power Electronics Limited";
	case 188:
		return "Ace Sensor Inc";
	case 189:
		return "Aplix Corporation";
	case 190:
		return "AAMP of America";
	case 191:
		return "Stalmart Technology Limited";
	case 192:
		return "AMICCOM Electronics Corporation";
	case 193:
		return "Shenzhen Excelsecu Data Technology Co.,Ltd";
	case 194:
		return "Geneq Inc.";
	case 195:
		return "adidas AG";
	case 196:
		return "LG Electronics";
	case 197:
		return "Onset Computer Corporation";
	case 198:
		return "Selfly BV";
	case 199:
		return "Quuppa Oy.";
	case 200:
		return "GeLo Inc";
	case 201:
		return "Evluma";
	case 202:
		return "MC10";
	case 203:
		return "Binauric SE";
	case 204:
		return "Beats Electronics";
	case 205:
		return "Microchip Technology Inc.";
	case 65535:
		return "internal use";
	default:
		return "not assigned";
	}
}
