support multi handle, not use default handle
[platform/core/system/haptic-module-tizen.git] / tizen / DEVICE / src / haptic.c
1 /*
2  * haptic-module-tizen
3  * Copyright (c) 2012 Samsung Electronics Co., Ltd.
4  *
5  * Licensed under the Apache License, Version 2.0 (the License);
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <assert.h>
27 #include <time.h>
28 #include <vconf.h>
29
30 #include <haptic_plugin_intf.h>
31 #include "haptic_module_log.h"
32 #include "file.h"
33
34 #ifndef EXTAPI
35 #define EXTAPI __attribute__ ((visibility("default")))
36 #endif
37
38 #define DEFAULT_MOTOR_COUNT             1
39 #define DEFAULT_DEVICE_HANDLE   0x01
40 #define DEFAULT_EFFECT_HANDLE   0x02
41 #define HAPTIC_FEEDBACK_AUTO    101
42 #define HAPTIC_PLAY_FILE_EXT    ".tht"
43
44 /* START of Static Function Section */
45 static int __to_level(int feedback, int *type)
46 {
47         static int max = -1;
48         int t;
49
50         if (max == -1) {
51                 int status = GetHapticLevelMax(&max);
52                 if (status < 0) {
53                         MODULE_ERROR("GetHapticLevelMax fail : %d", status);
54                         return HAPTIC_MODULE_OPERATION_FAILED;
55                 }
56         }
57
58         t = feedback * max / HAPTIC_MODULE_FEEDBACK_MAX;
59         MODULE_LOG("feedback value is changed : %d -> %d", feedback, t);
60
61         if (type)
62                 *type = t;
63
64         return 0;
65 }
66
67 static void __trim_name(const char *file_name, char *vibe_buffer, int size)
68 {
69         int length;
70
71         assert(file_name);
72         assert(vibe_buffer);
73         assert(size > 0);
74
75         snprintf(vibe_buffer, size, "%s", file_name);
76
77         length = strlen(vibe_buffer);
78         while (vibe_buffer[--length] == ' ');
79         vibe_buffer[length + 1] = '\0';
80 }
81
82 static int __check_ext(const char *name)
83 {
84         char *ext;
85
86         assert(name);
87
88         ext = strrchr(name, '.');
89         if (ext && !strcmp(ext, HAPTIC_PLAY_FILE_EXT))
90                 return 1;
91
92         return 0;
93 }
94
95 static int __get_size(FILE *pf, const char *fname)
96 {
97         int status;
98         int size;
99
100         assert(pf);
101
102         status = fseek(pf, 0, SEEK_END);
103         if (status == -1) {
104                 MODULE_ERROR("fseek failed: %s", fname);
105                 return -1;
106         }
107
108         size = ftell(pf);
109
110         status = fseek(pf, 0, SEEK_SET);
111         if (status == -1) {
112                 MODULE_ERROR("fseek failed: %s", fname);
113                 return -1;
114         }
115
116         return size;
117 }
118
119 static unsigned char *__read_file(const char *fname)
120 {
121         int status;
122         FILE *pf;
123         long size;
124         unsigned char *vibe_buffer;
125
126         assert(fname);
127
128         pf = fopen(fname, "rb");
129         if (!pf) {
130                 MODULE_ERROR("fopen failed: %s", fname);
131                 return NULL;
132         }
133
134         size = __get_size(pf, fname);
135         if (size <= 0) {
136                 fclose(pf);
137                 return NULL;
138         }
139
140         vibe_buffer = malloc(size);
141         if (!vibe_buffer) {
142                 fclose(pf);
143                 MODULE_ERROR("buffer alloc failed");
144                 return NULL;
145         }
146
147         status = fread(vibe_buffer, 1, size, pf);
148         if (status != size) {
149                 MODULE_ERROR("fread failed: expect %d read %d", size, status);
150                 free(vibe_buffer);
151                 vibe_buffer = NULL;
152         }
153
154         fclose(pf);
155
156         return vibe_buffer;
157 }
158
159 static unsigned char* __convert_file_to_buffer(const char *file_name)
160 {
161         char fname[FILENAME_MAX];
162         int status;
163
164         __trim_name(file_name, fname, sizeof(fname));
165         status = __check_ext(fname);
166         if (!status) {
167                 MODULE_ERROR("__check_file faild");
168                 return NULL;
169         }
170
171         return __read_file(fname);
172 }
173
174 static int __save_file(const unsigned char *vibe_buferf, int size, const char *file_name)
175 {
176         int status;
177         FILE *pf;
178         int fd;
179
180         pf = fopen(file_name, "wb+");
181         if (pf == NULL) {
182                 MODULE_ERROR("To open file is failed");
183                 return HAPTIC_MODULE_OPERATION_FAILED;
184         }
185
186         status = fwrite(vibe_buferf, 1, size, pf);
187         if (status != size) {
188                 MODULE_ERROR("To write file is failed");
189                 return HAPTIC_MODULE_OPERATION_FAILED;
190         }
191
192         fd = fileno(pf);
193         if (fd == -1) {
194                 MODULE_ERROR("To get file descriptor is failed");
195                 return HAPTIC_MODULE_OPERATION_FAILED;
196         }
197
198         status = fsync(fd);
199         if (status == -1) {
200                 MODULE_ERROR("To be synchronized with the disk is failed");
201                 return HAPTIC_MODULE_OPERATION_FAILED;
202         }
203
204         fclose(pf);
205
206         return 0;
207 }
208
209 static int __vibrate(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority)
210 {
211         int status;
212         int level;
213
214         assert(vibe_buffer);
215
216         status = __to_level(feedback, &level);
217         if (status != HAPTIC_MODULE_ERROR_NONE)
218                 return status;
219
220         status = PlayBuffer(device_handle, vibe_buffer, iteration, level);
221         if (status < 0) {
222                 MODULE_ERROR("PlayHapticBuffer fail : %d", status);
223                 return HAPTIC_MODULE_OPERATION_FAILED;
224         }
225
226         return 0;
227 }
228
229 static void *_create_handle(void)
230 {
231         return ((getpid()<<16)|time(NULL));
232 }
233 /* END of Static Function Section */
234
235
236 static int _get_device_count(int *count)
237 {
238         if (count == NULL)
239                 return HAPTIC_MODULE_INVALID_ARGUMENT;
240
241         *count = DEFAULT_MOTOR_COUNT;
242         return HAPTIC_MODULE_ERROR_NONE;
243 }
244
245 static int _open_device(int device_index, int *device_handle)
246 {
247         int handle;
248         int status;
249
250         if (device_index < HAPTIC_MODULE_DEVICE_0 || device_index > HAPTIC_MODULE_DEVICE_ALL)
251                 return HAPTIC_MODULE_INVALID_ARGUMENT;
252
253         if (device_handle == NULL)
254                 return HAPTIC_MODULE_INVALID_ARGUMENT;
255
256         handle = _create_handle();
257         status = OpenDevice(handle);
258         if (status < 0) {
259                 MODULE_ERROR("OpenHapticDevice fail :%d", status);
260                 return HAPTIC_MODULE_OPERATION_FAILED;
261         }
262
263         *device_handle = handle;
264         return HAPTIC_MODULE_ERROR_NONE;
265 }
266
267 static int _close_device(int device_handle)
268 {
269         int status;
270
271         if (device_handle < 0)
272                 return HAPTIC_MODULE_INVALID_ARGUMENT;
273
274         status = CloseDevice(device_handle);
275         if (status < 0) {
276                 MODULE_ERROR("CloseHapticDevice fail : %d", status);
277                 return HAPTIC_MODULE_OPERATION_FAILED;
278         }
279
280         return HAPTIC_MODULE_ERROR_NONE;
281 }
282
283 static int _vibrate_monotone(int device_handle, int duration, int feedback, int priority, int *effect_handle)
284 {
285         int status;
286         int level;
287
288         if (device_handle < 0)
289                 return HAPTIC_MODULE_INVALID_ARGUMENT;
290
291         if (duration < 0)
292                 return HAPTIC_MODULE_INVALID_ARGUMENT;
293
294         if (feedback < HAPTIC_MODULE_FEEDBACK_MIN || feedback > HAPTIC_MODULE_FEEDBACK_MAX)
295                 return HAPTIC_MODULE_INVALID_ARGUMENT;
296
297         if (priority < HAPTIC_MODULE_PRIORITY_MIN || priority > HAPTIC_MODULE_PRIORITY_HIGH)
298                 return HAPTIC_MODULE_INVALID_ARGUMENT;
299
300         if (effect_handle == NULL)
301                 return HAPTIC_MODULE_INVALID_ARGUMENT;
302
303         if (feedback == HAPTIC_MODULE_FEEDBACK_MIN)
304                 return HAPTIC_MODULE_ERROR_NONE;
305
306         status = __to_level(feedback, &level);
307         if (status != HAPTIC_MODULE_ERROR_NONE)
308                 return status;
309
310         status = PlayOneshot(device_handle, duration, level);
311         if (status < 0) {
312                 MODULE_ERROR("PlayOneshot fail : %d", status);
313                 return HAPTIC_MODULE_OPERATION_FAILED;
314         }
315
316         *effect_handle = DEFAULT_EFFECT_HANDLE;
317         return HAPTIC_MODULE_ERROR_NONE;
318 }
319
320 static int _vibrate_file(int device_handle, const char *file_path, int iteration, int feedback, int priority, int  *effect_handle)
321 {
322         int status;
323         unsigned char *vibe_buffer;
324
325         if (device_handle < 0)
326                 return HAPTIC_MODULE_INVALID_ARGUMENT;
327
328         if (file_path == NULL)
329                 return HAPTIC_MODULE_INVALID_ARGUMENT;
330
331         if (iteration < HAPTIC_MODULE_ITERATION_ONCE || iteration > HAPTIC_MODULE_ITERATION_INFINITE)
332                 return HAPTIC_MODULE_INVALID_ARGUMENT;
333
334         if (feedback < HAPTIC_MODULE_FEEDBACK_MIN || feedback > HAPTIC_MODULE_FEEDBACK_MAX)
335                 return HAPTIC_MODULE_INVALID_ARGUMENT;
336
337         if (priority < HAPTIC_MODULE_PRIORITY_MIN || priority > HAPTIC_MODULE_PRIORITY_HIGH)
338                 return HAPTIC_MODULE_INVALID_ARGUMENT;
339
340         if (effect_handle == NULL)
341                 return HAPTIC_MODULE_INVALID_ARGUMENT;
342
343         if (feedback == HAPTIC_MODULE_FEEDBACK_MIN)
344                 return HAPTIC_MODULE_ERROR_NONE;
345
346         vibe_buffer = __convert_file_to_buffer(file_path);
347         if (!vibe_buffer) {
348                 MODULE_ERROR("File load filed");
349                 return HAPTIC_MODULE_OPERATION_FAILED;
350         }
351
352         status = __vibrate(device_handle, vibe_buffer, iteration, feedback, priority);
353         free(vibe_buffer);
354
355         return status;
356 }
357
358 static int _vibrate_buffer(int device_handle, const unsigned char *vibe_buffer, int iteration, int feedback, int priority, int *effect_handle)
359 {
360         if (device_handle < 0)
361                 return HAPTIC_MODULE_INVALID_ARGUMENT;
362
363         if (vibe_buffer == NULL)
364                 return HAPTIC_MODULE_INVALID_ARGUMENT;
365
366         if (iteration < HAPTIC_MODULE_ITERATION_ONCE || iteration > HAPTIC_MODULE_ITERATION_INFINITE)
367                 return HAPTIC_MODULE_INVALID_ARGUMENT;
368
369         if (feedback < HAPTIC_MODULE_FEEDBACK_MIN || feedback > HAPTIC_MODULE_FEEDBACK_MAX)
370                 return HAPTIC_MODULE_INVALID_ARGUMENT;
371
372         if (priority < HAPTIC_MODULE_PRIORITY_MIN || priority > HAPTIC_MODULE_PRIORITY_HIGH)
373                 return HAPTIC_MODULE_INVALID_ARGUMENT;
374
375         if (effect_handle == NULL)
376                 return HAPTIC_MODULE_INVALID_ARGUMENT;
377
378         if (feedback == HAPTIC_MODULE_FEEDBACK_MIN)
379                 return HAPTIC_MODULE_ERROR_NONE;
380
381         return __vibrate(device_handle, vibe_buffer, iteration, feedback, priority);
382 }
383
384 static int _stop_effect(int device_handle, int effect_handle)
385 {
386         int status;
387
388         if (device_handle < 0)
389                 return HAPTIC_MODULE_INVALID_ARGUMENT;
390
391         if (effect_handle < 0)
392                 return HAPTIC_MODULE_INVALID_ARGUMENT;
393
394         status = Stop(device_handle);
395         if (status < 0) {
396                 MODULE_ERROR("StopHaptic fail : %d", status);
397                 return HAPTIC_MODULE_OPERATION_FAILED;
398         }
399
400         return HAPTIC_MODULE_ERROR_NONE;
401 }
402
403 static int _stop_all_effects(int device_handle)
404 {
405         int status;
406
407         if (device_handle < 0)
408                 return HAPTIC_MODULE_INVALID_ARGUMENT;
409
410         status = Stop(device_handle);
411         if (status < 0) {
412                 MODULE_ERROR("StopHaptic fail : %d", status);
413                 return HAPTIC_MODULE_OPERATION_FAILED;
414         }
415
416         return HAPTIC_MODULE_ERROR_NONE;
417 }
418
419 static int _pause_effect(int device_handle, int effect_handle)
420 {
421         if (device_handle < 0)
422                 return HAPTIC_MODULE_INVALID_ARGUMENT;
423
424         if (effect_handle < 0)
425                 return HAPTIC_MODULE_INVALID_ARGUMENT;
426
427         MODULE_ERROR("This device is not supported this function(%s)", __func__);
428         return HAPTIC_MODULE_NOT_SUPPORTED;
429 }
430
431 static int _resume_effect(int device_handle, int effect_handle)
432 {
433         if (device_handle < 0)
434                 return HAPTIC_MODULE_INVALID_ARGUMENT;
435
436         if (effect_handle < 0)
437                 return HAPTIC_MODULE_INVALID_ARGUMENT;
438
439         MODULE_ERROR("This device is not supported this function(%s)", __func__);
440         return HAPTIC_MODULE_NOT_SUPPORTED;
441 }
442
443 static int _get_effect_state(int device_handle, int effect_handle, int *state)
444 {
445         if (device_handle < 0)
446                 return HAPTIC_MODULE_INVALID_ARGUMENT;
447
448         if (effect_handle < 0)
449                 return HAPTIC_MODULE_INVALID_ARGUMENT;
450
451         if (state == NULL)
452                 return HAPTIC_MODULE_INVALID_ARGUMENT;
453
454         MODULE_ERROR("This device is not supported this function(%s)", __func__);
455         return HAPTIC_MODULE_NOT_SUPPORTED;
456 }
457
458 static int _create_effect(unsigned char *vibe_buffer, int max_bufsize, haptic_module_effect_element *elem_arr, int max_elemcnt)
459 {
460         int status;
461         int i;
462         HapticElement elem;
463
464         if (vibe_buffer == NULL)
465                 return HAPTIC_MODULE_INVALID_ARGUMENT;
466
467         if (max_bufsize < 0)
468                 return HAPTIC_MODULE_INVALID_ARGUMENT;
469
470         if (elem_arr == NULL)
471                 return HAPTIC_MODULE_INVALID_ARGUMENT;
472
473         if (max_elemcnt < 0)
474                 return HAPTIC_MODULE_INVALID_ARGUMENT;
475
476         status = InitializeBuffer(vibe_buffer, max_bufsize);
477         if (status < 0) {
478                 MODULE_ERROR("InitializeHapticBuffer fail: %d", status);
479                 return HAPTIC_MODULE_OPERATION_FAILED;
480         }
481
482         MODULE_LOG("effect count : %d", max_elemcnt);
483         for (i = 0; i < max_elemcnt; ++i) {
484                 elem.duration = elem_arr[i].haptic_duration;
485                 elem.level = elem_arr[i].haptic_level;
486                 MODULE_LOG("%d) duration : %d, level : %d", i, elem_arr[i].haptic_duration, elem_arr[i].haptic_level);
487
488                 status = InsertElement(vibe_buffer, max_bufsize, &elem);
489                 if (status < 0) {
490                         MODULE_ERROR("InsertHapticElement fail: %d", status);
491                         return HAPTIC_MODULE_OPERATION_FAILED;
492                 }
493         }
494
495         return HAPTIC_MODULE_ERROR_NONE;
496 }
497
498 static int _save_effect(const unsigned char *vibe_buffer, int max_bufsize, const char *file_path)
499 {
500         int status;
501         int size;
502
503         if (vibe_buffer == NULL)
504                 return HAPTIC_MODULE_INVALID_ARGUMENT;
505
506         if (max_bufsize < 0)
507                 return HAPTIC_MODULE_INVALID_ARGUMENT;
508
509         if (file_path == NULL)
510                 return HAPTIC_MODULE_INVALID_ARGUMENT;
511
512         status = GetBufferSize(vibe_buffer, &size);
513         if (status < 0) {
514                 MODULE_ERROR("GetHapticBufferSize fail: %d", status);
515                 return HAPTIC_MODULE_OPERATION_FAILED;
516         }
517
518         return __save_file(vibe_buffer, size, file_path);
519 }
520
521 static int _get_file_duration(int device_handle, const char *file_path, int *file_duration)
522 {
523         int status;
524         unsigned char *vibe_buffer;
525         int duration;
526
527         if (device_handle < 0)
528                 return HAPTIC_MODULE_INVALID_ARGUMENT;
529
530         if (file_path == NULL)
531                 return HAPTIC_MODULE_INVALID_ARGUMENT;
532
533         if (file_duration == NULL)
534                 return HAPTIC_MODULE_INVALID_ARGUMENT;
535
536         vibe_buffer = __convert_file_to_buffer(file_path);
537         if (!vibe_buffer) {
538                 MODULE_ERROR("File load filed");
539                 return HAPTIC_MODULE_OPERATION_FAILED;
540         }
541
542         status = GetBufferDuration(vibe_buffer, &duration);
543         free(vibe_buffer);
544         if (status < 0) {
545                 MODULE_ERROR("GetHapticBufferDuration fail: %d", status);
546                 return HAPTIC_MODULE_OPERATION_FAILED;
547         }
548
549         *file_duration = duration;
550         return HAPTIC_MODULE_ERROR_NONE;
551 }
552
553 static int _get_buffer_duration(int device_handle, const unsigned char *vibe_buffer, int *buffer_duration)
554 {
555         int status;
556         int duration;
557
558         if (device_handle < 0)
559                 return HAPTIC_MODULE_INVALID_ARGUMENT;
560
561         if (vibe_buffer == NULL)
562                 return HAPTIC_MODULE_INVALID_ARGUMENT;
563
564         if (buffer_duration == NULL)
565                 return HAPTIC_MODULE_INVALID_ARGUMENT;
566
567         status = GetBufferDuration(vibe_buffer, &duration);
568         if (status < 0) {
569                 MODULE_ERROR("GetHapticBufferDuration fail: %d", status);
570                 return HAPTIC_MODULE_OPERATION_FAILED;
571         }
572
573         *buffer_duration = duration;
574         return HAPTIC_MODULE_ERROR_NONE;
575 }
576
577 static int _convert_binary (void)
578 {
579         MODULE_ERROR("This device is not supported this function(%s)", __func__);
580         return HAPTIC_MODULE_NOT_SUPPORTED;
581 }
582
583 static const haptic_plugin_interface haptic_plugin_tizen = {
584         .haptic_internal_get_device_count               = _get_device_count,
585         .haptic_internal_open_device                    = _open_device,
586         .haptic_internal_close_device                   = _close_device,
587         .haptic_internal_vibrate_monotone               = _vibrate_monotone,
588         .haptic_internal_vibrate_file                   = _vibrate_file,
589         .haptic_internal_vibrate_buffer                 = _vibrate_buffer,
590         .haptic_internal_stop_effect                    = _stop_effect,
591         .haptic_internal_stop_all_effects               = _stop_all_effects,
592         .haptic_internal_pause_effect                   = _pause_effect,
593         .haptic_internal_resume_effect                  = _resume_effect,
594         .haptic_internal_get_effect_state               = _get_effect_state,
595         .haptic_internal_create_effect                  = _create_effect,
596         .haptic_internal_save_effect                    = _save_effect,
597         .haptic_internal_get_file_duration              = _get_file_duration,
598         .haptic_internal_get_buffer_duration    = _get_buffer_duration,
599         .haptic_internal_convert_binary                 = _convert_binary,
600 };
601
602 EXTAPI
603 const haptic_plugin_interface *get_haptic_plugin_interface()
604 {
605         return &haptic_plugin_tizen;
606 }