bolt-device.c 24.1 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
23
/*
 * 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"

#include "bolt-device.h"
24

25
#include "bolt-enums.h"
26
#include "bolt-error.h"
27
#include "bolt-io.h"
28
#include "bolt-log.h"
29
#include "bolt-manager.h"
30
#include "bolt-names.h"
31
#include "bolt-store.h"
32
#include "bolt-str.h"
33

34
#include <dirent.h>
35
36
#include <libudev.h>

37
/* dbus method calls */
38
39
40
static gboolean    handle_authorize (BoltExported          *object,
                                     GVariant              *params,
                                     GDBusMethodInvocation *invocation);
41

42

43
44
struct _BoltDevice
{
45
  BoltExported object;
46

47
  /* device props */
48
  char          *dbus_path;
49

50
51
52
  char          *uid;
  char          *name;
  char          *vendor;
53

54
55
  BoltDeviceType type;
  BoltStatus     status;
56

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

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


enum {
  PROP_0,

72
73
  PROP_STORE,

74
  /* exported properties start here, */
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

  PROP_LAST,
  PROP_EXPORTED = PROP_UID
91
92
};

93
static GParamSpec *props[PROP_LAST] = {NULL, };
94

95
96
97
98
99
100
101
enum {
  SIGNAL_STATUS_CHANGED,
  SIGNAL_LAST
};

static guint signals[SIGNAL_LAST] = {0};

102
103
G_DEFINE_TYPE (BoltDevice,
               bolt_device,
104
               BOLT_TYPE_EXPORTED)
105
106
107
108
109
110

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

111
112
  g_clear_object (&dev->store);

113
114
  g_free (dev->dbus_path);

115
  g_free (dev->uid);
116
117
  g_free (dev->name);
  g_free (dev->vendor);
118
119

  g_free (dev->parent);
120
  g_free (dev->syspath);
121
122
123
124
125

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

static void
126
bolt_device_init (BoltDevice *dev)
127
128
129
130
131
132
133
134
135
136
137
138
139
{
}

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

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

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

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

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

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

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

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

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

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

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

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

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

188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
    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);

  switch (prop_id)
    {
203
204
    case PROP_STORE:
      dev->store = g_value_dup_object (value);
205
      g_object_notify_by_pspec (object, props[PROP_STORED]);
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
260
261
262
263
    case PROP_POLICY:
      dev->policy = g_value_get_uint (value);
      break;

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

264
265
266
267
268
269
270
271
272
273
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
}


static void
bolt_device_class_init (BoltDeviceClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
274
  BoltExportedClass *exported_class = BOLT_EXPORTED_CLASS (klass);
275
276
277
278
279
280

  gobject_class->finalize = bolt_device_finalize;

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

281
282
283
284
285
  props[PROP_STORE] =
    g_param_spec_object ("store",
                         NULL, NULL,
                         BOLT_TYPE_STORE,
                         G_PARAM_READWRITE |
286
                         G_PARAM_STATIC_STRINGS);
287

288
289
290
291
292
293
294
  props[PROP_UID] =
    g_param_spec_string ("uid",
                         "Uid", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_STRINGS);
295

296
297
298
299
300
301
302
  props[PROP_NAME] =
    g_param_spec_string ("name",
                         "Name", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_STRINGS);
303

304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
  props[PROP_VENDOR] =
    g_param_spec_string ("vendor",
                         "Vendor", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_CONSTRUCT_ONLY |
                         G_PARAM_STATIC_STRINGS);

  props[PROP_TYPE] =
    g_param_spec_uint ("type",
                       "Type", NULL,
                       BOLT_DEVICE_HOST,
                       BOLT_DEVICE_PERIPHERAL,
                       BOLT_DEVICE_PERIPHERAL,
                       G_PARAM_READWRITE |
                       G_PARAM_CONSTRUCT_ONLY |
                       G_PARAM_STATIC_STRINGS);

  props[PROP_STATUS] =
    g_param_spec_uint ("status",
                       "Status", NULL,
                       0,
                       BOLT_STATUS_LAST,
                       BOLT_STATUS_DISCONNECTED,
                       G_PARAM_READWRITE |
                       G_PARAM_STATIC_STRINGS);

  props[PROP_PARENT] =
    g_param_spec_string ("parent",
                         "Parent", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_STATIC_STRINGS);
337

338
339
340
341
342
343
  props[PROP_SYSFS] =
    g_param_spec_string ("sysfs-path",
                         "SysfsPath", NULL,
                         NULL,
                         G_PARAM_READWRITE |
                         G_PARAM_STATIC_STRINGS);
344

345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
  props[PROP_SECURITY] =
    g_param_spec_uint ("security",
                       "Security", NULL,
                       0,
                       BOLT_SECURITY_LAST,
                       BOLT_SECURITY_NONE,
                       G_PARAM_READWRITE |
                       G_PARAM_STATIC_STRINGS);

  props[PROP_STORED] =
    g_param_spec_boolean ("stored",
                          "Stored", NULL,
                          FALSE,
                          G_PARAM_READWRITE |
                          G_PARAM_STATIC_STRINGS);

  props[PROP_POLICY] =
    g_param_spec_uint ("policy",
                       "Policy", NULL,
                       0,
                       BOLT_POLICY_LAST,
                       BOLT_POLICY_DEFAULT,
                       G_PARAM_READWRITE |
                       G_PARAM_STATIC_STRINGS);

  props[PROP_HAVE_KEY] =
    g_param_spec_uint ("key",
                       "Key", NULL,
                       0,
                       BOLT_KEY_NEW,
                       BOLT_KEY_MISSING,
                       G_PARAM_READWRITE |
                       G_PARAM_STATIC_STRINGS);
378

379
380
381
  g_object_class_install_properties (gobject_class,
                                     PROP_LAST,
                                     props);
382
383
384
385
386
387
388
389
390
391
392

  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);

393
394
395
396
397
398
399
400
401
402
403
404
405
  bolt_exported_class_set_interface_info (exported_class,
                                          BOLT_DBUS_DEVICE_INTERFACE,
                                          "/boltd/org.freedesktop.bolt.xml");

  bolt_exported_class_export_properties (exported_class,
                                         PROP_EXPORTED,
                                         PROP_LAST,
                                         props);

  bolt_exported_class_export_method (exported_class,
                                     "Authorize",
                                     handle_authorize);

406
}
407
408
409

/* internal methods */

410
411
static const char *
read_sysattr_name (struct udev_device *udev, const char *attr, GError **error)
412
413
{
  g_autofree char *s = NULL;
414
  const char *v;
415
416

  s = g_strdup_printf ("%s_name", attr);
417
418
419
420
421
422
  v = udev_device_get_sysattr_value (udev, s);

  if (v != NULL)
    return v;

  v = udev_device_get_sysattr_value (udev, attr);
423

424
  if (v == NULL)
425
426
427
    g_set_error (error,
                 BOLT_ERROR, BOLT_ERROR_UDEV,
                 "failed to get sysfs attr: %s", attr);
428
429

  return v;
430
431
}

432
433
434
435
436
437
438
439
440
441
442
443
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;

444
  val = g_ascii_strtoll (str, &end, 0);
445
446
447
448
449
450

  if (str == end)
    return 0;

  if (val > G_MAXINT || val < G_MININT)
    {
451
      bolt_warn ("value read from sysfs outside of gint's range.");
452
453
454
455
456
457
458
459
460
461
462
463
      val = 0;
    }

  return (gint) val;
}

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

464
465
466
467
468
469
470
471
472
473
474
475
476
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;
}

477
478
479
480
481
482
483
484
485
486
487
488
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;
}

489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
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;
}

519
520
521
522
523
524
525
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");
}
526
527

static struct udev_device *
528
bolt_sysfs_domain_for_device (struct udev_device *udev)
529
530
531
532
533
534
535
536
537
538
539
540
{
  struct udev_device *parent;
  gboolean found;

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

541
      found = bolt_sysfs_device_is_domain (parent);
542
543
544
545
546
547
548
    }
  while (!found);

  return found ? parent : NULL;
}

static BoltSecurity
549
bolt_sysfs_security_for_device (struct udev_device *udev)
550
551
552
553
554
{
  struct udev_device *parent = NULL;
  const char *v;
  BoltSecurity s;

555
  parent = bolt_sysfs_domain_for_device (udev);
556
557
  if (parent == NULL)
    {
558
      bolt_warn ("failed to determine domain device");
559
560
561
562
563
564
      return BOLT_SECURITY_NONE;
    }

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

565
566
  if (!bolt_security_validate (s))
    {
567
      bolt_warn ("invalid security: %s", v);
568
569
570
      s = BOLT_SECURITY_NONE;
    }

571
572
573
  return s;
}

574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
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;
}

602
603
604
605
/*  device authorization */

typedef struct
{
606
  BoltAuth *auth;
607
608

  /* the outer callback  */
609
610
  GAsyncReadyCallback callback;
  gpointer            user_data;
611
612
613
614
615
616
617
618

} AuthData;

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

619
  g_clear_object (&auth->auth);
620
621
622
  g_slice_free (AuthData, auth);
}

623
624
static gboolean
authorize_device_internal (BoltDevice *dev,
625
                           BoltAuth   *auth,
626
                           GError    **error)
627
628
{
  g_autoptr(DIR) devdir = NULL;
629
630
  BoltKey *key;
  BoltSecurity level;
631
632
  gboolean ok;

633
634
635
  key = bolt_auth_get_key (auth);
  level = bolt_auth_get_level (auth);

636
  devdir = bolt_opendir (dev->syspath, error);
637
  if (devdir == NULL)
638
    return FALSE;
639

640
  ok = bolt_verify_uid (dirfd (devdir), dev->uid, error);
641
  if (!ok)
642
643
    return FALSE;

644
  if (key)
645
    {
646
647
      int keyfd;

648
      bolt_debug (LOG_DEV (dev), "writing key");
649
650
651
652
      keyfd = bolt_openat (dirfd (devdir), "key", O_WRONLY | O_CLOEXEC, error);
      if (keyfd < 0)
        return FALSE;

653
      ok = bolt_key_write_to (key, keyfd, &level, error);
654
655
656
      close (keyfd);
      if (!ok)
        return FALSE;
657
658
    }

659
  bolt_debug (LOG_DEV (dev), "writing authorization");
660
661
  ok = bolt_write_char_at (dirfd (devdir),
                           "authorized",
662
                           level,
663
664
665
666
667
668
669
670
671
672
673
674
                           error);
  return ok;
}

static void
authorize_in_thread (GTask        *task,
                     gpointer      source,
                     gpointer      context,
                     GCancellable *cancellable)
{
  g_autoptr(GError) error = NULL;
  BoltDevice *dev = source;
675
676
  AuthData *auth_data = context;
  BoltAuth *auth = auth_data->auth;
677
678
679
  gboolean ok;

  ok = authorize_device_internal (dev, auth, &error);
680
681

  if (!ok)
682
683
684
    g_task_return_new_error (task, BOLT_ERROR, BOLT_ERROR_FAILED,
                             "failed to authorize device: %s",
                             error->message);
685
  else
686
    g_task_return_boolean (task, TRUE);
687
688
689
690
691
692
693
}

static void
authorize_thread_done (GObject      *object,
                       GAsyncResult *res,
                       gpointer      user_data)
{
694
  g_autoptr(GError) error = NULL;
695
696
  BoltDevice *dev = BOLT_DEVICE (object);
  GTask *task = G_TASK (res);
697
  BoltStatus status;
698
699
  AuthData *auth_data;
  BoltAuth *auth;
700
701
  gboolean ok;

702
703
704
  auth_data = g_task_get_task_data (task);
  auth = auth_data->auth;

705
706
  ok = g_task_propagate_boolean (task, &error);

707
  if (!ok)
708
709
710
711
    bolt_auth_return_error (auth, &error);

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

713
714
715
716
  if (auth_data->callback)
    auth_data->callback (G_OBJECT (dev),
                         G_ASYNC_RESULT (auth),
                         auth_data->user_data);
717
718
}

719
720
721
722
723
void
bolt_device_authorize (BoltDevice         *dev,
                       BoltAuth           *auth,
                       GAsyncReadyCallback callback,
                       gpointer            user_data)
724
725
726
727
{
  AuthData *auth_data;
  GTask *task;

728
729
  g_object_set (auth, "device", dev, NULL);

730
731
732
  if (dev->status != BOLT_STATUS_CONNECTED &&
      dev->status != BOLT_STATUS_AUTH_ERROR)
    {
733
734
      bolt_auth_return_new_error (auth, BOLT_ERROR, BOLT_ERROR_FAILED,
                                  "wrong device state: %u", dev->status);
735

736
737
      if (callback)
        callback (G_OBJECT (dev), G_ASYNC_RESULT (auth), user_data);
738

739
      return;
740
741
742
    }

  task = g_task_new (dev, NULL, authorize_thread_done, NULL);
743
744
745
  auth_data = g_slice_new (AuthData);
  auth_data->callback = callback;
  auth_data->user_data = user_data;
746
  auth_data->auth = g_object_ref (auth);
747
748
  g_task_set_task_data (task, auth_data, auth_data_free);

749
  g_object_set (dev, "status", BOLT_STATUS_AUTHORIZING, NULL);
750
751
752
753
754
755
756
757
758

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


/* dbus methods */

static void
759
760
761
handle_authorize_done (GObject      *device,
                       GAsyncResult *res,
                       gpointer      user_data)
762
{
763
764
765
766
767
768
769
  GDBusMethodInvocation *inv;
  GError *error = NULL;
  BoltAuth *auth;
  gboolean ok;

  inv  = user_data;
  auth = BOLT_AUTH (res);
770

771
  ok = bolt_auth_check (auth, &error);
772
  if (ok)
773
    g_dbus_method_invocation_return_value (inv, g_variant_new ("()"));
774
  else
775
    g_dbus_method_invocation_take_error (inv, error);
776
777
778
}

static gboolean
779
780
781
handle_authorize (BoltExported          *object,
                  GVariant              *params,
                  GDBusMethodInvocation *inv)
782
783
784
{
  BoltDevice *dev = BOLT_DEVICE (object);
  GError *error = NULL;
785
786
787
  BoltAuth *auth;
  BoltSecurity level;
  BoltKey *key;
788

789
790
  level = dev->security;
  key = NULL;
791

792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
  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);
808
809
810
811

  return TRUE;
}

812
813
814
/* public methods */

BoltDevice *
815
bolt_device_new_for_udev (struct udev_device *udev,
816
817
                          GError            **error)
{
818
  struct udev_device *parent_dev;
819
820
821
822
  const char *uid;
  const char *name;
  const char *vendor;
  const char *syspath;
823
  const char *parent;
824
  BoltDeviceType type;
825
  BoltDevice *dev;
826

827
828
829
830
831
832
833
  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;
    }
834

835
836
  syspath = udev_device_get_syspath (udev);
  g_return_val_if_fail (syspath != NULL, NULL);
837

838
  name = read_sysattr_name (udev, "device", error);
839
840
841
  if (name == NULL)
    return NULL;

842
  vendor = read_sysattr_name (udev, "vendor", error);
843
844
  if (vendor == NULL)
    return NULL;
845

846
847
848
849
  name = cleanup_name (name, vendor, error);
  if (name == NULL)
    return NULL;

850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
  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;
    }

865
  parent = bolt_sysfs_get_parent_uid (udev);
866
  dev = g_object_new (BOLT_TYPE_DEVICE,
867
868
869
                      "uid", uid,
                      "name", name,
                      "vendor", vendor,
870
                      "type", type,
871
                      "sysfs-path", syspath,
872
                      "parent", parent,
873
874
                      NULL);

875
  dev->status = bolt_status_from_udev (udev);
876
  dev->security = bolt_sysfs_security_for_device (udev);
877

878
879
880
  return dev;
}

881
const char *
882
883
884
885
bolt_device_export (BoltDevice      *device,
                    GDBusConnection *connection,
                    GError         **error)
{
886
  const char *path;
887
  gboolean ok;
888
889

  g_return_val_if_fail (BOLT_IS_DEVICE (device), FALSE);
890

891
  path = bolt_device_get_object_path (device);
892

893
894
895
896
897
  ok = bolt_exported_export (BOLT_EXPORTED (device),
                             connection,
                             path,
                             error);

898
  return ok ? path : NULL;
899
900
901
902
903
}

void
bolt_device_unexport (BoltDevice *device)
{
904
  bolt_exported_unexport (BOLT_EXPORTED (device));
905
}
906

907
908
909
910
911
912

BoltStatus
bolt_device_connected (BoltDevice         *dev,
                       struct udev_device *udev)
{
  const char *syspath;
913
  const char *parent;
914
915
916
917
918
  BoltSecurity security;
  BoltStatus status;

  syspath = udev_device_get_syspath (udev);
  status = bolt_status_from_udev (udev);
919
  security = bolt_sysfs_security_for_device (udev);
920
  parent = bolt_sysfs_get_parent_uid (udev);
921
922

  g_object_set (G_OBJECT (dev),
923
                "parent", parent,
924
925
926
927
928
                "sysfs-path", syspath,
                "security", security,
                "status", status,
                NULL);

929
  bolt_info (LOG_DEV (dev), "parent is %s", dev->parent);
930

931
932
933
934
935
936
937
  return status;
}

BoltStatus
bolt_device_disconnected (BoltDevice *dev)
{
  g_object_set (G_OBJECT (dev),
938
                "parent", NULL,
939
940
941
942
943
                "sysfs-path", NULL,
                "security", BOLT_SECURITY_NONE,
                "status", BOLT_STATUS_DISCONNECTED,
                NULL);

944
945
946
947
948
  /* 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)
949
    g_object_set (G_OBJECT (dev), "key", BOLT_KEY_HAVE, NULL);
950

951
952
953
954
  return dev->status;
}

gboolean
955
bolt_device_is_connected (const BoltDevice *device)
956
{
957
  return bolt_status_is_connected (device->status);
958
959
}

960
961
962
963
964
965
966
967
968
969
970
971
972
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;
}

973
BoltKeyState
974
bolt_device_get_keystate (const BoltDevice *dev)
975
976
977
978
{
  return dev->key;
}

979
const char *
980
bolt_device_get_name (const BoltDevice *dev)
981
982
983
984
{
  return dev->name;
}

985
986
987
988
989
990
991
992
993
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;

994
      path = g_strdup_printf (BOLT_DBUS_PATH "/devices/%s", device->uid);
995
996
997
998
999
1000
1001
      g_strdelimit (path, "-", '_');

      device->dbus_path = path;
    }

  return device->dbus_path;
}
1002

1003
BoltPolicy
1004
bolt_device_get_policy (const BoltDevice *dev)
1005
1006
1007
1008
{
  return dev->policy;
}

1009
const char *
1010
bolt_device_get_uid (const BoltDevice *dev)
1011
1012
1013
1014
{
  return dev->uid;
}

1015
BoltSecurity
1016
bolt_device_get_security (const BoltDevice *dev)
1017
1018
1019
1020
{
  return dev->security;
}

Christian Kellner's avatar
Christian Kellner committed
1021
BoltStatus
1022
bolt_device_get_status (const BoltDevice *dev)
Christian Kellner's avatar
Christian Kellner committed
1023
1024
1025
1026
{
  return dev->status;
}

1027
gboolean
1028
bolt_device_get_stored (const BoltDevice *dev)
1029
{
1030
  return dev->store != NULL;
1031
1032
}

1033
const char *
1034
bolt_device_get_syspath (const BoltDevice *dev)
1035
1036
1037
{
  return dev->syspath;
}
1038
1039

const char *
1040
bolt_device_get_vendor (const BoltDevice *dev)
1041
1042
1043
{
  return dev->vendor;
}
1044
1045
1046
1047
1048
1049

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