📄 dbus-sdp.c
字号:
c = pending_connect_new(conn, msg, dst, cb); if (!c) { if (err) *err = ENOMEM; return NULL; } hci_devba(dev_id, &srcba); str2ba(dst, &dstba); c->session = get_sdp_session(&srcba, &dstba); if (!c->session) { if (err) *err = errno; error("sdp_connect() failed: %s (%d)", strerror(errno), errno); pending_connect_free(c); return NULL; } chan = g_io_channel_unix_new(sdp_get_socket(c->session)); g_io_add_watch(chan, G_IO_OUT, sdp_client_connect_cb, c); g_io_channel_unref(chan); pending_connects = g_slist_append(pending_connects, c); return c;}static int remote_svc_rec_conn_cb(struct transaction_context *ctxt){ sdp_list_t *attrids; uint32_t range = 0x0000ffff; const char *dst; uint32_t handle; if (sdp_set_notify(ctxt->session, remote_svc_rec_completed_cb, ctxt) < 0) return -EINVAL; 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) { sdp_list_free(attrids, NULL); return -sdp_get_error(ctxt->session); } sdp_list_free(attrids, NULL); return 0;}static int remote_svc_rec_conn_xml_cb(struct transaction_context *ctxt){ sdp_list_t *attrids; uint32_t range = 0x0000ffff; const char *dst; uint32_t handle; if (sdp_set_notify(ctxt->session, remote_svc_rec_completed_xml_cb, ctxt) < 0) return -EINVAL; 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) { sdp_list_free(attrids, NULL); return -sdp_get_error(ctxt->session); } sdp_list_free(attrids, NULL); return 0;}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; connect_cb_t *cb; if (!adapter->up) return error_not_ready(conn, msg); 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, cb, &err)) { error("Search request failed: %s (%d)", strerror(err), err); return error_failed(conn, msg, err); } return DBUS_HANDLER_RESULT_HANDLED;}static int remote_svc_handles_conn_cb(struct transaction_context *ctxt){ sdp_list_t *search = NULL; const char *dst, *svc; if (sdp_set_notify(ctxt->session, remote_svc_handles_completed_cb, ctxt) < 0) return -EINVAL; dbus_message_get_args(ctxt->rq, NULL, DBUS_TYPE_STRING, &dst, DBUS_TYPE_STRING, &svc, DBUS_TYPE_INVALID); if (strlen(svc) > 0) str2uuid(&ctxt->uuid, svc); else sdp_uuid16_create(&ctxt->uuid, PUBLIC_BROWSE_GROUP); search = sdp_list_append(0, &ctxt->uuid); /* Create/send the search request and set the callback to indicate the request completion */ if (sdp_service_search_async(ctxt->session, search, 64) < 0) { error("send request failed: %s (%d)", strerror(errno), errno); sdp_list_free(search, NULL); return -sdp_get_error(ctxt->session); } sdp_list_free(search, NULL); return 0;}static int remote_svc_identifiers_conn_cb(struct transaction_context *ctxt){ if (sdp_set_notify(ctxt->session, remote_svc_identifiers_completed_cb, ctxt) < 0) return -EINVAL; return service_search_attr(ctxt, PUBLIC_BROWSE_GROUP);}DBusHandlerResult get_remote_svc_handles(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; const char *dst, *svc; int err; uuid_t uuid; if (!adapter->up) return error_not_ready(conn, msg); if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &dst, DBUS_TYPE_STRING, &svc, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg); if (strlen(svc) > 0) { /* Check if it is a service name string */ if (str2uuid(&uuid, svc) < 0) { error("Invalid service class name"); return error_invalid_arguments(conn, msg); } } if (find_pending_connect(dst)) return error_service_search_in_progress(conn, msg); if (!connect_request(conn, msg, adapter->dev_id, dst, remote_svc_handles_conn_cb, &err)) { error("Search request failed: %s (%d)", strerror(err), err); return error_failed(conn, msg, err); } return DBUS_HANDLER_RESULT_HANDLED;}DBusHandlerResult get_remote_svc_identifiers(DBusConnection *conn, DBusMessage *msg, void *data){ struct adapter *adapter = data; const char *dst; int err; if (!adapter->up) return error_not_ready(conn, msg); if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &dst, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg); if (find_pending_connect(dst)) return error_service_search_in_progress(conn, msg); if (!connect_request(conn, msg, adapter->dev_id, dst, remote_svc_identifiers_conn_cb, &err)) { error("Search request failed: %s (%d)", strerror(err), err); return error_failed(conn, msg, err); } return DBUS_HANDLER_RESULT_HANDLED;}DBusHandlerResult finish_remote_svc_transact(DBusConnection *conn, DBusMessage *msg, void *data){ struct cached_session *s; const char *address; struct adapter *adapter = data; DBusMessage *reply; bdaddr_t sba, dba; if (!dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID)) return error_invalid_arguments(conn, msg); reply = dbus_message_new_method_return(msg); if (!reply) return DBUS_HANDLER_RESULT_NEED_MEMORY; str2ba(adapter->address, &sba); str2ba(address, &dba); while ((s = get_cached_session(&sba, &dba))) { sdp_close(s->session); g_source_remove(s->timeout_id); g_source_remove(s->io_id); g_free(s); } return send_message_and_unref(conn, reply);}/* * Internal async get remote service record implementation */static void get_rec_with_handle_comp_cb(uint8_t type, uint16_t err, uint8_t *rsp, size_t size, void *udata){ struct transaction_context *ctxt = udata; int scanned, cb_err = 0; sdp_record_t *rec = NULL; if (err == 0xffff) { int sdp_err = sdp_get_error(ctxt->session); if (sdp_err < 0) { error("search failed: Invalid session!"); cb_err = EINVAL; goto failed; } error("search failed :%s (%d)", strerror(sdp_err), sdp_err); cb_err = sdp_err; goto failed; } if (type == SDP_ERROR_RSP || type != SDP_SVC_ATTR_RSP) { error("SDP error: %s(%d)", strerror(EPROTO), EPROTO); cb_err = EPROTO; goto failed; } rec = sdp_extract_pdu(rsp, &scanned); if (!rec) { error("Service record is NULL"); cb_err = EPROTO; goto failed; }failed: get_record_data_call_cb(ctxt->call, rec, cb_err); if (rec) sdp_record_free(rec); get_record_data_free(ctxt->call); transaction_context_free(ctxt, TRUE);}static int get_rec_with_handle_conn_cb(struct transaction_context *ctxt){ uint32_t range = 0x0000ffff; sdp_list_t *attrids; uint32_t handle; if (sdp_set_notify(ctxt->session, get_rec_with_handle_comp_cb, ctxt) < 0) { error("Invalid session data!"); return -EINVAL; } handle = *((uint32_t *)ctxt->call->search_data); attrids = sdp_list_append(NULL, &range); if (sdp_service_attr_async(ctxt->session, handle, SDP_ATTR_REQ_RANGE, attrids) < 0) { error("send request failed: %s (%d)", strerror(errno), errno); sdp_list_free(attrids, NULL); return -errno; } sdp_list_free(attrids, NULL); return 0;}int get_record_with_handle(DBusConnection *conn, DBusMessage *msg, uint16_t dev_id, const char *dst, uint32_t handle, get_record_cb_t *cb, void *data){ struct pending_connect *c; get_record_data_t *d; uint32_t *rec_handle; int err; if (find_pending_connect(dst)) { error("SDP search in progress!"); return -EINPROGRESS; } rec_handle = g_new(uint32_t, 1); *rec_handle = handle; d = get_record_data_new(dev_id, dst, rec_handle, cb, data); if (!(c = connect_request(conn, msg, dev_id, dst, get_rec_with_handle_conn_cb, &err))) { error("Search request failed: %s (%d)", strerror(err), err); get_record_data_free(d); return -err; } c->call = d; return 0;}static void get_rec_with_uuid_comp_cb(uint8_t type, uint16_t err, uint8_t *rsp, size_t size, void *udata){ struct transaction_context *ctxt = udata; get_record_data_t *d = ctxt->call; int csrc, tsrc, cb_err = 0; uint32_t *handle; uint8_t *pdata; if (err == 0xffff) { int sdp_err = sdp_get_error(ctxt->session); if (sdp_err < 0) { error("search failed: Invalid session!"); cb_err = EINVAL; goto failed; } error("search failed: %s (%d)", strerror(sdp_err), sdp_err); cb_err = sdp_err; goto failed; } if (type == SDP_ERROR_RSP || type != SDP_SVC_SEARCH_RSP) { error("SDP error: %s (%d)", strerror(EPROTO), EPROTO); cb_err = EPROTO; goto failed; } pdata = rsp; tsrc = ntohs(bt_get_unaligned((uint16_t *) pdata)); if (tsrc <= 0) goto failed; pdata += sizeof(uint16_t); csrc = ntohs(bt_get_unaligned((uint16_t *) pdata)); if (csrc <= 0) goto failed; pdata += sizeof(uint16_t); handle = g_new(uint32_t, 1); *handle = ntohl(bt_get_unaligned((uint32_t*) pdata)); g_free(d->search_data); d->search_data = handle; cb_err = get_rec_with_handle_conn_cb(ctxt); if (cb_err) goto failed; return;failed: get_record_data_call_cb(d, NULL, cb_err); get_record_data_free(d); transaction_context_free(ctxt, TRUE);}static int get_rec_with_uuid_conn_cb(struct transaction_context *ctxt){ get_record_data_t *d = ctxt->call; sdp_list_t *search = NULL; uuid_t *uuid; int err = 0; if (sdp_set_notify(ctxt->session, get_rec_with_uuid_comp_cb, ctxt) < 0) { err = -EINVAL; goto failed; } uuid = (uuid_t *)d->search_data; search = sdp_list_append(NULL, uuid); if (sdp_service_search_async(ctxt->session, search, 1) < 0) { error("send request failed: %s (%d)", strerror(errno), errno); err = -sdp_get_error(ctxt->session); goto failed; }failed: if (search) sdp_list_free(search, NULL); return err;}int get_record_with_uuid(DBusConnection *conn, DBusMessage *msg, uint16_t dev_id, const char *dst, const uuid_t *uuid, get_record_cb_t *cb, void *data){ struct pending_connect *c; get_record_data_t *d; int err; uuid_t *sdp_uuid; if (find_pending_connect(dst)) { error("SDP search in progress!"); return -EINPROGRESS; } sdp_uuid = g_new(uuid_t, 1); memcpy(sdp_uuid, uuid, sizeof(uuid_t)); d = get_record_data_new(dev_id, dst, sdp_uuid, cb, data); if (!(c = connect_request(conn, msg, dev_id, dst, get_rec_with_uuid_conn_cb, &err))) { error("Search request failed: %s (%d)", strerror(err), err); get_record_data_free(d); return -err; } c->call = d; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -