tizen 2.3 release
[framework/system/deviced.git] / src / haptic / standard.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18
19
20 #include <stdio.h>
21 #include <stdbool.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <limits.h>
27 #include <sys/types.h>
28 #include <fcntl.h>
29 #include <dirent.h>
30 #include <linux/input.h>
31 #include <Ecore.h>
32
33 #include "core/log.h"
34 #include "core/list.h"
35 #include "haptic.h"
36
37 #define MAX_MAGNITUDE                   0xFFFF
38 #define PERIODIC_MAX_MAGNITUDE  0x7FFF  /* 0.5 * MAX_MAGNITUDE */
39
40 #define DEV_INPUT   "/dev/input"
41 #define EVENT           "event"
42
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)
48
49
50 struct ff_info {
51         Ecore_Timer *timer;
52         struct ff_effect effect;
53 };
54
55 static int ff_fd;
56 static dd_list *ff_list;
57 static char ff_path[PATH_MAX];
58
59 /* for debug */
60 static void print_list(void)
61 {
62         struct ff_info *temp;
63         dd_list *elem;
64         int i = 0;
65
66         DD_LIST_FOREACH(ff_list, elem, temp)
67                 _D("[%d] %x", i++, temp);
68 }
69
70 static bool check_valid_handle(struct ff_info *info)
71 {
72         struct ff_info *temp;
73         dd_list *elem;
74
75         DD_LIST_FOREACH(ff_list, elem, temp) {
76                 if (temp == info)
77                         break;
78         }
79
80         if (!temp)
81                 return false;
82         return true;
83 }
84
85 static int ff_stop(int fd, struct ff_effect *effect);
86 static Eina_Bool timer_cb(void *data)
87 {
88         struct ff_info *info = (struct ff_info*)data;
89
90         if (!info)
91                 return ECORE_CALLBACK_CANCEL;
92
93         if (!check_valid_handle(info))
94                 return ECORE_CALLBACK_CANCEL;
95
96         _I("stop vibration by timer : id(%d)", info->effect.id);
97
98         /* stop previous vibration */
99         ff_stop(ff_fd, &info->effect);
100
101         /* reset timer */
102         info->timer = NULL;
103
104         return ECORE_CALLBACK_CANCEL;
105 }
106
107 static int ff_find_device(void)
108 {
109         DIR *dir;
110         struct dirent *dent;
111         char ev_path[PATH_MAX];
112         unsigned long features[1+FF_MAX/sizeof(unsigned long)];
113         int fd, ret;
114
115         dir = opendir(DEV_INPUT);
116         if (!dir)
117                 return -errno;
118
119         while ((dent = readdir(dir))) {
120                 if (dent->d_type == DT_DIR ||
121                         !strstr(dent->d_name, "event"))
122                         continue;
123
124                 snprintf(ev_path, sizeof(ev_path), "%s/%s", DEV_INPUT, dent->d_name);
125
126                 fd = open(ev_path, O_RDWR);
127                 if (fd < 0)
128                         continue;
129
130                 /* get force feedback device */
131                 memset(features, 0, sizeof(features));
132                 ret = ioctl(fd, EVIOCGBIT(EV_FF, sizeof(features)), features);
133                 if (ret == -1) {
134                         close(fd);
135                         continue;
136                 }
137
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);
148
149                 if (test_bit(FF_PERIODIC, features)) {
150                         memcpy(ff_path, ev_path, strlen(ev_path));
151                         close(fd);
152                         closedir(dir);
153                         return 0;
154                 }
155
156                 close(fd);
157         }
158
159         closedir(dir);
160         return -1;
161 }
162
163 static int ff_init_effect(struct ff_effect *effect)
164 {
165         if (!effect)
166                 return -EINVAL;
167
168         /* initialize member variables in effect struct */
169         effect->type = FF_PERIODIC;
170         effect->id = -1;
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;
185
186         return 0;
187 }
188
189 static int ff_set_effect(struct ff_effect *effect, int length, int level)
190 {
191         double magnitude;
192
193         if (!effect)
194                 return -EINVAL;
195
196         magnitude = (double)level/HAPTIC_MODULE_FEEDBACK_MAX;
197         magnitude *= PERIODIC_MAX_MAGNITUDE;
198
199         _I("info : magnitude(%d) length(%d)", (int)magnitude, length);
200
201         /* set member variables in effect struct */
202         effect->u.periodic.magnitude = (int)magnitude;
203         effect->replay.length = length;         /* length millisecond */
204
205         return 0;
206 }
207
208 static int ff_play(int fd, struct ff_effect *effect)
209 {
210         struct input_event play;
211
212         if (fd < 0 || !effect)
213                 return -EINVAL;
214
215         /* upload an effect */
216         if (ioctl(fd, EVIOCSFF, effect) == -1)
217                 return -errno;
218
219         /* play vibration*/
220         play.type = EV_FF;
221         play.code = effect->id;
222         play.value = 1; /* 1 : PLAY, 0 : STOP */
223
224         if (write(fd, (const void*)&play, sizeof(play)) == -1)
225                 return -errno;
226
227         return 0;
228 }
229
230 static int ff_stop(int fd, struct ff_effect *effect)
231 {
232         struct input_event stop;
233
234         if (fd < 0)
235                 return -EINVAL;
236
237         /* Stop vibration */
238         stop.type = EV_FF;
239         stop.code = effect->id;
240         stop.value = 0; /* 1 : PLAY, 0 : STOP */
241
242         if (write(fd, (const void*)&stop, sizeof(stop)) == -1)
243                 return -errno;
244
245         /* removing an effect from the device */
246         if (ioctl(fd, EVIOCRMFF, effect->id) == -1)
247                 return -errno;
248
249         /* reset effect id */
250         effect->id = -1;
251
252         return 0;
253 }
254
255 /* START: Haptic Module APIs */
256 static int get_device_count(int *count)
257 {
258         /* suppose there is just one haptic device */
259         if (count)
260                 *count = 1;
261
262         return 0;
263 }
264
265 static int open_device(int device_index, int *device_handle)
266 {
267         struct ff_info *info;
268         int n;
269
270         if (!device_handle)
271                 return -EINVAL;
272
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");
277                 /* open ff driver */
278                 ff_fd = open(ff_path, O_RDWR);
279                 if (!ff_fd) {
280                         _E("Failed to open %s : %s", ff_path, strerror(errno));
281                         return -errno;
282                 }
283         }
284
285         /* allocate memory */
286         info = calloc(sizeof(struct ff_info), 1);
287         if (!info) {
288                 _E("Failed to allocate memory : %s", strerror(errno));
289                 return -errno;
290         }
291
292         /* initialize ff_effect structure */
293         ff_init_effect(&info->effect);
294
295         /* add info to local list */
296         DD_LIST_APPEND(ff_list, info);
297
298         *device_handle = (int)info;
299         return 0;
300 }
301
302 static int close_device(int device_handle)
303 {
304         struct ff_info *info = (struct ff_info*)device_handle;
305         int r, n;
306
307         if (!info)
308                 return -EINVAL;
309
310         if (!check_valid_handle(info))
311                 return -EINVAL;
312
313         /* stop vibration */
314         r = ff_stop(ff_fd, &info->effect);
315         if (r < 0)
316                 _I("already stopped or failed to stop effect : %d", r);
317
318         /* unregister existing timer */
319         if (r >= 0 && info->timer) {
320                 ecore_timer_del(info->timer);
321                 info->timer = NULL;
322         }
323
324         /* remove info from local list */
325         DD_LIST_REMOVE(ff_list, info);
326         safe_free(info);
327
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 */
333                 close(ff_fd);
334                 ff_fd = 0;
335         }
336
337         return 0;
338 }
339
340 static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle)
341 {
342         struct ff_info *info = (struct ff_info*)device_handle;
343         int ret;
344
345         if (!info)
346                 return -EINVAL;
347
348         if (!check_valid_handle(info))
349                 return -EINVAL;
350
351         /* Zero(0) is the infinitely vibration value */
352         if (duration == HAPTIC_MODULE_DURATION_UNLIMITED)
353                 duration = 0;
354
355         /* set effect as per arguments */
356         ret = ff_set_effect(&info->effect, duration, feedback);
357         if (ret < 0) {
358                 _E("failed to set effect(duration:%d, feedback:%d) : %d",
359                                 duration, feedback, ret);
360                 return ret;
361         }
362
363         /* play effect as per arguments */
364         ret = ff_play(ff_fd, &info->effect);
365         if (ret < 0) {
366                 _E("failed to play haptic effect(id:%d) : %d",
367                                 info->effect.id, ret);
368                 return ret;
369         }
370
371         /* unregister existing timer */
372         if (info->timer) {
373                 ecore_timer_del(info->timer);
374                 info->timer = NULL;
375         }
376
377         /* register timer */
378         if (duration) {
379                 info->timer = ecore_timer_add(duration/1000.f, timer_cb, info);
380                 if (!info->timer)
381                         _E("Failed to add timer callback");
382         }
383
384         _D("effect id : %d", info->effect.id);
385         if (effect_handle)
386                 *effect_handle = info->effect.id;
387
388         return 0;
389 }
390
391 static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle)
392 {
393         /* temporary code */
394         return vibrate_monotone(device_handle, 300, feedback, priority, effect_handle);
395 }
396
397 static int stop_device(int device_handle)
398 {
399         struct ff_info *info = (struct ff_info*)device_handle;
400         int r;
401
402         if (!info)
403                 return -EINVAL;
404
405         if (!check_valid_handle(info))
406                 return -EINVAL;
407
408         /* stop effect */
409         r = ff_stop(ff_fd, &info->effect);
410         if (r < 0)
411                 _E("failed to stop effect(id:%d) : %d", info->effect.id, r);
412
413         /* unregister existing timer */
414         if (r >= 0 && info->timer) {
415                 ecore_timer_del(info->timer);
416                 info->timer = NULL;
417         }
418
419         return 0;
420 }
421
422 static int get_device_state(int device_index, int *effect_state)
423 {
424         struct ff_info *info;
425         dd_list *elem;
426         int n, status = false;
427
428         if (!effect_state)
429                 return -EINVAL;
430
431         /* suppose there is just one haptic device */
432         DD_LIST_FOREACH(ff_list, elem, info) {
433                 if (info->effect.id >= 0) {
434                         status = true;
435                         break;
436                 }
437         }
438
439         *effect_state = status;
440         return 0;
441 }
442
443 static int create_effect(unsigned char *vibe_buffer, int max_bufsize, haptic_module_effect_element *elem_arr, int max_elemcnt)
444 {
445         _E("Not support feature");
446         return -EACCES;
447 }
448
449 static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration)
450 {
451         _E("Not support feature");
452         return -EACCES;
453 }
454
455 static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path)
456 {
457         _E("Not support feature");
458         return -EACCES;
459 }
460 /* END: Haptic Module APIs */
461
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,
473 };
474
475 static bool is_valid(void)
476 {
477         int ret;
478
479         ret = ff_find_device();
480         if (ret < 0) {
481                 _I("Do not support standard haptic device");
482                 return false;
483         }
484
485         _I("Support standard haptic device");
486         return true;
487 }
488
489 static const struct haptic_plugin_ops *load(void)
490 {
491         return &default_plugin;
492 }
493
494 static const struct haptic_ops std_ops = {
495         .type     = HAPTIC_STANDARD,
496         .is_valid = is_valid,
497         .load     = load,
498 };
499
500 HAPTIC_OPS_REGISTER(&std_ops)