1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy of the CDDL is also available via the Internet at
9 * http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2019, Joyent, Inc.
14 * Copyright 2020 Oxide Computer Company
15 */
16
17 /*
18 * Create /devices links for various sensors. The sensor series of node types
19 * all begin with ddi_sensor. After which, there is a series of : delineated
20 * paths in the node type. Those represent the directory under /dev/sensors that
21 * the nodes should ultimately be created.
22 *
23 * For example, ddi_sensor:temperature:cpu would cause us to place the named
24 * minor under /dev/sensors/temperature/cpu/. Currently it is up to drivers to
25 * not conflict in names or if there is a fear of conflicting, make sure their
26 * minor is unique.
27 */
28
29 #include <devfsadm.h>
30 #include <string.h>
31
32 #define SENSORS_BASE "sensors"
33
34 static int
sensor_link(di_minor_t minor,di_node_t node)35 sensor_link(di_minor_t minor, di_node_t node)
36 {
37 const char *t, *dir_path = NULL;
38 char *type, *name, *c;
39 char buf[PATH_MAX];
40 size_t len;
41
42 if ((t = di_minor_nodetype(minor)) == NULL) {
43 return (DEVFSADM_CONTINUE);
44 }
45
46 if ((type = strdup(t)) == NULL) {
47 return (DEVFSADM_TERMINATE);
48 }
49
50 c = type;
51 while ((c = strchr(c, ':')) != NULL) {
52 if (dir_path == NULL) {
53 dir_path = c + 1;
54 }
55 *c = '/';
56 }
57
58 if ((t = di_minor_name(minor)) == NULL) {
59 free(type);
60 return (DEVFSADM_CONTINUE);
61 }
62
63 if ((name = strdup(t)) == NULL) {
64 free(type);
65 return (DEVFSADM_TERMINATE);
66 }
67
68 c = name;
69 while ((c = strchr(c, ':')) != NULL) {
70 *c = '/';
71 }
72
73
74 if (dir_path == NULL || *dir_path == '\0') {
75 len = snprintf(buf, sizeof (buf), "%s/%s", SENSORS_BASE,
76 name);
77 } else {
78 len = snprintf(buf, sizeof (buf), "%s/%s/%s", SENSORS_BASE,
79 dir_path, name);
80 }
81
82 if (len < sizeof (buf)) {
83 (void) devfsadm_mklink(buf, node, minor, 0);
84 }
85
86 free(type);
87 free(name);
88 return (DEVFSADM_CONTINUE);
89 }
90
91 static devfsadm_create_t sensor_create_cbt[] = {
92 { NULL, "ddi_sensor", NULL, TYPE_PARTIAL, ILEVEL_0, sensor_link }
93 };
94 DEVFSADM_CREATE_INIT_V0(sensor_create_cbt);
95