/*
 *
 *  BlueZ - Bluetooth protocol stack for Linux
 *
 *  Copyright (C) 2011  Nokia Corporation
 *  Copyright (C) 2011  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 <string.h>
#include <stdlib.h>
#include <errno.h>

#include "lib/bluetooth.h"
#include "uuid.h"

static uint128_t bluetooth_base_uuid = {
	.data = {	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
			0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB }
};

#define BASE_UUID16_OFFSET	2
#define BASE_UUID32_OFFSET	0

static void bt_uuid16_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
{
	uint16_t be16;

	dst->value.u128 = bluetooth_base_uuid;
	dst->type = BT_UUID128;

	/*
	 * No matter the system: 128-bit UUIDs should be stored
	 * as big-endian. 16-bit UUIDs are stored on host order.
	 */

	be16 = htons(src->value.u16);
	memcpy(&dst->value.u128.data[BASE_UUID16_OFFSET], &be16, sizeof(be16));
}

static void bt_uuid32_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
{
	uint32_t be32;

	dst->value.u128 = bluetooth_base_uuid;
	dst->type = BT_UUID128;

	/*
	 * No matter the system: 128-bit UUIDs should be stored
	 * as big-endian. 32-bit UUIDs are stored on host order.
	 */

	be32 = htonl(src->value.u32);
	memcpy(&dst->value.u128.data[BASE_UUID32_OFFSET], &be32, sizeof(be32));
}

void bt_uuid_to_uuid128(const bt_uuid_t *src, bt_uuid_t *dst)
{
	switch (src->type) {
	case BT_UUID128:
		*dst = *src;
		break;
	case BT_UUID32:
		bt_uuid32_to_uuid128(src, dst);
		break;
	case BT_UUID16:
		bt_uuid16_to_uuid128(src, dst);
		break;
	case BT_UUID_UNSPEC:
	default:
		break;
	}
}

static int bt_uuid128_cmp(const bt_uuid_t *u1, const bt_uuid_t *u2)
{
	return memcmp(&u1->value.u128, &u2->value.u128, sizeof(uint128_t));
}

int bt_uuid16_create(bt_uuid_t *btuuid, uint16_t value)
{
	memset(btuuid, 0, sizeof(bt_uuid_t));
	btuuid->type = BT_UUID16;
	btuuid->value.u16 = value;

	return 0;
}

int bt_uuid32_create(bt_uuid_t *btuuid, uint32_t value)
{
	memset(btuuid, 0, sizeof(bt_uuid_t));
	btuuid->type = BT_UUID32;
	btuuid->value.u32 = value;

	return 0;
}

int bt_uuid128_create(bt_uuid_t *btuuid, uint128_t value)
{
	memset(btuuid, 0, sizeof(bt_uuid_t));
	btuuid->type = BT_UUID128;
	btuuid->value.u128 = value;

	return 0;
}

int bt_uuid_cmp(const bt_uuid_t *uuid1, const bt_uuid_t *uuid2)
{
	bt_uuid_t u1, u2;

	bt_uuid_to_uuid128(uuid1, &u1);
	bt_uuid_to_uuid128(uuid2, &u2);

	return bt_uuid128_cmp(&u1, &u2);
}

/*
 * convert the UUID to string, copying a maximum of n characters.
 */
int bt_uuid_to_string(const bt_uuid_t *uuid, char *str, size_t n)
{
	bt_uuid_t tmp;
	unsigned int   data0;
	unsigned short data1;
	unsigned short data2;
	unsigned short data3;
	unsigned int   data4;
	unsigned short data5;
	const uint8_t *data;

	if (!uuid || uuid->type == BT_UUID_UNSPEC) {
		snprintf(str, n, "NULL");
		return -EINVAL;
	}

	/* Convert to 128 Bit format */
	bt_uuid_to_uuid128(uuid, &tmp);
	data = (uint8_t *) &tmp.value.u128;

	memcpy(&data0, &data[0], 4);
	memcpy(&data1, &data[4], 2);
	memcpy(&data2, &data[6], 2);
	memcpy(&data3, &data[8], 2);
	memcpy(&data4, &data[10], 4);
	memcpy(&data5, &data[14], 2);

	snprintf(str, n, "%.8x-%.4x-%.4x-%.4x-%.8x%.4x",
				ntohl(data0), ntohs(data1),
				ntohs(data2), ntohs(data3),
				ntohl(data4), ntohs(data5));

	return 0;
}

static inline int is_uuid128(const char *string)
{
	return (strlen(string) == 36 &&
			string[8] == '-' &&
			string[13] == '-' &&
			string[18] == '-' &&
			string[23] == '-');
}

static inline int is_base_uuid128(const char *string)
{
	uint16_t uuid;
	char dummy;

	if (!is_uuid128(string))
		return 0;

	return sscanf(string,
		"0000%04hx-0000-1000-8000-00805%1[fF]9%1[bB]34%1[fF]%1[bB]",
		&uuid, &dummy, &dummy, &dummy, &dummy) == 5;
}

static inline int is_uuid32(const char *string)
{
	return (strlen(string) == 8 || strlen(string) == 10);
}

static inline int is_uuid16(const char *string)
{
	return (strlen(string) == 4 || strlen(string) == 6);
}

static int bt_string_to_uuid16(bt_uuid_t *uuid, const char *string)
{
	uint16_t u16;
	char *endptr = NULL;

	u16 = strtol(string, &endptr, 16);
	if (endptr && (*endptr == '\0' || *endptr == '-')) {
		bt_uuid16_create(uuid, u16);
		return 0;
	}

	return -EINVAL;
}

static int bt_string_to_uuid32(bt_uuid_t *uuid, const char *string)
{
	uint32_t u32;
	char *endptr = NULL;

	u32 = strtol(string, &endptr, 16);
	if (endptr && *endptr == '\0') {
		bt_uuid32_create(uuid, u32);
		return 0;
	}

	return -EINVAL;
}

static int bt_string_to_uuid128(bt_uuid_t *uuid, const char *string)
{
	uint32_t data0, data4;
	uint16_t data1, data2, data3, data5;
	uint128_t u128;
	uint8_t *val = (uint8_t *) &u128;

	if (sscanf(string, "%08x-%04hx-%04hx-%04hx-%08x%04hx",
				&data0, &data1, &data2,
				&data3, &data4, &data5) != 6)
		return -EINVAL;

	data0 = htonl(data0);
	data1 = htons(data1);
	data2 = htons(data2);
	data3 = htons(data3);
	data4 = htonl(data4);
	data5 = htons(data5);

	memcpy(&val[0], &data0, 4);
	memcpy(&val[4], &data1, 2);
	memcpy(&val[6], &data2, 2);
	memcpy(&val[8], &data3, 2);
	memcpy(&val[10], &data4, 4);
	memcpy(&val[14], &data5, 2);

	bt_uuid128_create(uuid, u128);

	return 0;
}

int bt_string_to_uuid(bt_uuid_t *uuid, const char *string)
{
	if (is_base_uuid128(string))
		return bt_string_to_uuid16(uuid, string + 4);
	else if (is_uuid128(string))
		return bt_string_to_uuid128(uuid, string);
	else if (is_uuid32(string))
		return bt_string_to_uuid32(uuid, string);
	else if (is_uuid16(string))
		return bt_string_to_uuid16(uuid, string);

	return -EINVAL;
}

int bt_uuid_strcmp(const void *a, const void *b)
{
	bt_uuid_t u1, u2;

	bt_string_to_uuid(&u1, a);
	bt_string_to_uuid(&u2, b);

	return bt_uuid_cmp(&u1, &u2);
}

int bt_uuid_to_le(const bt_uuid_t *src, void *dst)
{
	bt_uuid_t uuid;

	switch (src->type) {
	case BT_UUID16:
		bt_put_le16(src->value.u16, dst);
		return 0;
	case BT_UUID32:
		bt_uuid32_to_uuid128(src, &uuid);
		src = &uuid;
		/* Fallthrough */
	case BT_UUID128:
		/* Convert from 128-bit BE to LE */
		bswap_128(&src->value.u128, dst);
		return 0;
	case BT_UUID_UNSPEC:
	default:
		return -EINVAL;
	}
}
