diff options
-rw-r--r-- | modules/devices/devicetree.c | 124 |
1 files changed, 104 insertions, 20 deletions
diff --git a/modules/devices/devicetree.c b/modules/devices/devicetree.c index 5430bf28..142721c9 100644 --- a/modules/devices/devicetree.c +++ b/modules/devices/devicetree.c @@ -39,6 +39,7 @@ enum { typedef struct { char *path; + char *name; int type; unsigned long length; void *data; @@ -51,6 +52,8 @@ static struct { { "compatible", DTP_STR }, { "model", DTP_STR }, { "reg", DTP_HEX }, + { "clocks", DTP_HEX }, + { "gpios", DTP_HEX }, { "phandle", DTP_HEX }, { "interrupts", DTP_HEX }, { "regulator-min-microvolt", DTP_UINT }, @@ -59,6 +62,9 @@ static struct { { NULL, 0 }, }; +static dt_raw *get_dt_raw(char *); +static void dt_raw_free(dt_raw *); + /* Hardinfo labels that have # are truncated and/or hidden. * Labels can't have $ because that is the delimiter in * moreinfo. */ @@ -115,21 +121,16 @@ gchar *hardinfo_clean_value(const gchar *v, int replacing) { return clean; } +#define DT_CHECK_NAME(prop, nm) (strcmp(prop->name, nm) == 0) + /*cstd*/ static int dt_guess_type(dt_raw *prop) { - char *tmp, *slash, *dash; + char *tmp, *dash; int i = 0, anc = 0, might_be_str = 1; - /* find name after last slash, or start */ - slash = strrchr(prop->path, '/'); - if (slash != NULL) - slash++; - else - slash = prop->path; - /* special #(.*)-cells names are UINT */ - if (*slash == '#') { - dash = strrchr(slash, '-'); + if (*prop->name == '#') { + dash = strrchr(prop->name, '-'); if (dash != NULL) { if (strcmp(dash, "-cells") == 0) return DTP_UINT; @@ -138,7 +139,7 @@ static int dt_guess_type(dt_raw *prop) { /* lookup known type */ while (prop_types[i].name != NULL) { - if (strcmp(slash, prop_types[i].name) == 0) + if (strcmp(prop->name, prop_types[i].name) == 0) return prop_types[i].type; i++; } @@ -164,22 +165,93 @@ static int dt_guess_type(dt_raw *prop) { } /*cstd*/ -static char* dt_hex_list(uint32_t *list, int count) { - char *ret, *dest, buff[11] = ""; - int i, l; - l = count * 11 + 1; - ret = malloc(l); +static char* dt_hex_list(uint32_t *list, int count, int tup_len) { + char *ret, *dest; + char buff[15] = ""; /* max element: ">, <0x00000000\0" */ + int i, l, tc; + l = count * 15 + 1; + dest = ret = malloc(l); memset(ret, 0, l); - dest = ret; + if (tup_len) { + strcpy(dest, "<"); + dest = ret + 1; + } + tc = 0; for (i = 0; i < count; i++) { - sprintf(buff, "0x%x ", be32toh(list[i])); + if (tup_len) { + if (tc == tup_len) { + sprintf(buff, ">, <0x%x", be32toh(list[i])); + tc = 1; + } else { + sprintf(buff, "%s0x%x", (i) ? " " : "", be32toh(list[i])); + tc++; + } + } else + sprintf(buff, "%s0x%x", (i) ? " " : "", be32toh(list[i])); l = strlen(buff); strncpy(dest, buff, l); dest += l; } + if (tup_len) + strcpy(dest, ">"); + return ret; +} + +/* find an inherited property by climbing the path */ +/*cstd*/ +static int dt_inh_find(dt_raw *prop, char *inh_prop) { + char *slash, *tmp, *parent; + char buff[1024] = ""; + dt_raw *tprop; + uint32_t ret = 0; + + if (prop == NULL) + return 0; + + parent = strdup(prop->path); + while ( slash = strrchr(parent, '/') ) { + *slash = 0; + sprintf(buff, "%s/%s", parent, inh_prop); + tprop = get_dt_raw(buff); + if (tprop != NULL) { + ret = be32toh(*(uint32_t*)tprop->data); + dt_raw_free(tprop); + break; + } + } + + free(parent); return ret; } +/*cstd*/ +static int dt_tup_len(dt_raw *prop) { + int address_cells, size_cells, + clock_cells, gpio_cells; + + if (prop == NULL) + return 0; + + if DT_CHECK_NAME(prop, "reg") { + address_cells = dt_inh_find(prop, "#address-cells"); + size_cells = dt_inh_find(prop, "#size-cells"); + return address_cells + size_cells; + } + + if DT_CHECK_NAME(prop, "gpios") { + gpio_cells = dt_inh_find(prop, "#gpio-cells"); + if (gpio_cells == 0) gpio_cells = 1; + return gpio_cells; + } + + if DT_CHECK_NAME(prop, "clocks") { + clock_cells = dt_inh_find(prop, "#clock-cells"); + return 1 + clock_cells; + } + + return 0; +} + /*cstd, except for g_strescape()*/ static char* dt_str(dt_raw *prop) { char *tmp, *esc, *next_str; @@ -219,7 +291,7 @@ static char* dt_str(dt_raw *prop) { sprintf(ret, "%u", be32toh(*(uint32_t*)prop->data) ); } else if (i == DTP_HEX && !(prop->length % 4)) { l = prop->length / 4; - tmp = dt_hex_list((uint32_t*)prop->data, l); + tmp = dt_hex_list((uint32_t*)prop->data, l, dt_tup_len(prop)); strcpy(ret, tmp); free(tmp); } else { @@ -242,8 +314,19 @@ static dt_raw *get_dt_raw(char *p) { prop->type = DT_NODE; } else { prop->type = DT_PROPERTY; - g_file_get_contents(full_path, (gchar**)&prop->data, (gsize*)&prop->length, NULL); + if (!g_file_get_contents(full_path, (gchar**)&prop->data, (gsize*)&prop->length, NULL)) { + dt_raw_free(prop); + return NULL; + } } + + /* find name after last slash, or start */ + char *slash = strrchr(prop->path, '/'); + if (slash != NULL) + prop->name = strdup(slash + 1); + else + prop->name = strdup(prop->path); + return prop; } return NULL; @@ -253,6 +336,7 @@ static dt_raw *get_dt_raw(char *p) { void dt_raw_free(dt_raw *s) { if (s != NULL) { free(s->path); + free(s->name); free(s->data); } free(s); |