Hi,
These patches implement the appearance of the device. It can be obtained via
GAP Appearance characteristic or via Advertising data. After getting the
appearance, the icon is set based in this information.
Currently, only a few Freedesktop.org icons map to GAP appearance values. We
can try to propose more icons to their standard, but it may take time and not
all icons may be accepted. Any ideas?
Comments are welcome.
BR,
Bruna Moreira.
Bruna Moreira (4):
dbus-common: Map GAP Appearance characteristic to icon
storage: Add storage to GAP characteristic
device: Appearance characteristic from GAP service
eir: Read GAP appearance from advertising data
src/adapter.c | 11 ++++++++
src/dbus-common.c | 33 ++++++++++++++++++++++++
src/dbus-common.h | 1 +
src/device.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++----
src/eir.c | 9 ++++++
src/eir.h | 2 +
src/storage.c | 38 ++++++++++++++++++++++++++++
src/storage.h | 2 +
8 files changed, 162 insertions(+), 6 deletions(-)
--
1.7.5.4
Hi Bruna,
On Thu, Mar 29, 2012, Bruna Moreira wrote:
> After searching for primary services, the appearance characteristic is
> read from GAP service and saved in "appearance" file. Running
> GetProperty in device interface, will show the respective icon based in
> "appearance" value.
> ---
> src/device.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
> 1 files changed, 63 insertions(+), 7 deletions(-)
All four patches in this set have been applied. Thanks.
Johan
After searching for primary services, the appearance characteristic is
read from GAP service and saved in "appearance" file. Running
GetProperty in device interface, will show the respective icon based in
"appearance" value.
---
src/device.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 63 insertions(+), 7 deletions(-)
diff --git a/src/device.c b/src/device.c
index 3b772ee..48b693c 100644
--- a/src/device.c
+++ b/src/device.c
@@ -73,6 +73,9 @@
/* When all services should trust a remote device */
#define GLOBAL_TRUST "[all]"
+#define GAP_SVC_UUID "00001800-0000-1000-8000-00805f9b34fb"
+#define APPEARANCE_CHR_UUID 0x2a01
+
struct btd_disconnect_data {
guint id;
disconnect_watch watch;
@@ -319,9 +322,10 @@ static DBusMessage *get_properties(DBusConnection *conn,
bdaddr_t src;
char name[MAX_NAME_LENGTH + 1], srcaddr[18], dstaddr[18];
char **str;
- const char *ptr;
+ const char *ptr, *icon = NULL;
dbus_bool_t boolean;
uint32_t class;
+ uint16_t app;
int i;
GSList *l;
@@ -363,14 +367,14 @@ static DBusMessage *get_properties(DBusConnection *conn,
/* Class */
if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
- const char *icon = class_to_icon(class);
+ icon = class_to_icon(class);
dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
+ } else if (read_remote_appearance(&src, &device->bdaddr, &app) == 0)
+ /* Appearance */
+ icon = gap_appearance_to_icon(app);
- if (icon)
- dict_append_entry(&dict, "Icon",
- DBUS_TYPE_STRING, &icon);
- }
+ dict_append_entry(&dict, "Icon", DBUS_TYPE_STRING, &icon);
/* Vendor */
if (device->vendor)
@@ -1784,10 +1788,50 @@ done:
return FALSE;
}
+static void appearance_cb(guint8 status, const guint8 *pdu, guint16 plen,
+ gpointer user_data)
+{
+ struct btd_device *device = user_data;
+ struct btd_adapter *adapter = device->adapter;
+ struct att_data_list *list = NULL;
+ uint16_t app;
+ bdaddr_t src;
+ uint8_t *atval;
+
+ if (status != 0) {
+ DBG("Read characteristics by UUID failed: %s\n",
+ att_ecode2str(status));
+ goto done;
+ }
+
+ list = dec_read_by_type_resp(pdu, plen);
+ if (list == NULL)
+ goto done;
+
+ if (list->len != 4) {
+ DBG("Appearance value: invalid data");
+ goto done;
+ }
+
+ /* A device shall have only one instance of the
+ Appearance characteristic. */
+ atval = list->data[0] + 2; /* skip handle value */
+ app = att_get_u16(atval);
+
+ adapter_get_address(adapter, &src);
+ write_remote_appearance(&src, &device->bdaddr, app);
+
+done:
+ att_data_list_free(list);
+ if (device->attios == NULL && device->attios_offline == NULL)
+ att_cleanup(device);
+}
+
static void primary_cb(GSList *services, guint8 status, gpointer user_data)
{
struct browse_req *req = user_data;
struct btd_device *device = req->device;
+ struct gatt_primary *gap_prim = NULL;
GSList *l, *uuids = NULL;
if (status) {
@@ -1804,13 +1848,25 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
for (l = services; l; l = l->next) {
struct gatt_primary *prim = l->data;
+
+ if (strcmp(prim->uuid, GAP_SVC_UUID) == 0)
+ gap_prim = prim;
+
uuids = g_slist_append(uuids, prim->uuid);
}
device_register_services(req->conn, device, g_slist_copy(services), -1);
device_probe_drivers(device, uuids);
- if (device->attios == NULL && device->attios_offline == NULL)
+ if (gap_prim) {
+ /* Read appearance characteristic */
+ bt_uuid_t uuid;
+
+ bt_uuid16_create(&uuid, APPEARANCE_CHR_UUID);
+
+ gatt_read_char_by_uuid(device->attrib, gap_prim->range.start,
+ gap_prim->range.end, &uuid, appearance_cb, device);
+ } else if (device->attios == NULL && device->attios_offline == NULL)
att_cleanup(device);
g_slist_free(uuids);
--
1.7.5.4
On Wed, Mar 28, 2012 at 5:58 AM, Johan Hedberg <[email protected]> wrote:
> Hi Bruna,
>
> On Tue, Mar 27, 2012, Bruna Moreira wrote:
>> @@ -363,15 +367,19 @@ static DBusMessage *get_properties(DBusConnection *conn,
>>
>> ? ? ? /* Class */
>> ? ? ? if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
>> - ? ? ? ? ? ? const char *icon = class_to_icon(class);
>> + ? ? ? ? ? ? icon = class_to_icon(class);
>>
>> ? ? ? ? ? ? ? dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
>> + ? ? } else if (read_remote_appearance(&src, &device->bdaddr, &app) == 0) {
>> + ? ? ? ? ? ? /* Appearance */
>> + ? ? ? ? ? ? icon = gap_appearance_to_icon(app);
>> + ? ? ? ? ? ? class = 0;
>>
>> - ? ? ? ? ? ? if (icon)
>> - ? ? ? ? ? ? ? ? ? ? dict_append_entry(&dict, "Icon",
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DBUS_TYPE_STRING, &icon);
>> + ? ? ? ? ? ? dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
>> ? ? ? }
>
> If we don't have a proper remote class value wouldn't it be simpler to
> just leave it out from the properties list instead of including a 0
> value?
Agreed, I am sending a new patch fixing that. Thanks.
BR,
--
Bruna Moreira
Instituto Nokia de Tecnologia (INdT)
Manaus - Brazil
Hi Bruna,
On Tue, Mar 27, 2012, Bruna Moreira wrote:
> @@ -363,15 +367,19 @@ static DBusMessage *get_properties(DBusConnection *conn,
>
> /* Class */
> if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
> - const char *icon = class_to_icon(class);
> + icon = class_to_icon(class);
>
> dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
> + } else if (read_remote_appearance(&src, &device->bdaddr, &app) == 0) {
> + /* Appearance */
> + icon = gap_appearance_to_icon(app);
> + class = 0;
>
> - if (icon)
> - dict_append_entry(&dict, "Icon",
> - DBUS_TYPE_STRING, &icon);
> + dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
> }
If we don't have a proper remote class value wouldn't it be simpler to
just leave it out from the properties list instead of including a 0
value?
Johan
This was introduced on Core Specification Supplement (CSS) v1.
---
src/adapter.c | 11 +++++++++++
src/eir.c | 7 +++++++
src/eir.h | 2 ++
3 files changed, 20 insertions(+), 0 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 7a2214a..3c7c6d8 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2698,6 +2698,7 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
if (dev->type != ADDR_TYPE_BREDR) {
gboolean broadcaster;
+ uint16_t app;
if (dev->flags & (EIR_LIM_DISC | EIR_GEN_DISC))
broadcaster = FALSE;
@@ -2706,8 +2707,14 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
dev->legacy = FALSE;
+ if (read_remote_appearance(&adapter->bdaddr, &dev->bdaddr,
+ &app) == 0)
+ icon = gap_appearance_to_icon(app);
+
emit_device_found(adapter->path, paddr,
"Address", DBUS_TYPE_STRING, &paddr,
+ "Class", DBUS_TYPE_UINT32, &dev->class,
+ "Icon", DBUS_TYPE_STRING, &icon,
"RSSI", DBUS_TYPE_INT16, &rssi,
"Name", DBUS_TYPE_STRING, &dev->name,
"Alias", DBUS_TYPE_STRING, &alias,
@@ -2837,6 +2844,10 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
if (dev_class != 0)
write_remote_class(&adapter->bdaddr, bdaddr, dev_class);
+ if (eir_data.appearance != 0)
+ write_remote_appearance(&adapter->bdaddr, bdaddr,
+ eir_data.appearance);
+
if (eir_data.name != NULL && eir_data.name_complete)
write_device_name(&adapter->bdaddr, bdaddr, eir_data.name);
diff --git a/src/eir.c b/src/eir.c
index 419f444..a8b3ae0 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -164,6 +164,13 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, uint8_t eir_len)
if (data_len < 3)
break;
memcpy(eir->dev_class, data, 3);
+ break;
+
+ case EIR_GAP_APPEARANCE:
+ if (data_len < 2)
+ break;
+ eir->appearance = bt_get_le16(data);
+ break;
}
eir_data += field_len + 1;
diff --git a/src/eir.h b/src/eir.h
index 13311ef..f712be5 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -34,6 +34,7 @@
#define EIR_TX_POWER 0x0A /* transmit power level */
#define EIR_CLASS_OF_DEV 0x0D /* Class of Device */
#define EIR_DEVICE_ID 0x10 /* device ID */
+#define EIR_GAP_APPEARANCE 0x19 /* GAP appearance */
struct uuid_info {
uuid_t uuid;
@@ -45,6 +46,7 @@ struct eir_data {
int flags;
char *name;
uint8_t dev_class[3];
+ uint16_t appearance;
gboolean name_complete;
};
--
1.7.5.4
Hi Bruna,
On Tue, Mar 27, 2012, Bruna Moreira wrote:
> --- a/src/eir.c
> +++ b/src/eir.c
> @@ -108,6 +108,7 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, uint8_t eir_len)
> while (len < eir_len - 1) {
> uint8_t field_len = eir_data[0];
> uint8_t data_len, *data = &eir_data[2];
> + uint16_t *u16;
>
> /* Check for the end of EIR */
> if (field_len == 0)
> @@ -164,6 +165,14 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, uint8_t eir_len)
> if (data_len < 3)
> break;
> memcpy(eir->dev_class, data, 3);
> + break;
> +
> + case EIR_GAP_APPEARANCE:
> + if (data_len < 2)
> + break;
> + u16 = (uint16_t *) data;
> + eir->appearance = btohs(bt_get_unaligned(u16));
> + break;
> }
I don't think you need the u16 variable at all. Just do:
eir->appearance = bt_get_le16(data);
Johan
This was introduced on Core Specification Supplement (CSS) v1.
---
src/adapter.c | 11 +++++++++++
src/eir.c | 9 +++++++++
src/eir.h | 2 ++
3 files changed, 22 insertions(+), 0 deletions(-)
diff --git a/src/adapter.c b/src/adapter.c
index 7a2214a..3c7c6d8 100644
--- a/src/adapter.c
+++ b/src/adapter.c
@@ -2698,6 +2698,7 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
if (dev->type != ADDR_TYPE_BREDR) {
gboolean broadcaster;
+ uint16_t app;
if (dev->flags & (EIR_LIM_DISC | EIR_GEN_DISC))
broadcaster = FALSE;
@@ -2706,8 +2707,14 @@ void adapter_emit_device_found(struct btd_adapter *adapter,
dev->legacy = FALSE;
+ if (read_remote_appearance(&adapter->bdaddr, &dev->bdaddr,
+ &app) == 0)
+ icon = gap_appearance_to_icon(app);
+
emit_device_found(adapter->path, paddr,
"Address", DBUS_TYPE_STRING, &paddr,
+ "Class", DBUS_TYPE_UINT32, &dev->class,
+ "Icon", DBUS_TYPE_STRING, &icon,
"RSSI", DBUS_TYPE_INT16, &rssi,
"Name", DBUS_TYPE_STRING, &dev->name,
"Alias", DBUS_TYPE_STRING, &alias,
@@ -2837,6 +2844,10 @@ void adapter_update_found_devices(struct btd_adapter *adapter,
if (dev_class != 0)
write_remote_class(&adapter->bdaddr, bdaddr, dev_class);
+ if (eir_data.appearance != 0)
+ write_remote_appearance(&adapter->bdaddr, bdaddr,
+ eir_data.appearance);
+
if (eir_data.name != NULL && eir_data.name_complete)
write_device_name(&adapter->bdaddr, bdaddr, eir_data.name);
diff --git a/src/eir.c b/src/eir.c
index 419f444..b9ecf31 100644
--- a/src/eir.c
+++ b/src/eir.c
@@ -108,6 +108,7 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, uint8_t eir_len)
while (len < eir_len - 1) {
uint8_t field_len = eir_data[0];
uint8_t data_len, *data = &eir_data[2];
+ uint16_t *u16;
/* Check for the end of EIR */
if (field_len == 0)
@@ -164,6 +165,14 @@ int eir_parse(struct eir_data *eir, uint8_t *eir_data, uint8_t eir_len)
if (data_len < 3)
break;
memcpy(eir->dev_class, data, 3);
+ break;
+
+ case EIR_GAP_APPEARANCE:
+ if (data_len < 2)
+ break;
+ u16 = (uint16_t *) data;
+ eir->appearance = btohs(bt_get_unaligned(u16));
+ break;
}
eir_data += field_len + 1;
diff --git a/src/eir.h b/src/eir.h
index 13311ef..f712be5 100644
--- a/src/eir.h
+++ b/src/eir.h
@@ -34,6 +34,7 @@
#define EIR_TX_POWER 0x0A /* transmit power level */
#define EIR_CLASS_OF_DEV 0x0D /* Class of Device */
#define EIR_DEVICE_ID 0x10 /* device ID */
+#define EIR_GAP_APPEARANCE 0x19 /* GAP appearance */
struct uuid_info {
uuid_t uuid;
@@ -45,6 +46,7 @@ struct eir_data {
int flags;
char *name;
uint8_t dev_class[3];
+ uint16_t appearance;
gboolean name_complete;
};
--
1.7.5.4
After searching for primary services, the appearance characteristic is
read from GAP service and saved in "appearance" file. Running
GetProperty in device interface, will show the Class equals to zero
(meaning the device is discovered over GATT and has an Appearance
characteristic) and the respective icon.
---
src/device.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 66 insertions(+), 6 deletions(-)
diff --git a/src/device.c b/src/device.c
index eab7e4c..4243263 100644
--- a/src/device.c
+++ b/src/device.c
@@ -73,6 +73,9 @@
/* When all services should trust a remote device */
#define GLOBAL_TRUST "[all]"
+#define GAP_SVC_UUID "00001800-0000-1000-8000-00805f9b34fb"
+#define APPEARANCE_CHR_UUID 0x2a01
+
struct btd_disconnect_data {
guint id;
disconnect_watch watch;
@@ -319,9 +322,10 @@ static DBusMessage *get_properties(DBusConnection *conn,
bdaddr_t src;
char name[MAX_NAME_LENGTH + 1], srcaddr[18], dstaddr[18];
char **str;
- const char *ptr;
+ const char *ptr, *icon = NULL;
dbus_bool_t boolean;
uint32_t class;
+ uint16_t app;
int i;
GSList *l;
@@ -363,15 +367,19 @@ static DBusMessage *get_properties(DBusConnection *conn,
/* Class */
if (read_remote_class(&src, &device->bdaddr, &class) == 0) {
- const char *icon = class_to_icon(class);
+ icon = class_to_icon(class);
dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
+ } else if (read_remote_appearance(&src, &device->bdaddr, &app) == 0) {
+ /* Appearance */
+ icon = gap_appearance_to_icon(app);
+ class = 0;
- if (icon)
- dict_append_entry(&dict, "Icon",
- DBUS_TYPE_STRING, &icon);
+ dict_append_entry(&dict, "Class", DBUS_TYPE_UINT32, &class);
}
+ dict_append_entry(&dict, "Icon", DBUS_TYPE_STRING, &icon);
+
/* Vendor */
if (device->vendor)
dict_append_entry(&dict, "Vendor", DBUS_TYPE_UINT16,
@@ -1784,10 +1792,50 @@ done:
return FALSE;
}
+static void appearance_cb(guint8 status, const guint8 *pdu, guint16 plen,
+ gpointer user_data)
+{
+ struct btd_device *device = user_data;
+ struct btd_adapter *adapter = device->adapter;
+ struct att_data_list *list = NULL;
+ uint16_t app;
+ bdaddr_t src;
+ uint8_t *atval;
+
+ if (status != 0) {
+ DBG("Read characteristics by UUID failed: %s\n",
+ att_ecode2str(status));
+ goto done;
+ }
+
+ list = dec_read_by_type_resp(pdu, plen);
+ if (list == NULL)
+ goto done;
+
+ if (list->len != 4) {
+ DBG("Appearance value: invalid data");
+ goto done;
+ }
+
+ /* A device shall have only one instance of the
+ Appearance characteristic. */
+ atval = list->data[0] + 2; /* skip handle value */
+ app = att_get_u16(atval);
+
+ adapter_get_address(adapter, &src);
+ write_remote_appearance(&src, &device->bdaddr, app);
+
+done:
+ att_data_list_free(list);
+ if (device->attios == NULL && device->attios_offline == NULL)
+ att_cleanup(device);
+}
+
static void primary_cb(GSList *services, guint8 status, gpointer user_data)
{
struct browse_req *req = user_data;
struct btd_device *device = req->device;
+ struct gatt_primary *gap_prim = NULL;
GSList *l, *uuids = NULL;
if (status) {
@@ -1804,13 +1852,25 @@ static void primary_cb(GSList *services, guint8 status, gpointer user_data)
for (l = services; l; l = l->next) {
struct gatt_primary *prim = l->data;
+
+ if (strcmp(prim->uuid, GAP_SVC_UUID) == 0)
+ gap_prim = prim;
+
uuids = g_slist_append(uuids, prim->uuid);
}
device_register_services(req->conn, device, g_slist_copy(services), -1);
device_probe_drivers(device, uuids);
- if (device->attios == NULL && device->attios_offline == NULL)
+ if (gap_prim) {
+ /* Read appearance characteristic */
+ bt_uuid_t uuid;
+
+ bt_uuid16_create(&uuid, APPEARANCE_CHR_UUID);
+
+ gatt_read_char_by_uuid(device->attrib, gap_prim->range.start,
+ gap_prim->range.end, &uuid, appearance_cb, device);
+ } else if (device->attios == NULL && device->attios_offline == NULL)
att_cleanup(device);
g_slist_free(uuids);
--
1.7.5.4
Add functions to read and write remote Appearance characteristic. The values
are saved in "appearance" file.
---
src/storage.c | 38 ++++++++++++++++++++++++++++++++++++++
src/storage.h | 2 ++
2 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/src/storage.c b/src/storage.c
index a65cee4..e9413b4 100644
--- a/src/storage.c
+++ b/src/storage.c
@@ -282,6 +282,44 @@ int read_local_class(bdaddr_t *bdaddr, uint8_t *class)
return 0;
}
+int read_remote_appearance(bdaddr_t *local, bdaddr_t *peer,
+ uint16_t *appearance)
+{
+ char filename[PATH_MAX + 1], addr[18], *str;
+
+ create_filename(filename, PATH_MAX, local, "appearance");
+
+ ba2str(peer, addr);
+
+ str = textfile_get(filename, addr);
+ if (!str)
+ return -ENOENT;
+
+ if (sscanf(str, "%hx", appearance) != 1) {
+ free(str);
+ return -ENOENT;
+ }
+
+ free(str);
+
+ return 0;
+}
+
+int write_remote_appearance(bdaddr_t *local, bdaddr_t *peer,
+ uint16_t appearance)
+{
+ char filename[PATH_MAX + 1], addr[18], str[7];
+
+ create_filename(filename, PATH_MAX, local, "appearance");
+
+ create_file(filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ ba2str(peer, addr);
+ sprintf(str, "0x%4.4x", appearance);
+
+ return textfile_put(filename, addr, str);
+}
+
int write_remote_class(bdaddr_t *local, bdaddr_t *peer, uint32_t class)
{
char filename[PATH_MAX + 1], addr[18], str[9];
diff --git a/src/storage.h b/src/storage.h
index 2f145d0..6967f97 100644
--- a/src/storage.h
+++ b/src/storage.h
@@ -36,6 +36,8 @@ int write_local_name(bdaddr_t *bdaddr, const char *name);
int read_local_name(bdaddr_t *bdaddr, char *name);
int write_local_class(bdaddr_t *bdaddr, uint8_t *class);
int read_local_class(bdaddr_t *bdaddr, uint8_t *class);
+int write_remote_appearance(bdaddr_t *local, bdaddr_t *peer, uint16_t appearance);
+int read_remote_appearance(bdaddr_t *local, bdaddr_t *peer, uint16_t *appearance);
int write_remote_class(bdaddr_t *local, bdaddr_t *peer, uint32_t class);
int read_remote_class(bdaddr_t *local, bdaddr_t *peer, uint32_t *class);
int write_device_name(bdaddr_t *local, bdaddr_t *peer, char *name);
--
1.7.5.4
Add function appearance_to_icon() to map values from Appearance
Characteristic to icon available.
Note: The Appearance Characteristic is composed of a category (10-bits)
and sub-categories (6-bits). These categories are defined at:
http://developer.bluetooth.org/gatt/characteristics/Pages/
CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
---
src/dbus-common.c | 33 +++++++++++++++++++++++++++++++++
src/dbus-common.h | 1 +
2 files changed, 34 insertions(+), 0 deletions(-)
diff --git a/src/dbus-common.c b/src/dbus-common.c
index ef3b375..7e1bc94 100644
--- a/src/dbus-common.c
+++ b/src/dbus-common.c
@@ -243,3 +243,36 @@ const char *class_to_icon(uint32_t class)
return NULL;
}
+
+const char *gap_appearance_to_icon(uint16_t appearance)
+{
+ switch ((appearance & 0xffc0) >> 6) {
+ case 0x01:
+ return "phone";
+ case 0x02:
+ return "computer";
+ case 0x05:
+ return "video-display";
+ case 0x0a:
+ return "multimedia-player";
+ case 0x0b:
+ return "scanner";
+ case 0x0f: /* HID Generic */
+ switch (appearance & 0x3f) {
+ case 0x01:
+ return "input-keyboard";
+ case 0x02:
+ return "input-mouse";
+ case 0x03:
+ case 0x04:
+ return "input-gaming";
+ case 0x05:
+ return "input-tablet";
+ case 0x08:
+ return "scanner";
+ }
+ break;
+ }
+
+ return NULL;
+}
diff --git a/src/dbus-common.h b/src/dbus-common.h
index b196a1b..b9531f2 100644
--- a/src/dbus-common.h
+++ b/src/dbus-common.h
@@ -45,3 +45,4 @@ void set_dbus_connection(DBusConnection *conn);
DBusConnection *get_dbus_connection(void);
const char *class_to_icon(uint32_t class);
+const char *gap_appearance_to_icon(uint16_t appearance);
--
1.7.5.4