| | 38 | #define DYNAMIC_CHIP_REGEX "\\([[:alpha:]]\\{1,\\}[[:digit:]]\\{0,\\}\\)\\(\\_[[:alpha:]]\\{1,\\}\\)\\{0,1\\}" |
| | 39 | |
| | 40 | static int sensors_read_dynamic_chip_check_mapping( |
| | 41 | sensors_chip_feature *minor, |
| | 42 | sensors_chip_feature *major, |
| | 43 | regmatch_t *pmatch) |
| | 44 | { |
| | 45 | if (pmatch[1].rm_so == -1 || pmatch[2].rm_so == -1 || |
| | 46 | strncmp(minor->data.name, major->data.name, |
| | 47 | pmatch[1].rm_eo - pmatch[1].rm_so)) { |
| | 48 | return 0; |
| | 49 | } else { |
| | 50 | minor->data.mapping = |
| | 51 | minor->data.compute_mapping = |
| | 52 | major->data.number; |
| | 53 | |
| | 54 | return 1; |
| | 55 | } |
| | 56 | } |
| | 57 | |
| | 58 | static |
| | 59 | sensors_chip_features sensors_read_dynamic_chip(struct sysfs_device *sysdir) |
| | 60 | { |
| | 61 | int fnum = 1, i, last_major = -1; |
| | 62 | struct sysfs_attribute *attr; |
| | 63 | struct dlist *attrs; |
| | 64 | sensors_chip_features ret = {0, 0}; |
| | 65 | sensors_chip_feature features[256], *dyn_features; |
| | 66 | regex_t preg; |
| | 67 | regmatch_t pmatch[3]; |
| | 68 | char *name; |
| | 69 | |
| | 70 | attrs = sysfs_get_device_attributes(sysdir); |
| | 71 | |
| | 72 | if (attrs == NULL) |
| | 73 | return ret; |
| | 74 | |
| | 75 | regcomp(&preg, DYNAMIC_CHIP_REGEX, 0); |
| | 76 | |
| | 77 | dlist_for_each_data(attrs, attr, struct sysfs_attribute) { |
| | 78 | sensors_chip_feature feature = { { 0, }, 0, }; |
| | 79 | name = attr->name; |
| | 80 | |
| | 81 | if (!strcmp(name, "name")) { |
| | 82 | ret.prefix = strndup(attr->value, strlen(attr->value) - 1); |
| | 83 | continue; |
| | 84 | } else if (regexec(&preg, name, 3, pmatch, 0) != 0) { |
| | 85 | continue; |
| | 86 | } |
| | 87 | |
| | 88 | feature.data.number = fnum; |
| | 89 | feature.data.mode = (attr->method & (SYSFS_METHOD_SHOW|SYSFS_METHOD_STORE)) == |
| | 90 | (SYSFS_METHOD_SHOW|SYSFS_METHOD_STORE) ? |
| | 91 | SENSORS_MODE_RW : |
| | 92 | (attr->method & SYSFS_METHOD_SHOW) ? SENSORS_MODE_R : |
| | 93 | (attr->method & SYSFS_METHOD_STORE) ? SENSORS_MODE_W : |
| | 94 | SENSORS_MODE_NO_RW; |
| | 95 | feature.data.mapping = SENSORS_NO_MAPPING; |
| | 96 | feature.data.compute_mapping = SENSORS_NO_MAPPING; |
| | 97 | |
| | 98 | if (pmatch[2].rm_so != -1) { |
| | 99 | if (!strncmp(name + pmatch[2].rm_so, "_input", |
| | 100 | pmatch[2].rm_eo - pmatch[2].rm_so)) { |
| | 101 | int last_match; |
| | 102 | |
| | 103 | /* copy only the part before the _ */ |
| | 104 | feature.data.name = strndup(name, |
| | 105 | pmatch[1].rm_eo - pmatch[1].rm_so); |
| | 106 | |
| | 107 | /* check if the features previously read are sub devices of this major |
| | 108 | and update their mapping accordingly */ |
| | 109 | last_match = fnum - 1; |
| | 110 | for(i = fnum - 2; i >= 0; i--) { |
| | 111 | if (regexec(&preg, features[i].data.name, 3, pmatch, 0) == -1 || |
| | 112 | !sensors_read_dynamic_chip_check_mapping(&features[i], |
| | 113 | &feature, pmatch)) { |
| | 114 | break; |
| | 115 | } else { |
| | 116 | last_match = i; |
| | 117 | } |
| | 118 | } |
| | 119 | |
| | 120 | /* if so the major should be in the list before any minor feature, |
| | 121 | so swap with the oldest read */ |
| | 122 | if (last_match < fnum - 1) { |
| | 123 | sensors_chip_feature tmp = features[last_match]; |
| | 124 | features[last_match] = feature; |
| | 125 | features[fnum - 1] = tmp; |
| | 126 | |
| | 127 | last_major = last_match; |
| | 128 | |
| | 129 | goto NEXT_NUM; /* NOTE: goto used */ |
| | 130 | } else { |
| | 131 | last_major = fnum - 1; |
| | 132 | } |
| | 133 | |
| | 134 | } else { |
| | 135 | feature.data.name = strdup(name); |
| | 136 | |
| | 137 | if (last_major != -1 && |
| | 138 | !sensors_read_dynamic_chip_check_mapping(&feature, |
| | 139 | &features[last_major], pmatch)) { |
| | 140 | last_major = -1; /* no more features for current major */ |
| | 141 | } |
| | 142 | } |
| | 143 | } else { |
| | 144 | feature.data.name = strdup(name); |
| | 145 | } |
| | 146 | |
| | 147 | features[fnum - 1] = feature; |
| | 148 | NEXT_NUM: |
| | 149 | fnum++; |
| | 150 | } |
| | 151 | |
| | 152 | regfree(&preg); |
| | 153 | |
| | 154 | dyn_features = malloc(sizeof(sensors_chip_feature) * fnum); |
| | 155 | if (dyn_features == NULL) { |
| | 156 | sensors_fatal_error(__FUNCTION__,"Out of memory"); |
| | 157 | } |
| | 158 | |
| | 159 | for(i = 0; i < fnum - 1; i++) { |
| | 160 | dyn_features[i] = features[i]; |
| | 161 | } |
| | 162 | dyn_features[fnum - 1].data.name = 0; |
| | 163 | |
| | 164 | ret.feature = dyn_features; |
| | 165 | |
| | 166 | return ret; |
| | 167 | } |
| | 168 | |