xref: /freebsd/usr.sbin/bluetooth/hccontrol/adv_data.c (revision 42b388439bd3795e09258c57a74ce9eec3651c7b)
19287f06dSTakanori Watanabe /*-
29287f06dSTakanori Watanabe  * adv_data.c
39287f06dSTakanori Watanabe  *
4*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
59287f06dSTakanori Watanabe 
69287f06dSTakanori Watanabe  * Copyright (c) 2020 Marc Veldman <marc@bumblingdork.com>
79287f06dSTakanori Watanabe  * All rights reserved.
89287f06dSTakanori Watanabe  *
99287f06dSTakanori Watanabe  * Redistribution and use in source and binary forms, with or without
109287f06dSTakanori Watanabe  * modification, are permitted provided that the following conditions
119287f06dSTakanori Watanabe  * are met:
129287f06dSTakanori Watanabe  * 1. Redistributions of source code must retain the above copyright
139287f06dSTakanori Watanabe  *    notice, this list of conditions and the following disclaimer.
149287f06dSTakanori Watanabe  * 2. Redistributions in binary form must reproduce the above copyright
159287f06dSTakanori Watanabe  *    notice, this list of conditions and the following disclaimer in the
169287f06dSTakanori Watanabe  *    documentation and/or other materials provided with the distribution.
179287f06dSTakanori Watanabe  *
189287f06dSTakanori Watanabe  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
199287f06dSTakanori Watanabe  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
209287f06dSTakanori Watanabe  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
219287f06dSTakanori Watanabe  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
229287f06dSTakanori Watanabe  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
239287f06dSTakanori Watanabe  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
249287f06dSTakanori Watanabe  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
259287f06dSTakanori Watanabe  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
269287f06dSTakanori Watanabe  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
279287f06dSTakanori Watanabe  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
289287f06dSTakanori Watanabe  * SUCH DAMAGE.
299287f06dSTakanori Watanabe  *
309287f06dSTakanori Watanabe  * $Id$
319287f06dSTakanori Watanabe  */
329287f06dSTakanori Watanabe 
339287f06dSTakanori Watanabe #include <sys/types.h>
349287f06dSTakanori Watanabe #include <stdio.h>
359287f06dSTakanori Watanabe #include <string.h>
369287f06dSTakanori Watanabe #include <uuid.h>
379287f06dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
389287f06dSTakanori Watanabe #include <bluetooth.h>
399287f06dSTakanori Watanabe #include "hccontrol.h"
409287f06dSTakanori Watanabe 
419287f06dSTakanori Watanabe static char* const adv_data2str(int len, uint8_t* data, char* buffer,
429287f06dSTakanori Watanabe 	int size);
439287f06dSTakanori Watanabe static char* const adv_name2str(int len, uint8_t* advdata, char* buffer,
449287f06dSTakanori Watanabe 	int size);
459287f06dSTakanori Watanabe static char* const adv_uuid2str(int datalen, uint8_t* data, char* buffer,
469287f06dSTakanori Watanabe 	int size);
479287f06dSTakanori Watanabe 
dump_adv_data(int len,uint8_t * advdata)489287f06dSTakanori Watanabe void dump_adv_data(int len, uint8_t* advdata)
499287f06dSTakanori Watanabe {
509287f06dSTakanori Watanabe 	int n=0;
519287f06dSTakanori Watanabe 	fprintf(stdout, "\tADV Data: ");
529287f06dSTakanori Watanabe 	for (n = 0; n < len+1; n++) {
539287f06dSTakanori Watanabe 		fprintf(stdout, "%02x ", advdata[n]);
549287f06dSTakanori Watanabe 	}
559287f06dSTakanori Watanabe 	fprintf(stdout, "\n");
569287f06dSTakanori Watanabe }
579287f06dSTakanori Watanabe 
print_adv_data(int len,uint8_t * advdata)589287f06dSTakanori Watanabe void print_adv_data(int len, uint8_t* advdata)
599287f06dSTakanori Watanabe {
609287f06dSTakanori Watanabe 	int n=0;
619287f06dSTakanori Watanabe 	while(n < len)
629287f06dSTakanori Watanabe 	{
639287f06dSTakanori Watanabe 		char buffer[2048];
649287f06dSTakanori Watanabe 		uint8_t datalen = advdata[n];
659287f06dSTakanori Watanabe 		uint8_t datatype = advdata[++n];
669287f06dSTakanori Watanabe 		/* Skip type */
679287f06dSTakanori Watanabe 		++n;
689287f06dSTakanori Watanabe 		datalen--;
699287f06dSTakanori Watanabe 		switch (datatype) {
709287f06dSTakanori Watanabe 			case 0x01:
719287f06dSTakanori Watanabe 				fprintf(stdout,
729287f06dSTakanori Watanabe 					"\tFlags: %s\n",
739287f06dSTakanori Watanabe 					adv_data2str(
749287f06dSTakanori Watanabe 						datalen,
759287f06dSTakanori Watanabe 						&advdata[n],
769287f06dSTakanori Watanabe 						buffer,
779287f06dSTakanori Watanabe 						sizeof(buffer)));
789287f06dSTakanori Watanabe 				break;
799287f06dSTakanori Watanabe 			case 0x02:
809287f06dSTakanori Watanabe 				fprintf(stdout,
819287f06dSTakanori Watanabe 					"\tIncomplete list of service"
829287f06dSTakanori Watanabe 					" class UUIDs (16-bit): %s\n",
839287f06dSTakanori Watanabe 					adv_data2str(
849287f06dSTakanori Watanabe 						datalen,
859287f06dSTakanori Watanabe 						&advdata[n],
869287f06dSTakanori Watanabe 						buffer,
879287f06dSTakanori Watanabe 						sizeof(buffer)));
889287f06dSTakanori Watanabe 				break;
899287f06dSTakanori Watanabe 			case 0x03:
909287f06dSTakanori Watanabe 				fprintf(stdout,
919287f06dSTakanori Watanabe 					"\tComplete list of service "
929287f06dSTakanori Watanabe 					"class UUIDs (16-bit): %s\n",
939287f06dSTakanori Watanabe 					adv_data2str(
949287f06dSTakanori Watanabe 						datalen,
959287f06dSTakanori Watanabe 						&advdata[n],
969287f06dSTakanori Watanabe 						buffer,
979287f06dSTakanori Watanabe 						sizeof(buffer)));
989287f06dSTakanori Watanabe 				break;
999287f06dSTakanori Watanabe 			case 0x07:
1009287f06dSTakanori Watanabe 				fprintf(stdout,
1019287f06dSTakanori Watanabe 					"\tComplete list of service "
1029287f06dSTakanori Watanabe 					"class UUIDs (128 bit): %s\n",
1039287f06dSTakanori Watanabe 					adv_uuid2str(
1049287f06dSTakanori Watanabe 						datalen,
1059287f06dSTakanori Watanabe 						&advdata[n],
1069287f06dSTakanori Watanabe 						buffer,
1079287f06dSTakanori Watanabe 						sizeof(buffer)));
1089287f06dSTakanori Watanabe 				break;
1099287f06dSTakanori Watanabe 			case 0x08:
1109287f06dSTakanori Watanabe 				fprintf(stdout,
1119287f06dSTakanori Watanabe 					"\tShortened local name: %s\n",
1129287f06dSTakanori Watanabe 					adv_name2str(
1139287f06dSTakanori Watanabe 						datalen,
1149287f06dSTakanori Watanabe 						&advdata[n],
1159287f06dSTakanori Watanabe 						buffer,
1169287f06dSTakanori Watanabe 						sizeof(buffer)));
1179287f06dSTakanori Watanabe 				break;
1189287f06dSTakanori Watanabe 			case 0x09:
1199287f06dSTakanori Watanabe 				fprintf(stdout,
1209287f06dSTakanori Watanabe 					"\tComplete local name: %s\n",
1219287f06dSTakanori Watanabe 					adv_name2str(
1229287f06dSTakanori Watanabe 						datalen,
1239287f06dSTakanori Watanabe 						&advdata[n],
1249287f06dSTakanori Watanabe 						buffer,
1259287f06dSTakanori Watanabe 						sizeof(buffer)));
1269287f06dSTakanori Watanabe 				break;
1279287f06dSTakanori Watanabe 			case 0x0a:
1289287f06dSTakanori Watanabe 				fprintf(stdout,
1299287f06dSTakanori Watanabe 					"\tTx Power level: %d dBm\n",
1309287f06dSTakanori Watanabe 						(int8_t)advdata[n]);
1319287f06dSTakanori Watanabe 				break;
1329287f06dSTakanori Watanabe 			case 0x0d:
1339287f06dSTakanori Watanabe 				fprintf(stdout,
1349287f06dSTakanori Watanabe 					"\tClass of device: %s\n",
1359287f06dSTakanori Watanabe 					adv_data2str(
1369287f06dSTakanori Watanabe 						datalen,
1379287f06dSTakanori Watanabe 						&advdata[n],
1389287f06dSTakanori Watanabe 						buffer,
1399287f06dSTakanori Watanabe 						sizeof(buffer)));
1409287f06dSTakanori Watanabe 				break;
1419287f06dSTakanori Watanabe 			case 0x16:
1429287f06dSTakanori Watanabe 				fprintf(stdout,
1439287f06dSTakanori Watanabe 					"\tService data: %s\n",
1449287f06dSTakanori Watanabe 					adv_data2str(
1459287f06dSTakanori Watanabe 						datalen,
1469287f06dSTakanori Watanabe 						&advdata[n],
1479287f06dSTakanori Watanabe 						buffer,
1489287f06dSTakanori Watanabe 						sizeof(buffer)));
1499287f06dSTakanori Watanabe 				break;
1509287f06dSTakanori Watanabe 			case 0x19:
1519287f06dSTakanori Watanabe 				fprintf(stdout,
1529287f06dSTakanori Watanabe 					"\tAppearance: %s\n",
1539287f06dSTakanori Watanabe 					adv_data2str(
1549287f06dSTakanori Watanabe 						datalen,
1559287f06dSTakanori Watanabe 						&advdata[n],
1569287f06dSTakanori Watanabe 						buffer,
1579287f06dSTakanori Watanabe 						sizeof(buffer)));
1589287f06dSTakanori Watanabe 				break;
1599287f06dSTakanori Watanabe 			case 0xff:
1609287f06dSTakanori Watanabe 				fprintf(stdout,
1619287f06dSTakanori Watanabe 					"\tManufacturer: %s\n",
1629287f06dSTakanori Watanabe 			       		hci_manufacturer2str(
1639287f06dSTakanori Watanabe 						advdata[n]|advdata[n+1]<<8));
1649287f06dSTakanori Watanabe 				fprintf(stdout,
1659287f06dSTakanori Watanabe 					"\tManufacturer specific data: %s\n",
1669287f06dSTakanori Watanabe 					adv_data2str(
1679287f06dSTakanori Watanabe 						datalen-2,
1689287f06dSTakanori Watanabe 						&advdata[n+2],
1699287f06dSTakanori Watanabe 						buffer,
1709287f06dSTakanori Watanabe 						sizeof(buffer)));
1719287f06dSTakanori Watanabe 				break;
1729287f06dSTakanori Watanabe 			default:
1739287f06dSTakanori Watanabe 				fprintf(stdout,
1749287f06dSTakanori Watanabe 					"\tUNKNOWN datatype: %02x data %s\n",
1759287f06dSTakanori Watanabe 					datatype,
1769287f06dSTakanori Watanabe 					adv_data2str(
1779287f06dSTakanori Watanabe 						datalen,
1789287f06dSTakanori Watanabe 						&advdata[n],
1799287f06dSTakanori Watanabe 						buffer,
1809287f06dSTakanori Watanabe 						sizeof(buffer)));
1819287f06dSTakanori Watanabe 		}
1829287f06dSTakanori Watanabe 		n += datalen;
1839287f06dSTakanori Watanabe 	}
1849287f06dSTakanori Watanabe }
1859287f06dSTakanori Watanabe 
adv_data2str(int datalen,uint8_t * data,char * buffer,int size)1869287f06dSTakanori Watanabe static char* const adv_data2str(int datalen, uint8_t* data, char* buffer,
1879287f06dSTakanori Watanabe 	int size)
1889287f06dSTakanori Watanabe {
1899287f06dSTakanori Watanabe         int i = 0;
1909287f06dSTakanori Watanabe 	char tmpbuf[5];
1919287f06dSTakanori Watanabe 
1929287f06dSTakanori Watanabe 	if (buffer == NULL)
1939287f06dSTakanori Watanabe 		return NULL;
1949287f06dSTakanori Watanabe 
1959287f06dSTakanori Watanabe 	memset(buffer, 0, size);
1969287f06dSTakanori Watanabe 
1979287f06dSTakanori Watanabe 	while(i < datalen) {
1989287f06dSTakanori Watanabe 		(void)snprintf(tmpbuf, sizeof(tmpbuf), "%02x ", data[i]);
1999287f06dSTakanori Watanabe 		/* Check if buffer is full */
2009287f06dSTakanori Watanabe 		if (strlcat(buffer, tmpbuf, size) > size)
2019287f06dSTakanori Watanabe 			break;
2029287f06dSTakanori Watanabe 		i++;
2039287f06dSTakanori Watanabe 	}
2049287f06dSTakanori Watanabe 	return buffer;
2059287f06dSTakanori Watanabe }
2069287f06dSTakanori Watanabe 
adv_name2str(int datalen,uint8_t * data,char * buffer,int size)2079287f06dSTakanori Watanabe static char* const adv_name2str(int datalen, uint8_t* data, char* buffer,
2089287f06dSTakanori Watanabe 	int size)
2099287f06dSTakanori Watanabe {
2109287f06dSTakanori Watanabe 	if (buffer == NULL)
2119287f06dSTakanori Watanabe 		return NULL;
2129287f06dSTakanori Watanabe 
2139287f06dSTakanori Watanabe 	memset(buffer, 0, size);
2149287f06dSTakanori Watanabe 
2159287f06dSTakanori Watanabe 	(void)strlcpy(buffer, (char*)data, datalen+1);
2169287f06dSTakanori Watanabe 	return buffer;
2179287f06dSTakanori Watanabe }
2189287f06dSTakanori Watanabe 
adv_uuid2str(int datalen,uint8_t * data,char * buffer,int size)2199287f06dSTakanori Watanabe static char* const adv_uuid2str(int datalen, uint8_t* data, char* buffer,
2209287f06dSTakanori Watanabe 	int size)
2219287f06dSTakanori Watanabe {
2229287f06dSTakanori Watanabe 	int i;
2239287f06dSTakanori Watanabe 	uuid_t uuid;
2249287f06dSTakanori Watanabe 	uint32_t ustatus;
2259287f06dSTakanori Watanabe 	char* tmpstr;
2269287f06dSTakanori Watanabe 
2279287f06dSTakanori Watanabe 	if (buffer == NULL)
2289287f06dSTakanori Watanabe 		return NULL;
2299287f06dSTakanori Watanabe 
2309287f06dSTakanori Watanabe 	memset(buffer, 0, size);
2319287f06dSTakanori Watanabe 	if (datalen < 16)
2329287f06dSTakanori Watanabe 		return buffer;
2339287f06dSTakanori Watanabe 	uuid.time_low = le32dec(data+12);
2349287f06dSTakanori Watanabe 	uuid.time_mid = le16dec(data+10);
2359287f06dSTakanori Watanabe 	uuid.time_hi_and_version = le16dec(data+8);
2369287f06dSTakanori Watanabe 	uuid.clock_seq_hi_and_reserved = data[7];
2379287f06dSTakanori Watanabe 	uuid.clock_seq_low = data[6];
2389287f06dSTakanori Watanabe 	for(i = 0; i < _UUID_NODE_LEN; i++){
2399287f06dSTakanori Watanabe 		uuid.node[i] = data[5 - i];
2409287f06dSTakanori Watanabe 	}
2419287f06dSTakanori Watanabe 	uuid_to_string(&uuid, &tmpstr, &ustatus);
2429287f06dSTakanori Watanabe 	if(ustatus == uuid_s_ok) {
2439287f06dSTakanori Watanabe 		strlcpy(buffer, tmpstr, size);
2449287f06dSTakanori Watanabe 	}
2459287f06dSTakanori Watanabe 	free(tmpstr);
2469287f06dSTakanori Watanabe 
2479287f06dSTakanori Watanabe 	return buffer;
2489287f06dSTakanori Watanabe }
249