Coverage Report

Created: 2026-03-11 07:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fwupd/libfwupd/fwupd-device.c
Line
Count
Source
1
/*
2
 * Copyright 2015 Richard Hughes <richard@hughsie.com>
3
 *
4
 * SPDX-License-Identifier: LGPL-2.1-or-later
5
 */
6
7
#include "config.h"
8
9
#include <gio/gio.h>
10
#include <string.h>
11
12
#include "fwupd-codec.h"
13
#include "fwupd-common-private.h"
14
#include "fwupd-device-private.h"
15
#include "fwupd-enums-private.h"
16
#include "fwupd-error.h"
17
#include "fwupd-json-array.h"
18
#include "fwupd-json-object.h"
19
20
/**
21
 * FwupdDevice:
22
 *
23
 * A physical device on the host with optionally updatable firmware.
24
 *
25
 * See also: [class@FwupdRelease]
26
 */
27
28
static void
29
fwupd_device_finalize(GObject *object);
30
31
typedef struct {
32
  gchar *id;
33
  gchar *parent_id;
34
  gchar *composite_id;
35
  guint64 created;
36
  guint64 modified;
37
  guint64 flags;
38
  guint64 request_flags;
39
  guint64 problems;
40
  GPtrArray *guids;  /* (nullable) (element-type utf-8) */
41
  GPtrArray *vendor_ids;   /* (nullable) (element-type utf-8) */
42
  GPtrArray *protocols;  /* (nullable) (element-type utf-8) */
43
  GPtrArray *instance_ids; /* (nullable) (element-type utf-8) */
44
  GPtrArray *icons;  /* (nullable) (element-type utf-8) */
45
  GPtrArray *issues;   /* (nullable) (element-type utf-8) */
46
  gchar *name;
47
  gchar *serial;
48
  gchar *summary;
49
  gchar *branch;
50
  gchar *vendor;
51
  gchar *homepage;
52
  gchar *plugin;
53
  gchar *version;
54
  gchar *version_lowest;
55
  gchar *version_bootloader;
56
  FwupdVersionFormat version_format;
57
  guint64 version_raw;
58
  guint64 version_build_date;
59
  guint64 version_lowest_raw;
60
  guint64 version_bootloader_raw;
61
  GPtrArray *checksums; /* (nullable) (element-type utf-8) */
62
  GPtrArray *children;  /* (nullable) (element-type FuDevice) */
63
  guint32 flashes_left;
64
  guint32 battery_level;
65
  guint32 battery_threshold;
66
  guint32 install_duration;
67
  FwupdUpdateState update_state;
68
  gchar *update_error;
69
  FwupdStatus status;
70
  guint percentage;
71
  GPtrArray *releases; /* (nullable) (element-type FwupdRelease) */
72
  FwupdDevice *parent; /* noref */
73
} FwupdDevicePrivate;
74
75
enum {
76
  PROP_0,
77
  PROP_ID,
78
  PROP_VERSION,
79
  PROP_VERSION_FORMAT,
80
  PROP_FLAGS,
81
  PROP_REQUEST_FLAGS,
82
  PROP_STATUS,
83
  PROP_PERCENTAGE,
84
  PROP_PARENT,
85
  PROP_UPDATE_STATE,
86
  PROP_UPDATE_ERROR,
87
  PROP_BATTERY_LEVEL,
88
  PROP_BATTERY_THRESHOLD,
89
  PROP_PROBLEMS,
90
  PROP_VENDOR,
91
  PROP_LAST
92
};
93
94
static void
95
fwupd_device_codec_iface_init(FwupdCodecInterface *iface);
96
97
20.1k
G_DEFINE_TYPE_EXTENDED(FwupdDevice,
98
20.1k
           fwupd_device,
99
20.1k
           G_TYPE_OBJECT,
100
20.1k
           0,
101
20.1k
           G_ADD_PRIVATE(FwupdDevice)
102
20.1k
         G_IMPLEMENT_INTERFACE(FWUPD_TYPE_CODEC, fwupd_device_codec_iface_init));
103
20.1k
104
20.1k
#define GET_PRIVATE(o) (fwupd_device_get_instance_private(o))
105
106
0
#define FWUPD_BATTERY_THRESHOLD_DEFAULT 10 /* % */
107
108
static void
109
fwupd_device_ensure_checksums(FwupdDevice *self)
110
0
{
111
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
112
0
  if (priv->checksums == NULL)
113
0
    priv->checksums = g_ptr_array_new_with_free_func(g_free);
114
0
}
115
116
/**
117
 * fwupd_device_get_checksums:
118
 * @self: a #FwupdDevice
119
 *
120
 * Gets the device checksums.
121
 *
122
 * Returns: (element-type utf8) (transfer none): the checksums, which may be empty
123
 *
124
 * Since: 0.9.3
125
 **/
126
GPtrArray *
127
fwupd_device_get_checksums(FwupdDevice *self)
128
0
{
129
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
130
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
131
0
  fwupd_device_ensure_checksums(self);
132
0
  return priv->checksums;
133
0
}
134
135
/**
136
 * fwupd_device_has_checksum:
137
 * @self: a #FwupdDevice
138
 * @checksum: (not nullable): the device checksum
139
 *
140
 * Finds out if the device has this specific checksum.
141
 *
142
 * Returns: %TRUE if the checksum name is found
143
 *
144
 * Since: 1.8.7
145
 **/
146
gboolean
147
fwupd_device_has_checksum(FwupdDevice *self, const gchar *checksum)
148
0
{
149
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
150
151
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
152
0
  g_return_val_if_fail(checksum != NULL, FALSE);
153
154
0
  if (priv->checksums == NULL)
155
0
    return FALSE;
156
0
  for (guint i = 0; i < priv->checksums->len; i++) {
157
0
    const gchar *checksum_tmp = g_ptr_array_index(priv->checksums, i);
158
0
    if (g_strcmp0(checksum, checksum_tmp) == 0)
159
0
      return TRUE;
160
0
  }
161
0
  return FALSE;
162
0
}
163
164
/**
165
 * fwupd_device_add_checksum:
166
 * @self: a #FwupdDevice
167
 * @checksum: (not nullable): the device checksum
168
 *
169
 * Adds a device checksum.
170
 *
171
 * Since: 0.9.3
172
 **/
173
void
174
fwupd_device_add_checksum(FwupdDevice *self, const gchar *checksum)
175
0
{
176
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
177
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
178
0
  g_return_if_fail(checksum != NULL);
179
180
0
  if (fwupd_device_has_checksum(self, checksum))
181
0
    return;
182
0
  fwupd_device_ensure_checksums(self);
183
0
  g_ptr_array_add(priv->checksums, g_strdup(checksum));
184
0
}
185
186
static void
187
fwupd_device_ensure_issues(FwupdDevice *self)
188
0
{
189
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
190
0
  if (priv->issues == NULL)
191
0
    priv->issues = g_ptr_array_new_with_free_func(g_free);
192
0
}
193
194
/**
195
 * fwupd_device_get_issues:
196
 * @self: a #FwupdDevice
197
 *
198
 * Gets the list of issues currently affecting this device.
199
 *
200
 * Returns: (element-type utf8) (transfer none): the issues, which may be empty
201
 *
202
 * Since: 1.7.6
203
 **/
204
GPtrArray *
205
fwupd_device_get_issues(FwupdDevice *self)
206
0
{
207
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
208
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
209
0
  fwupd_device_ensure_issues(self);
210
0
  return priv->issues;
211
0
}
212
213
/**
214
 * fwupd_device_add_issue:
215
 * @self: a #FwupdDevice
216
 * @issue: (not nullable): the update issue, e.g. `CVE-2019-12345`
217
 *
218
 * Adds an current issue to this device.
219
 *
220
 * Since: 1.7.6
221
 **/
222
void
223
fwupd_device_add_issue(FwupdDevice *self, const gchar *issue)
224
0
{
225
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
226
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
227
0
  g_return_if_fail(issue != NULL);
228
229
0
  fwupd_device_ensure_issues(self);
230
0
  for (guint i = 0; i < priv->issues->len; i++) {
231
0
    const gchar *issue_tmp = g_ptr_array_index(priv->issues, i);
232
0
    if (g_strcmp0(issue_tmp, issue) == 0)
233
0
      return;
234
0
  }
235
0
  g_ptr_array_add(priv->issues, g_strdup(issue));
236
0
}
237
238
static void
239
fwupd_device_ensure_children(FwupdDevice *self)
240
0
{
241
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
242
0
  if (priv->children == NULL)
243
0
    priv->children = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
244
0
}
245
246
/**
247
 * fwupd_device_get_children:
248
 * @self: a #FwupdDevice
249
 *
250
 * Gets the device children. These can only be assigned using fwupd_device_set_parent().
251
 *
252
 * Returns: (element-type FwupdDevice) (transfer none): the children, which may be empty
253
 *
254
 * Since: 1.3.7
255
 **/
256
GPtrArray *
257
fwupd_device_get_children(FwupdDevice *self)
258
0
{
259
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
260
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
261
0
  fwupd_device_ensure_children(self);
262
0
  return priv->children;
263
0
}
264
265
/**
266
 * fwupd_device_get_summary:
267
 * @self: a #FwupdDevice
268
 *
269
 * Gets the device summary.
270
 *
271
 * Returns: the device summary, or %NULL if unset
272
 *
273
 * Since: 0.9.3
274
 **/
275
const gchar *
276
fwupd_device_get_summary(FwupdDevice *self)
277
0
{
278
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
279
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
280
0
  return priv->summary;
281
0
}
282
283
/**
284
 * fwupd_device_set_summary:
285
 * @self: a #FwupdDevice
286
 * @summary: (nullable): the device one line summary
287
 *
288
 * Sets the device summary.
289
 *
290
 * Since: 0.9.3
291
 **/
292
void
293
fwupd_device_set_summary(FwupdDevice *self, const gchar *summary)
294
0
{
295
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
296
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
297
298
  /* not changed */
299
0
  if (g_strcmp0(priv->summary, summary) == 0)
300
0
    return;
301
302
0
  g_free(priv->summary);
303
0
  priv->summary = g_strdup(summary);
304
0
}
305
306
/**
307
 * fwupd_device_get_branch:
308
 * @self: a #FwupdDevice
309
 *
310
 * Gets the current device branch.
311
 *
312
 * Returns: the device branch, or %NULL if unset
313
 *
314
 * Since: 1.5.0
315
 **/
316
const gchar *
317
fwupd_device_get_branch(FwupdDevice *self)
318
0
{
319
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
320
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
321
0
  return priv->branch;
322
0
}
323
324
/**
325
 * fwupd_device_set_branch:
326
 * @self: a #FwupdDevice
327
 * @branch: (nullable): the device one line branch
328
 *
329
 * Sets the current device branch.
330
 *
331
 * Since: 1.5.0
332
 **/
333
void
334
fwupd_device_set_branch(FwupdDevice *self, const gchar *branch)
335
0
{
336
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
337
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
338
339
  /* not changed */
340
0
  if (g_strcmp0(priv->branch, branch) == 0)
341
0
    return;
342
343
0
  g_free(priv->branch);
344
0
  priv->branch = g_strdup(branch);
345
0
}
346
347
/**
348
 * fwupd_device_get_serial:
349
 * @self: a #FwupdDevice
350
 *
351
 * Gets the serial number for the device.
352
 *
353
 * Returns: a string value, or %NULL if never set.
354
 *
355
 * Since: 1.1.2
356
 **/
357
const gchar *
358
fwupd_device_get_serial(FwupdDevice *self)
359
0
{
360
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
361
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
362
0
  return priv->serial;
363
0
}
364
365
/**
366
 * fwupd_device_set_serial:
367
 * @self: a #FwupdDevice
368
 * @serial: (nullable): the device serial number
369
 *
370
 * Sets the serial number for the device.
371
 *
372
 * Since: 1.1.2
373
 **/
374
void
375
fwupd_device_set_serial(FwupdDevice *self, const gchar *serial)
376
0
{
377
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
378
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
379
380
  /* not changed */
381
0
  if (g_strcmp0(priv->serial, serial) == 0)
382
0
    return;
383
384
0
  g_free(priv->serial);
385
0
  priv->serial = g_strdup(serial);
386
0
}
387
388
/**
389
 * fwupd_device_get_id:
390
 * @self: a #FwupdDevice
391
 *
392
 * Gets the ID.
393
 *
394
 * Returns: the ID, or %NULL if unset
395
 *
396
 * Since: 0.9.3
397
 **/
398
const gchar *
399
fwupd_device_get_id(FwupdDevice *self)
400
0
{
401
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
402
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
403
0
  return priv->id;
404
0
}
405
406
/**
407
 * fwupd_device_set_id:
408
 * @self: a #FwupdDevice
409
 * @id: (nullable): the device ID, usually a SHA1 hash
410
 *
411
 * Sets the ID.
412
 *
413
 * Since: 0.9.3
414
 **/
415
void
416
fwupd_device_set_id(FwupdDevice *self, const gchar *id)
417
0
{
418
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
419
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
420
421
  /* not changed */
422
0
  if (g_strcmp0(priv->id, id) == 0)
423
0
    return;
424
425
  /* sanity check */
426
0
  if (!fwupd_device_id_is_valid(id)) {
427
0
    g_critical("%s is not a valid device ID", id);
428
0
    return;
429
0
  }
430
431
0
  g_free(priv->id);
432
0
  priv->id = g_strdup(id);
433
0
  g_object_notify(G_OBJECT(self), "id");
434
0
}
435
436
/**
437
 * fwupd_device_get_parent_id:
438
 * @self: a #FwupdDevice
439
 *
440
 * Gets the parent ID.
441
 *
442
 * Returns: the parent ID, or %NULL if unset
443
 *
444
 * Since: 1.0.8
445
 **/
446
const gchar *
447
fwupd_device_get_parent_id(FwupdDevice *self)
448
0
{
449
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
450
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
451
0
  return priv->parent_id;
452
0
}
453
454
/**
455
 * fwupd_device_set_parent_id:
456
 * @self: a #FwupdDevice
457
 * @parent_id: (nullable): the device ID, usually a SHA1 hash
458
 *
459
 * Sets the parent ID.
460
 *
461
 * Since: 1.0.8
462
 **/
463
void
464
fwupd_device_set_parent_id(FwupdDevice *self, const gchar *parent_id)
465
1.15k
{
466
1.15k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
467
1.15k
  g_return_if_fail(FWUPD_IS_DEVICE(self));
468
469
  /* not changed */
470
1.15k
  if (g_strcmp0(priv->parent_id, parent_id) == 0)
471
1.15k
    return;
472
473
  /* sanity check */
474
0
  if (parent_id != NULL && !fwupd_device_id_is_valid(parent_id)) {
475
0
    g_critical("%s is not a valid device ID", parent_id);
476
0
    return;
477
0
  }
478
479
0
  g_free(priv->parent_id);
480
0
  priv->parent_id = g_strdup(parent_id);
481
0
}
482
483
/**
484
 * fwupd_device_get_composite_id:
485
 * @self: a #FwupdDevice
486
 *
487
 * Gets the composite ID, falling back to the device ID if unset.
488
 *
489
 * The composite ID will be the same value for all parent, child and sibling
490
 * devices.
491
 *
492
 * Returns: (nullable): the composite ID
493
 *
494
 * Since: 1.6.0
495
 **/
496
const gchar *
497
fwupd_device_get_composite_id(FwupdDevice *self)
498
0
{
499
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
500
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
501
0
  if (priv->composite_id != NULL)
502
0
    return priv->composite_id;
503
0
  return priv->id;
504
0
}
505
506
/**
507
 * fwupd_device_set_composite_id:
508
 * @self: a #FwupdDevice
509
 * @composite_id: (nullable): a device ID
510
 *
511
 * Sets the composite ID, which is usually a SHA1 hash of a grandparent or
512
 * parent device.
513
 *
514
 * Since: 1.6.0
515
 **/
516
void
517
fwupd_device_set_composite_id(FwupdDevice *self, const gchar *composite_id)
518
0
{
519
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
520
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
521
522
  /* not changed */
523
0
  if (g_strcmp0(priv->composite_id, composite_id) == 0)
524
0
    return;
525
526
  /* sanity check */
527
0
  if (!fwupd_device_id_is_valid(composite_id)) {
528
0
    g_critical("%s is not a valid device ID", composite_id);
529
0
    return;
530
0
  }
531
532
0
  g_free(priv->composite_id);
533
0
  priv->composite_id = g_strdup(composite_id);
534
0
}
535
536
/**
537
 * fwupd_device_get_parent:
538
 * @self: a #FwupdDevice
539
 *
540
 * Gets the parent.
541
 *
542
 * Returns: (transfer none): the parent device, or %NULL if unset
543
 *
544
 * Since: 1.0.8
545
 **/
546
FwupdDevice *
547
fwupd_device_get_parent(FwupdDevice *self)
548
1.15k
{
549
1.15k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
550
1.15k
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
551
1.15k
  return priv->parent;
552
1.15k
}
553
554
/**
555
 * fwupd_device_get_root:
556
 * @self: a #FwupdDevice
557
 *
558
 * Gets the device root.
559
 *
560
 * Returns: (transfer none): the root device, or %NULL if unset
561
 *
562
 * Since: 1.7.4
563
 **/
564
FwupdDevice *
565
fwupd_device_get_root(FwupdDevice *self)
566
0
{
567
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
568
0
  while (1) {
569
0
    FwupdDevicePrivate *priv = GET_PRIVATE(self);
570
0
    if (priv->parent == NULL)
571
0
      break;
572
0
    self = priv->parent;
573
0
  }
574
0
  return self;
575
0
}
576
577
/**
578
 * fwupd_device_set_parent:
579
 * @self: a #FwupdDevice
580
 * @parent: (nullable): another #FwupdDevice
581
 *
582
 * Sets the parent. Only used internally.
583
 *
584
 * Since: 1.0.8
585
 **/
586
void
587
fwupd_device_set_parent(FwupdDevice *self, FwupdDevice *parent)
588
1.15k
{
589
1.15k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
590
1.15k
  g_return_if_fail(FWUPD_IS_DEVICE(self));
591
1.15k
  g_return_if_fail(self != parent);
592
593
1.15k
  if (priv->parent != NULL)
594
0
    g_object_remove_weak_pointer(G_OBJECT(priv->parent), (gpointer *)&priv->parent);
595
1.15k
  if (parent != NULL)
596
0
    g_object_add_weak_pointer(G_OBJECT(parent), (gpointer *)&priv->parent);
597
1.15k
  priv->parent = parent;
598
599
  /* this is what goes over D-Bus */
600
1.15k
  fwupd_device_set_parent_id(self, parent != NULL ? fwupd_device_get_id(parent) : NULL);
601
1.15k
}
602
603
static void
604
fwupd_device_child_finalized_cb(gpointer data, GObject *where_the_object_was)
605
0
{
606
0
  FwupdDevice *self = FWUPD_DEVICE(data);
607
0
  g_critical("FuDevice child %p was finalized while still having parent %s [%s]!",
608
0
       where_the_object_was,
609
0
       fwupd_device_get_name(self),
610
0
       fwupd_device_get_id(self));
611
0
}
612
613
/**
614
 * fwupd_device_add_child:
615
 * @self: a #FwupdDevice
616
 * @child: (not nullable): Another #FwupdDevice
617
 *
618
 * Adds a child device. An child device is logically linked to the primary
619
 * device in some way.
620
 *
621
 * NOTE: You should never call this function from user code, it is for daemon
622
 * use only. Only use fwupd_device_set_parent() to set up a logical tree.
623
 *
624
 * Since: 1.5.1
625
 **/
626
void
627
fwupd_device_add_child(FwupdDevice *self, FwupdDevice *child)
628
0
{
629
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
630
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
631
0
  g_return_if_fail(FWUPD_IS_DEVICE(child));
632
0
  g_return_if_fail(self != child);
633
634
  /* add if the child does not already exist */
635
0
  fwupd_device_ensure_children(self);
636
0
  for (guint i = 0; i < priv->children->len; i++) {
637
0
    FwupdDevice *devtmp = g_ptr_array_index(priv->children, i);
638
0
    if (devtmp == child)
639
0
      return;
640
0
  }
641
0
  g_object_weak_ref(G_OBJECT(child), fwupd_device_child_finalized_cb, self);
642
0
  g_ptr_array_add(priv->children, g_object_ref(child));
643
0
}
644
645
/**
646
 * fwupd_device_remove_child:
647
 * @self: a #FwupdDevice
648
 * @child: Another #FwupdDevice
649
 *
650
 * Removes a child device.
651
 *
652
 * NOTE: You should never call this function from user code, it is for daemon
653
 * use only.
654
 *
655
 * Since: 1.6.2
656
 **/
657
void
658
fwupd_device_remove_child(FwupdDevice *self, FwupdDevice *child)
659
0
{
660
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
661
662
  /* remove if the child exists */
663
0
  if (priv->children == NULL)
664
0
    return;
665
0
  for (guint i = 0; i < priv->children->len; i++) {
666
0
    FwupdDevice *child_tmp = g_ptr_array_index(priv->children, i);
667
0
    if (child_tmp == child) {
668
0
      g_object_weak_unref(G_OBJECT(child), fwupd_device_child_finalized_cb, self);
669
0
      g_ptr_array_remove_index(priv->children, i);
670
0
      return;
671
0
    }
672
0
  }
673
0
}
674
675
/**
676
 * fwupd_device_remove_children:
677
 * @self: a #FwupdDevice
678
 *
679
 * Removes all child devices.
680
 *
681
 * NOTE: You should never call this function from user code, it is for daemon
682
 * use only.
683
 *
684
 * Since: 2.0.0
685
 **/
686
void
687
fwupd_device_remove_children(FwupdDevice *self)
688
0
{
689
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
690
691
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
692
693
0
  if (priv->children == NULL)
694
0
    return;
695
0
  for (guint i = 0; i < priv->children->len; i++) {
696
0
    FwupdDevice *child = g_ptr_array_index(priv->children, i);
697
0
    g_object_weak_unref(G_OBJECT(child), fwupd_device_child_finalized_cb, self);
698
0
  }
699
0
  g_ptr_array_set_size(priv->children, 0);
700
0
}
701
702
static void
703
fwupd_device_ensure_guids(FwupdDevice *self)
704
0
{
705
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
706
0
  if (priv->guids == NULL)
707
0
    priv->guids = g_ptr_array_new_with_free_func(g_free);
708
0
}
709
710
/**
711
 * fwupd_device_get_guids:
712
 * @self: a #FwupdDevice
713
 *
714
 * Gets the GUIDs.
715
 *
716
 * Returns: (element-type utf8) (transfer none): the GUIDs
717
 *
718
 * Since: 0.9.3
719
 **/
720
GPtrArray *
721
fwupd_device_get_guids(FwupdDevice *self)
722
0
{
723
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
724
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
725
0
  fwupd_device_ensure_guids(self);
726
0
  return priv->guids;
727
0
}
728
729
/**
730
 * fwupd_device_has_guid:
731
 * @self: a #FwupdDevice
732
 * @guid: (not nullable): the GUID, e.g. `2082b5e0-7a64-478a-b1b2-e3404fab6dad`
733
 *
734
 * Finds out if the device has this specific GUID.
735
 *
736
 * Returns: %TRUE if the GUID is found
737
 *
738
 * Since: 0.9.3
739
 **/
740
gboolean
741
fwupd_device_has_guid(FwupdDevice *self, const gchar *guid)
742
0
{
743
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
744
745
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
746
0
  g_return_val_if_fail(guid != NULL, FALSE);
747
748
0
  if (priv->guids == NULL)
749
0
    return FALSE;
750
0
  for (guint i = 0; i < priv->guids->len; i++) {
751
0
    const gchar *guid_tmp = g_ptr_array_index(priv->guids, i);
752
0
    if (g_strcmp0(guid, guid_tmp) == 0)
753
0
      return TRUE;
754
0
  }
755
0
  return FALSE;
756
0
}
757
758
/**
759
 * fwupd_device_add_guid:
760
 * @self: a #FwupdDevice
761
 * @guid: the GUID, e.g. `2082b5e0-7a64-478a-b1b2-e3404fab6dad`
762
 *
763
 * Adds the GUID if it does not already exist.
764
 *
765
 * Since: 0.9.3
766
 **/
767
void
768
fwupd_device_add_guid(FwupdDevice *self, const gchar *guid)
769
0
{
770
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
771
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
772
0
  g_return_if_fail(guid != NULL);
773
0
  if (fwupd_device_has_guid(self, guid))
774
0
    return;
775
0
  fwupd_device_ensure_guids(self);
776
0
  g_ptr_array_add(priv->guids, g_strdup(guid));
777
0
}
778
779
/**
780
 * fwupd_device_get_guid_default:
781
 * @self: a #FwupdDevice
782
 *
783
 * Gets the default GUID.
784
 *
785
 * Returns: the GUID, or %NULL if unset
786
 *
787
 * Since: 0.9.3
788
 **/
789
const gchar *
790
fwupd_device_get_guid_default(FwupdDevice *self)
791
0
{
792
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
793
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
794
0
  if (priv->guids == NULL || priv->guids->len == 0)
795
0
    return NULL;
796
0
  return g_ptr_array_index(priv->guids, 0);
797
0
}
798
799
static void
800
fwupd_device_ensure_instance_ids(FwupdDevice *self)
801
0
{
802
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
803
0
  if (priv->instance_ids == NULL)
804
0
    priv->instance_ids = g_ptr_array_new_with_free_func(g_free);
805
0
}
806
807
/**
808
 * fwupd_device_get_instance_ids:
809
 * @self: a #FwupdDevice
810
 *
811
 * Gets the instance IDs.
812
 *
813
 * Returns: (element-type utf8) (transfer none): the instance IDs
814
 *
815
 * Since: 1.2.5
816
 **/
817
GPtrArray *
818
fwupd_device_get_instance_ids(FwupdDevice *self)
819
0
{
820
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
821
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
822
0
  fwupd_device_ensure_instance_ids(self);
823
0
  return priv->instance_ids;
824
0
}
825
826
/**
827
 * fwupd_device_has_instance_id:
828
 * @self: a #FwupdDevice
829
 * @instance_id: (not nullable): the instance ID, e.g. `PCI\VEN_10EC&DEV_525A`
830
 *
831
 * Finds out if the device has this specific instance ID.
832
 *
833
 * Returns: %TRUE if the instance ID is found
834
 *
835
 * Since: 1.2.5
836
 **/
837
gboolean
838
fwupd_device_has_instance_id(FwupdDevice *self, const gchar *instance_id)
839
0
{
840
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
841
842
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
843
0
  g_return_val_if_fail(instance_id != NULL, FALSE);
844
845
0
  if (priv->instance_ids == NULL)
846
0
    return FALSE;
847
0
  for (guint i = 0; i < priv->instance_ids->len; i++) {
848
0
    const gchar *instance_id_tmp = g_ptr_array_index(priv->instance_ids, i);
849
0
    if (g_strcmp0(instance_id, instance_id_tmp) == 0)
850
0
      return TRUE;
851
0
  }
852
0
  return FALSE;
853
0
}
854
855
/**
856
 * fwupd_device_add_instance_id:
857
 * @self: a #FwupdDevice
858
 * @instance_id: (not nullable): the instance ID, e.g. `PCI\VEN_10EC&DEV_525A`
859
 *
860
 * Adds the instance ID if it does not already exist.
861
 *
862
 * Since: 1.2.5
863
 **/
864
void
865
fwupd_device_add_instance_id(FwupdDevice *self, const gchar *instance_id)
866
0
{
867
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
868
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
869
0
  g_return_if_fail(instance_id != NULL);
870
0
  if (fwupd_device_has_instance_id(self, instance_id))
871
0
    return;
872
0
  fwupd_device_ensure_instance_ids(self);
873
0
  g_ptr_array_add(priv->instance_ids, g_strdup(instance_id));
874
0
}
875
876
static void
877
fwupd_device_ensure_icons(FwupdDevice *self)
878
0
{
879
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
880
0
  if (priv->icons == NULL)
881
0
    priv->icons = g_ptr_array_new_with_free_func(g_free);
882
0
}
883
884
/**
885
 * fwupd_device_get_icons:
886
 * @self: a #FwupdDevice
887
 *
888
 * Gets the icon names to use for the device.
889
 *
890
 * NOTE: Icons specified without a full path are stock icons and should
891
 * be loaded from the users icon theme.
892
 *
893
 * Returns: (element-type utf8) (transfer none): an array of icon names
894
 *
895
 * Since: 0.9.8
896
 **/
897
GPtrArray *
898
fwupd_device_get_icons(FwupdDevice *self)
899
0
{
900
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
901
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
902
0
  fwupd_device_ensure_icons(self);
903
0
  return priv->icons;
904
0
}
905
906
/**
907
 * fwupd_device_has_icon:
908
 * @self: a #FwupdDevice
909
 * @icon: the icon name, e.g. `input-mouse` or `/usr/share/icons/foo.png`
910
 *
911
 * Finds out if the device has this specific icon.
912
 *
913
 * Returns: %TRUE if the icon name is found
914
 *
915
 * Since: 1.6.2
916
 **/
917
gboolean
918
fwupd_device_has_icon(FwupdDevice *self, const gchar *icon)
919
0
{
920
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
921
0
  if (priv->icons == NULL)
922
0
    return FALSE;
923
0
  for (guint i = 0; i < priv->icons->len; i++) {
924
0
    const gchar *icon_tmp = g_ptr_array_index(priv->icons, i);
925
0
    if (g_strcmp0(icon, icon_tmp) == 0)
926
0
      return TRUE;
927
0
  }
928
0
  return FALSE;
929
0
}
930
931
/**
932
 * fwupd_device_add_icon:
933
 * @self: a #FwupdDevice
934
 * @icon: (not nullable): the icon name, e.g. `input-mouse` or `/usr/share/icons/foo.png`
935
 *
936
 * Adds the icon name if it does not already exist.
937
 *
938
 * Since: 0.9.8
939
 **/
940
void
941
fwupd_device_add_icon(FwupdDevice *self, const gchar *icon)
942
0
{
943
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
944
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
945
0
  g_return_if_fail(icon != NULL);
946
0
  if (fwupd_device_has_icon(self, icon))
947
0
    return;
948
0
  fwupd_device_ensure_icons(self);
949
0
  g_ptr_array_add(priv->icons, g_strdup(icon));
950
0
}
951
952
/**
953
 * fwupd_device_get_name:
954
 * @self: a #FwupdDevice
955
 *
956
 * Gets the device name.
957
 *
958
 * Returns: the device name, or %NULL if unset
959
 *
960
 * Since: 0.9.3
961
 **/
962
const gchar *
963
fwupd_device_get_name(FwupdDevice *self)
964
0
{
965
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
966
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
967
0
  return priv->name;
968
0
}
969
970
/**
971
 * fwupd_device_set_name:
972
 * @self: a #FwupdDevice
973
 * @name: (nullable): the device name, e.g. `ColorHug2`
974
 *
975
 * Sets the device name.
976
 *
977
 * Since: 0.9.3
978
 **/
979
void
980
fwupd_device_set_name(FwupdDevice *self, const gchar *name)
981
1.15k
{
982
1.15k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
983
1.15k
  g_return_if_fail(FWUPD_IS_DEVICE(self));
984
985
  /* not changed */
986
1.15k
  if (g_strcmp0(priv->name, name) == 0)
987
1.15k
    return;
988
989
0
  g_free(priv->name);
990
0
  priv->name = g_strdup(name);
991
0
}
992
993
/**
994
 * fwupd_device_get_vendor:
995
 * @self: a #FwupdDevice
996
 *
997
 * Gets the device vendor.
998
 *
999
 * Returns: the device vendor, or %NULL if unset
1000
 *
1001
 * Since: 0.9.3
1002
 **/
1003
const gchar *
1004
fwupd_device_get_vendor(FwupdDevice *self)
1005
0
{
1006
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1007
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1008
0
  return priv->vendor;
1009
0
}
1010
1011
/**
1012
 * fwupd_device_set_vendor:
1013
 * @self: a #FwupdDevice
1014
 * @vendor: (nullable): the vendor
1015
 *
1016
 * Sets the device vendor.
1017
 *
1018
 * Since: 0.9.3
1019
 **/
1020
void
1021
fwupd_device_set_vendor(FwupdDevice *self, const gchar *vendor)
1022
0
{
1023
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1024
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1025
1026
  /* not changed */
1027
0
  if (g_strcmp0(priv->vendor, vendor) == 0)
1028
0
    return;
1029
1030
0
  g_free(priv->vendor);
1031
0
  priv->vendor = g_strdup(vendor);
1032
0
  g_object_notify(G_OBJECT(self), "vendor");
1033
0
}
1034
1035
static void
1036
fwupd_device_ensure_vendor_ids(FwupdDevice *self)
1037
0
{
1038
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1039
0
  if (priv->vendor_ids == NULL)
1040
0
    priv->vendor_ids = g_ptr_array_new_with_free_func(g_free);
1041
0
}
1042
1043
/**
1044
 * fwupd_device_get_vendor_ids:
1045
 * @self: a #FwupdDevice
1046
 *
1047
 * Gets the device vendor ID.
1048
 *
1049
 * Returns: (element-type utf8) (transfer none): the device vendor ID
1050
 *
1051
 * Since: 1.5.5
1052
 **/
1053
GPtrArray *
1054
fwupd_device_get_vendor_ids(FwupdDevice *self)
1055
0
{
1056
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1057
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1058
0
  fwupd_device_ensure_vendor_ids(self);
1059
0
  return priv->vendor_ids;
1060
0
}
1061
1062
/**
1063
 * fwupd_device_has_vendor_id:
1064
 * @self: a #FwupdDevice
1065
 * @vendor_id: (not nullable): the vendor ID, e.g. 'USB:0x1234'
1066
 *
1067
 * Finds out if the device has this specific vendor ID.
1068
 *
1069
 * Returns: %TRUE if the vendor ID is found
1070
 *
1071
 * Since: 1.5.5
1072
 **/
1073
gboolean
1074
fwupd_device_has_vendor_id(FwupdDevice *self, const gchar *vendor_id)
1075
0
{
1076
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1077
1078
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
1079
0
  g_return_val_if_fail(vendor_id != NULL, FALSE);
1080
1081
0
  if (priv->vendor_ids == NULL)
1082
0
    return FALSE;
1083
0
  for (guint i = 0; i < priv->vendor_ids->len; i++) {
1084
0
    const gchar *vendor_id_tmp = g_ptr_array_index(priv->vendor_ids, i);
1085
0
    if (g_strcmp0(vendor_id, vendor_id_tmp) == 0)
1086
0
      return TRUE;
1087
0
  }
1088
0
  return FALSE;
1089
0
}
1090
1091
/**
1092
 * fwupd_device_add_vendor_id:
1093
 * @self: a #FwupdDevice
1094
 * @vendor_id: (not nullable): the ID, e.g. 'USB:0x1234'
1095
 *
1096
 * Adds a device vendor ID.
1097
 *
1098
 * Since: 1.5.5
1099
 **/
1100
void
1101
fwupd_device_add_vendor_id(FwupdDevice *self, const gchar *vendor_id)
1102
0
{
1103
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1104
1105
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1106
0
  g_return_if_fail(vendor_id != NULL);
1107
1108
0
  if (fwupd_device_has_vendor_id(self, vendor_id))
1109
0
    return;
1110
0
  fwupd_device_ensure_vendor_ids(self);
1111
0
  g_ptr_array_add(priv->vendor_ids, g_strdup(vendor_id));
1112
0
}
1113
1114
/**
1115
 * fwupd_device_get_version:
1116
 * @self: a #FwupdDevice
1117
 *
1118
 * Gets the device version.
1119
 *
1120
 * Returns: the device version, or %NULL if unset
1121
 *
1122
 * Since: 0.9.3
1123
 **/
1124
const gchar *
1125
fwupd_device_get_version(FwupdDevice *self)
1126
0
{
1127
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1128
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1129
0
  return priv->version;
1130
0
}
1131
1132
/**
1133
 * fwupd_device_set_version:
1134
 * @self: a #FwupdDevice
1135
 * @version: (nullable): the device version, e.g. `1.2.3`
1136
 *
1137
 * Sets the device version.
1138
 *
1139
 * Since: 0.9.3
1140
 **/
1141
void
1142
fwupd_device_set_version(FwupdDevice *self, const gchar *version)
1143
0
{
1144
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1145
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1146
1147
  /* not changed */
1148
0
  if (g_strcmp0(priv->version, version) == 0)
1149
0
    return;
1150
1151
0
  g_free(priv->version);
1152
0
  priv->version = g_strdup(version);
1153
0
  g_object_notify(G_OBJECT(self), "version");
1154
0
}
1155
1156
/**
1157
 * fwupd_device_get_version_lowest:
1158
 * @self: a #FwupdDevice
1159
 *
1160
 * Gets the lowest version of firmware the device will accept.
1161
 *
1162
 * Returns: the device version_lowest, or %NULL if unset
1163
 *
1164
 * Since: 0.9.3
1165
 **/
1166
const gchar *
1167
fwupd_device_get_version_lowest(FwupdDevice *self)
1168
0
{
1169
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1170
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1171
0
  return priv->version_lowest;
1172
0
}
1173
1174
/**
1175
 * fwupd_device_set_version_lowest:
1176
 * @self: a #FwupdDevice
1177
 * @version_lowest: (nullable): the version
1178
 *
1179
 * Sets the lowest version of firmware the device will accept.
1180
 *
1181
 * Since: 0.9.3
1182
 **/
1183
void
1184
fwupd_device_set_version_lowest(FwupdDevice *self, const gchar *version_lowest)
1185
0
{
1186
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1187
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1188
1189
  /* not changed */
1190
0
  if (g_strcmp0(priv->version_lowest, version_lowest) == 0)
1191
0
    return;
1192
1193
0
  g_free(priv->version_lowest);
1194
0
  priv->version_lowest = g_strdup(version_lowest);
1195
0
}
1196
1197
/**
1198
 * fwupd_device_get_version_lowest_raw:
1199
 * @self: a #FwupdDevice
1200
 *
1201
 * Gets the lowest version of firmware the device will accept in raw format.
1202
 *
1203
 * Returns: integer version number, or %0 if unset
1204
 *
1205
 * Since: 1.4.0
1206
 **/
1207
guint64
1208
fwupd_device_get_version_lowest_raw(FwupdDevice *self)
1209
0
{
1210
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1211
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1212
0
  return priv->version_lowest_raw;
1213
0
}
1214
1215
/**
1216
 * fwupd_device_set_version_lowest_raw:
1217
 * @self: a #FwupdDevice
1218
 * @version_lowest_raw: the raw hardware version
1219
 *
1220
 * Sets the raw lowest version number from the hardware before converted to a string.
1221
 *
1222
 * Since: 1.4.0
1223
 **/
1224
void
1225
fwupd_device_set_version_lowest_raw(FwupdDevice *self, guint64 version_lowest_raw)
1226
0
{
1227
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1228
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1229
0
  priv->version_lowest_raw = version_lowest_raw;
1230
0
}
1231
1232
/**
1233
 * fwupd_device_get_version_bootloader:
1234
 * @self: a #FwupdDevice
1235
 *
1236
 * Gets the version of the bootloader.
1237
 *
1238
 * Returns: the device version_bootloader, or %NULL if unset
1239
 *
1240
 * Since: 0.9.3
1241
 **/
1242
const gchar *
1243
fwupd_device_get_version_bootloader(FwupdDevice *self)
1244
0
{
1245
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1246
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1247
0
  return priv->version_bootloader;
1248
0
}
1249
1250
/**
1251
 * fwupd_device_set_version_bootloader:
1252
 * @self: a #FwupdDevice
1253
 * @version_bootloader: (nullable): the version
1254
 *
1255
 * Sets the bootloader version.
1256
 *
1257
 * Since: 0.9.3
1258
 **/
1259
void
1260
fwupd_device_set_version_bootloader(FwupdDevice *self, const gchar *version_bootloader)
1261
0
{
1262
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1263
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1264
1265
  /* not changed */
1266
0
  if (g_strcmp0(priv->version_bootloader, version_bootloader) == 0)
1267
0
    return;
1268
1269
0
  g_free(priv->version_bootloader);
1270
0
  priv->version_bootloader = g_strdup(version_bootloader);
1271
0
}
1272
1273
/**
1274
 * fwupd_device_get_version_bootloader_raw:
1275
 * @self: a #FwupdDevice
1276
 *
1277
 * Gets the bootloader version of firmware the device will accept in raw format.
1278
 *
1279
 * Returns: integer version number, or %0 if unset
1280
 *
1281
 * Since: 1.4.0
1282
 **/
1283
guint64
1284
fwupd_device_get_version_bootloader_raw(FwupdDevice *self)
1285
0
{
1286
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1287
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1288
0
  return priv->version_bootloader_raw;
1289
0
}
1290
1291
/**
1292
 * fwupd_device_set_version_bootloader_raw:
1293
 * @self: a #FwupdDevice
1294
 * @version_bootloader_raw: the raw hardware version
1295
 *
1296
 * Sets the raw bootloader version number from the hardware before converted to a string.
1297
 *
1298
 * Since: 1.4.0
1299
 **/
1300
void
1301
fwupd_device_set_version_bootloader_raw(FwupdDevice *self, guint64 version_bootloader_raw)
1302
0
{
1303
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1304
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1305
0
  priv->version_bootloader_raw = version_bootloader_raw;
1306
0
}
1307
1308
/**
1309
 * fwupd_device_get_flashes_left:
1310
 * @self: a #FwupdDevice
1311
 *
1312
 * Gets the number of flash cycles left on the device
1313
 *
1314
 * Returns: the flash cycles left, or %NULL if unset
1315
 *
1316
 * Since: 0.9.3
1317
 **/
1318
guint32
1319
fwupd_device_get_flashes_left(FwupdDevice *self)
1320
0
{
1321
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1322
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1323
0
  return priv->flashes_left;
1324
0
}
1325
1326
/**
1327
 * fwupd_device_set_flashes_left:
1328
 * @self: a #FwupdDevice
1329
 * @flashes_left: the description
1330
 *
1331
 * Sets the number of flash cycles left on the device
1332
 *
1333
 * Since: 0.9.3
1334
 **/
1335
void
1336
fwupd_device_set_flashes_left(FwupdDevice *self, guint32 flashes_left)
1337
0
{
1338
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1339
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1340
0
  priv->flashes_left = flashes_left;
1341
0
}
1342
1343
/**
1344
 * fwupd_device_get_battery_level:
1345
 * @self: a #FwupdDevice
1346
 *
1347
 * Returns the battery level.
1348
 *
1349
 * Returns: value in percent
1350
 *
1351
 * Since: 1.8.1
1352
 **/
1353
guint32
1354
fwupd_device_get_battery_level(FwupdDevice *self)
1355
0
{
1356
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1357
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), G_MAXUINT32);
1358
0
  return priv->battery_level;
1359
0
}
1360
1361
/**
1362
 * fwupd_device_set_battery_level:
1363
 * @self: a #FwupdDevice
1364
 * @battery_level: the percentage value
1365
 *
1366
 * Sets the battery level, or %FWUPD_BATTERY_LEVEL_INVALID.
1367
 *
1368
 * Setting this allows fwupd to show a warning if the device change is too low
1369
 * to perform the update.
1370
 *
1371
 * Since: 1.8.1
1372
 **/
1373
void
1374
fwupd_device_set_battery_level(FwupdDevice *self, guint32 battery_level)
1375
0
{
1376
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1377
1378
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1379
0
  g_return_if_fail(battery_level <= FWUPD_BATTERY_LEVEL_INVALID);
1380
1381
0
  if (priv->battery_level == battery_level)
1382
0
    return;
1383
0
  priv->battery_level = battery_level;
1384
0
  g_object_notify(G_OBJECT(self), "battery-level");
1385
0
}
1386
1387
/**
1388
 * fwupd_device_get_battery_threshold:
1389
 * @self: a #FwupdDevice
1390
 *
1391
 * Returns the battery threshold under which a firmware update cannot be
1392
 * performed.
1393
 *
1394
 * If fwupd_device_set_battery_threshold() has not been used, a default value is
1395
 * used instead.
1396
 *
1397
 * Returns: value in percent
1398
 *
1399
 * Since: 1.8.1
1400
 **/
1401
guint32
1402
fwupd_device_get_battery_threshold(FwupdDevice *self)
1403
0
{
1404
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1405
1406
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), G_MAXUINT32);
1407
1408
  /* default value */
1409
0
  if (priv->battery_threshold == FWUPD_BATTERY_LEVEL_INVALID)
1410
0
    return FWUPD_BATTERY_THRESHOLD_DEFAULT;
1411
1412
0
  return priv->battery_threshold;
1413
0
}
1414
1415
/**
1416
 * fwupd_device_set_battery_threshold:
1417
 * @self: a #FwupdDevice
1418
 * @battery_threshold: the percentage value
1419
 *
1420
 * Sets the battery level, or %FWUPD_BATTERY_LEVEL_INVALID for the default.
1421
 *
1422
 * Setting this allows fwupd to show a warning if the device change is too low
1423
 * to perform the update.
1424
 *
1425
 * Since: 1.8.1
1426
 **/
1427
void
1428
fwupd_device_set_battery_threshold(FwupdDevice *self, guint32 battery_threshold)
1429
0
{
1430
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1431
1432
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1433
0
  g_return_if_fail(battery_threshold <= FWUPD_BATTERY_LEVEL_INVALID);
1434
1435
0
  if (priv->battery_threshold == battery_threshold)
1436
0
    return;
1437
0
  priv->battery_threshold = battery_threshold;
1438
0
  g_object_notify(G_OBJECT(self), "battery-threshold");
1439
0
}
1440
1441
/**
1442
 * fwupd_device_get_install_duration:
1443
 * @self: a #FwupdDevice
1444
 *
1445
 * Gets the time estimate for firmware installation (in seconds)
1446
 *
1447
 * Returns: the estimated time to flash this device (or 0 if unset)
1448
 *
1449
 * Since: 1.1.3
1450
 **/
1451
guint32
1452
fwupd_device_get_install_duration(FwupdDevice *self)
1453
0
{
1454
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1455
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1456
0
  return priv->install_duration;
1457
0
}
1458
1459
/**
1460
 * fwupd_device_set_install_duration:
1461
 * @self: a #FwupdDevice
1462
 * @duration: the amount of time
1463
 *
1464
 * Sets the time estimate for firmware installation (in seconds)
1465
 *
1466
 * Since: 1.1.3
1467
 **/
1468
void
1469
fwupd_device_set_install_duration(FwupdDevice *self, guint32 duration)
1470
0
{
1471
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1472
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1473
0
  priv->install_duration = duration;
1474
0
}
1475
1476
/**
1477
 * fwupd_device_get_plugin:
1478
 * @self: a #FwupdDevice
1479
 *
1480
 * Gets the plugin that created the device.
1481
 *
1482
 * Returns: the plugin name, or %NULL if unset
1483
 *
1484
 * Since: 1.0.0
1485
 **/
1486
const gchar *
1487
fwupd_device_get_plugin(FwupdDevice *self)
1488
0
{
1489
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1490
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1491
0
  return priv->plugin;
1492
0
}
1493
1494
/**
1495
 * fwupd_device_set_plugin:
1496
 * @self: a #FwupdDevice
1497
 * @plugin: (nullable): the plugin name, e.g. `hughski_colorhug`
1498
 *
1499
 * Sets the plugin that created the device.
1500
 *
1501
 * Since: 1.0.0
1502
 **/
1503
void
1504
fwupd_device_set_plugin(FwupdDevice *self, const gchar *plugin)
1505
0
{
1506
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1507
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1508
1509
  /* not changed */
1510
0
  if (g_strcmp0(priv->plugin, plugin) == 0)
1511
0
    return;
1512
1513
0
  g_free(priv->plugin);
1514
0
  priv->plugin = g_strdup(plugin);
1515
0
}
1516
1517
static void
1518
fwupd_device_ensure_protocols(FwupdDevice *self)
1519
271
{
1520
271
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1521
271
  if (priv->protocols == NULL)
1522
271
    priv->protocols = g_ptr_array_new_with_free_func(g_free);
1523
271
}
1524
1525
/**
1526
 * fwupd_device_get_protocols:
1527
 * @self: a #FwupdDevice
1528
 *
1529
 * Gets the device protocol names.
1530
 *
1531
 * Returns: (element-type utf8) (transfer none): the device protocol names
1532
 *
1533
 * Since: 1.5.8
1534
 **/
1535
GPtrArray *
1536
fwupd_device_get_protocols(FwupdDevice *self)
1537
0
{
1538
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1539
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
1540
0
  fwupd_device_ensure_protocols(self);
1541
0
  return priv->protocols;
1542
0
}
1543
1544
/**
1545
 * fwupd_device_has_protocol:
1546
 * @self: a #FwupdDevice
1547
 * @protocol: (not nullable): the protocol name, e.g. `com.hughski.colorhug`
1548
 *
1549
 * Finds out if the device has this specific protocol name.
1550
 *
1551
 * Returns: %TRUE if the protocol name is found
1552
 *
1553
 * Since: 1.5.8
1554
 **/
1555
gboolean
1556
fwupd_device_has_protocol(FwupdDevice *self, const gchar *protocol)
1557
271
{
1558
271
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1559
1560
271
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
1561
271
  g_return_val_if_fail(protocol != NULL, FALSE);
1562
1563
271
  if (priv->protocols == NULL)
1564
271
    return FALSE;
1565
0
  for (guint i = 0; i < priv->protocols->len; i++) {
1566
0
    const gchar *protocol_tmp = g_ptr_array_index(priv->protocols, i);
1567
0
    if (g_strcmp0(protocol, protocol_tmp) == 0)
1568
0
      return TRUE;
1569
0
  }
1570
0
  return FALSE;
1571
0
}
1572
1573
/**
1574
 * fwupd_device_add_protocol:
1575
 * @self: a #FwupdDevice
1576
 * @protocol: (not nullable): the protocol name, e.g. `com.hughski.colorhug`
1577
 *
1578
 * Adds a device protocol name.
1579
 *
1580
 * Since: 1.5.8
1581
 **/
1582
void
1583
fwupd_device_add_protocol(FwupdDevice *self, const gchar *protocol)
1584
271
{
1585
271
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1586
1587
271
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1588
271
  g_return_if_fail(protocol != NULL);
1589
1590
271
  if (fwupd_device_has_protocol(self, protocol))
1591
0
    return;
1592
271
  fwupd_device_ensure_protocols(self);
1593
271
  g_ptr_array_add(priv->protocols, g_strdup(protocol));
1594
271
}
1595
1596
/**
1597
 * fwupd_device_get_flags:
1598
 * @self: a #FwupdDevice
1599
 *
1600
 * Gets device flags.
1601
 *
1602
 * Returns: device flags, or 0 if unset
1603
 *
1604
 * Since: 0.9.3
1605
 **/
1606
guint64
1607
fwupd_device_get_flags(FwupdDevice *self)
1608
0
{
1609
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1610
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1611
0
  return priv->flags;
1612
0
}
1613
1614
/**
1615
 * fwupd_device_set_flags:
1616
 * @self: a #FwupdDevice
1617
 * @flags: device flags, e.g. %FWUPD_DEVICE_FLAG_REQUIRE_AC
1618
 *
1619
 * Sets device flags.
1620
 *
1621
 * Since: 0.9.3
1622
 **/
1623
void
1624
fwupd_device_set_flags(FwupdDevice *self, guint64 flags)
1625
0
{
1626
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1627
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1628
0
  if (priv->flags == flags)
1629
0
    return;
1630
0
  priv->flags = flags;
1631
0
  g_object_notify(G_OBJECT(self), "flags");
1632
0
}
1633
1634
/**
1635
 * fwupd_device_add_flag:
1636
 * @self: a #FwupdDevice
1637
 * @flag: the #FwupdDeviceFlags
1638
 *
1639
 * Adds a specific device flag to the device.
1640
 *
1641
 * Since: 0.9.3
1642
 **/
1643
void
1644
fwupd_device_add_flag(FwupdDevice *self, FwupdDeviceFlags flag)
1645
1.69k
{
1646
1.69k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1647
1.69k
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1648
1.69k
  if (flag == 0)
1649
0
    return;
1650
1.69k
  if ((priv->flags | flag) == priv->flags)
1651
0
    return;
1652
1.69k
  priv->flags |= flag;
1653
1.69k
  g_object_notify(G_OBJECT(self), "flags");
1654
1.69k
}
1655
1656
/**
1657
 * fwupd_device_remove_flag:
1658
 * @self: a #FwupdDevice
1659
 * @flag: the #FwupdDeviceFlags
1660
 *
1661
 * Removes a specific device flag from the device.
1662
 *
1663
 * Since: 0.9.3
1664
 **/
1665
void
1666
fwupd_device_remove_flag(FwupdDevice *self, FwupdDeviceFlags flag)
1667
542
{
1668
542
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1669
542
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1670
542
  if (flag == 0)
1671
0
    return;
1672
542
  if ((priv->flags & flag) == 0)
1673
271
    return;
1674
271
  priv->flags &= ~flag;
1675
271
  g_object_notify(G_OBJECT(self), "flags");
1676
271
}
1677
1678
/**
1679
 * fwupd_device_has_flag:
1680
 * @self: a #FwupdDevice
1681
 * @flag: the #FwupdDeviceFlags
1682
 *
1683
 * Finds if the device has a specific device flag.
1684
 *
1685
 * Returns: %TRUE if the flag is set
1686
 *
1687
 * Since: 0.9.3
1688
 **/
1689
gboolean
1690
fwupd_device_has_flag(FwupdDevice *self, FwupdDeviceFlags flag)
1691
2.24k
{
1692
2.24k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1693
2.24k
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
1694
2.24k
  return (priv->flags & flag) > 0;
1695
2.24k
}
1696
1697
/**
1698
 * fwupd_device_get_problems:
1699
 * @self: a #FwupdDevice
1700
 *
1701
 * Gets device problems.
1702
 *
1703
 * Returns: device problems, or 0 if unset
1704
 *
1705
 * Since: 1.8.1
1706
 **/
1707
guint64
1708
fwupd_device_get_problems(FwupdDevice *self)
1709
0
{
1710
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1711
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1712
0
  return priv->problems;
1713
0
}
1714
1715
/**
1716
 * fwupd_device_set_problems:
1717
 * @self: a #FwupdDevice
1718
 * @problems: device problems, e.g. %FWUPD_DEVICE_PROBLEM_SYSTEM_POWER_TOO_LOW
1719
 *
1720
 * Sets device problems.
1721
 *
1722
 * Since: 1.8.1
1723
 **/
1724
void
1725
fwupd_device_set_problems(FwupdDevice *self, guint64 problems)
1726
0
{
1727
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1728
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1729
0
  if (priv->problems == problems)
1730
0
    return;
1731
0
  priv->problems = problems;
1732
0
  g_object_notify(G_OBJECT(self), "problems");
1733
0
}
1734
1735
/**
1736
 * fwupd_device_add_problem:
1737
 * @self: a #FwupdDevice
1738
 * @problem: the #FwupdDeviceProblem, e.g. #FWUPD_DEVICE_PROBLEM_SYSTEM_POWER_TOO_LOW
1739
 *
1740
 * Adds a specific device problem kind to the device.
1741
 *
1742
 * Since: 1.8.1
1743
 **/
1744
void
1745
fwupd_device_add_problem(FwupdDevice *self, FwupdDeviceProblem problem)
1746
0
{
1747
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1748
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1749
0
  if (problem == FWUPD_DEVICE_PROBLEM_NONE)
1750
0
    return;
1751
0
  if (fwupd_device_has_problem(self, problem))
1752
0
    return;
1753
0
  priv->problems |= problem;
1754
0
  g_object_notify(G_OBJECT(self), "problems");
1755
0
}
1756
1757
/**
1758
 * fwupd_device_remove_problem:
1759
 * @self: a #FwupdDevice
1760
 * @problem: the #FwupdDeviceProblem, e.g. #FWUPD_DEVICE_PROBLEM_SYSTEM_POWER_TOO_LOW
1761
 *
1762
 * Removes a specific device problem kind from the device.
1763
 *
1764
 * Since: 1.8.1
1765
 **/
1766
void
1767
fwupd_device_remove_problem(FwupdDevice *self, FwupdDeviceProblem problem)
1768
0
{
1769
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1770
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1771
0
  if (problem == FWUPD_DEVICE_PROBLEM_NONE)
1772
0
    return;
1773
0
  if (!fwupd_device_has_problem(self, problem))
1774
0
    return;
1775
0
  priv->problems &= ~problem;
1776
0
  g_object_notify(G_OBJECT(self), "problems");
1777
0
}
1778
1779
/**
1780
 * fwupd_device_has_problem:
1781
 * @self: a #FwupdDevice
1782
 * @problem: the #FwupdDeviceProblem
1783
 *
1784
 * Finds if the device has a specific device problem kind.
1785
 *
1786
 * Returns: %TRUE if the problem is set
1787
 *
1788
 * Since: 1.8.1
1789
 **/
1790
gboolean
1791
fwupd_device_has_problem(FwupdDevice *self, FwupdDeviceProblem problem)
1792
0
{
1793
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1794
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
1795
0
  return (priv->problems & problem) > 0;
1796
0
}
1797
1798
/**
1799
 * fwupd_device_get_request_flags:
1800
 * @self: a #FwupdDevice
1801
 *
1802
 * Gets device request flags.
1803
 *
1804
 * Returns: device request flags, or 0 if unset
1805
 *
1806
 * Since: 1.9.10
1807
 **/
1808
guint64
1809
fwupd_device_get_request_flags(FwupdDevice *self)
1810
0
{
1811
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1812
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1813
0
  return priv->request_flags;
1814
0
}
1815
1816
/**
1817
 * fwupd_device_set_request_flags:
1818
 * @self: a #FwupdDevice
1819
 * @request_flags: device request flags, e.g. %FWUPD_DEVICE_REQUEST_FLAG_REQUIRE_AC
1820
 *
1821
 * Sets device request flags.
1822
 *
1823
 * Since: 1.9.10
1824
 **/
1825
void
1826
fwupd_device_set_request_flags(FwupdDevice *self, guint64 request_flags)
1827
0
{
1828
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1829
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1830
0
  if (priv->request_flags == request_flags)
1831
0
    return;
1832
0
  priv->request_flags = request_flags;
1833
0
  g_object_notify(G_OBJECT(self), "request-flags");
1834
0
}
1835
1836
/**
1837
 * fwupd_device_add_request_flag:
1838
 * @self: a #FwupdDevice
1839
 * @request_flag: the #FwupdRequestFlags
1840
 *
1841
 * Adds a specific device request flag to the device.
1842
 *
1843
 * Since: 1.9.10
1844
 **/
1845
void
1846
fwupd_device_add_request_flag(FwupdDevice *self, FwupdRequestFlags request_flag)
1847
0
{
1848
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1849
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1850
0
  if (request_flag == 0)
1851
0
    return;
1852
0
  if ((priv->request_flags | request_flag) == priv->request_flags)
1853
0
    return;
1854
0
  priv->request_flags |= request_flag;
1855
0
  g_object_notify(G_OBJECT(self), "request-flags");
1856
0
}
1857
1858
/**
1859
 * fwupd_device_remove_request_flag:
1860
 * @self: a #FwupdDevice
1861
 * @request_flag: the #FwupdRequestFlags
1862
 *
1863
 * Removes a specific device request flag from the device.
1864
 *
1865
 * Since: 1.9.10
1866
 **/
1867
void
1868
fwupd_device_remove_request_flag(FwupdDevice *self, FwupdRequestFlags request_flag)
1869
0
{
1870
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1871
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1872
0
  if (request_flag == 0)
1873
0
    return;
1874
0
  if ((priv->request_flags & request_flag) == 0)
1875
0
    return;
1876
0
  priv->request_flags &= ~request_flag;
1877
0
  g_object_notify(G_OBJECT(self), "request-flags");
1878
0
}
1879
1880
/**
1881
 * fwupd_device_has_request_flag:
1882
 * @self: a #FwupdDevice
1883
 * @request_flag: the #FwupdRequestFlags
1884
 *
1885
 * Finds if the device has a specific device request flag.
1886
 *
1887
 * Returns: %TRUE if the request_flag is set
1888
 *
1889
 * Since: 1.9.10
1890
 **/
1891
gboolean
1892
fwupd_device_has_request_flag(FwupdDevice *self, FwupdRequestFlags request_flag)
1893
0
{
1894
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1895
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
1896
0
  return (priv->request_flags & request_flag) > 0;
1897
0
}
1898
1899
/**
1900
 * fwupd_device_get_created:
1901
 * @self: a #FwupdDevice
1902
 *
1903
 * Gets when the device was created.
1904
 *
1905
 * Returns: the UNIX time, or 0 if unset
1906
 *
1907
 * Since: 0.9.3
1908
 **/
1909
guint64
1910
fwupd_device_get_created(FwupdDevice *self)
1911
0
{
1912
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1913
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1914
0
  return priv->created;
1915
0
}
1916
1917
/**
1918
 * fwupd_device_set_created:
1919
 * @self: a #FwupdDevice
1920
 * @created: the UNIX time
1921
 *
1922
 * Sets when the device was created.
1923
 *
1924
 * Since: 0.9.3
1925
 **/
1926
void
1927
fwupd_device_set_created(FwupdDevice *self, guint64 created)
1928
0
{
1929
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1930
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1931
0
  priv->created = created;
1932
0
}
1933
1934
/**
1935
 * fwupd_device_get_modified:
1936
 * @self: a #FwupdDevice
1937
 *
1938
 * Gets when the device was modified.
1939
 *
1940
 * Returns: the UNIX time, or 0 if unset
1941
 *
1942
 * Since: 0.9.3
1943
 **/
1944
guint64
1945
fwupd_device_get_modified(FwupdDevice *self)
1946
0
{
1947
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1948
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
1949
0
  return priv->modified;
1950
0
}
1951
1952
/**
1953
 * fwupd_device_set_modified:
1954
 * @self: a #FwupdDevice
1955
 * @modified: the UNIX time
1956
 *
1957
 * Sets when the device was modified.
1958
 *
1959
 * Since: 0.9.3
1960
 **/
1961
void
1962
fwupd_device_set_modified(FwupdDevice *self, guint64 modified)
1963
0
{
1964
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1965
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1966
0
  priv->modified = modified;
1967
0
}
1968
1969
/**
1970
 * fwupd_device_incorporate:
1971
 * @self: a #FwupdDevice
1972
 * @donor: Another #FwupdDevice
1973
 *
1974
 * Copy all properties from the donor object if they have not already been set.
1975
 *
1976
 * Since: 1.1.0
1977
 **/
1978
void
1979
fwupd_device_incorporate(FwupdDevice *self, FwupdDevice *donor)
1980
0
{
1981
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
1982
0
  FwupdDevicePrivate *priv_donor = GET_PRIVATE(donor);
1983
1984
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
1985
0
  g_return_if_fail(FWUPD_IS_DEVICE(donor));
1986
1987
0
  fwupd_device_add_flag(self, priv_donor->flags);
1988
0
  fwupd_device_add_request_flag(self, priv_donor->request_flags);
1989
0
  fwupd_device_add_problem(self, priv_donor->problems);
1990
0
  if (priv->created == 0)
1991
0
    fwupd_device_set_created(self, priv_donor->created);
1992
0
  if (priv->modified == 0)
1993
0
    fwupd_device_set_modified(self, priv_donor->modified);
1994
0
  if (priv->version_build_date == 0)
1995
0
    fwupd_device_set_version_build_date(self, priv_donor->version_build_date);
1996
0
  if (priv->flashes_left == 0)
1997
0
    fwupd_device_set_flashes_left(self, priv_donor->flashes_left);
1998
0
  if (priv->battery_level == FWUPD_BATTERY_LEVEL_INVALID)
1999
0
    fwupd_device_set_battery_level(self, priv_donor->battery_level);
2000
0
  if (priv->battery_threshold == FWUPD_BATTERY_LEVEL_INVALID)
2001
0
    fwupd_device_set_battery_threshold(self, priv_donor->battery_threshold);
2002
0
  if (priv->install_duration == 0)
2003
0
    fwupd_device_set_install_duration(self, priv_donor->install_duration);
2004
0
  if (priv->update_state == FWUPD_UPDATE_STATE_UNKNOWN)
2005
0
    fwupd_device_set_update_state(self, priv_donor->update_state);
2006
0
  if (priv->id == NULL)
2007
0
    fwupd_device_set_id(self, priv_donor->id);
2008
0
  if (priv->parent_id == NULL)
2009
0
    fwupd_device_set_parent_id(self, priv_donor->parent_id);
2010
0
  if (priv->composite_id == NULL)
2011
0
    fwupd_device_set_composite_id(self, priv_donor->composite_id);
2012
0
  if (priv->name == NULL)
2013
0
    fwupd_device_set_name(self, priv_donor->name);
2014
0
  if (priv->serial == NULL)
2015
0
    fwupd_device_set_serial(self, priv_donor->serial);
2016
0
  if (priv->summary == NULL)
2017
0
    fwupd_device_set_summary(self, priv_donor->summary);
2018
0
  if (priv->branch == NULL)
2019
0
    fwupd_device_set_branch(self, priv_donor->branch);
2020
0
  if (priv->vendor == NULL)
2021
0
    fwupd_device_set_vendor(self, priv_donor->vendor);
2022
0
  if (priv_donor->vendor_ids != NULL) {
2023
0
    for (guint i = 0; i < priv_donor->vendor_ids->len; i++) {
2024
0
      const gchar *tmp = g_ptr_array_index(priv_donor->vendor_ids, i);
2025
0
      fwupd_device_add_vendor_id(self, tmp);
2026
0
    }
2027
0
  }
2028
0
  if (priv->plugin == NULL)
2029
0
    fwupd_device_set_plugin(self, priv_donor->plugin);
2030
0
  if (priv_donor->protocols != NULL) {
2031
0
    for (guint i = 0; i < priv_donor->protocols->len; i++) {
2032
0
      const gchar *tmp = g_ptr_array_index(priv_donor->protocols, i);
2033
0
      fwupd_device_add_protocol(self, tmp);
2034
0
    }
2035
0
  }
2036
0
  if (priv->update_error == NULL)
2037
0
    fwupd_device_set_update_error(self, priv_donor->update_error);
2038
0
  if (priv->version == NULL)
2039
0
    fwupd_device_set_version(self, priv_donor->version);
2040
0
  if (priv->version_lowest == NULL)
2041
0
    fwupd_device_set_version_lowest(self, priv_donor->version_lowest);
2042
0
  if (priv->version_bootloader == NULL)
2043
0
    fwupd_device_set_version_bootloader(self, priv_donor->version_bootloader);
2044
0
  if (priv->version_format == FWUPD_VERSION_FORMAT_UNKNOWN)
2045
0
    fwupd_device_set_version_format(self, priv_donor->version_format);
2046
0
  if (priv->version_raw == 0)
2047
0
    fwupd_device_set_version_raw(self, priv_donor->version_raw);
2048
0
  if (priv->version_lowest_raw == 0)
2049
0
    fwupd_device_set_version_lowest_raw(self, priv_donor->version_lowest_raw);
2050
0
  if (priv->version_bootloader_raw == 0)
2051
0
    fwupd_device_set_version_bootloader_raw(self, priv_donor->version_bootloader_raw);
2052
0
  if (priv_donor->guids != NULL) {
2053
0
    for (guint i = 0; i < priv_donor->guids->len; i++) {
2054
0
      const gchar *tmp = g_ptr_array_index(priv_donor->guids, i);
2055
0
      fwupd_device_add_guid(self, tmp);
2056
0
    }
2057
0
  }
2058
0
  if (priv_donor->instance_ids != NULL) {
2059
0
    for (guint i = 0; i < priv_donor->instance_ids->len; i++) {
2060
0
      const gchar *tmp = g_ptr_array_index(priv_donor->instance_ids, i);
2061
0
      fwupd_device_add_instance_id(self, tmp);
2062
0
    }
2063
0
  }
2064
0
  if (priv_donor->icons != NULL) {
2065
0
    for (guint i = 0; i < priv_donor->icons->len; i++) {
2066
0
      const gchar *tmp = g_ptr_array_index(priv_donor->icons, i);
2067
0
      fwupd_device_add_icon(self, tmp);
2068
0
    }
2069
0
  }
2070
0
  if (priv_donor->checksums != NULL) {
2071
0
    for (guint i = 0; i < priv_donor->checksums->len; i++) {
2072
0
      const gchar *tmp = g_ptr_array_index(priv_donor->checksums, i);
2073
0
      fwupd_device_add_checksum(self, tmp);
2074
0
    }
2075
0
  }
2076
0
  if (priv_donor->releases != NULL) {
2077
0
    for (guint i = 0; i < priv_donor->releases->len; i++) {
2078
0
      FwupdRelease *tmp = g_ptr_array_index(priv_donor->releases, i);
2079
0
      fwupd_device_add_release(self, tmp);
2080
0
    }
2081
0
  }
2082
0
}
2083
2084
static void
2085
fwupd_device_add_variant(FwupdCodec *codec, GVariantBuilder *builder, FwupdCodecFlags flags)
2086
0
{
2087
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
2088
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2089
2090
0
  if (priv->id != NULL) {
2091
0
    g_variant_builder_add(builder,
2092
0
              "{sv}",
2093
0
              FWUPD_RESULT_KEY_DEVICE_ID,
2094
0
              g_variant_new_string(priv->id));
2095
0
  }
2096
0
  if (priv->parent_id != NULL) {
2097
0
    g_variant_builder_add(builder,
2098
0
              "{sv}",
2099
0
              FWUPD_RESULT_KEY_PARENT_DEVICE_ID,
2100
0
              g_variant_new_string(priv->parent_id));
2101
0
  }
2102
0
  if (priv->composite_id != NULL) {
2103
0
    g_variant_builder_add(builder,
2104
0
              "{sv}",
2105
0
              FWUPD_RESULT_KEY_COMPOSITE_ID,
2106
0
              g_variant_new_string(priv->composite_id));
2107
0
  }
2108
0
  if (priv->guids != NULL && priv->guids->len > 0) {
2109
0
    const gchar *const *tmp = (const gchar *const *)priv->guids->pdata;
2110
0
    g_variant_builder_add(builder,
2111
0
              "{sv}",
2112
0
              FWUPD_RESULT_KEY_GUID,
2113
0
              g_variant_new_strv(tmp, priv->guids->len));
2114
0
  }
2115
0
  if (priv->icons != NULL && priv->icons->len > 0) {
2116
0
    const gchar *const *tmp = (const gchar *const *)priv->icons->pdata;
2117
0
    g_variant_builder_add(builder,
2118
0
              "{sv}",
2119
0
              FWUPD_RESULT_KEY_ICON,
2120
0
              g_variant_new_strv(tmp, priv->icons->len));
2121
0
  }
2122
0
  if (priv->name != NULL) {
2123
0
    g_variant_builder_add(builder,
2124
0
              "{sv}",
2125
0
              FWUPD_RESULT_KEY_NAME,
2126
0
              g_variant_new_string(priv->name));
2127
0
  }
2128
0
  if (priv->vendor != NULL) {
2129
0
    g_variant_builder_add(builder,
2130
0
              "{sv}",
2131
0
              FWUPD_RESULT_KEY_VENDOR,
2132
0
              g_variant_new_string(priv->vendor));
2133
0
  }
2134
0
  if (priv->vendor_ids != NULL && priv->vendor_ids->len > 0) {
2135
0
    g_autoptr(GString) str = g_string_new(NULL);
2136
0
    for (guint i = 0; i < priv->vendor_ids->len; i++) {
2137
0
      const gchar *tmp = g_ptr_array_index(priv->vendor_ids, i);
2138
0
      g_string_append_printf(str, "%s|", tmp);
2139
0
    }
2140
0
    if (str->len > 0)
2141
0
      g_string_truncate(str, str->len - 1);
2142
0
    g_variant_builder_add(builder,
2143
0
              "{sv}",
2144
0
              FWUPD_RESULT_KEY_VENDOR_ID,
2145
0
              g_variant_new_string(str->str));
2146
0
  }
2147
0
  if (priv->flags > 0) {
2148
0
    g_variant_builder_add(builder,
2149
0
              "{sv}",
2150
0
              FWUPD_RESULT_KEY_FLAGS,
2151
0
              g_variant_new_uint64(priv->flags));
2152
0
  }
2153
0
  if (priv->request_flags > 0) {
2154
0
    g_variant_builder_add(builder,
2155
0
              "{sv}",
2156
0
              FWUPD_RESULT_KEY_REQUEST_FLAGS,
2157
0
              g_variant_new_uint64(priv->request_flags));
2158
0
  }
2159
0
  if (priv->problems > 0) {
2160
0
    g_variant_builder_add(builder,
2161
0
              "{sv}",
2162
0
              FWUPD_RESULT_KEY_PROBLEMS,
2163
0
              g_variant_new_uint64(priv->problems));
2164
0
  }
2165
0
  if (priv->created > 0) {
2166
0
    g_variant_builder_add(builder,
2167
0
              "{sv}",
2168
0
              FWUPD_RESULT_KEY_CREATED,
2169
0
              g_variant_new_uint64(priv->created));
2170
0
  }
2171
0
  if (priv->modified > 0) {
2172
0
    g_variant_builder_add(builder,
2173
0
              "{sv}",
2174
0
              FWUPD_RESULT_KEY_MODIFIED,
2175
0
              g_variant_new_uint64(priv->modified));
2176
0
  }
2177
0
  if (priv->version_build_date > 0) {
2178
0
    g_variant_builder_add(builder,
2179
0
              "{sv}",
2180
0
              FWUPD_RESULT_KEY_VERSION_BUILD_DATE,
2181
0
              g_variant_new_uint64(priv->version_build_date));
2182
0
  }
2183
2184
0
  if (priv->summary != NULL) {
2185
0
    g_variant_builder_add(builder,
2186
0
              "{sv}",
2187
0
              FWUPD_RESULT_KEY_SUMMARY,
2188
0
              g_variant_new_string(priv->summary));
2189
0
  }
2190
0
  if (priv->branch != NULL) {
2191
0
    g_variant_builder_add(builder,
2192
0
              "{sv}",
2193
0
              FWUPD_RESULT_KEY_BRANCH,
2194
0
              g_variant_new_string(priv->branch));
2195
0
  }
2196
0
  if (priv->checksums != NULL && priv->checksums->len > 0) {
2197
0
    g_autoptr(GString) str = g_string_new("");
2198
0
    for (guint i = 0; i < priv->checksums->len; i++) {
2199
0
      const gchar *checksum = g_ptr_array_index(priv->checksums, i);
2200
0
      g_string_append_printf(str, "%s,", checksum);
2201
0
    }
2202
0
    if (str->len > 0)
2203
0
      g_string_truncate(str, str->len - 1);
2204
0
    g_variant_builder_add(builder,
2205
0
              "{sv}",
2206
0
              FWUPD_RESULT_KEY_CHECKSUM,
2207
0
              g_variant_new_string(str->str));
2208
0
  }
2209
0
  if (priv->plugin != NULL) {
2210
0
    g_variant_builder_add(builder,
2211
0
              "{sv}",
2212
0
              FWUPD_RESULT_KEY_PLUGIN,
2213
0
              g_variant_new_string(priv->plugin));
2214
0
  }
2215
0
  if (priv->protocols != NULL && priv->protocols->len > 0) {
2216
0
    g_autoptr(GString) str = g_string_new(NULL);
2217
0
    for (guint i = 0; i < priv->protocols->len; i++) {
2218
0
      const gchar *tmp = g_ptr_array_index(priv->protocols, i);
2219
0
      g_string_append_printf(str, "%s|", tmp);
2220
0
    }
2221
0
    if (str->len > 0)
2222
0
      g_string_truncate(str, str->len - 1);
2223
0
    g_variant_builder_add(builder,
2224
0
              "{sv}",
2225
0
              FWUPD_RESULT_KEY_PROTOCOL,
2226
0
              g_variant_new_string(str->str));
2227
0
  }
2228
0
  if (priv->issues != NULL && priv->issues->len > 0) {
2229
0
    g_autofree const gchar **strv = g_new0(const gchar *, priv->issues->len + 1);
2230
0
    for (guint i = 0; i < priv->issues->len; i++)
2231
0
      strv[i] = (const gchar *)g_ptr_array_index(priv->issues, i);
2232
0
    g_variant_builder_add(builder,
2233
0
              "{sv}",
2234
0
              FWUPD_RESULT_KEY_ISSUES,
2235
0
              g_variant_new_strv(strv, -1));
2236
0
  }
2237
0
  if (priv->version != NULL) {
2238
0
    g_variant_builder_add(builder,
2239
0
              "{sv}",
2240
0
              FWUPD_RESULT_KEY_VERSION,
2241
0
              g_variant_new_string(priv->version));
2242
0
  }
2243
0
  if (priv->version_lowest != NULL) {
2244
0
    g_variant_builder_add(builder,
2245
0
              "{sv}",
2246
0
              FWUPD_RESULT_KEY_VERSION_LOWEST,
2247
0
              g_variant_new_string(priv->version_lowest));
2248
0
  }
2249
0
  if (priv->version_bootloader != NULL) {
2250
0
    g_variant_builder_add(builder,
2251
0
              "{sv}",
2252
0
              FWUPD_RESULT_KEY_VERSION_BOOTLOADER,
2253
0
              g_variant_new_string(priv->version_bootloader));
2254
0
  }
2255
0
  if (priv->version_raw > 0) {
2256
0
    g_variant_builder_add(builder,
2257
0
              "{sv}",
2258
0
              FWUPD_RESULT_KEY_VERSION_RAW,
2259
0
              g_variant_new_uint64(priv->version_raw));
2260
0
  }
2261
0
  if (priv->version_lowest_raw > 0) {
2262
0
    g_variant_builder_add(builder,
2263
0
              "{sv}",
2264
0
              FWUPD_RESULT_KEY_VERSION_LOWEST_RAW,
2265
0
              g_variant_new_uint64(priv->version_lowest_raw));
2266
0
  }
2267
0
  if (priv->version_bootloader_raw > 0) {
2268
0
    g_variant_builder_add(builder,
2269
0
              "{sv}",
2270
0
              FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW,
2271
0
              g_variant_new_uint64(priv->version_raw));
2272
0
  }
2273
0
  if (priv->flashes_left > 0) {
2274
0
    g_variant_builder_add(builder,
2275
0
              "{sv}",
2276
0
              FWUPD_RESULT_KEY_FLASHES_LEFT,
2277
0
              g_variant_new_uint32(priv->flashes_left));
2278
0
  }
2279
0
  if (priv->battery_level != FWUPD_BATTERY_LEVEL_INVALID) {
2280
0
    g_variant_builder_add(builder,
2281
0
              "{sv}",
2282
0
              FWUPD_RESULT_KEY_BATTERY_LEVEL,
2283
0
              g_variant_new_uint32(priv->battery_level));
2284
0
  }
2285
0
  if (priv->battery_threshold != FWUPD_BATTERY_LEVEL_INVALID) {
2286
0
    g_variant_builder_add(builder,
2287
0
              "{sv}",
2288
0
              FWUPD_RESULT_KEY_BATTERY_THRESHOLD,
2289
0
              g_variant_new_uint32(priv->battery_threshold));
2290
0
  }
2291
0
  if (priv->install_duration > 0) {
2292
0
    g_variant_builder_add(builder,
2293
0
              "{sv}",
2294
0
              FWUPD_RESULT_KEY_INSTALL_DURATION,
2295
0
              g_variant_new_uint32(priv->install_duration));
2296
0
  }
2297
0
  if (priv->update_error != NULL) {
2298
0
    g_variant_builder_add(builder,
2299
0
              "{sv}",
2300
0
              FWUPD_RESULT_KEY_UPDATE_ERROR,
2301
0
              g_variant_new_string(priv->update_error));
2302
0
  }
2303
0
  if (priv->update_state != FWUPD_UPDATE_STATE_UNKNOWN) {
2304
0
    g_variant_builder_add(builder,
2305
0
              "{sv}",
2306
0
              FWUPD_RESULT_KEY_UPDATE_STATE,
2307
0
              g_variant_new_uint32(priv->update_state));
2308
0
  }
2309
0
  if (priv->status != FWUPD_STATUS_UNKNOWN) {
2310
0
    g_variant_builder_add(builder,
2311
0
              "{sv}",
2312
0
              FWUPD_RESULT_KEY_STATUS,
2313
0
              g_variant_new_uint32(priv->status));
2314
0
  }
2315
0
  if (priv->percentage != 0) {
2316
0
    g_variant_builder_add(builder,
2317
0
              "{sv}",
2318
0
              FWUPD_RESULT_KEY_PERCENTAGE,
2319
0
              g_variant_new_uint32(priv->percentage));
2320
0
  }
2321
0
  if (priv->version_format != FWUPD_VERSION_FORMAT_UNKNOWN) {
2322
0
    g_variant_builder_add(builder,
2323
0
              "{sv}",
2324
0
              FWUPD_RESULT_KEY_VERSION_FORMAT,
2325
0
              g_variant_new_uint32(priv->version_format));
2326
0
  }
2327
0
  if (priv->instance_ids != NULL && (flags & FWUPD_CODEC_FLAG_TRUSTED) > 0) {
2328
0
    if (priv->serial != NULL) {
2329
0
      g_variant_builder_add(builder,
2330
0
                "{sv}",
2331
0
                FWUPD_RESULT_KEY_SERIAL,
2332
0
                g_variant_new_string(priv->serial));
2333
0
    }
2334
0
    if (priv->instance_ids->len > 0) {
2335
0
      const gchar *const *tmp = (const gchar *const *)priv->instance_ids->pdata;
2336
0
      g_variant_builder_add(builder,
2337
0
                "{sv}",
2338
0
                FWUPD_RESULT_KEY_INSTANCE_IDS,
2339
0
                g_variant_new_strv(tmp, priv->instance_ids->len));
2340
0
    }
2341
0
  }
2342
2343
  /* create an array with all the metadata in */
2344
0
  if (priv->releases != NULL && priv->releases->len > 0) {
2345
0
    g_autofree GVariant **children = NULL;
2346
0
    children = g_new0(GVariant *, priv->releases->len);
2347
0
    for (guint i = 0; i < priv->releases->len; i++) {
2348
0
      FwupdRelease *release = g_ptr_array_index(priv->releases, i);
2349
0
      children[i] =
2350
0
          fwupd_codec_to_variant(FWUPD_CODEC(release), FWUPD_CODEC_FLAG_NONE);
2351
0
    }
2352
0
    g_variant_builder_add(
2353
0
        builder,
2354
0
        "{sv}",
2355
0
        FWUPD_RESULT_KEY_RELEASE,
2356
0
        g_variant_new_array(G_VARIANT_TYPE("a{sv}"), children, priv->releases->len));
2357
0
  }
2358
0
}
2359
2360
static void
2361
fwupd_device_from_key_value(FwupdDevice *self, const gchar *key, GVariant *value)
2362
0
{
2363
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_RELEASE) == 0) {
2364
0
    GVariantIter iter;
2365
0
    GVariant *child;
2366
0
    g_variant_iter_init(&iter, value);
2367
0
    while ((child = g_variant_iter_next_value(&iter))) {
2368
0
      g_autoptr(FwupdRelease) release = fwupd_release_new();
2369
0
      if (fwupd_codec_from_variant(FWUPD_CODEC(release), child, NULL))
2370
0
        fwupd_device_add_release(self, release);
2371
0
      g_variant_unref(child);
2372
0
    }
2373
0
    return;
2374
0
  }
2375
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_DEVICE_ID) == 0) {
2376
0
    fwupd_device_set_id(self, g_variant_get_string(value, NULL));
2377
0
    return;
2378
0
  }
2379
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PARENT_DEVICE_ID) == 0) {
2380
0
    fwupd_device_set_parent_id(self, g_variant_get_string(value, NULL));
2381
0
    return;
2382
0
  }
2383
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_COMPOSITE_ID) == 0) {
2384
0
    fwupd_device_set_composite_id(self, g_variant_get_string(value, NULL));
2385
0
    return;
2386
0
  }
2387
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_FLAGS) == 0) {
2388
0
    fwupd_device_set_flags(self, fwupd_variant_get_uint64(value));
2389
0
    return;
2390
0
  }
2391
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PROBLEMS) == 0) {
2392
0
    fwupd_device_set_problems(self, fwupd_variant_get_uint64(value));
2393
0
    return;
2394
0
  }
2395
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_REQUEST_FLAGS) == 0) {
2396
0
    fwupd_device_set_request_flags(self, fwupd_variant_get_uint64(value));
2397
0
    return;
2398
0
  }
2399
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_CREATED) == 0) {
2400
0
    fwupd_device_set_created(self, fwupd_variant_get_uint64(value));
2401
0
    return;
2402
0
  }
2403
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_MODIFIED) == 0) {
2404
0
    fwupd_device_set_modified(self, fwupd_variant_get_uint64(value));
2405
0
    return;
2406
0
  }
2407
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_BUILD_DATE) == 0) {
2408
0
    fwupd_device_set_version_build_date(self, fwupd_variant_get_uint64(value));
2409
0
    return;
2410
0
  }
2411
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_GUID) == 0) {
2412
0
    g_autofree const gchar **guids = g_variant_get_strv(value, NULL);
2413
0
    for (guint i = 0; guids != NULL && guids[i] != NULL; i++)
2414
0
      fwupd_device_add_guid(self, guids[i]);
2415
0
    return;
2416
0
  }
2417
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_INSTANCE_IDS) == 0) {
2418
0
    g_autofree const gchar **instance_ids = g_variant_get_strv(value, NULL);
2419
0
    for (guint i = 0; instance_ids != NULL && instance_ids[i] != NULL; i++)
2420
0
      fwupd_device_add_instance_id(self, instance_ids[i]);
2421
0
    return;
2422
0
  }
2423
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_ICON) == 0) {
2424
0
    g_autofree const gchar **icons = g_variant_get_strv(value, NULL);
2425
0
    for (guint i = 0; icons != NULL && icons[i] != NULL; i++)
2426
0
      fwupd_device_add_icon(self, icons[i]);
2427
0
    return;
2428
0
  }
2429
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_NAME) == 0) {
2430
0
    fwupd_device_set_name(self, g_variant_get_string(value, NULL));
2431
0
    return;
2432
0
  }
2433
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VENDOR) == 0) {
2434
0
    fwupd_device_set_vendor(self, g_variant_get_string(value, NULL));
2435
0
    return;
2436
0
  }
2437
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VENDOR_ID) == 0) {
2438
0
    g_auto(GStrv) vendor_ids = NULL;
2439
0
    vendor_ids = g_strsplit(g_variant_get_string(value, NULL), "|", -1);
2440
0
    for (guint i = 0; vendor_ids[i] != NULL; i++)
2441
0
      fwupd_device_add_vendor_id(self, vendor_ids[i]);
2442
0
    return;
2443
0
  }
2444
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_SERIAL) == 0) {
2445
0
    fwupd_device_set_serial(self, g_variant_get_string(value, NULL));
2446
0
    return;
2447
0
  }
2448
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_SUMMARY) == 0) {
2449
0
    fwupd_device_set_summary(self, g_variant_get_string(value, NULL));
2450
0
    return;
2451
0
  }
2452
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BRANCH) == 0) {
2453
0
    fwupd_device_set_branch(self, g_variant_get_string(value, NULL));
2454
0
    return;
2455
0
  }
2456
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_CHECKSUM) == 0) {
2457
0
    const gchar *checksums = g_variant_get_string(value, NULL);
2458
0
    if (checksums != NULL) {
2459
0
      g_auto(GStrv) split = g_strsplit(checksums, ",", -1);
2460
0
      for (guint i = 0; split[i] != NULL; i++)
2461
0
        fwupd_device_add_checksum(self, split[i]);
2462
0
    }
2463
0
    return;
2464
0
  }
2465
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PLUGIN) == 0) {
2466
0
    fwupd_device_set_plugin(self, g_variant_get_string(value, NULL));
2467
0
    return;
2468
0
  }
2469
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PROTOCOL) == 0) {
2470
0
    g_auto(GStrv) protocols = NULL;
2471
0
    protocols = g_strsplit(g_variant_get_string(value, NULL), "|", -1);
2472
0
    for (guint i = 0; protocols[i] != NULL; i++)
2473
0
      fwupd_device_add_protocol(self, protocols[i]);
2474
0
    return;
2475
0
  }
2476
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_ISSUES) == 0) {
2477
0
    g_autofree const gchar **strv = g_variant_get_strv(value, NULL);
2478
0
    for (guint i = 0; strv[i] != NULL; i++)
2479
0
      fwupd_device_add_issue(self, strv[i]);
2480
0
    return;
2481
0
  }
2482
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION) == 0) {
2483
0
    fwupd_device_set_version(self, g_variant_get_string(value, NULL));
2484
0
    return;
2485
0
  }
2486
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_LOWEST) == 0) {
2487
0
    fwupd_device_set_version_lowest(self, g_variant_get_string(value, NULL));
2488
0
    return;
2489
0
  }
2490
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_BOOTLOADER) == 0) {
2491
0
    fwupd_device_set_version_bootloader(self, g_variant_get_string(value, NULL));
2492
0
    return;
2493
0
  }
2494
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_FLASHES_LEFT) == 0) {
2495
0
    fwupd_device_set_flashes_left(self, fwupd_variant_get_uint32(value));
2496
0
    return;
2497
0
  }
2498
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BATTERY_LEVEL) == 0) {
2499
0
    fwupd_device_set_battery_level(self, fwupd_variant_get_uint32(value));
2500
0
    return;
2501
0
  }
2502
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_BATTERY_THRESHOLD) == 0) {
2503
0
    fwupd_device_set_battery_threshold(self, fwupd_variant_get_uint32(value));
2504
0
    return;
2505
0
  }
2506
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_INSTALL_DURATION) == 0) {
2507
0
    fwupd_device_set_install_duration(self, fwupd_variant_get_uint32(value));
2508
0
    return;
2509
0
  }
2510
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_UPDATE_ERROR) == 0) {
2511
0
    fwupd_device_set_update_error(self, g_variant_get_string(value, NULL));
2512
0
    return;
2513
0
  }
2514
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_UPDATE_STATE) == 0) {
2515
0
    fwupd_device_set_update_state(self, fwupd_variant_get_uint32(value));
2516
0
    return;
2517
0
  }
2518
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_STATUS) == 0) {
2519
0
    fwupd_device_set_status(self, fwupd_variant_get_uint32(value));
2520
0
    return;
2521
0
  }
2522
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_PERCENTAGE) == 0) {
2523
0
    fwupd_device_set_percentage(self, fwupd_variant_get_uint32(value));
2524
0
    return;
2525
0
  }
2526
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_FORMAT) == 0) {
2527
0
    fwupd_device_set_version_format(self, fwupd_variant_get_uint32(value));
2528
0
    return;
2529
0
  }
2530
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_RAW) == 0) {
2531
0
    fwupd_device_set_version_raw(self, fwupd_variant_get_uint64(value));
2532
0
    return;
2533
0
  }
2534
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_LOWEST_RAW) == 0) {
2535
0
    fwupd_device_set_version_lowest_raw(self, fwupd_variant_get_uint64(value));
2536
0
    return;
2537
0
  }
2538
0
  if (g_strcmp0(key, FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW) == 0) {
2539
0
    fwupd_device_set_version_bootloader_raw(self, fwupd_variant_get_uint64(value));
2540
0
    return;
2541
0
  }
2542
0
}
2543
2544
static void
2545
fwupd_device_string_append_flags(GString *str, guint idt, const gchar *key, guint64 device_flags)
2546
0
{
2547
0
  g_autoptr(GString) tmp = g_string_new("");
2548
0
  for (guint i = 0; i < 64; i++) {
2549
0
    if ((device_flags & ((guint64)1 << i)) == 0)
2550
0
      continue;
2551
0
    g_string_append_printf(tmp, "%s|", fwupd_device_flag_to_string((guint64)1 << i));
2552
0
  }
2553
0
  if (tmp->len == 0) {
2554
0
    g_string_append(tmp, fwupd_device_flag_to_string(0));
2555
0
  } else {
2556
0
    g_string_truncate(tmp, tmp->len - 1);
2557
0
  }
2558
0
  fwupd_codec_string_append(str, idt, key, tmp->str);
2559
0
}
2560
2561
static void
2562
fwupd_device_string_append_request_flags(GString *str,
2563
           guint idt,
2564
           const gchar *key,
2565
           guint64 request_flags)
2566
0
{
2567
0
  g_autoptr(GString) tmp = g_string_new("");
2568
0
  for (guint i = 0; i < 64; i++) {
2569
0
    if ((request_flags & ((guint64)1 << i)) == 0)
2570
0
      continue;
2571
0
    g_string_append_printf(tmp, "%s|", fwupd_request_flag_to_string((guint64)1 << i));
2572
0
  }
2573
0
  if (tmp->len == 0) {
2574
0
    g_string_append(tmp, fwupd_request_flag_to_string(0));
2575
0
  } else {
2576
0
    g_string_truncate(tmp, tmp->len - 1);
2577
0
  }
2578
0
  fwupd_codec_string_append(str, idt, key, tmp->str);
2579
0
}
2580
2581
static void
2582
fwupd_device_string_append_problems(GString *str,
2583
            guint idt,
2584
            const gchar *key,
2585
            guint64 device_problems)
2586
0
{
2587
0
  g_autoptr(GString) tmp = g_string_new("");
2588
0
  for (guint i = 0; i < 64; i++) {
2589
0
    if ((device_problems & ((guint64)1 << i)) == 0)
2590
0
      continue;
2591
0
    g_string_append_printf(tmp, "%s|", fwupd_device_problem_to_string((guint64)1 << i));
2592
0
  }
2593
0
  if (tmp->len == 0) {
2594
0
    g_string_append(tmp, fwupd_device_problem_to_string(0));
2595
0
  } else {
2596
0
    g_string_truncate(tmp, tmp->len - 1);
2597
0
  }
2598
0
  fwupd_codec_string_append(str, idt, key, tmp->str);
2599
0
}
2600
2601
/**
2602
 * fwupd_device_get_update_state:
2603
 * @self: a #FwupdDevice
2604
 *
2605
 * Gets the update state.
2606
 *
2607
 * Returns: the update state, or %FWUPD_UPDATE_STATE_UNKNOWN if unset
2608
 *
2609
 * Since: 0.9.8
2610
 **/
2611
FwupdUpdateState
2612
fwupd_device_get_update_state(FwupdDevice *self)
2613
0
{
2614
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2615
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FWUPD_UPDATE_STATE_UNKNOWN);
2616
0
  return priv->update_state;
2617
0
}
2618
2619
/**
2620
 * fwupd_device_set_update_state:
2621
 * @self: a #FwupdDevice
2622
 * @update_state: the state, e.g. %FWUPD_UPDATE_STATE_PENDING
2623
 *
2624
 * Sets the update state.
2625
 *
2626
 * Since: 0.9.8
2627
 **/
2628
void
2629
fwupd_device_set_update_state(FwupdDevice *self, FwupdUpdateState update_state)
2630
0
{
2631
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2632
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2633
0
  if (priv->update_state == update_state)
2634
0
    return;
2635
0
  priv->update_state = update_state;
2636
0
  g_object_notify(G_OBJECT(self), "update-state");
2637
0
}
2638
2639
/**
2640
 * fwupd_device_get_version_format:
2641
 * @self: a #FwupdDevice
2642
 *
2643
 * Gets the version format.
2644
 *
2645
 * Returns: the version format, or %FWUPD_VERSION_FORMAT_UNKNOWN if unset
2646
 *
2647
 * Since: 1.2.9
2648
 **/
2649
FwupdVersionFormat
2650
fwupd_device_get_version_format(FwupdDevice *self)
2651
0
{
2652
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2653
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FWUPD_VERSION_FORMAT_UNKNOWN);
2654
0
  return priv->version_format;
2655
0
}
2656
2657
/**
2658
 * fwupd_device_set_version_format:
2659
 * @self: a #FwupdDevice
2660
 * @version_format: the version format, e.g. %FWUPD_VERSION_FORMAT_NUMBER
2661
 *
2662
 * Sets the version format.
2663
 *
2664
 * Since: 1.2.9
2665
 **/
2666
void
2667
fwupd_device_set_version_format(FwupdDevice *self, FwupdVersionFormat version_format)
2668
0
{
2669
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2670
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2671
0
  priv->version_format = version_format;
2672
0
}
2673
2674
/**
2675
 * fwupd_device_get_version_raw:
2676
 * @self: a #FwupdDevice
2677
 *
2678
 * Gets the raw version number from the hardware before converted to a string.
2679
 *
2680
 * Returns: the hardware version, or 0 if unset
2681
 *
2682
 * Since: 1.3.6
2683
 **/
2684
guint64
2685
fwupd_device_get_version_raw(FwupdDevice *self)
2686
0
{
2687
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2688
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
2689
0
  return priv->version_raw;
2690
0
}
2691
2692
/**
2693
 * fwupd_device_set_version_raw:
2694
 * @self: a #FwupdDevice
2695
 * @version_raw: the raw hardware version
2696
 *
2697
 * Sets the raw version number from the hardware before converted to a string.
2698
 *
2699
 * Since: 1.3.6
2700
 **/
2701
void
2702
fwupd_device_set_version_raw(FwupdDevice *self, guint64 version_raw)
2703
0
{
2704
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2705
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2706
0
  priv->version_raw = version_raw;
2707
0
}
2708
2709
/**
2710
 * fwupd_device_get_version_build_date:
2711
 * @self: a #FwupdDevice
2712
 *
2713
 * Gets the date when the firmware was built.
2714
 *
2715
 * Returns: the UNIX time, or 0 if unset
2716
 *
2717
 * Since: 1.6.2
2718
 **/
2719
guint64
2720
fwupd_device_get_version_build_date(FwupdDevice *self)
2721
0
{
2722
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2723
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
2724
0
  return priv->version_build_date;
2725
0
}
2726
2727
/**
2728
 * fwupd_device_set_version_build_date:
2729
 * @self: a #FwupdDevice
2730
 * @version_build_date: the UNIX time
2731
 *
2732
 * Sets the date when the firmware was built.
2733
 *
2734
 * Since: 1.6.2
2735
 **/
2736
void
2737
fwupd_device_set_version_build_date(FwupdDevice *self, guint64 version_build_date)
2738
0
{
2739
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2740
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2741
0
  priv->version_build_date = version_build_date;
2742
0
}
2743
2744
/**
2745
 * fwupd_device_get_update_error:
2746
 * @self: a #FwupdDevice
2747
 *
2748
 * Gets the update error string.
2749
 *
2750
 * Returns: the update error string, or %NULL if unset
2751
 *
2752
 * Since: 0.9.8
2753
 **/
2754
const gchar *
2755
fwupd_device_get_update_error(FwupdDevice *self)
2756
0
{
2757
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2758
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
2759
0
  return priv->update_error;
2760
0
}
2761
2762
/**
2763
 * fwupd_device_set_update_error:
2764
 * @self: a #FwupdDevice
2765
 * @update_error: (nullable): the update error string
2766
 *
2767
 * Sets the update error string.
2768
 *
2769
 * Since: 0.9.8
2770
 **/
2771
void
2772
fwupd_device_set_update_error(FwupdDevice *self, const gchar *update_error)
2773
0
{
2774
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2775
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2776
2777
  /* not changed */
2778
0
  if (g_strcmp0(priv->update_error, update_error) == 0)
2779
0
    return;
2780
2781
0
  g_free(priv->update_error);
2782
0
  priv->update_error = g_strdup(update_error);
2783
0
  g_object_notify(G_OBJECT(self), "update-error");
2784
0
}
2785
2786
/**
2787
 * fwupd_device_get_release_default:
2788
 * @self: a #FwupdDevice
2789
 *
2790
 * Gets the default release for this device.
2791
 *
2792
 * Returns: (transfer none): the #FwupdRelease, or %NULL if not set
2793
 *
2794
 * Since: 0.9.8
2795
 **/
2796
FwupdRelease *
2797
fwupd_device_get_release_default(FwupdDevice *self)
2798
0
{
2799
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2800
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
2801
0
  if (priv->releases == NULL || priv->releases->len == 0)
2802
0
    return NULL;
2803
0
  return FWUPD_RELEASE(g_ptr_array_index(priv->releases, 0));
2804
0
}
2805
2806
static void
2807
fwupd_device_ensure_releases(FwupdDevice *self)
2808
0
{
2809
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2810
0
  if (priv->releases == NULL)
2811
0
    priv->releases = g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
2812
0
}
2813
2814
/**
2815
 * fwupd_device_get_releases:
2816
 * @self: a #FwupdDevice
2817
 *
2818
 * Gets all the releases for this device.
2819
 *
2820
 * Returns: (transfer none) (element-type FwupdRelease): array of releases
2821
 *
2822
 * Since: 0.9.8
2823
 **/
2824
GPtrArray *
2825
fwupd_device_get_releases(FwupdDevice *self)
2826
0
{
2827
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2828
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), NULL);
2829
0
  fwupd_device_ensure_releases(self);
2830
0
  return priv->releases;
2831
0
}
2832
2833
/**
2834
 * fwupd_device_add_release:
2835
 * @self: a #FwupdDevice
2836
 * @release: (not nullable): a release
2837
 *
2838
 * Adds a release for this device.
2839
 *
2840
 * Since: 0.9.8
2841
 **/
2842
void
2843
fwupd_device_add_release(FwupdDevice *self, FwupdRelease *release)
2844
0
{
2845
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2846
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2847
0
  g_return_if_fail(FWUPD_IS_RELEASE(release));
2848
0
  fwupd_device_ensure_releases(self);
2849
0
  g_ptr_array_add(priv->releases, g_object_ref(release));
2850
0
}
2851
2852
/**
2853
 * fwupd_device_get_status:
2854
 * @self: a #FwupdDevice
2855
 *
2856
 * Returns what the device is currently doing.
2857
 *
2858
 * Returns: the status value, e.g. %FWUPD_STATUS_DEVICE_WRITE
2859
 *
2860
 * Since: 1.4.0
2861
 **/
2862
FwupdStatus
2863
fwupd_device_get_status(FwupdDevice *self)
2864
0
{
2865
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2866
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
2867
0
  return priv->status;
2868
0
}
2869
2870
/**
2871
 * fwupd_device_set_status:
2872
 * @self: a #FwupdDevice
2873
 * @status: the status value, e.g. %FWUPD_STATUS_DEVICE_WRITE
2874
 *
2875
 * Sets what the device is currently doing.
2876
 *
2877
 * Since: 1.4.0
2878
 **/
2879
void
2880
fwupd_device_set_status(FwupdDevice *self, FwupdStatus status)
2881
0
{
2882
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2883
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2884
0
  if (priv->status == status)
2885
0
    return;
2886
0
  priv->status = status;
2887
0
  g_object_notify(G_OBJECT(self), "status");
2888
0
}
2889
2890
/**
2891
 * fwupd_device_get_percentage:
2892
 * @self: a #FwupdDevice
2893
 *
2894
 * Returns the percentage completion of the device.
2895
 *
2896
 * Returns: the percentage value
2897
 *
2898
 * Since: 1.8.11
2899
 **/
2900
guint
2901
fwupd_device_get_percentage(FwupdDevice *self)
2902
0
{
2903
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2904
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), 0);
2905
0
  return priv->percentage;
2906
0
}
2907
2908
/**
2909
 * fwupd_device_set_percentage:
2910
 * @self: a #FwupdDevice
2911
 * @percentage: the percentage value
2912
 *
2913
 * Sets the percentage completion of the device.
2914
 *
2915
 * Since: 1.8.11
2916
 **/
2917
void
2918
fwupd_device_set_percentage(FwupdDevice *self, guint percentage)
2919
0
{
2920
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2921
0
  g_return_if_fail(FWUPD_IS_DEVICE(self));
2922
0
  if (priv->percentage == percentage)
2923
0
    return;
2924
0
  priv->percentage = percentage;
2925
0
  g_object_notify(G_OBJECT(self), "percentage");
2926
0
}
2927
2928
static void
2929
fwupd_device_string_append_update_state(GString *str,
2930
          guint idt,
2931
          const gchar *key,
2932
          FwupdUpdateState value)
2933
0
{
2934
0
  if (value == FWUPD_UPDATE_STATE_UNKNOWN)
2935
0
    return;
2936
0
  fwupd_codec_string_append(str, idt, key, fwupd_update_state_to_string(value));
2937
0
}
2938
2939
static void
2940
fwupd_device_add_json(FwupdCodec *codec, FwupdJsonObject *json_obj, FwupdCodecFlags flags)
2941
0
{
2942
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
2943
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
2944
2945
0
  if (priv->name != NULL)
2946
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_NAME, priv->name);
2947
0
  if (priv->id != NULL)
2948
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_DEVICE_ID, priv->id);
2949
0
  if (priv->parent_id != NULL) {
2950
0
    fwupd_json_object_add_string(json_obj,
2951
0
               FWUPD_RESULT_KEY_PARENT_DEVICE_ID,
2952
0
               priv->parent_id);
2953
0
  }
2954
0
  if (priv->composite_id != NULL) {
2955
0
    fwupd_json_object_add_string(json_obj,
2956
0
               FWUPD_RESULT_KEY_COMPOSITE_ID,
2957
0
               priv->composite_id);
2958
0
  }
2959
0
  if ((flags & FWUPD_CODEC_FLAG_TRUSTED) > 0 && priv->instance_ids != NULL &&
2960
0
      priv->instance_ids->len > 0) {
2961
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2962
0
    for (guint i = 0; i < priv->instance_ids->len; i++) {
2963
0
      const gchar *instance_id = g_ptr_array_index(priv->instance_ids, i);
2964
0
      fwupd_json_array_add_string(json_arr, instance_id);
2965
0
    }
2966
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_INSTANCE_IDS, json_arr);
2967
0
  }
2968
0
  if (priv->guids != NULL && priv->guids->len > 0) {
2969
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2970
0
    for (guint i = 0; i < priv->guids->len; i++) {
2971
0
      const gchar *guid = g_ptr_array_index(priv->guids, i);
2972
0
      fwupd_json_array_add_string(json_arr, guid);
2973
0
    }
2974
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_GUID, json_arr);
2975
0
  }
2976
0
  if (priv->serial != NULL && (flags & FWUPD_CODEC_FLAG_TRUSTED) > 0)
2977
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_SERIAL, priv->serial);
2978
0
  if (priv->summary != NULL)
2979
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
2980
0
  if (priv->branch != NULL)
2981
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_BRANCH, priv->branch);
2982
0
  if (priv->plugin != NULL)
2983
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
2984
0
  if (priv->protocols != NULL && priv->protocols->len > 0) {
2985
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2986
0
    for (guint i = 0; i < priv->protocols->len; i++) {
2987
0
      const gchar *tmp = g_ptr_array_index(priv->protocols, i);
2988
0
      fwupd_json_array_add_string(json_arr, tmp);
2989
0
    }
2990
0
    fwupd_json_object_add_array(json_obj, "Protocols", json_arr);
2991
0
  }
2992
0
  if (priv->issues != NULL && priv->issues->len > 0) {
2993
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
2994
0
    for (guint i = 0; i < priv->issues->len; i++) {
2995
0
      const gchar *tmp = g_ptr_array_index(priv->issues, i);
2996
0
      fwupd_json_array_add_string(json_arr, tmp);
2997
0
    }
2998
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_ISSUES, json_arr);
2999
0
  }
3000
0
  if (priv->flags != FWUPD_DEVICE_FLAG_NONE) {
3001
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3002
0
    for (guint i = 0; i < 64; i++) {
3003
0
      const gchar *tmp;
3004
0
      if ((priv->flags & ((guint64)1 << i)) == 0)
3005
0
        continue;
3006
0
      tmp = fwupd_device_flag_to_string((guint64)1 << i);
3007
0
      fwupd_json_array_add_string(json_arr, tmp);
3008
0
    }
3009
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_FLAGS, json_arr);
3010
0
  }
3011
0
  if (priv->request_flags != FWUPD_REQUEST_FLAG_NONE) {
3012
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3013
0
    for (guint i = 0; i < 64; i++) {
3014
0
      const gchar *tmp;
3015
0
      if ((priv->request_flags & ((guint64)1 << i)) == 0)
3016
0
        continue;
3017
0
      tmp = fwupd_request_flag_to_string((guint64)1 << i);
3018
0
      fwupd_json_array_add_string(json_arr, tmp);
3019
0
    }
3020
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_REQUEST_FLAGS, json_arr);
3021
0
  }
3022
0
  if (priv->problems != FWUPD_DEVICE_PROBLEM_NONE) {
3023
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3024
0
    for (guint i = 0; i < 64; i++) {
3025
0
      const gchar *tmp;
3026
0
      if ((priv->problems & ((guint64)1 << i)) == 0)
3027
0
        continue;
3028
0
      tmp = fwupd_device_problem_to_string((guint64)1 << i);
3029
0
      fwupd_json_array_add_string(json_arr, tmp);
3030
0
    }
3031
0
    fwupd_json_object_add_array(json_obj, FWUPD_RESULT_KEY_PROBLEMS, json_arr);
3032
0
  }
3033
0
  if (priv->checksums != NULL && priv->checksums->len > 0) {
3034
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3035
0
    for (guint i = 0; i < priv->checksums->len; i++) {
3036
0
      const gchar *checksum = g_ptr_array_index(priv->checksums, i);
3037
0
      fwupd_json_array_add_string(json_arr, checksum);
3038
0
    }
3039
0
    fwupd_json_object_add_array(json_obj, "Checksums", json_arr);
3040
0
  }
3041
0
  if (priv->vendor != NULL)
3042
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_VENDOR, priv->vendor);
3043
0
  if (priv->vendor_ids != NULL && priv->vendor_ids->len > 0) {
3044
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3045
0
    for (guint i = 0; i < priv->vendor_ids->len; i++) {
3046
0
      const gchar *tmp = g_ptr_array_index(priv->vendor_ids, i);
3047
0
      fwupd_json_array_add_string(json_arr, tmp);
3048
0
    }
3049
0
    fwupd_json_object_add_array(json_obj, "VendorIds", json_arr);
3050
0
  }
3051
0
  if (priv->version != NULL)
3052
0
    fwupd_json_object_add_string(json_obj, FWUPD_RESULT_KEY_VERSION, priv->version);
3053
0
  if (priv->version_lowest != NULL) {
3054
0
    fwupd_json_object_add_string(json_obj,
3055
0
               FWUPD_RESULT_KEY_VERSION_LOWEST,
3056
0
               priv->version_lowest);
3057
0
  }
3058
0
  if (priv->version_bootloader != NULL) {
3059
0
    fwupd_json_object_add_string(json_obj,
3060
0
               FWUPD_RESULT_KEY_VERSION_BOOTLOADER,
3061
0
               priv->version_bootloader);
3062
0
  }
3063
0
  if (priv->version_format != FWUPD_VERSION_FORMAT_UNKNOWN) {
3064
0
    fwupd_json_object_add_string(json_obj,
3065
0
               FWUPD_RESULT_KEY_VERSION_FORMAT,
3066
0
               fwupd_version_format_to_string(priv->version_format));
3067
0
  }
3068
0
  if (priv->flashes_left > 0) {
3069
0
    fwupd_json_object_add_integer(json_obj,
3070
0
                FWUPD_RESULT_KEY_FLASHES_LEFT,
3071
0
                priv->flashes_left);
3072
0
  }
3073
0
  if (priv->battery_level != FWUPD_BATTERY_LEVEL_INVALID) {
3074
0
    fwupd_json_object_add_integer(json_obj,
3075
0
                FWUPD_RESULT_KEY_BATTERY_LEVEL,
3076
0
                priv->battery_level);
3077
0
  }
3078
0
  if (priv->battery_threshold != FWUPD_BATTERY_LEVEL_INVALID) {
3079
0
    fwupd_json_object_add_integer(json_obj,
3080
0
                FWUPD_RESULT_KEY_BATTERY_THRESHOLD,
3081
0
                priv->battery_threshold);
3082
0
  }
3083
0
  if (priv->version_raw > 0) {
3084
0
    fwupd_json_object_add_integer(json_obj,
3085
0
                FWUPD_RESULT_KEY_VERSION_RAW,
3086
0
                priv->version_raw);
3087
0
  }
3088
0
  if (priv->version_lowest_raw > 0)
3089
0
    fwupd_json_object_add_integer(json_obj,
3090
0
                FWUPD_RESULT_KEY_VERSION_LOWEST_RAW,
3091
0
                priv->version_lowest_raw);
3092
0
  if (priv->version_bootloader_raw > 0)
3093
0
    fwupd_json_object_add_integer(json_obj,
3094
0
                FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW,
3095
0
                priv->version_bootloader_raw);
3096
0
  if (priv->version_build_date > 0) {
3097
0
    fwupd_json_object_add_integer(json_obj,
3098
0
                FWUPD_RESULT_KEY_VERSION_BUILD_DATE,
3099
0
                priv->version_build_date);
3100
0
  }
3101
0
  if (priv->icons != NULL && priv->icons->len > 0) {
3102
0
    g_autoptr(FwupdJsonArray) json_arr = fwupd_json_array_new();
3103
0
    for (guint i = 0; i < priv->icons->len; i++) {
3104
0
      const gchar *icon = g_ptr_array_index(priv->icons, i);
3105
0
      fwupd_json_array_add_string(json_arr, icon);
3106
0
    }
3107
0
    fwupd_json_object_add_array(json_obj, "Icons", json_arr);
3108
0
  }
3109
0
  if (priv->install_duration > 0) {
3110
0
    fwupd_json_object_add_integer(json_obj,
3111
0
                FWUPD_RESULT_KEY_INSTALL_DURATION,
3112
0
                priv->install_duration);
3113
0
  }
3114
0
  if (priv->created > 0)
3115
0
    fwupd_json_object_add_integer(json_obj, FWUPD_RESULT_KEY_CREATED, priv->created);
3116
0
  if (priv->modified > 0)
3117
0
    fwupd_json_object_add_integer(json_obj, FWUPD_RESULT_KEY_MODIFIED, priv->modified);
3118
0
  if (priv->update_state > 0) {
3119
0
    fwupd_json_object_add_integer(json_obj,
3120
0
                FWUPD_RESULT_KEY_UPDATE_STATE,
3121
0
                priv->update_state);
3122
0
  }
3123
0
  if (priv->status > 0)
3124
0
    fwupd_json_object_add_integer(json_obj, FWUPD_RESULT_KEY_STATUS, priv->status);
3125
0
  if (priv->percentage > 0) {
3126
0
    fwupd_json_object_add_integer(json_obj,
3127
0
                FWUPD_RESULT_KEY_PERCENTAGE,
3128
0
                priv->percentage);
3129
0
  }
3130
0
  if (priv->update_error != NULL) {
3131
0
    fwupd_json_object_add_string(json_obj,
3132
0
               FWUPD_RESULT_KEY_UPDATE_ERROR,
3133
0
               priv->update_error);
3134
0
  }
3135
0
  if (priv->releases != NULL && priv->releases->len > 0)
3136
0
    fwupd_codec_array_to_json(priv->releases, "Releases", json_obj, flags);
3137
0
}
3138
3139
static gboolean
3140
fwupd_device_from_json(FwupdCodec *codec, FwupdJsonObject *json_obj, GError **error)
3141
0
{
3142
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
3143
0
  const gchar *tmp;
3144
0
  gint64 tmp64;
3145
0
  g_autoptr(FwupdJsonArray) json_array_checksums = NULL;
3146
0
  g_autoptr(FwupdJsonArray) json_array_flags = NULL;
3147
0
  g_autoptr(FwupdJsonArray) json_array_guids = NULL;
3148
0
  g_autoptr(FwupdJsonArray) json_array_icons = NULL;
3149
0
  g_autoptr(FwupdJsonArray) json_array_instance_ids = NULL;
3150
0
  g_autoptr(FwupdJsonArray) json_array_issues = NULL;
3151
0
  g_autoptr(FwupdJsonArray) json_array_problems = NULL;
3152
0
  g_autoptr(FwupdJsonArray) json_array_protocols = NULL;
3153
0
  g_autoptr(FwupdJsonArray) json_array_requests = NULL;
3154
0
  g_autoptr(FwupdJsonArray) json_array_vendor_ids = NULL;
3155
3156
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
3157
0
  g_return_val_if_fail(json_obj != NULL, FALSE);
3158
0
  g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
3159
3160
  /* this has to exist */
3161
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_DEVICE_ID, error);
3162
0
  if (tmp == NULL)
3163
0
    return FALSE;
3164
0
  fwupd_device_set_id(self, tmp);
3165
3166
  /* also optional */
3167
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_NAME, NULL);
3168
0
  if (tmp != NULL)
3169
0
    fwupd_device_set_name(self, tmp);
3170
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_PARENT_DEVICE_ID, NULL);
3171
0
  if (tmp != NULL)
3172
0
    fwupd_device_set_parent_id(self, tmp);
3173
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_COMPOSITE_ID, NULL);
3174
0
  if (tmp != NULL)
3175
0
    fwupd_device_set_composite_id(self, tmp);
3176
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_PROTOCOL, NULL);
3177
0
  if (tmp != NULL)
3178
0
    fwupd_device_add_protocol(self, tmp);
3179
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_SERIAL, NULL);
3180
0
  if (tmp != NULL)
3181
0
    fwupd_device_set_serial(self, tmp);
3182
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_SUMMARY, NULL);
3183
0
  if (tmp != NULL)
3184
0
    fwupd_device_set_summary(self, tmp);
3185
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_BRANCH, NULL);
3186
0
  if (tmp != NULL)
3187
0
    fwupd_device_set_branch(self, tmp);
3188
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_PLUGIN, NULL);
3189
0
  if (tmp != NULL)
3190
0
    fwupd_device_set_plugin(self, tmp);
3191
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VENDOR, NULL);
3192
0
  if (tmp != NULL)
3193
0
    fwupd_device_set_vendor(self, tmp);
3194
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VENDOR_ID, NULL);
3195
0
  if (tmp != NULL) {
3196
0
    g_auto(GStrv) split = g_strsplit(tmp, "|", -1);
3197
0
    for (guint i = 0; split[i] != NULL; i++)
3198
0
      fwupd_device_add_vendor_id(self, split[i]);
3199
0
  }
3200
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VERSION, NULL);
3201
0
  if (tmp != NULL)
3202
0
    fwupd_device_set_version(self, tmp);
3203
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VERSION_LOWEST, NULL);
3204
0
  if (tmp != NULL)
3205
0
    fwupd_device_set_version_lowest(self, tmp);
3206
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VERSION_BOOTLOADER, NULL);
3207
0
  if (tmp != NULL)
3208
0
    fwupd_device_set_version_bootloader(self, tmp);
3209
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_VERSION_FORMAT, NULL);
3210
0
  if (tmp != NULL)
3211
0
    fwupd_device_set_version_format(self, fwupd_version_format_from_string(tmp));
3212
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3213
0
              FWUPD_RESULT_KEY_FLASHES_LEFT,
3214
0
              &tmp64,
3215
0
              0,
3216
0
              error))
3217
0
    return FALSE;
3218
0
  fwupd_device_set_flashes_left(self, tmp64);
3219
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3220
0
              FWUPD_RESULT_KEY_BATTERY_LEVEL,
3221
0
              &tmp64,
3222
0
              0,
3223
0
              error))
3224
0
    return FALSE;
3225
0
  fwupd_device_set_battery_level(self, tmp64);
3226
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3227
0
              FWUPD_RESULT_KEY_BATTERY_THRESHOLD,
3228
0
              &tmp64,
3229
0
              0,
3230
0
              error))
3231
0
    return FALSE;
3232
0
  fwupd_device_set_battery_threshold(self, tmp64);
3233
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3234
0
              FWUPD_RESULT_KEY_VERSION_RAW,
3235
0
              &tmp64,
3236
0
              0,
3237
0
              error))
3238
0
    return FALSE;
3239
0
  fwupd_device_set_version_raw(self, tmp64);
3240
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3241
0
              FWUPD_RESULT_KEY_VERSION_LOWEST_RAW,
3242
0
              &tmp64,
3243
0
              0,
3244
0
              error))
3245
0
    return FALSE;
3246
0
  fwupd_device_set_version_lowest_raw(self, tmp64);
3247
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3248
0
              FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW,
3249
0
              &tmp64,
3250
0
              0,
3251
0
              error))
3252
0
    return FALSE;
3253
0
  fwupd_device_set_version_bootloader_raw(self, tmp64);
3254
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3255
0
              FWUPD_RESULT_KEY_VERSION_BUILD_DATE,
3256
0
              &tmp64,
3257
0
              0,
3258
0
              error))
3259
0
    return FALSE;
3260
0
  fwupd_device_set_version_build_date(self, tmp64);
3261
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3262
0
              FWUPD_RESULT_KEY_INSTALL_DURATION,
3263
0
              &tmp64,
3264
0
              0,
3265
0
              error))
3266
0
    return FALSE;
3267
0
  fwupd_device_set_install_duration(self, tmp64);
3268
3269
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3270
0
              FWUPD_RESULT_KEY_CREATED,
3271
0
              &tmp64,
3272
0
              0,
3273
0
              error))
3274
0
    return FALSE;
3275
0
  fwupd_device_set_created(self, tmp64);
3276
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3277
0
              FWUPD_RESULT_KEY_MODIFIED,
3278
0
              &tmp64,
3279
0
              0,
3280
0
              error))
3281
0
    return FALSE;
3282
0
  fwupd_device_set_modified(self, tmp64);
3283
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_UPDATE_STATE, NULL);
3284
0
  if (tmp != NULL)
3285
0
    fwupd_device_set_update_state(self, fwupd_update_state_from_string(tmp));
3286
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_STATUS, NULL);
3287
0
  if (tmp != NULL)
3288
0
    fwupd_device_set_status(self, fwupd_status_from_string(tmp));
3289
0
  if (!fwupd_json_object_get_integer_with_default(json_obj,
3290
0
              FWUPD_RESULT_KEY_PERCENTAGE,
3291
0
              &tmp64,
3292
0
              0,
3293
0
              error))
3294
0
    return FALSE;
3295
0
  fwupd_device_set_percentage(self, tmp64);
3296
0
  tmp = fwupd_json_object_get_string(json_obj, FWUPD_RESULT_KEY_UPDATE_ERROR, NULL);
3297
0
  if (tmp != NULL)
3298
0
    fwupd_device_set_update_error(self, tmp);
3299
3300
0
  json_array_instance_ids =
3301
0
      fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_INSTANCE_IDS, NULL);
3302
0
  if (json_array_instance_ids != NULL) {
3303
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_instance_ids); i++) {
3304
0
      fwupd_device_add_instance_id(
3305
0
          self,
3306
0
          fwupd_json_array_get_string(json_array_instance_ids, i, NULL));
3307
0
    }
3308
0
  }
3309
0
  json_array_guids = fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_GUID, NULL);
3310
0
  if (json_array_guids != NULL) {
3311
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_guids); i++) {
3312
0
      fwupd_device_add_guid(
3313
0
          self,
3314
0
          fwupd_json_array_get_string(json_array_guids, i, NULL));
3315
0
    }
3316
0
  }
3317
0
  json_array_issues = fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_ISSUES, NULL);
3318
0
  if (json_array_issues != NULL) {
3319
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_issues); i++) {
3320
0
      fwupd_device_add_issue(
3321
0
          self,
3322
0
          fwupd_json_array_get_string(json_array_issues, i, NULL));
3323
0
    }
3324
0
  }
3325
0
  json_array_flags = fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_FLAGS, NULL);
3326
0
  if (json_array_flags != NULL) {
3327
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_flags); i++) {
3328
0
      tmp = fwupd_json_array_get_string(json_array_flags, i, NULL);
3329
0
      fwupd_device_add_flag(self, fwupd_device_flag_from_string(tmp));
3330
0
    }
3331
0
  }
3332
0
  json_array_problems =
3333
0
      fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_PROBLEMS, NULL);
3334
0
  if (json_array_problems != NULL) {
3335
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_problems); i++) {
3336
0
      tmp = fwupd_json_array_get_string(json_array_problems, i, NULL);
3337
0
      fwupd_device_add_problem(self, fwupd_device_problem_from_string(tmp));
3338
0
    }
3339
0
  }
3340
0
  json_array_requests =
3341
0
      fwupd_json_object_get_array(json_obj, FWUPD_RESULT_KEY_REQUEST_FLAGS, NULL);
3342
0
  if (json_array_requests != NULL) {
3343
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_requests); i++) {
3344
0
      tmp = fwupd_json_array_get_string(json_array_requests, i, NULL);
3345
0
      fwupd_device_add_request_flag(self, fwupd_request_flag_from_string(tmp));
3346
0
    }
3347
0
  }
3348
0
  json_array_vendor_ids = fwupd_json_object_get_array(json_obj, "VendorIds", NULL);
3349
0
  if (json_array_vendor_ids != NULL) {
3350
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_vendor_ids); i++) {
3351
0
      fwupd_device_add_vendor_id(
3352
0
          self,
3353
0
          fwupd_json_array_get_string(json_array_vendor_ids, i, NULL));
3354
0
    }
3355
0
  }
3356
0
  json_array_protocols = fwupd_json_object_get_array(json_obj, "Protocols", NULL);
3357
0
  if (json_array_protocols != NULL) {
3358
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_protocols); i++) {
3359
0
      fwupd_device_add_protocol(
3360
0
          self,
3361
0
          fwupd_json_array_get_string(json_array_protocols, i, NULL));
3362
0
    }
3363
0
  }
3364
0
  json_array_icons = fwupd_json_object_get_array(json_obj, "Icons", NULL);
3365
0
  if (json_array_icons != NULL) {
3366
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_icons); i++) {
3367
0
      fwupd_device_add_icon(
3368
0
          self,
3369
0
          fwupd_json_array_get_string(json_array_icons, i, NULL));
3370
0
    }
3371
0
  }
3372
0
  json_array_checksums = fwupd_json_object_get_array(json_obj, "Checksums", NULL);
3373
0
  if (json_array_checksums != NULL) {
3374
0
    for (guint i = 0; i < fwupd_json_array_get_size(json_array_checksums); i++) {
3375
0
      fwupd_device_add_checksum(
3376
0
          self,
3377
0
          fwupd_json_array_get_string(json_array_checksums, i, NULL));
3378
0
    }
3379
0
  }
3380
3381
  /* success */
3382
0
  return TRUE;
3383
0
}
3384
3385
static gchar *
3386
fwupd_device_verstr_raw(guint64 value_raw)
3387
0
{
3388
0
  if (value_raw > 0xffffffff) {
3389
0
    return g_strdup_printf("0x%08x%08x",
3390
0
               (guint)(value_raw >> 32),
3391
0
               (guint)(value_raw & 0xffffffff));
3392
0
  }
3393
0
  return g_strdup_printf("0x%08x", (guint)value_raw);
3394
0
}
3395
3396
typedef struct {
3397
  gchar *guid;
3398
  gchar *instance_id;
3399
} FwupdDeviceGuidHelper;
3400
3401
static void
3402
fwupd_device_guid_helper_new(FwupdDeviceGuidHelper *helper)
3403
0
{
3404
0
  g_free(helper->guid);
3405
0
  g_free(helper->instance_id);
3406
0
  g_free(helper);
3407
0
}
3408
3409
static FwupdDeviceGuidHelper *
3410
fwupd_device_guid_helper_array_find(GPtrArray *array, const gchar *guid)
3411
0
{
3412
0
  for (guint i = 0; i < array->len; i++) {
3413
0
    FwupdDeviceGuidHelper *helper = g_ptr_array_index(array, i);
3414
0
    if (g_strcmp0(helper->guid, guid) == 0)
3415
0
      return helper;
3416
0
  }
3417
0
  return NULL;
3418
0
}
3419
3420
static void
3421
fwupd_device_add_string(FwupdCodec *codec, guint idt, GString *str)
3422
0
{
3423
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
3424
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3425
0
  g_autoptr(GPtrArray) guid_helpers = NULL;
3426
3427
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_DEVICE_ID, priv->id);
3428
0
  if (g_strcmp0(priv->composite_id, priv->parent_id) != 0) {
3429
0
    fwupd_codec_string_append(str,
3430
0
            idt,
3431
0
            FWUPD_RESULT_KEY_PARENT_DEVICE_ID,
3432
0
            priv->parent_id);
3433
0
  }
3434
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_COMPOSITE_ID, priv->composite_id);
3435
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_NAME, priv->name);
3436
0
  if (priv->status != FWUPD_STATUS_UNKNOWN) {
3437
0
    fwupd_codec_string_append(str,
3438
0
            idt,
3439
0
            FWUPD_RESULT_KEY_STATUS,
3440
0
            fwupd_status_to_string(priv->status));
3441
0
  }
3442
0
  fwupd_codec_string_append_int(str, idt, FWUPD_RESULT_KEY_PERCENTAGE, priv->percentage);
3443
3444
  /* show instance IDs optionally mapped to GUIDs, and also "standalone" GUIDs */
3445
0
  guid_helpers = g_ptr_array_new_with_free_func((GDestroyNotify)fwupd_device_guid_helper_new);
3446
0
  if (priv->instance_ids != NULL) {
3447
0
    for (guint i = 0; i < priv->instance_ids->len; i++) {
3448
0
      FwupdDeviceGuidHelper *helper = g_new0(FwupdDeviceGuidHelper, 1);
3449
0
      const gchar *instance_id = g_ptr_array_index(priv->instance_ids, i);
3450
0
      helper->guid = fwupd_guid_hash_string(instance_id);
3451
0
      helper->instance_id = g_strdup(instance_id);
3452
0
      g_ptr_array_add(guid_helpers, helper);
3453
0
    }
3454
0
  }
3455
0
  if (priv->guids != NULL) {
3456
0
    for (guint i = 0; i < priv->guids->len; i++) {
3457
0
      const gchar *guid = g_ptr_array_index(priv->guids, i);
3458
0
      if (fwupd_device_guid_helper_array_find(guid_helpers, guid) == NULL) {
3459
0
        FwupdDeviceGuidHelper *helper = g_new0(FwupdDeviceGuidHelper, 1);
3460
0
        helper->guid = g_strdup(guid);
3461
0
        g_ptr_array_add(guid_helpers, helper);
3462
0
      }
3463
0
    }
3464
0
  }
3465
0
  for (guint i = 0; i < guid_helpers->len; i++) {
3466
0
    FwupdDeviceGuidHelper *helper = g_ptr_array_index(guid_helpers, i);
3467
0
    g_autoptr(GString) tmp = g_string_new(helper->guid);
3468
0
    if (helper->instance_id != NULL)
3469
0
      g_string_append_printf(tmp, " ← %s", helper->instance_id);
3470
0
    if (!fwupd_device_has_guid(self, helper->guid))
3471
0
      g_string_append(tmp, " ⚠");
3472
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_GUID, tmp->str);
3473
0
  }
3474
3475
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_SERIAL, priv->serial);
3476
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_SUMMARY, priv->summary);
3477
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_BRANCH, priv->branch);
3478
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_PLUGIN, priv->plugin);
3479
0
  if (priv->protocols != NULL) {
3480
0
    for (guint i = 0; i < priv->protocols->len; i++) {
3481
0
      const gchar *tmp = g_ptr_array_index(priv->protocols, i);
3482
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_PROTOCOL, tmp);
3483
0
    }
3484
0
  }
3485
0
  if (priv->issues != NULL) {
3486
0
    for (guint i = 0; i < priv->issues->len; i++) {
3487
0
      const gchar *tmp = g_ptr_array_index(priv->issues, i);
3488
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_ISSUES, tmp);
3489
0
    }
3490
0
  }
3491
0
  fwupd_device_string_append_flags(str, idt, FWUPD_RESULT_KEY_FLAGS, priv->flags);
3492
0
  if (priv->problems != FWUPD_DEVICE_PROBLEM_NONE) {
3493
0
    fwupd_device_string_append_problems(str,
3494
0
                idt,
3495
0
                FWUPD_RESULT_KEY_PROBLEMS,
3496
0
                priv->problems);
3497
0
  }
3498
0
  if (priv->request_flags > 0) {
3499
0
    fwupd_device_string_append_request_flags(str,
3500
0
               idt,
3501
0
               FWUPD_RESULT_KEY_REQUEST_FLAGS,
3502
0
               priv->request_flags);
3503
0
  }
3504
0
  if (priv->checksums != NULL) {
3505
0
    for (guint i = 0; i < priv->checksums->len; i++) {
3506
0
      const gchar *checksum = g_ptr_array_index(priv->checksums, i);
3507
0
      g_autofree gchar *checksum_display =
3508
0
          fwupd_checksum_format_for_display(checksum);
3509
0
      fwupd_codec_string_append(str,
3510
0
              idt,
3511
0
              FWUPD_RESULT_KEY_CHECKSUM,
3512
0
              checksum_display);
3513
0
    }
3514
0
  }
3515
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VENDOR, priv->vendor);
3516
0
  if (priv->vendor_ids != NULL) {
3517
0
    for (guint i = 0; i < priv->vendor_ids->len; i++) {
3518
0
      const gchar *tmp = g_ptr_array_index(priv->vendor_ids, i);
3519
0
      fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VENDOR_ID, tmp);
3520
0
    }
3521
0
  }
3522
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION, priv->version);
3523
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_LOWEST, priv->version_lowest);
3524
0
  fwupd_codec_string_append(str,
3525
0
          idt,
3526
0
          FWUPD_RESULT_KEY_VERSION_BOOTLOADER,
3527
0
          priv->version_bootloader);
3528
0
  if (priv->version_format != FWUPD_VERSION_FORMAT_UNKNOWN) {
3529
0
    fwupd_codec_string_append(str,
3530
0
            idt,
3531
0
            FWUPD_RESULT_KEY_VERSION_FORMAT,
3532
0
            fwupd_version_format_to_string(priv->version_format));
3533
0
  }
3534
0
  if (priv->flashes_left < 2) {
3535
0
    fwupd_codec_string_append_int(str,
3536
0
                idt,
3537
0
                FWUPD_RESULT_KEY_FLASHES_LEFT,
3538
0
                priv->flashes_left);
3539
0
  }
3540
0
  if (priv->battery_level != FWUPD_BATTERY_LEVEL_INVALID) {
3541
0
    fwupd_codec_string_append_int(str,
3542
0
                idt,
3543
0
                FWUPD_RESULT_KEY_BATTERY_LEVEL,
3544
0
                priv->battery_level);
3545
0
  }
3546
0
  if (priv->battery_threshold != FWUPD_BATTERY_LEVEL_INVALID) {
3547
0
    fwupd_codec_string_append_int(str,
3548
0
                idt,
3549
0
                FWUPD_RESULT_KEY_BATTERY_THRESHOLD,
3550
0
                priv->battery_threshold);
3551
0
  }
3552
0
  if (priv->version_raw > 0) {
3553
0
    g_autofree gchar *tmp = fwupd_device_verstr_raw(priv->version_raw);
3554
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_RAW, tmp);
3555
0
  }
3556
0
  if (priv->version_lowest_raw > 0) {
3557
0
    g_autofree gchar *tmp = fwupd_device_verstr_raw(priv->version_lowest_raw);
3558
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_LOWEST_RAW, tmp);
3559
0
  }
3560
0
  fwupd_codec_string_append_time(str,
3561
0
               idt,
3562
0
               FWUPD_RESULT_KEY_VERSION_BUILD_DATE,
3563
0
               priv->version_build_date);
3564
0
  if (priv->version_bootloader_raw > 0) {
3565
0
    g_autofree gchar *tmp = fwupd_device_verstr_raw(priv->version_bootloader_raw);
3566
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_VERSION_BOOTLOADER_RAW, tmp);
3567
0
  }
3568
0
  if (priv->icons != NULL && priv->icons->len > 0) {
3569
0
    g_autoptr(GString) tmp = g_string_new(NULL);
3570
0
    for (guint i = 0; i < priv->icons->len; i++) {
3571
0
      const gchar *icon = g_ptr_array_index(priv->icons, i);
3572
0
      g_string_append_printf(tmp, "%s,", icon);
3573
0
    }
3574
0
    if (tmp->len > 1)
3575
0
      g_string_truncate(tmp, tmp->len - 1);
3576
0
    fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_ICON, tmp->str);
3577
0
  }
3578
0
  fwupd_codec_string_append_int(str,
3579
0
              idt,
3580
0
              FWUPD_RESULT_KEY_INSTALL_DURATION,
3581
0
              priv->install_duration);
3582
0
  fwupd_codec_string_append_time(str, idt, FWUPD_RESULT_KEY_CREATED, priv->created);
3583
0
  fwupd_codec_string_append_time(str, idt, FWUPD_RESULT_KEY_MODIFIED, priv->modified);
3584
0
  fwupd_device_string_append_update_state(str,
3585
0
            idt,
3586
0
            FWUPD_RESULT_KEY_UPDATE_STATE,
3587
0
            priv->update_state);
3588
0
  fwupd_codec_string_append(str, idt, FWUPD_RESULT_KEY_UPDATE_ERROR, priv->update_error);
3589
0
  if (priv->releases != NULL) {
3590
0
    for (guint i = 0; i < priv->releases->len; i++) {
3591
0
      FwupdRelease *release = g_ptr_array_index(priv->releases, i);
3592
0
      fwupd_codec_add_string(FWUPD_CODEC(release), idt, str);
3593
0
    }
3594
0
  }
3595
0
}
3596
3597
static void
3598
fwupd_device_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
3599
0
{
3600
0
  FwupdDevice *self = FWUPD_DEVICE(object);
3601
0
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3602
0
  switch (prop_id) {
3603
0
  case PROP_ID:
3604
0
    g_value_set_string(value, priv->id);
3605
0
    break;
3606
0
  case PROP_VERSION:
3607
0
    g_value_set_string(value, priv->version);
3608
0
    break;
3609
0
  case PROP_VENDOR:
3610
0
    g_value_set_string(value, priv->vendor);
3611
0
    break;
3612
0
  case PROP_VERSION_FORMAT:
3613
0
    g_value_set_uint(value, priv->version_format);
3614
0
    break;
3615
0
  case PROP_FLAGS:
3616
0
    g_value_set_uint64(value, priv->flags);
3617
0
    break;
3618
0
  case PROP_PROBLEMS:
3619
0
    g_value_set_uint64(value, priv->problems);
3620
0
    break;
3621
0
  case PROP_REQUEST_FLAGS:
3622
0
    g_value_set_uint64(value, priv->request_flags);
3623
0
    break;
3624
0
  case PROP_UPDATE_ERROR:
3625
0
    g_value_set_string(value, priv->update_error);
3626
0
    break;
3627
0
  case PROP_STATUS:
3628
0
    g_value_set_uint(value, priv->status);
3629
0
    break;
3630
0
  case PROP_PERCENTAGE:
3631
0
    g_value_set_uint(value, priv->percentage);
3632
0
    break;
3633
0
  case PROP_PARENT:
3634
0
    g_value_set_object(value, priv->parent);
3635
0
    break;
3636
0
  case PROP_UPDATE_STATE:
3637
0
    g_value_set_uint(value, priv->update_state);
3638
0
    break;
3639
0
  case PROP_BATTERY_LEVEL:
3640
0
    g_value_set_uint(value, priv->battery_level);
3641
0
    break;
3642
0
  case PROP_BATTERY_THRESHOLD:
3643
0
    g_value_set_uint(value, priv->battery_threshold);
3644
0
    break;
3645
0
  default:
3646
0
    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
3647
0
    break;
3648
0
  }
3649
0
}
3650
3651
static void
3652
fwupd_device_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
3653
0
{
3654
0
  FwupdDevice *self = FWUPD_DEVICE(object);
3655
0
  switch (prop_id) {
3656
0
  case PROP_VERSION:
3657
0
    fwupd_device_set_version(self, g_value_get_string(value));
3658
0
    break;
3659
0
  case PROP_VENDOR:
3660
0
    fwupd_device_set_vendor(self, g_value_get_string(value));
3661
0
    break;
3662
0
  case PROP_ID:
3663
0
    fwupd_device_set_id(self, g_value_get_string(value));
3664
0
    break;
3665
0
  case PROP_VERSION_FORMAT:
3666
0
    fwupd_device_set_version_format(self, g_value_get_uint(value));
3667
0
    break;
3668
0
  case PROP_FLAGS:
3669
0
    fwupd_device_set_flags(self, g_value_get_uint64(value));
3670
0
    break;
3671
0
  case PROP_PROBLEMS:
3672
0
    fwupd_device_set_problems(self, g_value_get_uint64(value));
3673
0
    break;
3674
0
  case PROP_REQUEST_FLAGS:
3675
0
    fwupd_device_set_request_flags(self, g_value_get_uint64(value));
3676
0
    break;
3677
0
  case PROP_UPDATE_ERROR:
3678
0
    fwupd_device_set_update_error(self, g_value_get_string(value));
3679
0
    break;
3680
0
  case PROP_STATUS:
3681
0
    fwupd_device_set_status(self, g_value_get_uint(value));
3682
0
    break;
3683
0
  case PROP_PERCENTAGE:
3684
0
    fwupd_device_set_percentage(self, g_value_get_uint(value));
3685
0
    break;
3686
0
  case PROP_PARENT:
3687
0
    fwupd_device_set_parent(self, g_value_get_object(value));
3688
0
    break;
3689
0
  case PROP_UPDATE_STATE:
3690
0
    fwupd_device_set_update_state(self, g_value_get_uint(value));
3691
0
    break;
3692
0
  case PROP_BATTERY_LEVEL:
3693
0
    fwupd_device_set_battery_level(self, g_value_get_uint(value));
3694
0
    break;
3695
0
  case PROP_BATTERY_THRESHOLD:
3696
0
    fwupd_device_set_battery_threshold(self, g_value_get_uint(value));
3697
0
    break;
3698
0
  default:
3699
0
    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
3700
0
    break;
3701
0
  }
3702
0
}
3703
3704
static void
3705
fwupd_device_class_init(FwupdDeviceClass *klass)
3706
2
{
3707
2
  GObjectClass *object_class = G_OBJECT_CLASS(klass);
3708
2
  GParamSpec *pspec;
3709
3710
2
  object_class->finalize = fwupd_device_finalize;
3711
2
  object_class->get_property = fwupd_device_get_property;
3712
2
  object_class->set_property = fwupd_device_set_property;
3713
3714
  /**
3715
   * FwupdDevice:version:
3716
   *
3717
   * The device version.
3718
   *
3719
   * Since: 1.8.15
3720
   */
3721
2
  pspec = g_param_spec_string("version",
3722
2
            NULL,
3723
2
            NULL,
3724
2
            NULL,
3725
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3726
2
  g_object_class_install_property(object_class, PROP_VERSION, pspec);
3727
3728
  /**
3729
   * FwupdDevice:vendor:
3730
   *
3731
   * The device vendor.
3732
   *
3733
   * Since: 2.0.17
3734
   */
3735
2
  pspec = g_param_spec_string("vendor",
3736
2
            NULL,
3737
2
            NULL,
3738
2
            NULL,
3739
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3740
2
  g_object_class_install_property(object_class, PROP_VENDOR, pspec);
3741
3742
  /**
3743
   * FwupdDevice:id:
3744
   *
3745
   * The device ID.
3746
   *
3747
   * Since: 2.0.0
3748
   */
3749
2
  pspec =
3750
2
      g_param_spec_string("id", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3751
2
  g_object_class_install_property(object_class, PROP_ID, pspec);
3752
3753
  /**
3754
   * FwupdDevice:version-format:
3755
   *
3756
   * The version format of the device.
3757
   *
3758
   * Since: 1.2.9
3759
   */
3760
2
  pspec = g_param_spec_uint("version-format",
3761
2
          NULL,
3762
2
          NULL,
3763
2
          FWUPD_VERSION_FORMAT_UNKNOWN,
3764
2
          FWUPD_VERSION_FORMAT_LAST,
3765
2
          FWUPD_VERSION_FORMAT_UNKNOWN,
3766
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3767
2
  g_object_class_install_property(object_class, PROP_VERSION_FORMAT, pspec);
3768
3769
  /**
3770
   * FwupdDevice:flags:
3771
   *
3772
   * The device flags.
3773
   *
3774
   * Since: 0.9.3
3775
   */
3776
2
  pspec = g_param_spec_uint64("flags",
3777
2
            NULL,
3778
2
            NULL,
3779
2
            FWUPD_DEVICE_FLAG_NONE,
3780
2
            FWUPD_DEVICE_FLAG_UNKNOWN,
3781
2
            FWUPD_DEVICE_FLAG_NONE,
3782
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3783
2
  g_object_class_install_property(object_class, PROP_FLAGS, pspec);
3784
3785
  /**
3786
   * FwupdDevice:problems:
3787
   *
3788
   * The problems with the device that the user could fix, e.g. "lid open".
3789
   *
3790
   * Since: 1.8.1
3791
   */
3792
2
  pspec = g_param_spec_uint64("problems",
3793
2
            NULL,
3794
2
            NULL,
3795
2
            FWUPD_DEVICE_PROBLEM_NONE,
3796
2
            FWUPD_DEVICE_PROBLEM_UNKNOWN,
3797
2
            FWUPD_DEVICE_PROBLEM_NONE,
3798
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3799
2
  g_object_class_install_property(object_class, PROP_PROBLEMS, pspec);
3800
3801
  /**
3802
   * FwupdDevice:request-flags:
3803
   *
3804
   * The device request flags.
3805
   *
3806
   * Since: 1.9.10
3807
   */
3808
2
  pspec = g_param_spec_uint64("request-flags",
3809
2
            NULL,
3810
2
            NULL,
3811
2
            FWUPD_REQUEST_FLAG_NONE,
3812
2
            FWUPD_REQUEST_FLAG_UNKNOWN,
3813
2
            FWUPD_REQUEST_FLAG_NONE,
3814
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3815
2
  g_object_class_install_property(object_class, PROP_REQUEST_FLAGS, pspec);
3816
3817
  /**
3818
   * FwupdDevice:status:
3819
   *
3820
   * The current device status.
3821
   *
3822
   * Since: 1.4.0
3823
   */
3824
2
  pspec = g_param_spec_uint("status",
3825
2
          NULL,
3826
2
          NULL,
3827
2
          FWUPD_STATUS_UNKNOWN,
3828
2
          FWUPD_STATUS_LAST,
3829
2
          FWUPD_STATUS_UNKNOWN,
3830
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3831
2
  g_object_class_install_property(object_class, PROP_STATUS, pspec);
3832
3833
  /**
3834
   * FwupdDevice:percentage:
3835
   *
3836
   * The current device percentage.
3837
   *
3838
   * Since: 1.8.11
3839
   */
3840
2
  pspec = g_param_spec_uint("percentage",
3841
2
          NULL,
3842
2
          NULL,
3843
2
          0,
3844
2
          100,
3845
2
          0,
3846
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3847
2
  g_object_class_install_property(object_class, PROP_PERCENTAGE, pspec);
3848
3849
  /**
3850
   * FwupdDevice:parent:
3851
   *
3852
   * The device parent.
3853
   *
3854
   * Since: 1.0.8
3855
   */
3856
2
  pspec = g_param_spec_object("parent",
3857
2
            NULL,
3858
2
            NULL,
3859
2
            FWUPD_TYPE_DEVICE,
3860
2
            G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_NAME);
3861
2
  g_object_class_install_property(object_class, PROP_PARENT, pspec);
3862
3863
  /**
3864
   * FwupdDevice:update-state:
3865
   *
3866
   * The device update state.
3867
   *
3868
   * Since: 0.9.8
3869
   */
3870
2
  pspec = g_param_spec_uint("update-state",
3871
2
          NULL,
3872
2
          NULL,
3873
2
          FWUPD_UPDATE_STATE_UNKNOWN,
3874
2
          FWUPD_UPDATE_STATE_LAST,
3875
2
          FWUPD_UPDATE_STATE_UNKNOWN,
3876
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3877
2
  g_object_class_install_property(object_class, PROP_UPDATE_STATE, pspec);
3878
3879
  /**
3880
   * FwupdDevice:update-error:
3881
   *
3882
   * The device update error.
3883
   *
3884
   * Since: 0.9.8
3885
   */
3886
2
  pspec = g_param_spec_string("update-error",
3887
2
            NULL,
3888
2
            NULL,
3889
2
            NULL,
3890
2
            G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3891
2
  g_object_class_install_property(object_class, PROP_UPDATE_ERROR, pspec);
3892
3893
  /**
3894
   * FwupdDevice:battery-level:
3895
   *
3896
   * The device battery level in percent.
3897
   *
3898
   * Since: 1.5.8
3899
   */
3900
2
  pspec = g_param_spec_uint("battery-level",
3901
2
          NULL,
3902
2
          NULL,
3903
2
          0,
3904
2
          FWUPD_BATTERY_LEVEL_INVALID,
3905
2
          FWUPD_BATTERY_LEVEL_INVALID,
3906
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3907
2
  g_object_class_install_property(object_class, PROP_BATTERY_LEVEL, pspec);
3908
3909
  /**
3910
   * FwupdDevice:battery-threshold:
3911
   *
3912
   * The device battery threshold in percent.
3913
   *
3914
   * Since: 1.5.8
3915
   */
3916
2
  pspec = g_param_spec_uint("battery-threshold",
3917
2
          NULL,
3918
2
          NULL,
3919
2
          0,
3920
2
          FWUPD_BATTERY_LEVEL_INVALID,
3921
2
          FWUPD_BATTERY_LEVEL_INVALID,
3922
2
          G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
3923
2
  g_object_class_install_property(object_class, PROP_BATTERY_THRESHOLD, pspec);
3924
2
}
3925
3926
static void
3927
fwupd_device_init(FwupdDevice *self)
3928
1.15k
{
3929
1.15k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3930
1.15k
  priv->battery_level = FWUPD_BATTERY_LEVEL_INVALID;
3931
1.15k
  priv->battery_threshold = FWUPD_BATTERY_LEVEL_INVALID;
3932
1.15k
}
3933
3934
static void
3935
fwupd_device_finalize(GObject *object)
3936
1.15k
{
3937
1.15k
  FwupdDevice *self = FWUPD_DEVICE(object);
3938
1.15k
  FwupdDevicePrivate *priv = GET_PRIVATE(self);
3939
3940
1.15k
  if (priv->parent != NULL)
3941
0
    g_object_remove_weak_pointer(G_OBJECT(priv->parent), (gpointer *)&priv->parent);
3942
1.15k
  if (priv->children != NULL) {
3943
0
    for (guint i = 0; i < priv->children->len; i++) {
3944
0
      FwupdDevice *child = g_ptr_array_index(priv->children, i);
3945
0
      g_object_weak_unref(G_OBJECT(child), fwupd_device_child_finalized_cb, self);
3946
0
    }
3947
0
  }
3948
3949
1.15k
  g_free(priv->id);
3950
1.15k
  g_free(priv->parent_id);
3951
1.15k
  g_free(priv->composite_id);
3952
1.15k
  g_free(priv->name);
3953
1.15k
  g_free(priv->serial);
3954
1.15k
  g_free(priv->summary);
3955
1.15k
  g_free(priv->branch);
3956
1.15k
  g_free(priv->vendor);
3957
1.15k
  g_free(priv->plugin);
3958
1.15k
  g_free(priv->update_error);
3959
1.15k
  g_free(priv->version);
3960
1.15k
  g_free(priv->version_lowest);
3961
1.15k
  g_free(priv->version_bootloader);
3962
1.15k
  if (priv->guids != NULL)
3963
0
    g_ptr_array_unref(priv->guids);
3964
1.15k
  if (priv->vendor_ids != NULL)
3965
0
    g_ptr_array_unref(priv->vendor_ids);
3966
1.15k
  if (priv->protocols != NULL)
3967
271
    g_ptr_array_unref(priv->protocols);
3968
1.15k
  if (priv->instance_ids != NULL)
3969
0
    g_ptr_array_unref(priv->instance_ids);
3970
1.15k
  if (priv->icons != NULL)
3971
0
    g_ptr_array_unref(priv->icons);
3972
1.15k
  if (priv->checksums != NULL)
3973
0
    g_ptr_array_unref(priv->checksums);
3974
1.15k
  if (priv->children != NULL)
3975
0
    g_ptr_array_unref(priv->children);
3976
1.15k
  if (priv->releases != NULL)
3977
0
    g_ptr_array_unref(priv->releases);
3978
1.15k
  if (priv->issues != NULL)
3979
0
    g_ptr_array_unref(priv->issues);
3980
3981
1.15k
  G_OBJECT_CLASS(fwupd_device_parent_class)->finalize(object);
3982
1.15k
}
3983
3984
static void
3985
fwupd_device_from_variant_iter(FwupdCodec *codec, GVariantIter *iter)
3986
0
{
3987
0
  FwupdDevice *self = FWUPD_DEVICE(codec);
3988
0
  GVariant *value;
3989
0
  const gchar *key;
3990
0
  while (g_variant_iter_next(iter, "{&sv}", &key, &value)) {
3991
0
    fwupd_device_from_key_value(self, key, value);
3992
0
    g_variant_unref(value);
3993
0
  }
3994
0
}
3995
3996
static void
3997
fwupd_device_codec_iface_init(FwupdCodecInterface *iface)
3998
2
{
3999
2
  iface->add_string = fwupd_device_add_string;
4000
2
  iface->add_json = fwupd_device_add_json;
4001
2
  iface->from_json = fwupd_device_from_json;
4002
2
  iface->add_variant = fwupd_device_add_variant;
4003
2
  iface->from_variant_iter = fwupd_device_from_variant_iter;
4004
2
}
4005
4006
/**
4007
 * fwupd_device_array_ensure_parents:
4008
 * @devices: (not nullable) (element-type FwupdDevice): devices
4009
 *
4010
 * Sets the parent object on all devices in the array using the parent ID.
4011
 *
4012
 * Since: 1.3.7
4013
 **/
4014
void
4015
fwupd_device_array_ensure_parents(GPtrArray *devices)
4016
0
{
4017
0
  g_autoptr(GHashTable) devices_by_id = NULL;
4018
4019
0
  g_return_if_fail(devices != NULL);
4020
4021
  /* create hash of ID->FwupdDevice */
4022
0
  devices_by_id = g_hash_table_new(g_str_hash, g_str_equal);
4023
0
  for (guint i = 0; i < devices->len; i++) {
4024
0
    FwupdDevice *dev = g_ptr_array_index(devices, i);
4025
0
    if (fwupd_device_get_id(dev) == NULL)
4026
0
      continue;
4027
0
    g_hash_table_insert(devices_by_id,
4028
0
            (gpointer)fwupd_device_get_id(dev),
4029
0
            (gpointer)dev);
4030
0
  }
4031
4032
  /* set the parent on each child */
4033
0
  for (guint i = 0; i < devices->len; i++) {
4034
0
    FwupdDevice *dev = g_ptr_array_index(devices, i);
4035
0
    const gchar *parent_id = fwupd_device_get_parent_id(dev);
4036
0
    if (parent_id != NULL) {
4037
0
      FwupdDevice *dev_tmp;
4038
0
      dev_tmp = g_hash_table_lookup(devices_by_id, parent_id);
4039
0
      if (dev_tmp != NULL)
4040
0
        fwupd_device_set_parent(dev, dev_tmp);
4041
0
    }
4042
0
  }
4043
0
}
4044
4045
/**
4046
 * fwupd_device_compare:
4047
 * @self1: (not nullable): a device
4048
 * @self2: (not nullable): a different device
4049
 *
4050
 * Comparison function for comparing two device objects.
4051
 *
4052
 * Returns: negative, 0 or positive
4053
 *
4054
 * Since: 1.1.1
4055
 **/
4056
gint
4057
fwupd_device_compare(FwupdDevice *self1, FwupdDevice *self2)
4058
0
{
4059
0
  FwupdDevicePrivate *priv1 = GET_PRIVATE(self1);
4060
0
  FwupdDevicePrivate *priv2 = GET_PRIVATE(self2);
4061
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self1), 0);
4062
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self2), 0);
4063
0
  return g_strcmp0(priv1->id, priv2->id);
4064
0
}
4065
4066
/**
4067
 * fwupd_device_match_flags:
4068
 * @include: #FwupdDeviceFlags, or %FWUPD_DEVICE_FLAG_NONE
4069
 * @exclude: #FwupdDeviceFlags, or %FWUPD_DEVICE_FLAG_NONE
4070
 *
4071
 * Check if the device flags match.
4072
 *
4073
 * Returns: %TRUE if the device flags match
4074
 *
4075
 * Since: 1.9.3
4076
 **/
4077
gboolean
4078
fwupd_device_match_flags(FwupdDevice *self, FwupdDeviceFlags include, FwupdDeviceFlags exclude)
4079
0
{
4080
0
  g_return_val_if_fail(FWUPD_IS_DEVICE(self), FALSE);
4081
4082
0
  for (guint i = 0; i < 64; i++) {
4083
0
    FwupdDeviceFlags flag = 1LLU << i;
4084
0
    if ((include & flag) > 0) {
4085
0
      if (!fwupd_device_has_flag(self, flag))
4086
0
        return FALSE;
4087
0
    }
4088
0
    if ((exclude & flag) > 0) {
4089
0
      if (fwupd_device_has_flag(self, flag))
4090
0
        return FALSE;
4091
0
    }
4092
0
  }
4093
0
  return TRUE;
4094
0
}
4095
4096
/**
4097
 * fwupd_device_array_filter_flags:
4098
 * @devices: (not nullable) (element-type FwupdDevice): devices
4099
 * @include: #FwupdDeviceFlags, or %FWUPD_DEVICE_FLAG_NONE
4100
 * @exclude: #FwupdDeviceFlags, or %FWUPD_DEVICE_FLAG_NONE
4101
 * @error: (nullable): optional return location for an error
4102
 *
4103
 * Creates an array of new devices that match using fwupd_device_match_flags().
4104
 *
4105
 * Returns: (transfer container) (element-type FwupdDevice): devices
4106
 *
4107
 * Since: 1.9.3
4108
 **/
4109
GPtrArray *
4110
fwupd_device_array_filter_flags(GPtrArray *devices,
4111
        FwupdDeviceFlags include,
4112
        FwupdDeviceFlags exclude,
4113
        GError **error)
4114
0
{
4115
0
  g_autoptr(GPtrArray) devices_filtered =
4116
0
      g_ptr_array_new_with_free_func((GDestroyNotify)g_object_unref);
4117
4118
0
  g_return_val_if_fail(devices != NULL, NULL);
4119
0
  g_return_val_if_fail(error == NULL || *error == NULL, NULL);
4120
4121
0
  for (guint i = 0; i < devices->len; i++) {
4122
0
    FwupdDevice *device = g_ptr_array_index(devices, i);
4123
0
    if (!fwupd_device_match_flags(device, include, exclude))
4124
0
      continue;
4125
0
    g_ptr_array_add(devices_filtered, g_object_ref(device));
4126
0
  }
4127
0
  if (devices_filtered->len == 0) {
4128
0
    g_set_error_literal(error, FWUPD_ERROR, FWUPD_ERROR_NOTHING_TO_DO, "no devices");
4129
0
    return NULL;
4130
0
  }
4131
0
  return g_steal_pointer(&devices_filtered);
4132
0
}
4133
4134
/**
4135
 * fwupd_device_new:
4136
 *
4137
 * Creates a new device.
4138
 *
4139
 * Returns: a new #FwupdDevice
4140
 *
4141
 * Since: 0.9.3
4142
 **/
4143
FwupdDevice *
4144
fwupd_device_new(void)
4145
0
{
4146
0
  FwupdDevice *self;
4147
0
  self = g_object_new(FWUPD_TYPE_DEVICE, NULL);
4148
0
  return FWUPD_DEVICE(self);
4149
0
}