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