aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDima Zavin <dima@android.com>2013-03-06 16:23:57 -0800
committerGiulio Cervera <giulio.cervera@cyanogenmod.org>2013-09-05 22:13:53 +0200
commitba213e9edf578a3c661b32aece87b3dcdf5a4c1f (patch)
tree0688fd2b85ff4d9e01045b8c8619ef41cf8c6733
parentd7bf4df76836a8006a805fcff74a0ac5f3fa9850 (diff)
downloadsystem_core-ba213e9edf578a3c661b32aece87b3dcdf5a4c1f.zip
system_core-ba213e9edf578a3c661b32aece87b3dcdf5a4c1f.tar.gz
system_core-ba213e9edf578a3c661b32aece87b3dcdf5a4c1f.tar.bz2
ueventd: allow platform devices to have just a /devices/ prefix - DO NOT MERGE
When using device tree, platform devices may not have a /devices/platform/ path prefix, but can be rooted in /devices/. Modify the platform device tracking code to store the device path as well as the name. This way, when we create symlinks, we can correctly skip the base platform device prefix and get to the proper device node path. Change-Id: I939ef8fbcb45c5c803cd9a054e40136a912efc72 Signed-off-by: Dima Zavin <dima@android.com>
-rw-r--r--init/devices.c83
1 files changed, 44 insertions, 39 deletions
diff --git a/init/devices.c b/init/devices.c
index c30303f..ac54ced 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -87,7 +87,8 @@ struct perm_node {
struct platform_node {
char *name;
- int name_len;
+ char *path;
+ int path_len;
struct listnode list;
};
@@ -222,61 +223,69 @@ static void make_device(const char *path,
#endif
}
-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;
@@ -362,8 +371,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);
@@ -372,7 +383,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;
@@ -409,7 +420,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];
@@ -421,18 +432,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);
@@ -454,17 +463,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,
@@ -497,12 +502,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)
@@ -540,7 +545,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,