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>
36 #define DEFAULT_HAPTIC_HANDLE 0xFFFF
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)
49 static struct ff_effect ff_effect;
50 static char ff_path[PATH_MAX];
51 static int ff_use_count;
53 static Ecore_Timer *timer;
55 static int ff_stop(int fd);
56 static Eina_Bool timer_cb(void *data)
58 /* stop previous vibration */
60 _I("stop vibration by timer");
62 return ECORE_CALLBACK_CANCEL;
65 static int register_timer(int ms)
68 timer = ecore_timer_add(ms/1000.f, timer_cb, NULL);
75 static int unregister_timer(void)
78 ecore_timer_del(timer);
85 static int ff_find_device(char *path, int size)
89 char ev_path[PATH_MAX];
90 unsigned long features[1+FF_MAX/sizeof(unsigned long)];
93 dir = opendir(DEV_INPUT);
97 while ((dent = readdir(dir))) {
98 if (dent->d_type == DT_DIR ||
99 !strstr(dent->d_name, "event"))
102 snprintf(ev_path, sizeof(ev_path), "%s/%s", DEV_INPUT, dent->d_name);
104 fd = open(ev_path, O_RDWR);
108 /* get force feedback device */
109 memset(features, 0, sizeof(features));
110 ret = ioctl(fd, EVIOCGBIT(EV_FF, sizeof(features)), features);
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);
127 if (test_bit(FF_PERIODIC, features)) {
128 memcpy(ff_path, ev_path, strlen(ev_path));
141 static int ff_play(int fd, int length, int level)
143 struct input_event play;
150 /* unregister existing timer */
153 magnitude = (double)level/HAPTIC_MODULE_FEEDBACK_MAX;
154 magnitude *= PERIODIC_MAX_MAGNITUDE;
156 _I("info : magnitude(%d) length(%d)", (int)magnitude, length);
158 /* Set member variables in effect struct */
159 ff_effect.type = FF_PERIODIC;
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;
177 if (ioctl(fd, EVIOCSFF, &ff_effect) == -1) {
178 /* workaround: if effect is erased, try one more */
180 if (ioctl(fd, EVIOCSFF, &ff_effect) == -1)
186 play.code = ff_effect.id;
187 play.value = 1; /* 1 : PLAY, 0 : STOP */
189 if (write(fd, (const void*)&play, sizeof(play)) == -1)
193 register_timer(length);
198 static int ff_stop(int fd)
200 struct input_event stop;
208 stop.code = ff_effect.id;
211 if (write(fd, (const void*)&stop, sizeof(stop)) == -1)
217 /* START: Haptic Module APIs */
218 static int get_device_count(int *count)
226 static int open_device(int device_index, int *device_handle)
229 if (ff_use_count == 0) {
230 ff_fd = open(ff_path, O_RDWR);
232 _E("Failed to open %s : %s", ff_path, strerror(errno));
237 /* Increase handle count */
241 *device_handle = DEFAULT_HAPTIC_HANDLE;
246 static int close_device(int device_handle)
248 if (device_handle != DEFAULT_HAPTIC_HANDLE)
251 if (ff_use_count == 0)
256 /* Decrease handle count */
259 /* close ff driver */
260 if (ff_use_count == 0) {
261 /* Initialize effect structure */
262 memset(&ff_effect, 0, sizeof(ff_effect));
270 static int vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle)
272 if (device_handle != DEFAULT_HAPTIC_HANDLE)
275 return ff_play(ff_fd, duration, feedback);
278 static int vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle)
280 if (device_handle != DEFAULT_HAPTIC_HANDLE)
284 return ff_play(ff_fd, 300, feedback);
287 static int stop_device(int device_handle)
289 if (device_handle != DEFAULT_HAPTIC_HANDLE)
292 return ff_stop(ff_fd);
295 static int get_device_state(int device_index, int *effect_state)
299 if (ff_effect.id != 0)
305 *effect_state = status;
310 static int create_effect(unsigned char *vibe_buffer, int max_bufsize, haptic_module_effect_element *elem_arr, int max_elemcnt)
312 _E("Not support feature");
316 static int get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration)
318 if (device_handle != DEFAULT_HAPTIC_HANDLE)
321 _E("Not support feature");
325 static int convert_binary(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path)
327 _E("Not support feature");
330 /* END: Haptic Module APIs */
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,
345 static bool is_valid(void)
349 ret = ff_find_device(ff_path, sizeof(ff_path));
357 static const struct haptic_plugin_ops *load(void)
359 return &default_plugin;
362 static const struct haptic_ops std_ops = {
363 .is_valid = is_valid,
367 HAPTIC_OPS_REGISTER(&std_ops)