[PATCH v2 1/2] Simplify eir_parse function

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

 



---
 src/eir.c |  155 +++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 80 insertions(+), 75 deletions(-)

diff --git a/src/eir.c b/src/eir.c
index e82d30b..f188031 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -54,24 +54,72 @@
 void eir_data_free(struct eir_data *eir)
 {
 	g_slist_free_full(eir->services, g_free);
+	eir->services = NULL;
 	g_free(eir->name);
+	eir->name = NULL;
 }
 
-int eir_parse(struct eir_data *eir, uint8_t *eir_data)
+static void eir_parse_uuid16(struct eir_data *eir, uint8_t *data, uint8_t len)
 {
-	uint16_t len = 0;
-	size_t total;
-	size_t uuid16_count = 0;
-	size_t uuid32_count = 0;
-	size_t uuid128_count = 0;
-	uint8_t *uuid16 = NULL;
-	uint8_t *uuid32 = NULL;
-	uint8_t *uuid128 = NULL;
+	uint8_t *uuid_ptr = data;
+	uuid_t service;
+	char *uuid_str;
+	unsigned int i;
+	uint16_t val16;
+
+	service.type = SDP_UUID16;
+	for (i = 0; i < len / 2; i++) {
+		val16 = uuid_ptr[1];
+		val16 = (val16 << 8) + uuid_ptr[0];
+		service.value.uuid16 = val16;
+		uuid_str = bt_uuid2string(&service);
+		eir->services = g_slist_append(eir->services, uuid_str);
+		uuid_ptr += 2;
+	}
+}
+
+static void eir_parse_uuid32(struct eir_data *eir, uint8_t *data, uint8_t len)
+{
+	uint8_t *uuid_ptr = data;
 	uuid_t service;
 	char *uuid_str;
-	const char *name = NULL;
-	size_t name_len;
 	unsigned int i;
+	uint32_t val32;
+	int k;
+
+	service.type = SDP_UUID32;
+	for (i = 0; i < len / 4; i++) {
+		val32 = uuid_ptr[3];
+		for (k = 2; k >= 0; k--)
+			val32 = (val32 << 8) + uuid_ptr[k];
+		service.value.uuid32 = val32;
+		uuid_str = bt_uuid2string(&service);
+		eir->services = g_slist_append(eir->services, uuid_str);
+		uuid_ptr += 4;
+	}
+}
+
+static void eir_parse_uuid128(struct eir_data *eir, uint8_t *data, uint8_t len)
+{
+	uint8_t *uuid_ptr = data;
+	uuid_t service;
+	char *uuid_str;
+	unsigned int i;
+	int k;
+
+	service.type = SDP_UUID128;
+	for (i = 0; i < len / 16; i++) {
+		for (k = 0; k < 16; k++)
+			service.value.uuid128.data[k] = uuid_ptr[16 - k - 1];
+		uuid_str = bt_uuid2string(&service);
+		eir->services = g_slist_append(eir->services, uuid_str);
+		uuid_ptr += 16;
+	}
+}
+
+int eir_parse(struct eir_data *eir, uint8_t *eir_data)
+{
+	uint16_t len = 0;
 
 	eir->flags = -1;
 
@@ -86,92 +134,49 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data)
 		if (field_len == 0)
 			break;
 
+		len += field_len + 1;
+
+		/* Bail out if got incorrect length */
+		if (len > HCI_MAX_EIR_LENGTH) {
+			eir_data_free(eir);
+			return -EINVAL;
+		}
+
 		switch (eir_data[1]) {
 		case EIR_UUID16_SOME:
 		case EIR_UUID16_ALL:
-			uuid16_count = field_len / 2;
-			uuid16 = &eir_data[2];
+			eir_parse_uuid16(eir, &eir_data[2], field_len);
 			break;
+
 		case EIR_UUID32_SOME:
 		case EIR_UUID32_ALL:
-			uuid32_count = field_len / 4;
-			uuid32 = &eir_data[2];
+			eir_parse_uuid32(eir, &eir_data[2], field_len);
 			break;
+
 		case EIR_UUID128_SOME:
 		case EIR_UUID128_ALL:
-			uuid128_count = field_len / 16;
-			uuid128 = &eir_data[2];
+			eir_parse_uuid128(eir, &eir_data[2], field_len);
 			break;
+
 		case EIR_FLAGS:
 			eir->flags = eir_data[2];
 			break;
+
 		case EIR_NAME_SHORT:
 		case EIR_NAME_COMPLETE:
-			name = (const char *) &eir_data[2];
-			name_len = field_len - 1;
+			if (g_utf8_validate((char *) &eir_data[2],
+							field_len - 1, NULL))
+				eir->name = g_strndup((char *) &eir_data[2],
+								field_len - 1);
+			else
+				eir->name = g_strdup("");
 			eir->name_complete = eir_data[1] == EIR_NAME_COMPLETE;
 			break;
 		}
 
-		len += field_len + 1;
 		eir_data += field_len + 1;
 	}
 
-	/* Bail out if got incorrect length */
-	if (len > HCI_MAX_EIR_LENGTH)
-		return -EINVAL;
-
-	if (name != NULL) {
-		if (g_utf8_validate(name, name_len, NULL))
-			eir->name = g_strndup(name, name_len);
-		else
-			eir->name = g_strdup("");
-	}
-
-	total = uuid16_count + uuid32_count + uuid128_count;
-
-	/* No UUIDs were parsed, so skip code below */
-	if (!total)
-		return 0;
-
-	/* Generate uuids in SDP format (EIR data is Little Endian) */
-	service.type = SDP_UUID16;
-	for (i = 0; i < uuid16_count; i++) {
-		uint16_t val16 = uuid16[1];
-
-		val16 = (val16 << 8) + uuid16[0];
-		service.value.uuid16 = val16;
-		uuid_str = bt_uuid2string(&service);
-		eir->services = g_slist_append(eir->services, uuid_str);
-		uuid16 += 2;
-	}
-
-	service.type = SDP_UUID32;
-	for (i = uuid16_count; i < uuid32_count + uuid16_count; i++) {
-		uint32_t val32 = uuid32[3];
-		int k;
-
-		for (k = 2; k >= 0; k--)
-			val32 = (val32 << 8) + uuid32[k];
-
-		service.value.uuid32 = val32;
-		uuid_str = bt_uuid2string(&service);
-		eir->services = g_slist_append(eir->services, uuid_str);
-		uuid32 += 4;
-	}
-
-	service.type = SDP_UUID128;
-	for (i = uuid32_count + uuid16_count; i < total; i++) {
-		int k;
-
-		for (k = 0; k < 16; k++)
-			service.value.uuid128.data[k] = uuid128[16 - k - 1];
-
-		uuid_str = bt_uuid2string(&service);
-		eir->services = g_slist_append(eir->services, uuid_str);
-		uuid128 += 16;
-	}
-
 	return 0;
 }
 
-- 
1.7.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