From 280cca9f112cbc2f86a9b7653a2ad003769e4fcb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 31 Mar 2004 20:14:52 +0000 Subject: Add sdptool utility --- tools/sdptool.c | 2072 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2072 insertions(+) create mode 100644 tools/sdptool.c (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c new file mode 100644 index 00000000..5340ab1b --- /dev/null +++ b/tools/sdptool.c @@ -0,0 +1,2072 @@ +/* + Service Discovery Protocol (SDP) + Copyright (C) 2002 Maxim Krasnyansky + Copyright (C) 2002 Stephen Crane + + Based on original SDP implementation by Nokia Corporation. + Copyright (C) 2001,2002 Nokia Corporation. + Original author Guruprasad Krishnamurthy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM, + OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER + RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE + USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS, + TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED. +*/ + +/* + * $Id$ + */ + +#include +#include +#include +#include + +#include +#include +#include + +#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 + */ +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); +} + +/* Pass args to the inquiry/search handler */ +struct search_context { + char *svc; /* Service */ + uuid_t group; /* Browse group */ + int tree; /* Display full attribute tree */ + 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 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 -- */ + { 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 }, + { 0x1108, "Headset", + audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) }, + { 0x1109, "CordlessTelephony", 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 }, + /* ... */ + { 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)", NULL, 0 }, + { 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 }, + /* ... */ + { 0x1200, "PnPInformation", NULL, 0 }, + { 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 }, +}; + +const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def); + +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... + */ +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); + 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); + } +} + +/* + * Set attributes with single values in SDP record + * Jean II + */ +int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, char *value) +{ + sdp_list_t *attrid_list; + uint32_t range = 0x0000ffff; + sdp_record_t *rec; + + /* Get the old SDP record */ + attrid_list = sdp_list_append(NULL, &range); + rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attrid_list); + + if (!rec) { + printf("Service get request failed.\n"); + return -1; + } + + /* Check the type of attribute */ + if (!strncasecmp(value, "u0x", 3)) { + /* UUID16 */ + uint16_t value_int = 0; + uuid_t value_uuid; + value_int = strtoul(value + 3, NULL, 16); + sdp_uuid16_create(&value_uuid, value_int); + printf("Adding attrib 0x%X uuid16 0x%X to record 0x%X\n", + attrib, value_int, handle); + + sdp_attr_add_new(rec, attrib, SDP_UUID16, &value_uuid.value.uuid16); + } else if (!strncasecmp(value, "0x", 2)) { + /* Int */ + uint32_t value_int; + value_int = strtoul(value + 2, NULL, 16); + printf("Adding attrib 0x%X int 0x%X to record 0x%X\n", + attrib, value_int, handle); + + sdp_attr_add_new(rec, attrib, SDP_UINT32, &value_int); + } else { + /* String */ + printf("Adding attrib 0x%X string \"%s\" to record 0x%X\n", + attrib, value, handle); + + /* Add/Update our attribute to the record */ + sdp_attr_add_new(rec, attrib, SDP_TEXT_STR8, value); + } + + /* Update on the server */ + if (sdp_record_update(sess, rec)) { + printf("Service Record update failed (%d).\n", errno); + return -1; + } + return 0; +} + +static struct option set_options[] = { + {"help", 0,0, 'h'}, + {0, 0, 0, 0} +}; + +static char *set_help = + "Usage:\n" + "\tget record_handle attrib_id attrib_value\n"; + +/* + * Add an attribute to an existing SDP record on the local SDP server + */ +int cmd_setattr(int argc, char **argv) +{ + int opt, status; + uint32_t handle; + uint16_t attrib; + sdp_session_t *sess; + + for_each_opt(opt, set_options, NULL) { + switch(opt) { + default: + printf(set_help); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc < 3) { + printf(set_help); + return -1; + } + + /* Convert command line args */ + handle = strtoul(argv[0], NULL, 16); + attrib = strtoul(argv[1], NULL, 16); + + /* Do it */ + sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); + if (!sess) + return -1; + status = set_attrib(sess, handle, attrib, argv[2]); + sdp_close(sess); + return status; +} + +/* + * We do only simple data sequences. Sequence of sequences is a pain ;-) + * Jean II + */ +int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attrib, int argc, char **argv) +{ + sdp_list_t *attrid_list; + uint32_t range = 0x0000ffff; + sdp_record_t *rec; + sdp_data_t *pSequenceHolder = NULL; + void **dtdArray; + void **valueArray; + void **allocArray; + uint8_t uuid16 = SDP_UUID16; + uint8_t uint32 = SDP_UINT32; + uint8_t str8 = SDP_TEXT_STR8; + int i; + + /* Get the old SDP record */ + attrid_list = sdp_list_append(NULL, &range); + rec = sdp_service_attr_req(session, handle, SDP_ATTR_REQ_RANGE, attrid_list); + + if (!rec) { + printf("Service get request failed.\n"); + return -1; + } + + /* Create arrays */ + dtdArray = (void **)malloc(argc * sizeof(void *)); + valueArray = (void **)malloc(argc * sizeof(void *)); + allocArray = (void **)malloc(argc * sizeof(void *)); + + /* Loop on all args, add them in arrays */ + for (i = 0; i < argc; i++) { + /* Check the type of attribute */ + if (!strncasecmp(argv[i], "u0x", 3)) { + /* UUID16 */ + uint16_t value_int = strtoul((argv[i]) + 3, NULL, 16); + uuid_t *value_uuid = (uuid_t *)malloc(sizeof(uuid_t)); + allocArray[i] = value_uuid; + sdp_uuid16_create(value_uuid, value_int); + + printf("Adding uuid16 0x%X to record 0x%X\n", + value_int, handle); + dtdArray[i] = &uuid16; + valueArray[i] = &value_uuid->value.uuid16; + } else if (!strncasecmp(argv[i], "0x", 2)) { + /* Int */ + uint32_t *value_int = (int *)malloc(sizeof(int)); + allocArray[i] = value_int; + *value_int = strtoul((argv[i]) + 2, NULL, 16); + + printf("Adding int 0x%X to record 0x%X\n", + *value_int, handle); + dtdArray[i] = &uint32; + valueArray[i] = value_int; + } else { + /* String */ + printf("Adding string \"%s\" to record 0x%X\n", + argv[i], handle); + dtdArray[i] = &str8; + valueArray[i] = argv[i]; + } + } + + /* Add this sequence to the attrib list */ + pSequenceHolder = sdp_seq_alloc(dtdArray, valueArray, argc); + if (pSequenceHolder) { + sdp_attr_replace(rec, attrib, pSequenceHolder); + + /* Update on the server */ + if (sdp_record_update(session, rec)) { + printf("Service Record update failed (%d).\n", errno); + return -1; + } + } else { + printf("Failed to create pSequenceHolder\n"); + } + + /* Cleanup */ + for (i = 0; i < argc; i++) + free(allocArray[i]); + free(dtdArray); + free(valueArray); + + return 0; +} + +static struct option seq_options[] = { + {"help", 0,0, 'h'}, + {0, 0, 0, 0} +}; + +static char *seq_help = + "Usage:\n" + "\tget record_handle attrib_id attrib_values\n"; + +/* + * Add an attribute sequence to an existing SDP record + * on the local SDP server + */ +int cmd_setseq(int argc, char **argv) +{ + int opt, status; + uint32_t handle; + uint16_t attrib; + sdp_session_t *sess; + + for_each_opt(opt, seq_options, NULL) { + switch(opt) { + default: + printf(seq_help); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc < 3) { + printf(seq_help); + return -1; + } + + /* Convert command line args */ + handle = strtoul(argv[0], NULL, 16); + attrib = strtoul(argv[1], NULL, 16); + + argc -= 2; + argv += 2; + + /* Do it */ + sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); + if (!sess) + return -1; + status = set_attribseq(sess, handle, attrib, argc, argv); + sdp_close(sess); + return status; +} + +static void print_service_class(void *value, void *userData) +{ + char ServiceClassUUID_str[MAX_LEN_SERVICECLASS_UUID_STR]; + uuid_t *uuid = (uuid_t *)value; + + sdp_uuid2strn(uuid, UUID_str, MAX_LEN_UUID_STR); + sdp_svclass_uuid2strn(uuid, ServiceClassUUID_str, MAX_LEN_SERVICECLASS_UUID_STR); + printf(" \"%s\" (0x%s)\n", ServiceClassUUID_str, UUID_str); +} + +static void print_service_desc(void *value, void *user) +{ + char str[MAX_LEN_PROTOCOL_UUID_STR]; + sdp_data_t *p = (sdp_data_t *)value, *s; + int i = 0, proto = 0; + + for (; p; p = p->next, i++) { + switch (p->dtd) { + case SDP_UUID16: + case SDP_UUID32: + case SDP_UUID128: + sdp_uuid2strn(&p->val.uuid, UUID_str, MAX_LEN_UUID_STR); + sdp_proto_uuid2strn(&p->val.uuid, str, sizeof(str)); + proto = sdp_uuid_to_proto(&p->val.uuid); + printf(" \"%s\" (0x%s)\n", str, UUID_str); + break; + case SDP_UINT8: + if (proto == RFCOMM_UUID) + printf(" Channel: %d\n", p->val.uint8); + else + printf(" uint8: 0x%x\n", p->val.uint8); + break; + case SDP_UINT16: + if (proto == L2CAP_UUID) { + if (i == 1) + printf(" PSM: %d\n", p->val.uint16); + else + printf(" Version: 0x%04x\n", p->val.uint16); + } else if (proto == BNEP_UUID) + if (i == 1) + printf(" Version: 0x%04x\n", p->val.uint16); + else + printf(" uint16: 0x%x\n", p->val.uint16); + else + printf(" uint16: 0x%x\n", p->val.uint16); + break; + case SDP_SEQ16: + printf(" SEQ16:"); + for (s = p->val.dataseq; s; s = s->next) + printf(" %x", s->val.uint16); + printf("\n"); + break; + case SDP_SEQ8: + printf(" SEQ8:"); + for (s = p->val.dataseq; s; s = s->next) + printf(" %x", s->val.uint8); + printf("\n"); + break; + default: + printf(" FIXME: dtd=0%x\n", p->dtd); + break; + } + } +} + +void print_lang_attr(void *value, void *user) +{ + sdp_lang_attr_t *lang = (sdp_lang_attr_t *)value; + printf(" code_ISO639: 0x%02x\n", lang->code_ISO639); + printf(" encoding: 0x%02x\n", lang->encoding); + printf(" base_offset: 0x%02x\n", lang->base_offset); +} + +void print_access_protos(value, userData) +{ + sdp_list_t *protDescSeq = (sdp_list_t *)value; + sdp_list_foreach(protDescSeq, print_service_desc, 0); +} + +void print_profile_desc(void *value, void *userData) +{ + sdp_profile_desc_t *desc = (sdp_profile_desc_t *)value; + char str[MAX_LEN_PROFILEDESCRIPTOR_UUID_STR]; + + sdp_uuid2strn(&desc->uuid, UUID_str, MAX_LEN_UUID_STR); + sdp_profile_uuid2strn(&desc->uuid, str, MAX_LEN_PROFILEDESCRIPTOR_UUID_STR); + + printf(" \"%s\" (0x%s)\n", str, UUID_str); + if (desc->version) + printf(" Version: 0x%04x\n", desc->version); +} + +/* + * Parse a SDP record in user friendly form. + */ +void print_service_attr(sdp_record_t *rec) +{ + sdp_list_t *list = 0, *proto = 0; + + sdp_record_print(rec); + + printf("Service RecHandle: 0x%x\n", rec->handle); + + if (sdp_get_service_classes(rec, &list) == 0) { + printf("Service Class ID List:\n"); + sdp_list_foreach(list, print_service_class, 0); + sdp_list_free(list, free); + } + if (sdp_get_access_protos(rec, &proto) == 0) { + printf("Protocol Descriptor List:\n"); + sdp_list_foreach(proto, print_access_protos, 0); + sdp_list_free(proto, (sdp_free_func_t)sdp_data_free); + } + if (sdp_get_lang_attr(rec, &list) == 0) { + printf("Language Base Attr List:\n"); + sdp_list_foreach(list, print_lang_attr, 0); + sdp_list_free(list, free); + } + if (sdp_get_profile_descs(rec, &list) == 0) { + printf("Profile Descriptor List:\n"); + sdp_list_foreach(list, print_profile_desc, 0); + sdp_list_free(list, free); + } +} + +/* + * Support for Service (de)registration + */ +typedef struct { + char *name; + char *provider; + char *desc; + + unsigned int class; + unsigned int profile; + unsigned int channel; +} svc_info_t; + +static int add_sp(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto; + uuid_t root_uuid, sp_uuid, l2cap, rfcomm; + sdp_profile_desc_t profile; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel: 1; + sdp_data_t *channel; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + sdp_list_free(root, 0); + + sdp_uuid16_create(&sp_uuid, SERIAL_PORT_SVCLASS_ID); + svclass_id = sdp_list_append(0, &sp_uuid); + sdp_set_service_classes(&record, svclass_id); + sdp_list_free(svclass_id, 0); + + sdp_uuid16_create(&profile.uuid, SERIAL_PORT_PROFILE_ID); + profile.version = 0x0100; + profiles = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, profiles); + sdp_list_free(profiles, 0); + + sdp_uuid16_create(&l2cap, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Serial Port", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("Serial Port service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_dun(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root, *aproto; + uuid_t rootu, dun, gn, l2cap, rfcomm; + sdp_profile_desc_t profile; + sdp_list_t *proto[2]; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel: 1; + sdp_data_t *channel; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &rootu); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&dun, DIALUP_NET_SVCLASS_ID); + svclass_id = sdp_list_append(0, &dun); + sdp_uuid16_create(&gn, GENERIC_NETWORKING_SVCLASS_ID); + svclass_id = sdp_list_append(svclass_id, &gn); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile.uuid, DIALUP_NET_PROFILE_ID); + profile.version = 0x0100; + pfseq = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("Dial-Up Networking service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_lan(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; + sdp_profile_desc_t profile; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel: 2; + sdp_data_t *channel; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&svclass_uuid, LAN_ACCESS_SVCLASS_ID); + svclass_id = sdp_list_append(0, &svclass_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile.uuid, LAN_ACCESS_PROFILE_ID); + profile.version = 0x0100; + pfseq = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("LAN Access service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + + +static int add_headset(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; + sdp_profile_desc_t profile; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel: 5; + sdp_data_t *channel; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&svclass_uuid, HEADSET_SVCLASS_ID); + svclass_id = sdp_list_append(0, &svclass_uuid); + sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); + svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID); + profile.version = 0x0100; + pfseq = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Headset", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("Headset service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_handsfree(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; + sdp_profile_desc_t profile; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel: 3; + uint16_t u16 = 0x31; + sdp_data_t *channel, *features; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&svclass_uuid, HANDSFREE_SVCLASS_ID); + svclass_id = sdp_list_append(0, &svclass_uuid); + sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); + svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID); + profile.version = 0x0101; + pfseq = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + features = sdp_data_alloc(SDP_UINT16, &u16); + sdp_attr_add(&record, SDP_SUPPORTED_FEATURES, features); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("Handsfree service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + + +static int add_fax(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, fax_uuid, tel_uuid, l2cap_uuid, rfcomm_uuid; + sdp_profile_desc_t profile; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel: 3; + sdp_data_t *channel; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&fax_uuid, FAX_SVCLASS_ID); + svclass_id = sdp_list_append(0, &fax_uuid); + sdp_uuid16_create(&tel_uuid, GENERIC_TELEPHONY_SVCLASS_ID); + svclass_id = sdp_list_append(svclass_id, &tel_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile.uuid, FAX_PROFILE_ID); + profile.version = 0x0100; + pfseq = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Fax", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("Fax service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_opush(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[3]; + sdp_record_t record; + uint8_t chan = si->channel? si->channel: 4; + sdp_data_t *channel; + uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; + //uint8_t formats[] = { 0xff }; + void *dtds[sizeof(formats)], *values[sizeof(formats)]; + int i; + uint8_t dtd = SDP_UINT8; + sdp_data_t *sflist; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&opush_uuid, OBEX_OBJPUSH_SVCLASS_ID); + svclass_id = sdp_list_append(0, &opush_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, OBEX_OBJPUSH_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &chan); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + sdp_uuid16_create(&obex_uuid, OBEX_UUID); + proto[2] = sdp_list_append(0, &obex_uuid); + apseq = sdp_list_append(apseq, proto[2]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + for (i = 0; i < sizeof(formats); i++) { + dtds[i] = &dtd; + values[i] = &formats[i]; + } + sflist = sdp_seq_alloc(dtds, values, sizeof(formats)); + sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FORMATS_LIST, sflist); + + sdp_set_info_attr(&record, "OBEX Object Push", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("OBEX Object Push service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(proto[2], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_file_trans(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, ftrn_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[3]; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel: 4; + sdp_data_t *channel; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&ftrn_uuid, OBEX_FILETRANS_SVCLASS_ID); + svclass_id = sdp_list_append(0, &ftrn_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, OBEX_FILETRANS_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + sdp_uuid16_create(&obex_uuid, OBEX_UUID); + proto[2] = sdp_list_append(0, &obex_uuid); + apseq = sdp_list_append(apseq, proto[2]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("OBEX File Transfer service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(proto[2], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_nap(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint16_t lp = 0x000f, ver = 0x0100; + sdp_data_t *psm, *version; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&ftrn_uuid, NAP_SVCLASS_ID); + svclass_id = sdp_list_append(0, &ftrn_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, NAP_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + psm = sdp_data_alloc(SDP_UINT16, &lp); + proto[0] = sdp_list_append(proto[0], psm); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&bnep_uuid, BNEP_UUID); + proto[1] = sdp_list_append(0, &bnep_uuid); + version = sdp_data_alloc(SDP_UINT16, &ver); + proto[1] = sdp_list_append(proto[1], version); + + { + uint16_t ptype[4] = { 0x0010, 0x0020, 0x0030, 0x0040 }; + sdp_data_t *head, *pseq; + int p; + + for (p = 0, head = NULL; p < 4; p++) { + sdp_data_t *data = sdp_data_alloc(SDP_UINT16, &ptype[p]); + head = sdp_seq_append(head, data); + } + pseq = sdp_data_alloc(SDP_SEQ16, head); + proto[1] = sdp_list_append(proto[1], pseq); + } + + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Network Access Point Service", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("NAP service registered\n"); +end: + sdp_data_free(version); + sdp_data_free(psm); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_gn(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint16_t lp = 0x000f, ver = 0x0100; + sdp_data_t *psm, *version; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&ftrn_uuid, GN_SVCLASS_ID); + svclass_id = sdp_list_append(0, &ftrn_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, GN_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + psm = sdp_data_alloc(SDP_UINT16, &lp); + proto[0] = sdp_list_append(proto[0], psm); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&bnep_uuid, BNEP_UUID); + proto[1] = sdp_list_append(0, &bnep_uuid); + version = sdp_data_alloc(SDP_UINT16, &ver); + proto[1] = sdp_list_append(proto[1], version); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Group Network Service", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("GN service registered\n"); +end: + sdp_data_free(version); + sdp_data_free(psm); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_hid(sdp_session_t *sess, svc_info_t *si) +{ + return -1; +} + +static int add_cip(sdp_session_t *sess, svc_info_t *si) +{ + return -1; +} + +static int add_ctp(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, l2cap, tcsbin, ctp; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint8_t netid = 0x02; // 0x01-0x07 cf. p120 profile document + sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&ctp, CORDLESS_TELEPHONY_SVCLASS_ID); + svclass_id = sdp_list_append(0, &ctp); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, CORDLESS_TELEPHONY_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&tcsbin, TCS_BIN_UUID); + proto[1] = sdp_list_append(0, &tcsbin); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_attr_add(&record, SDP_EXTERNAL_NETWORK, network); + + sdp_set_info_attr(&record, "Cordless Telephony", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("CTP service registered\n"); +end: + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + sdp_data_free(network); + return ret; +} + +struct { + char *name; + uint16_t class; + int (*add)(sdp_session_t *sess, svc_info_t *si); +} service[] = { + { "SP", SERIAL_PORT_SVCLASS_ID, add_sp }, + { "DUN", DIALUP_NET_SVCLASS_ID, add_dun }, + { "LAN", LAN_ACCESS_SVCLASS_ID, add_lan }, + { "FAX", FAX_SVCLASS_ID, add_fax }, + { "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush }, + { "FTRN", OBEX_FILETRANS_SVCLASS_ID, add_file_trans }, + + { "HS", HEADSET_SVCLASS_ID, add_headset }, + { "HF", HANDSFREE_SVCLASS_ID, add_handsfree }, + + { "NAP", NAP_SVCLASS_ID, add_nap }, + { "GN", GN_SVCLASS_ID, add_gn }, + + { "HID", HID_SVCLASS_ID, add_hid }, + { "CIP", CIP_SVCLASS_ID, add_cip }, + { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, + + { 0 } +}; + +/* Add local service */ +int add_service(bdaddr_t *bdaddr, svc_info_t *si) +{ + int i; + sdp_session_t *sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); + + if (!sess) + return -1; + if (si->name) + for (i=0; service[i].name; i++) + if (!strcasecmp(service[i].name, si->name)) { + int ret = service[i].add(sess, si); + free(si->name); + sdp_close(sess); + return ret; + } + printf("Unknown service name: %s\n", si->name); + free(si->name); + sdp_close(sess); + return -1; +} + +static struct option add_options[] = { + {"help", 0,0, 'h'}, + {"channel", 1,0, 'c'}, + {0, 0, 0, 0} +}; + +static char *add_help = + "Usage:\n" + "\tadd [--channel=CHAN] service\n"; + +int cmd_add(int argc, char **argv) +{ + svc_info_t si; + int opt; + + memset(&si, 0, sizeof(si)); + for_each_opt(opt, add_options, 0) { + switch(opt) { + case 'c': + si.channel = atoi(optarg); + break; + default: + printf(add_help); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { + printf(add_help); + return -1; + } + + si.name = strdup(argv[0]); + return add_service(0, &si); +} + +/* Delete local service */ +int del_service(bdaddr_t *bdaddr, void *arg) +{ + uint32_t handle, range = 0x0000ffff; + sdp_list_t *attr; + sdp_session_t *sess; + sdp_record_t *rec; + + if (!arg) { + printf("Record handle was not specified.\n"); + return -1; + } + sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); + if (!sess) { + printf("No local SDP server!\n"); + return -1; + } + handle = strtoul((char *)arg, 0, 16); + attr = sdp_list_append(0, &range); + rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr); + sdp_list_free(attr, 0); + if (!rec) { + printf("Service Record not found.\n"); + sdp_close(sess); + return -1; + } + if (sdp_record_unregister(sess, rec)) { + printf("Failed to unregister service record: %s\n", strerror(errno)); + sdp_close(sess); + return -1; + } + printf("Service Record deleted.\n"); + sdp_close(sess); + return 0; +} + +static struct option del_options[] = { + {"help", 0,0, 'h'}, + {0, 0, 0, 0} +}; + +static char *del_help = + "Usage:\n" + "\tdel record_handle\n"; + +int cmd_del(int argc, char **argv) +{ + int opt; + + for_each_opt(opt, del_options, 0) { + switch(opt) { + default: + printf(del_help); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { + printf(del_help); + return -1; + } + return del_service(0, argv[0]); +} + +/* + * Perform an inquiry and search/browse all peer found. + */ +static void inquiry(handler_t handler, void *arg) +{ + inquiry_info ii[20]; + uint8_t count = 0; + int i; + + printf("Inquiring ...\n"); + if (sdp_general_inquiry(ii, 20, 8, &count) < 0) { + printf("Inquiry failed\n"); + return; + } + for (i=0; isvc) + printf("Searching for %s on %s ...\n", context->svc, str); + else + printf("Browsing %s ...\n", str); + + attrid = sdp_list_append(0, &range); + search = sdp_list_append(0, &context->group); + if (sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_RANGE, attrid, &seq)) { + printf("Service Search failed: %s\n", strerror(errno)); + sdp_close(sess); + return -1; + } + sdp_list_free(attrid, 0); + sdp_list_free(search, 0); + + for (; seq; seq = next) { + sdp_record_t *rec = (sdp_record_t *) seq->data; + struct search_context sub_context; + + if (context->tree) { + /* Display full tree */ + sdp_printf_service_attr(rec); + } else { + /* Display user friendly form */ + print_service_attr(rec); + } + printf("\n"); + + if (sdp_get_group_id(rec, &sub_context.group) != -1) { + /* Set the subcontext for browsing the sub tree */ + memcpy(&sub_context, context, sizeof(struct search_context)); + /* Browse the next level down if not done */ + if (sub_context.group.value.uuid16 != context->group.value.uuid16) + do_search(bdaddr, &sub_context); + } + next = seq->next; + free(seq); + sdp_record_free(rec); + } + sdp_close(sess); + return 0; +} + +static struct option browse_options[] = { + {"help", 0,0, 'h'}, + {"tree", 0,0, 't'}, + {0, 0, 0, 0} +}; + +static char *browse_help = + "Usage:\n" + "\tbrowse [--tree] [bdaddr]\n"; + +/* + * Browse the full SDP database (i.e. list all services starting from the + * root/top-level). + */ +int cmd_browse(int argc, char **argv) +{ + struct search_context context; + int opt; + + /* Initialise context */ + memset(&context, '\0', sizeof(struct search_context)); + /* We want to browse the top-level/root */ + sdp_uuid16_create(&(context.group), PUBLIC_BROWSE_GROUP); + + for_each_opt(opt, browse_options, 0) { + switch(opt) { + case 't': + context.tree = 1; + break; + default: + printf(browse_help); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc >= 1) { + bdaddr_t bdaddr; + estr2ba(argv[0], &bdaddr); + return do_search(&bdaddr, &context); + } + return do_search(0, &context); +} + +static struct option search_options[] = { + {"help", 0,0, 'h'}, + {"bdaddr", 1,0, 'b'}, + {"tree", 0,0, 't'}, + {0, 0, 0, 0} +}; + +static char *search_help = + "Usage:\n" + "\tsearch [--bdaddr bdaddr] [--tree] SERVICE\n" + "SERVICE is a name (string) or UUID (0x1002)\n"; + +/* + * Search for a specific SDP service + * + * Note : we should support multiple services on the command line : + * sdptool search 0x0100 0x000f 0x1002 + * (this would search a service supporting both L2CAP and BNEP directly in + * the top level browse group) + */ +int cmd_search(int argc, char **argv) +{ + struct search_context context; + uint16_t class = 0; + bdaddr_t bdaddr; + int has_addr = 0; + int i; + int opt; + + /* Initialise context */ + memset(&context, '\0', sizeof(struct search_context)); + + for_each_opt(opt, search_options, 0) { + switch(opt) { + case 'b': + estr2ba(optarg, &bdaddr); + has_addr = 1; + break; + case 't': + context.tree = 1; + break; + default: + printf(search_help); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { + printf(search_help); + return -1; + } + /* Note : we need to find a way to support search combining + * multiple services - Jean II */ + context.svc = strdup(argv[0]); + if (!strncasecmp(context.svc, "0x", 2)) { + int num; + /* This is a UUID16, just convert to int */ + sscanf(context.svc + 2, "%X", &num); + class = num; + printf("Class 0x%X\n", class); + } else { + /* Convert class name to an UUID */ + + for (i=0; service[i].name; i++) + if (strcasecmp(context.svc, service[i].name) == 0) { + class = service[i].class; + break; + } + if (!class) { + printf("Unknown service %s\n", context.svc); + return -1; + } + } + + sdp_uuid16_create(&context.group, class); + + if (has_addr) + return do_search(&bdaddr, &context); + return do_search(0, &context); +} + +/* + * Show how to get a specific SDP record by its handle. + * Not really useful to the user, just show how it can be done... + * Jean II + */ +int get_service(bdaddr_t *bdaddr, struct search_context *context) +{ + sdp_list_t *attrid; + uint32_t range = 0x0000ffff; + sdp_record_t *rec; + sdp_session_t *session = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY); + + if (!session) { + char str[20]; + ba2str(bdaddr, str); + printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno)); + return -1; + } + attrid = sdp_list_append(0, &range); + rec = sdp_service_attr_req(session, context->handle, SDP_ATTR_REQ_RANGE, attrid); + sdp_list_free(attrid, 0); + sdp_close(session); + if (!rec) { + printf("Service get request failed.\n"); + return -1; + } + if (context->tree) { + /* Display full tree */ + sdp_printf_service_attr(rec); + } else { + /* Display user friendly form */ + print_service_attr(rec); + } + printf("\n"); + sdp_record_free(rec); + return 0; +} + +static struct option get_options[] = { + {"help", 0,0, 'h'}, + {"bdaddr", 1,0, 'b'}, + {"tree", 0,0, 't'}, + {0, 0, 0, 0} +}; + +static char *get_help = + "Usage:\n" + "\tget [--tree] [--bdaddr bdaddr] record_handle\n"; + +/* + * Get a specific SDP record on the local SDP server + */ +int cmd_get(int argc, char **argv) +{ + struct search_context context; + bdaddr_t bdaddr; + int has_addr = 0; + int opt; + + /* Initialise context */ + memset(&context, '\0', sizeof(struct search_context)); + + for_each_opt(opt, get_options, 0) { + switch(opt) { + case 'b': + estr2ba(optarg, &bdaddr); + has_addr = 1; + break; + case 't': + context.tree = 1; + break; + default: + printf(get_help); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { + printf(get_help); + return -1; + } + /* Convert command line parameters */ + context.handle = strtoul(argv[0], 0, 16); + + return get_service(has_addr? &bdaddr: BDADDR_LOCAL, &context); +} + +struct { + char *cmd; + int (*func)(int argc, char **argv); + char *doc; +} command[] = { + { "search", cmd_search, "Search for a service" }, + { "browse", cmd_browse, "Browse all available services" }, + { "add", cmd_add, "Add local service" }, + { "del", cmd_del, "Delete local service" }, + { "get", cmd_get, "Get local service" }, + { "setattr", cmd_setattr, "Set/Add attribute to a SDP record" }, + { "setseq", cmd_setseq, "Set/Add attribute sequence to a SDP record" }, + { 0, 0, 0} +}; + +static void usage(void) +{ + int i; + + printf("sdptool - SDP Tool v%s\n", VERSION); + printf("Usage:\n" + "\tsdptool [options] [command parameters]\n"); + printf("Options:\n" + "\t--help\t\tDisplay help\n" + "\t--source\tSpecify source interface\n"); + + printf("Commands:\n"); + for (i=0; command[i].cmd; i++) + printf("\t%-4s\t\t%s\n", command[i].cmd, command[i].doc); + + printf("\nServices:\n\t"); + for (i=0; service[i].name; i++) + printf("%s ", service[i].name); + printf("\n"); +} + +static struct option main_options[] = { + {"help", 0, 0, 'h'}, + {"source", 1, 0, 'S'}, + {0, 0, 0, 0} +}; + +int main(int argc, char **argv) +{ + int opt, i; + + bacpy(&interface, BDADDR_ANY); + while ((opt=getopt_long(argc, argv, "+hS:", main_options, 0)) != -1) { + switch(opt) { + case 'S': + str2ba(optarg, &interface); + break; + case 'h': + default: + usage(); + return -1; + } + } + argc -= optind; + argv += optind; + optind = 0; + + if (argc < 1) { + usage(); + return -1; + } + for (i=0; command[i].cmd; i++) + if (strncmp(command[i].cmd, argv[0], 4) == 0) + return command[i].func(argc, argv); + return -1; +} -- cgit From a16293f34e175408334275267776142408032d45 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 1 Apr 2004 14:28:28 +0000 Subject: Display string as hex bytes if it is longer than strlen() --- tools/sdptool.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 5340ab1b..abb8b439 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -396,8 +396,15 @@ void sdp_data_printf(sdp_data_t *sdpdata, case SDP_TEXT_STR8: case SDP_TEXT_STR16: case SDP_TEXT_STR32: - printf("%.*sText : \"%s\"\n", indent, indent_spaces, - sdpdata->val.str); + if (sdpdata->unitSize > strlen(sdpdata->val.str)) { + int i; + printf("%.*sData :", indent, indent_spaces); + for (i = 0; i < sdpdata->unitSize; i++) + printf(" %02x", (unsigned char) sdpdata->val.str[i]); + printf("\n"); + } else + printf("%.*sText : \"%s\"\n", indent, indent_spaces, + sdpdata->val.str); break; case SDP_URL_STR8: case SDP_URL_STR16: -- cgit From 1d3715db11f573060cb02a2b7b7c44f06607d337 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 3 Apr 2004 06:04:35 +0000 Subject: Update BlueZ library configuration --- tools/sdptool.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index abb8b439..87646cab 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -28,14 +28,18 @@ * $Id$ */ +#ifdef HAVE_CONFIG_H +#include +#endif + #include #include #include #include +#include #include #include -#include #define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, 0)) != -1) -- cgit From b66d3f9b2cb8934a0eb7ac07f347001984488ac6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 28 Apr 2004 10:39:47 +0000 Subject: Unify copyright and license information --- tools/sdptool.c | 55 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 87646cab..1dcdf8e4 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1,31 +1,32 @@ /* - Service Discovery Protocol (SDP) - Copyright (C) 2002 Maxim Krasnyansky - Copyright (C) 2002 Stephen Crane - - Based on original SDP implementation by Nokia Corporation. - Copyright (C) 2001,2002 Nokia Corporation. - Original author Guruprasad Krishnamurthy - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation; - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. - IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY CLAIM, - OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER - RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, - NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE - USE OR PERFORMANCE OF THIS SOFTWARE. - - ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, COPYRIGHTS, - TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS SOFTWARE IS DISCLAIMED. -*/ - -/* - * $Id$ + * + * BlueZ - Bluetooth protocol stack for Linux + * + * Copyright (C) 2001-2002 Nokia Corporation + * Copyright (C) 2002-2003 Maxim Krasnyansky + * Copyright (C) 2002-2004 Marcel Holtmann + * Copyright (C) 2002-2003 Stephen Crane + * + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + * SOFTWARE IS DISCLAIMED. + * + * + * $Id$ */ #ifdef HAVE_CONFIG_H -- cgit From 2650bf7cbc4b7e0121a9995cd056b8debf3bc424 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Jun 2004 11:43:19 +0000 Subject: Add support for audio source and audio sink --- tools/sdptool.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 1dcdf8e4..b3ccf411 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1562,6 +1562,124 @@ end: return ret; } +static int add_audio_source(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, l2cap, avdtp, a2src; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + sdp_data_t *psm, *version; + uint16_t lp = 0x0019, ver = 0x0100; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&a2src, AUDIO_SOURCE_SVCLASS_ID); + svclass_id = sdp_list_append(0, &a2src); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap); + psm = sdp_data_alloc(SDP_UINT16, &lp); + proto[0] = sdp_list_append(proto[0], psm); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&avdtp, AVDTP_UUID); + proto[1] = sdp_list_append(0, &avdtp); + version = sdp_data_alloc(SDP_UINT16, &ver); + proto[1] = sdp_list_append(proto[1], version); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Audio Source", 0, 0); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto done; + } + + printf("Audio source service registered\n"); + +done: + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_audio_sink(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, l2cap, avdtp, a2snk; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + sdp_data_t *psm, *version; + uint16_t lp = 0x0019, ver = 0x0100; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&a2snk, AUDIO_SINK_SVCLASS_ID); + svclass_id = sdp_list_append(0, &a2snk); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, ADVANCED_AUDIO_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap); + psm = sdp_data_alloc(SDP_UINT16, &lp); + proto[0] = sdp_list_append(proto[0], psm); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&avdtp, AVDTP_UUID); + proto[1] = sdp_list_append(0, &avdtp); + version = sdp_data_alloc(SDP_UINT16, &ver); + proto[1] = sdp_list_append(proto[1], version); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Audio Sink", 0, 0); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto done; + } + + printf("Audio sink service registered\n"); + +done: + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + struct { char *name; uint16_t class; @@ -1584,6 +1702,9 @@ struct { { "CIP", CIP_SVCLASS_ID, add_cip }, { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, + { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_audio_source }, + { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_audio_sink }, + { 0 } }; -- cgit From ee253a9633d29120dcc2e3be4265240ae538a072 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 13 Jul 2004 03:25:36 +0000 Subject: Add Jean to the copyright statement --- tools/sdptool.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index b3ccf411..4f89491d 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -6,6 +6,7 @@ * Copyright (C) 2002-2003 Maxim Krasnyansky * Copyright (C) 2002-2004 Marcel Holtmann * Copyright (C) 2002-2003 Stephen Crane + * Copyright (C) 2002-2003 Jean Tourrilhes * * * This program is free software; you can redistribute it and/or modify -- cgit From 6153da844acccec9519301e3e15743643c096e09 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 1 Oct 2004 11:38:41 +0000 Subject: Fix class display and some compile warnings for 64 bit userland --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 4f89491d..99684d9c 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -813,7 +813,7 @@ void print_lang_attr(void *value, void *user) printf(" base_offset: 0x%02x\n", lang->base_offset); } -void print_access_protos(value, userData) +void print_access_protos(void *value, void *userData) { sdp_list_t *protDescSeq = (sdp_list_t *)value; sdp_list_foreach(protDescSeq, print_service_desc, 0); -- cgit From 1dd606979d87e4d725df282fdb00669fb8a76d1a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 13 Oct 2004 12:05:52 +0000 Subject: Add support for SIM Access Profile --- tools/sdptool.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 99684d9c..025ab0da 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -254,6 +254,7 @@ static struct uuid_def uuid16_names[] = { { 0x1127, "HCR_Scan (HCR)", NULL, 0 }, { 0x1128, "Common ISDN Access (CIP)", NULL, 0 }, { 0x1129, "VideoConferencingGW (VCP)", NULL, 0 }, + { 0x112d, "SIM Access (SAP)", NULL, 0 }, /* ... */ { 0x1200, "PnPInformation", NULL, 0 }, { 0x1201, "GenericNetworking", NULL, 0 }, @@ -1154,7 +1155,7 @@ static int add_handsfree(sdp_session_t *session, svc_info_t *si) aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&record, aproto); - sdp_set_info_attr(&record, "", 0, 0); + sdp_set_info_attr(&record, "Handsfree", 0, 0); if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { printf("Service Record registration failed\n"); @@ -1171,6 +1172,67 @@ end: return ret; } +static int add_simaccess(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; + sdp_profile_desc_t profile; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel: 3; + uint16_t u16 = 0x31; + sdp_data_t *channel, *features; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&svclass_uuid, SAP_SVCLASS_ID); + svclass_id = sdp_list_append(0, &svclass_uuid); + sdp_uuid16_create(&ga_svclass_uuid, GENERIC_TELEPHONY_SVCLASS_ID); + svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile.uuid, SAP_PROFILE_ID); + profile.version = 0x0101; + pfseq = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + features = sdp_data_alloc(SDP_UINT16, &u16); + sdp_attr_add(&record, SDP_SUPPORTED_FEATURES, features); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "SIM Access", 0, 0); + + if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("Handsfree service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} static int add_fax(sdp_session_t *session, svc_info_t *si) { @@ -1695,6 +1757,7 @@ struct { { "HS", HEADSET_SVCLASS_ID, add_headset }, { "HF", HANDSFREE_SVCLASS_ID, add_handsfree }, + { "SAP", SAP_SVCLASS_ID, add_simaccess }, { "NAP", NAP_SVCLASS_ID, add_nap }, { "GN", GN_SVCLASS_ID, add_gn }, -- cgit From 9e05169423054722af54ca7e93261c2c8c694e3d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 26 Oct 2004 02:21:16 +0000 Subject: Add more audio/video profile translations --- tools/sdptool.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 025ab0da..c63750c4 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -226,8 +226,12 @@ static struct uuid_def uuid16_names[] = { { 0x1108, "Headset", audio_attrib_names, sizeof(audio_attrib_names)/sizeof(struct attrib_def) }, { 0x1109, "CordlessTelephony", NULL, 0 }, - /* ... */ - { 0x110F, "VideoConferencing", 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 }, -- cgit From 2ec32295cb3b5f8b1cf140a8913d1e75dd8a6db5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 29 Nov 2004 03:49:36 +0000 Subject: Update UUID translation for WAP --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index c63750c4..3257159a 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -236,7 +236,7 @@ static struct uuid_def uuid16_names[] = { { 0x1111, "Fax", NULL, 0 }, { 0x1112, "HeadsetAudioGateway", NULL, 0 }, { 0x1113, "WAP", NULL, 0 }, - { 0x1114, "WAP_CLIENT", 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)", -- cgit From c75b3f2fae502b565565bcb94a4fab9dd889646a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 4 Dec 2004 04:53:46 +0000 Subject: Use --device and make more functions static --- tools/sdptool.c | 161 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 87 insertions(+), 74 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 3257159a..8d212c4e 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -34,12 +34,15 @@ #include #endif -#include #include -#include #include +#include +#include #include +#include +#include +#include #include #include @@ -48,7 +51,7 @@ /* * Convert a string to a BDADDR, with a few "enhancements" - Jean II */ -int estr2ba(char *str, bdaddr_t *ba) +static int estr2ba(char *str, bdaddr_t *ba) { /* Only trap "local", "any" is already dealt with */ if(!strcmp(str, "local")) { @@ -268,16 +271,16 @@ static struct uuid_def uuid16_names[] = { { 0x1204, "GenericTelephony", NULL, 0 }, }; -const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def); +static const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def); -void sdp_data_printf(sdp_data_t *, struct attrib_context *, int); +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... */ -void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int indent) +static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int indent) { if (uuid) { if (uuid->type == SDP_UUID16) { @@ -360,7 +363,7 @@ static void printf_dataseq(sdp_data_t * pData, * Parse a single data element (either in the attribute or in a data * sequence). */ -void sdp_data_printf(sdp_data_t *sdpdata, +static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, int indent) { @@ -443,7 +446,7 @@ void sdp_data_printf(sdp_data_t *sdpdata, /* * Parse a single attribute. */ -void sdp_attr_printf_func(void *value, void *userData) +static void sdp_attr_printf_func(void *value, void *userData) { sdp_data_t *sdpdata = NULL; uint16_t attrId; @@ -496,7 +499,7 @@ void sdp_attr_printf_func(void *value, void *userData) * We assume the record has already been read, parsed and cached * locally. Jean II */ -void sdp_printf_service_attr(sdp_record_t *rec) +static void sdp_printf_service_attr(sdp_record_t *rec) { if (rec && rec->attrlist) { struct service_context service = { NULL }; @@ -508,7 +511,7 @@ void sdp_printf_service_attr(sdp_record_t *rec) * Set attributes with single values in SDP record * Jean II */ -int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, char *value) +static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, char *value) { sdp_list_t *attrid_list; uint32_t range = 0x0000ffff; @@ -560,8 +563,8 @@ int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, char *valu } static struct option set_options[] = { - {"help", 0,0, 'h'}, - {0, 0, 0, 0} + { "help", 0,0, 'h' }, + { 0, 0, 0, 0 } }; static char *set_help = @@ -571,7 +574,7 @@ static char *set_help = /* * Add an attribute to an existing SDP record on the local SDP server */ -int cmd_setattr(int argc, char **argv) +static int cmd_setattr(int argc, char **argv) { int opt, status; uint32_t handle; @@ -610,7 +613,7 @@ int cmd_setattr(int argc, char **argv) * We do only simple data sequences. Sequence of sequences is a pain ;-) * Jean II */ -int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attrib, int argc, char **argv) +static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attrib, int argc, char **argv) { sdp_list_t *attrid_list; uint32_t range = 0x0000ffff; @@ -695,8 +698,8 @@ int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attrib, int } static struct option seq_options[] = { - {"help", 0,0, 'h'}, - {0, 0, 0, 0} + { "help", 0,0, 'h' }, + { 0, 0, 0, 0 } }; static char *seq_help = @@ -707,7 +710,7 @@ static char *seq_help = * Add an attribute sequence to an existing SDP record * on the local SDP server */ -int cmd_setseq(int argc, char **argv) +static int cmd_setseq(int argc, char **argv) { int opt, status; uint32_t handle; @@ -810,7 +813,7 @@ static void print_service_desc(void *value, void *user) } } -void print_lang_attr(void *value, void *user) +static void print_lang_attr(void *value, void *user) { sdp_lang_attr_t *lang = (sdp_lang_attr_t *)value; printf(" code_ISO639: 0x%02x\n", lang->code_ISO639); @@ -818,13 +821,13 @@ void print_lang_attr(void *value, void *user) printf(" base_offset: 0x%02x\n", lang->base_offset); } -void print_access_protos(void *value, void *userData) +static void print_access_protos(void *value, void *userData) { sdp_list_t *protDescSeq = (sdp_list_t *)value; sdp_list_foreach(protDescSeq, print_service_desc, 0); } -void print_profile_desc(void *value, void *userData) +static void print_profile_desc(void *value, void *userData) { sdp_profile_desc_t *desc = (sdp_profile_desc_t *)value; char str[MAX_LEN_PROFILEDESCRIPTOR_UUID_STR]; @@ -840,7 +843,7 @@ void print_profile_desc(void *value, void *userData) /* * Parse a SDP record in user friendly form. */ -void print_service_attr(sdp_record_t *rec) +static void print_service_attr(sdp_record_t *rec) { sdp_list_t *list = 0, *proto = 0; @@ -926,7 +929,7 @@ static int add_sp(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Serial Port", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -984,7 +987,7 @@ static int add_dun(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1040,7 +1043,7 @@ static int add_lan(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1099,7 +1102,7 @@ static int add_headset(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Headset", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1161,7 +1164,7 @@ static int add_handsfree(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Handsfree", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1223,7 +1226,7 @@ static int add_simaccess(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "SIM Access", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1281,7 +1284,7 @@ static int add_fax(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Fax", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1354,7 +1357,7 @@ static int add_opush(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "OBEX Object Push", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1415,7 +1418,7 @@ static int add_file_trans(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1488,7 +1491,7 @@ static int add_nap(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Network Access Point Service", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1547,7 +1550,7 @@ static int add_gn(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Group Network Service", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1614,7 +1617,7 @@ static int add_ctp(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Cordless Telephony", 0, 0); - if (0 > sdp_record_register(session, &record, SDP_RECORD_PERSIST)) { + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1777,7 +1780,7 @@ struct { }; /* Add local service */ -int add_service(bdaddr_t *bdaddr, svc_info_t *si) +static int add_service(bdaddr_t *bdaddr, svc_info_t *si) { int i; sdp_session_t *sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); @@ -1799,16 +1802,16 @@ int add_service(bdaddr_t *bdaddr, svc_info_t *si) } static struct option add_options[] = { - {"help", 0,0, 'h'}, - {"channel", 1,0, 'c'}, - {0, 0, 0, 0} + { "help", 0,0, 'h' }, + { "channel", 1,0, 'c' }, + { 0, 0, 0, 0} }; static char *add_help = "Usage:\n" "\tadd [--channel=CHAN] service\n"; -int cmd_add(int argc, char **argv) +static int cmd_add(int argc, char **argv) { svc_info_t si; int opt; @@ -1837,7 +1840,7 @@ int cmd_add(int argc, char **argv) } /* Delete local service */ -int del_service(bdaddr_t *bdaddr, void *arg) +static int del_service(bdaddr_t *bdaddr, void *arg) { uint32_t handle, range = 0x0000ffff; sdp_list_t *attr; @@ -1873,15 +1876,15 @@ int del_service(bdaddr_t *bdaddr, void *arg) } static struct option del_options[] = { - {"help", 0,0, 'h'}, - {0, 0, 0, 0} + { "help", 0,0, 'h' }, + { 0, 0, 0, 0 } }; static char *del_help = "Usage:\n" "\tdel record_handle\n"; -int cmd_del(int argc, char **argv) +static int cmd_del(int argc, char **argv) { int opt; @@ -1923,7 +1926,7 @@ static void inquiry(handler_t handler, void *arg) /* * Search for a specific SDP service */ -int do_search(bdaddr_t *bdaddr, struct search_context *context) +static int do_search(bdaddr_t *bdaddr, struct search_context *context) { sdp_list_t *attrid, *search, *seq, *next; uint32_t range = 0x0000ffff; @@ -1984,9 +1987,9 @@ int do_search(bdaddr_t *bdaddr, struct search_context *context) } static struct option browse_options[] = { - {"help", 0,0, 'h'}, - {"tree", 0,0, 't'}, - {0, 0, 0, 0} + { "help", 0,0, 'h' }, + { "tree", 0,0, 't' }, + { 0, 0, 0, 0 } }; static char *browse_help = @@ -1997,7 +2000,7 @@ static char *browse_help = * Browse the full SDP database (i.e. list all services starting from the * root/top-level). */ -int cmd_browse(int argc, char **argv) +static int cmd_browse(int argc, char **argv) { struct search_context context; int opt; @@ -2029,10 +2032,10 @@ int cmd_browse(int argc, char **argv) } static struct option search_options[] = { - {"help", 0,0, 'h'}, - {"bdaddr", 1,0, 'b'}, - {"tree", 0,0, 't'}, - {0, 0, 0, 0} + { "help", 0,0, 'h' }, + { "bdaddr", 1,0, 'b' }, + { "tree", 0,0, 't' }, + { 0, 0, 0, 0} }; static char *search_help = @@ -2048,7 +2051,7 @@ static char *search_help = * (this would search a service supporting both L2CAP and BNEP directly in * the top level browse group) */ -int cmd_search(int argc, char **argv) +static int cmd_search(int argc, char **argv) { struct search_context context; uint16_t class = 0; @@ -2116,7 +2119,7 @@ int cmd_search(int argc, char **argv) * Not really useful to the user, just show how it can be done... * Jean II */ -int get_service(bdaddr_t *bdaddr, struct search_context *context) +static int get_service(bdaddr_t *bdaddr, struct search_context *context) { sdp_list_t *attrid; uint32_t range = 0x0000ffff; @@ -2150,10 +2153,10 @@ int get_service(bdaddr_t *bdaddr, struct search_context *context) } static struct option get_options[] = { - {"help", 0,0, 'h'}, - {"bdaddr", 1,0, 'b'}, - {"tree", 0,0, 't'}, - {0, 0, 0, 0} + { "help", 0,0, 'h' }, + { "bdaddr", 1,0, 'b' }, + { "tree", 0,0, 't' }, + { 0, 0, 0, 0 } }; static char *get_help = @@ -2163,7 +2166,7 @@ static char *get_help = /* * Get a specific SDP record on the local SDP server */ -int cmd_get(int argc, char **argv) +static int cmd_get(int argc, char **argv) { struct search_context context; bdaddr_t bdaddr; @@ -2200,7 +2203,7 @@ int cmd_get(int argc, char **argv) return get_service(has_addr? &bdaddr: BDADDR_LOCAL, &context); } -struct { +static struct { char *cmd; int (*func)(int argc, char **argv); char *doc; @@ -2212,14 +2215,14 @@ struct { { "get", cmd_get, "Get local service" }, { "setattr", cmd_setattr, "Set/Add attribute to a SDP record" }, { "setseq", cmd_setseq, "Set/Add attribute sequence to a SDP record" }, - { 0, 0, 0} + { 0, 0, 0 } }; static void usage(void) { int i; - printf("sdptool - SDP Tool v%s\n", VERSION); + printf("sdptool - SDP tool v%s\n", VERSION); printf("Usage:\n" "\tsdptool [options] [command parameters]\n"); printf("Options:\n" @@ -2227,47 +2230,57 @@ static void usage(void) "\t--source\tSpecify source interface\n"); printf("Commands:\n"); - for (i=0; command[i].cmd; i++) + for (i = 0; command[i].cmd; i++) printf("\t%-4s\t\t%s\n", command[i].cmd, command[i].doc); printf("\nServices:\n\t"); - for (i=0; service[i].name; i++) + for (i = 0; service[i].name; i++) printf("%s ", service[i].name); printf("\n"); } static struct option main_options[] = { - {"help", 0, 0, 'h'}, - {"source", 1, 0, 'S'}, - {0, 0, 0, 0} + { "help", 0, 0, 'h' }, + { "device", 1, 0, 'i' }, + { 0, 0, 0, 0 } }; int main(int argc, char **argv) { - int opt, i; + int i, opt; bacpy(&interface, BDADDR_ANY); - while ((opt=getopt_long(argc, argv, "+hS:", main_options, 0)) != -1) { + + while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) { switch(opt) { - case 'S': - str2ba(optarg, &interface); + case 'i': + if (!strncmp(optarg, "hci", 3)) + hci_devba(atoi(optarg + 3), &interface); + else + str2ba(optarg, &interface); break; + case 'h': - default: usage(); - return -1; + exit(0); + + default: + exit(1); } } + argc -= optind; argv += optind; optind = 0; if (argc < 1) { usage(); - return -1; + exit(1); } - for (i=0; command[i].cmd; i++) + + for (i = 0; command[i].cmd; i++) if (strncmp(command[i].cmd, argv[0], 4) == 0) return command[i].func(argc, argv); + return -1; } -- cgit From b85cf3e041b3972ed220af85c0152efdc9fe19f3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 7 Dec 2004 11:48:52 +0000 Subject: Whitespace cleanup --- tools/sdptool.c | 374 ++++++++++++++++++++++++++------------------------------ 1 file changed, 176 insertions(+), 198 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 8d212c4e..fb657a3d 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -63,7 +63,7 @@ static int estr2ba(char *str, bdaddr_t *ba) /* Pass args to the inquiry/search handler */ struct search_context { - char *svc; /* Service */ + char *svc; /* Service */ uuid_t group; /* Browse group */ int tree; /* Display full attribute tree */ uint32_t handle; /* Service record handle */ @@ -76,35 +76,35 @@ static bdaddr_t interface; /* Definition of attribute members */ struct member_def { - char *name; + 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 */ + 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 */ + 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 */ + 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 */ + struct uuid_def *service; /* Service UUID, if known */ }; /* Allow us to do nice formatting of the lists */ @@ -117,158 +117,157 @@ static char *indent_spaces = " "; /* Definition of the optional arguments in protocol list */ static struct member_def protocol_members[] = { - { "Protocol" }, - { "Channel/Port" }, - { "Version" }, + { "Protocol" }, + { "Channel/Port" }, + { "Version" }, }; /* Definition of the optional arguments in profile list */ static struct member_def profile_members[] = { - { "Profile" }, - { "Version" }, + { "Profile" }, + { "Version" }, }; /* Definition of the optional arguments in Language list */ static struct member_def language_members[] = { - { "Code ISO639" }, - { "Encoding" }, - { "Base Offset" }, + { "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) */ + { 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 }, + { 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 }, + { 0x200, "GroupID", 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 }, + { 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 }, + { 0x302, "Remote audio volume control", 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 }, - { 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 }, - /* ... */ - { 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)", NULL, 0 }, - { 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 }, - { 0x112d, "SIM Access (SAP)", NULL, 0 }, - /* ... */ - { 0x1200, "PnPInformation", NULL, 0 }, - { 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 }, + /* -- Protocols -- */ + { 0x0001, "SDP (Service Discovery Protocol)", 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 (PAN/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)", + 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 }, + { 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 }, + /* ... */ + { 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)", NULL, 0 }, + { 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 }, + { 0x112d, "SIM Access (SAP)", NULL, 0 }, + /* ... */ + { 0x1200, "PnPInformation", NULL, 0 }, + { 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 }, }; static const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def); @@ -302,14 +301,13 @@ static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int in if(uuidDef) printf("%.*sUUID16 : 0x%.4x - %s\n", - indent, indent_spaces, - uuidNum, uuidDef->name); + indent, indent_spaces, uuidNum, uuidDef->name); else printf("%.*sUUID16 : 0x%.4x\n", - indent, indent_spaces, uuidNum); + indent, indent_spaces, uuidNum); } else if (uuid->type == SDP_UUID32) { printf("%.*sUUID32 : 0x%.8x\n", - indent, indent_spaces, uuid->value.uuid32); + indent, indent_spaces, uuid->value.uuid32); } else if (uuid->type == SDP_UUID128) { unsigned int data0; unsigned short data1; @@ -326,23 +324,21 @@ static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int in 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)); + 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); + indent, indent_spaces); } else printf("%.*sNull passed to print UUID\n", - indent, indent_spaces); + 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) +static void printf_dataseq(sdp_data_t * pData, struct attrib_context *context, int indent) { sdp_data_t *sdpdata = NULL; @@ -363,9 +359,7 @@ static void printf_dataseq(sdp_data_t * pData, * 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) +static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, int indent) { char *member_name = NULL; @@ -392,11 +386,10 @@ static void sdp_data_printf(sdp_data_t *sdpdata, case SDP_INT128: if (member_name) { printf("%.*s%s (Integer) : 0x%x\n", - indent, indent_spaces, - member_name, sdpdata->val.uint32); + indent, indent_spaces, member_name, sdpdata->val.uint32); } else { printf("%.*sInteger : 0x%x\n", indent, indent_spaces, - sdpdata->val.uint32); + sdpdata->val.uint32); } break; @@ -417,14 +410,12 @@ static void sdp_data_printf(sdp_data_t *sdpdata, printf(" %02x", (unsigned char) sdpdata->val.str[i]); printf("\n"); } else - printf("%.*sText : \"%s\"\n", indent, indent_spaces, - sdpdata->val.str); + 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); + printf("%.*sURL : %s\n", indent, indent_spaces, sdpdata->val.str); break; case SDP_SEQ8: @@ -464,9 +455,8 @@ static void sdp_attr_printf_func(void *value, void *userData) break; } /* Search amongst the specific attributes of this service */ - if ((attrDef == NULL) && - (service->service != NULL) && - (service->service->attribs != NULL)) { + 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++) @@ -477,8 +467,7 @@ static void sdp_attr_printf_func(void *value, void *userData) } if (attrDef) - printf("Attribute Identifier : 0x%x - %s\n", - attrId, attrDef->name); + printf("Attribute Identifier : 0x%x - %s\n", attrId, attrDef->name); else printf("Attribute Identifier : 0x%x\n", attrId); /* Build context */ @@ -534,7 +523,7 @@ static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, cha value_int = strtoul(value + 3, NULL, 16); sdp_uuid16_create(&value_uuid, value_int); printf("Adding attrib 0x%X uuid16 0x%X to record 0x%X\n", - attrib, value_int, handle); + attrib, value_int, handle); sdp_attr_add_new(rec, attrib, SDP_UUID16, &value_uuid.value.uuid16); } else if (!strncasecmp(value, "0x", 2)) { @@ -542,13 +531,13 @@ static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, cha uint32_t value_int; value_int = strtoul(value + 2, NULL, 16); printf("Adding attrib 0x%X int 0x%X to record 0x%X\n", - attrib, value_int, handle); + attrib, value_int, handle); sdp_attr_add_new(rec, attrib, SDP_UINT32, &value_int); } else { /* String */ printf("Adding attrib 0x%X string \"%s\" to record 0x%X\n", - attrib, value, handle); + attrib, value, handle); /* Add/Update our attribute to the record */ sdp_attr_add_new(rec, attrib, SDP_TEXT_STR8, value); @@ -651,8 +640,7 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri allocArray[i] = value_uuid; sdp_uuid16_create(value_uuid, value_int); - printf("Adding uuid16 0x%X to record 0x%X\n", - value_int, handle); + printf("Adding uuid16 0x%X to record 0x%X\n", value_int, handle); dtdArray[i] = &uuid16; valueArray[i] = &value_uuid->value.uuid16; } else if (!strncasecmp(argv[i], "0x", 2)) { @@ -661,14 +649,12 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri allocArray[i] = value_int; *value_int = strtoul((argv[i]) + 2, NULL, 16); - printf("Adding int 0x%X to record 0x%X\n", - *value_int, handle); + printf("Adding int 0x%X to record 0x%X\n", *value_int, handle); dtdArray[i] = &uint32; valueArray[i] = value_int; } else { /* String */ - printf("Adding string \"%s\" to record 0x%X\n", - argv[i], handle); + printf("Adding string \"%s\" to record 0x%X\n", argv[i], handle); dtdArray[i] = &str8; valueArray[i] = argv[i]; } @@ -1566,16 +1552,6 @@ end: return ret; } -static int add_hid(sdp_session_t *sess, svc_info_t *si) -{ - return -1; -} - -static int add_cip(sdp_session_t *sess, svc_info_t *si) -{ - return -1; -} - static int add_ctp(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -1751,30 +1727,30 @@ done: } struct { - char *name; - uint16_t class; - int (*add)(sdp_session_t *sess, svc_info_t *si); + char *name; + uint16_t class; + int (*add)(sdp_session_t *sess, svc_info_t *si); } service[] = { - { "SP", SERIAL_PORT_SVCLASS_ID, add_sp }, - { "DUN", DIALUP_NET_SVCLASS_ID, add_dun }, - { "LAN", LAN_ACCESS_SVCLASS_ID, add_lan }, - { "FAX", FAX_SVCLASS_ID, add_fax }, - { "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush }, - { "FTRN", OBEX_FILETRANS_SVCLASS_ID, add_file_trans }, + { "SP", SERIAL_PORT_SVCLASS_ID, add_sp }, + { "DUN", DIALUP_NET_SVCLASS_ID, add_dun }, + { "LAN", LAN_ACCESS_SVCLASS_ID, add_lan }, + { "FAX", FAX_SVCLASS_ID, add_fax }, + { "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush }, + { "FTRN", OBEX_FILETRANS_SVCLASS_ID, add_file_trans }, - { "HS", HEADSET_SVCLASS_ID, add_headset }, - { "HF", HANDSFREE_SVCLASS_ID, add_handsfree }, - { "SAP", SAP_SVCLASS_ID, add_simaccess }, + { "HS", HEADSET_SVCLASS_ID, add_headset }, + { "HF", HANDSFREE_SVCLASS_ID, add_handsfree }, + { "SAP", SAP_SVCLASS_ID, add_simaccess }, - { "NAP", NAP_SVCLASS_ID, add_nap }, - { "GN", GN_SVCLASS_ID, add_gn }, + { "NAP", NAP_SVCLASS_ID, add_nap }, + { "GN", GN_SVCLASS_ID, add_gn }, - { "HID", HID_SVCLASS_ID, add_hid }, - { "CIP", CIP_SVCLASS_ID, add_cip }, - { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, + { "HID", HID_SVCLASS_ID, NULL }, + { "CIP", CIP_SVCLASS_ID, NULL }, + { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, - { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_audio_source }, - { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_audio_sink }, + { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_audio_source}, + { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_audio_sink }, { 0 } }; @@ -1788,9 +1764,11 @@ static int add_service(bdaddr_t *bdaddr, svc_info_t *si) if (!sess) return -1; if (si->name) - for (i=0; service[i].name; i++) + for (i = 0; service[i].name; i++) if (!strcasecmp(service[i].name, si->name)) { - int ret = service[i].add(sess, si); + int ret = -1; + if (service[i].add) + ret = service[i].add(sess, si); free(si->name); sdp_close(sess); return ret; @@ -1919,7 +1897,7 @@ static void inquiry(handler_t handler, void *arg) printf("Inquiry failed\n"); return; } - for (i=0; i Date: Tue, 7 Dec 2004 12:31:26 +0000 Subject: Add support for Device ID --- tools/sdptool.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index fb657a3d..358fbb42 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -170,6 +170,16 @@ 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 PAN attributes. See BT assigned numbers */ /* Note : those need to be double checked - Jean II */ static struct attrib_def pan_attrib_names[] = { @@ -262,7 +272,8 @@ static struct uuid_def uuid16_names[] = { { 0x1129, "VideoConferencingGW (VCP)", NULL, 0 }, { 0x112d, "SIM Access (SAP)", NULL, 0 }, /* ... */ - { 0x1200, "PnPInformation", 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", @@ -1143,7 +1154,7 @@ static int add_handsfree(sdp_session_t *session, svc_info_t *si) apseq = sdp_list_append(apseq, proto[1]); features = sdp_data_alloc(SDP_UINT16, &u16); - sdp_attr_add(&record, SDP_SUPPORTED_FEATURES, features); + sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&record, aproto); @@ -1205,7 +1216,7 @@ static int add_simaccess(sdp_session_t *session, svc_info_t *si) apseq = sdp_list_append(apseq, proto[1]); features = sdp_data_alloc(SDP_UINT16, &u16); - sdp_attr_add(&record, SDP_SUPPORTED_FEATURES, features); + sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&record, aproto); @@ -1589,7 +1600,7 @@ static int add_ctp(sdp_session_t *session, svc_info_t *si) aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&record, aproto); - sdp_attr_add(&record, SDP_EXTERNAL_NETWORK, network); + sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network); sdp_set_info_attr(&record, "Cordless Telephony", 0, 0); @@ -1731,6 +1742,8 @@ struct { uint16_t class; int (*add)(sdp_session_t *sess, svc_info_t *si); } service[] = { + { "DID", PNP_INFO_SVCLASS_ID, NULL, }, + { "SP", SERIAL_PORT_SVCLASS_ID, add_sp }, { "DUN", DIALUP_NET_SVCLASS_ID, add_dun }, { "LAN", LAN_ACCESS_SVCLASS_ID, add_lan }, @@ -2074,7 +2087,7 @@ static int cmd_search(int argc, char **argv) } else { /* Convert class name to an UUID */ - for (i=0; service[i].name; i++) + for (i = 0; service[i].name; i++) if (strcasecmp(context.svc, service[i].name) == 0) { class = service[i].class; break; -- cgit From a4a063c607c0d2693f253af261b6d8a0bf221f9c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 7 Dec 2004 12:50:50 +0000 Subject: Add support for HID attribute descriptions --- tools/sdptool.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 358fbb42..6ceb0bd9 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -180,6 +180,25 @@ static struct attrib_def did_attrib_names[] = { { 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[] = { @@ -264,7 +283,8 @@ static struct uuid_def uuid16_names[] = { { 0x1121, "ReflectedUI (BPP)", NULL, 0 }, { 0x1122, "BasicPrinting (BPP)", NULL, 0 }, { 0x1123, "PrintingStatus (BPP)", NULL, 0 }, - { 0x1124, "HumanInterfaceDeviceService (HID)", 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 }, -- cgit From 19812023eacc4a912db4adb92c040a02a50cdff7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 10 Dec 2004 09:06:36 +0000 Subject: Also translate UUID-32 to string --- tools/sdptool.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 6ceb0bd9..cfbe2bba 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -318,8 +318,8 @@ static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int in struct uuid_def *uuidDef = NULL; int i; - for(i = 0; i < uuid16_max; i++) - if(uuid16_names[i].num == uuidNum) { + for (i = 0; i < uuid16_max; i++) + if (uuid16_names[i].num == uuidNum) { uuidDef = &uuid16_names[i]; break; } @@ -330,15 +330,31 @@ static void sdp_uuid_printf(uuid_t *uuid, struct attrib_context *context, int in context->service = uuidDef; } - if(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); + 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; -- cgit From d05333281217cd6623de9cc27b90448d7fd5d81a Mon Sep 17 00:00:00 2001 From: Stephen Crane Date: Mon, 28 Feb 2005 11:58:54 +0000 Subject: free protocol descriptor list properly --- tools/sdptool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index cfbe2bba..a3c3c551 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -892,7 +892,8 @@ static void print_service_attr(sdp_record_t *rec) if (sdp_get_access_protos(rec, &proto) == 0) { printf("Protocol Descriptor List:\n"); sdp_list_foreach(proto, print_access_protos, 0); - sdp_list_free(proto, (sdp_free_func_t)sdp_data_free); + sdp_list_foreach(proto, (sdp_list_func_t)sdp_list_free, 0); + sdp_list_free(proto, 0); } if (sdp_get_lang_attr(rec, &list) == 0) { printf("Language Base Attr List:\n"); -- cgit From 4eaf4a6acc09c87c010f31b169dac5a7b99cc1c6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 28 Feb 2005 14:09:08 +0000 Subject: Call it SIM Access --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index a3c3c551..bed5e90e 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1265,7 +1265,7 @@ static int add_simaccess(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } - printf("Handsfree service registered\n"); + printf("SIM Access service registered\n"); end: sdp_data_free(channel); sdp_list_free(proto[0], 0); -- cgit From 210da6834b4b6f219b0331cddacdd6e915dbb8fe Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 9 Mar 2005 17:01:54 +0000 Subject: Add language attributes --- tools/sdptool.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index bed5e90e..5c93dd69 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -920,6 +920,20 @@ typedef struct { unsigned int channel; } svc_info_t; +static void add_lang_attr(sdp_record_t *r) +{ + sdp_lang_attr_t base_lang; + sdp_list_t *langs = 0; + + /* UTF-8 MIBenum (http://www.iana.org/assignments/character-sets) */ + base_lang.code_ISO639 = (0x65 << 8) | 0x6e; + base_lang.encoding = 106; + base_lang.base_offset = SDP_PRIMARY_LANG_BASE; + langs = sdp_list_append(0, &base_lang); + sdp_set_lang_attr(r, langs); + sdp_list_free(langs, 0); +} + static int add_sp(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *apseq, *proto[2], *profiles, *root, *aproto; @@ -961,7 +975,9 @@ static int add_sp(sdp_session_t *session, svc_info_t *si) aproto = sdp_list_append(0, apseq); sdp_set_access_protos(&record, aproto); - sdp_set_info_attr(&record, "Serial Port", 0, 0); + add_lang_attr(&record); + + sdp_set_info_attr(&record, "Serial Port", 0, "COM Port"); if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); -- cgit From 44b78feaa5e08e10d3d61404cc8ce8de416f70c3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 28 Mar 2005 20:00:34 +0000 Subject: Add support registering PANU service record --- tools/sdptool.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 5c93dd69..962c9ce9 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1616,6 +1616,68 @@ end: return ret; } +static int add_panu(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, ftrn_uuid, l2cap_uuid, bnep_uuid; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint16_t lp = 0x000f, ver = 0x0100; + sdp_data_t *psm, *version; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + sdp_list_free(root, NULL); + + sdp_uuid16_create(&ftrn_uuid, PANU_SVCLASS_ID); + svclass_id = sdp_list_append(NULL, &ftrn_uuid); + sdp_set_service_classes(&record, svclass_id); + sdp_list_free(svclass_id, NULL); + + sdp_uuid16_create(&profile[0].uuid, PANU_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(NULL, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + sdp_list_free(pfseq, NULL); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(NULL, &l2cap_uuid); + psm = sdp_data_alloc(SDP_UINT16, &lp); + proto[0] = sdp_list_append(proto[0], psm); + apseq = sdp_list_append(NULL, proto[0]); + + sdp_uuid16_create(&bnep_uuid, BNEP_UUID); + proto[1] = sdp_list_append(NULL, &bnep_uuid); + version = sdp_data_alloc(SDP_UINT16, &ver); + proto[1] = sdp_list_append(proto[1], version); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(NULL, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "PAN User", NULL, NULL); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("PANU service registered\n"); +end: + sdp_data_free(version); + sdp_data_free(psm); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + static int add_ctp(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -1810,6 +1872,7 @@ struct { { "NAP", NAP_SVCLASS_ID, add_nap }, { "GN", GN_SVCLASS_ID, add_gn }, + { "PANU", PANU_SVCLASS_ID, add_panu }, { "HID", HID_SVCLASS_ID, NULL }, { "CIP", CIP_SVCLASS_ID, NULL }, -- cgit From b0f097c96eed5c5227973a48d8ad30bb5c18703e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 5 Apr 2005 15:20:10 +0000 Subject: Add support for browsing the L2CAP group --- tools/sdptool.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 962c9ce9..980778ea 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2096,12 +2096,13 @@ static int do_search(bdaddr_t *bdaddr, struct search_context *context) static struct option browse_options[] = { { "help", 0,0, 'h' }, { "tree", 0,0, 't' }, + { "l2cap", 0,0, 'l' }, { 0, 0, 0, 0 } }; static char *browse_help = "Usage:\n" - "\tbrowse [--tree] [bdaddr]\n"; + "\tbrowse [--tree] [--l2cap] [bdaddr]\n"; /* * Browse the full SDP database (i.e. list all services starting from the @@ -2115,13 +2116,16 @@ static int cmd_browse(int argc, char **argv) /* Initialise context */ memset(&context, '\0', sizeof(struct search_context)); /* We want to browse the top-level/root */ - sdp_uuid16_create(&(context.group), PUBLIC_BROWSE_GROUP); + sdp_uuid16_create(&context.group, PUBLIC_BROWSE_GROUP); for_each_opt(opt, browse_options, 0) { switch(opt) { case 't': context.tree = 1; break; + case 'l': + sdp_uuid16_create(&context.group, L2CAP_UUID); + break; default: printf(browse_help); return -1; -- cgit From 9f02be3e3b3d9af1e11e158c6cf386228e12d41f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 7 Apr 2005 13:43:23 +0000 Subject: Add support to browse various UUIDs --- tools/sdptool.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 980778ea..d3da429d 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2094,15 +2094,16 @@ static int do_search(bdaddr_t *bdaddr, struct search_context *context) } static struct option browse_options[] = { - { "help", 0,0, 'h' }, - { "tree", 0,0, 't' }, - { "l2cap", 0,0, 'l' }, + { "help", 0, 0, 'h' }, + { "tree", 0, 0, 't' }, + { "uuid", 1, 0, 'u' }, + { "l2cap", 0, 0, 'l' }, { 0, 0, 0, 0 } }; static char *browse_help = "Usage:\n" - "\tbrowse [--tree] [--l2cap] [bdaddr]\n"; + "\tbrowse [--tree] [--uuid uuid] [--l2cap] [bdaddr]\n"; /* * Browse the full SDP database (i.e. list all services starting from the @@ -2111,7 +2112,7 @@ static char *browse_help = static int cmd_browse(int argc, char **argv) { struct search_context context; - int opt; + int opt, num; /* Initialise context */ memset(&context, '\0', sizeof(struct search_context)); @@ -2123,6 +2124,13 @@ static int cmd_browse(int argc, char **argv) case 't': context.tree = 1; break; + case 'u': + if (sscanf(optarg, "%i", &num) != 1 || num < 0 || num > 0xffff) { + printf("Invalid uuid %s\n", optarg); + return -1; + } + sdp_uuid16_create(&context.group, num); + break; case 'l': sdp_uuid16_create(&context.group, L2CAP_UUID); break; -- cgit From 1487aa2f7c8a1bd0633d3f959699b1ccb1a5031c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 20 Apr 2005 22:30:36 +0000 Subject: Support adding of Nokia ID and PC Suite service records --- tools/sdptool.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 91 insertions(+), 5 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index d3da429d..83e86fb5 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -4,7 +4,7 @@ * * Copyright (C) 2001-2002 Nokia Corporation * Copyright (C) 2002-2003 Maxim Krasnyansky - * Copyright (C) 2002-2004 Marcel Holtmann + * Copyright (C) 2002-2005 Marcel Holtmann * Copyright (C) 2002-2003 Stephen Crane * Copyright (C) 2002-2003 Jean Tourrilhes * @@ -1423,7 +1423,7 @@ end: return ret; } -static int add_file_trans(sdp_session_t *session, svc_info_t *si) +static int add_ftp(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, ftrn_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; @@ -1852,6 +1852,83 @@ done: return ret; } +static unsigned char nokid_uuid[] = { 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; + +static int add_nokia_id(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass; + uuid_t root_uuid, svclass_uuid; + uint16_t verid = 0x005f; + sdp_data_t *version = sdp_data_alloc(SDP_UINT16, &verid); + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid128_create(&svclass_uuid, (void *) nokid_uuid); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + + sdp_attr_add(&record, SDP_ATTR_SERVICE_VERSION, version); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + sdp_data_free(version); + return -1; + } + + printf("Nokia ID service record registered\n"); + + return 0; +} + +static unsigned char pcsuite_uuid[] = { 0x00, 0x00, 0x50, 0x02, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; + +static int add_pcsuite(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass, *proto; + uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; + uint8_t channel = si->channel? si->channel: 14; + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto = sdp_list_append(proto, sdp_list_append( + sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); + + sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); + + sdp_uuid128_create(&svclass_uuid, (void *) pcsuite_uuid); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + + sdp_set_info_attr(&record, "Nokia PC Suite", NULL, NULL); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("Nokia PC Suite service registered\n"); + + return 0; +} + struct { char *name; uint16_t class; @@ -1864,7 +1941,7 @@ struct { { "LAN", LAN_ACCESS_SVCLASS_ID, add_lan }, { "FAX", FAX_SVCLASS_ID, add_fax }, { "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush }, - { "FTRN", OBEX_FILETRANS_SVCLASS_ID, add_file_trans }, + { "FTP", OBEX_FILETRANS_SVCLASS_ID, add_ftp }, { "HS", HEADSET_SVCLASS_ID, add_headset }, { "HF", HANDSFREE_SVCLASS_ID, add_handsfree }, @@ -1881,6 +1958,9 @@ struct { { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_audio_source}, { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_audio_sink }, + { "NOKID", 0, add_nokia_id }, + { "PCSUITE", 0, add_pcsuite }, + { 0 } }; @@ -2339,7 +2419,7 @@ static struct { static void usage(void) { - int i; + int i, pos = 0; printf("sdptool - SDP tool v%s\n", VERSION); printf("Usage:\n" @@ -2353,8 +2433,14 @@ static void usage(void) printf("\t%-4s\t\t%s\n", command[i].cmd, command[i].doc); printf("\nServices:\n\t"); - for (i = 0; service[i].name; i++) + for (i = 0; service[i].name; i++) { printf("%s ", service[i].name); + pos += strlen(service[i].name) + 1; + if (pos > 60) { + printf("\n\t"); + pos = 0; + } + } printf("\n"); } -- cgit From 3f8f26bc831ca52caa7cc8ca500ae814818977a8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 2 May 2005 15:45:57 +0000 Subject: Add support for Toshiba SR-1 service record --- tools/sdptool.c | 45 +++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 83e86fb5..c7e58ac9 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1734,7 +1734,7 @@ end: return ret; } -static int add_audio_source(sdp_session_t *session, svc_info_t *si) +static int add_a2source(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, l2cap, avdtp, a2src; @@ -1793,7 +1793,7 @@ done: return ret; } -static int add_audio_sink(sdp_session_t *session, svc_info_t *si) +static int add_a2sink(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; uuid_t root_uuid, l2cap, avdtp, a2snk; @@ -1855,7 +1855,7 @@ done: static unsigned char nokid_uuid[] = { 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; -static int add_nokia_id(sdp_session_t *session, svc_info_t *si) +static int add_nokiaid(sdp_session_t *session, svc_info_t *si) { sdp_record_t record; sdp_list_t *root, *svclass; @@ -1929,6 +1929,38 @@ static int add_pcsuite(sdp_session_t *session, svc_info_t *si) return 0; } +static unsigned char sr1_uuid[] = { 0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0, + 0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 }; + +static int add_sr1(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass; + uuid_t root_uuid, svclass_uuid; + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + + sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("Toshiba Speech Recognition SR-1 service record registered\n"); + + return 0; +} + struct { char *name; uint16_t class; @@ -1955,11 +1987,12 @@ struct { { "CIP", CIP_SVCLASS_ID, NULL }, { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, - { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_audio_source}, - { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_audio_sink }, + { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source }, + { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink }, - { "NOKID", 0, add_nokia_id }, + { "NOKID", 0, add_nokiaid }, { "PCSUITE", 0, add_pcsuite }, + { "SR1", 0, add_sr1 }, { 0 } }; -- cgit From 25886ef5728f16533735b778d9fb5d1ab685768e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 May 2005 12:40:56 +0000 Subject: Add service registration for SyncML Client --- tools/sdptool.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index c7e58ac9..51c13e09 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1852,6 +1852,51 @@ done: return ret; } +static unsigned char syncml_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 }; + +static int add_syncml(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass, *proto; + uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; + uint8_t channel = si->channel? si->channel: 15; + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid128_create(&svclass_uuid, (void *) syncml_uuid); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto = sdp_list_append(proto, sdp_list_append( + sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); + + sdp_uuid16_create(&obex_uuid, OBEX_UUID); + proto = sdp_list_append(proto, sdp_list_append(NULL, &obex_uuid)); + + sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); + + sdp_set_info_attr(&record, "SyncML Client", NULL, NULL); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("SyncML Client service record registered\n"); + + return 0; +} + static unsigned char nokid_uuid[] = { 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; @@ -1990,6 +2035,8 @@ struct { { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source }, { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink }, + { "SYNCML", 0, add_syncml }, + { "NOKID", 0, add_nokiaid }, { "PCSUITE", 0, add_pcsuite }, { "SR1", 0, add_sr1 }, -- cgit From cc2dd8a3670f68984f324d6861a344cb68728a1a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 May 2005 13:28:15 +0000 Subject: Support searching for services with UUID-128 --- tools/sdptool.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 51c13e09..b81273cb 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2010,6 +2010,7 @@ struct { char *name; uint16_t class; int (*add)(sdp_session_t *sess, svc_info_t *si); + unsigned char *uuid; } service[] = { { "DID", PNP_INFO_SVCLASS_ID, NULL, }, @@ -2035,11 +2036,10 @@ struct { { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source }, { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink }, - { "SYNCML", 0, add_syncml }, - - { "NOKID", 0, add_nokiaid }, - { "PCSUITE", 0, add_pcsuite }, - { "SR1", 0, add_sr1 }, + { "SYNCML", 0, add_syncml, syncml_uuid }, + { "NOKID", 0, add_nokiaid, nokid_uuid }, + { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, + { "SR1", 0, add_sr1, sr1_uuid }, { 0 } }; @@ -2333,6 +2333,7 @@ static char *search_help = static int cmd_search(int argc, char **argv) { struct search_context context; + unsigned char *uuid = NULL; uint16_t class = 0; bdaddr_t bdaddr; int has_addr = 0; @@ -2363,6 +2364,7 @@ static int cmd_search(int argc, char **argv) printf(search_help); return -1; } + /* Note : we need to find a way to support search combining * multiple services - Jean II */ context.svc = strdup(argv[0]); @@ -2378,19 +2380,24 @@ static int cmd_search(int argc, char **argv) for (i = 0; service[i].name; i++) if (strcasecmp(context.svc, service[i].name) == 0) { class = service[i].class; + uuid = service[i].uuid; break; } - if (!class) { + if (!class && !uuid) { printf("Unknown service %s\n", context.svc); return -1; } - } + } - sdp_uuid16_create(&context.group, class); + if (class) + sdp_uuid16_create(&context.group, class); + else + sdp_uuid128_create(&context.group, uuid); if (has_addr) return do_search(&bdaddr, &context); - return do_search(0, &context); + + return do_search(NULL, &context); } /* -- cgit From 18cb95673231d41455528a782b168ee05f32fe2b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 May 2005 14:13:41 +0000 Subject: Add command for retrieving possible service records --- tools/sdptool.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 14 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index b81273cb..64e3a464 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2085,7 +2085,7 @@ static int cmd_add(int argc, char **argv) memset(&si, 0, sizeof(si)); for_each_opt(opt, add_options, 0) { - switch(opt) { + switch (opt) { case 'c': si.channel = atoi(optarg); break; @@ -2103,11 +2103,12 @@ static int cmd_add(int argc, char **argv) } si.name = strdup(argv[0]); + return add_service(0, &si); } /* Delete local service */ -static int del_service(bdaddr_t *bdaddr, void *arg) +static int del_service(bdaddr_t *bdaddr, void *arg) { uint32_t handle, range = 0x0000ffff; sdp_list_t *attr; @@ -2118,11 +2119,13 @@ static int del_service(bdaddr_t *bdaddr, void *arg) printf("Record handle was not specified.\n"); return -1; } + sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); if (!sess) { printf("No local SDP server!\n"); return -1; } + handle = strtoul((char *)arg, 0, 16); attr = sdp_list_append(0, &range); rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr); @@ -2132,11 +2135,13 @@ static int del_service(bdaddr_t *bdaddr, void *arg) sdp_close(sess); return -1; } + if (sdp_record_unregister(sess, rec)) { printf("Failed to unregister service record: %s\n", strerror(errno)); sdp_close(sess); return -1; } + printf("Service Record deleted.\n"); sdp_close(sess); return 0; @@ -2156,7 +2161,7 @@ static int cmd_del(int argc, char **argv) int opt; for_each_opt(opt, del_options, 0) { - switch(opt) { + switch (opt) { default: printf(del_help); return -1; @@ -2169,7 +2174,8 @@ static int cmd_del(int argc, char **argv) printf(del_help); return -1; } - return del_service(0, argv[0]); + + return del_service(NULL, argv[0]); } /* @@ -2186,6 +2192,7 @@ static void inquiry(handler_t handler, void *arg) printf("Inquiry failed\n"); return; } + for (i = 0; i < count; i++) handler(&ii[i].bdaddr, arg); } @@ -2204,12 +2211,14 @@ static int do_search(bdaddr_t *bdaddr, struct search_context *context) inquiry(do_search, context); return 0; } + sess = sdp_connect(&interface, bdaddr, SDP_RETRY_IF_BUSY); ba2str(bdaddr, str); if (!sess) { printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno)); return -1; } + if (context->svc) printf("Searching for %s on %s ...\n", context->svc, str); else @@ -2249,6 +2258,7 @@ static int do_search(bdaddr_t *bdaddr, struct search_context *context) free(seq); sdp_record_free(rec); } + sdp_close(sess); return 0; } @@ -2280,7 +2290,7 @@ static int cmd_browse(int argc, char **argv) sdp_uuid16_create(&context.group, PUBLIC_BROWSE_GROUP); for_each_opt(opt, browse_options, 0) { - switch(opt) { + switch (opt) { case 't': context.tree = 1; break; @@ -2307,7 +2317,8 @@ static int cmd_browse(int argc, char **argv) estr2ba(argv[0], &bdaddr); return do_search(&bdaddr, &context); } - return do_search(0, &context); + + return do_search(NULL, &context); } static struct option search_options[] = { @@ -2344,7 +2355,7 @@ static int cmd_search(int argc, char **argv) memset(&context, '\0', sizeof(struct search_context)); for_each_opt(opt, search_options, 0) { - switch(opt) { + switch (opt) { case 'b': estr2ba(optarg, &bdaddr); has_addr = 1; @@ -2405,7 +2416,7 @@ static int cmd_search(int argc, char **argv) * Not really useful to the user, just show how it can be done... * Jean II */ -static int get_service(bdaddr_t *bdaddr, struct search_context *context) +static int get_service(bdaddr_t *bdaddr, struct search_context *context, int quite) { sdp_list_t *attrid; uint32_t range = 0x0000ffff; @@ -2418,14 +2429,17 @@ static int get_service(bdaddr_t *bdaddr, struct search_context *context) printf("Failed to connect to SDP server on %s: %s\n", str, strerror(errno)); return -1; } + attrid = sdp_list_append(0, &range); rec = sdp_service_attr_req(session, context->handle, SDP_ATTR_REQ_RANGE, attrid); sdp_list_free(attrid, 0); sdp_close(session); if (!rec) { - printf("Service get request failed.\n"); + if (!quite) + printf("Service get request failed.\n"); return -1; } + if (context->tree) { /* Display full tree */ sdp_printf_service_attr(rec); @@ -2434,14 +2448,68 @@ static int get_service(bdaddr_t *bdaddr, struct search_context *context) print_service_attr(rec); } printf("\n"); + sdp_record_free(rec); return 0; } +static struct option records_options[] = { + { "help", 0, 0, 'h' }, + { "tree", 0, 0, 't' }, + { 0, 0, 0, 0 } +}; + +static char *records_help = + "Usage:\n" + "\trecords [--tree] bdaddr\n"; + +/* + * Request possible SDP service records + */ +static int cmd_records(int argc, char **argv) +{ + struct search_context context; + uint32_t base[] = { 0x10000, 0x1002e }; + bdaddr_t bdaddr; + int i, n, opt, num = 32; + + /* Initialise context */ + memset(&context, '\0', sizeof(struct search_context)); + + for_each_opt(opt, records_options, 0) { + switch (opt) { + case 't': + context.tree = 1; + break; + default: + printf(records_help); + return -1; + } + } + argc -= optind; + argv += optind; + + if (argc < 1) { + printf(records_help); + return -1; + } + + /* Convert command line parameters */ + estr2ba(argv[0], &bdaddr); + + for (i = 0; i < sizeof(base) / sizeof(uint32_t); i++) + for (n = 0; n < num; n++) { + context.handle = base[i] + n; + get_service(&bdaddr, &context, 1); + } + + return 0; +} + static struct option get_options[] = { - { "help", 0,0, 'h' }, - { "bdaddr", 1,0, 'b' }, - { "tree", 0,0, 't' }, + { "help", 0,0, 'h' }, + { "bdaddr", 1,0, 'b' }, + { "tree", 0,0, 't' }, { 0, 0, 0, 0 } }; @@ -2463,7 +2531,7 @@ static int cmd_get(int argc, char **argv) memset(&context, '\0', sizeof(struct search_context)); for_each_opt(opt, get_options, 0) { - switch(opt) { + switch (opt) { case 'b': estr2ba(optarg, &bdaddr); has_addr = 1; @@ -2483,10 +2551,11 @@ static int cmd_get(int argc, char **argv) printf(get_help); return -1; } + /* Convert command line parameters */ context.handle = strtoul(argv[0], 0, 16); - return get_service(has_addr? &bdaddr: BDADDR_LOCAL, &context); + return get_service(has_addr ? &bdaddr : BDADDR_LOCAL, &context, 0); } static struct { @@ -2496,6 +2565,7 @@ static struct { } command[] = { { "search", cmd_search, "Search for a service" }, { "browse", cmd_browse, "Browse all available services" }, + { "records", cmd_records, "Request all records" }, { "add", cmd_add, "Add local service" }, { "del", cmd_del, "Delete local service" }, { "get", cmd_get, "Get local service" }, -- cgit From e7b5f3c69c6a7303b951e7a1398c87a568a16761 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 May 2005 16:10:26 +0000 Subject: Include a raw mode for showing the original record tree --- tools/sdptool.c | 326 +++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 278 insertions(+), 48 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 64e3a464..d015f12f 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -36,9 +36,11 @@ #include #include +#include #include +#include #include -#include +#include #include #include @@ -46,6 +48,8 @@ #include #include +#include + #define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, 0)) != -1) /* @@ -61,11 +65,15 @@ static int estr2ba(char *str, bdaddr_t *ba) 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 */ + /* Pass args to the inquiry/search handler */ struct search_context { char *svc; /* Service */ uuid_t group; /* Browse group */ - int tree; /* Display full attribute tree */ + int view; /* View mode */ uint32_t handle; /* Service record handle */ }; @@ -219,7 +227,7 @@ static struct attrib_def audio_attrib_names[] = { /* Same for the UUIDs. See BT assigned numbers */ static struct uuid_def uuid16_names[] = { /* -- Protocols -- */ - { 0x0001, "SDP (Service Discovery Protocol)", NULL, 0 }, + { 0x0001, "SDP", NULL, 0 }, { 0x0002, "UDP", NULL, 0 }, { 0x0003, "RFCOMM", NULL, 0 }, { 0x0004, "TCP", NULL, 0 }, @@ -230,7 +238,7 @@ static struct uuid_def uuid16_names[] = { { 0x000a, "FTP", NULL, 0 }, { 0x000c, "HTTP", NULL, 0 }, { 0x000e, "WSP", NULL, 0 }, - { 0x000f, "BNEP (PAN/BNEP)", NULL, 0 }, + { 0x000f, "BNEP", NULL, 0 }, { 0x0010, "UPnP/ESDP", NULL, 0 }, { 0x0011, "HIDP", NULL, 0 }, { 0x0012, "HardcopyControlChannel", NULL, 0 }, @@ -242,11 +250,11 @@ static struct uuid_def uuid16_names[] = { { 0x001d, "UDI_C-Plane", NULL, 0 }, { 0x0100, "L2CAP", NULL, 0 }, /* -- Services -- */ - { 0x1000, "ServiceDiscoveryServerServiceClassID (SDP)", + { 0x1000, "ServiceDiscoveryServerServiceClassID", sdp_attrib_names, sizeof(sdp_attrib_names)/sizeof(struct attrib_def) }, - { 0x1001, "BrowseGroupDescriptorServiceClassID (SDP)", + { 0x1001, "BrowseGroupDescriptorServiceClassID", browse_attrib_names, sizeof(browse_attrib_names)/sizeof(struct attrib_def) }, - { 0x1002, "PublicBrowseGroup (SDP)", NULL, 0 }, + { 0x1002, "PublicBrowseGroup", NULL, 0 }, { 0x1101, "SerialPort", NULL, 0 }, { 0x1102, "LANAccessUsingPPP", NULL, 0 }, { 0x1103, "DialupNetworking (DUN)", NULL, 0 }, @@ -276,7 +284,10 @@ static struct uuid_def uuid16_names[] = { 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 }, @@ -411,9 +422,9 @@ static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, 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; + 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) { @@ -484,7 +495,7 @@ static void sdp_data_printf(sdp_data_t *sdpdata, struct attrib_context *context, /* * Parse a single attribute. */ -static void sdp_attr_printf_func(void *value, void *userData) +static void print_tree_attr_func(void *value, void *userData) { sdp_data_t *sdpdata = NULL; uint16_t attrId; @@ -535,11 +546,191 @@ static void sdp_attr_printf_func(void *value, void *userData) * We assume the record has already been read, parsed and cached * locally. Jean II */ -static void sdp_printf_service_attr(sdp_record_t *rec) +static void print_tree_attr(sdp_record_t *rec) { if (rec && rec->attrlist) { struct service_context service = { NULL }; - sdp_list_foreach(rec->attrlist, sdp_attr_printf_func, &service); + sdp_list_foreach(rec->attrlist, print_tree_attr_func, &service); + } +} + +static void print_raw_data(sdp_data_t *data, int indent) +{ + struct uuid_def *def; + char *str; + int i, hex; + + if (!data) + return; + + for (i = 0; i < indent; i++) + printf("\t"); + + switch (data->dtd) { + case SDP_DATA_NIL: + printf("NIL\n"); + break; + case SDP_BOOL: + printf("Bool %s\n", data->val.uint8 ? "True" : "False"); + break; + case SDP_UINT8: + printf("UINT8 0x%02x\n", data->val.uint8); + break; + case SDP_UINT16: + printf("UINT16 0x%04x\n", data->val.uint16); + break; + case SDP_UINT32: + printf("UINT32 0x%08x\n", data->val.uint32); + break; + case SDP_UINT64: + printf("UINT64 0x%016llx\n", data->val.uint64); + break; + case SDP_UINT128: + printf("UINT128 ...\n"); + break; + case SDP_INT8: + printf("INT8 %d\n", data->val.int8); + break; + case SDP_INT16: + printf("INT16 %d\n", data->val.int16); + break; + case SDP_INT32: + printf("INT32 %d\n", data->val.int32); + break; + case SDP_INT64: + printf("INT64 %lld\n", data->val.int64); + break; + case SDP_INT128: + printf("INT128 ...\n"); + break; + case SDP_UUID16: + case SDP_UUID32: + case SDP_UUID128: + switch (data->val.uuid.type) { + case SDP_UUID16: + def = NULL; + for (i = 0; i < uuid16_max; i++) + if (uuid16_names[i].num == data->val.uuid.value.uuid16) { + def = &uuid16_names[i]; + break; + } + if (def) + printf("UUID16 0x%04x - %s\n", data->val.uuid.value.uuid16, def->name); + else + printf("UUID16 0x%04x\n", data->val.uuid.value.uuid16); + break; + case SDP_UUID32: + def = NULL; + if (!(data->val.uuid.value.uuid32 & 0xffff0000)) { + uint16_t value = data->val.uuid.value.uuid32; + for (i = 0; i < uuid16_max; i++) + if (uuid16_names[i].num == value) { + def = &uuid16_names[i]; + break; + } + } + if (def) + printf("UUID32 0x%08x - %s\n", data->val.uuid.value.uuid32, def->name); + else + printf("UUID32 0x%08x\n", data->val.uuid.value.uuid32); + break; + case SDP_UUID128: + printf("UUID128 "); + for (i = 0; i < 16; i++) { + switch (i) { + case 4: + case 6: + case 8: + case 10: + printf("-"); + break; + } + printf("%02x", (unsigned char ) data->val.uuid.value.uuid128.data[i]); + } + printf("\n"); + break; + default: + printf("UUID type 0x%02x\n", data->val.uuid.type); + break; + } + break; + case SDP_TEXT_STR8: + case SDP_TEXT_STR16: + case SDP_TEXT_STR32: + str = data->val.str; + if (data->unitSize > strlen(str) + 1) { + hex = 0; + for (i = 0; i < data->unitSize - 1; i++) + if (!isprint(str[i])) { + hex = 1; + break; + } + if (str[data->unitSize - 1] != '\0') + hex = 1; + } else + hex = 0; + if (hex) { + printf("String"); + for (i = 0; i < data->unitSize; i++) + printf(" %02x", (unsigned char) str[i]); + printf("\n"); + } else + printf("String %s\n", str); + break; + case SDP_URL_STR8: + case SDP_URL_STR16: + case SDP_URL_STR32: + printf("URL %s\n", data->val.str); + break; + case SDP_SEQ8: + case SDP_SEQ16: + case SDP_SEQ32: + printf("Sequence\n"); + print_raw_data(data->val.dataseq, indent + 1); + break; + case SDP_ALT8: + case SDP_ALT16: + case SDP_ALT32: + printf("Alternate\n"); + print_raw_data(data->val.dataseq, indent + 1); + break; + default: + printf("Unknown type 0x%02x\n", data->dtd); + break; + } + + print_raw_data(data->next, indent); +} + +static void print_raw_attr_func(void *value, void *userData) +{ + sdp_data_t *data = (sdp_data_t *) value; + struct attrib_def *def = NULL; + int i; + + /* Search amongst the generic attributes */ + for (i = 0; i < attrib_max; i++) + if (attrib_names[i].num == data->attrId) { + def = &attrib_names[i]; + break; + } + + if (def) + printf("\tAttribute 0x%04x - %s\n", data->attrId, def->name); + else + printf("\tAttribute 0x%04x\n", data->attrId); + + if (data) + print_raw_data(data, 2); + else + printf(" NULL value\n"); +} + +static void print_raw_attr(sdp_record_t *rec) +{ + if (rec && rec->attrlist) { + printf("Sequence\n"); + sdp_list_foreach(rec->attrlist, print_raw_attr_func, 0); } } @@ -2219,10 +2410,12 @@ static int do_search(bdaddr_t *bdaddr, struct search_context *context) return -1; } - if (context->svc) - printf("Searching for %s on %s ...\n", context->svc, str); - else - printf("Browsing %s ...\n", str); + if (context->view != RAW_VIEW) { + if (context->svc) + printf("Searching for %s on %s ...\n", context->svc, str); + else + printf("Browsing %s ...\n", str); + } attrid = sdp_list_append(0, &range); search = sdp_list_append(0, &context->group); @@ -2238,15 +2431,23 @@ static int do_search(bdaddr_t *bdaddr, struct search_context *context) sdp_record_t *rec = (sdp_record_t *) seq->data; struct search_context sub_context; - if (context->tree) { - /* Display full tree */ - sdp_printf_service_attr(rec); - } else { + switch (context->view) { + case DEFAULT_VIEW: /* Display user friendly form */ print_service_attr(rec); + printf("\n"); + break; + case TREE_VIEW: + /* Display full tree */ + print_tree_attr(rec); + printf("\n"); + break; + default: + /* Display raw tree */ + print_raw_attr(rec); + break; } - printf("\n"); - + if (sdp_get_group_id(rec, &sub_context.group) != -1) { /* Set the subcontext for browsing the sub tree */ memcpy(&sub_context, context, sizeof(struct search_context)); @@ -2266,6 +2467,7 @@ static int do_search(bdaddr_t *bdaddr, struct search_context *context) static struct option browse_options[] = { { "help", 0, 0, 'h' }, { "tree", 0, 0, 't' }, + { "raw", 0, 0, 'r' }, { "uuid", 1, 0, 'u' }, { "l2cap", 0, 0, 'l' }, { 0, 0, 0, 0 } @@ -2273,7 +2475,7 @@ static struct option browse_options[] = { static char *browse_help = "Usage:\n" - "\tbrowse [--tree] [--uuid uuid] [--l2cap] [bdaddr]\n"; + "\tbrowse [--tree] [--raw] [--uuid uuid] [--l2cap] [bdaddr]\n"; /* * Browse the full SDP database (i.e. list all services starting from the @@ -2292,7 +2494,10 @@ static int cmd_browse(int argc, char **argv) for_each_opt(opt, browse_options, 0) { switch (opt) { case 't': - context.tree = 1; + context.view = TREE_VIEW; + break; + case 'r': + context.view = RAW_VIEW; break; case 'u': if (sscanf(optarg, "%i", &num) != 1 || num < 0 || num > 0xffff) { @@ -2322,15 +2527,16 @@ static int cmd_browse(int argc, char **argv) } static struct option search_options[] = { - { "help", 0,0, 'h' }, - { "bdaddr", 1,0, 'b' }, - { "tree", 0,0, 't' }, + { "help", 0,0, 'h' }, + { "bdaddr", 1,0, 'b' }, + { "tree", 0,0, 't' }, + { "raw", 0, 0, 'r' }, { 0, 0, 0, 0} }; static char *search_help = "Usage:\n" - "\tsearch [--bdaddr bdaddr] [--tree] SERVICE\n" + "\tsearch [--bdaddr bdaddr] [--tree] [--raw] SERVICE\n" "SERVICE is a name (string) or UUID (0x1002)\n"; /* @@ -2361,7 +2567,10 @@ static int cmd_search(int argc, char **argv) has_addr = 1; break; case 't': - context.tree = 1; + context.view = TREE_VIEW; + break; + case 'r': + context.view = RAW_VIEW; break; default: printf(search_help); @@ -2435,19 +2644,29 @@ static int get_service(bdaddr_t *bdaddr, struct search_context *context, int qui sdp_list_free(attrid, 0); sdp_close(session); if (!rec) { - if (!quite) + if (!quite) { printf("Service get request failed.\n"); - return -1; + return -1; + } else + return 0; } - if (context->tree) { - /* Display full tree */ - sdp_printf_service_attr(rec); - } else { + switch (context->view) { + case DEFAULT_VIEW: /* Display user friendly form */ print_service_attr(rec); + printf("\n"); + break; + case TREE_VIEW: + /* Display full tree */ + print_tree_attr(rec); + printf("\n"); + break; + default: + /* Display raw tree */ + print_raw_attr(rec); + break; } - printf("\n"); sdp_record_free(rec); return 0; @@ -2456,12 +2675,13 @@ static int get_service(bdaddr_t *bdaddr, struct search_context *context, int qui static struct option records_options[] = { { "help", 0, 0, 'h' }, { "tree", 0, 0, 't' }, + { "raw", 0, 0, 'r' }, { 0, 0, 0, 0 } }; static char *records_help = "Usage:\n" - "\trecords [--tree] bdaddr\n"; + "\trecords [--tree] [--raw] bdaddr\n"; /* * Request possible SDP service records @@ -2469,9 +2689,9 @@ static char *records_help = static int cmd_records(int argc, char **argv) { struct search_context context; - uint32_t base[] = { 0x10000, 0x1002e }; + uint32_t base[] = { 0x10000, 0x1002e, 0x110b }; bdaddr_t bdaddr; - int i, n, opt, num = 32; + int i, n, opt, err = 0, num = 32; /* Initialise context */ memset(&context, '\0', sizeof(struct search_context)); @@ -2479,7 +2699,10 @@ static int cmd_records(int argc, char **argv) for_each_opt(opt, records_options, 0) { switch (opt) { case 't': - context.tree = 1; + context.view = TREE_VIEW; + break; + case 'r': + context.view = RAW_VIEW; break; default: printf(records_help); @@ -2500,22 +2723,26 @@ static int cmd_records(int argc, char **argv) for (i = 0; i < sizeof(base) / sizeof(uint32_t); i++) for (n = 0; n < num; n++) { context.handle = base[i] + n; - get_service(&bdaddr, &context, 1); + err = get_service(&bdaddr, &context, 1); + if (err < 0) + goto done; } +done: return 0; } static struct option get_options[] = { - { "help", 0,0, 'h' }, - { "bdaddr", 1,0, 'b' }, - { "tree", 0,0, 't' }, + { "help", 0, 0, 'h' }, + { "bdaddr", 1, 0, 'b' }, + { "tree", 0, 0, 't' }, + { "raw", 0, 0, 'r' }, { 0, 0, 0, 0 } }; static char *get_help = "Usage:\n" - "\tget [--tree] [--bdaddr bdaddr] record_handle\n"; + "\tget [--tree] [--raw] [--bdaddr bdaddr] record_handle\n"; /* * Get a specific SDP record on the local SDP server @@ -2537,7 +2764,10 @@ static int cmd_get(int argc, char **argv) has_addr = 1; break; case 't': - context.tree = 1; + context.view = TREE_VIEW; + break; + case 'r': + context.view = RAW_VIEW; break; default: printf(get_help); -- cgit From ef24c2a9db8b95032e4d87b730dcffdf1b9901a4 Mon Sep 17 00:00:00 2001 From: Stephen Crane Date: Fri, 24 Jun 2005 13:56:56 +0000 Subject: fix help message --- tools/sdptool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index d015f12f..97282e8d 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2812,8 +2812,8 @@ static void usage(void) printf("Usage:\n" "\tsdptool [options] [command parameters]\n"); printf("Options:\n" - "\t--help\t\tDisplay help\n" - "\t--source\tSpecify source interface\n"); + "\t-h\t\tDisplay help\n" + "\t-i\t\tSpecify source interface\n"); printf("Commands:\n"); for (i = 0; command[i].cmd; i++) -- cgit From 1f422e5f2b343d35a8c77ce4be16f74b2819b2bf Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 5 Jul 2005 21:15:41 +0000 Subject: Fix some GCC 4.0 warnings --- tools/sdptool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 97282e8d..3a2ce834 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -874,7 +874,7 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri if (!strncasecmp(argv[i], "u0x", 3)) { /* UUID16 */ uint16_t value_int = strtoul((argv[i]) + 3, NULL, 16); - uuid_t *value_uuid = (uuid_t *)malloc(sizeof(uuid_t)); + uuid_t *value_uuid = (uuid_t *) malloc(sizeof(uuid_t)); allocArray[i] = value_uuid; sdp_uuid16_create(value_uuid, value_int); @@ -883,7 +883,7 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri valueArray[i] = &value_uuid->value.uuid16; } else if (!strncasecmp(argv[i], "0x", 2)) { /* Int */ - uint32_t *value_int = (int *)malloc(sizeof(int)); + uint32_t *value_int = (uint32_t *) malloc(sizeof(int)); allocArray[i] = value_int; *value_int = strtoul((argv[i]) + 2, NULL, 16); -- cgit From ef05ec89bbe7f2460d64e1206799c63913c71df5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 5 Aug 2005 02:59:49 +0000 Subject: Use the new device specific functions --- tools/sdptool.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 3a2ce834..b3f4648c 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -782,7 +782,7 @@ static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, cha } /* Update on the server */ - if (sdp_record_update(sess, rec)) { + if (sdp_device_record_update(sess, &interface, rec)) { printf("Service Record update failed (%d).\n", errno); return -1; } @@ -904,7 +904,7 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri sdp_attr_replace(rec, attrib, pSequenceHolder); /* Update on the server */ - if (sdp_record_update(session, rec)) { + if (sdp_device_record_update(session, &interface, rec)) { printf("Service Record update failed (%d).\n", errno); return -1; } @@ -1170,7 +1170,7 @@ static int add_sp(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Serial Port", 0, "COM Port"); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1228,7 +1228,7 @@ static int add_dun(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Dial-Up Networking", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1284,7 +1284,7 @@ static int add_lan(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "LAN Access over PPP", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1343,7 +1343,7 @@ static int add_headset(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Headset", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1405,7 +1405,7 @@ static int add_handsfree(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Handsfree", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1467,7 +1467,7 @@ static int add_simaccess(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "SIM Access", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1525,7 +1525,7 @@ static int add_fax(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Fax", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1598,7 +1598,7 @@ static int add_opush(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "OBEX Object Push", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1659,7 +1659,7 @@ static int add_ftp(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "OBEX File Transfer", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1732,7 +1732,7 @@ static int add_nap(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Network Access Point Service", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1791,7 +1791,7 @@ static int add_gn(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Group Network Service", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1853,7 +1853,7 @@ static int add_panu(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "PAN User", NULL, NULL); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1910,7 +1910,7 @@ static int add_ctp(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Cordless Telephony", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto end; @@ -1968,7 +1968,7 @@ static int add_a2source(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Audio Source", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto done; @@ -2027,7 +2027,7 @@ static int add_a2sink(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Audio Sink", 0, 0); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); ret = -1; goto done; @@ -2078,7 +2078,7 @@ static int add_syncml(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "SyncML Client", NULL, NULL); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); return -1; } @@ -2112,7 +2112,7 @@ static int add_nokiaid(sdp_session_t *session, svc_info_t *si) sdp_attr_add(&record, SDP_ATTR_SERVICE_VERSION, version); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); sdp_data_free(version); return -1; @@ -2155,7 +2155,7 @@ static int add_pcsuite(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "Nokia PC Suite", NULL, NULL); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); return -1; } @@ -2187,7 +2187,7 @@ static int add_sr1(sdp_session_t *session, svc_info_t *si) sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL); - if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); return -1; } @@ -2327,7 +2327,7 @@ static int del_service(bdaddr_t *bdaddr, void *arg) return -1; } - if (sdp_record_unregister(sess, rec)) { + if (sdp_device_record_unregister(sess, &interface, rec)) { printf("Failed to unregister service record: %s\n", strerror(errno)); sdp_close(sess); return -1; -- cgit From 08ecd7d64afc3493046db2e09e5e8f875571ee84 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 7 Aug 2005 11:24:49 +0000 Subject: Add UUIDs for phonebook access profile --- tools/sdptool.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index b3f4648c..f6a47ddf 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -302,6 +302,8 @@ static struct uuid_def uuid16_names[] = { { 0x1128, "Common ISDN Access (CIP)", NULL, 0 }, { 0x1129, "VideoConferencingGW (VCP)", NULL, 0 }, { 0x112d, "SIM Access (SAP)", NULL, 0 }, + { 0x112e, "Phonebook Access (PBAP) - PCE", NULL, 0 }, + { 0x112f, "Phonebook Access (PBAP) - PSE", NULL, 0 }, /* ... */ { 0x1200, "PnPInformation", did_attrib_names, sizeof(did_attrib_names)/sizeof(struct attrib_def) }, -- cgit From 326acb25fa999f4cf908a69412e9dc6f429f9d49 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 7 Aug 2005 11:28:27 +0000 Subject: Add missing UUID translations --- tools/sdptool.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index f6a47ddf..96a95cc8 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -301,6 +301,9 @@ static struct uuid_def uuid16_names[] = { { 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 }, @@ -312,6 +315,10 @@ static struct uuid_def uuid16_names[] = { { 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 }, }; static const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def); -- cgit From 6b4fc0af31df1b4736c2209893b2b7d8890b0ed7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 7 Aug 2005 11:42:07 +0000 Subject: Add support for HotSync service records --- tools/sdptool.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 96a95cc8..41e2fc09 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2097,6 +2097,36 @@ static int add_syncml(sdp_session_t *session, svc_info_t *si) return 0; } +static unsigned char hotsync_uuid[] = { 0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51, + 0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 }; + +static int add_hotsync(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass; + uuid_t root_uuid, svclass_uuid; + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("HotSync service record registered\n"); + + return 0; +} + static unsigned char nokid_uuid[] = { 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; @@ -2237,6 +2267,7 @@ struct { { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink }, { "SYNCML", 0, add_syncml, syncml_uuid }, + { "HOTSYNC", 0, add_hotsync, hotsync_uuid }, { "NOKID", 0, add_nokiaid, nokid_uuid }, { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, { "SR1", 0, add_sr1, sr1_uuid }, -- cgit From 9781497af59916008927db6089cd38f782e16261 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 19 Aug 2005 14:40:45 +0000 Subject: Add support for HotSync and ActiveSync profiles --- tools/sdptool.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 3 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 41e2fc09..fd824c2c 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2097,10 +2097,94 @@ static int add_syncml(sdp_session_t *session, svc_info_t *si) return 0; } -static unsigned char hotsync_uuid[] = { 0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51, - 0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 }; +static unsigned char async_uuid[] = { 0x03, 0x50, 0x27, 0x8F, 0x3D, 0xCA, 0x4E, 0x62, + 0x83, 0x1D, 0xA4, 0x11, 0x65, 0xFF, 0x90, 0x6C }; + +static int add_activesync(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass, *proto; + uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; + uint8_t channel = si->channel? si->channel: 21; + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto = sdp_list_append(proto, sdp_list_append( + sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); + + sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); + + sdp_uuid128_create(&svclass_uuid, (void *) async_uuid); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + + sdp_set_info_attr(&record, "Microsoft ActiveSync", NULL, NULL); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("ActiveSync service record registered\n"); + + return 0; +} + +static unsigned char hotsync_uuid[] = { 0xD8, 0x0C, 0xF9, 0xEA, 0x13, 0x4C, 0x11, 0xD5, + 0x83, 0xCE, 0x00, 0x30, 0x65, 0x7C, 0x54, 0x3C }; static int add_hotsync(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass, *proto; + uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; + uint8_t channel = si->channel? si->channel: 22; + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto = sdp_list_append(proto, sdp_list_append( + sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); + + sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); + + sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + + sdp_set_info_attr(&record, "PalmOS HotSync", NULL, NULL); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("HotSync service record registered\n"); + + return 0; +} + +static unsigned char palmos_uuid[] = { 0xF5, 0xBE, 0xB6, 0x51, 0x41, 0x71, 0x40, 0x51, + 0xAC, 0xF5, 0x6C, 0xA7, 0x20, 0x22, 0x42, 0xF0 }; + +static int add_palmos(sdp_session_t *session, svc_info_t *si) { sdp_record_t record; sdp_list_t *root, *svclass; @@ -2122,7 +2206,7 @@ static int add_hotsync(sdp_session_t *session, svc_info_t *si) return -1; } - printf("HotSync service record registered\n"); + printf("PalmOS service record registered\n"); return 0; } @@ -2267,7 +2351,9 @@ struct { { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink }, { "SYNCML", 0, add_syncml, syncml_uuid }, + { "ACTIVESYNC", 0, add_activesync, async_uuid }, { "HOTSYNC", 0, add_hotsync, hotsync_uuid }, + { "PALMOS", 0, add_palmos, palmos_uuid }, { "NOKID", 0, add_nokiaid, nokid_uuid }, { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, { "SR1", 0, add_sr1, sr1_uuid }, -- cgit From fad20a44db8a86d6687c6c57e3f7e18a5320c95e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 16 Sep 2005 04:18:46 +0000 Subject: Fix wrong UUID-128 for the PalmOS id record --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index fd824c2c..6c07cfab 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2197,7 +2197,7 @@ static int add_palmos(sdp_session_t *session, svc_info_t *si) root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(&record, root); - sdp_uuid128_create(&svclass_uuid, (void *) hotsync_uuid); + sdp_uuid128_create(&svclass_uuid, (void *) palmos_uuid); svclass = sdp_list_append(NULL, &svclass_uuid); sdp_set_service_classes(&record, svclass); -- cgit From 632a9432774ff3a0c6e556e8f32a565b38890767 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 29 Oct 2005 22:36:31 +0000 Subject: Big cleanup of CVS relics --- tools/sdptool.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 6c07cfab..052c0b05 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -10,24 +10,19 @@ * * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; + * 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. * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY - * CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * 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. * - * ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, - * COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS - * SOFTWARE IS DISCLAIMED. + * 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 * - * - * $Id$ */ #ifdef HAVE_CONFIG_H -- cgit From 518f2131be6bbc676121e6558f190950308958e3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 29 Nov 2005 20:37:43 +0000 Subject: Add support for AVRCP specific service records --- tools/sdptool.c | 192 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 159 insertions(+), 33 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 052c0b05..6074ef77 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2047,6 +2047,162 @@ done: return ret; } +static int add_avrct(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, l2cap, avctp, avrct; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + sdp_data_t *psm, *version, *features; + uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&avrct, AV_REMOTE_SVCLASS_ID); + svclass_id = sdp_list_append(0, &avrct); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap); + psm = sdp_data_alloc(SDP_UINT16, &lp); + proto[0] = sdp_list_append(proto[0], psm); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&avctp, AVCTP_UUID); + proto[1] = sdp_list_append(0, &avctp); + version = sdp_data_alloc(SDP_UINT16, &ver); + proto[1] = sdp_list_append(proto[1], version); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + features = sdp_data_alloc(SDP_UINT16, &feat); + sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); + + sdp_set_info_attr(&record, "AVRCP CT", 0, 0); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto done; + } + + printf("Remote control service registered\n"); + +done: + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static int add_avrtg(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, l2cap, avctp, avrtg; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + sdp_data_t *psm, *version, *features; + uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = 0xffffffff; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&avrtg, AV_REMOTE_TARGET_SVCLASS_ID); + svclass_id = sdp_list_append(0, &avrtg); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, AV_REMOTE_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap); + psm = sdp_data_alloc(SDP_UINT16, &lp); + proto[0] = sdp_list_append(proto[0], psm); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&avctp, AVCTP_UUID); + proto[1] = sdp_list_append(0, &avctp); + version = sdp_data_alloc(SDP_UINT16, &ver); + proto[1] = sdp_list_append(proto[1], version); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + features = sdp_data_alloc(SDP_UINT16, &feat); + sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); + + sdp_set_info_attr(&record, "AVRCP TG", 0, 0); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto done; + } + + printf("Remote target service registered\n"); + +done: + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + +static unsigned char sr1_uuid[] = { 0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0, + 0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 }; + +static int add_sr1(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass; + uuid_t root_uuid, svclass_uuid; + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + + sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("Toshiba Speech Recognition SR-1 service record registered\n"); + + return 0; +} + static unsigned char syncml_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 }; @@ -2283,38 +2439,6 @@ static int add_pcsuite(sdp_session_t *session, svc_info_t *si) return 0; } -static unsigned char sr1_uuid[] = { 0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0, - 0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 }; - -static int add_sr1(sdp_session_t *session, svc_info_t *si) -{ - sdp_record_t record; - sdp_list_t *root, *svclass; - uuid_t root_uuid, svclass_uuid; - - memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; - - sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); - root = sdp_list_append(NULL, &root_uuid); - sdp_set_browse_groups(&record, root); - - sdp_uuid128_create(&svclass_uuid, (void *) sr1_uuid); - svclass = sdp_list_append(NULL, &svclass_uuid); - sdp_set_service_classes(&record, svclass); - - sdp_set_info_attr(&record, "TOSHIBA SR-1", NULL, NULL); - - if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { - printf("Service Record registration failed\n"); - return -1; - } - - printf("Toshiba Speech Recognition SR-1 service record registered\n"); - - return 0; -} - struct { char *name; uint16_t class; @@ -2344,14 +2468,16 @@ struct { { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source }, { "A2SNK", AUDIO_SINK_SVCLASS_ID, add_a2sink }, + { "AVRCT", AV_REMOTE_SVCLASS_ID, add_avrct }, + { "AVRTG", AV_REMOTE_TARGET_SVCLASS_ID, add_avrtg }, + { "SR1", 0, add_sr1, sr1_uuid }, { "SYNCML", 0, add_syncml, syncml_uuid }, { "ACTIVESYNC", 0, add_activesync, async_uuid }, { "HOTSYNC", 0, add_hotsync, hotsync_uuid }, { "PALMOS", 0, add_palmos, palmos_uuid }, { "NOKID", 0, add_nokiaid, nokid_uuid }, { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, - { "SR1", 0, add_sr1, sr1_uuid }, { 0 } }; -- cgit From 4312264fa42014771b188da1d61c3911026390e8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 9 Dec 2005 09:09:33 +0000 Subject: Fix display of text strings --- tools/sdptool.c | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 6074ef77..2fcd0c7a 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -561,7 +561,6 @@ static void print_tree_attr(sdp_record_t *rec) static void print_raw_data(sdp_data_t *data, int indent) { struct uuid_def *def; - char *str; int i, hex; if (!data) @@ -661,25 +660,18 @@ static void print_raw_data(sdp_data_t *data, int indent) case SDP_TEXT_STR8: case SDP_TEXT_STR16: case SDP_TEXT_STR32: - str = data->val.str; - if (data->unitSize > strlen(str) + 1) { - hex = 0; - for (i = 0; i < data->unitSize - 1; i++) - if (!isprint(str[i])) { - hex = 1; - break; - } - if (str[data->unitSize - 1] != '\0') + hex = 0; + for (i = 0; i < data->unitSize; i++) + if (!isprint(data->val.str[i])) { hex = 1; - } else - hex = 0; - if (hex) { - printf("String"); - for (i = 0; i < data->unitSize; i++) - printf(" %02x", (unsigned char) str[i]); - printf("\n"); - } else - printf("String %s\n", str); + break; + } + for (i = 0; i < data->unitSize; i++) + if (hex) + printf(" %02x", (unsigned char) data->val.str[i]); + else + printf("%c", data->val.str[i]); + printf("\n"); break; case SDP_URL_STR8: case SDP_URL_STR16: -- cgit From 6ab0c763564fb55fc50f2f8ce4712fc718321635 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 13 Dec 2005 10:35:27 +0000 Subject: Fix display of text and data strings --- tools/sdptool.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 2fcd0c7a..b3124c58 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -666,11 +666,15 @@ static void print_raw_data(sdp_data_t *data, int indent) hex = 1; break; } - for (i = 0; i < data->unitSize; i++) - if (hex) + if (hex) { + printf("Data"); + for (i = 0; i < data->unitSize; i++) printf(" %02x", (unsigned char) data->val.str[i]); - else + } else { + printf("String "); + for (i = 0; i < data->unitSize; i++) printf("%c", data->val.str[i]); + } printf("\n"); break; case SDP_URL_STR8: -- cgit From f2e48c44a7e4c9ee31b8ce2e302186f6047cfeab Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jan 2006 13:28:56 +0000 Subject: Update copyright information --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index b3124c58..689f724d 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -4,7 +4,7 @@ * * Copyright (C) 2001-2002 Nokia Corporation * Copyright (C) 2002-2003 Maxim Krasnyansky - * Copyright (C) 2002-2005 Marcel Holtmann + * Copyright (C) 2002-2006 Marcel Holtmann * Copyright (C) 2002-2003 Stephen Crane * Copyright (C) 2002-2003 Jean Tourrilhes * -- cgit From 4fe03a99ce951164c711e7f2146f2bee6df44c64 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jan 2006 13:31:18 +0000 Subject: Use %jx instead of %llx for uint64_t and int64_t --- tools/sdptool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 689f724d..8749e0b5 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -586,7 +586,7 @@ static void print_raw_data(sdp_data_t *data, int indent) printf("UINT32 0x%08x\n", data->val.uint32); break; case SDP_UINT64: - printf("UINT64 0x%016llx\n", data->val.uint64); + printf("UINT64 0x%016jx\n", data->val.uint64); break; case SDP_UINT128: printf("UINT128 ...\n"); @@ -601,7 +601,7 @@ static void print_raw_data(sdp_data_t *data, int indent) printf("INT32 %d\n", data->val.int32); break; case SDP_INT64: - printf("INT64 %lld\n", data->val.int64); + printf("INT64 %jd\n", data->val.int64); break; case SDP_INT128: printf("INT128 ...\n"); -- cgit From a0de58e012d1d85dcbef1c52eb082ea6c8a8e9de Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jan 2006 15:26:43 +0000 Subject: Add UUID for N-Gage games --- tools/sdptool.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 8749e0b5..39583530 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2435,6 +2435,9 @@ static int add_pcsuite(sdp_session_t *session, svc_info_t *si) return 0; } +static unsigned char ngage_uuid[] = { 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; + struct { char *name; uint16_t class; @@ -2474,6 +2477,7 @@ struct { { "PALMOS", 0, add_palmos, palmos_uuid }, { "NOKID", 0, add_nokiaid, nokid_uuid }, { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, + { "NGAGE", 0, NULL, ngage_uuid }, { 0 } }; -- cgit From b27690df2da69d959a78d95483217a0a5c529cfb Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 3 Jan 2006 21:03:23 +0000 Subject: Add UUID for Apple Macintosh Attributes --- tools/sdptool.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 39583530..ea4e4d3d 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2438,6 +2438,9 @@ static int add_pcsuite(sdp_session_t *session, svc_info_t *si) static unsigned char ngage_uuid[] = { 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; +static unsigned char apple_uuid[] = { 0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e, 0x90, + 0x8c, 0xc2, 0x1b, 0x46, 0xf5, 0xf2, 0xef, 0xe2 }; + struct { char *name; uint16_t class; @@ -2478,6 +2481,7 @@ struct { { "NOKID", 0, add_nokiaid, nokid_uuid }, { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, { "NGAGE", 0, NULL, ngage_uuid }, + { "APPLE", 0, NULL, apple_uuid }, { 0 } }; -- cgit From f83f040580da69b2e95ac817d308724bc35e75da Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 4 Jan 2006 00:05:22 +0000 Subject: dd definitions for Apple Agent --- tools/sdptool.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index ea4e4d3d..2b291aa5 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -314,6 +314,7 @@ static struct uuid_def uuid16_names[] = { { 0x1303, "VideoSource", NULL, 0 }, { 0x1304, "VideoSink", NULL, 0 }, { 0x1305, "VideoDistribution", NULL, 0 }, + { 0x2112, "AppleAgent", NULL, 0 }, }; static const int uuid16_max = sizeof(uuid16_names)/sizeof(struct uuid_def); @@ -2483,6 +2484,8 @@ struct { { "NGAGE", 0, NULL, ngage_uuid }, { "APPLE", 0, NULL, apple_uuid }, + { "ISYNC", APPLE_AGENT_SVCLASS_ID, NULL, }, + { 0 } }; -- cgit From b769dcbea87081a6e0010db03a97f163256cd372 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 4 Jan 2006 01:38:54 +0000 Subject: Add Apple attributes and iSync records --- tools/sdptool.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 81 insertions(+), 2 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 2b291aa5..ae2925cc 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2442,6 +2442,85 @@ static unsigned char ngage_uuid[] = { 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, static unsigned char apple_uuid[] = { 0xf0, 0x72, 0x2e, 0x20, 0x0f, 0x8b, 0x4e, 0x90, 0x8c, 0xc2, 0x1b, 0x46, 0xf5, 0xf2, 0xef, 0xe2 }; +static int add_apple(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root; + uuid_t root_uuid; + uint32_t attr783 = 0x00000000; + uint32_t attr785 = 0x00000002; + uint16_t attr786 = 0x1234; + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_attr_add_new(&record, 0x0780, SDP_UUID128, (void *) apple_uuid); + sdp_attr_add_new(&record, 0x0781, SDP_TEXT_STR8, (void *) "Macmini"); + sdp_attr_add_new(&record, 0x0782, SDP_TEXT_STR8, (void *) "PowerMac10,1"); + sdp_attr_add_new(&record, 0x0783, SDP_UINT32, (void *) &attr783); + sdp_attr_add_new(&record, 0x0784, SDP_TEXT_STR8, (void *) "1.6.6f22"); + sdp_attr_add_new(&record, 0x0785, SDP_UINT32, (void *) &attr785); + sdp_attr_add_new(&record, 0x0786, SDP_UUID16, (void *) &attr786); + + sdp_set_info_attr(&record, "Apple Macintosh Attributes", NULL, NULL); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("Apple attribute service registered\n"); + + return 0; +} + +static int add_isync(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass, *proto; + uuid_t root_uuid, svclass_uuid, serial_uuid, l2cap_uuid, rfcomm_uuid; + uint8_t channel = si->channel? si->channel: 8; + + memset(&record, 0, sizeof(record)); + record.handle = 0xffffffff; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto = sdp_list_append(proto, sdp_list_append( + sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); + + sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); + + sdp_uuid16_create(&serial_uuid, SERIAL_PORT_SVCLASS_ID); + svclass = sdp_list_append(NULL, &serial_uuid); + + sdp_uuid16_create(&svclass_uuid, APPLE_AGENT_SVCLASS_ID); + svclass = sdp_list_append(svclass, &svclass_uuid); + + sdp_set_service_classes(&record, svclass); + + sdp_set_info_attr(&record, "AppleAgent", "Bluetooth acceptor", "Apple Computer Ltd."); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("Apple iSync service registered\n"); + + return 0; +} + struct { char *name; uint16_t class; @@ -2482,9 +2561,9 @@ struct { { "NOKID", 0, add_nokiaid, nokid_uuid }, { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, { "NGAGE", 0, NULL, ngage_uuid }, - { "APPLE", 0, NULL, apple_uuid }, + { "APPLE", 0, add_apple, apple_uuid }, - { "ISYNC", APPLE_AGENT_SVCLASS_ID, NULL, }, + { "ISYNC", APPLE_AGENT_SVCLASS_ID, add_isync, }, { 0 } }; -- cgit From 88e399ec1d771872d9ee895875218a3d3aa2f6ec Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 6 Jan 2006 12:59:57 +0000 Subject: Allow null-terminated strings --- tools/sdptool.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index ae2925cc..b3876233 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -662,11 +662,14 @@ static void print_raw_data(sdp_data_t *data, int indent) case SDP_TEXT_STR16: case SDP_TEXT_STR32: hex = 0; - for (i = 0; i < data->unitSize; i++) + for (i = 0; i < data->unitSize; i++) { + if (i == (data->unitSize - 1) && data->val.str[i] == '\0') + break; if (!isprint(data->val.str[i])) { hex = 1; break; } + } if (hex) { printf("Data"); for (i = 0; i < data->unitSize; i++) -- cgit From e9799abfdd2520e3adbd5c3a1d27a9e466361598 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 16 Jan 2006 15:09:53 +0000 Subject: Add support for the Handsfree Audio Gateway service record --- tools/sdptool.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index b3876233..55d7f590 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1303,7 +1303,6 @@ end: return ret; } - static int add_headset(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -1424,6 +1423,73 @@ end: return ret; } +static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; + sdp_profile_desc_t profile; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel: 3; + uint16_t u16 = 0x17; + sdp_data_t *channel, *features; + uint8_t netid = 0x01; // ???? profile document + sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + //record.handle = 0xffffffff; + record.handle = 0x10001; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&svclass_uuid, HANDSFREE_AGW_SVCLASS_ID); + svclass_id = sdp_list_append(0, &svclass_uuid); + sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); + svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID); + profile.version = 0x0100; + pfseq = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + features = sdp_data_alloc(SDP_UINT16, &u16); + sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Voice Gateway", 0, 0); + + sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("Handsfree AG service registered\n"); +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + return ret; +} + static int add_simaccess(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -2541,6 +2607,7 @@ struct { { "HS", HEADSET_SVCLASS_ID, add_headset }, { "HF", HANDSFREE_SVCLASS_ID, add_handsfree }, + { "HFAG", HANDSFREE_AGW_SVCLASS_ID, add_handsfree_ag}, { "SAP", SAP_SVCLASS_ID, add_simaccess }, { "NAP", NAP_SVCLASS_ID, add_nap }, -- cgit From aebaa2bd80065ac380237d2f52bc675e4d1462d1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 17 Jan 2006 10:43:04 +0000 Subject: Add support for choosing a specific service record handle --- tools/sdptool.c | 365 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 216 insertions(+), 149 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 55d7f590..02db6e2c 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -747,7 +747,7 @@ static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, cha sdp_list_t *attrid_list; uint32_t range = 0x0000ffff; sdp_record_t *rec; - + /* Get the old SDP record */ attrid_list = sdp_list_append(NULL, &range); rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attrid_list); @@ -794,7 +794,7 @@ static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, cha } static struct option set_options[] = { - { "help", 0,0, 'h' }, + { "help", 0, 0, 'h' }, { 0, 0, 0, 0 } }; @@ -819,6 +819,7 @@ static int cmd_setattr(int argc, char **argv) return -1; } } + argc -= optind; argv += optind; @@ -835,8 +836,10 @@ static int cmd_setattr(int argc, char **argv) sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); if (!sess) return -1; + status = set_attrib(sess, handle, attrib, argv[2]); sdp_close(sess); + return status; } @@ -912,13 +915,13 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri printf("Service Record update failed (%d).\n", errno); return -1; } - } else { + } else printf("Failed to create pSequenceHolder\n"); - } /* Cleanup */ for (i = 0; i < argc; i++) free(allocArray[i]); + free(dtdArray); free(valueArray); @@ -926,7 +929,7 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri } static struct option seq_options[] = { - { "help", 0,0, 'h' }, + { "help", 0, 0, 'h' }, { 0, 0, 0, 0 } }; @@ -952,6 +955,7 @@ static int cmd_setseq(int argc, char **argv) return -1; } } + argc -= optind; argv += optind; @@ -971,8 +975,10 @@ static int cmd_setseq(int argc, char **argv) sess = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); if (!sess) return -1; + status = set_attribseq(sess, handle, attrib, argc, argv); sdp_close(sess); + return status; } @@ -991,7 +997,7 @@ static void print_service_desc(void *value, void *user) char str[MAX_LEN_PROTOCOL_UUID_STR]; sdp_data_t *p = (sdp_data_t *)value, *s; int i = 0, proto = 0; - + for (; p; p = p->next, i++) { switch (p->dtd) { case SDP_UUID16: @@ -1106,10 +1112,10 @@ static void print_service_attr(sdp_record_t *rec) * Support for Service (de)registration */ typedef struct { + uint32_t handle; char *name; char *provider; char *desc; - unsigned int class; unsigned int profile; unsigned int channel; @@ -1135,12 +1141,12 @@ static int add_sp(sdp_session_t *session, svc_info_t *si) uuid_t root_uuid, sp_uuid, l2cap, rfcomm; sdp_profile_desc_t profile; sdp_record_t record; - uint8_t u8 = si->channel? si->channel: 1; + uint8_t u8 = si->channel ? si->channel : 1; sdp_data_t *channel; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1179,13 +1185,16 @@ static int add_sp(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("Serial Port service registered\n"); + end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1196,12 +1205,12 @@ static int add_dun(sdp_session_t *session, svc_info_t *si) sdp_profile_desc_t profile; sdp_list_t *proto[2]; sdp_record_t record; - uint8_t u8 = si->channel? si->channel: 1; + uint8_t u8 = si->channel ? si->channel : 2; sdp_data_t *channel; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &rootu); sdp_set_browse_groups(&record, root); @@ -1237,7 +1246,68 @@ static int add_dun(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("Dial-Up Networking service registered\n"); + +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + + return ret; +} + +static int add_fax(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, fax_uuid, tel_uuid, l2cap_uuid, rfcomm_uuid; + sdp_profile_desc_t profile; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint8_t u8 = si->channel? si->channel : 3; + sdp_data_t *channel; + int ret = 0; + + memset((void *)&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&fax_uuid, FAX_SVCLASS_ID); + svclass_id = sdp_list_append(0, &fax_uuid); + sdp_uuid16_create(&tel_uuid, GENERIC_TELEPHONY_SVCLASS_ID); + svclass_id = sdp_list_append(svclass_id, &tel_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile.uuid, FAX_PROFILE_ID); + profile.version = 0x0100; + pfseq = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Fax", 0, 0); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + printf("Fax service registered\n"); end: sdp_data_free(channel); sdp_list_free(proto[0], 0); @@ -1254,12 +1324,12 @@ static int add_lan(sdp_session_t *session, svc_info_t *si) sdp_profile_desc_t profile; sdp_list_t *aproto, *proto[2]; sdp_record_t record; - uint8_t u8 = si->channel? si->channel: 2; + uint8_t u8 = si->channel ? si->channel : 4; sdp_data_t *channel; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1293,13 +1363,16 @@ static int add_lan(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("LAN Access service registered\n"); + end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1310,12 +1383,12 @@ static int add_headset(sdp_session_t *session, svc_info_t *si) sdp_profile_desc_t profile; sdp_list_t *aproto, *proto[2]; sdp_record_t record; - uint8_t u8 = si->channel? si->channel: 5; + uint8_t u8 = si->channel ? si->channel : 5; sdp_data_t *channel; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1351,13 +1424,16 @@ static int add_headset(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("Headset service registered\n"); + end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1368,13 +1444,13 @@ static int add_handsfree(sdp_session_t *session, svc_info_t *si) sdp_profile_desc_t profile; sdp_list_t *aproto, *proto[2]; sdp_record_t record; - uint8_t u8 = si->channel? si->channel: 3; + uint8_t u8 = si->channel ? si->channel : 6; uint16_t u16 = 0x31; - sdp_data_t *channel, *features; + sdp_data_t *channel, *features; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1413,13 +1489,16 @@ static int add_handsfree(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("Handsfree service registered\n"); + end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1430,16 +1509,15 @@ static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si) sdp_profile_desc_t profile; sdp_list_t *aproto, *proto[2]; sdp_record_t record; - uint8_t u8 = si->channel? si->channel: 3; + uint8_t u8 = si->channel ? si->channel : 7; uint16_t u16 = 0x17; sdp_data_t *channel, *features; uint8_t netid = 0x01; // ???? profile document sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - //record.handle = 0xffffffff; - record.handle = 0x10001; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1480,13 +1558,16 @@ static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("Handsfree AG service registered\n"); + end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1497,13 +1578,13 @@ static int add_simaccess(sdp_session_t *session, svc_info_t *si) sdp_profile_desc_t profile; sdp_list_t *aproto, *proto[2]; sdp_record_t record; - uint8_t u8 = si->channel? si->channel: 3; + uint8_t u8 = si->channel? si->channel : 8; uint16_t u16 = 0x31; sdp_data_t *channel, *features; int ret = 0; memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1552,64 +1633,6 @@ end: return ret; } -static int add_fax(sdp_session_t *session, svc_info_t *si) -{ - sdp_list_t *svclass_id, *pfseq, *apseq, *root; - uuid_t root_uuid, fax_uuid, tel_uuid, l2cap_uuid, rfcomm_uuid; - sdp_profile_desc_t profile; - sdp_list_t *aproto, *proto[2]; - sdp_record_t record; - uint8_t u8 = si->channel? si->channel: 3; - sdp_data_t *channel; - int ret = 0; - - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; - sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); - root = sdp_list_append(0, &root_uuid); - sdp_set_browse_groups(&record, root); - - sdp_uuid16_create(&fax_uuid, FAX_SVCLASS_ID); - svclass_id = sdp_list_append(0, &fax_uuid); - sdp_uuid16_create(&tel_uuid, GENERIC_TELEPHONY_SVCLASS_ID); - svclass_id = sdp_list_append(svclass_id, &tel_uuid); - sdp_set_service_classes(&record, svclass_id); - - sdp_uuid16_create(&profile.uuid, FAX_PROFILE_ID); - profile.version = 0x0100; - pfseq = sdp_list_append(0, &profile); - sdp_set_profile_descs(&record, pfseq); - - sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); - proto[0] = sdp_list_append(0, &l2cap_uuid); - apseq = sdp_list_append(0, proto[0]); - - sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); - proto[1] = sdp_list_append(0, &rfcomm_uuid); - channel = sdp_data_alloc(SDP_UINT8, &u8); - proto[1] = sdp_list_append(proto[1], channel); - apseq = sdp_list_append(apseq, proto[1]); - - aproto = sdp_list_append(0, apseq); - sdp_set_access_protos(&record, aproto); - - sdp_set_info_attr(&record, "Fax", 0, 0); - - if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { - printf("Service Record registration failed\n"); - ret = -1; - goto end; - } - printf("Fax service registered\n"); -end: - sdp_data_free(channel); - sdp_list_free(proto[0], 0); - sdp_list_free(proto[1], 0); - sdp_list_free(apseq, 0); - sdp_list_free(aproto, 0); - return ret; -} - static int add_opush(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -1617,7 +1640,7 @@ static int add_opush(sdp_session_t *session, svc_info_t *si) sdp_profile_desc_t profile[1]; sdp_list_t *aproto, *proto[3]; sdp_record_t record; - uint8_t chan = si->channel? si->channel: 4; + uint8_t chan = si->channel ? si->channel : 9; sdp_data_t *channel; uint8_t formats[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 }; //uint8_t formats[] = { 0xff }; @@ -1627,8 +1650,8 @@ static int add_opush(sdp_session_t *session, svc_info_t *si) sdp_data_t *sflist; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1673,7 +1696,9 @@ static int add_opush(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("OBEX Object Push service registered\n"); + end: sdp_data_free(channel); sdp_list_free(proto[0], 0); @@ -1681,6 +1706,7 @@ end: sdp_list_free(proto[2], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1691,12 +1717,12 @@ static int add_ftp(sdp_session_t *session, svc_info_t *si) sdp_profile_desc_t profile[1]; sdp_list_t *aproto, *proto[3]; sdp_record_t record; - uint8_t u8 = si->channel? si->channel: 4; + uint8_t u8 = si->channel ? si->channel: 10; sdp_data_t *channel; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1734,7 +1760,9 @@ static int add_ftp(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("OBEX File Transfer service registered\n"); + end: sdp_data_free(channel); sdp_list_free(proto[0], 0); @@ -1742,6 +1770,7 @@ end: sdp_list_free(proto[2], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1756,8 +1785,8 @@ static int add_nap(sdp_session_t *session, svc_info_t *si) sdp_data_t *psm, *version; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1807,7 +1836,9 @@ static int add_nap(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("NAP service registered\n"); + end: sdp_data_free(version); sdp_data_free(psm); @@ -1815,6 +1846,7 @@ end: sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1829,8 +1861,8 @@ static int add_gn(sdp_session_t *session, svc_info_t *si) sdp_data_t *psm, *version; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1866,7 +1898,9 @@ static int add_gn(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("GN service registered\n"); + end: sdp_data_free(version); sdp_data_free(psm); @@ -1874,6 +1908,7 @@ end: sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1888,8 +1923,8 @@ static int add_panu(sdp_session_t *session, svc_info_t *si) sdp_data_t *psm, *version; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1928,7 +1963,9 @@ static int add_panu(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("PANU service registered\n"); + end: sdp_data_free(version); sdp_data_free(psm); @@ -1936,6 +1973,7 @@ end: sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -1950,8 +1988,8 @@ static int add_ctp(sdp_session_t *session, svc_info_t *si) sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1985,13 +2023,16 @@ static int add_ctp(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("CTP service registered\n"); + end: sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); sdp_data_free(network); + return ret; } @@ -2006,8 +2047,8 @@ static int add_a2source(sdp_session_t *session, svc_info_t *si) uint16_t lp = 0x0019, ver = 0x0100; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -2051,6 +2092,7 @@ done: sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -2065,8 +2107,8 @@ static int add_a2sink(sdp_session_t *session, svc_info_t *si) uint16_t lp = 0x0019, ver = 0x0100; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -2110,6 +2152,7 @@ done: sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -2124,8 +2167,8 @@ static int add_avrct(sdp_session_t *session, svc_info_t *si) uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -2172,6 +2215,7 @@ done: sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -2186,8 +2230,8 @@ static int add_avrtg(sdp_session_t *session, svc_info_t *si) uint16_t lp = 0x0017, ver = 0x0100, feat = 0x000f; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); - record.handle = 0xffffffff; + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -2234,6 +2278,7 @@ done: sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -2247,7 +2292,7 @@ static int add_sr1(sdp_session_t *session, svc_info_t *si) uuid_t root_uuid, svclass_uuid; memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); @@ -2277,10 +2322,10 @@ static int add_syncml(sdp_session_t *session, svc_info_t *si) sdp_record_t record; sdp_list_t *root, *svclass, *proto; uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; - uint8_t channel = si->channel? si->channel: 15; + uint8_t channel = si->channel ? si->channel: 15; memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); @@ -2322,10 +2367,10 @@ static int add_activesync(sdp_session_t *session, svc_info_t *si) sdp_record_t record; sdp_list_t *root, *svclass, *proto; uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; - uint8_t channel = si->channel? si->channel: 21; + uint8_t channel = si->channel ? si->channel: 21; memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); @@ -2364,10 +2409,10 @@ static int add_hotsync(sdp_session_t *session, svc_info_t *si) sdp_record_t record; sdp_list_t *root, *svclass, *proto; uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; - uint8_t channel = si->channel? si->channel: 22; + uint8_t channel = si->channel ? si->channel: 22; memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); @@ -2408,7 +2453,7 @@ static int add_palmos(sdp_session_t *session, svc_info_t *si) uuid_t root_uuid, svclass_uuid; memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); @@ -2440,7 +2485,7 @@ static int add_nokiaid(sdp_session_t *session, svc_info_t *si) sdp_data_t *version = sdp_data_alloc(SDP_UINT16, &verid); memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); @@ -2471,10 +2516,10 @@ static int add_pcsuite(sdp_session_t *session, svc_info_t *si) sdp_record_t record; sdp_list_t *root, *svclass, *proto; uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; - uint8_t channel = si->channel? si->channel: 14; + uint8_t channel = si->channel ? si->channel: 14; memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); @@ -2521,7 +2566,7 @@ static int add_apple(sdp_session_t *session, svc_info_t *si) uint16_t attr786 = 0x1234; memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); @@ -2552,10 +2597,10 @@ static int add_isync(sdp_session_t *session, svc_info_t *si) sdp_record_t record; sdp_list_t *root, *svclass, *proto; uuid_t root_uuid, svclass_uuid, serial_uuid, l2cap_uuid, rfcomm_uuid; - uint8_t channel = si->channel? si->channel: 8; + uint8_t channel = si->channel ? si->channel : 16; memset(&record, 0, sizeof(record)); - record.handle = 0xffffffff; + record.handle = si->handle; sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); @@ -2641,36 +2686,42 @@ struct { /* Add local service */ static int add_service(bdaddr_t *bdaddr, svc_info_t *si) { - int i; - sdp_session_t *sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); + sdp_session_t *sess; + int i, ret = -1; + + if (!si->name) + return -1; + sess = sdp_connect(&interface, BDADDR_LOCAL, SDP_RETRY_IF_BUSY); if (!sess) return -1; - if (si->name) - for (i = 0; service[i].name; i++) - if (!strcasecmp(service[i].name, si->name)) { - int ret = -1; - if (service[i].add) - ret = service[i].add(sess, si); - free(si->name); - sdp_close(sess); - return ret; - } + + for (i = 0; service[i].name; i++) + if (!strcasecmp(service[i].name, si->name)) { + if (service[i].add) + ret = service[i].add(sess, si); + goto done; + } + printf("Unknown service name: %s\n", si->name); + +done: free(si->name); sdp_close(sess); - return -1; + + return ret; } static struct option add_options[] = { - { "help", 0,0, 'h' }, - { "channel", 1,0, 'c' }, - { 0, 0, 0, 0} + { "help", 0, 0, 'h' }, + { "handle", 1, 0, 'r' }, + { "channel", 1, 0, 'c' }, + { 0, 0, 0, 0 } }; static char *add_help = "Usage:\n" - "\tadd [--channel=CHAN] service\n"; + "\tadd [--handle=RECORD_HANDLE --channel=CHANNEL] service\n"; static int cmd_add(int argc, char **argv) { @@ -2678,8 +2729,16 @@ static int cmd_add(int argc, char **argv) int opt; memset(&si, 0, sizeof(si)); + si.handle = 0xffffffff; + for_each_opt(opt, add_options, 0) { switch (opt) { + case 'r': + if (strncasecmp(optarg, "0x", 2)) + si.handle = atoi(optarg); + else + si.handle = strtol(optarg + 2, NULL, 16); + break; case 'c': si.channel = atoi(optarg); break; @@ -2688,6 +2747,7 @@ static int cmd_add(int argc, char **argv) return -1; } } + argc -= optind; argv += optind; @@ -2724,6 +2784,7 @@ static int del_service(bdaddr_t *bdaddr, void *arg) attr = sdp_list_append(0, &range); rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attr); sdp_list_free(attr, 0); + if (!rec) { printf("Service Record not found.\n"); sdp_close(sess); @@ -2738,11 +2799,12 @@ static int del_service(bdaddr_t *bdaddr, void *arg) printf("Service Record deleted.\n"); sdp_close(sess); + return 0; } static struct option del_options[] = { - { "help", 0,0, 'h' }, + { "help", 0, 0, 'h' }, { 0, 0, 0, 0 } }; @@ -2761,6 +2823,7 @@ static int cmd_del(int argc, char **argv) return -1; } } + argc -= optind; argv += optind; @@ -2917,6 +2980,7 @@ static int cmd_browse(int argc, char **argv) return -1; } } + argc -= optind; argv += optind; @@ -2930,9 +2994,9 @@ static int cmd_browse(int argc, char **argv) } static struct option search_options[] = { - { "help", 0,0, 'h' }, - { "bdaddr", 1,0, 'b' }, - { "tree", 0,0, 't' }, + { "help", 0, 0, 'h' }, + { "bdaddr", 1, 0, 'b' }, + { "tree", 0, 0, 't' }, { "raw", 0, 0, 'r' }, { 0, 0, 0, 0} }; @@ -2946,7 +3010,7 @@ static char *search_help = * Search for a specific SDP service * * Note : we should support multiple services on the command line : - * sdptool search 0x0100 0x000f 0x1002 + * sdptool search 0x0100 0x000f 0x1002 * (this would search a service supporting both L2CAP and BNEP directly in * the top level browse group) */ @@ -2980,6 +3044,7 @@ static int cmd_search(int argc, char **argv) return -1; } } + argc -= optind; argv += optind; @@ -2989,7 +3054,7 @@ static int cmd_search(int argc, char **argv) } /* Note : we need to find a way to support search combining - * multiple services - Jean II */ + * multiple services */ context.svc = strdup(argv[0]); if (!strncasecmp(context.svc, "0x", 2)) { int num; @@ -3026,7 +3091,6 @@ static int cmd_search(int argc, char **argv) /* * Show how to get a specific SDP record by its handle. * Not really useful to the user, just show how it can be done... - * Jean II */ static int get_service(bdaddr_t *bdaddr, struct search_context *context, int quite) { @@ -3046,6 +3110,7 @@ static int get_service(bdaddr_t *bdaddr, struct search_context *context, int qui rec = sdp_service_attr_req(session, context->handle, SDP_ATTR_REQ_RANGE, attrid); sdp_list_free(attrid, 0); sdp_close(session); + if (!rec) { if (!quite) { printf("Service get request failed.\n"); @@ -3112,6 +3177,7 @@ static int cmd_records(int argc, char **argv) return -1; } } + argc -= optind; argv += optind; @@ -3177,6 +3243,7 @@ static int cmd_get(int argc, char **argv) return -1; } } + argc -= optind; argv += optind; @@ -3202,7 +3269,7 @@ static struct { { "add", cmd_add, "Add local service" }, { "del", cmd_del, "Delete local service" }, { "get", cmd_get, "Get local service" }, - { "setattr", cmd_setattr, "Set/Add attribute to a SDP record" }, + { "setattr", cmd_setattr, "Set/Add attribute to a SDP record" }, { "setseq", cmd_setseq, "Set/Add attribute sequence to a SDP record" }, { 0, 0, 0 } }; @@ -3277,5 +3344,5 @@ int main(int argc, char **argv) if (strncmp(command[i].cmd, argv[0], 4) == 0) return command[i].func(argc, argv); - return -1; + return 1; } -- cgit From a6a6a79950afbf7b2366718b7e209da203d173d7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 21 Jan 2006 10:56:33 +0000 Subject: Add UDI service records --- tools/sdptool.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 02db6e2c..ba624401 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2282,6 +2282,88 @@ done: return ret; } +static int add_udiue(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass, *proto; + uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; + uint8_t channel = si->channel ? si->channel: 18; + + memset(&record, 0, sizeof(record)); + record.handle = si->handle; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + sdp_list_free(root, NULL); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto = sdp_list_append(proto, sdp_list_append( + sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); + + sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); + + sdp_uuid16_create(&svclass_uuid, UDI_MT_SVCLASS_ID); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + sdp_list_free(svclass, NULL); + + sdp_set_info_attr(&record, "UDI UE", NULL, NULL); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("UDI UE service registered\n"); + + return 0; +} + +static int add_udite(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *root, *svclass, *proto; + uuid_t root_uuid, svclass_uuid, l2cap_uuid, rfcomm_uuid; + uint8_t channel = si->channel ? si->channel: 19; + + memset(&record, 0, sizeof(record)); + record.handle = si->handle; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + sdp_list_free(root, NULL); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto = sdp_list_append(NULL, sdp_list_append(NULL, &l2cap_uuid)); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto = sdp_list_append(proto, sdp_list_append( + sdp_list_append(NULL, &rfcomm_uuid), sdp_data_alloc(SDP_UINT8, &channel))); + + sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); + + sdp_uuid16_create(&svclass_uuid, UDI_TA_SVCLASS_ID); + svclass = sdp_list_append(NULL, &svclass_uuid); + sdp_set_service_classes(&record, svclass); + sdp_list_free(svclass, NULL); + + sdp_set_info_attr(&record, "UDI TE", NULL, NULL); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("UDI TE service registered\n"); + + return 0; +} + static unsigned char sr1_uuid[] = { 0xbc, 0x19, 0x9c, 0x24, 0x95, 0x8b, 0x4c, 0xc0, 0xa2, 0xcb, 0xfd, 0x8a, 0x30, 0xbf, 0x32, 0x06 }; @@ -2668,6 +2750,9 @@ struct { { "AVRCT", AV_REMOTE_SVCLASS_ID, add_avrct }, { "AVRTG", AV_REMOTE_TARGET_SVCLASS_ID, add_avrtg }, + { "UDIUE", UDI_MT_SVCLASS_ID, add_udiue }, + { "UDITE", UDI_TA_SVCLASS_ID, add_udite }, + { "SR1", 0, add_sr1, sr1_uuid }, { "SYNCML", 0, add_syncml, syncml_uuid }, { "ACTIVESYNC", 0, add_activesync, async_uuid }, -- cgit From 6c53a6b4e4282459ec072a64d09a4c13a7feded5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 21 Jan 2006 11:39:07 +0000 Subject: Add service record for the ISDN profile --- tools/sdptool.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 6 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index ba624401..0484d8af 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1118,7 +1118,9 @@ typedef struct { char *desc; unsigned int class; unsigned int profile; - unsigned int channel; + uint16_t psm; + uint8_t channel; + uint8_t network; } svc_info_t; static void add_lang_attr(sdp_record_t *r) @@ -1211,6 +1213,7 @@ static int add_dun(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&rootu, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &rootu); sdp_set_browse_groups(&record, root); @@ -1270,8 +1273,9 @@ static int add_fax(sdp_session_t *session, svc_info_t *si) sdp_data_t *channel; int ret = 0; - memset((void *)&record, 0, sizeof(sdp_record_t)); + memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1330,6 +1334,7 @@ static int add_lan(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1389,6 +1394,7 @@ static int add_headset(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1451,6 +1457,7 @@ static int add_handsfree(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1512,12 +1519,13 @@ static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si) uint8_t u8 = si->channel ? si->channel : 7; uint16_t u16 = 0x17; sdp_data_t *channel, *features; - uint8_t netid = 0x01; // ???? profile document + uint8_t netid = si->network ? si->network : 0x01; // ???? profile document sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); int ret = 0; memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1585,6 +1593,7 @@ static int add_simaccess(sdp_session_t *session, svc_info_t *si) memset((void *)&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1652,6 +1661,7 @@ static int add_opush(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1723,6 +1733,7 @@ static int add_ftp(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1787,6 +1798,7 @@ static int add_nap(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1863,6 +1875,7 @@ static int add_gn(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1925,6 +1938,7 @@ static int add_panu(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(&record, root); @@ -1977,6 +1991,69 @@ end: return ret; } +static int add_cip(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, l2cap, cmtp, cip; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint16_t psm = si->psm ? si->psm : 0x1001; + uint8_t netid = si->network ? si->network : 0x02; // 0x02 = ISDN, 0x03 = GSM + sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); + int ret = 0; + + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&cip, CIP_SVCLASS_ID); + svclass_id = sdp_list_append(0, &cip); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, CIP_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, &profile[0]); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap); + apseq = sdp_list_append(0, proto[0]); + proto[0] = sdp_list_append(proto[0], sdp_data_alloc(SDP_UINT16, &psm)); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&cmtp, CMTP_UUID); + proto[1] = sdp_list_append(0, &cmtp); + apseq = sdp_list_append(apseq, proto[1]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network); + + sdp_set_info_attr(&record, "Common ISDN Access", 0, 0); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + + printf("CIP service registered\n"); + +end: + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + sdp_data_free(network); + + return ret; +} + static int add_ctp(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -1984,12 +2061,13 @@ static int add_ctp(sdp_session_t *session, svc_info_t *si) sdp_profile_desc_t profile[1]; sdp_list_t *aproto, *proto[2]; sdp_record_t record; - uint8_t netid = 0x02; // 0x01-0x07 cf. p120 profile document + uint8_t netid = si->network ? si->network : 0x02; // 0x01-0x07 cf. p120 profile document sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); int ret = 0; memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -2049,6 +2127,7 @@ static int add_a2source(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -2109,6 +2188,7 @@ static int add_a2sink(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -2169,6 +2249,7 @@ static int add_avrct(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -2232,6 +2313,7 @@ static int add_avrtg(sdp_session_t *session, svc_info_t *si) memset(&record, 0, sizeof(sdp_record_t)); record.handle = si->handle; + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(0, &root_uuid); sdp_set_browse_groups(&record, root); @@ -2742,7 +2824,7 @@ struct { { "PANU", PANU_SVCLASS_ID, add_panu }, { "HID", HID_SVCLASS_ID, NULL }, - { "CIP", CIP_SVCLASS_ID, NULL }, + { "CIP", CIP_SVCLASS_ID, add_cip }, { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, { "A2SRC", AUDIO_SOURCE_SVCLASS_ID, add_a2source }, @@ -2800,7 +2882,9 @@ done: static struct option add_options[] = { { "help", 0, 0, 'h' }, { "handle", 1, 0, 'r' }, + { "psm", 1, 0, 'p' }, { "channel", 1, 0, 'c' }, + { "network", 1, 0, 'n' }, { 0, 0, 0, 0 } }; @@ -2824,8 +2908,23 @@ static int cmd_add(int argc, char **argv) else si.handle = strtol(optarg + 2, NULL, 16); break; + case 'p': + if (strncasecmp(optarg, "0x", 2)) + si.psm = atoi(optarg); + else + si.psm = strtol(optarg + 2, NULL, 16); + break; case 'c': - si.channel = atoi(optarg); + if (strncasecmp(optarg, "0x", 2)) + si.channel = atoi(optarg); + else + si.channel = strtol(optarg + 2, NULL, 16); + break; + case 'n': + if (strncasecmp(optarg, "0x", 2)) + si.network = atoi(optarg); + else + si.network = strtol(optarg + 2, NULL, 16); break; default: printf(add_help); -- cgit From e45e2d95822026cd2fd1de52644ba5096a1d4858 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 21 Jan 2006 13:36:10 +0000 Subject: Add HCRP service identifier --- tools/sdptool.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 0484d8af..556d0a89 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2823,6 +2823,7 @@ struct { { "GN", GN_SVCLASS_ID, add_gn }, { "PANU", PANU_SVCLASS_ID, add_panu }, + { "HCRP", HCR_SVCLASS_ID, NULL }, { "HID", HID_SVCLASS_ID, NULL }, { "CIP", CIP_SVCLASS_ID, add_cip }, { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, -- cgit From b2dfbf8a88f83dd6293a6535a002b572c973de9b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 24 Jan 2006 23:34:49 +0000 Subject: Add service record for direct printing --- tools/sdptool.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 556d0a89..79ca3544 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1785,6 +1785,71 @@ end: return ret; } +static int add_directprint(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, opush_uuid, l2cap_uuid, rfcomm_uuid, obex_uuid; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[3]; + sdp_record_t record; + uint8_t chan = si->channel ? si->channel : 12; + sdp_data_t *channel; + int ret = 0; + + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&opush_uuid, DIRECT_PRINTING_SVCLASS_ID); + svclass_id = sdp_list_append(0, &opush_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, BASIC_PRINTING_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &chan); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + sdp_uuid16_create(&obex_uuid, OBEX_UUID); + proto[2] = sdp_list_append(0, &obex_uuid); + apseq = sdp_list_append(apseq, proto[2]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Direct Printing", 0, 0); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + + printf("Direct Printing service registered\n"); + +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(proto[2], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + + return ret; +} + static int add_nap(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -2813,6 +2878,7 @@ struct { { "FAX", FAX_SVCLASS_ID, add_fax }, { "OPUSH", OBEX_OBJPUSH_SVCLASS_ID, add_opush }, { "FTP", OBEX_FILETRANS_SVCLASS_ID, add_ftp }, + { "PRINT", DIRECT_PRINTING_SVCLASS_ID, add_directprint }, { "HS", HEADSET_SVCLASS_ID, add_headset }, { "HF", HANDSFREE_SVCLASS_ID, add_handsfree }, -- cgit From 8b25f36fba836612200a6d1022858d6f2649db72 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 8 Feb 2006 11:09:24 +0000 Subject: Add SDP service record for HID keyboards --- tools/sdptool.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 170 insertions(+), 4 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 79ca3544..afdc567a 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1632,13 +1632,16 @@ static int add_simaccess(sdp_session_t *session, svc_info_t *si) ret = -1; goto end; } + printf("SIM Access service registered\n"); + end: sdp_data_free(channel); sdp_list_free(proto[0], 0); sdp_list_free(proto[1], 0); sdp_list_free(apseq, 0); sdp_list_free(aproto, 0); + return ret; } @@ -2055,6 +2058,168 @@ end: return ret; } +static int add_hid_keyb(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, hidkb_uuid, l2cap_uuid, hidp_uuid; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[3]; + sdp_data_t *channel, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2; + int i; + uint8_t dtd = SDP_UINT16; + uint8_t dtd2 = SDP_UINT8; + uint8_t dtd_data = SDP_TEXT_STR8; + void *dtds[2]; + void *values[2]; + void *dtds2[2]; + void *values2[2]; + int leng[2]; + uint8_t hid_spec_type = 0x22; + uint16_t hid_attr_lang[] = { 0x409, 0x100 }; + static const uint8_t ctrl = 0x11; + static const uint8_t intr = 0x13; + static const uint16_t hid_attr[] = { 0x100, 0x111, 0x40, 0x0d, 0x01, 0x01 }; + static const uint16_t hid_attr2[] = { 0x0, 0x01, 0x100, 0x1f40, 0x01, 0x01 }; + const uint8_t hid_spec[] = { + 0x05, 0x01, // usage page + 0x09, 0x06, // keyboard + 0xa1, 0x01, // key codes + 0x85, 0x01, // minimum + 0x05, 0x07, // max + 0x19, 0xe0, // logical min + 0x29, 0xe7, // logical max + 0x15, 0x00, // report size + 0x25, 0x01, // report count + 0x75, 0x01, // input data variable absolute + 0x95, 0x08, // report count + 0x81, 0x02, // report size + 0x75, 0x08, + 0x95, 0x01, + 0x81, 0x01, + 0x75, 0x01, + 0x95, 0x05, + 0x05, 0x08, + 0x19, 0x01, + 0x29, 0x05, + 0x91, 0x02, + 0x75, 0x03, + 0x95, 0x01, + 0x91, 0x01, + 0x75, 0x08, + 0x95, 0x06, + 0x15, 0x00, + 0x26, 0xff, + 0x00, 0x05, + 0x07, 0x19, + 0x00, 0x2a, + 0xff, 0x00, + 0x81, 0x00, + 0x75, 0x01, + 0x95, 0x01, + 0x15, 0x00, + 0x25, 0x01, + 0x05, 0x0c, + 0x09, 0xb8, + 0x81, 0x06, + 0x09, 0xe2, + 0x81, 0x06, + 0x09, 0xe9, + 0x81, 0x02, + 0x09, 0xea, + 0x81, 0x02, + 0x75, 0x01, + 0x95, 0x04, + 0x81, 0x01, + 0xc0 // end tag + }; + + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + add_lang_attr(&record); + + sdp_uuid16_create(&hidkb_uuid, HID_SVCLASS_ID); + svclass_id = sdp_list_append(0, &hidkb_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(0, profile); + sdp_set_profile_descs(&record, pfseq); + + /* protocols */ + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[1] = sdp_list_append(0, &l2cap_uuid); + channel = sdp_data_alloc(SDP_UINT8, &ctrl); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(0, proto[1]); + + sdp_uuid16_create(&hidp_uuid, HIDP_UUID); + proto[2] = sdp_list_append(0, &hidp_uuid); + apseq = sdp_list_append(apseq, proto[2]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + /* additional protocols */ + proto[1] = sdp_list_append(0, &l2cap_uuid); + channel = sdp_data_alloc(SDP_UINT8, &intr); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(0, proto[1]); + + sdp_uuid16_create(&hidp_uuid, HIDP_UUID); + proto[2] = sdp_list_append(0, &hidp_uuid); + apseq = sdp_list_append(apseq, proto[2]); + + aproto = sdp_list_append(0, apseq); + sdp_set_add_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "HID Keyboard", NULL, NULL); + + for (i = 0; i < sizeof(hid_attr) / 2; i++) + sdp_attr_add_new(&record, + SDP_ATTR_HID_DEVICE_RELEASE_NUMBER + i, + SDP_UINT16, &hid_attr[i]); + + dtds[0] = &dtd2; + values[0] = &hid_spec_type; + dtds[1] = &dtd_data; + values[1] = (uint8_t *) hid_spec; + leng[0] = 0; + leng[1] = sizeof(hid_spec); + hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2); + hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst); + sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2); + + for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) { + dtds2[i] = &dtd; + values2[i] = &hid_attr_lang[i]; + } + + lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2); + lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst); + sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2); + + sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, SDP_UINT16, &hid_attr2[0]); + + for (i = 0; i < sizeof(hid_attr2) / 2 - 1; i++) + sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP + i, + SDP_UINT16, &hid_attr2[i + 1]); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("HID keyboard service registered\n"); + + return 0; +} static int add_cip(sdp_session_t *session, svc_info_t *si) { @@ -2429,7 +2594,7 @@ done: return ret; } -static int add_udiue(sdp_session_t *session, svc_info_t *si) +static int add_udi_ue(sdp_session_t *session, svc_info_t *si) { sdp_record_t record; sdp_list_t *root, *svclass, *proto; @@ -2470,7 +2635,7 @@ static int add_udiue(sdp_session_t *session, svc_info_t *si) return 0; } -static int add_udite(sdp_session_t *session, svc_info_t *si) +static int add_udi_te(sdp_session_t *session, svc_info_t *si) { sdp_record_t record; sdp_list_t *root, *svclass, *proto; @@ -2891,6 +3056,7 @@ struct { { "HCRP", HCR_SVCLASS_ID, NULL }, { "HID", HID_SVCLASS_ID, NULL }, + { "KEYB", HID_SVCLASS_ID, add_hid_keyb }, { "CIP", CIP_SVCLASS_ID, add_cip }, { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, @@ -2899,8 +3065,8 @@ struct { { "AVRCT", AV_REMOTE_SVCLASS_ID, add_avrct }, { "AVRTG", AV_REMOTE_TARGET_SVCLASS_ID, add_avrtg }, - { "UDIUE", UDI_MT_SVCLASS_ID, add_udiue }, - { "UDITE", UDI_TA_SVCLASS_ID, add_udite }, + { "UDIUE", UDI_MT_SVCLASS_ID, add_udi_ue }, + { "UDITE", UDI_TA_SVCLASS_ID, add_udi_te }, { "SR1", 0, add_sr1, sr1_uuid }, { "SYNCML", 0, add_syncml, syncml_uuid }, -- cgit From 0722d48e5cd78d94fc66e27de13a726ad81d3425 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 8 Feb 2006 11:16:47 +0000 Subject: Add service record for SEMC High Level Authentication --- tools/sdptool.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 5 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index afdc567a..fb1a0fbf 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -3029,9 +3029,57 @@ static int add_isync(sdp_session_t *session, svc_info_t *si) return 0; } +static int add_semchla(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_profile_desc_t profile; + sdp_list_t *root, *svclass, *proto, *profiles; + uuid_t root_uuid, service_uuid, l2cap_uuid, semchla_uuid; + uint16_t psm = 0xf0f9; + + memset(&record, 0, sizeof(record)); + record.handle = si->handle; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto = sdp_list_append(NULL, sdp_list_append( + sdp_list_append(NULL, &l2cap_uuid), sdp_data_alloc(SDP_UINT16, &psm))); + + sdp_uuid32_create(&semchla_uuid, 0x8e770300); + proto = sdp_list_append(proto, sdp_list_append(NULL, &semchla_uuid)); + + sdp_set_access_protos(&record, sdp_list_append(NULL, proto)); + + sdp_uuid32_create(&service_uuid, 0x8e771301); + svclass = sdp_list_append(NULL, &service_uuid); + + sdp_set_service_classes(&record, svclass); + + sdp_uuid32_create(&profile.uuid, 0x8e771302); // Headset + //sdp_uuid32_create(&profile.uuid, 0x8e771303); // Phone + profile.version = 0x0100; + profiles = sdp_list_append(NULL, &profile); + sdp_set_profile_descs(&record, profiles); + + sdp_set_info_attr(&record, "SEMC HLA", NULL, NULL); + + if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + /* SEMC High Level Authentication */ + printf("SEMC HLA service registered\n"); + + return 0; +} + struct { char *name; - uint16_t class; + uint32_t class; int (*add)(sdp_session_t *sess, svc_info_t *si); unsigned char *uuid; } service[] = { @@ -3068,6 +3116,8 @@ struct { { "UDIUE", UDI_MT_SVCLASS_ID, add_udi_ue }, { "UDITE", UDI_TA_SVCLASS_ID, add_udi_te }, + { "SEMCHLA", 0x8e771301, add_semchla }, + { "SR1", 0, add_sr1, sr1_uuid }, { "SYNCML", 0, add_syncml, syncml_uuid }, { "ACTIVESYNC", 0, add_activesync, async_uuid }, @@ -3435,7 +3485,7 @@ static int cmd_search(int argc, char **argv) { struct search_context context; unsigned char *uuid = NULL; - uint16_t class = 0; + uint32_t class = 0; bdaddr_t bdaddr; int has_addr = 0; int i; @@ -3494,9 +3544,14 @@ static int cmd_search(int argc, char **argv) } } - if (class) - sdp_uuid16_create(&context.group, class); - else + if (class) { + if (class & 0xffff0000) + sdp_uuid32_create(&context.group, class); + else { + uint16_t class16 = class & 0xffff; + sdp_uuid16_create(&context.group, class16); + } + } else sdp_uuid128_create(&context.group, uuid); if (has_addr) -- cgit From 65d1a12cfff5d53e535134dbf03eedcc02ffb589 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 15 Feb 2006 08:09:39 +0000 Subject: Improve display of UUID-128 strings --- tools/sdptool.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index fb1a0fbf..efe59e02 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -989,7 +989,10 @@ static void print_service_class(void *value, void *userData) sdp_uuid2strn(uuid, UUID_str, MAX_LEN_UUID_STR); sdp_svclass_uuid2strn(uuid, ServiceClassUUID_str, MAX_LEN_SERVICECLASS_UUID_STR); - printf(" \"%s\" (0x%s)\n", ServiceClassUUID_str, UUID_str); + if (uuid->type != SDP_UUID128) + printf(" \"%s\" (0x%s)\n", ServiceClassUUID_str, UUID_str); + else + printf(" UUID 128: %s\n", UUID_str); } static void print_service_desc(void *value, void *user) -- cgit From 868eb388eacf226e1ff0fc84c7923aaa13836216 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 9 Mar 2006 20:15:58 +0000 Subject: Add workaround for missing Apple service identifier --- tools/sdptool.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index efe59e02..8bee7985 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -45,6 +45,10 @@ #include +#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) /* -- cgit From 403066f6cd6f4df68f68178acc2db0926370e95c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 28 Apr 2006 14:30:59 +0000 Subject: Cleanup main function declarations --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 8bee7985..8beff568 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -3786,7 +3786,7 @@ static struct option main_options[] = { { 0, 0, 0, 0 } }; -int main(int argc, char **argv) +int main(int argc, char *argv[]) { int i, opt; -- cgit From fe2fcaafb891599e82853fcf2940e79cd25e8e78 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 30 May 2006 11:00:34 +0000 Subject: Add another Phonebook Access identifier --- tools/sdptool.c | 1 + 1 file changed, 1 insertion(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 8beff568..d5ad511c 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -306,6 +306,7 @@ static struct uuid_def uuid16_names[] = { { 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) }, -- cgit From cb778770890a9c3e69179488f5b21becc5973e59 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 14 Jun 2006 11:01:32 +0000 Subject: Adapt possible record range --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index d5ad511c..2b0a1df2 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -3637,7 +3637,7 @@ static char *records_help = static int cmd_records(int argc, char **argv) { struct search_context context; - uint32_t base[] = { 0x10000, 0x1002e, 0x110b }; + uint32_t base[] = { 0x10000, 0x1002e, 0x110b, 0x90000, 0x2008000, 0x4000000, 0x1000000 }; bdaddr_t bdaddr; int i, n, opt, err = 0, num = 32; -- cgit From 33b2522fb2f86590aaf40dc79a6156b94d5a6980 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 15 Jun 2006 05:44:22 +0000 Subject: Use uint16 for PSM in the HID keyboard record --- tools/sdptool.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 2b0a1df2..0cefafb0 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2073,7 +2073,7 @@ static int add_hid_keyb(sdp_session_t *session, svc_info_t *si) uuid_t root_uuid, hidkb_uuid, l2cap_uuid, hidp_uuid; sdp_profile_desc_t profile[1]; sdp_list_t *aproto, *proto[3]; - sdp_data_t *channel, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2; + sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2; int i; uint8_t dtd = SDP_UINT16; uint8_t dtd2 = SDP_UINT8; @@ -2085,8 +2085,8 @@ static int add_hid_keyb(sdp_session_t *session, svc_info_t *si) int leng[2]; uint8_t hid_spec_type = 0x22; uint16_t hid_attr_lang[] = { 0x409, 0x100 }; - static const uint8_t ctrl = 0x11; - static const uint8_t intr = 0x13; + static const uint16_t ctrl = 0x11; + static const uint16_t intr = 0x13; static const uint16_t hid_attr[] = { 0x100, 0x111, 0x40, 0x0d, 0x01, 0x01 }; static const uint16_t hid_attr2[] = { 0x0, 0x01, 0x100, 0x1f40, 0x01, 0x01 }; const uint8_t hid_spec[] = { @@ -2163,8 +2163,8 @@ static int add_hid_keyb(sdp_session_t *session, svc_info_t *si) /* protocols */ sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); proto[1] = sdp_list_append(0, &l2cap_uuid); - channel = sdp_data_alloc(SDP_UINT8, &ctrl); - proto[1] = sdp_list_append(proto[1], channel); + psm = sdp_data_alloc(SDP_UINT16, &ctrl); + proto[1] = sdp_list_append(proto[1], psm); apseq = sdp_list_append(0, proto[1]); sdp_uuid16_create(&hidp_uuid, HIDP_UUID); @@ -2176,8 +2176,8 @@ static int add_hid_keyb(sdp_session_t *session, svc_info_t *si) /* additional protocols */ proto[1] = sdp_list_append(0, &l2cap_uuid); - channel = sdp_data_alloc(SDP_UINT8, &intr); - proto[1] = sdp_list_append(proto[1], channel); + psm = sdp_data_alloc(SDP_UINT16, &intr); + proto[1] = sdp_list_append(proto[1], psm); apseq = sdp_list_append(0, proto[1]); sdp_uuid16_create(&hidp_uuid, HIDP_UUID); -- cgit From d544342b190eabf0703218169c1248f3905b09b1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 15 Oct 2006 13:07:47 +0000 Subject: Add another Ricoh specific range --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 0cefafb0..477f05a1 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -3637,7 +3637,7 @@ static char *records_help = static int cmd_records(int argc, char **argv) { struct search_context context; - uint32_t base[] = { 0x10000, 0x1002e, 0x110b, 0x90000, 0x2008000, 0x4000000, 0x1000000 }; + uint32_t base[] = { 0x10000, 0x1002e, 0x110b, 0x90000, 0x2008000, 0x4000000, 0x100000, 0x1000000 }; bdaddr_t bdaddr; int i, n, opt, err = 0, num = 32; -- cgit From 77d92a75f16e380ed204fb2e42eb292a16355ec9 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 23 Nov 2006 04:59:17 +0000 Subject: Add support for XML view of service records --- tools/sdptool.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 477f05a1..4c3bf5cc 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -45,6 +45,8 @@ #include +#include "sdp-xml.h" + #ifndef APPLE_AGENT_SVCLASS_ID #define APPLE_AGENT_SVCLASS_ID 0x2112 #endif @@ -67,6 +69,7 @@ static int estr2ba(char *str, bdaddr_t *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 { @@ -3329,6 +3332,11 @@ static void inquiry(handler_t handler, void *arg) handler(&ii[i].bdaddr, arg); } +static void doprintf(void *data, const char *str) +{ + printf(str); +} + /* * Search for a specific SDP service */ @@ -3383,6 +3391,10 @@ static int do_search(bdaddr_t *bdaddr, struct search_context *context) print_tree_attr(rec); printf("\n"); break; + case XML_VIEW: + /* Display raw XML tree */ + convert_sdp_record_to_xml(rec, 0, doprintf); + break; default: /* Display raw tree */ print_raw_attr(rec); @@ -3409,6 +3421,7 @@ static struct option browse_options[] = { { "help", 0, 0, 'h' }, { "tree", 0, 0, 't' }, { "raw", 0, 0, 'r' }, + { "xml", 0, 0, 'x' }, { "uuid", 1, 0, 'u' }, { "l2cap", 0, 0, 'l' }, { 0, 0, 0, 0 } @@ -3416,7 +3429,7 @@ static struct option browse_options[] = { static char *browse_help = "Usage:\n" - "\tbrowse [--tree] [--raw] [--uuid uuid] [--l2cap] [bdaddr]\n"; + "\tbrowse [--tree] [--raw] [--xml] [--uuid uuid] [--l2cap] [bdaddr]\n"; /* * Browse the full SDP database (i.e. list all services starting from the @@ -3440,6 +3453,9 @@ static int cmd_browse(int argc, char **argv) case 'r': context.view = RAW_VIEW; break; + case 'x': + context.view = XML_VIEW; + break; case 'u': if (sscanf(optarg, "%i", &num) != 1 || num < 0 || num > 0xffff) { printf("Invalid uuid %s\n", optarg); @@ -3473,12 +3489,13 @@ static struct option search_options[] = { { "bdaddr", 1, 0, 'b' }, { "tree", 0, 0, 't' }, { "raw", 0, 0, 'r' }, + { "xml", 0, 0, 'x' }, { 0, 0, 0, 0} }; static char *search_help = "Usage:\n" - "\tsearch [--bdaddr bdaddr] [--tree] [--raw] SERVICE\n" + "\tsearch [--bdaddr bdaddr] [--tree] [--raw] [--xml] SERVICE\n" "SERVICE is a name (string) or UUID (0x1002)\n"; /* @@ -3514,6 +3531,9 @@ static int cmd_search(int argc, char **argv) case 'r': context.view = RAW_VIEW; break; + case 'x': + context.view = XML_VIEW; + break; default: printf(search_help); return -1; @@ -3610,6 +3630,10 @@ static int get_service(bdaddr_t *bdaddr, struct search_context *context, int qui print_tree_attr(rec); printf("\n"); break; + case XML_VIEW: + /* Display raw XML tree */ + convert_sdp_record_to_xml(rec, 0, doprintf); + break; default: /* Display raw tree */ print_raw_attr(rec); @@ -3624,12 +3648,13 @@ static struct option records_options[] = { { "help", 0, 0, 'h' }, { "tree", 0, 0, 't' }, { "raw", 0, 0, 'r' }, + { "xml", 0, 0, 'x' }, { 0, 0, 0, 0 } }; static char *records_help = "Usage:\n" - "\trecords [--tree] [--raw] bdaddr\n"; + "\trecords [--tree] [--raw] [--xml] bdaddr\n"; /* * Request possible SDP service records @@ -3652,6 +3677,9 @@ static int cmd_records(int argc, char **argv) case 'r': context.view = RAW_VIEW; break; + case 'x': + context.view = XML_VIEW; + break; default: printf(records_help); return -1; @@ -3686,12 +3714,13 @@ static struct option get_options[] = { { "bdaddr", 1, 0, 'b' }, { "tree", 0, 0, 't' }, { "raw", 0, 0, 'r' }, + { "xml", 0, 0, 'x' }, { 0, 0, 0, 0 } }; static char *get_help = "Usage:\n" - "\tget [--tree] [--raw] [--bdaddr bdaddr] record_handle\n"; + "\tget [--tree] [--raw] [--xml] [--bdaddr bdaddr] record_handle\n"; /* * Get a specific SDP record on the local SDP server @@ -3718,6 +3747,9 @@ static int cmd_get(int argc, char **argv) case 'r': context.view = RAW_VIEW; break; + case 'x': + context.view = XML_VIEW; + break; default: printf(get_help); return -1; -- cgit From 607695ed109340f4b7a5628420e0a8e8aee34f4e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 13 Jan 2007 17:48:12 +0000 Subject: Update copyright information --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 4c3bf5cc..2fb7504f 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -4,7 +4,7 @@ * * Copyright (C) 2001-2002 Nokia Corporation * Copyright (C) 2002-2003 Maxim Krasnyansky - * Copyright (C) 2002-2006 Marcel Holtmann + * Copyright (C) 2002-2007 Marcel Holtmann * Copyright (C) 2002-2003 Stephen Crane * Copyright (C) 2002-2003 Jean Tourrilhes * -- cgit From a60dd957416d08b5f752d24b7277e885d4951fc5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 21 Jan 2007 01:20:52 +0000 Subject: Add UUID for Nokia FTP --- tools/sdptool.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 2fb7504f..6418eafb 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2955,6 +2955,9 @@ static int add_pcsuite(sdp_session_t *session, svc_info_t *si) return 0; } +static unsigned char nftp_uuid[] = { 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; + static unsigned char ngage_uuid[] = { 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; @@ -3136,6 +3139,7 @@ struct { { "PALMOS", 0, add_palmos, palmos_uuid }, { "NOKID", 0, add_nokiaid, nokid_uuid }, { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, + { "NFTP", 0, NULL, nftp_uuid }, { "NGAGE", 0, NULL, ngage_uuid }, { "APPLE", 0, add_apple, apple_uuid }, -- cgit From 5b1649afe025b7b3f0e620fbd4c7a21b71545fe5 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 11 Feb 2007 00:17:41 +0000 Subject: Add Wii-Mote HID service record --- tools/sdptool.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 6418eafb..8864dc99 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2069,6 +2069,7 @@ end: return ret; } + static int add_hid_keyb(sdp_session_t *session, svc_info_t *si) { sdp_record_t record; @@ -2232,6 +2233,177 @@ static int add_hid_keyb(sdp_session_t *session, svc_info_t *si) return 0; } +static int add_hid_wiimote(sdp_session_t *session, svc_info_t *si) +{ + sdp_record_t record; + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, hid_uuid, l2cap_uuid, hidp_uuid; + sdp_profile_desc_t profile[1]; + sdp_list_t *aproto, *proto[3]; + sdp_data_t *psm, *lang_lst, *lang_lst2, *hid_spec_lst, *hid_spec_lst2; + int i; + uint8_t dtd = SDP_UINT16; + uint8_t dtd2 = SDP_UINT8; + uint8_t dtd_data = SDP_TEXT_STR8; + void *dtds[2]; + void *values[2]; + void *dtds2[2]; + void *values2[2]; + int leng[2]; + uint8_t hid_spec_type = 0x22; + uint16_t hid_attr_lang[] = { 0x409, 0x100 }; + uint16_t ctrl = 0x11, intr = 0x13; + uint16_t hid_release = 0x0100, parser_version = 0x0111; + uint8_t subclass = 0x04, country = 0x33; + uint8_t virtual_cable = 0, reconnect = 1, sdp_disable = 0; + uint8_t battery = 1, remote_wakeup = 1; + uint16_t profile_version = 0x0100, superv_timeout = 0x0c80; + uint8_t norm_connect = 0, boot_device = 0; + const uint8_t hid_spec[] = { + 0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x10, + 0x15, 0x00, 0x26, 0xff, 0x00, 0x75, 0x08, 0x95, + 0x01, 0x06, 0x00, 0xff, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x11, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x12, 0x95, 0x02, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x13, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x14, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x15, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x16, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x17, 0x95, 0x06, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x18, 0x95, 0x15, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x19, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x1a, 0x95, 0x01, 0x09, 0x01, 0x91, 0x00, + 0x85, 0x20, 0x95, 0x06, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x21, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x22, 0x95, 0x04, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x30, 0x95, 0x02, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x31, 0x95, 0x05, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x32, 0x95, 0x0a, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x33, 0x95, 0x11, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x34, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x35, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x36, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x37, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x3d, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x3e, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, + 0x85, 0x3f, 0x95, 0x15, 0x09, 0x01, 0x81, 0x00, + 0xc0, 0x00 + }; + + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(NULL, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&hid_uuid, HID_SVCLASS_ID); + svclass_id = sdp_list_append(NULL, &hid_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile[0].uuid, HID_PROFILE_ID); + profile[0].version = 0x0100; + pfseq = sdp_list_append(NULL, profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[1] = sdp_list_append(0, &l2cap_uuid); + psm = sdp_data_alloc(SDP_UINT16, &ctrl); + proto[1] = sdp_list_append(proto[1], psm); + apseq = sdp_list_append(0, proto[1]); + + sdp_uuid16_create(&hidp_uuid, HIDP_UUID); + proto[2] = sdp_list_append(0, &hidp_uuid); + apseq = sdp_list_append(apseq, proto[2]); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + proto[1] = sdp_list_append(0, &l2cap_uuid); + psm = sdp_data_alloc(SDP_UINT16, &intr); + proto[1] = sdp_list_append(proto[1], psm); + apseq = sdp_list_append(0, proto[1]); + + sdp_uuid16_create(&hidp_uuid, HIDP_UUID); + proto[2] = sdp_list_append(0, &hidp_uuid); + apseq = sdp_list_append(apseq, proto[2]); + + aproto = sdp_list_append(0, apseq); + sdp_set_add_access_protos(&record, aproto); + + add_lang_attr(&record); + + sdp_set_info_attr(&record, "Nintendo RVL-CNT-01", + "Nintendo", "Nintendo RVL-CNT-01"); + + sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_RELEASE_NUMBER, + SDP_UINT16, &hid_release); + + sdp_attr_add_new(&record, SDP_ATTR_HID_PARSER_VERSION, + SDP_UINT16, &parser_version); + + sdp_attr_add_new(&record, SDP_ATTR_HID_DEVICE_SUBCLASS, + SDP_UINT8, &subclass); + + sdp_attr_add_new(&record, SDP_ATTR_HID_COUNTRY_CODE, + SDP_UINT8, &country); + + sdp_attr_add_new(&record, SDP_ATTR_HID_VIRTUAL_CABLE, + SDP_BOOL, &virtual_cable); + + sdp_attr_add_new(&record, SDP_ATTR_HID_RECONNECT_INITIATE, + SDP_BOOL, &reconnect); + + dtds[0] = &dtd2; + values[0] = &hid_spec_type; + dtds[1] = &dtd_data; + values[1] = (uint8_t *) hid_spec; + leng[0] = 0; + leng[1] = sizeof(hid_spec); + hid_spec_lst = sdp_seq_alloc_with_length(dtds, values, leng, 2); + hid_spec_lst2 = sdp_data_alloc(SDP_SEQ8, hid_spec_lst); + sdp_attr_add(&record, SDP_ATTR_HID_DESCRIPTOR_LIST, hid_spec_lst2); + + for (i = 0; i < sizeof(hid_attr_lang) / 2; i++) { + dtds2[i] = &dtd; + values2[i] = &hid_attr_lang[i]; + } + + lang_lst = sdp_seq_alloc(dtds2, values2, sizeof(hid_attr_lang) / 2); + lang_lst2 = sdp_data_alloc(SDP_SEQ8, lang_lst); + sdp_attr_add(&record, SDP_ATTR_HID_LANG_ID_BASE_LIST, lang_lst2); + + sdp_attr_add_new(&record, SDP_ATTR_HID_SDP_DISABLE, + SDP_BOOL, &sdp_disable); + + sdp_attr_add_new(&record, SDP_ATTR_HID_BATTERY_POWER, + SDP_BOOL, &battery); + + sdp_attr_add_new(&record, SDP_ATTR_HID_REMOTE_WAKEUP, + SDP_BOOL, &remote_wakeup); + + sdp_attr_add_new(&record, SDP_ATTR_HID_PROFILE_VERSION, + SDP_UINT16, &profile_version); + + sdp_attr_add_new(&record, SDP_ATTR_HID_SUPERVISION_TIMEOUT, + SDP_UINT16, &superv_timeout); + + sdp_attr_add_new(&record, SDP_ATTR_HID_NORMALLY_CONNECTABLE, + SDP_BOOL, &norm_connect); + + sdp_attr_add_new(&record, SDP_ATTR_HID_BOOT_DEVICE, + SDP_BOOL, &boot_device); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + return -1; + } + + printf("Wii-Mote service registered\n"); + + return 0; +} + static int add_cip(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -3119,6 +3291,7 @@ struct { { "HCRP", HCR_SVCLASS_ID, NULL }, { "HID", HID_SVCLASS_ID, NULL }, { "KEYB", HID_SVCLASS_ID, add_hid_keyb }, + { "WIIMOTE", HID_SVCLASS_ID, add_hid_wiimote }, { "CIP", CIP_SVCLASS_ID, add_cip }, { "CTP", CORDLESS_TELEPHONY_SVCLASS_ID, add_ctp }, -- cgit From fcb09f4016ced43843625b197d851c90088dd418 Mon Sep 17 00:00:00 2001 From: Claudio Takahasi Date: Wed, 6 Jun 2007 20:36:28 +0000 Subject: sdptool: fixed memory leak for setattr and setseq --- tools/sdptool.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 8864dc99..1bf3526c 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -755,10 +755,12 @@ static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, cha sdp_list_t *attrid_list; uint32_t range = 0x0000ffff; sdp_record_t *rec; + int ret; /* Get the old SDP record */ attrid_list = sdp_list_append(NULL, &range); rec = sdp_service_attr_req(sess, handle, SDP_ATTR_REQ_RANGE, attrid_list); + sdp_list_free(attrid_list, NULL); if (!rec) { printf("Service get request failed.\n"); @@ -794,11 +796,11 @@ static int set_attrib(sdp_session_t *sess, uint32_t handle, uint16_t attrib, cha } /* Update on the server */ - if (sdp_device_record_update(sess, &interface, rec)) { + ret = sdp_device_record_update(sess, &interface, rec); + if (ret < 0) printf("Service Record update failed (%d).\n", errno); - return -1; - } - return 0; + sdp_record_free(rec); + return ret; } static struct option set_options[] = { @@ -867,11 +869,12 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri uint8_t uuid16 = SDP_UUID16; uint8_t uint32 = SDP_UINT32; uint8_t str8 = SDP_TEXT_STR8; - int i; + int i, ret = 0; /* Get the old SDP record */ attrid_list = sdp_list_append(NULL, &range); rec = sdp_service_attr_req(session, handle, SDP_ATTR_REQ_RANGE, attrid_list); + sdp_list_free(attrid_list, NULL); if (!rec) { printf("Service get request failed.\n"); @@ -919,10 +922,9 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri sdp_attr_replace(rec, attrib, pSequenceHolder); /* Update on the server */ - if (sdp_device_record_update(session, &interface, rec)) { + ret = sdp_device_record_update(session, &interface, rec); + if (ret < 0) printf("Service Record update failed (%d).\n", errno); - return -1; - } } else printf("Failed to create pSequenceHolder\n"); @@ -932,8 +934,11 @@ static int set_attribseq(sdp_session_t *session, uint32_t handle, uint16_t attri free(dtdArray); free(valueArray); + free(allocArray); - return 0; + sdp_record_free(rec); + + return ret; } static struct option seq_options[] = { -- cgit From 35cc0e38796c35a24bcd7949e5b478def0672207 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 23 Jul 2007 23:20:29 +0000 Subject: Add identifier for Nokia SyncML records --- tools/sdptool.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 1bf3526c..f3bd6432 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -3135,6 +3135,9 @@ static int add_pcsuite(sdp_session_t *session, svc_info_t *si) static unsigned char nftp_uuid[] = { 0x00, 0x00, 0x50, 0x05, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; +static unsigned char nsyncml_uuid[] = { 0x00, 0x00, 0x56, 0x01, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; + static unsigned char ngage_uuid[] = { 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x01 }; @@ -3318,6 +3321,7 @@ struct { { "NOKID", 0, add_nokiaid, nokid_uuid }, { "PCSUITE", 0, add_pcsuite, pcsuite_uuid }, { "NFTP", 0, NULL, nftp_uuid }, + { "NSYNCML", 0, NULL, nsyncml_uuid }, { "NGAGE", 0, NULL, ngage_uuid }, { "APPLE", 0, add_apple, apple_uuid }, -- cgit From a46dd97e351ed0f312601cf8f0297fcbc358318e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 23 Jul 2007 23:28:19 +0000 Subject: Add SymcML server definition --- tools/sdptool.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index f3bd6432..562c75a6 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -2896,7 +2896,10 @@ static int add_sr1(sdp_session_t *session, svc_info_t *si) return 0; } -static unsigned char syncml_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, +static unsigned char syncmls_uuid[] = { 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, + 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 }; + +static unsigned char syncmlc_uuid[] = { 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 }; static int add_syncml(sdp_session_t *session, svc_info_t *si) @@ -2913,7 +2916,7 @@ static int add_syncml(sdp_session_t *session, svc_info_t *si) root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(&record, root); - sdp_uuid128_create(&svclass_uuid, (void *) syncml_uuid); + sdp_uuid128_create(&svclass_uuid, (void *) syncmlc_uuid); svclass = sdp_list_append(NULL, &svclass_uuid); sdp_set_service_classes(&record, svclass); @@ -3314,7 +3317,8 @@ struct { { "SEMCHLA", 0x8e771301, add_semchla }, { "SR1", 0, add_sr1, sr1_uuid }, - { "SYNCML", 0, add_syncml, syncml_uuid }, + { "SYNCML", 0, add_syncml, syncmlc_uuid }, + { "SYNCMLSERV", 0, NULL, syncmls_uuid }, { "ACTIVESYNC", 0, add_activesync, async_uuid }, { "HOTSYNC", 0, add_hotsync, hotsync_uuid }, { "PALMOS", 0, add_palmos, palmos_uuid }, -- cgit From 38f7e247cfe425a3e7b01aa24784b10231998125 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 10 Oct 2007 13:50:40 +0000 Subject: Add two more record handle ranges from Sony Ericsson headsets --- tools/sdptool.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 562c75a6..fc4b1f7b 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -3852,7 +3852,9 @@ static char *records_help = static int cmd_records(int argc, char **argv) { struct search_context context; - uint32_t base[] = { 0x10000, 0x1002e, 0x110b, 0x90000, 0x2008000, 0x4000000, 0x100000, 0x1000000 }; + uint32_t base[] = { 0x10000, 0x10300, 0x10500, + 0x1002e, 0x110b, 0x90000, 0x2008000, + 0x4000000, 0x100000, 0x1000000 }; bdaddr_t bdaddr; int i, n, opt, err = 0, num = 32; -- cgit From 312471773c71bfc1e64d9d6e8a71e933d3b9cc98 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 12 Nov 2007 01:19:18 +0000 Subject: Add record handle range from Apple iPhone --- tools/sdptool.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index fc4b1f7b..35f75c48 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -3853,8 +3853,8 @@ static int cmd_records(int argc, char **argv) { struct search_context context; uint32_t base[] = { 0x10000, 0x10300, 0x10500, - 0x1002e, 0x110b, 0x90000, 0x2008000, - 0x4000000, 0x100000, 0x1000000 }; + 0x1002e, 0x110b, 0x90000, 0x2008000, + 0x4000000, 0x100000, 0x1000000, 0x4f491100 }; bdaddr_t bdaddr; int i, n, opt, err = 0, num = 32; -- cgit From 207ed32b02954e52bd162f270db60b8e37d58442 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 25 Dec 2007 20:41:29 +0000 Subject: Add definitions for MDP --- tools/sdptool.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 35f75c48..ac17f9ad 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -322,6 +322,9 @@ static struct uuid_def uuid16_names[] = { { 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 }, }; -- cgit From e823c15e43a6f924779e466d434c51157002d9ee Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 2 Feb 2008 03:37:05 +0000 Subject: Update copyright information --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index ac17f9ad..19882396 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -4,7 +4,7 @@ * * Copyright (C) 2001-2002 Nokia Corporation * Copyright (C) 2002-2003 Maxim Krasnyansky - * Copyright (C) 2002-2007 Marcel Holtmann + * Copyright (C) 2002-2008 Marcel Holtmann * Copyright (C) 2002-2003 Stephen Crane * Copyright (C) 2002-2003 Jean Tourrilhes * -- cgit From ee0b35445ba76b7b73badbcdefbeca4ac9d5dc77 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Jul 2008 01:15:44 +0000 Subject: Add extra attributes to the serial port record --- tools/sdptool.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 19882396..eb890df9 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1199,7 +1199,15 @@ static int add_sp(sdp_session_t *session, svc_info_t *si) add_lang_attr(&record); - sdp_set_info_attr(&record, "Serial Port", 0, "COM Port"); + sdp_set_info_attr(&record, "Serial Port", "BlueZ", "COM Port"); + + sdp_set_url_attr(&record, "http://www.bluez.org/", + "http://www.bluez.org/", "http://www.bluez.org/"); + + sdp_set_service_id(&record, sp_uuid); + sdp_set_service_ttl(&record, 0xffff); + sdp_set_service_avail(&record, 0xff); + sdp_set_record_state(&record, 0x00001234); if (sdp_device_record_register(session, &interface, &record, SDP_RECORD_PERSIST) < 0) { printf("Service Record registration failed\n"); -- cgit From 976827b9191dd074b26dd93b02cff8d639ec8bdc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Jul 2008 01:21:30 +0000 Subject: Use Handsfree version 0x0105 for the gateway role --- tools/sdptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index eb890df9..1c49ed4e 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1564,7 +1564,7 @@ static int add_handsfree_ag(sdp_session_t *session, svc_info_t *si) sdp_set_service_classes(&record, svclass_id); sdp_uuid16_create(&profile.uuid, HANDSFREE_PROFILE_ID); - profile.version = 0x0100; + profile.version = 0x0105; pfseq = sdp_list_append(0, &profile); sdp_set_profile_descs(&record, pfseq); -- cgit From 6930e84ba9858aabce5c8941a9511b593e0859d4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Jul 2008 01:34:08 +0000 Subject: Add example record for headset audio gateway record --- tools/sdptool.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'tools/sdptool.c') diff --git a/tools/sdptool.c b/tools/sdptool.c index 1c49ed4e..003d8875 100644 --- a/tools/sdptool.c +++ b/tools/sdptool.c @@ -1470,6 +1470,76 @@ end: return ret; } +static int add_headset_ag(sdp_session_t *session, svc_info_t *si) +{ + sdp_list_t *svclass_id, *pfseq, *apseq, *root; + uuid_t root_uuid, svclass_uuid, ga_svclass_uuid, l2cap_uuid, rfcomm_uuid; + sdp_profile_desc_t profile; + sdp_list_t *aproto, *proto[2]; + sdp_record_t record; + uint8_t u8 = si->channel ? si->channel : 7; + uint16_t u16 = 0x17; + sdp_data_t *channel, *features; + uint8_t netid = si->network ? si->network : 0x01; // ???? profile document + sdp_data_t *network = sdp_data_alloc(SDP_UINT8, &netid); + int ret = 0; + + memset(&record, 0, sizeof(sdp_record_t)); + record.handle = si->handle; + + sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); + root = sdp_list_append(0, &root_uuid); + sdp_set_browse_groups(&record, root); + + sdp_uuid16_create(&svclass_uuid, HEADSET_AGW_SVCLASS_ID); + svclass_id = sdp_list_append(0, &svclass_uuid); + sdp_uuid16_create(&ga_svclass_uuid, GENERIC_AUDIO_SVCLASS_ID); + svclass_id = sdp_list_append(svclass_id, &ga_svclass_uuid); + sdp_set_service_classes(&record, svclass_id); + + sdp_uuid16_create(&profile.uuid, HEADSET_PROFILE_ID); + profile.version = 0x0100; + pfseq = sdp_list_append(0, &profile); + sdp_set_profile_descs(&record, pfseq); + + sdp_uuid16_create(&l2cap_uuid, L2CAP_UUID); + proto[0] = sdp_list_append(0, &l2cap_uuid); + apseq = sdp_list_append(0, proto[0]); + + sdp_uuid16_create(&rfcomm_uuid, RFCOMM_UUID); + proto[1] = sdp_list_append(0, &rfcomm_uuid); + channel = sdp_data_alloc(SDP_UINT8, &u8); + proto[1] = sdp_list_append(proto[1], channel); + apseq = sdp_list_append(apseq, proto[1]); + + features = sdp_data_alloc(SDP_UINT16, &u16); + sdp_attr_add(&record, SDP_ATTR_SUPPORTED_FEATURES, features); + + aproto = sdp_list_append(0, apseq); + sdp_set_access_protos(&record, aproto); + + sdp_set_info_attr(&record, "Voice Gateway", 0, 0); + + sdp_attr_add(&record, SDP_ATTR_EXTERNAL_NETWORK, network); + + if (sdp_record_register(session, &record, SDP_RECORD_PERSIST) < 0) { + printf("Service Record registration failed\n"); + ret = -1; + goto end; + } + + printf("Headset AG service registered\n"); + +end: + sdp_data_free(channel); + sdp_list_free(proto[0], 0); + sdp_list_free(proto[1], 0); + sdp_list_free(apseq, 0); + sdp_list_free(aproto, 0); + + return ret; +} + static int add_handsfree(sdp_session_t *session, svc_info_t *si) { sdp_list_t *svclass_id, *pfseq, *apseq, *root; @@ -3302,6 +3372,7 @@ struct { { "PRINT", DIRECT_PRINTING_SVCLASS_ID, add_directprint }, { "HS", HEADSET_SVCLASS_ID, add_headset }, + { "HSAG", HEADSET_AGW_SVCLASS_ID, add_headset_ag }, { "HF", HANDSFREE_SVCLASS_ID, add_handsfree }, { "HFAG", HANDSFREE_AGW_SVCLASS_ID, add_handsfree_ag}, { "SAP", SAP_SVCLASS_ID, add_simaccess }, -- cgit