[PATCH BlueZ 09/18] core: gatt: Support WriteValue for characteristics

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for writing to a characteristic from an external
application during a write procedure.
---
 src/gatt-manager.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 115 insertions(+), 5 deletions(-)

diff --git a/src/gatt-manager.c b/src/gatt-manager.c
index 66a4f72..ac9e01b 100644
--- a/src/gatt-manager.c
+++ b/src/gatt-manager.c
@@ -563,10 +563,116 @@ error:
 	gatt_db_attribute_read_result(attrib, id, ecode, NULL, 0);
 }
 
+static void write_setup_cb(DBusMessageIter *iter, void *user_data)
+{
+	struct pending_dbus_op *op = user_data;
+	struct iovec *iov = op->user_data;
+	DBusMessageIter array;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "y", &array);
+	dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+						&iov->iov_base, iov->iov_len);
+	dbus_message_iter_close_container(iter, &array);
+}
+
+static void write_reply_cb(DBusMessage *message, void *user_data)
+{
+	struct pending_dbus_op *op = user_data;
+	DBusError err;
+	DBusMessageIter iter;
+	uint8_t ecode = 0;
+
+	if (!op->chrc) {
+		DBG("Pending write was canceled when object got removed");
+		return;
+	}
+
+	dbus_error_init(&err);
+
+	if (dbus_set_error_from_message(&err, message) == TRUE) {
+		DBG("Failed to write value: %s: %s", err.name, err.message);
+		ecode = dbus_error_to_att_ecode(err.name);
+		ecode = ecode ? ecode : BT_ATT_ERROR_WRITE_NOT_PERMITTED;
+		dbus_error_free(&err);
+		goto done;
+	}
+
+	dbus_message_iter_init(message, &iter);
+	if (dbus_message_iter_has_next(&iter)) {
+		/*
+		 * Return not supported for this, as the external app basically
+		 * doesn't properly support the "WriteValue" API.
+		 */
+		ecode = BT_ATT_ERROR_REQUEST_NOT_SUPPORTED;
+		error("Invalid return value received for \"WriteValue\"");
+	}
+
+done:
+	gatt_db_attribute_write_result(op->chrc->attrib, op->id, ecode);
+}
+
+static void chrc_write_cb(struct gatt_db_attribute *attrib,
+					unsigned int id, uint16_t offset,
+					const uint8_t *value, size_t len,
+					uint8_t opcode, struct bt_att *att,
+					void *user_data)
+{
+	struct external_chrc *chrc = user_data;
+	struct pending_dbus_op *op;
+	uint8_t ecode = BT_ATT_ERROR_UNLIKELY;
+	struct iovec iov;
+
+	if (chrc->attrib != attrib) {
+		error("Write callback called with incorrect attribute");
+		goto error;
+	}
+
+	op = new0(struct pending_dbus_op, 1);
+	if (!op) {
+		error("Failed to allocate memory for pending read call");
+		ecode = BT_ATT_ERROR_INSUFFICIENT_RESOURCES;
+		goto error;
+	}
+
+	iov.iov_base = (uint8_t *) value;
+	iov.iov_len = len;
+
+	op->chrc = chrc;
+	op->id = id;
+	op->user_data = &iov;
+	queue_push_tail(chrc->pending_ops, op);
+
+	if (g_dbus_proxy_method_call(chrc->proxy, "WriteValue", write_setup_cb,
+						write_reply_cb, op,
+						pending_dbus_op_free) == TRUE)
+		return;
+
+	pending_dbus_op_free(op);
+
+error:
+	gatt_db_attribute_write_result(attrib, id, ecode);
+}
+
+static uint32_t permissions_from_props(uint8_t props, uint8_t ext_props)
+{
+	uint32_t perm = 0;
+
+	if (props & BT_GATT_CHRC_PROP_WRITE ||
+			props & BT_GATT_CHRC_PROP_WRITE_WITHOUT_RESP ||
+			ext_props & BT_GATT_CHRC_EXT_PROP_RELIABLE_WRITE)
+		perm |= BT_ATT_PERM_WRITE;
+
+	if (props & BT_GATT_CHRC_PROP_READ)
+		perm |= BT_ATT_PERM_READ;
+
+	return perm;
+}
+
 static bool create_chrc_entry(struct external_service *service,
 						struct external_chrc *chrc)
 {
 	bt_uuid_t uuid;
+	uint32_t perm;
 
 	if (!parse_uuid(chrc->proxy, &uuid)) {
 		error("Failed to read \"UUID\" property of characteristic");
@@ -575,15 +681,19 @@ static bool create_chrc_entry(struct external_service *service,
 
 	if (!parse_service(chrc->proxy, service)) {
 		error("Invalid service path for characteristic");
-		service->failed = true;
 		return false;
 	}
 
-	/* TODO: Assign permissions and write callback */
+	/*
+	 * TODO: Once shared/gatt-server properly supports permission checks,
+	 * set the permissions based on a D-Bus property of the external
+	 * characteristic.
+	 */
+	perm = permissions_from_props(chrc->props, chrc->ext_props);
 	chrc->attrib = gatt_db_service_add_characteristic(service->attrib,
-							&uuid, 0, chrc->props,
-							chrc_read_cb,
-							NULL, chrc);
+						&uuid, perm,
+						chrc->props, chrc_read_cb,
+						chrc_write_cb, chrc);
 
 	/* TODO: Create descriptor entries */
 
-- 
2.2.0.rc0.207.ga3a616c

--
To unsubscribe from this list: send the line "unsubscribe linux-bluetooth" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Bluez Devel]     [Linux Wireless Networking]     [Linux Wireless Personal Area Networking]     [Linux ATH6KL]     [Linux USB Devel]     [Linux Media Drivers]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Big List of Linux Books]

  Powered by Linux