diff --git a/src/fu-device-locker.c b/src/fu-device-locker.c index cc9e66eb5..b032baae9 100644 --- a/src/fu-device-locker.c +++ b/src/fu-device-locker.c @@ -72,8 +72,8 @@ fu_device_locker_init (FuDeviceLocker *self) * manually closed using g_clear_object(). * * The functions used for opening and closing the device are set automatically. - * If the @device is not a type or supertype of #GUsbDevice or #FuUsbDevice - * then this function will not work. + * If the @device is not a type or supertype of #GUsbDevice, #FuUsbDevice or + * #FuDevice then this function will not work. * * For custom objects please use fu_device_locker_new_full(). * @@ -104,6 +104,14 @@ fu_device_locker_new (gpointer device, GError **error) (FuDeviceLockerFunc) fu_usb_device_close, error); } + + /* FuDevice */ + if (FU_IS_DEVICE (device)) { + return fu_device_locker_new_full (device, + (FuDeviceLockerFunc) fu_device_open, + (FuDeviceLockerFunc) fu_device_close, + error); + } g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, diff --git a/src/fu-device.c b/src/fu-device.c index dba9150dc..b010ed2fd 100644 --- a/src/fu-device.c +++ b/src/fu-device.c @@ -39,6 +39,7 @@ typedef struct { guint progress; guint order; guint priority; + gboolean done_probe; } FuDevicePrivate; enum { @@ -1243,6 +1244,101 @@ fu_device_attach (FuDevice *device, GError **error) return klass->attach (device, error); } +/** + * fu_device_open: + * @device: A #FuDevice + * @error: A #GError, or %NULL + * + * Opens a device, optionally running a object-specific vfunc. + * + * Returns: %TRUE for success + * + * Since: 1.1.2 + **/ +gboolean +fu_device_open (FuDevice *device, GError **error) +{ + FuDeviceClass *klass = FU_DEVICE_GET_CLASS (device); + + g_return_val_if_fail (FU_IS_DEVICE (device), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* probe */ + if (!fu_device_probe (device, error)) + return FALSE; + + /* subclassed */ + if (klass->open != NULL) { + if (!klass->open (device, error)) + return FALSE; + } + + /* success */ + return TRUE; +} + +/** + * fu_device_open: + * @device: A #FuDevice + * @error: A #GError, or %NULL + * + * Closes a device, optionally running a object-specific vfunc. + * + * Returns: %TRUE for success + * + * Since: 1.1.2 + **/ +gboolean +fu_device_close (FuDevice *device, GError **error) +{ + FuDeviceClass *klass = FU_DEVICE_GET_CLASS (device); + + g_return_val_if_fail (FU_IS_DEVICE (device), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* subclassed */ + if (klass->close != NULL) { + if (!klass->close (device, error)) + return FALSE; + } + return TRUE; +} + +/** + * fu_device_probe: + * @device: A #FuDevice + * @error: A #GError, or %NULL + * + * Probes a device, setting parameters on the object that does not need + * the device open or the interface claimed. + * If the device is not compatible then an error should be returned. + * + * Returns: %TRUE for success + * + * Since: 1.1.2 + **/ +gboolean +fu_device_probe (FuDevice *device, GError **error) +{ + FuDevicePrivate *priv = GET_PRIVATE (device); + FuDeviceClass *klass = FU_DEVICE_GET_CLASS (device); + + g_return_val_if_fail (FU_IS_DEVICE (device), FALSE); + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + + /* already done */ + if (priv->done_probe) + return TRUE; + + /* subclassed */ + if (klass->probe != NULL) { + if (!klass->probe (device, error)) + return FALSE; + } + priv->done_probe = TRUE; + return TRUE; +} + /** * fu_device_incorporate: * @device: A #FuDevice diff --git a/src/fu-device.h b/src/fu-device.h index 9f637bc2f..8a0db1e17 100644 --- a/src/fu-device.h +++ b/src/fu-device.h @@ -31,8 +31,14 @@ struct _FuDeviceClass GError **error); gboolean (*attach) (FuDevice *device, GError **error); + gboolean (*open) (FuDevice *device, + GError **error); + gboolean (*close) (FuDevice *device, + GError **error); + gboolean (*probe) (FuDevice *device, + GError **error); /*< private >*/ - gpointer padding[28]; + gpointer padding[25]; }; /** @@ -172,6 +178,12 @@ gboolean fu_device_detach (FuDevice *device, GError **error); void fu_device_incorporate (FuDevice *self, FuDevice *donor); +gboolean fu_device_open (FuDevice *device, + GError **error); +gboolean fu_device_close (FuDevice *device, + GError **error); +gboolean fu_device_probe (FuDevice *device, + GError **error); G_END_DECLS