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