Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80dac350 authored by Colin Cross's avatar Colin Cross Committed by Gerrit Code Review
Browse files

Merge "ueventd: allow platform devices to have just a /devices/ prefix"

parents 0b535558 f395c923
Loading
Loading
Loading
Loading
+44 −39
Original line number Diff line number Diff line
@@ -83,7 +83,8 @@ struct perm_node {

struct platform_node {
    char *name;
    int name_len;
    char *path;
    int path_len;
    struct listnode list;
};

@@ -215,61 +216,69 @@ static void make_device(const char *path,
    }
}

static void add_platform_device(const char *name)
static void add_platform_device(const char *path)
{
    int name_len = strlen(name);
    int path_len = strlen(path);
    struct listnode *node;
    struct platform_node *bus;
    const char *name = path;

    if (!strncmp(path, "/devices/", 9)) {
        name += 9;
        if (!strncmp(name, "platform/", 9))
            name += 9;
    }

    list_for_each_reverse(node, &platform_names) {
        bus = node_to_item(node, struct platform_node, list);
        if ((bus->name_len < name_len) &&
                (name[bus->name_len] == '/') &&
                !strncmp(name, bus->name, bus->name_len))
        if ((bus->path_len < path_len) &&
                (path[bus->path_len] == '/') &&
                !strncmp(path, bus->path, bus->path_len))
            /* subdevice of an existing platform, ignore it */
            return;
    }

    INFO("adding platform device %s\n", name);
    INFO("adding platform device %s (%s)\n", name, path);

    bus = calloc(1, sizeof(struct platform_node));
    bus->name = strdup(name);
    bus->name_len = name_len;
    bus->path = strdup(path);
    bus->path_len = path_len;
    bus->name = bus->path + (name - path);
    list_add_tail(&platform_names, &bus->list);
}

/*
 * given a name that may start with a platform device, find the length of the
 * given a path that may start with a platform device, find the length of the
 * platform device prefix.  If it doesn't start with a platform device, return
 * 0.
 */
static const char *find_platform_device(const char *name)
static struct platform_node *find_platform_device(const char *path)
{
    int name_len = strlen(name);
    int path_len = strlen(path);
    struct listnode *node;
    struct platform_node *bus;

    list_for_each_reverse(node, &platform_names) {
        bus = node_to_item(node, struct platform_node, list);
        if ((bus->name_len < name_len) &&
                (name[bus->name_len] == '/') &&
                !strncmp(name, bus->name, bus->name_len))
            return bus->name;
        if ((bus->path_len < path_len) &&
                (path[bus->path_len] == '/') &&
                !strncmp(path, bus->path, bus->path_len))
            return bus;
    }

    return NULL;
}

static void remove_platform_device(const char *name)
static void remove_platform_device(const char *path)
{
    struct listnode *node;
    struct platform_node *bus;

    list_for_each_reverse(node, &platform_names) {
        bus = node_to_item(node, struct platform_node, list);
        if (!strcmp(name, bus->name)) {
            INFO("removing platform device %s\n", name);
            free(bus->name);
        if (!strcmp(path, bus->path)) {
            INFO("removing platform device %s\n", bus->name);
            free(bus->path);
            list_remove(node);
            free(bus);
            return;
@@ -355,8 +364,10 @@ static char **get_character_device_symlinks(struct uevent *uevent)
    char **links;
    int link_num = 0;
    int width;
    struct platform_node *pdev;

    if (strncmp(uevent->path, "/devices/platform/", 18))
    pdev = find_platform_device(uevent->path);
    if (!pdev)
        return NULL;

    links = malloc(sizeof(char *) * 2);
@@ -365,7 +376,7 @@ static char **get_character_device_symlinks(struct uevent *uevent)
    memset(links, 0, sizeof(char *) * 2);

    /* skip "/devices/platform/<driver>" */
    parent = strchr(uevent->path + 18, '/');
    parent = strchr(uevent->path + pdev->path_len, '/');
    if (!*parent)
        goto err;

@@ -402,7 +413,7 @@ err:
static char **parse_platform_block_device(struct uevent *uevent)
{
    const char *device;
    const char *path;
    struct platform_node *pdev;
    char *slash;
    int width;
    char buf[256];
@@ -414,18 +425,16 @@ static char **parse_platform_block_device(struct uevent *uevent)
    unsigned int size;
    struct stat info;

    pdev = find_platform_device(uevent->path);
    if (!pdev)
        return NULL;
    device = pdev->name;

    char **links = malloc(sizeof(char *) * 4);
    if (!links)
        return NULL;
    memset(links, 0, sizeof(char *) * 4);

    /* Drop "/devices/platform/" */
    path = uevent->path;
    device = path + 18;
    device = find_platform_device(device);
    if (!device)
        goto err;

    INFO("found platform device %s\n", device);

    snprintf(link_path, sizeof(link_path), "/dev/block/platform/%s", device);
@@ -447,17 +456,13 @@ static char **parse_platform_block_device(struct uevent *uevent)
            links[link_num] = NULL;
    }

    slash = strrchr(path, '/');
    slash = strrchr(uevent->path, '/');
    if (asprintf(&links[link_num], "%s/%s", link_path, slash + 1) > 0)
        link_num++;
    else
        links[link_num] = NULL;

    return links;

err:
    free(links);
    return NULL;
}

static void handle_device(const char *action, const char *devpath,
@@ -490,12 +495,12 @@ static void handle_device(const char *action, const char *devpath,

static void handle_platform_device_event(struct uevent *uevent)
{
    const char *name = uevent->path + 18; /* length of /devices/platform/ */
    const char *path = uevent->path;

    if (!strcmp(uevent->action, "add"))
        add_platform_device(name);
        add_platform_device(path);
    else if (!strcmp(uevent->action, "remove"))
        remove_platform_device(name);
        remove_platform_device(path);
}

static const char *parse_device_name(struct uevent *uevent, unsigned int len)
@@ -533,7 +538,7 @@ static void handle_block_device_event(struct uevent *uevent)
    snprintf(devpath, sizeof(devpath), "%s%s", base, name);
    make_dir(base, 0755);

    if (!strncmp(uevent->path, "/devices/platform/", 18))
    if (!strncmp(uevent->path, "/devices/", 9))
        links = parse_platform_block_device(uevent);

    handle_device(uevent->action, devpath, uevent->path, 1,