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