⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdptool.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2001-2002  Nokia Corporation *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com> *  Copyright (C) 2002-2008  Marcel Holtmann <marcel@holtmann.org> *  Copyright (C) 2002-2003  Stephen Crane <steve.crane@rococosoft.com> *  Copyright (C) 2002-2003  Jean Tourrilhes <jt@hpl.hp.com> * * *  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 <stdlib.h>#include <string.h>#include <getopt.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <bluetooth/sdp.h>#include <bluetooth/sdp_lib.h>#include <netinet/in.h>#include "sdp-xml.h"#ifndef APPLE_AGENT_SVCLASS_ID#define APPLE_AGENT_SVCLASS_ID 0x2112#endif#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, 0)) != -1)/* * Convert a string to a BDADDR, with a few "enhancements" - Jean II */static int estr2ba(char *str, bdaddr_t *ba){	/* Only trap "local", "any" is already dealt with */	if(!strcmp(str, "local")) {		bacpy(ba, BDADDR_LOCAL);		return 0;	}	return str2ba(str, ba);}#define DEFAULT_VIEW	0	/* Display only known attribute */#define TREE_VIEW	1	/* Display full attribute tree */#define RAW_VIEW	2	/* Display raw tree */#define XML_VIEW	3	/* Display xml tree *//* Pass args to the inquiry/search handler */struct search_context {	char		*svc;		/* Service */	uuid_t		group;		/* Browse group */	int		view;		/* View mode */	uint32_t	handle;		/* Service record handle */};typedef int (*handler_t)(bdaddr_t *bdaddr, struct search_context *arg);static char UUID_str[MAX_LEN_UUID_STR];static bdaddr_t interface;/* Definition of attribute members */struct member_def {	char *name;};/* Definition of an attribute */struct attrib_def {	int			num;		/* Numeric ID - 16 bits */	char			*name;		/* User readable name */	struct member_def	*members;	/* Definition of attribute args */	int			member_max;	/* Max of attribute arg definitions */};/* Definition of a service or protocol */struct uuid_def {	int			num;		/* Numeric ID - 16 bits */	char			*name;		/* User readable name */	struct attrib_def	*attribs;	/* Specific attribute definitions */	int			attrib_max;	/* Max of attribute definitions */};/* Context information about current attribute */struct attrib_context {	struct uuid_def		*service;	/* Service UUID, if known */	struct attrib_def	*attrib;	/* Description of the attribute */	int			member_index;	/* Index of current attribute member */};/* Context information about the whole service */struct service_context {	struct uuid_def		*service;	/* Service UUID, if known */};/* Allow us to do nice formatting of the lists */static char *indent_spaces = "                                         ";/* ID of the service attribute. * Most attributes after 0x200 are defined based on the service, so * we need to find what is the service (which is messy) - Jean II */#define SERVICE_ATTR	0x1/* Definition of the optional arguments in protocol list */static struct member_def protocol_members[] = {	{ "Protocol"		},	{ "Channel/Port"	},	{ "Version"		},};/* Definition of the optional arguments in profile list */static struct member_def profile_members[] = {	{ "Profile"	},	{ "Version"	},};/* Definition of the optional arguments in Language list */static struct member_def language_members[] = {	{ "Code ISO639"		},	{ "Encoding"		},	{ "Base Offset"		},};/* Name of the various common attributes. See BT assigned numbers */static struct attrib_def attrib_names[] = {	{ 0x0, "ServiceRecordHandle", NULL, 0 },	{ 0x1, "ServiceClassIDList", NULL, 0 },	{ 0x2, "ServiceRecordState", NULL, 0 },	{ 0x3, "ServiceID", NULL, 0 },	{ 0x4, "ProtocolDescriptorList",		protocol_members, sizeof(protocol_members)/sizeof(struct member_def) },	{ 0x5, "BrowseGroupList", NULL, 0 },	{ 0x6, "LanguageBaseAttributeIDList",		language_members, sizeof(language_members)/sizeof(struct member_def) },	{ 0x7, "ServiceInfoTimeToLive", NULL, 0 },	{ 0x8, "ServiceAvailability", NULL, 0 },	{ 0x9, "BluetoothProfileDescriptorList",		profile_members, sizeof(profile_members)/sizeof(struct member_def) },	{ 0xA, "DocumentationURL", NULL, 0 },	{ 0xB, "ClientExecutableURL", NULL, 0 },	{ 0xC, "IconURL", NULL, 0 },	{ 0xD, "AdditionalProtocolDescriptorLists", NULL, 0 },	/* Definitions after that are tricky (per profile or offset) */};const int attrib_max = sizeof(attrib_names)/sizeof(struct attrib_def);/* Name of the various SPD attributes. See BT assigned numbers */static struct attrib_def sdp_attrib_names[] = {	{ 0x200, "VersionNumberList", NULL, 0 },	{ 0x201, "ServiceDatabaseState", NULL, 0 },};/* Name of the various SPD attributes. See BT assigned numbers */static struct attrib_def browse_attrib_names[] = {	{ 0x200, "GroupID", NULL, 0 },};/* Name of the various Device ID attributes. See Device Id spec. */static struct attrib_def did_attrib_names[] = {	{ 0x200, "SpecificationID", NULL, 0 },	{ 0x201, "VendorID", NULL, 0 },	{ 0x202, "ProductID", NULL, 0 },	{ 0x203, "Version", NULL, 0 },	{ 0x204, "PrimaryRecord", NULL, 0 },	{ 0x205, "VendorIDSource", NULL, 0 },};/* Name of the various HID attributes. See HID spec. */static struct attrib_def hid_attrib_names[] = {	{ 0x200, "DeviceReleaseNum", NULL, 0 },	{ 0x201, "ParserVersion", NULL, 0 },	{ 0x202, "DeviceSubclass", NULL, 0 },	{ 0x203, "CountryCode", NULL, 0 },	{ 0x204, "VirtualCable", NULL, 0 },	{ 0x205, "ReconnectInitiate", NULL, 0 },	{ 0x206, "DescriptorList", NULL, 0 },	{ 0x207, "LangIDBaseList", NULL, 0 },	{ 0x208, "SDPDisable", NULL, 0 },	{ 0x209, "BatteryPower", NULL, 0 },	{ 0x20a, "RemoteWakeup", NULL, 0 },	{ 0x20b, "ProfileVersion", NULL, 0 },	{ 0x20c, "SupervisionTimeout", NULL, 0 },	{ 0x20d, "NormallyConnectable", NULL, 0 },	{ 0x20e, "BootDevice", NULL, 0 },};/* Name of the various PAN attributes. See BT assigned numbers *//* Note : those need to be double checked - Jean II */static struct attrib_def pan_attrib_names[] = {	{ 0x200, "IpSubnet", NULL, 0 },		/* Obsolete ??? */	{ 0x30A, "SecurityDescription", NULL, 0 },	{ 0x30B, "NetAccessType", NULL, 0 },	{ 0x30C, "MaxNetAccessrate", NULL, 0 },	{ 0x30D, "IPv4Subnet", NULL, 0 },	{ 0x30E, "IPv6Subnet", NULL, 0 },};/* Name of the various Generic-Audio attributes. See BT assigned numbers *//* Note : totally untested - Jean II */static struct attrib_def audio_attrib_names[] = {	{ 0x302, "Remote audio volume control", NULL, 0 },};/* Same for the UUIDs. See BT assigned numbers */static struct uuid_def uuid16_names[] = {	/* -- Protocols -- */	{ 0x0001, "SDP", NULL, 0 },	{ 0x0002, "UDP", NULL, 0 },	{ 0x0003, "RFCOMM", NULL, 0 },	{ 0x0004, "TCP", NULL, 0 },	{ 0x0005, "TCS-BIN", NULL, 0 },	{ 0x0006, "TCS-AT", NULL, 0 },	{ 0x0008, "OBEX", NULL, 0 },	{ 0x0009, "IP", NULL, 0 },	{ 0x000a, "FTP", NULL, 0 },	{ 0x000c, "HTTP", NULL, 0 },	{ 0x000e, "WSP", NULL, 0 },	{ 0x000f, "BNEP", NULL, 0 },	{ 0x0010, "UPnP/ESDP", NULL, 0 },	{ 0x0011, "HIDP", NULL, 0 },	{ 0x0012, "HardcopyControlChannel", NULL, 0 },	{ 0x0014, "HardcopyDataChannel", NULL, 0 },	{ 0x0016, "HardcopyNotification", NULL, 0 },	{ 0x0017, "AVCTP", NULL, 0 },	{ 0x0019, "AVDTP", NULL, 0 },	{ 0x001b, "CMTP", NULL, 0 },	{ 0x001d, "UDI_C-Plane", NULL, 0 },	{ 0x0100, "L2CAP", NULL, 0 },	/* -- Services -- */	{ 0x1000, "ServiceDiscoveryServerServiceClassID",		sdp_attrib_names, sizeof(sdp_attrib_names)/sizeof(struct attrib_def) },	{ 0x1001, "BrowseGroupDescriptorServiceClassID",		browse_attrib_names, sizeof(browse_attrib_names)/sizeof(struct attrib_def) },	{ 0x1002, "PublicBrowseGroup", NULL, 0 },	{ 0x1101, "SerialPort", NULL, 0 },	{ 0x1102, "LANAccessUsingPPP", NULL, 0 },	{ 0x1103, "DialupNetworking (DUN)", NULL, 0 },	{ 0x1104, "IrMCSync", NULL, 0 },	{ 0x1105, "OBEXObjectPush", NULL, 0 },	{ 0x1106, "OBEXFileTransfer", NULL, 0 },	{ 0x1107, "IrMCSyncCommand", NULL, 0 },	{ 0x1108, "Headset",		audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) },	{ 0x1109, "CordlessTelephony", NULL, 0 },	{ 0x110a, "AudioSource", NULL, 0 },	{ 0x110b, "AudioSink", NULL, 0 },	{ 0x110c, "RemoteControlTarget", NULL, 0 },	{ 0x110d, "AdvancedAudio", NULL, 0 },	{ 0x110e, "RemoteControl", NULL, 0 },	{ 0x110f, "VideoConferencing", NULL, 0 },	{ 0x1110, "Intercom", NULL, 0 },	{ 0x1111, "Fax", NULL, 0 },	{ 0x1112, "HeadsetAudioGateway", NULL, 0 },	{ 0x1113, "WAP", NULL, 0 },	{ 0x1114, "WAP Client", NULL, 0 },	{ 0x1115, "PANU (PAN/BNEP)",		pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) },	{ 0x1116, "NAP (PAN/BNEP)",		pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) },	{ 0x1117, "GN (PAN/BNEP)",		pan_attrib_names, sizeof(pan_attrib_names)/sizeof(struct attrib_def) },	{ 0x1118, "DirectPrinting (BPP)", NULL, 0 },	{ 0x1119, "ReferencePrinting (BPP)", NULL, 0 },	{ 0x111a, "Imaging (BIP)", NULL, 0 },	{ 0x111b, "ImagingResponder (BIP)", NULL, 0 },	{ 0x111c, "ImagingAutomaticArchive (BIP)", NULL, 0 },	{ 0x111d, "ImagingReferencedObjects (BIP)", NULL, 0 },	{ 0x111e, "Handsfree", NULL, 0 },	{ 0x111f, "HandsfreeAudioGateway", NULL, 0 },	{ 0x1120, "DirectPrintingReferenceObjectsService (BPP)", NULL, 0 },	{ 0x1121, "ReflectedUI (BPP)", NULL, 0 },	{ 0x1122, "BasicPrinting (BPP)", NULL, 0 },	{ 0x1123, "PrintingStatus (BPP)", NULL, 0 },	{ 0x1124, "HumanInterfaceDeviceService (HID)",		hid_attrib_names, sizeof(hid_attrib_names)/sizeof(struct attrib_def) },	{ 0x1125, "HardcopyCableReplacement (HCR)", NULL, 0 },	{ 0x1126, "HCR_Print (HCR)", NULL, 0 },	{ 0x1127, "HCR_Scan (HCR)", NULL, 0 },	{ 0x1128, "Common ISDN Access (CIP)", NULL, 0 },	{ 0x1129, "VideoConferencingGW (VCP)", NULL, 0 },	{ 0x112a, "UDI-MT", NULL, 0 },	{ 0x112b, "UDI-TA", NULL, 0 },	{ 0x112c, "Audio/Video", NULL, 0 },	{ 0x112d, "SIM Access (SAP)", NULL, 0 },	{ 0x112e, "Phonebook Access (PBAP) - PCE", NULL, 0 },	{ 0x112f, "Phonebook Access (PBAP) - PSE", NULL, 0 },	{ 0x1130, "Phonebook Access (PBAP)", NULL, 0 },	/* ... */	{ 0x1200, "PnPInformation",		did_attrib_names, sizeof(did_attrib_names)/sizeof(struct attrib_def) },	{ 0x1201, "GenericNetworking", NULL, 0 },	{ 0x1202, "GenericFileTransfer", NULL, 0 },	{ 0x1203, "GenericAudio",		audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) },	{ 0x1204, "GenericTelephony", NULL, 0 },	/* ... */	{ 0x1303, "VideoSource", NULL, 0 },	{ 0x1304, "VideoSink", NULL, 0 },	{ 0x1305, "VideoDistribution", NULL, 0 },	{ 0x1400, "MDP", NULL, 0 },	{ 0x1401, "MDPSource", NULL, 0 },	{ 0x1402, "MDPSink", NULL, 0 },	{ 0x2112, "AppleAgent", NULL, 0 },};static const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def);static void sdp_data_printf(sdp_data_t *, struct attrib_context *, int);/* * Parse a UUID. * The BT assigned numbers only list UUID16, so I'm not sure the * other types will ever get used... */static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int indent){	if (uuid) {		if (uuid->type == SDP_UUID16) {			uint16_t uuidNum = uuid->value.uuid16;			struct uuid_def *uuidDef = NULL;			int i;			for (i = 0; i < uuid16_max; i++)				if (uuid16_names[i].num == uuidNum) {					uuidDef = &uuid16_names[i];					break;				}			/* Check if it's the service attribute */			if (context->attrib && context->attrib->num == SERVICE_ATTR) {				/* We got the service ID !!! */				context->service = uuidDef;			}			if (uuidDef)				printf("%.*sUUID16 : 0x%.4x - %s\n",					indent, indent_spaces, uuidNum, uuidDef->name);			else				printf("%.*sUUID16 : 0x%.4x\n",					indent, indent_spaces, uuidNum);		} else if (uuid->type == SDP_UUID32) {			struct uuid_def *uuidDef = NULL;			int i;			if (!(uuid->value.uuid32 & 0xffff0000)) {				uint16_t uuidNum = uuid->value.uuid32;				for (i = 0; i < uuid16_max; i++)					if (uuid16_names[i].num == uuidNum) {						uuidDef = &uuid16_names[i];						break;					}			}			if (uuidDef)				printf("%.*sUUID32 : 0x%.8x - %s\n",					indent, indent_spaces, uuid->value.uuid32, uuidDef->name);			else				printf("%.*sUUID32 : 0x%.8x\n",					indent, indent_spaces, uuid->value.uuid32);		} else if (uuid->type == SDP_UUID128) {			unsigned int data0;			unsigned short data1;			unsigned short data2;			unsigned short data3;			unsigned int data4;			unsigned short data5;			memcpy(&data0, &uuid->value.uuid128.data[0], 4);			memcpy(&data1, &uuid->value.uuid128.data[4], 2);			memcpy(&data2, &uuid->value.uuid128.data[6], 2);			memcpy(&data3, &uuid->value.uuid128.data[8], 2);			memcpy(&data4, &uuid->value.uuid128.data[10], 4);			memcpy(&data5, &uuid->value.uuid128.data[14], 2);			printf("%.*sUUID128 : 0x%.8x-%.4x-%.4x-%.4x-%.8x-%.4x\n",				indent, indent_spaces,				ntohl(data0), ntohs(data1), ntohs(data2),				ntohs(data3), ntohl(data4), ntohs(data5));		} else			printf("%.*sEnum type of UUID not set\n",				indent, indent_spaces);	} else		printf("%.*sNull passed to print UUID\n",				indent, indent_spaces);}/* * Parse a sequence of data elements (i.e. a list) */static void printf_dataseq(sdp_data_t * pData, struct attrib_context *context, int indent){	sdp_data_t *sdpdata = NULL;	sdpdata = pData;	if (sdpdata) {		context->member_index = 0;		do {			sdp_data_printf(sdpdata, context, indent + 2);			sdpdata = sdpdata->next;			context->member_index++;		} while (sdpdata);	} else {		printf("%.*sBroken dataseq link\n", indent, indent_spaces);	}}/* * Parse a single data element (either in the attribute or in a data * sequence). */static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, int indent){	char *member_name = NULL;	/* Find member name. Almost black magic ;-) */	if (context && context->attrib && context->attrib->members &&			context->member_index < context->attrib->member_max) {		member_name = context->attrib->members[context->member_index].name;	}	switch (sdpdata->dtd) {	case SDP_DATA_NIL:		printf("%.*sNil\n", indent, indent_spaces);		break;	case SDP_BOOL:	case SDP_UINT8:	case SDP_UINT16:	case SDP_UINT32:	case SDP_UINT64:	case SDP_UINT128:	case SDP_INT8:	case SDP_INT16:	case SDP_INT32:	case SDP_INT64:	case SDP_INT128:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -