hidpp: retrieve serial number for devices (v2)

Before this, history files were saved as history-rate-M525.dat. Since
multiple devices of the same model might be connected, this name is not
unique enough.

The serial number gives a more reliable path for the history files and
allows clients to distinguish their devices (an object path like
/org/freedesktop/UPower/devices/mouse_0003o046DoC52Bx0018 does not stay
the same).

Note: if a serial number cannot be read, instead of reverting this
patch, consider splitting the serial refresh from the version, kind and
model refresh.

 - v2: Fix invalid return value when an invalid parameter is passed to
   hidpp_device_get_serial.

Signed-off-by: Peter Wu <lekensteyn@gmail.com>
This commit is contained in:
Peter Wu 2013-08-19 12:46:48 +02:00 committed by Martin Pitt
parent 81ea62d8e1
commit 984d88f943
3 changed files with 42 additions and 1 deletions

View file

@ -153,6 +153,7 @@ struct HidppDevicePrivate
HidppDeviceKind kind;
int fd;
gboolean is_present;
gchar *serial;
};
typedef struct {
@ -524,6 +525,16 @@ hidpp_device_get_kind (HidppDevice *device)
return device->priv->kind;
}
/**
* hidpp_device_get_serial:
**/
const gchar *
hidpp_device_get_serial (HidppDevice *device)
{
g_return_val_if_fail (HIDPP_IS_DEVICE (device), NULL);
return device->priv->serial;
}
/**
* hidpp_device_is_reachable:
**/
@ -746,6 +757,30 @@ hidpp_device_refresh (HidppDevice *device,
}
}
/* get serial number, this can be queried from the receiver */
if ((refresh_flags & HIDPP_REFRESH_FLAGS_SERIAL) > 0) {
guint32 *serialp;
msg.type = HIDPP_MSG_TYPE_SHORT;
msg.device_idx = HIDPP_RECEIVER_ADDRESS;
msg.feature_idx = HIDPP_READ_LONG_REGISTER;
msg.function_idx = 0xb5;
msg.s.params[0] = 0x30 | (priv->device_idx - 1);
msg.s.params[1] = 0x00;
msg.s.params[2] = 0x00;
ret = hidpp_device_cmd (device,
&msg, &msg,
error);
if (!ret)
goto out;
name = g_string_new ("");
serialp = (guint32 *) &msg.l.params[1];
g_string_printf (name, "%08X", g_ntohl(*serialp));
priv->serial = g_strdup (name->str);
}
/* get battery status */
if ((refresh_flags & HIDPP_REFRESH_FLAGS_BATTERY) > 0) {
if (priv->version == 1) {
@ -918,6 +953,7 @@ hidpp_device_init (HidppDevice *device)
device->priv->batt_status = HIDPP_DEVICE_BATT_STATUS_UNKNOWN;
device->priv->batt_is_approx = FALSE;
device->priv->kind = HIDPP_DEVICE_KIND_UNKNOWN;
device->priv->serial = NULL;
/* add known root */
map = g_new0 (HidppDeviceMap, 1);
@ -952,6 +988,7 @@ hidpp_device_finalize (GObject *object)
g_free (device->priv->hidraw_device);
g_free (device->priv->model);
g_free (device->priv->serial);
G_OBJECT_CLASS (hidpp_device_parent_class)->finalize (object);
}

View file

@ -69,7 +69,8 @@ typedef enum {
HIDPP_REFRESH_FLAGS_KIND = 2,
HIDPP_REFRESH_FLAGS_BATTERY = 4,
HIDPP_REFRESH_FLAGS_MODEL = 8,
HIDPP_REFRESH_FLAGS_FEATURES = 16
HIDPP_REFRESH_FLAGS_FEATURES = 16,
HIDPP_REFRESH_FLAGS_SERIAL = 32
} HidppRefreshFlags;
GType hidpp_device_get_type (void);
@ -78,6 +79,7 @@ guint hidpp_device_get_batt_percentage (HidppDevice *device);
guint hidpp_device_get_version (HidppDevice *device);
HidppDeviceBattStatus hidpp_device_get_batt_status (HidppDevice *device);
HidppDeviceKind hidpp_device_get_kind (HidppDevice *device);
const gchar *hidpp_device_get_serial (HidppDevice *device);
void hidpp_device_set_hidraw_device (HidppDevice *device,
const gchar *hidraw_device);
void hidpp_device_set_index (HidppDevice *device,

View file

@ -246,6 +246,7 @@ up_device_unifying_coldplug (UpDevice *device)
ret = hidpp_device_refresh (unifying->priv->hidpp_device,
HIDPP_REFRESH_FLAGS_VERSION |
HIDPP_REFRESH_FLAGS_KIND |
HIDPP_REFRESH_FLAGS_SERIAL |
HIDPP_REFRESH_FLAGS_MODEL,
&error);
if (!ret) {
@ -264,6 +265,7 @@ up_device_unifying_coldplug (UpDevice *device)
"vendor", vendor,
"type", up_device_unifying_get_device_kind (unifying),
"model", hidpp_device_get_model (unifying->priv->hidpp_device),
"serial", hidpp_device_get_serial (unifying->priv->hidpp_device),
"has-history", TRUE,
"is-rechargeable", TRUE,
"power-supply", FALSE,