bolt-device.c 6.27 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
#include <libudev.h>

struct _BoltDevice
{
  BoltDBusDeviceSkeleton object;

34 35
  char                  *dbus_path;

36
  char                  *uid;
37 38 39 40 41
  char                  *name;
  char                  *vendor;

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


enum {
  PROP_0,

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

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

67 68
  g_free (dev->dbus_path);

69
  g_free (dev->uid);
70 71 72
  g_free (dev->name);
  g_free (dev->vendor);
  g_free (dev->syspath);
73

74 75 76
  if (dev->devdir)
    closedir (dev->devdir);

77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
  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;

100 101 102 103 104 105 106 107 108 109 110 111
    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;

112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
    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;

131 132 133 134 135 136 137 138 139 140 141 142
    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;

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

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

}
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191

/* 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;
192 193 194 195 196 197 198 199 200
}

/* public methods */

BoltDevice *
bolt_device_new_for_udev (BoltManager        *mgr,
                          struct udev_device *udev,
                          GError            **error)
{
201 202 203 204 205
  g_autofree char *uid = NULL;
  g_autofree char *name = NULL;
  g_autofree char *vendor = NULL;

  g_autoptr(DIR) devdir = NULL;
206
  BoltDevice *dev;
207 208
  const char *sysfs;
  int fd;
209

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

  dev = g_object_new (BOLT_TYPE_DEVICE,
                      NULL);

233 234 235 236 237 238
  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);

239 240 241 242 243 244 245 246
  return dev;
}

gboolean
bolt_device_export (BoltDevice      *device,
                    GDBusConnection *connection,
                    GError         **error)
{
247 248 249
  const char *path;

  g_return_val_if_fail (BOLT_IS_DEVICE (device), FALSE);
250

251
  path = bolt_device_get_object_path (device);
252 253 254 255 256 257 258 259 260 261 262 263 264 265

  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));
}
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283

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