Initialize Tizen 2.3
[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 "haptic.h"
35
36 #define DEFAULT_HAPTIC_HANDLE   0xFFFF
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 static struct ff_effect ff_effect;
50 static char ff_path[PATH_MAX];
51 static int ff_use_count;
52 static int ff_fd;
53 static Ecore_Timer *timer;
54
55 static int ff_stop(int fd);
56 static Eina_Bool timer_cb(void *data)
57 {
58         /* stop previous vibration */
59         ff_stop(ff_fd);
60         _I("stop vibration by timer");
61
62         return ECORE_CALLBACK_CANCEL;
63 }
64
65 static int register_timer(int ms)
66 {
67         /* add new timer */
68         timer = ecore_timer_add(ms/1000.f, timer_cb, NULL);
69         if (!timer)
70                 return -EPERM;
71
72         return 0;
73 }
74
75 static int unregister_timer(void)
76 {
77         if (timer) {
78                 ecore_timer_del(timer);
79                 timer = NULL;
80         }
81
82         return 0;
83 }
84
85 static int ff_find_device(char *path, int size)
86 {
87         DIR *dir;
88         struct dirent *dent;
89         char ev_path[PATH_MAX];
90         unsigned long features[1+FF_MAX/sizeof(unsigned long)];
91         int fd, ret;
92
93         dir = opendir(DEV_INPUT);
94         if (!dir)
95                 return -errno;
96
97         while ((dent = readdir(dir))) {
98                 if (dent->d_type == DT_DIR ||
99                         !strstr(dent->d_name, "event"))
100                         continue;
101
102                 snprintf(ev_path, sizeof(ev_path), "%s/%s", DEV_INPUT, dent->d_name);
103
104                 fd = open(ev_path, O_RDWR);
105                 if (fd < 0)
106                         continue;
107
108                 /* get force feedback device */
109                 memset(features, 0, sizeof(features));
110                 ret = ioctl(fd, EVIOCGBIT(EV_FF, sizeof(features)), features);
111                 if (ret == -1) {
112                         close(fd);
113                         continue;
114                 }
115
116                 if (test_bit(FF_CONSTANT, features))
117                         _D("%s type : constant", ev_path);
118                 if (test_bit(FF_PERIODIC, features))
119                         _D("%s type : periodic", ev_path);
120                 if (test_bit(FF_SPRING, features))
121                         _D("%s type : spring", ev_path);
122                 if (test_bit(FF_FRICTION, features))
123                         _D("%s type : friction", ev_path);
124                 if (test_bit(FF_RUMBLE, features))
125                         _D("%s type : rumble", ev_path);
126
127                 if (test_bit(FF_PERIODIC, features)) {
128                         memcpy(ff_path, ev_path, strlen(ev_path));
129                         close(fd);
130                         closedir(dir);
131                         return 0;
132                 }
133
134                 close(fd);
135         }
136
137         closedir(dir);
138         return -1;
139 }
140
141 static int ff_play(int fd, int length, int level)
142 {
143         struct input_event play;
144         int r = 0;
145         double magnitude;
146
147         if (fd < 0)
148                 return -EINVAL;
149
150         /* unregister existing timer */
151         unregister_timer();
152
153         magnitude = (double)level/HAPTIC_MODULE_FEEDBACK_MAX;
154         magnitude *= PERIODIC_MAX_MAGNITUDE;
155
156         _I("info : magnitude(%d) length(%d)", (int)magnitude, length);
157
158         /* Set member variables in effect struct */
159         ff_effect.type = FF_PERIODIC;
160         if (!ff_effect.id)
161                 ff_effect.id = -1;
162         ff_effect.u.periodic.waveform = FF_SQUARE;
163         ff_effect.u.periodic.period = 0.1*0x100;        /* 0.1 second */
164         ff_effect.u.periodic.magnitude = (int)magnitude;
165         ff_effect.u.periodic.offset = 0;
166         ff_effect.u.periodic.phase = 0;
167         ff_effect.direction = 0x4000;   /* Along X axis */
168         ff_effect.u.periodic.envelope.attack_length = 0;
169         ff_effect.u.periodic.envelope.attack_level = 0;
170         ff_effect.u.periodic.envelope.fade_length = 0;
171         ff_effect.u.periodic.envelope.fade_level = 0;
172         ff_effect.trigger.button = 0;
173         ff_effect.trigger.interval = 0;
174         ff_effect.replay.length = length;
175         ff_effect.replay.delay = 0;
176
177         if (ioctl(fd, EVIOCSFF, &ff_effect) == -1) {
178                 /* workaround: if effect is erased, try one more */
179                 ff_effect.id = -1;
180                 if (ioctl(fd, EVIOCSFF, &ff_effect) == -1)
181                         return -errno;
182         }
183
184         /* Play vibration*/
185         play.type = EV_FF;
186         play.code = ff_effect.id;
187         play.value = 1; /* 1 : PLAY, 0 : STOP */
188
189         if (write(fd, (const void*)&play, sizeof(play)) == -1)
190                 return -errno;
191
192         /* register timer */
193         register_timer(length);
194
195         return 0;
196 }
197
198 static int ff_stop(int fd)
199 {
200         struct input_event stop;
201         int r = 0;
202
203         if (fd < 0)
204                 return -EINVAL;
205
206         /* Stop vibration */
207         stop.type = EV_FF;
208         stop.code = ff_effect.id;
209         stop.value = 0;
210
211         if (write(fd, (const void*)&stop, sizeof(stop)) == -1)
212                 return -errno;
213
214         return 0;
215 }
216
217 /* START: Haptic Module APIs */
218 static int get_device_count(int *count)
219 {
220         if (count)
221                 *count = 1;
222
223         return 0;
224 }
225
226 static int open_device(int device_index, int *device_handle)
227 {
228         /* open ff driver */
229         if (ff_use_count == 0) {
230                 ff_fd = open(ff_path, O_RDWR);
231                 if (!ff_fd) {
232                         _E("Failed to open %s : %s", ff_path, strerror(errno));
233                         return -errno;
234                 }
235         }
236
237         /* Increase handle count */
238         ff_use_count++;
239
240         if (device_handle)
241                 *device_handle = DEFAULT_HAPTIC_HANDLE;
242
243         return 0;
244 }
245
246 static int close_device(int device_handle)
247 {
248         if (device_handle != DEFAULT_HAPTIC_HANDLE)
249                 return -EINVAL;
250
251         if (ff_use_count == 0)
252                 return -EPERM;
253
254         ff_stop(ff_fd);
255
256         /* Decrease handle count */
257         ff_use_count--;
258
259         /* close ff driver */
260         if (ff_use_count == 0) {
261                 /* Initialize effect structure */
262                 memset(&ff_effect, 0, sizeof(ff_effect));
263                 close(ff_fd);
264                 ff_fd = -1;
265         }
266
267         return 0;
268 }
269
270 static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle)
271 {
272         if (device_handle != DEFAULT_HAPTIC_HANDLE)
273                 return -EINVAL;
274
275         return ff_play(ff_fd, duration, feedback);
276 }
277
278 static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle)
279 {
280         if (device_handle != DEFAULT_HAPTIC_HANDLE)
281                 return -EINVAL;
282
283         /* temporary code */
284         return ff_play(ff_fd, 300, feedback);
285 }
286
287 static int stop_device(int device_handle)
288 {
289         if (device_handle != DEFAULT_HAPTIC_HANDLE)
290                 return -EINVAL;
291
292         return ff_stop(ff_fd);
293 }
294
295 static int get_device_state(int device_index, int *effect_state)
296 {
297         int status;
298
299         if (ff_effect.id != 0)
300                 status = 1;
301         else
302                 status = 0;
303
304         if (effect_state)
305                 *effect_state = status;
306
307         return 0;
308 }
309
310 static int create_effect(unsigned char *vibe_buffer, int max_bufsize, haptic_module_effect_element *elem_arr, int max_elemcnt)
311 {
312         _E("Not support feature");
313         return -EACCES;
314 }
315
316 static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration)
317 {
318         if (device_handle != DEFAULT_HAPTIC_HANDLE)
319                 return -EINVAL;
320
321         _E("Not support feature");
322         return -EACCES;
323 }
324
325 static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path)
326 {
327         _E("Not support feature");
328         return -EACCES;
329 }
330 /* END: Haptic Module APIs */
331
332 static const struct haptic_plugin_ops default_plugin = {
333         .get_device_count    = get_device_count,
334         .open_device         = open_device,
335         .close_device        = close_device,
336         .vibrate_monotone    = vibrate_monotone,
337         .vibrate_buffer      = vibrate_buffer,
338         .stop_device         = stop_device,
339         .get_device_state    = get_device_state,
340         .create_effect       = create_effect,
341         .get_buffer_duration = get_buffer_duration,
342         .convert_binary      = convert_binary,
343 };
344
345 static bool is_valid(void)
346 {
347         int ret;
348
349         ret = ff_find_device(ff_path, sizeof(ff_path));
350
351         if (ret < 0)
352                 return false;
353
354         return true;
355 }
356
357 static const struct haptic_plugin_ops *load(void)
358 {
359         return &default_plugin;
360 }
361
362 static const struct haptic_ops std_ops = {
363         .is_valid = is_valid,
364         .load     = load,
365 };
366
367 HAPTIC_OPS_REGISTER(&std_ops)