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