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

📄 listattr.c

📁 蓝牙的各种编程接口和各种按理介绍,还有一些例子和说明
💻 C
字号:
/* * Here should go the usual boiler plate. * The stuff I've added if Copyright Jean Tourrilhes 2002. * As most of it is cut'n'paste from part of the SDP library, this code * is of course GPL... * Jean II *//************************** DOCUMENTATION **************************//* * This code use a "brute force" approach to parsing SDP records. * Instead of a top down approach in sdptool, which pick only know * attributes/members, we use a bottom up approach, printing every * single bit of the record and trying to associate its defintion * to it. * The advantage is that, of course, every attribute is displayed, * even unknow one. Also, the display is lower level, so much closer * to the raw data, so more useful for SDP debugging. * On the other hand, the display is much less user friendly... * * Why is this code here, and not in the libs, especially that we include * sdp_internal.h ? Well, I don't want to bother every single sdp app * (including sdpd) with lists of attribute. That seems unnecessary * overhead for a feature that is used only for debugging. * * Jean II *//***************************** INCLUDES *****************************/#include <stdio.h>#include "sdp.h"#include "sdp_lib.h"/* We need to access the low level structure of the attributes */#include "sdp_internal.h"/****************************** TYPES ******************************//* 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 */};/**************************** CONSTANTS ****************************//* 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/* Defintion of the optional arguments in protocol list */static struct member_def protocol_members[] = {  { "Protocol" },  { "Channel/Port" },  { "Version" },};/* Defintion of the optional arguments in profile list */static struct member_def profile_members[] = {  { "Profile" },  { "Version" },};/* Name of the various 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", NULL, 0 },  { 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 },};/* Same for the UUIDs. See BT assigned numbers */static struct uuid_def uuid16_names[] = {  /* -- Protocols -- */  { 0x1, "SDP (Service Discovery Protocol)", NULL, 0 },  { 0x2, "UDP", NULL, 0 },  { 0x3, "RFCOMM", NULL, 0 },  { 0x4, "TCP", NULL, 0 },  { 0x5, "TCS-BIN", NULL, 0 },  { 0x6, "TCS-AT", NULL, 0 },  { 0x8, "OBEX", NULL, 0 },  { 0x9, "IP", NULL, 0 },  { 0xA, "FTP", NULL, 0 },  { 0xC, "HTTP", NULL, 0 },  { 0xE, "WSP", NULL, 0 },  { 0xF, "BNEP (PAN/BNEP)", NULL, 0 },  { 0x10, "UPnP/ESDP", NULL, 0 },  { 0x11, "HIDP", NULL, 0 },  { 0x12, "HardcopyControlChannel", NULL, 0 },  { 0x14, "HardcopyDataChannel", NULL, 0 },  { 0x16, "HardcopyNotification", NULL, 0 },  { 0x17, "AVCTP", NULL, 0 },  { 0x19, "AVDTP", NULL, 0 },  { 0x1B, "CMTP", NULL, 0 },  { 0x1D, "UDI_C-Plane", NULL, 0 },  { 0x100, "L2CAP", NULL, 0 },  /* -- Services -- */  { 0x1000, "ServiceDiscoveryServerServiceClassID (SDP)",    sdp_attrib_names, sizeof(sdp_attrib_names)/sizeof(struct attrib_def) },  { 0x1001, "BrowseGroupDescriptorServiceClassID (SDP)",    browse_attrib_names,    sizeof(browse_attrib_names)/sizeof(struct attrib_def) },  { 0x1002, "PublicBrowseGroup (SDP)", 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 },  /* ... */  { 0x1115, "PANU (PAN/BNEP)", NULL, 0 },  { 0x1116, "NAP (PAN/BNEP)", NULL, 0 },  { 0x1117, "GN (PAN/BNEP)", NULL, 0 },  /* ... */  { 0x1128, "Common ISDN Access (CIP)", NULL, 0 },};const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def);/**************************** PROTOTYPES ****************************/void sdp_data_printf(sdp_data_t *, struct attrib_context *, int);/******************************* CODE *******************************//* ------------------------------------------------------------------- *//* * Parse a UUID. * The BT assigned numbers only list UUID16, so I'm not sure the * other types will ever get used... */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) {			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). */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->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:		if (member_name) {			printf("%.*s%s (Integer) : 0x%x\n",			       indent, indent_spaces,			       member_name, sdpdata->val.uint32);		} else {			printf("%.*sInteger : 0x%x\n", indent, indent_spaces,			       sdpdata->val.uint32);		}		break;	case SDP_UUID16:	case SDP_UUID32:	case SDP_UUID128:		//printf("%.*sUUID\n", indent, indent_spaces);		sdp_uuid_printf(&sdpdata->val.uuid, context, indent);		break;	case SDP_TEXT_STR8:	case SDP_TEXT_STR16:	case SDP_TEXT_STR32:		printf("%.*sText : \"%s\"\n", indent, indent_spaces,		       sdpdata->val.str);		break;	case SDP_URL_STR8:	case SDP_URL_STR16:	case SDP_URL_STR32:		printf("%.*sURL : %s\n", indent, indent_spaces,		       sdpdata->val.str);		break;	case SDP_SEQ8:	case SDP_SEQ16:	case SDP_SEQ32:		printf("%.*sData Sequence\n", indent, indent_spaces);		printf_dataseq(sdpdata->val.dataseq, context, indent);		break;	case SDP_ALT8:	case SDP_ALT16:	case SDP_ALT32:		printf("%.*sData Sequence Alternates\n", indent, indent_spaces);		/* Not tested, and I believe it's bogus - Jean II */		printf_dataseq(sdpdata->val.dataseq, context, indent);		break;	}}/* ------------------------------------------------------------------- *//* * Parse a single attribute. */void sdp_attr_printf_func(void *value, void *userData){	sdp_data_t *sdpdata = NULL;	uint16_t attrId;	struct service_context *service = (struct service_context *) userData;	struct attrib_context context;	struct attrib_def *attrDef = NULL;	int i;	sdpdata = (sdp_data_t *)value;	attrId = sdpdata->attrId;	/* Search amongst the generic attributes */	for (i = 0; i < attrib_max; i++)		if (attrib_names[i].num == attrId) {			attrDef = &attrib_names[i];			break;		}	/* Search amongst the specific attributes of this service */	if ((attrDef == NULL) &&	   (service->service != NULL) &&	   (service->service->attribs != NULL)) {		struct attrib_def *svc_attribs = service->service->attribs;		int		svc_attrib_max = service->service->attrib_max;		for (i = 0; i < svc_attrib_max; i++)			if (svc_attribs[i].num == attrId) {				attrDef = &svc_attribs[i];				break;			}	}	if (attrDef)		printf("Attribute Identifier : 0x%x - %s\n",		       attrId, attrDef->name);	else		printf("Attribute Identifier : 0x%x\n", attrId);	/* Build context */	context.service = service->service;	context.attrib = attrDef;	context.member_index = 0;	/* Parse attribute members */	if (sdpdata)		sdp_data_printf(sdpdata, &context, 2);	else		printf("  NULL value\n");	/* Update service */	service->service = context.service;}/* ------------------------------------------------------------------- *//* * Main entry point of this library. Parse a SDP record. * We assume the record has already been read, parsed and cached * locally. Jean II */void sdp_printf_service_attr(sdp_record_t *rec){	if (rec && rec->attrlist) {		struct service_context service = { NULL };		sdp_list_foreach(rec->attrlist, sdp_attr_printf_func, &service);	}}

⌨️ 快捷键说明

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