diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:25 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:25 -0800 |
commit | 5ae090ed949cea9d1e7ab1552b455a229f8f9757 (patch) | |
tree | 555f686d531f29f4907d80655e7b0a7e69f2a180 /init | |
parent | 35237d135807af84bf9b0e5b8d7f8633e58db6f5 (diff) | |
download | system_core-5ae090ed949cea9d1e7ab1552b455a229f8f9757.zip system_core-5ae090ed949cea9d1e7ab1552b455a229f8f9757.tar.gz system_core-5ae090ed949cea9d1e7ab1552b455a229f8f9757.tar.bz2 |
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'init')
-rw-r--r-- | init/devices.c | 1 | ||||
-rw-r--r-- | init/init.c | 157 | ||||
-rw-r--r-- | init/init.h | 7 | ||||
-rw-r--r-- | init/keywords.h | 1 | ||||
-rw-r--r-- | init/parser.c | 45 |
5 files changed, 183 insertions, 28 deletions
diff --git a/init/devices.c b/init/devices.c index f86eab9..44e263d 100644 --- a/init/devices.c +++ b/init/devices.c @@ -122,6 +122,7 @@ static struct perms_ devperms[] = { { "/dev/msm_pcm_out", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/msm_pcm_in", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/msm_pcm_ctl", 0660, AID_SYSTEM, AID_AUDIO, 1 }, + { "/dev/msm_snd", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 }, { "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 }, diff --git a/init/init.c b/init/init.c index 3616840..b8b4f40 100644 --- a/init/init.c +++ b/init/init.c @@ -37,6 +37,7 @@ #include <cutils/sockets.h> #include <termios.h> #include <linux/kd.h> +#include <linux/keychord.h> #include <sys/system_properties.h> @@ -60,6 +61,9 @@ static char bootloader[32]; static char hardware[32]; static unsigned revision = 0; static char qemu[32]; +static struct input_keychord *keychords = 0; +static int keychords_count = 0; +static int keychords_length = 0; static void drain_action_queue(void); @@ -233,7 +237,7 @@ void service_start(struct service *svc) setpgid(0, getpid()); - /* as requested, set our gid, supplemental gids, and uid */ + /* as requested, set our gid, supplemental gids, and uid */ if (svc->gid) { setgid(svc->gid); } @@ -658,17 +662,101 @@ void open_devnull_stdio(void) exit(1); } +void add_service_keycodes(struct service *svc) +{ + struct input_keychord *keychord; + int i, size; + + if (svc->keycodes) { + /* add a new keychord to the list */ + size = sizeof(*keychord) + svc->nkeycodes * sizeof(keychord->keycodes[0]); + keychords = realloc(keychords, keychords_length + size); + if (!keychords) { + ERROR("could not allocate keychords\n"); + keychords_length = 0; + keychords_count = 0; + return; + } + + keychord = (struct input_keychord *)((char *)keychords + keychords_length); + keychord->version = KEYCHORD_VERSION; + keychord->id = keychords_count + 1; + keychord->count = svc->nkeycodes; + svc->keychord_id = keychord->id; + + for (i = 0; i < svc->nkeycodes; i++) { + keychord->keycodes[i] = svc->keycodes[i]; + } + keychords_count++; + keychords_length += size; + } +} + +int open_keychord() +{ + int fd, ret; + + service_for_each(add_service_keycodes); + + /* nothing to do if no services require keychords */ + if (!keychords) + return -1; + + fd = open("/dev/keychord", O_RDWR); + if (fd < 0) { + ERROR("could not open /dev/keychord\n"); + return fd; + } + fcntl(fd, F_SETFD, FD_CLOEXEC); + + ret = write(fd, keychords, keychords_length); + if (ret != keychords_length) { + ERROR("could not configure /dev/keychord %d (%d)\n", ret, errno); + close(fd); + fd = -1; + } + + free(keychords); + keychords = 0; + + return fd; +} + +void handle_keychord(int fd) +{ + struct service *svc; + int ret; + __u16 id; + + ret = read(fd, &id, sizeof(id)); + if (ret != sizeof(id)) { + ERROR("could not read keychord id\n"); + return; + } + + svc = service_find_by_keychord(id); + if (svc) { + INFO("starting service %s from keychord\n", svc->name); + service_start(svc); + } else { + ERROR("service for keychord %d not found\n", id); + } +} + int main(int argc, char **argv) { int device_fd = -1; int property_set_fd = -1; int signal_recv_fd = -1; + int keychord_fd = -1; + int fd_count; int s[2]; int fd; struct sigaction act; char tmp[PROP_VALUE_MAX]; struct pollfd ufds[4]; char *tmpdev; + char* debuggable; act.sa_handler = sigchld_handler; act.sa_flags = SA_NOCLDSTOP; @@ -721,6 +809,12 @@ int main(int argc, char **argv) device_fd = device_init(); property_init(); + + // only listen for keychords if ro.debuggable is true + debuggable = property_get("ro.debuggable"); + if (debuggable && !strcmp(debuggable, "1")) { + keychord_fd = open_keychord(); + } if (console[0]) { snprintf(tmp, sizeof(tmp), "/dev/%s", console); @@ -733,27 +827,27 @@ int main(int argc, char **argv) close(fd); if( load_565rle_image(INIT_IMAGE_FILE) ) { - fd = open("/dev/tty0", O_WRONLY); - if (fd >= 0) { - const char *msg; + fd = open("/dev/tty0", O_WRONLY); + if (fd >= 0) { + const char *msg; msg = "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" // console is 40 cols x 30 lines - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - " A N D R O I D "; - write(fd, msg, strlen(msg)); - close(fd); - } + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" // console is 40 cols x 30 lines + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + " A N D R O I D "; + write(fd, msg, strlen(msg)); + close(fd); + } } if (qemu[0]) @@ -823,6 +917,16 @@ int main(int argc, char **argv) ufds[1].events = POLLIN; ufds[2].fd = signal_recv_fd; ufds[2].events = POLLIN; + fd_count = 3; + + if (keychord_fd > 0) { + ufds[3].fd = keychord_fd; + ufds[3].events = POLLIN; + fd_count++; + } else { + ufds[3].events = 0; + ufds[3].revents = 0; + } #if BOOTCHART bootchart_count = bootchart_init(); @@ -836,11 +940,10 @@ int main(int argc, char **argv) #endif for(;;) { - int nr, timeout = -1; + int nr, i, timeout = -1; - ufds[0].revents = 0; - ufds[1].revents = 0; - ufds[2].revents = 0; + for (i = 0; i < fd_count; i++) + ufds[i].revents = 0; drain_action_queue(); restart_processes(); @@ -861,7 +964,7 @@ int main(int argc, char **argv) } } #endif - nr = poll(ufds, 3, timeout); + nr = poll(ufds, fd_count, timeout); if (nr <= 0) continue; @@ -878,6 +981,8 @@ int main(int argc, char **argv) if (ufds[1].revents == POLLIN) handle_property_set_fd(property_set_fd); + if (ufds[3].revents == POLLIN) + handle_keychord(keychord_fd); } return 0; diff --git a/init/init.h b/init/init.h index 4ff0c69..b686869 100644 --- a/init/init.h +++ b/init/init.h @@ -139,12 +139,19 @@ struct service { int nargs; char *args[1]; struct action onrestart; /* Actions to execute on restart. */ + + /* keycodes for triggering this service via /dev/keychord */ + int *keycodes; + int nkeycodes; + int keychord_id; }; int parse_config_file(const char *fn); struct service *service_find_by_name(const char *name); struct service *service_find_by_pid(pid_t pid); +struct service *service_find_by_keychord(int keychord_id); +void service_for_each(void (*func)(struct service *svc)); void service_for_each_class(const char *classname, void (*func)(struct service *svc)); void service_for_each_flags(unsigned matchflags, diff --git a/init/keywords.h b/init/keywords.h index 058996e..6f47379 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -45,6 +45,7 @@ enum { KEYWORD(ifup, COMMAND, 1, do_ifup) KEYWORD(insmod, COMMAND, 1, do_insmod) KEYWORD(import, COMMAND, 1, do_import) + KEYWORD(keycodes, OPTION, 0, 0) KEYWORD(mkdir, COMMAND, 1, do_mkdir) KEYWORD(mount, COMMAND, 3, do_mount) KEYWORD(on, SECTION, 0, 0) diff --git a/init/parser.c b/init/parser.c index a51691b..6a22d24 100644 --- a/init/parser.c +++ b/init/parser.c @@ -158,6 +158,9 @@ int lookup_keyword(const char *s) if (!strcmp(s, "nsmod")) return K_insmod; if (!strcmp(s, "mport")) return K_import; break; + case 'k': + if (!strcmp(s, "eycodes")) return K_keycodes; + break; case 'l': if (!strcmp(s, "oglevel")) return K_loglevel; break; @@ -183,7 +186,7 @@ int lookup_keyword(const char *s) if (!strcmp(s, "tart")) return K_start; if (!strcmp(s, "top")) return K_stop; if (!strcmp(s, "ymlink")) return K_symlink; - if (!strcmp(s, "ysclktz")) return K_sysclktz; + if (!strcmp(s, "ysclktz")) return K_sysclktz; break; case 't': if (!strcmp(s, "rigger")) return K_trigger; @@ -440,6 +443,29 @@ struct service *service_find_by_pid(pid_t pid) return 0; } +struct service *service_find_by_keychord(int keychord_id) +{ + struct listnode *node; + struct service *svc; + list_for_each(node, &service_list) { + svc = node_to_item(node, struct service, slist); + if (svc->keychord_id == keychord_id) { + return svc; + } + } + return 0; +} + +void service_for_each(void (*func)(struct service *svc)) +{ + struct listnode *node; + struct service *svc; + list_for_each(node, &service_list) { + svc = node_to_item(node, struct service, slist); + func(svc); + } +} + void service_for_each_class(const char *classname, void (*func)(struct service *svc)) { @@ -586,7 +612,7 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args { struct service *svc = state->context; struct command *cmd; - int kw, kw_nargs; + int i, kw, kw_nargs; if (nargs == 0) { return; @@ -624,6 +650,21 @@ static void parse_line_service(struct parse_state *state, int nargs, char **args svc->nr_supp_gids = n - 2; } break; + case K_keycodes: + if (nargs < 2) { + parse_error(state, "keycodes option requires atleast one keycode\n"); + } else { + svc->keycodes = malloc((nargs - 1) * sizeof(svc->keycodes[0])); + if (!svc->keycodes) { + parse_error(state, "could not allocate keycodes\n"); + } else { + svc->nkeycodes = nargs - 1; + for (i = 1; i < nargs; i++) { + svc->keycodes[i - 1] = atoi(args[i]); + } + } + } + break; case K_oneshot: svc->flags |= SVC_ONESHOT; break; |