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