bolt-device.c 6.7 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
#include "bolt-manager.h"
27

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

struct _BoltDevice
{
  BoltDBusDeviceSkeleton object;

35 36
  /* weak reference */
  BoltManager *mgr;
37

38 39 40 41 42
  char        *dbus_path;

  char        *uid;
  char        *name;
  char        *vendor;
43 44 45

  /* when device is attached */
  char *syspath;
46
  DIR  *devdir;
47 48 49 50 51 52 53
};


enum {
  PROP_0,

  PROP_UID,
54 55 56
  PROP_NAME,
  PROP_VENDOR,
  PROP_SYSFS,
57 58 59 60 61 62 63 64 65 66 67 68 69 70

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

71 72
  g_free (dev->dbus_path);

73
  g_free (dev->uid);
74 75 76
  g_free (dev->name);
  g_free (dev->vendor);
  g_free (dev->syspath);
77

78 79 80
  if (dev->devdir)
    closedir (dev->devdir);

81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
  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;

104 105 106 107 108 109 110 111 112 113 114 115
    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;

116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    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;

135 136 137 138 139 140 141 142 143 144 145 146
    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;

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    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");
166 167 168 169 170 171 172 173 174 175 176 177 178 179

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

}
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195

/* 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;
196 197 198 199 200 201 202 203 204
}

/* public methods */

BoltDevice *
bolt_device_new_for_udev (BoltManager        *mgr,
                          struct udev_device *udev,
                          GError            **error)
{
205 206 207 208 209
  g_autofree char *uid = NULL;
  g_autofree char *name = NULL;
  g_autofree char *vendor = NULL;

  g_autoptr(DIR) devdir = NULL;
210
  BoltDevice *dev;
211 212
  const char *sysfs;
  int fd;
213

214 215 216 217 218 219 220 221 222
  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);
223
  if (uid == NULL)
224 225 226 227 228 229 230 231 232
    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;
233 234 235 236

  dev = g_object_new (BOLT_TYPE_DEVICE,
                      NULL);

237 238 239 240 241 242
  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);

243 244 245
  g_object_add_weak_pointer (G_OBJECT (mgr),
                             (gpointer *) &dev->mgr);

246 247 248
  return dev;
}

249
const char *
250 251 252 253
bolt_device_export (BoltDevice      *device,
                    GDBusConnection *connection,
                    GError         **error)
{
254
  const char *path;
255
  gboolean ok;
256 257

  g_return_val_if_fail (BOLT_IS_DEVICE (device), FALSE);
258

259
  path = bolt_device_get_object_path (device);
260 261 262

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

263 264 265 266 267
  ok = g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (device),
                                         connection,
                                         path,
                                         error);
  return ok ? path : NULL;
268 269 270 271 272
}

void
bolt_device_unexport (BoltDevice *device)
{
273 274 275 276 277
  const char *path;

  path = bolt_device_get_object_path (device);

  g_debug ("Unexporting device at: %s", path);
278 279
  g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (device));
}
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297

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;

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

      device->dbus_path = path;
    }

  return device->dbus_path;
}
298 299 300 301 302 303 304 305 306 307 308 309

const char *
bolt_device_get_uid (BoltDevice *dev)
{
  return dev->uid;
}

const char *
bolt_device_get_syspath (BoltDevice *dev)
{
  return dev->syspath;
}