[PATCH ] GATT: Fixed PTS issues for multiple write request

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

 



Updates gatt attribute db using offset value. This fixes below
PTS TCs.

TP/GAW/SR/BV-06-C
TP/GAW/SR/BV-10-C
TP/GAW/SR/BI-14-C
TP/GAW/SR/BI-15-C
TP/GAW/SR/BV-05-C
TP/GAW/SR/BI-07-C
TP/GAW/SR/BI-08-C
TP/GAW/SR/BI-34-C
TP/GAW/SR/BI-25-C
TP/GAW/SR/BI-26-C
---
 plugins/gatt-example.c        |  2 +-
 profiles/alert/server.c       | 16 ++++++-------
 profiles/proximity/linkloss.c |  2 +-
 profiles/time/server.c        |  6 ++---
 src/attrib-server.c           | 53 +++++++++++++++++++++++++++++++++++--------
 src/attrib-server.h           |  2 +-
 6 files changed, 57 insertions(+), 24 deletions(-)

diff --git a/plugins/gatt-example.c b/plugins/gatt-example.c
index 6e20b1f..f6c0ba0 100644
--- a/plugins/gatt-example.c
+++ b/plugins/gatt-example.c
@@ -101,7 +101,7 @@ static uint8_t battery_state_read(struct attribute *a,
 	uint8_t value;
 
 	value = 0x04;
-	attrib_db_update(adapter, a->handle, NULL, &value, sizeof(value), NULL);
+	attrib_db_update(adapter, a->handle, NULL, &value, sizeof(value), NULL, 0);
 
 	return 0;
 }
diff --git a/profiles/alert/server.c b/profiles/alert/server.c
index 1612d6c..4004ddc 100644
--- a/profiles/alert/server.c
+++ b/profiles/alert/server.c
@@ -302,12 +302,12 @@ static void update_supported_categories(gpointer data, gpointer user_data)
 	}
 
 	attrib_db_update(adapter, al_adapter->supp_new_alert_cat_handle, NULL,
-						value, sizeof(value), NULL);
+						value, sizeof(value), NULL, 0);
 
 	/* FIXME: For now report all registered categories as supporting unread
 	 * status, until it is known which ones should be supported */
 	attrib_db_update(adapter, al_adapter->supp_unread_alert_cat_handle,
-					NULL, value, sizeof(value), NULL);
+					NULL, value, sizeof(value), NULL, 0);
 }
 
 static void watcher_disconnect(DBusConnection *conn, void *user_data)
@@ -522,7 +522,7 @@ static void update_new_alert(gpointer data, gpointer user_data)
 	uint8_t *value = user_data;
 
 	attrib_db_update(adapter, al_adapter->hnd_value[NOTIFY_NEW_ALERT], NULL,
-						&value[1], value[0], NULL);
+						&value[1], value[0], NULL, 0);
 
 	notify_devices(al_adapter, NOTIFY_NEW_ALERT, &value[1], value[0]);
 }
@@ -682,7 +682,7 @@ static void update_unread_alert(gpointer data, gpointer user_data)
 
 	attrib_db_update(adapter,
 			al_adapter->hnd_value[NOTIFY_UNREAD_ALERT], NULL, value,
-			2, NULL);
+			2, NULL, 0);
 
 	notify_devices(al_adapter, NOTIFY_UNREAD_ALERT, value, 2);
 }
@@ -776,7 +776,7 @@ static uint8_t alert_status_read(struct attribute *a,
 
 	if (a->data == NULL || a->data[0] != alert_status)
 		attrib_db_update(adapter, a->handle, NULL, &alert_status,
-						sizeof(alert_status), NULL);
+						sizeof(alert_status), NULL, 0);
 
 	return 0;
 }
@@ -791,7 +791,7 @@ static uint8_t ringer_setting_read(struct attribute *a,
 
 	if (a->data == NULL || a->data[0] != ringer_setting)
 		attrib_db_update(adapter, a->handle, NULL, &ringer_setting,
-						sizeof(ringer_setting), NULL);
+						sizeof(ringer_setting), NULL, 0);
 
 	return 0;
 }
@@ -843,7 +843,7 @@ static uint8_t supp_new_alert_cat_read(struct attribute *a,
 
 	if (a->data == NULL)
 		attrib_db_update(adapter, a->handle, NULL, value, sizeof(value),
-									NULL);
+									NULL, 0);
 
 	return 0;
 }
@@ -859,7 +859,7 @@ static uint8_t supp_unread_alert_cat_read(struct attribute *a,
 
 	if (a->data == NULL)
 		attrib_db_update(adapter, a->handle, NULL, value, sizeof(value),
-									NULL);
+									NULL, 0);
 
 	return 0;
 }
diff --git a/profiles/proximity/linkloss.c b/profiles/proximity/linkloss.c
index 476803a..daf1156 100644
--- a/profiles/proximity/linkloss.c
+++ b/profiles/proximity/linkloss.c
@@ -165,7 +165,7 @@ out:
 
 	/* update the alert level according to the requesting device */
 	attrib_db_update(la->adapter, a->handle, NULL, &alert_level,
-						sizeof(alert_level), NULL);
+						sizeof(alert_level), NULL, 0);
 
 	return 0;
 }
diff --git a/profiles/time/server.c b/profiles/time/server.c
index 1716a5e..3a3ab2f 100644
--- a/profiles/time/server.c
+++ b/profiles/time/server.c
@@ -116,7 +116,7 @@ static uint8_t current_time_read(struct attribute *a,
 	if (encode_current_time(value) < 0)
 		return ATT_ECODE_IO;
 
-	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
+	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL, 0);
 
 	return 0;
 }
@@ -139,7 +139,7 @@ static uint8_t local_time_info_read(struct attribute *a,
 	 * is DST for the local time or not. The offset is unknown. */
 	value[1] = daylight ? 0xff : 0x00;
 
-	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
+	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL, 0);
 
 	return 0;
 }
@@ -202,7 +202,7 @@ static uint8_t time_update_status(struct attribute *a,
 
 	value[0] = UPDATE_STATE_IDLE;
 	value[1] = UPDATE_RESULT_SUCCESSFUL;
-	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL);
+	attrib_db_update(adapter, a->handle, NULL, value, sizeof(value), NULL, 0);
 
 	return 0;
 }
diff --git a/src/attrib-server.c b/src/attrib-server.c
index e65fff2..9e099ae 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -871,7 +871,7 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
 
 static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
 					const uint8_t *value, size_t vlen,
-					uint8_t *pdu, size_t len)
+					uint8_t *pdu, size_t len, uint16_t offset)
 {
 	struct attribute *a;
 	uint8_t status;
@@ -894,7 +894,7 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
 	if (bt_uuid_cmp(&ccc_uuid, &a->uuid) != 0) {
 
 		attrib_db_update(channel->server->adapter, handle, NULL,
-							value, vlen, NULL);
+							value, vlen, NULL, offset);
 
 		if (a->write_cb) {
 			status = a->write_cb(a, channel->device,
@@ -994,6 +994,7 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
 	uint8_t *value = g_attrib_get_buffer(channel->attrib, &vlen);
 
 	DBG("op 0x%02x", ipdu[0]);
+	length = 0;
 
 	if (len > vlen) {
 		error("Too much data on ATT socket");
@@ -1071,13 +1072,13 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
 		}
 
 		length = write_value(channel, start, value, vlen, opdu,
-								channel->mtu);
+								channel->mtu, 0);
 		break;
 	case ATT_OP_WRITE_CMD:
 		length = dec_write_cmd(ipdu, len, &start, value, &vlen);
 		if (length > 0)
 			write_value(channel, start, value, vlen, opdu,
-								channel->mtu);
+								channel->mtu, 0);
 		return;
 	case ATT_OP_FIND_BY_TYPE_REQ:
 		length = dec_find_by_type_req(ipdu, len, &start, &end,
@@ -1096,9 +1097,20 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
 	case ATT_OP_HANDLE_NOTIFY:
 		/* The attribute client is already handling these */
 		return;
-	case ATT_OP_READ_MULTI_REQ:
 	case ATT_OP_PREP_WRITE_REQ:
+		length = dec_prep_write_req(ipdu, len, &start, &offset, value, &vlen);
+		if (length == 0) {
+			status = ATT_ECODE_INVALID_PDU;
+			goto done;
+		}
+
+		length = write_value(channel, start, value, vlen, opdu,
+									channel->mtu, offset);
+		break;
+
 	case ATT_OP_EXEC_WRITE_REQ:
+		break;
+	case ATT_OP_READ_MULTI_REQ:
 	default:
 		DBG("Unsupported request 0x%02x", ipdu[0]);
 		status = ATT_ECODE_REQ_NOT_SUPP;
@@ -1562,7 +1574,7 @@ struct attribute *attrib_db_add(struct btd_adapter *adapter, uint16_t handle,
 
 int attrib_db_update(struct btd_adapter *adapter, uint16_t handle,
 					bt_uuid_t *uuid, const uint8_t *value,
-					size_t len, struct attribute **attr)
+					size_t len, struct attribute **attr, uint16_t offset)
 {
 	struct gatt_server *server;
 	struct attribute *a;
@@ -1585,12 +1597,33 @@ int attrib_db_update(struct btd_adapter *adapter, uint16_t handle,
 
 	a = dl->data;
 
-	a->data = g_try_realloc(a->data, len);
+	if (offset) {
+		uint8_t *temp;
+		temp = malloc(sizeof(uint8_t) * a->len);
+		if (temp == NULL) {
+			DBG("Unable to allocate memory");
+			return -ENOMEM;
+		}
+		memcpy(temp, a->data, a->len);
+		a->data = g_try_realloc(a->data, (a->len + (a->len - offset) + len));
+		memcpy(a->data, temp, a->len);
+		free(temp);
+	}
+	else {
+		a->data = g_try_realloc(a->data, len);
+	}
+
 	if (len && a->data == NULL)
 		return -ENOMEM;
 
-	a->len = len;
-	memcpy(a->data, value, len);
+	if (offset) {
+		a->len = a->len + (a->len - offset) + len;
+		memcpy((a->data + offset), value, len);
+	}
+	else {
+		a->len = len;
+		memcpy(a->data, value, len);
+	}
 
 	if (uuid != NULL)
 		a->uuid = *uuid;
@@ -1656,5 +1689,5 @@ int attrib_gap_set(struct btd_adapter *adapter, uint16_t uuid,
 		return -ENOSYS;
 	}
 
-	return attrib_db_update(adapter, handle, NULL, value, len, NULL);
+	return attrib_db_update(adapter, handle, NULL, value, len, NULL, 0);
 }
diff --git a/src/attrib-server.h b/src/attrib-server.h
index 063cb66..8b9e26e 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -30,7 +30,7 @@ struct attribute *attrib_db_add(struct btd_adapter *adapter, uint16_t handle,
 				size_t len);
 int attrib_db_update(struct btd_adapter *adapter, uint16_t handle,
 					bt_uuid_t *uuid, const uint8_t *value,
-					size_t len, struct attribute **attr);
+					size_t len, struct attribute **attr, uint16_t offset);
 int attrib_db_del(struct btd_adapter *adapter, uint16_t handle);
 int attrib_gap_set(struct btd_adapter *adapter, uint16_t uuid,
 					const uint8_t *value, size_t len);
-- 
1.9.1

--
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