bolt-device.c 5.86 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 24
/*
 * 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"
#include "bolt-error.h"
25
#include "bolt-io.h"
26

27
#include <dirent.h>
28 29 30 31 32 33 34
#include <libudev.h>

struct _BoltDevice
{
  BoltDBusDeviceSkeleton object;

  char                  *uid;
35 36 37 38 39
  char                  *name;
  char                  *vendor;

  /* when device is attached */
  char *syspath;
40
  DIR  *devdir;
41 42 43 44 45 46 47
};


enum {
  PROP_0,

  PROP_UID,
48 49 50
  PROP_NAME,
  PROP_VENDOR,
  PROP_SYSFS,
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65

  PROP_LAST
};


G_DEFINE_TYPE (BoltDevice,
               bolt_device,
               BOLT_DBUS_TYPE_DEVICE_SKELETON)

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

  g_free (dev->uid);
66 67 68
  g_free (dev->name);
  g_free (dev->vendor);
  g_free (dev->syspath);
69

70 71 72
  if (dev->devdir)
    closedir (dev->devdir);

73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  G_OBJECT_CLASS (bolt_device_parent_class)->finalize (object);
}

static void
bolt_device_init (BoltDevice *mgr)
{

}

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

  switch (prop_id)
    {
    case PROP_UID:
      g_value_set_string (value, dev->uid);
      break;

96 97 98 99 100 101 102 103 104 105 106 107
    case PROP_NAME:
      g_value_set_string (value, dev->name);
      break;

    case PROP_VENDOR:
      g_value_set_string (value, dev->vendor);
      break;

    case PROP_SYSFS:
      g_value_set_string (value, dev->syspath);
      break;

108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    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)
    {
    case PROP_UID:
      dev->uid = g_value_dup_string (value);
      break;

127 128 129 130 131 132 133 134 135 136 137 138
    case PROP_NAME:
      dev->vendor = g_value_dup_string (value);
      break;

    case PROP_VENDOR:
      dev->name = g_value_dup_string (value);
      break;

    case PROP_SYSFS:
      dev->syspath = g_value_dup_string (value);
      break;

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
    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);

  gobject_class->finalize = bolt_device_finalize;

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

  g_object_class_override_property (gobject_class,
                                    PROP_UID,
                                    "uid");
158 159 160 161 162 163 164 165 166 167 168 169 170 171

  g_object_class_override_property (gobject_class,
                                    PROP_NAME,
                                    "name");

  g_object_class_override_property (gobject_class,
                                    PROP_VENDOR,
                                    "vendor");

  g_object_class_override_property (gobject_class,
                                    PROP_SYSFS,
                                    "sysfs-path");

}
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

/* internal methods */

static char *
read_sysattr_name (int fd, const char *attr, GError **error)
{
  g_autofree char *s = NULL;
  char *v;

  s = g_strdup_printf ("%s_name", attr);

  v = bolt_read_value_at (fd, s, NULL);
  if (!v)
    v = bolt_read_value_at (fd, attr, error);

  return v;
188 189 190 191 192 193 194 195 196
}

/* public methods */

BoltDevice *
bolt_device_new_for_udev (BoltManager        *mgr,
                          struct udev_device *udev,
                          GError            **error)
{
197 198 199 200 201
  g_autofree char *uid = NULL;
  g_autofree char *name = NULL;
  g_autofree char *vendor = NULL;

  g_autoptr(DIR) devdir = NULL;
202
  BoltDevice *dev;
203 204
  const char *sysfs;
  int fd;
205

206 207 208 209 210 211 212 213 214
  sysfs = udev_device_get_syspath (udev);
  devdir = bolt_opendir (sysfs, error);

  if (devdir == NULL)
    return NULL;

  fd = dirfd (devdir);

  uid = bolt_read_value_at (fd, "unique_id", error);
215
  if (uid == NULL)
216 217 218 219 220 221 222 223 224
    return NULL;

  name = read_sysattr_name (fd, "device", error);
  if (name == NULL)
    return NULL;

  vendor = read_sysattr_name (fd, "vendor", error);
  if (vendor == NULL)
    return NULL;
225 226 227 228

  dev = g_object_new (BOLT_TYPE_DEVICE,
                      NULL);

229 230 231 232 233 234
  dev->uid = g_steal_pointer (&uid);
  dev->name = g_steal_pointer (&name);
  dev->vendor = g_steal_pointer (&vendor);
  dev->syspath = g_strdup (sysfs);
  dev->devdir = g_steal_pointer (&devdir);

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
  return dev;
}

gboolean
bolt_device_export (BoltDevice      *device,
                    GDBusConnection *connection,
                    GError         **error)
{
  g_autofree char *path = NULL;

  path = g_strdup_printf ("/org/freedesktop/Bolt/devices/%s", device->uid);
  g_strdelimit (path, "-", '_');

  g_debug ("Exporting device at: %s", path);

  return g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (device),
                                           connection,
                                           path,
                                           error);
}

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