bolt-device.c 23.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/*
 * Copyright © 2017 Red Hat, Inc
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *       Christian J. Kellner <christian@kellner.me>
 */

#include "config.h"

23
#include "bolt-dbus.h"
24
#include "bolt-device.h"
25
#include "bolt-enums.h"
26
#include "bolt-error.h"
27
#include "bolt-io.h"
28
#include "bolt-manager.h"
29
#include "bolt-store.h"
30
#include "bolt-str.h"
31

32
#include <dirent.h>
33
34
#include <libudev.h>

35
36
37
38
39
/* dbus method calls */
static gboolean    handle_authorize (BoltDBusDevice        *object,
                                     GDBusMethodInvocation *invocation,
                                     gpointer               user_data);

40

41
42
43
44
struct _BoltDevice
{
  BoltDBusDeviceSkeleton object;

45
  /* device props */
46
  char          *dbus_path;
47

48
49
50
  char          *uid;
  char          *name;
  char          *vendor;
51

52
53
  BoltDeviceType type;
  BoltStatus     status;
54

55
  /* when device is attached */
56
57
  char        *syspath;
  BoltSecurity security;
58
  char        *parent;
59
60

  /* when device is stored */
61
  BoltStore   *store;
62
63
  BoltPolicy   policy;
  BoltKeyState key;
64
65
66
67
68
69
};


enum {
  PROP_0,

70
71
72
73
74
  PROP_STORE,

  PROP_LAST,

  /* overridden */
75
  PROP_UID,
76
77
  PROP_NAME,
  PROP_VENDOR,
78
  PROP_TYPE,
79
  PROP_STATUS,
80

81
  PROP_PARENT,
82
  PROP_SYSFS,
83
  PROP_SECURITY,
84

85
86
87
  PROP_STORED,
  PROP_POLICY,
  PROP_HAVE_KEY,
88
89
};

90
static GParamSpec *props[PROP_LAST] = {NULL, };
91

92
93
94
95
96
97
98
enum {
  SIGNAL_STATUS_CHANGED,
  SIGNAL_LAST
};

static guint signals[SIGNAL_LAST] = {0};

99
100
101
102
103
104
105
106
107
G_DEFINE_TYPE (BoltDevice,
               bolt_device,
               BOLT_DBUS_TYPE_DEVICE_SKELETON)

static void
bolt_device_finalize (GObject *object)
{
  BoltDevice *dev = BOLT_DEVICE (object);

108
109
  g_clear_object (&dev->store);

110
111
  g_free (dev->dbus_path);

112
  g_free (dev->uid);
113
114
  g_free (dev->name);
  g_free (dev->vendor);
115
116

  g_free (dev->parent);
117
  g_free (dev->syspath);
118
119
120
121
122

  G_OBJECT_CLASS (bolt_device_parent_class)->finalize (object);
}

static void
123
bolt_device_init (BoltDevice *dev)
124
{
125
126
  g_signal_connect (dev, "handle-authorize",
                    G_CALLBACK (handle_authorize), NULL);
127
128
129
130
131
132
133
134
135
136
137
138
}

static void
bolt_device_get_property (GObject    *object,
                          guint       prop_id,
                          GValue     *value,
                          GParamSpec *pspec)
{
  BoltDevice *dev = BOLT_DEVICE (object);

  switch (prop_id)
    {
139
140
141
142
    case PROP_STORE:
      g_value_set_object (value, dev->store);
      break;

143
144
145
146
    case PROP_UID:
      g_value_set_string (value, dev->uid);
      break;

147
148
149
150
    case PROP_NAME:
      g_value_set_string (value, dev->name);
      break;

151
152
153
154
    case PROP_TYPE:
      g_value_set_uint (value, dev->type);
      break;

155
156
157
158
    case PROP_VENDOR:
      g_value_set_string (value, dev->vendor);
      break;

159
160
161
162
    case PROP_STATUS:
      g_value_set_uint (value, dev->status);
      break;

163
164
165
166
    case PROP_PARENT:
      g_value_set_string (value, dev->parent);
      break;

167
168
169
170
    case PROP_SYSFS:
      g_value_set_string (value, dev->syspath);
      break;

171
172
173
174
    case PROP_SECURITY:
      g_value_set_uint (value, dev->security);
      break;

175
    case PROP_STORED:
176
      g_value_set_boolean (value, dev->store != NULL);
177
178
179
180
181
182
183
184
185
186
      break;

    case PROP_POLICY:
      g_value_set_uint (value, dev->policy);
      break;

    case PROP_HAVE_KEY:
      g_value_set_uint (value, dev->key);
      break;

187
188
189
190
191
192
193
194
195
196
197
198
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}

static void
bolt_device_set_property (GObject      *object,
                          guint         prop_id,
                          const GValue *value,
                          GParamSpec   *pspec)
{
  BoltDevice *dev = BOLT_DEVICE (object);
199
  GParamSpec *parent;
200
201
202

  switch (prop_id)
    {
203
204
    case PROP_STORE:
      dev->store = g_value_dup_object (value);
205
      g_object_set (object, "stored", dev->store != NULL, NULL);
206
207
      break;

208
    case PROP_UID:
209
      g_return_if_fail (dev->uid == NULL);
210
211
212
      dev->uid = g_value_dup_string (value);
      break;

213
    case PROP_NAME:
214
      g_clear_pointer (&dev->name, g_free);
215
      dev->name = g_value_dup_string (value);
216
217
218
      break;

    case PROP_VENDOR:
219
      g_clear_pointer (&dev->vendor, g_free);
220
      dev->vendor = g_value_dup_string (value);
221
222
      break;

223
224
225
226
    case PROP_TYPE:
      dev->type = g_value_get_uint (value);
      break;

227
    case PROP_STATUS:
228
229
230
231
232
233
234
235
236
237
238
239
240
      {
        BoltStatus old = dev->status;
        BoltStatus now = g_value_get_uint (value);
        if (old == now)
          break;

        dev->status = now;
        g_signal_emit (dev,
                       signals[SIGNAL_STATUS_CHANGED],
                       0,
                       old);
        break;
      }
241

242
243
244
245
246
    case PROP_PARENT:
      g_clear_pointer (&dev->parent, g_free);
      dev->parent = g_value_dup_string (value);
      break;

247
    case PROP_SYSFS:
248
      g_clear_pointer (&dev->syspath, g_free);
249
250
      dev->syspath = g_value_dup_string (value);
      break;
251
252
253
254

    case PROP_SECURITY:
      dev->security = g_value_get_uint (value);
      break;
255

256
257
258
259
    case PROP_STORED:
      /* this is just here for the hack below :( */
      break;

260
261
262
263
264
265
266
267
    case PROP_POLICY:
      dev->policy = g_value_get_uint (value);
      break;

    case PROP_HAVE_KEY:
      dev->key = g_value_get_uint (value);
      break;

268
269
270
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304

  /* This is one gross hack to make the DBus property change
   * signal emission work.
   *   The heart "problem" is a combination of two things:
   *   1) the dbus object properties are override here,
   *      which means the property setter from the parent
   *      (the dbus skeleton) will not be called.
   *   2) The dbus skeleton will only emit the signal on the
   *      bus if it finds that the value has changed, which
   *      it can only detect if its property setter was called
   *   => We need to call the skeleton's set_property function
   *      from here, so it can detect property changes itself.
   */

  /* all properties below PROP_LAST are our own, non-dbus props */
  if (prop_id < PROP_LAST)
    return;

  /* we need to original GParamSpec, since the one we got is
   * the new, overridden one */
  parent = g_object_class_find_property (bolt_device_parent_class,
                                         pspec->name);
  if (parent == NULL)
    return;

  /* the prop_id is *our* prop_id, not the parent's prop_id, which
   * we need. For this to work our property list *after* PROP_LAST
   * need to be in sync with the parent */
  prop_id -= PROP_LAST;

  G_OBJECT_CLASS (bolt_device_parent_class)->set_property (object,
                                                           prop_id,
                                                           value,
                                                           parent);
305
306
307
308
309
310
311
312
313
314
315
316
317
}


static void
bolt_device_class_init (BoltDeviceClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->finalize = bolt_device_finalize;

  gobject_class->get_property = bolt_device_get_property;
  gobject_class->set_property = bolt_device_set_property;

318
319
320
321
322
323
324
325
326
327
328
  props[PROP_STORE] =
    g_param_spec_object ("store",
                         NULL, NULL,
                         BOLT_TYPE_STORE,
                         G_PARAM_READWRITE |
                         G_PARAM_STATIC_NICK);

  g_object_class_install_properties (gobject_class,
                                     PROP_LAST,
                                     props);

329
330
331
  g_object_class_override_property (gobject_class,
                                    PROP_UID,
                                    "uid");
332
333
334
335
336
337
338
339
340

  g_object_class_override_property (gobject_class,
                                    PROP_NAME,
                                    "name");

  g_object_class_override_property (gobject_class,
                                    PROP_VENDOR,
                                    "vendor");

341
342
343
344
  g_object_class_override_property (gobject_class,
                                    PROP_TYPE,
                                    "type");

345
346
347
348
  g_object_class_override_property (gobject_class,
                                    PROP_STATUS,
                                    "status");

349
350
351
352
  g_object_class_override_property (gobject_class,
                                    PROP_PARENT,
                                    "parent");

353
354
355
356
  g_object_class_override_property (gobject_class,
                                    PROP_SYSFS,
                                    "sysfs-path");

357
358
359
360
  g_object_class_override_property (gobject_class,
                                    PROP_SECURITY,
                                    "security");

361
362
  g_object_class_override_property (gobject_class,
                                    PROP_STORED,
363
                                    "stored");
364
365
366
367
368
369
370
371
372

  g_object_class_override_property (gobject_class,
                                    PROP_POLICY,
                                    "policy");

  g_object_class_override_property (gobject_class,
                                    PROP_HAVE_KEY,
                                    "key");

373
374
375
376
377
378
379
380
381
382
383

  signals[SIGNAL_STATUS_CHANGED] =
    g_signal_new ("status-changed",
                  G_TYPE_FROM_CLASS (gobject_class),
                  G_SIGNAL_RUN_LAST,
                  0,
                  NULL, NULL,
                  NULL,
                  G_TYPE_NONE,
                  1, BOLT_TYPE_STATUS);

384
}
385
386
387

/* internal methods */

388
389
static const char *
read_sysattr_name (struct udev_device *udev, const char *attr, GError **error)
390
391
{
  g_autofree char *s = NULL;
392
  const char *v;
393
394

  s = g_strdup_printf ("%s_name", attr);
395
396
397
398
399
400
  v = udev_device_get_sysattr_value (udev, s);

  if (v != NULL)
    return v;

  v = udev_device_get_sysattr_value (udev, attr);
401

402
  if (v == NULL)
403
404
405
    g_set_error (error,
                 BOLT_ERROR, BOLT_ERROR_UDEV,
                 "failed to get sysfs attr: %s", attr);
406
407

  return v;
408
409
}

410
411
412
413
414
415
416
417
418
419
420
421
static gint
read_sysfs_attr_int (struct udev_device *device, const char *attr)
{
  const char *str;
  char *end;
  gint64 val;

  str = udev_device_get_sysattr_value (device, attr);

  if (str == NULL)
    return 0;

422
  val = g_ascii_strtoll (str, &end, 0);
423
424
425
426
427
428

  if (str == end)
    return 0;

  if (val > G_MAXINT || val < G_MININT)
    {
429
      g_warning ("value read from sysfs outside of gint's range.");
430
431
432
433
434
435
436
437
438
439
440
441
      val = 0;
    }

  return (gint) val;
}

static gboolean
string_nonzero (const char *str)
{
  return str != NULL && str[0] != '\0';
}

442
443
444
445
446
447
448
449
450
451
452
453
454
static struct udev_device *
bolt_sysfs_get_parent (struct udev_device *udev,
                       GError            **error)
{
  struct udev_device * parent = udev_device_get_parent (udev);

  if (parent == NULL)
    g_set_error (error, BOLT_ERROR, BOLT_ERROR_UDEV,
                 "could not get parent udev device");

  return parent;
}

455
456
457
458
459
460
461
462
463
464
465
466
static const char *
bolt_sysfs_get_parent_uid (struct udev_device *udev)
{
  struct udev_device *parent;
  const char *uid = NULL;

  parent = udev_device_get_parent (udev);
  if (parent)
    uid = udev_device_get_sysattr_value (parent, "unique_id");
  return uid;
}

467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
static BoltStatus
bolt_status_from_udev (struct udev_device *udev)
{
  gint authorized;
  const char *key;
  gboolean have_key;

  authorized = read_sysfs_attr_int (udev, "authorized");

  if (authorized == 2)
    return BOLT_STATUS_AUTHORIZED_SECURE;

  key = udev_device_get_sysattr_value (udev, "key");
  have_key = string_nonzero (key);

  if (authorized == 1)
    {
      if (have_key)
        return BOLT_STATUS_AUTHORIZED_NEWKEY;
      else
        return BOLT_STATUS_AUTHORIZED;
    }
  else if (authorized == 0 && have_key)
    {
      return BOLT_STATUS_AUTH_ERROR;
    }

  return BOLT_STATUS_CONNECTED;
}

497
498
499
500
501
502
503
static gboolean
bolt_sysfs_device_is_domain (struct udev_device *udev)
{
  const char *devtype = udev_device_get_devtype (udev);

  return bolt_streq (devtype, "thunderbolt_domain");
}
504
505

static struct udev_device *
506
bolt_sysfs_domain_for_device (struct udev_device *udev)
507
508
509
510
511
512
513
514
515
516
517
518
{
  struct udev_device *parent;
  gboolean found;

  found = FALSE;
  parent = udev;
  do
    {
      parent = udev_device_get_parent (parent);
      if (!parent)
        break;

519
      found = bolt_sysfs_device_is_domain (parent);
520
521
522
523
524
525
526
    }
  while (!found);

  return found ? parent : NULL;
}

static BoltSecurity
527
bolt_sysfs_security_for_device (struct udev_device *udev)
528
529
530
531
532
{
  struct udev_device *parent = NULL;
  const char *v;
  BoltSecurity s;

533
  parent = bolt_sysfs_domain_for_device (udev);
534
535
536
537
538
539
540
541
542
  if (parent == NULL)
    {
      g_warning ("Failed to determine domain device");
      return BOLT_SECURITY_NONE;
    }

  v = udev_device_get_sysattr_value (parent, "security");
  s = bolt_security_from_string (v);

543
544
545
546
547
548
  if (!bolt_security_validate (s))
    {
      g_warning ("invalid security: %s", v);
      s = BOLT_SECURITY_NONE;
    }

549
550
551
  return s;
}

552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
static const char *
cleanup_name (const char *name,
              const char *vendor,
              GError    **error)
{
  g_return_val_if_fail (vendor != NULL, NULL);
  g_return_val_if_fail (name != NULL, NULL);

  /* some devices have the vendor name as a prefix */
  if (!g_str_has_prefix (name, vendor))
    return name;

  name += strlen (vendor);

  while (g_ascii_isspace (*name))
    name++;

  if (*name == '\0')
    {
      g_set_error_literal (error,
                           BOLT_ERROR, BOLT_ERROR_UDEV,
                           "device has empty name after cleanup");
      return NULL;
    }

  return name;
}

580
581
582
583
/*  device authorization */

typedef struct
{
584
  BoltAuth *auth;
585
586

  /* the outer callback  */
587
588
  GAsyncReadyCallback callback;
  gpointer            user_data;
589
590
591
592
593
594
595
596
597

} AuthData;

static void
auth_data_free (gpointer data)
{
  AuthData *auth = data;

  g_debug ("freeing auth data");
598
  g_clear_object (&auth->auth);
599
600
601
  g_slice_free (AuthData, auth);
}

602
603
static gboolean
authorize_device_internal (BoltDevice *dev,
604
                           BoltAuth   *auth,
605
                           GError    **error)
606
607
{
  g_autoptr(DIR) devdir = NULL;
608
609
  BoltKey *key;
  BoltSecurity level;
610
611
  gboolean ok;

612
613
614
  key = bolt_auth_get_key (auth);
  level = bolt_auth_get_level (auth);

615
  devdir = bolt_opendir (dev->syspath, error);
616
  if (devdir == NULL)
617
    return FALSE;
618

619
  ok = bolt_verify_uid (dirfd (devdir), dev->uid, error);
620
  if (!ok)
621
622
    return FALSE;

623
  if (key)
624
    {
625
626
627
628
629
630
631
      int keyfd;

      g_debug ("[%s] writing key", dev->uid);
      keyfd = bolt_openat (dirfd (devdir), "key", O_WRONLY | O_CLOEXEC, error);
      if (keyfd < 0)
        return FALSE;

632
      ok = bolt_key_write_to (key, keyfd, &level, error);
633
634
635
      close (keyfd);
      if (!ok)
        return FALSE;
636
637
    }

638
  g_debug ("[%s] writing authorization", dev->uid);
639
640
  ok = bolt_write_char_at (dirfd (devdir),
                           "authorized",
641
                           level,
642
643
644
645
646
647
648
649
650
651
652
653
                           error);
  return ok;
}

static void
authorize_in_thread (GTask        *task,
                     gpointer      source,
                     gpointer      context,
                     GCancellable *cancellable)
{
  g_autoptr(GError) error = NULL;
  BoltDevice *dev = source;
654
655
  AuthData *auth_data = context;
  BoltAuth *auth = auth_data->auth;
656
657
658
  gboolean ok;

  ok = authorize_device_internal (dev, auth, &error);
659
660

  if (!ok)
661
662
663
    g_task_return_new_error (task, BOLT_ERROR, BOLT_ERROR_FAILED,
                             "failed to authorize device: %s",
                             error->message);
664
  else
665
    g_task_return_boolean (task, TRUE);
666
667
668
669
670
671
672
}

static void
authorize_thread_done (GObject      *object,
                       GAsyncResult *res,
                       gpointer      user_data)
{
673
  g_autoptr(GError) error = NULL;
674
675
  BoltDevice *dev = BOLT_DEVICE (object);
  GTask *task = G_TASK (res);
676
  BoltStatus status;
677
678
  AuthData *auth_data;
  BoltAuth *auth;
679
680
  gboolean ok;

681
682
683
  auth_data = g_task_get_task_data (task);
  auth = auth_data->auth;

684
685
  ok = g_task_propagate_boolean (task, &error);

686
  if (!ok)
687
688
689
690
    bolt_auth_return_error (auth, &error);

  status = bolt_auth_to_status (auth);
  g_object_set (dev, "status", status, NULL);
691

692
693
694
695
  if (auth_data->callback)
    auth_data->callback (G_OBJECT (dev),
                         G_ASYNC_RESULT (auth),
                         auth_data->user_data);
696
697
}

698
699
700
701
702
void
bolt_device_authorize (BoltDevice         *dev,
                       BoltAuth           *auth,
                       GAsyncReadyCallback callback,
                       gpointer            user_data)
703
704
705
706
{
  AuthData *auth_data;
  GTask *task;

707
708
  g_object_set (auth, "device", dev, NULL);

709
710
711
  if (dev->status != BOLT_STATUS_CONNECTED &&
      dev->status != BOLT_STATUS_AUTH_ERROR)
    {
712
713
      bolt_auth_return_new_error (auth, BOLT_ERROR, BOLT_ERROR_FAILED,
                                  "wrong device state: %u", dev->status);
714

715
716
      if (callback)
        callback (G_OBJECT (dev), G_ASYNC_RESULT (auth), user_data);
717

718
      return;
719
720
721
    }

  task = g_task_new (dev, NULL, authorize_thread_done, NULL);
722
723
724
  auth_data = g_slice_new (AuthData);
  auth_data->callback = callback;
  auth_data->user_data = user_data;
725
  auth_data->auth = g_object_ref (auth);
726
727
  g_task_set_task_data (task, auth_data, auth_data_free);

728
  g_object_set (dev, "status", BOLT_STATUS_AUTHORIZING, NULL);
729
730
731
732
733
734
735
736
737

  g_task_run_in_thread (task, authorize_in_thread);
  g_object_unref (task);
}


/* dbus methods */

static void
738
739
740
handle_authorize_done (GObject      *device,
                       GAsyncResult *res,
                       gpointer      user_data)
741
{
742
743
744
745
746
747
748
749
750
  GDBusMethodInvocation *inv;
  GError *error = NULL;
  BoltAuth *auth;
  BoltDevice *dev;
  gboolean ok;

  dev = BOLT_DEVICE (device);
  inv  = user_data;
  auth = BOLT_AUTH (res);
751

752
  ok = bolt_auth_check (auth, &error);
753
  if (ok)
754
    bolt_dbus_device_complete_authorize (BOLT_DBUS_DEVICE (dev), inv);
755
  else
756
    g_dbus_method_invocation_take_error (inv, error);
757
758
759
760
}

static gboolean
handle_authorize (BoltDBusDevice        *object,
761
                  GDBusMethodInvocation *inv,
762
763
764
765
                  gpointer               user_data)
{
  BoltDevice *dev = BOLT_DEVICE (object);
  GError *error = NULL;
766
767
768
  BoltAuth *auth;
  BoltSecurity level;
  BoltKey *key;
769

770
771
  level = dev->security;
  key = NULL;
772

773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
  if (level == BOLT_SECURITY_SECURE)
    {
      if (dev->key)
        key = bolt_store_get_key (dev->store, dev->uid, &error);
      else
        level = BOLT_SECURITY_USER;
    }

  if (level == BOLT_SECURITY_SECURE && key == NULL)
    {
      g_dbus_method_invocation_take_error (inv, error);
      return TRUE;
    }

  auth = bolt_auth_new (dev, level, key);
  bolt_device_authorize (dev, auth, handle_authorize_done, inv);
789
790
791
792

  return TRUE;
}

793
794
795
/* public methods */

BoltDevice *
796
bolt_device_new_for_udev (struct udev_device *udev,
797
798
                          GError            **error)
{
799
  struct udev_device *parent_dev;
800
801
802
803
  const char *uid;
  const char *name;
  const char *vendor;
  const char *syspath;
804
  const char *parent;
805
  BoltDeviceType type;
806
  BoltDevice *dev;
807

808
809
810
811
812
813
814
  uid = udev_device_get_sysattr_value (udev, "unique_id");
  if (udev == NULL)
    {
      g_set_error (error, BOLT_ERROR, BOLT_ERROR_UDEV,
                   "could not get unique_id for udev");
      return NULL;
    }
815

816
817
  syspath = udev_device_get_syspath (udev);
  g_return_val_if_fail (syspath != NULL, NULL);
818

819
  name = read_sysattr_name (udev, "device", error);
820
821
822
  if (name == NULL)
    return NULL;

823
  vendor = read_sysattr_name (udev, "vendor", error);
824
825
  if (vendor == NULL)
    return NULL;
826

827
828
829
830
  name = cleanup_name (name, vendor, error);
  if (name == NULL)
    return NULL;

831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
  parent_dev = bolt_sysfs_get_parent (udev, error);
  if (parent_dev == NULL)
    return NULL;

  if (bolt_sysfs_device_is_domain (parent_dev))
    {
      parent = NULL;
      type = BOLT_DEVICE_HOST;
    }
  else
    {
      parent = udev_device_get_sysattr_value (parent_dev, "unique_id");
      type = BOLT_DEVICE_PERIPHERAL;
    }

846
  parent = bolt_sysfs_get_parent_uid (udev);
847
  dev = g_object_new (BOLT_TYPE_DEVICE,
848
849
850
                      "uid", uid,
                      "name", name,
                      "vendor", vendor,
851
                      "type", type,
852
                      "sysfs-path", syspath,
853
                      "parent", parent,
854
855
                      NULL);

856
  dev->status = bolt_status_from_udev (udev);
857
  dev->security = bolt_sysfs_security_for_device (udev);
858

859
860
861
  return dev;
}

862
const char *
863
864
865
866
bolt_device_export (BoltDevice      *device,
                    GDBusConnection *connection,
                    GError         **error)
{
867
  const char *path;
868
  gboolean ok;
869
870

  g_return_val_if_fail (BOLT_IS_DEVICE (device), FALSE);
871

872
  path = bolt_device_get_object_path (device);
873

874
875
876
877
878
  ok = g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (device),
                                         connection,
                                         path,
                                         error);
  return ok ? path : NULL;
879
880
881
882
883
884
885
}

void
bolt_device_unexport (BoltDevice *device)
{
  g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (device));
}
886

887
888
889
890
891
892

BoltStatus
bolt_device_connected (BoltDevice         *dev,
                       struct udev_device *udev)
{
  const char *syspath;
893
  const char *parent;
894
895
896
897
898
  BoltSecurity security;
  BoltStatus status;

  syspath = udev_device_get_syspath (udev);
  status = bolt_status_from_udev (udev);
899
  security = bolt_sysfs_security_for_device (udev);
900
  parent = bolt_sysfs_get_parent_uid (udev);
901
902

  g_object_set (G_OBJECT (dev),
903
                "parent", parent,
904
905
906
907
908
                "sysfs-path", syspath,
                "security", security,
                "status", status,
                NULL);

909
910
  g_debug ("[%s] parent is %s", dev->uid, dev->parent);

911
912
913
914
915
916
917
  return status;
}

BoltStatus
bolt_device_disconnected (BoltDevice *dev)
{
  g_object_set (G_OBJECT (dev),
918
                "parent", NULL,
919
920
921
922
923
                "sysfs-path", NULL,
                "security", BOLT_SECURITY_NONE,
                "status", BOLT_STATUS_DISCONNECTED,
                NULL);

924
925
926
927
928
  /* check if we have a new key for the device, and
   * if so, change its state to KEY_HAVE, because
   * now it is not new anymore.
   */
  if (dev->key == BOLT_KEY_NEW)
929
    g_object_set (G_OBJECT (dev), "key", BOLT_KEY_HAVE, NULL);
930

931
932
933
934
  return dev->status;
}

gboolean
935
bolt_device_is_connected (const BoltDevice *device)
936
{
937
  return bolt_status_is_connected (device->status);
938
939
}

940
941
942
943
944
945
946
947
948
949
950
951
952
BoltStatus
bolt_device_update_from_udev (BoltDevice         *dev,
                              struct udev_device *udev)
{
  BoltStatus status = bolt_status_from_udev (udev);

  g_object_set (G_OBJECT (dev),
                "status", status,
                NULL);

  return status;
}

953
BoltKeyState
954
bolt_device_get_keystate (const BoltDevice *dev)
955
956
957
958
{
  return dev->key;
}

959
const char *
960
bolt_device_get_name (const BoltDevice *dev)
961
962
963
964
{
  return dev->name;
}

965
966
967
968
969
970
971
972
973
const char *
bolt_device_get_object_path (BoltDevice *device)
{
  g_return_val_if_fail (BOLT_IS_DEVICE (device), FALSE);

  if (device->dbus_path == NULL)
    {
      char *path = NULL;

974
      path = g_strdup_printf (BOLT_DBUS_PATH "/devices/%s", device->uid);
975
976
977
978
979
980
981
      g_strdelimit (path, "-", '_');

      device->dbus_path = path;
    }

  return device->dbus_path;
}
982

983
BoltPolicy
984
bolt_device_get_policy (const BoltDevice *dev)
985
986
987
988
{
  return dev->policy;
}

989
const char *
990
bolt_device_get_uid (const BoltDevice *dev)
991
992
993
994
{
  return dev->uid;
}

995
BoltSecurity
996
bolt_device_get_security (const BoltDevice *dev)
997
998
999
1000
{
  return dev->security;
}

Christian Kellner's avatar
Christian Kellner committed
1001
BoltStatus
1002
bolt_device_get_status (const BoltDevice *dev)
Christian Kellner's avatar
Christian Kellner committed
1003
1004
1005
1006
{
  return dev->status;
}

1007
gboolean
1008
bolt_device_get_stored (const BoltDevice *dev)
1009
{
1010
  return dev->store != NULL;
1011
1012
}

1013
const char *
1014
bolt_device_get_syspath (const BoltDevice *dev)
1015
1016
1017
{
  return dev->syspath;
}
1018
1019

const char *
1020
bolt_device_get_vendor (const BoltDevice *dev)
1021
1022
1023
{
  return dev->vendor;
}
1024
1025
1026
1027
1028
1029

BoltDeviceType
bolt_device_get_device_type (const BoltDevice *dev)
{
  return dev->type;
}