summaryrefslogtreecommitdiffstats
path: root/init/devices.c
diff options
context:
space:
mode:
authorDima Zavin <dima@android.com>2013-03-06 16:23:57 -0800
committerDima Zavin <dima@android.com>2013-03-06 17:11:56 -0800
commit895c1b2c97a70ac6b9837354311e6c118c31172a (patch)
tree3e93e6af9152e22b362d4a17dcf15e121f396e39 /init/devices.c
parent9c4d9cdaf0ee0dbbf5d70d788f06f1086dde4f24 (diff)
downloadsystem_core-895c1b2c97a70ac6b9837354311e6c118c31172a.zip
system_core-895c1b2c97a70ac6b9837354311e6c118c31172a.tar.gz
system_core-895c1b2c97a70ac6b9837354311e6c118c31172a.tar.bz2
ueventd: allow platform devices to have just a /devices/ prefix
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>
Diffstat (limited to 'init/devices.c')
-rw-r--r--init/devices.c83
1 files changed, 44 insertions, 39 deletions
diff --git a/init/devices.c b/init/devices.c
index b07a1a6..e25034c 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -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,