4 * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
27 #include <sys/types.h>
30 #include <linux/input.h>
34 #include "core/list.h"
37 #define MAX_MAGNITUDE 0xFFFF
38 #define PERIODIC_MAX_MAGNITUDE 0x7FFF /* 0.5 * MAX_MAGNITUDE */
40 #define DEV_INPUT "/dev/input"
43 #define BITS_PER_LONG (sizeof(long) * 8)
44 #define OFF(x) ((x)%BITS_PER_LONG)
45 #define BIT(x) (1UL<<OFF(x))
46 #define LONG(x) ((x)/BITS_PER_LONG)
47 #define test_bit(bit, array) ((array[LONG(bit)] >> OFF(bit)) & 1)
52 struct ff_effect effect;
56 static dd_list *ff_list;
57 static char ff_path[PATH_MAX];
60 static void print_list(void)
66 DD_LIST_FOREACH(ff_list, elem, temp)
67 _D("[%d] %x", i++, temp);
70 static bool check_valid_handle(struct ff_info *info)
75 DD_LIST_FOREACH(ff_list, elem, temp) {
85 static int ff_stop(int fd, struct ff_effect *effect);
86 static Eina_Bool timer_cb(void *data)
88 struct ff_info *info = (struct ff_info*)data;
91 return ECORE_CALLBACK_CANCEL;
93 if (!check_valid_handle(info))
94 return ECORE_CALLBACK_CANCEL;
96 _I("stop vibration by timer : id(%d)", info->effect.id);
98 /* stop previous vibration */
99 ff_stop(ff_fd, &info->effect);
104 return ECORE_CALLBACK_CANCEL;
107 static int ff_find_device(void)
111 char ev_path[PATH_MAX];
112 unsigned long features[1+FF_MAX/sizeof(unsigned long)];
115 dir = opendir(DEV_INPUT);
119 while ((dent = readdir(dir))) {
120 if (dent->d_type == DT_DIR ||
121 !strstr(dent->d_name, "event"))
124 snprintf(ev_path, sizeof(ev_path), "%s/%s", DEV_INPUT, dent->d_name);
126 fd = open(ev_path, O_RDWR);
130 /* get force feedback device */
131 memset(features, 0, sizeof(features));
132 ret = ioctl(fd, EVIOCGBIT(EV_FF, sizeof(features)), features);
138 if (test_bit(FF_CONSTANT, features))
139 _D("%s type : constant", ev_path);
140 if (test_bit(FF_PERIODIC, features))
141 _D("%s type : periodic", ev_path);
142 if (test_bit(FF_SPRING, features))
143 _D("%s type : spring", ev_path);
144 if (test_bit(FF_FRICTION, features))
145 _D("%s type : friction", ev_path);
146 if (test_bit(FF_RUMBLE, features))
147 _D("%s type : rumble", ev_path);
149 if (test_bit(FF_PERIODIC, features)) {
150 memcpy(ff_path, ev_path, strlen(ev_path));
163 static int ff_init_effect(struct ff_effect *effect)
168 /* initialize member variables in effect struct */
169 effect->type = FF_PERIODIC;
171 effect->u.periodic.waveform = FF_SQUARE;
172 effect->u.periodic.period = 0.1*0x100; /* 0.1 second */
173 effect->u.periodic.magnitude = 0; /* temporary value */
174 effect->u.periodic.offset = 0;
175 effect->u.periodic.phase = 0;
176 effect->direction = 0x4000; /* Along X axis */
177 effect->u.periodic.envelope.attack_length = 0;
178 effect->u.periodic.envelope.attack_level = 0;
179 effect->u.periodic.envelope.fade_length = 0;
180 effect->u.periodic.envelope.fade_level = 0;
181 effect->trigger.button = 0;
182 effect->trigger.interval = 0;
183 effect->replay.length = 0; /* temporary value */
184 effect->replay.delay = 0;
189 static int ff_set_effect(struct ff_effect *effect, int length, int level)
196 magnitude = (double)level/HAPTIC_MODULE_FEEDBACK_MAX;
197 magnitude *= PERIODIC_MAX_MAGNITUDE;
199 _I("info : magnitude(%d) length(%d)", (int)magnitude, length);
201 /* set member variables in effect struct */
202 effect->u.periodic.magnitude = (int)magnitude;
203 effect->replay.length = length; /* length millisecond */
208 static int ff_play(int fd, struct ff_effect *effect)
210 struct input_event play;
212 if (fd < 0 || !effect)
215 /* upload an effect */
216 if (ioctl(fd, EVIOCSFF, effect) == -1)
221 play.code = effect->id;
222 play.value = 1; /* 1 : PLAY, 0 : STOP */
224 if (write(fd, (const void*)&play, sizeof(play)) == -1)
230 static int ff_stop(int fd, struct ff_effect *effect)
232 struct input_event stop;
239 stop.code = effect->id;
240 stop.value = 0; /* 1 : PLAY, 0 : STOP */
242 if (write(fd, (const void*)&stop, sizeof(stop)) == -1)
245 /* removing an effect from the device */
246 if (ioctl(fd, EVIOCRMFF, effect->id) == -1)
249 /* reset effect id */
255 /* START: Haptic Module APIs */
256 static int get_device_count(int *count)
258 /* suppose there is just one haptic device */
265 static int open_device(int device_index, int *device_handle)
267 struct ff_info *info;
273 /* if it is the first element */
274 n = DD_LIST_LENGTH(ff_list);
275 if (n == 0 && !ff_fd) {
276 _I("First element: open ff driver");
278 ff_fd = open(ff_path, O_RDWR);
280 _E("Failed to open %s : %s", ff_path, strerror(errno));
285 /* allocate memory */
286 info = calloc(sizeof(struct ff_info), 1);
288 _E("Failed to allocate memory : %s", strerror(errno));
292 /* initialize ff_effect structure */
293 ff_init_effect(&info->effect);
295 /* add info to local list */
296 DD_LIST_APPEND(ff_list, info);
298 *device_handle = (int)info;
302 static int close_device(int device_handle)
304 struct ff_info *info = (struct ff_info*)device_handle;
310 if (!check_valid_handle(info))
314 r = ff_stop(ff_fd, &info->effect);
316 _I("already stopped or failed to stop effect : %d", r);
318 /* unregister existing timer */
319 if (r >= 0 && info->timer) {
320 ecore_timer_del(info->timer);
324 /* remove info from local list */
325 DD_LIST_REMOVE(ff_list, info);
328 /* if it is the last element */
329 n = DD_LIST_LENGTH(ff_list);
330 if (n == 0 && ff_fd) {
331 _I("Last element: close ff driver");
332 /* close ff driver */
340 static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle)
342 struct ff_info *info = (struct ff_info*)device_handle;
348 if (!check_valid_handle(info))
351 /* Zero(0) is the infinitely vibration value */
352 if (duration == HAPTIC_MODULE_DURATION_UNLIMITED)
355 /* set effect as per arguments */
356 ret = ff_set_effect(&info->effect, duration, feedback);
358 _E("failed to set effect(duration:%d, feedback:%d) : %d",
359 duration, feedback, ret);
363 /* play effect as per arguments */
364 ret = ff_play(ff_fd, &info->effect);
366 _E("failed to play haptic effect(id:%d) : %d",
367 info->effect.id, ret);
371 /* unregister existing timer */
373 ecore_timer_del(info->timer);
379 info->timer = ecore_timer_add(duration/1000.f, timer_cb, info);
381 _E("Failed to add timer callback");
384 _D("effect id : %d", info->effect.id);
386 *effect_handle = info->effect.id;
391 static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle)
394 return vibrate_monotone(device_handle, 300, feedback, priority, effect_handle);
397 static int stop_device(int device_handle)
399 struct ff_info *info = (struct ff_info*)device_handle;
405 if (!check_valid_handle(info))
409 r = ff_stop(ff_fd, &info->effect);
411 _E("failed to stop effect(id:%d) : %d", info->effect.id, r);
413 /* unregister existing timer */
414 if (r >= 0 && info->timer) {
415 ecore_timer_del(info->timer);
422 static int get_device_state(int device_index, int *effect_state)
424 struct ff_info *info;
426 int n, status = false;
431 /* suppose there is just one haptic device */
432 DD_LIST_FOREACH(ff_list, elem, info) {
433 if (info->effect.id >= 0) {
439 *effect_state = status;
443 static int create_effect(unsigned char *vibe_buffer, int max_bufsize, haptic_module_effect_element *elem_arr, int max_elemcnt)
445 _E("Not support feature");
449 static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration)
451 _E("Not support feature");
455 static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path)
457 _E("Not support feature");
460 /* END: Haptic Module APIs */
462 static const struct haptic_plugin_ops default_plugin = {
463 .get_device_count = get_device_count,
464 .open_device = open_device,
465 .close_device = close_device,
466 .vibrate_monotone = vibrate_monotone,
467 .vibrate_buffer = vibrate_buffer,
468 .stop_device = stop_device,
469 .get_device_state = get_device_state,
470 .create_effect = create_effect,
471 .get_buffer_duration = get_buffer_duration,
472 .convert_binary = convert_binary,
475 static bool is_valid(void)
479 ret = ff_find_device();
481 _I("Do not support standard haptic device");
485 _I("Support standard haptic device");
489 static const struct haptic_plugin_ops *load(void)
491 return &default_plugin;
494 static const struct haptic_ops std_ops = {
495 .type = HAPTIC_STANDARD,
496 .is_valid = is_valid,
500 HAPTIC_OPS_REGISTER(&std_ops)