~ubuntu-branches/ubuntu/trusty/systemd/trusty

« back to all changes in this revision

Viewing changes to src/device.c

  • Committer: Package Import Robot
  • Author(s): Michael Biebl, Michael Biebl, Michael Stapelberg, Daniel Schaal, Ondrej Balaz
  • Date: 2013-09-12 00:13:11 UTC
  • mfrom: (1.1.11) (9.1.2 experimental)
  • mto: This revision was merged to the branch mainline in revision 53.
  • Revision ID: package-import@ubuntu.com-20130912001311-dz35it34wr2lbday
Tags: 204-3
[ Michael Biebl ]
* Upload to unstable.
* Use /bin/bash in debug-shell.service as Debian doesn't have /sbin/sushell.
* Only import net.ifaces cmdline property for network devices.
* Generate strict dependencies between the binary packages using a
  shlibs.local file and add an explicit versioned dependency on
  libsystemd-login0 to systemd to ensure packages are upgraded in sync.
  Closes: #719444
* Drop obsolete Replaces: libudev0 from udev package.
* Use correct paths for various binaries, like /sbin/quotaon, which are
  installed in / and not /usr in Debian.  Closes: #721347
* Don't install kernel-install(8) man page since we don't install the
  corresponding binary either.  Closes: #722180
* Cherry-pick upstream fixes to make switching runlevels and starting
  reboot via ctrl-alt-del more robust.
* Cherry-pick upstream fix to properly apply ACLs to Journal files.

[ Michael Stapelberg ]
* Make systemctl enable|disable call update-rc.d for SysV init scripts.
  Closes: #709780
* Don't mount /tmp as tmpfs by default and make it possible to enable this
  feature via "systemctl enable tmp.mount".

[ Daniel Schaal ]
* Add bug-script to systemd and udev.  Closes: #711245

[ Ondrej Balaz ]
* Recognize discard option in /etc/crypttab.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
 
 
3
 
/***
4
 
  This file is part of systemd.
5
 
 
6
 
  Copyright 2010 Lennart Poettering
7
 
 
8
 
  systemd is free software; you can redistribute it and/or modify it
9
 
  under the terms of the GNU General Public License as published by
10
 
  the Free Software Foundation; either version 2 of the License, or
11
 
  (at your option) any later version.
12
 
 
13
 
  systemd is distributed in the hope that it will be useful, but
14
 
  WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
 
  General Public License for more details.
17
 
 
18
 
  You should have received a copy of the GNU General Public License
19
 
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
20
 
***/
21
 
 
22
 
#include <errno.h>
23
 
#include <sys/epoll.h>
24
 
#include <libudev.h>
25
 
 
26
 
#include "unit.h"
27
 
#include "device.h"
28
 
#include "strv.h"
29
 
#include "log.h"
30
 
#include "unit-name.h"
31
 
#include "dbus-device.h"
32
 
#include "def.h"
33
 
 
34
 
static const UnitActiveState state_translation_table[_DEVICE_STATE_MAX] = {
35
 
        [DEVICE_DEAD] = UNIT_INACTIVE,
36
 
        [DEVICE_PLUGGED] = UNIT_ACTIVE
37
 
};
38
 
 
39
 
static void device_unset_sysfs(Device *d) {
40
 
        Device *first;
41
 
 
42
 
        assert(d);
43
 
 
44
 
        if (!d->sysfs)
45
 
                return;
46
 
 
47
 
        /* Remove this unit from the chain of devices which share the
48
 
         * same sysfs path. */
49
 
        first = hashmap_get(UNIT(d)->manager->devices_by_sysfs, d->sysfs);
50
 
        LIST_REMOVE(Device, same_sysfs, first, d);
51
 
 
52
 
        if (first)
53
 
                hashmap_remove_and_replace(UNIT(d)->manager->devices_by_sysfs, d->sysfs, first->sysfs, first);
54
 
        else
55
 
                hashmap_remove(UNIT(d)->manager->devices_by_sysfs, d->sysfs);
56
 
 
57
 
        free(d->sysfs);
58
 
        d->sysfs = NULL;
59
 
}
60
 
 
61
 
static void device_init(Unit *u) {
62
 
        Device *d = DEVICE(u);
63
 
 
64
 
        assert(d);
65
 
        assert(UNIT(d)->load_state == UNIT_STUB);
66
 
 
67
 
        /* In contrast to all other unit types we timeout jobs waiting
68
 
         * for devices by default. This is because they otherwise wait
69
 
         * indefinitely for plugged in devices, something which cannot
70
 
         * happen for the other units since their operations time out
71
 
         * anyway. */
72
 
        UNIT(d)->job_timeout = DEFAULT_TIMEOUT_USEC;
73
 
 
74
 
        UNIT(d)->ignore_on_isolate = true;
75
 
        UNIT(d)->ignore_on_snapshot = true;
76
 
}
77
 
 
78
 
static void device_done(Unit *u) {
79
 
        Device *d = DEVICE(u);
80
 
 
81
 
        assert(d);
82
 
 
83
 
        device_unset_sysfs(d);
84
 
}
85
 
 
86
 
static void device_set_state(Device *d, DeviceState state) {
87
 
        DeviceState old_state;
88
 
        assert(d);
89
 
 
90
 
        old_state = d->state;
91
 
        d->state = state;
92
 
 
93
 
        if (state != old_state)
94
 
                log_debug("%s changed %s -> %s",
95
 
                          UNIT(d)->id,
96
 
                          device_state_to_string(old_state),
97
 
                          device_state_to_string(state));
98
 
 
99
 
        unit_notify(UNIT(d), state_translation_table[old_state], state_translation_table[state], true);
100
 
}
101
 
 
102
 
static int device_coldplug(Unit *u) {
103
 
        Device *d = DEVICE(u);
104
 
 
105
 
        assert(d);
106
 
        assert(d->state == DEVICE_DEAD);
107
 
 
108
 
        if (d->sysfs)
109
 
                device_set_state(d, DEVICE_PLUGGED);
110
 
 
111
 
        return 0;
112
 
}
113
 
 
114
 
static void device_dump(Unit *u, FILE *f, const char *prefix) {
115
 
        Device *d = DEVICE(u);
116
 
 
117
 
        assert(d);
118
 
 
119
 
        fprintf(f,
120
 
                "%sDevice State: %s\n"
121
 
                "%sSysfs Path: %s\n",
122
 
                prefix, device_state_to_string(d->state),
123
 
                prefix, strna(d->sysfs));
124
 
}
125
 
 
126
 
static UnitActiveState device_active_state(Unit *u) {
127
 
        assert(u);
128
 
 
129
 
        return state_translation_table[DEVICE(u)->state];
130
 
}
131
 
 
132
 
static const char *device_sub_state_to_string(Unit *u) {
133
 
        assert(u);
134
 
 
135
 
        return device_state_to_string(DEVICE(u)->state);
136
 
}
137
 
 
138
 
static int device_add_escaped_name(Unit *u, const char *dn) {
139
 
        char *e;
140
 
        int r;
141
 
 
142
 
        assert(u);
143
 
        assert(dn);
144
 
        assert(dn[0] == '/');
145
 
 
146
 
        if (!(e = unit_name_from_path(dn, ".device")))
147
 
                return -ENOMEM;
148
 
 
149
 
        r = unit_add_name(u, e);
150
 
        free(e);
151
 
 
152
 
        if (r < 0 && r != -EEXIST)
153
 
                return r;
154
 
 
155
 
        return 0;
156
 
}
157
 
 
158
 
static int device_find_escape_name(Manager *m, const char *dn, Unit **_u) {
159
 
        char *e;
160
 
        Unit *u;
161
 
 
162
 
        assert(m);
163
 
        assert(dn);
164
 
        assert(dn[0] == '/');
165
 
        assert(_u);
166
 
 
167
 
        if (!(e = unit_name_from_path(dn, ".device")))
168
 
                return -ENOMEM;
169
 
 
170
 
        u = manager_get_unit(m, e);
171
 
        free(e);
172
 
 
173
 
        if (u) {
174
 
                *_u = u;
175
 
                return 1;
176
 
        }
177
 
 
178
 
        return 0;
179
 
}
180
 
 
181
 
static int device_update_unit(Manager *m, struct udev_device *dev, const char *path, bool main) {
182
 
        const char *sysfs, *model;
183
 
        Unit *u = NULL;
184
 
        int r;
185
 
        bool delete;
186
 
 
187
 
        assert(m);
188
 
 
189
 
        if (!(sysfs = udev_device_get_syspath(dev)))
190
 
                return -ENOMEM;
191
 
 
192
 
        if ((r = device_find_escape_name(m, path, &u)) < 0)
193
 
                return r;
194
 
 
195
 
        if (u && DEVICE(u)->sysfs && !path_equal(DEVICE(u)->sysfs, sysfs))
196
 
                return -EEXIST;
197
 
 
198
 
        if (!u) {
199
 
                delete = true;
200
 
 
201
 
                u = unit_new(m, sizeof(Device));
202
 
                if (!u)
203
 
                        return -ENOMEM;
204
 
 
205
 
                r = device_add_escaped_name(u, path);
206
 
                if (r < 0)
207
 
                        goto fail;
208
 
 
209
 
                unit_add_to_load_queue(u);
210
 
        } else
211
 
                delete = false;
212
 
 
213
 
        /* If this was created via some dependency and has not
214
 
         * actually been seen yet ->sysfs will not be
215
 
         * initialized. Hence initialize it if necessary. */
216
 
 
217
 
        if (!DEVICE(u)->sysfs) {
218
 
                Device *first;
219
 
 
220
 
                if (!(DEVICE(u)->sysfs = strdup(sysfs))) {
221
 
                        r = -ENOMEM;
222
 
                        goto fail;
223
 
                }
224
 
 
225
 
                if (!m->devices_by_sysfs)
226
 
                        if (!(m->devices_by_sysfs = hashmap_new(string_hash_func, string_compare_func))) {
227
 
                                r = -ENOMEM;
228
 
                                goto fail;
229
 
                        }
230
 
 
231
 
                first = hashmap_get(m->devices_by_sysfs, sysfs);
232
 
                LIST_PREPEND(Device, same_sysfs, first, DEVICE(u));
233
 
 
234
 
                if ((r = hashmap_replace(m->devices_by_sysfs, DEVICE(u)->sysfs, first)) < 0)
235
 
                        goto fail;
236
 
        }
237
 
 
238
 
        if ((model = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE")) ||
239
 
            (model = udev_device_get_property_value(dev, "ID_MODEL"))) {
240
 
                if ((r = unit_set_description(u, model)) < 0)
241
 
                        goto fail;
242
 
        } else
243
 
                if ((r = unit_set_description(u, path)) < 0)
244
 
                        goto fail;
245
 
 
246
 
        if (main) {
247
 
                /* The additional systemd udev properties we only
248
 
                 * interpret for the main object */
249
 
                const char *wants, *alias;
250
 
 
251
 
                if ((alias = udev_device_get_property_value(dev, "SYSTEMD_ALIAS"))) {
252
 
                        if (!is_path(alias))
253
 
                                log_warning("SYSTEMD_ALIAS for %s is not a path, ignoring: %s", sysfs, alias);
254
 
                        else {
255
 
                                if ((r = device_add_escaped_name(u, alias)) < 0)
256
 
                                        goto fail;
257
 
                        }
258
 
                }
259
 
 
260
 
                if ((wants = udev_device_get_property_value(dev, "SYSTEMD_WANTS"))) {
261
 
                        char *state, *w;
262
 
                        size_t l;
263
 
 
264
 
                        FOREACH_WORD_QUOTED(w, l, wants, state) {
265
 
                                char *e;
266
 
 
267
 
                                if (!(e = strndup(w, l))) {
268
 
                                        r = -ENOMEM;
269
 
                                        goto fail;
270
 
                                }
271
 
 
272
 
                                r = unit_add_dependency_by_name(u, UNIT_WANTS, e, NULL, true);
273
 
                                free(e);
274
 
 
275
 
                                if (r < 0)
276
 
                                        goto fail;
277
 
                        }
278
 
                }
279
 
        }
280
 
 
281
 
        unit_add_to_dbus_queue(u);
282
 
        return 0;
283
 
 
284
 
fail:
285
 
        log_warning("Failed to load device unit: %s", strerror(-r));
286
 
 
287
 
        if (delete && u)
288
 
                unit_free(u);
289
 
 
290
 
        return r;
291
 
}
292
 
 
293
 
static int device_process_new_device(Manager *m, struct udev_device *dev, bool update_state) {
294
 
        const char *sysfs, *dn;
295
 
        struct udev_list_entry *item = NULL, *first = NULL;
296
 
 
297
 
        assert(m);
298
 
 
299
 
        if (!(sysfs = udev_device_get_syspath(dev)))
300
 
                return -ENOMEM;
301
 
 
302
 
        /* Add the main unit named after the sysfs path */
303
 
        device_update_unit(m, dev, sysfs, true);
304
 
 
305
 
        /* Add an additional unit for the device node */
306
 
        if ((dn = udev_device_get_devnode(dev)))
307
 
                device_update_unit(m, dev, dn, false);
308
 
 
309
 
        /* Add additional units for all symlinks */
310
 
        first = udev_device_get_devlinks_list_entry(dev);
311
 
        udev_list_entry_foreach(item, first) {
312
 
                const char *p;
313
 
                struct stat st;
314
 
 
315
 
                /* Don't bother with the /dev/block links */
316
 
                p = udev_list_entry_get_name(item);
317
 
 
318
 
                if (path_startswith(p, "/dev/block/") ||
319
 
                    path_startswith(p, "/dev/char/"))
320
 
                        continue;
321
 
 
322
 
                /* Verify that the symlink in the FS actually belongs
323
 
                 * to this device. This is useful to deal with
324
 
                 * conflicting devices, e.g. when two disks want the
325
 
                 * same /dev/disk/by-label/xxx link because they have
326
 
                 * the same label. We want to make sure that the same
327
 
                 * device that won the symlink wins in systemd, so we
328
 
                 * check the device node major/minor*/
329
 
                if (stat(p, &st) >= 0)
330
 
                        if ((!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode)) ||
331
 
                            st.st_rdev != udev_device_get_devnum(dev))
332
 
                                continue;
333
 
 
334
 
                device_update_unit(m, dev, p, false);
335
 
        }
336
 
 
337
 
        if (update_state) {
338
 
                Device *d, *l;
339
 
 
340
 
                manager_dispatch_load_queue(m);
341
 
 
342
 
                l = hashmap_get(m->devices_by_sysfs, sysfs);
343
 
                LIST_FOREACH(same_sysfs, d, l)
344
 
                        device_set_state(d, DEVICE_PLUGGED);
345
 
        }
346
 
 
347
 
        return 0;
348
 
}
349
 
 
350
 
static int device_process_path(Manager *m, const char *path, bool update_state) {
351
 
        int r;
352
 
        struct udev_device *dev;
353
 
 
354
 
        assert(m);
355
 
        assert(path);
356
 
 
357
 
        if (!(dev = udev_device_new_from_syspath(m->udev, path))) {
358
 
                log_warning("Failed to get udev device object from udev for path %s.", path);
359
 
                return -ENOMEM;
360
 
        }
361
 
 
362
 
        r = device_process_new_device(m, dev, update_state);
363
 
        udev_device_unref(dev);
364
 
        return r;
365
 
}
366
 
 
367
 
static int device_process_removed_device(Manager *m, struct udev_device *dev) {
368
 
        const char *sysfs;
369
 
        Device *d;
370
 
 
371
 
        assert(m);
372
 
        assert(dev);
373
 
 
374
 
        if (!(sysfs = udev_device_get_syspath(dev)))
375
 
                return -ENOMEM;
376
 
 
377
 
        /* Remove all units of this sysfs path */
378
 
        while ((d = hashmap_get(m->devices_by_sysfs, sysfs))) {
379
 
                device_unset_sysfs(d);
380
 
                device_set_state(d, DEVICE_DEAD);
381
 
        }
382
 
 
383
 
        return 0;
384
 
}
385
 
 
386
 
static Unit *device_following(Unit *u) {
387
 
        Device *d = DEVICE(u);
388
 
        Device *other, *first = NULL;
389
 
 
390
 
        assert(d);
391
 
 
392
 
        if (startswith(u->id, "sys-"))
393
 
                return NULL;
394
 
 
395
 
        /* Make everybody follow the unit that's named after the sysfs path */
396
 
        for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
397
 
                if (startswith(UNIT(other)->id, "sys-"))
398
 
                        return UNIT(other);
399
 
 
400
 
        for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev) {
401
 
                if (startswith(UNIT(other)->id, "sys-"))
402
 
                        return UNIT(other);
403
 
 
404
 
                first = other;
405
 
        }
406
 
 
407
 
        return UNIT(first);
408
 
}
409
 
 
410
 
static int device_following_set(Unit *u, Set **_s) {
411
 
        Device *d = DEVICE(u);
412
 
        Device *other;
413
 
        Set *s;
414
 
        int r;
415
 
 
416
 
        assert(d);
417
 
        assert(_s);
418
 
 
419
 
        if (!d->same_sysfs_prev && !d->same_sysfs_next) {
420
 
                *_s = NULL;
421
 
                return 0;
422
 
        }
423
 
 
424
 
        if (!(s = set_new(NULL, NULL)))
425
 
                return -ENOMEM;
426
 
 
427
 
        for (other = d->same_sysfs_next; other; other = other->same_sysfs_next)
428
 
                if ((r = set_put(s, other)) < 0)
429
 
                        goto fail;
430
 
 
431
 
        for (other = d->same_sysfs_prev; other; other = other->same_sysfs_prev)
432
 
                if ((r = set_put(s, other)) < 0)
433
 
                        goto fail;
434
 
 
435
 
        *_s = s;
436
 
        return 1;
437
 
 
438
 
fail:
439
 
        set_free(s);
440
 
        return r;
441
 
}
442
 
 
443
 
static void device_shutdown(Manager *m) {
444
 
        assert(m);
445
 
 
446
 
        if (m->udev_monitor) {
447
 
                udev_monitor_unref(m->udev_monitor);
448
 
                m->udev_monitor = NULL;
449
 
        }
450
 
 
451
 
        if (m->udev) {
452
 
                udev_unref(m->udev);
453
 
                m->udev = NULL;
454
 
        }
455
 
 
456
 
        hashmap_free(m->devices_by_sysfs);
457
 
        m->devices_by_sysfs = NULL;
458
 
}
459
 
 
460
 
static int device_enumerate(Manager *m) {
461
 
        struct epoll_event ev;
462
 
        int r;
463
 
        struct udev_enumerate *e = NULL;
464
 
        struct udev_list_entry *item = NULL, *first = NULL;
465
 
 
466
 
        assert(m);
467
 
 
468
 
        if (!m->udev) {
469
 
                if (!(m->udev = udev_new()))
470
 
                        return -ENOMEM;
471
 
 
472
 
                if (!(m->udev_monitor = udev_monitor_new_from_netlink(m->udev, "udev"))) {
473
 
                        r = -ENOMEM;
474
 
                        goto fail;
475
 
                }
476
 
 
477
 
                /* This will fail if we are unprivileged, but that
478
 
                 * should not matter much, as user instances won't run
479
 
                 * during boot. */
480
 
                udev_monitor_set_receive_buffer_size(m->udev_monitor, 128*1024*1024);
481
 
 
482
 
                if (udev_monitor_filter_add_match_tag(m->udev_monitor, "systemd") < 0) {
483
 
                        r = -ENOMEM;
484
 
                        goto fail;
485
 
                }
486
 
 
487
 
                if (udev_monitor_enable_receiving(m->udev_monitor) < 0) {
488
 
                        r = -EIO;
489
 
                        goto fail;
490
 
                }
491
 
 
492
 
                m->udev_watch.type = WATCH_UDEV;
493
 
                m->udev_watch.fd = udev_monitor_get_fd(m->udev_monitor);
494
 
 
495
 
                zero(ev);
496
 
                ev.events = EPOLLIN;
497
 
                ev.data.ptr = &m->udev_watch;
498
 
 
499
 
                if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_watch.fd, &ev) < 0)
500
 
                        return -errno;
501
 
        }
502
 
 
503
 
        if (!(e = udev_enumerate_new(m->udev))) {
504
 
                r = -ENOMEM;
505
 
                goto fail;
506
 
        }
507
 
        if (udev_enumerate_add_match_tag(e, "systemd") < 0) {
508
 
                r = -EIO;
509
 
                goto fail;
510
 
        }
511
 
 
512
 
        if (udev_enumerate_scan_devices(e) < 0) {
513
 
                r = -EIO;
514
 
                goto fail;
515
 
        }
516
 
 
517
 
        first = udev_enumerate_get_list_entry(e);
518
 
        udev_list_entry_foreach(item, first)
519
 
                device_process_path(m, udev_list_entry_get_name(item), false);
520
 
 
521
 
        udev_enumerate_unref(e);
522
 
        return 0;
523
 
 
524
 
fail:
525
 
        if (e)
526
 
                udev_enumerate_unref(e);
527
 
 
528
 
        device_shutdown(m);
529
 
        return r;
530
 
}
531
 
 
532
 
void device_fd_event(Manager *m, int events) {
533
 
        struct udev_device *dev;
534
 
        int r;
535
 
        const char *action, *ready;
536
 
 
537
 
        assert(m);
538
 
 
539
 
        if (events != EPOLLIN) {
540
 
                static RATELIMIT_DEFINE(limit, 10*USEC_PER_SEC, 5);
541
 
 
542
 
                if (!ratelimit_test(&limit))
543
 
                        log_error("Failed to get udev event: %m");
544
 
                if (!(events & EPOLLIN))
545
 
                        return;
546
 
        }
547
 
 
548
 
        if (!(dev = udev_monitor_receive_device(m->udev_monitor))) {
549
 
                /*
550
 
                 * libudev might filter-out devices which pass the bloom filter,
551
 
                 * so getting NULL here is not necessarily an error
552
 
                 */
553
 
                return;
554
 
        }
555
 
 
556
 
        if (!(action = udev_device_get_action(dev))) {
557
 
                log_error("Failed to get udev action string.");
558
 
                goto fail;
559
 
        }
560
 
 
561
 
        ready = udev_device_get_property_value(dev, "SYSTEMD_READY");
562
 
 
563
 
        if (streq(action, "remove") || (ready && parse_boolean(ready) == 0)) {
564
 
                if ((r = device_process_removed_device(m, dev)) < 0) {
565
 
                        log_error("Failed to process udev device event: %s", strerror(-r));
566
 
                        goto fail;
567
 
                }
568
 
        } else {
569
 
                if ((r = device_process_new_device(m, dev, true)) < 0) {
570
 
                        log_error("Failed to process udev device event: %s", strerror(-r));
571
 
                        goto fail;
572
 
                }
573
 
        }
574
 
 
575
 
fail:
576
 
        udev_device_unref(dev);
577
 
}
578
 
 
579
 
static const char* const device_state_table[_DEVICE_STATE_MAX] = {
580
 
        [DEVICE_DEAD] = "dead",
581
 
        [DEVICE_PLUGGED] = "plugged"
582
 
};
583
 
 
584
 
DEFINE_STRING_TABLE_LOOKUP(device_state, DeviceState);
585
 
 
586
 
const UnitVTable device_vtable = {
587
 
        .suffix = ".device",
588
 
        .object_size = sizeof(Device),
589
 
        .sections =
590
 
                "Unit\0"
591
 
                "Device\0"
592
 
                "Install\0",
593
 
 
594
 
        .no_instances = true,
595
 
 
596
 
        .init = device_init,
597
 
 
598
 
        .load = unit_load_fragment_and_dropin_optional,
599
 
        .done = device_done,
600
 
        .coldplug = device_coldplug,
601
 
 
602
 
        .dump = device_dump,
603
 
 
604
 
        .active_state = device_active_state,
605
 
        .sub_state_to_string = device_sub_state_to_string,
606
 
 
607
 
        .bus_interface = "org.freedesktop.systemd1.Device",
608
 
        .bus_message_handler = bus_device_message_handler,
609
 
        .bus_invalidating_properties =  bus_device_invalidating_properties,
610
 
 
611
 
        .following = device_following,
612
 
        .following_set = device_following_set,
613
 
 
614
 
        .enumerate = device_enumerate,
615
 
        .shutdown = device_shutdown
616
 
};