diff options
-rwxr-xr-x | BoardConfig.mk | 3 | ||||
-rw-r--r-- | overlay/packages/inputmethods/LatinIME/java/res/values/config.xml | 20 | ||||
-rw-r--r-- | vibrator/vibrator.c | 188 |
3 files changed, 211 insertions, 0 deletions
diff --git a/BoardConfig.mk b/BoardConfig.mk index e3a564a..d4f6f73 100755 --- a/BoardConfig.mk +++ b/BoardConfig.mk @@ -65,6 +65,9 @@ USE_CAMERA_STUB := true BOARD_HAS_NO_SELECT_BUTTON := true +# Vibrator +BOARD_HAS_VIBRATOR_IMPLEMENTATION := ../../device/goldelico/gta04/vibrator/vibrator.c + # Boot animation TARGET_BOOTANIMATION_PRELOAD := true TARGET_BOOTANIMATION_TEXTURE_CACHE := true diff --git a/overlay/packages/inputmethods/LatinIME/java/res/values/config.xml b/overlay/packages/inputmethods/LatinIME/java/res/values/config.xml new file mode 100644 index 0000000..3bab366 --- /dev/null +++ b/overlay/packages/inputmethods/LatinIME/java/res/values/config.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2014 Paul Kocialkowski <contact@paulk.fr> + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + --> + +<resources> + <bool name="config_default_vibration_enabled">false</bool> +</resources> diff --git a/vibrator/vibrator.c b/vibrator/vibrator.c new file mode 100644 index 0000000..5d8d203 --- /dev/null +++ b/vibrator/vibrator.c @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2014 Paul Kocialkowski <contact@paulk.fr> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <dirent.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <linux/input.h> + +#define LOG_TAG "vibrator" +#include <cutils/log.h> + +/* + * Globals + */ + +const char rumble_input[] = "twl4030:vibrator"; + +int rumble_fd = -1; +int rumble_id = -1; + +/* + * Input + */ + +void input_event_set(struct input_event *event, int type, int code, int value) +{ + if (event == NULL) + return; + + memset(event, 0, sizeof(struct input_event)); + + event->type = type, + event->code = code; + event->value = value; + + gettimeofday(&event->time, NULL); +} + +int input_open(const char *name) +{ + DIR *d; + struct dirent *di; + + char input_name[80] = { 0 }; + char path[PATH_MAX]; + char *c; + int fd; + int rc; + + if (name == NULL) + return -EINVAL; + + d = opendir("/dev/input"); + if (d == NULL) + return -1; + + while ((di = readdir(d))) { + if (di == NULL || strcmp(di->d_name, ".") == 0 || strcmp(di->d_name, "..") == 0) + continue; + + snprintf(path, PATH_MAX, "/dev/input/%s", di->d_name); + fd = open(path, O_RDWR | O_NONBLOCK); + if (fd < 0) + continue; + + rc = ioctl(fd, EVIOCGNAME(sizeof(input_name) - 1), &input_name); + if (rc < 0) + continue; + + c = strstr((char *) &input_name, "\n"); + if (c != NULL) + *c = '\0'; + + if (strcmp(input_name, name) == 0) + return fd; + else + close(fd); + } + + return -1; +} + +/* + * Vibrator + */ + +int vibrator_exists(void) +{ + int fd; + + fd = input_open(rumble_input); + if (fd < 0) + return 0; + + close(fd); + + return 1; +} + +int sendit(int duration) +{ + struct input_event event; + struct ff_effect effect; + int rc; + + if (rumble_fd < 0) + rumble_fd = input_open(rumble_input); + + if (rumble_fd < 0) + goto error; + + if (rumble_id >= 0) { + input_event_set(&event, EV_FF, rumble_id, 0); + + rc = write(rumble_fd, &event, sizeof(event)); + if (rc < (int) sizeof(event)) + goto error; + + ioctl(rumble_fd, EVIOCRMFF, &rumble_id); + + rumble_id = -1; + } + + // Previous code should have removed the effect already + if (duration == 0) { + rc = 0; + goto complete; + } + + memset(&effect, 0, sizeof(effect)); + effect.type = FF_RUMBLE; + effect.id = -1; + effect.replay.length = duration; + effect.replay.delay = 0; + effect.u.rumble.strong_magnitude = 0xffff; + + rc = ioctl(rumble_fd, EVIOCSFF, &effect); + if (rc < 0) + goto error; + + rumble_id = effect.id; + + input_event_set(&event, EV_FF, rumble_id, 1); + + rc = write(rumble_fd, &event, sizeof(event)); + if (rc < (int) sizeof(event)) + goto error; + + rc = 0; + goto complete; + +error: + if (rumble_fd >= 0) { + if (rumble_id >= 0) { + input_event_set(&event, EV_FF, rumble_id, 0); + write(rumble_fd, &event, sizeof(event)); + + ioctl(rumble_fd, EVIOCRMFF, &rumble_id); + rumble_id = -1; + } + + close(rumble_fd); + rumble_fd = -1; + } + + rc = -1; + +complete: + return rc; +} |