client: Add set-advertise-manufacturer command

This adds set-advertise-manufacturer which can be used set manfacturer
spefic data to be advertised:

set-advertise-manufacturer [id][data=[xx xx ...]
[bluetooth]# set-advertise-manufacturer 0xffff 0x00 0x01 0x02 0x03
[bluetooth]# advertise on

@ Advertising Added: 1
< HCI Command: LE Set Advertising Data (0x08|0x0008) plen 32
        Length: 11
        Flags: 0x02
          LE General Discoverable Mode
        Company: internal use (65535)
          Data: 00010203
diff --git a/client/advertising.c b/client/advertising.c
index 3e4e10c..5176bc5 100644
--- a/client/advertising.c
+++ b/client/advertising.c
@@ -45,6 +45,9 @@
 static char *ad_service_uuid = NULL;
 static uint8_t ad_service_data[25];
 static uint8_t ad_service_data_len = 0;
+static uint16_t ad_manufacturer_id;
+static uint8_t ad_manufacturer_data[25];
+static uint8_t ad_manufacturer_data_len = 0;
 
 static void ad_release(DBusConnection *conn)
 {
@@ -212,10 +215,35 @@
 	return TRUE;
 }
 
+static gboolean manufacturer_data_exists(const GDBusPropertyTable *property,
+								void *data)
+{
+	return ad_manufacturer_id != 0;
+}
+
+static gboolean get_manufacturer_data(const GDBusPropertyTable *property,
+					DBusMessageIter *iter, void *user_data)
+{
+	DBusMessageIter dict;
+	const uint8_t *data = ad_manufacturer_data;
+
+	dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, "{qv}", &dict);
+
+	dict_append_basic_array(&dict, DBUS_TYPE_UINT16, &ad_manufacturer_id,
+					DBUS_TYPE_BYTE, &data,
+					ad_manufacturer_data_len);
+
+	dbus_message_iter_close_container(iter, &dict);
+
+	return TRUE;
+}
+
 static const GDBusPropertyTable ad_props[] = {
 	{ "Type", "s", get_type },
 	{ "ServiceUUIDs", "as", get_uuids, NULL, uuids_exists },
 	{ "ServiceData", "a{sv}", get_service_data, NULL, service_data_exists },
+	{ "ManufacturerData", "a{qv}", get_manufacturer_data, NULL,
+						manufacturer_data_exists },
 	{ }
 };
 
@@ -348,3 +376,56 @@
 done:
 	wordfree(&w);
 }
+
+static void ad_clear_manufacturer(void)
+{
+	ad_manufacturer_id = 0;
+	memset(ad_manufacturer_data, 0, sizeof(ad_manufacturer_data));
+	ad_manufacturer_data_len = 0;
+}
+
+void ad_advertise_manufacturer(const char *arg)
+{
+	wordexp_t w;
+	unsigned int i;
+	char *endptr = NULL;
+	long int val;
+
+	if (wordexp(arg, &w, WRDE_NOCMD)) {
+		rl_printf("Invalid argument\n");
+		return;
+	}
+
+	ad_clear_manufacturer();
+
+	if (w.we_wordc == 0)
+		goto done;
+
+	val = strtol(w.we_wordv[0], &endptr, 0);
+	if (!endptr || *endptr != '\0' || val > UINT16_MAX) {
+		rl_printf("Invalid manufacture id\n");
+		goto done;
+	}
+
+	ad_manufacturer_id = val;
+
+	for (i = 1; i < w.we_wordc; i++) {
+		if (i >= G_N_ELEMENTS(ad_service_data)) {
+			rl_printf("Too much data\n");
+			goto done;
+		}
+
+		val = strtol(w.we_wordv[i], &endptr, 0);
+		if (!endptr || *endptr != '\0' || val > UINT8_MAX) {
+			rl_printf("Invalid value at index %d\n", i);
+			ad_clear_service();
+			goto done;
+		}
+
+		ad_manufacturer_data[ad_manufacturer_data_len] = val;
+		ad_manufacturer_data_len++;
+	}
+
+done:
+	wordfree(&w);
+}
diff --git a/client/main.c b/client/main.c
index 72c2cd9..41a0af3 100644
--- a/client/main.c
+++ b/client/main.c
@@ -1883,6 +1883,11 @@
 	ad_advertise_service(arg);
 }
 
+static void cmd_set_advertise_manufacturer(const char *arg)
+{
+	ad_advertise_service(arg);
+}
+
 static const struct {
 	const char *cmd;
 	const char *arg;
@@ -1919,6 +1924,9 @@
 	{ "set-advertise-service", "[uuid][data=[xx xx ...]",
 			cmd_set_advertise_service,
 			"Set advertise service data" },
+	{ "set-advertise-manufacturer", "[id][data=[xx xx ...]",
+			cmd_set_advertise_manufacturer,
+			"Set advertise manufacturer data" },
 	{ "set-scan-filter-uuids", "[uuid1 uuid2 ...]",
 			cmd_set_scan_filter_uuids, "Set scan filter uuids" },
 	{ "set-scan-filter-rssi", "[rssi]", cmd_set_scan_filter_rssi,