blob: 5f32a6b91a55e01c07b1ce86ffd0370af51a0ebb [file] [log] [blame]
Richard Hughes117f8572021-02-09 20:02:48 +00001/*
2 * Copyright (C) 2021 Richard Hughes <richard@hughsie.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1+
5 */
6
7#define G_LOG_DOMAIN "FuBackend"
8
9#include "config.h"
10
11#include "fu-backend.h"
12
13typedef struct {
14 gchar *name;
Richard Hughes404f0522021-02-16 18:25:32 +000015 gboolean enabled;
Richard Hughes253e6e42021-02-24 14:59:24 +000016 GHashTable *devices; /* device_id : * FuDevice */
Richard Hughes117f8572021-02-09 20:02:48 +000017} FuBackendPrivate;
18
19enum {
20 SIGNAL_ADDED,
21 SIGNAL_REMOVED,
22 SIGNAL_CHANGED,
23 SIGNAL_LAST
24};
25
26enum {
27 PROP_0,
28 PROP_NAME,
29 PROP_LAST
30};
31
32static guint signals[SIGNAL_LAST] = { 0 };
33
34G_DEFINE_TYPE_WITH_PRIVATE (FuBackend, fu_backend, G_TYPE_OBJECT)
35#define GET_PRIVATE(o) (fu_backend_get_instance_private (o))
36
37void
38fu_backend_device_added (FuBackend *self, FuDevice *device)
39{
Richard Hughes253e6e42021-02-24 14:59:24 +000040 FuBackendPrivate *priv = GET_PRIVATE (self);
Richard Hughes117f8572021-02-09 20:02:48 +000041 g_return_if_fail (FU_IS_BACKEND (self));
42 g_return_if_fail (FU_IS_DEVICE (device));
Richard Hughes253e6e42021-02-24 14:59:24 +000043 g_hash_table_insert (priv->devices,
44 g_strdup (fu_device_get_backend_id (device)),
45 g_object_ref (device));
Richard Hughes117f8572021-02-09 20:02:48 +000046 g_signal_emit (self, signals[SIGNAL_ADDED], 0, device);
47}
48
49void
50fu_backend_device_removed (FuBackend *self, FuDevice *device)
51{
Richard Hughes253e6e42021-02-24 14:59:24 +000052 FuBackendPrivate *priv = GET_PRIVATE (self);
Richard Hughes117f8572021-02-09 20:02:48 +000053 g_return_if_fail (FU_IS_BACKEND (self));
54 g_return_if_fail (FU_IS_DEVICE (device));
55 g_signal_emit (self, signals[SIGNAL_REMOVED], 0, device);
Richard Hughes253e6e42021-02-24 14:59:24 +000056 g_hash_table_remove (priv->devices, fu_device_get_backend_id (device));
Richard Hughes117f8572021-02-09 20:02:48 +000057}
58
59void
60fu_backend_device_changed (FuBackend *self, FuDevice *device)
61{
62 g_return_if_fail (FU_IS_BACKEND (self));
63 g_return_if_fail (FU_IS_DEVICE (device));
64 g_signal_emit (self, signals[SIGNAL_CHANGED], 0, device);
65}
66
67gboolean
68fu_backend_setup (FuBackend *self, GError **error)
69{
70 FuBackendClass *klass = FU_BACKEND_GET_CLASS (self);
Richard Hughes404f0522021-02-16 18:25:32 +000071 FuBackendPrivate *priv = GET_PRIVATE (self);
72
Richard Hughes117f8572021-02-09 20:02:48 +000073 g_return_val_if_fail (FU_IS_BACKEND (self), FALSE);
74 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
Richard Hughes404f0522021-02-16 18:25:32 +000075
Richard Hughes117f8572021-02-09 20:02:48 +000076 if (klass->setup == NULL)
77 return TRUE;
Richard Hughes404f0522021-02-16 18:25:32 +000078 if (!klass->setup (self, error)) {
79 priv->enabled = FALSE;
80 return FALSE;
81 }
82 return TRUE;
Richard Hughes117f8572021-02-09 20:02:48 +000083}
84
85gboolean
86fu_backend_coldplug (FuBackend *self, GError **error)
87{
88 FuBackendClass *klass = FU_BACKEND_GET_CLASS (self);
89 g_return_val_if_fail (FU_IS_BACKEND (self), FALSE);
90 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
91 if (klass->coldplug == NULL)
92 return TRUE;
93 return klass->coldplug (self, error);
94}
95
Richard Hughes117f8572021-02-09 20:02:48 +000096const gchar *
97fu_backend_get_name (FuBackend *self)
98{
99 FuBackendPrivate *priv = GET_PRIVATE (self);
100 g_return_val_if_fail (FU_IS_BACKEND (self), NULL);
101 return priv->name;
102}
103
Richard Hughes404f0522021-02-16 18:25:32 +0000104gboolean
105fu_backend_get_enabled (FuBackend *self)
106{
107 FuBackendPrivate *priv = GET_PRIVATE (self);
108 g_return_val_if_fail (FU_IS_BACKEND (self), FALSE);
109 return priv->enabled;
110}
111
112void
113fu_backend_set_enabled (FuBackend *self, gboolean enabled)
114{
115 FuBackendPrivate *priv = GET_PRIVATE (self);
116 g_return_if_fail (FU_IS_BACKEND (self));
117 priv->enabled = FALSE;
118}
119
Richard Hughes253e6e42021-02-24 14:59:24 +0000120/* (transfer none) */
121FuDevice *
122fu_backend_lookup_by_id (FuBackend *self, const gchar *device_id)
123{
124 FuBackendPrivate *priv = GET_PRIVATE (self);
125 g_return_val_if_fail (FU_IS_BACKEND (self), NULL);
126 return g_hash_table_lookup (priv->devices, device_id);
127}
128
Richard Hughes117f8572021-02-09 20:02:48 +0000129static void
130fu_backend_get_property (GObject *object, guint prop_id,
131 GValue *value, GParamSpec *pspec)
132{
133 FuBackend *self = FU_BACKEND (object);
134 FuBackendPrivate *priv = GET_PRIVATE (self);
135 switch (prop_id) {
136 case PROP_NAME:
137 g_value_set_string (value, priv->name);
138 break;
139 default:
140 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
141 break;
142 }
143}
144
145static void
146fu_backend_set_property (GObject *object, guint prop_id,
147 const GValue *value, GParamSpec *pspec)
148{
149 FuBackend *self = FU_BACKEND (object);
150 FuBackendPrivate *priv = GET_PRIVATE (self);
151 switch (prop_id) {
152 case PROP_NAME:
153 priv->name = g_value_dup_string (value);
154 break;
155 default:
156 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
157 break;
158 }
159}
160
161static void
162fu_backend_init (FuBackend *self)
163{
Richard Hughes404f0522021-02-16 18:25:32 +0000164 FuBackendPrivate *priv = GET_PRIVATE (self);
165 priv->enabled = TRUE;
Richard Hughes253e6e42021-02-24 14:59:24 +0000166 priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal,
167 g_free,
168 (GDestroyNotify) g_object_unref);
Richard Hughes117f8572021-02-09 20:02:48 +0000169}
170
171static void
172fu_backend_finalize (GObject *object)
173{
174 FuBackend *self = FU_BACKEND (object);
175 FuBackendPrivate *priv = GET_PRIVATE (self);
176 g_free (priv->name);
Richard Hughes253e6e42021-02-24 14:59:24 +0000177 g_hash_table_unref (priv->devices);
Richard Hughes117f8572021-02-09 20:02:48 +0000178 G_OBJECT_CLASS (fu_backend_parent_class)->finalize (object);
179}
180
181static void
182fu_backend_class_init (FuBackendClass *klass)
183{
184 GObjectClass *object_class = G_OBJECT_CLASS (klass);
185 GParamSpec *pspec;
186
187 object_class->get_property = fu_backend_get_property;
188 object_class->set_property = fu_backend_set_property;
189 object_class->finalize = fu_backend_finalize;
190
191 pspec = g_param_spec_string ("name", NULL, NULL, NULL,
192 G_PARAM_CONSTRUCT_ONLY |
193 G_PARAM_READWRITE |
194 G_PARAM_STATIC_NAME);
195 g_object_class_install_property (object_class, PROP_NAME, pspec);
196
197 signals[SIGNAL_ADDED] =
198 g_signal_new ("device-added",
199 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
200 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
201 G_TYPE_NONE, 1, FU_TYPE_DEVICE);
202 signals[SIGNAL_REMOVED] =
203 g_signal_new ("device-removed",
204 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
205 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
206 G_TYPE_NONE, 1, FU_TYPE_DEVICE);
207 signals[SIGNAL_CHANGED] =
208 g_signal_new ("device-changed",
209 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
210 0, NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
211 G_TYPE_NONE, 1, FU_TYPE_DEVICE);
212}