Index: Makefile.am =================================================================== RCS file: /cvsroot/bluez/utils/hcid/Makefile.am,v retrieving revision 1.59 diff --unified=5 -r1.59 Makefile.am --- Makefile.am 1 Nov 2006 12:58:31 -0000 1.59 +++ Makefile.am 9 Nov 2006 01:11:23 -0000 @@ -23,11 +23,12 @@ dbus-hci.h dbus-hci.c dbus-common.c dbus-common.h \ dbus-error.c dbus-error.h dbus-manager.c dbus-manager.h \ dbus-adapter.c dbus-adapter.h \ dbus-device.c dbus-device.h dbus-service.c dbus-service.h \ dbus-security.c dbus-security.h dbus-test.c dbus-test.h \ - dbus-sdp.c dbus-sdp.h dbus-rfcomm.c dbus-rfcomm.h + dbus-sdp.c dbus-sdp.h dbus-rfcomm.c dbus-rfcomm.h \ + sdp-xml.c sdp-xml.h hcid_LDADD = @DBUS_LIBS@ @BLUEZ_LIBS@ $(top_builddir)/common/libhelper.a passkey_agent_SOURCES = passkey-agent.c Index: dbus-adapter.c =================================================================== RCS file: /cvsroot/bluez/utils/hcid/dbus-adapter.c,v retrieving revision 1.135 diff --unified=5 -r1.135 dbus-adapter.c --- dbus-adapter.c 7 Nov 2006 20:36:10 -0000 1.135 +++ dbus-adapter.c 9 Nov 2006 01:11:24 -0000 @@ -1059,28 +1059,17 @@ } static DBusHandlerResult adapter_get_remote_svc(DBusConnection *conn, DBusMessage *msg, void *data) { - return get_remote_svc_rec(conn, msg, data); + return get_remote_svc_rec(conn, msg, data, SDP_FORMAT_BINARY); } static DBusHandlerResult adapter_get_remote_svc_xml(DBusConnection *conn, DBusMessage *msg, void *data) { - DBusMessage *reply; - const char *result = "" - ""; - - reply = dbus_message_new_method_return(msg); - if (!reply) - return DBUS_HANDLER_RESULT_NEED_MEMORY; - - dbus_message_append_args(reply, DBUS_TYPE_STRING, &result, - DBUS_TYPE_INVALID); - - return send_message_and_unref(conn, reply); + return get_remote_svc_rec(conn, msg, data, SDP_FORMAT_XML); } static DBusHandlerResult adapter_get_remote_svc_handles(DBusConnection *conn, DBusMessage *msg, void *data) Index: dbus-sdp.c =================================================================== RCS file: /cvsroot/bluez/utils/hcid/dbus-sdp.c,v retrieving revision 1.54 diff --unified=5 -r1.54 dbus-sdp.c --- dbus-sdp.c 1 Nov 2006 12:58:31 -0000 1.54 +++ dbus-sdp.c 9 Nov 2006 01:11:25 -0000 @@ -55,10 +55,11 @@ #include "dbus-adapter.h" #include "dbus-error.h" #include "dbus-sdp.h" #define MAX_IDENTIFIER_LEN 29 /* "XX:XX:XX:XX:XX:XX/0xYYYYYYYY\0" */ +#define DEFAULT_XML_BUFFER_SIZE 1024 struct service_provider { char *owner; /* null for remote services or unique name if local */ char *prov; /* remote Bluetooth address that provides the service */ struct slist *lrec; @@ -96,10 +97,37 @@ char *name; uint16_t class; char *info_name; } sdp_service_t; +typedef struct { + int size; + char *str; +} string_t; + +static void append_and_grow_string(void *data, const char *str) +{ + string_t *string = (string_t *)data; + char *newbuf; + + int oldlen = strlen(string->str); + int newlen = strlen(str); + + if ((oldlen + newlen + 1) > string->size) { + newbuf = (char *) malloc(string->size * 2); + if (!newbuf) + return; + + memcpy(newbuf, string->str, oldlen+1); + string->size *= 2; + free(string->str); + string->str = newbuf; + } + + strcat(string->str, str); +} + /* FIXME: move to a common file */ sdp_service_t sdp_service[] = { { "vcp", VIDEO_CONF_SVCLASS_ID, "Video Conference" }, { "map", 0, NULL }, { "pbap", PBAP_SVCLASS_ID, "Phone Book Access" }, @@ -608,10 +636,80 @@ send_message_and_unref(ctxt->conn, reply); failed: transaction_context_free(ctxt); } +static void remote_svc_rec_completed_xml_cb(uint8_t type, uint16_t err, uint8_t *rsp, size_t size, void *udata) +{ + struct transaction_context *ctxt = udata; + sdp_record_t *rec = NULL; + DBusMessage *reply; + const char *dst; + int scanned; + string_t result; + + if (!ctxt) + return; + + if (err == 0xffff) { + /* Check for protocol error or I/O error */ + int sdp_err = sdp_get_error(ctxt->session); + if (sdp_err < 0) { + error("search failed: Invalid session!"); + error_failed(ctxt->conn, ctxt->rq, EINVAL); + goto failed; + } + + error("search failed: %s (%d)", strerror(sdp_err), sdp_err); + error_failed(ctxt->conn, ctxt->rq, sdp_err); + goto failed; + } + + if (type == SDP_ERROR_RSP) { + error_sdp_failed(ctxt->conn, ctxt->rq, err); + goto failed; + } + + /* check response PDU ID */ + if (type != SDP_SVC_ATTR_RSP) { + error("SDP error: %s (%d)", strerror(EPROTO), EPROTO); + error_failed(ctxt->conn, ctxt->rq, EPROTO); + goto failed; + } + + dbus_message_get_args(ctxt->rq, NULL, + DBUS_TYPE_STRING, &dst, + DBUS_TYPE_INVALID); + + reply = dbus_message_new_method_return(ctxt->rq); + + result.str = 0; + + rec = sdp_extract_pdu(rsp, &scanned); + if (rec == NULL) { + error("SVC REC is null"); + goto done; + } + + result.str = malloc(sizeof(char) * DEFAULT_XML_BUFFER_SIZE); + result.size = DEFAULT_XML_BUFFER_SIZE; + + sdp_cache_append(NULL, dst, rec); + + convert_sdp_record_to_xml(rec, &result, append_and_grow_string); + + dbus_message_append_args(reply, + DBUS_TYPE_STRING, &result.str, + DBUS_TYPE_INVALID); + +done: + send_message_and_unref(ctxt->conn, reply); + free(result.str); +failed: + transaction_context_free(ctxt); +} + static void remote_svc_handles_completed_cb(uint8_t type, uint16_t err, uint8_t *rsp, size_t size, void *udata) { struct transaction_context *ctxt = udata; DBusMessage *reply; DBusMessageIter iter, array_iter; @@ -898,28 +996,65 @@ sdp_list_free(attrids, NULL); return err; } -DBusHandlerResult get_remote_svc_rec(DBusConnection *conn, DBusMessage *msg, void *data) +static int remote_svc_rec_conn_xml_cb(struct transaction_context *ctxt) +{ + sdp_list_t *attrids = NULL; + uint32_t range = 0x0000ffff; + const char *dst; + uint32_t handle; + int err = 0; + + if (sdp_set_notify(ctxt->session, remote_svc_rec_completed_xml_cb, ctxt) < 0) { + err = -EINVAL; + goto fail; + } + + dbus_message_get_args(ctxt->rq, NULL, + DBUS_TYPE_STRING, &dst, + DBUS_TYPE_UINT32, &handle, + DBUS_TYPE_INVALID); + + attrids = sdp_list_append(NULL, &range); + /* Create/send the search request and set the callback to indicate the request completion */ + if (sdp_service_attr_async(ctxt->session, handle, SDP_ATTR_REQ_RANGE, attrids) < 0) { + err = -sdp_get_error(ctxt->session); + goto fail; + } + +fail: + if (attrids) + sdp_list_free(attrids, NULL); + + return err; +} + +DBusHandlerResult get_remote_svc_rec(DBusConnection *conn, DBusMessage *msg, void *data, sdp_format_t format) { struct adapter *adapter = data; const char *dst; uint32_t handle; int err = 0; + connect_cb_t *cb; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &dst, DBUS_TYPE_UINT32, &handle, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg); if (find_pending_connect(dst)) return error_service_search_in_progress(conn, msg); + cb = remote_svc_rec_conn_cb; + if (format == SDP_FORMAT_XML) + cb = remote_svc_rec_conn_xml_cb; + if (!connect_request(conn, msg, adapter->dev_id, - dst, remote_svc_rec_conn_cb, &err)) { + dst, cb, &err)) { error("Search request failed: %s (%d)", strerror(err), err); return error_failed(conn, msg, err); } return DBUS_HANDLER_RESULT_HANDLED; Index: dbus-sdp.h =================================================================== RCS file: /cvsroot/bluez/utils/hcid/dbus-sdp.h,v retrieving revision 1.1 diff --unified=5 -r1.1 dbus-sdp.h --- dbus-sdp.h 30 Oct 2006 18:39:38 -0000 1.1 +++ dbus-sdp.h 9 Nov 2006 01:11:25 -0000 @@ -28,15 +28,20 @@ #include #include #define SDP_INTERFACE "org.bluez.SDP" +typedef enum { + SDP_FORMAT_XML, + SDP_FORMAT_BINARY +} sdp_format_t; + DBusHandlerResult handle_sdp_method(DBusConnection *conn, DBusMessage *msg, void *data); DBusHandlerResult get_remote_svc_handles(DBusConnection *conn, DBusMessage *msg, void *data); -DBusHandlerResult get_remote_svc_rec(DBusConnection *conn, DBusMessage *msg, void *data); +DBusHandlerResult get_remote_svc_rec(DBusConnection *conn, DBusMessage *msg, void *data, sdp_format_t format); uint16_t sdp_str2svclass(const char *str); typedef void get_record_cb_t(sdp_record_t *rec, void *data, int err); Index: service-record.dtd =================================================================== RCS file: /cvsroot/bluez/utils/hcid/service-record.dtd,v retrieving revision 1.2 diff --unified=5 -r1.2 service-record.dtd --- service-record.dtd 30 Oct 2006 14:11:16 -0000 1.2 +++ service-record.dtd 9 Nov 2006 01:11:25 -0000 @@ -1,16 +1,17 @@ - + - + - + + @@ -29,10 +30,24 @@ - + + + + + + + + + + + - - - + + + + + + +