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 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 38 39 40 41
/* dbus method calls */
static gboolean    handle_authorize (BoltDBusDevice        *object,
                                     GDBusMethodInvocation *invocation,
                                     gpointer               user_data);

42

43 44 45 46
struct _BoltDevice
{
  BoltDBusDeviceSkeleton object;

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 74 75 76
  PROP_STORE,

  PROP_LAST,

  /* overridden */
77
  PROP_UID,
78 79
  PROP_NAME,
  PROP_VENDOR,
80
  PROP_TYPE,
81
  PROP_STATUS,
82

83
  PROP_PARENT,
84
  PROP_SYSFS,
85
  PROP_SECURITY,
86

87 88 89
  PROP_STORED,
  PROP_POLICY,
  PROP_HAVE_KEY,
90 91
};

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

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

static guint signals[SIGNAL_LAST] = {0};

101 102 103 104 105 106 107 108 109
G_DEFINE_TYPE (BoltDevice,
               bolt_device,
               BOLT_DBUS_TYPE_DEVICE_SKELETON)

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

110 111
  g_clear_object (&dev->store);

112 113
  g_free (dev->dbus_path);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

229
    case PROP_STATUS:
230 231 232 233 234 235 236 237 238 239 240 241 242
      {
        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;
      }
243

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

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

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

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

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

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

270 271 272
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
    }
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 305 306

  /* 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);
307 308 309 310 311 312 313 314 315 316 317 318 319
}


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;

320 321 322 323 324 325 326 327 328 329 330
  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);

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

  g_object_class_override_property (gobject_class,
                                    PROP_NAME,
                                    "name");

  g_object_class_override_property (gobject_class,
                                    PROP_VENDOR,
                                    "vendor");

343 344 345 346
  g_object_class_override_property (gobject_class,
                                    PROP_TYPE,
                                    "type");

347 348 349 350
  g_object_class_override_property (gobject_class,
                                    PROP_STATUS,
                                    "status");

351 352 353 354
  g_object_class_override_property (gobject_class,
                                    PROP_PARENT,
                                    "parent");

355 356 357 358
  g_object_class_override_property (gobject_class,
                                    PROP_SYSFS,
                                    "sysfs-path");

359 360 361 362
  g_object_class_override_property (gobject_class,
                                    PROP_SECURITY,
                                    "security");

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

  g_object_class_override_property (gobject_class,
                                    PROP_POLICY,
                                    "policy");

  g_object_class_override_property (gobject_class,
                                    PROP_HAVE_KEY,
                                    "key");

375 376 377 378 379 380 381 382 383 384 385

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

386
}
387 388 389

/* internal methods */

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

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

  if (v != NULL)
    return v;

  v = udev_device_get_sysattr_value (udev, attr);
403

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

  return v;
410 411
}

412 413 414 415 416 417 418 419 420 421 422 423
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;

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

  if (str == end)
    return 0;

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

  return (gint) val;
}

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

444 445 446 447 448 449 450 451 452 453 454 455 456
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;
}

457 458 459 460 461 462 463 464 465 466 467 468
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;
}

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

499 500 501 502 503 504 505
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");
}
506 507

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

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

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

  return found ? parent : NULL;
}

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

535
  parent = bolt_sysfs_domain_for_device (udev);
536 537
  if (parent == NULL)
    {
538
      bolt_warn ("failed to determine domain device");
539 540 541 542 543 544
      return BOLT_SECURITY_NONE;
    }

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

545 546
  if (!bolt_security_validate (s))
    {
547
      bolt_warn ("invalid security: %s", v);
548 549 550
      s = BOLT_SECURITY_NONE;
    }

551 552 553
  return s;
}

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

582 583 584 585
/*  device authorization */

typedef struct
{
586
  BoltAuth *auth;
587 588

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

} AuthData;

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

599
  g_clear_object (&auth->auth);
600 601 602
  g_slice_free (AuthData, auth);
}

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

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

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

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

624
  if (key)
625
    {
626 627
      int keyfd;

628
      bolt_debug (LOG_DEV (dev), "writing key");
629 630 631 632
      keyfd = bolt_openat (dirfd (devdir), "key", O_WRONLY | O_CLOEXEC, error);
      if (keyfd < 0)
        return FALSE;

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

639
  bolt_debug (LOG_DEV (dev), "writing authorization");
640 641
  ok = bolt_write_char_at (dirfd (devdir),
                           "authorized",
642
                           level,
643 644 645 646 647 648 649 650 651 652 653 654
                           error);
  return ok;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

719
      return;
720 721 722
    }

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

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

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


/* dbus methods */

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

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

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

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

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

774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789
  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);
790 791 792 793

  return TRUE;
}

794 795 796
/* public methods */

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

809 810 811 812 813 814 815
  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;
    }
816

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

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

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

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

832 833 834 835 836 837 838 839 840 841 842 843 844 845 846
  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;
    }

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

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

860 861 862
  return dev;
}

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

  g_return_val_if_fail (BOLT_IS_DEVICE (device), FALSE);
872

873
  path = bolt_device_get_object_path (device);
874

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

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

888 889 890 891 892 893

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

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

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

910
  bolt_info (LOG_DEV (dev), "parent is %s", dev->parent);
911

912 913 914 915 916 917 918
  return status;
}

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

925 926 927 928 929
  /* 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)
930
    g_object_set (G_OBJECT (dev), "key", BOLT_KEY_HAVE, NULL);
931

932 933 934 935
  return dev->status;
}

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

941 942 943 944 945 946 947 948 949 950 951 952 953
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;
}

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

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

966 967 968 969 970 971 972 973 974
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;

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

      device->dbus_path = path;
    }

  return device->dbus_path;
}
983

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

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

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

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

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

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

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

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