3c38779bf2738e5999d0ff8f5a4c445ec54791f2
[framework/api/haptic.git] / src / haptic.c
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License. 
15  */
16
17
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <stdbool.h>
24 #include <haptic.h>
25 #include <devman_haptic.h>
26 #include <glib.h>
27 #include <dlog.h>
28
29 #include "haptic_private.h"
30
31 #undef LOG_TAG
32 #define LOG_TAG "TIZEN_SYSTEM_HAPTIC"
33
34 #define NOT_ASSIGNED -1
35 #define VIBE_SILENCE -128
36
37 #define _MSG_HAPTIC_ERROR_INVALID_PARAMETER "Invalid parameter"
38 #define _MSG_HAPTIC_ERROR_NO_SUCH_FILE "No such file"
39 #define _MSG_HAPTIC_ERROR_NOT_SUPPORTED_FORMAT "Not supported format"
40 #define _MSG_HAPTIC_ERROR_NOT_INITIALIZED "Not initialize"
41 #define _MSG_HAPTIC_ERROR_OPERATION_FAILED "Operation failed"
42
43 #define RETURN_ERR_MSG(err_code, msg) \
44     do { \
45         LOGE("[%s] "_MSG_##err_code"(0x%08x) : %s", __FUNCTION__, err_code, msg); \
46         return err_code; \
47     }while(0)
48
49 #define RETURN_ERR(err_code) \
50     do { \
51         LOGE("[%s] "_MSG_##err_code"(0x%08x)", __FUNCTION__, err_code); \
52         return err_code; \
53     }while(0)
54
55 static int _DEV[] = {
56     DEV_IDX_ALL,
57     DEV_IDX_0,
58     DEV_IDX_1,
59 };
60
61 static int _LEVEL[] = 
62 {
63         HAPTIC_FEEDBACK_LEVEL_AUTO,
64     VIBE_SILENCE,
65         HAPTIC_FEEDBACK_LEVEL_1,
66         HAPTIC_FEEDBACK_LEVEL_2,
67         HAPTIC_FEEDBACK_LEVEL_3,
68         HAPTIC_FEEDBACK_LEVEL_4,
69         HAPTIC_FEEDBACK_LEVEL_5,
70 };
71
72 struct _vibe_pattern {
73     haptic_vibration_iter_s *iters;
74     int current;
75     int size;
76     int level_change;
77     int iter_count;
78     int stop;
79     int pattern_index;
80     int error;
81 };
82
83 GArray *pattern_table = NULL;
84
85 static int initialize = 0;
86 static int max_device = 0;
87
88 static int* haptic_ids = NULL;
89
90 static void _free_pattern_from_table(int index);
91
92 static bool invalid_ivt(const char* file_name)
93 {
94     if( 0 != access(file_name, R_OK) )
95     {
96         return false;
97     }
98
99     char* ext = strrchr(file_name, '.');
100     if (ext == NULL || 0 != strcasecmp(ext, ".ivt")){
101         return false;
102     }
103
104     return true;
105 }
106
107 int haptic_get_count(int* vibrator_number)
108 {
109     int count;
110     if(vibrator_number == NULL)
111         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
112
113     count = device_haptic_get_device_count();
114     if(count < 0)
115         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
116
117     *vibrator_number = count;
118
119     return HAPTIC_ERROR_NONE;
120 }
121
122 int haptic_initialize()
123 {
124     int i, j; 
125     int id;
126
127     if( haptic_get_count(&max_device) < 0)
128         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
129
130     haptic_ids = (int*)malloc(sizeof(int)*max_device+1); // max + zero
131
132     if(haptic_ids == NULL){
133         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
134     }
135
136     for(i=0; i<=max_device; i++){
137         id = device_haptic_open(_DEV[i], 0);
138         if(id < 0) {
139             for (j=i; i>=0; i--){
140                 device_haptic_close(haptic_ids[i]);
141             }
142             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
143         }
144
145         haptic_ids[i] = id;
146     }
147
148     initialize = 1;
149
150     pattern_table = g_array_new(FALSE, TRUE, sizeof(struct _vibe_pattern*));
151
152     _haptic_init();
153
154     return HAPTIC_ERROR_NONE;
155 }
156
157 int haptic_deinitialize()
158 {
159     int err, i;
160
161     if(!initialize)
162         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
163
164     for(i=0; i<=max_device; i++){
165         err = device_haptic_close(haptic_ids[i]);
166     }
167     initialize = 0;
168
169     if(haptic_ids != NULL)
170         free(haptic_ids);
171
172     for(i=0; i< pattern_table->len; i++){
173         _free_pattern_from_table(i);
174     }
175     g_array_free(pattern_table, TRUE);
176
177     _haptic_deinit();
178
179     return HAPTIC_ERROR_NONE;
180 }
181
182
183 int haptic_get_file_duration(int device_index, const char *file_name , int* duration)
184 {
185         int ret;
186
187     if(!initialize)
188         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
189
190     if(device_index < 0 || device_index > max_device)
191         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
192     
193     device_index = ((device_index < 3) ? device_index : 0); // xxx
194
195     if(!invalid_ivt(file_name))
196         RETURN_ERR(HAPTIC_ERROR_NOT_SUPPORTED_FORMAT);
197
198         ret = device_haptic_get_file_duration(haptic_ids[device_index], file_name, duration);
199
200         if(ret < 0){
201         if(ret == -2)
202             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
203         else
204             RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
205     }
206         
207         return HAPTIC_ERROR_NONE;
208 }
209
210 int haptic_vibrate_file(int device_index, const char *file_name , int count , haptic_level_e level)
211 {
212         int ret;
213
214     if(device_index < 0 || device_index > max_device)
215         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
216
217     device_index = ((device_index < 3) ? device_index : 0); // xxx
218
219     if(!initialize)
220         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
221
222     if(level == VIBE_SILENCE)
223         return HAPTIC_ERROR_NONE;
224
225         if(level > HAPTIC_LEVEL_5 || level < 0)
226                 RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
227
228     if(count < 0 || count >= HAPTIC_INFINITE_ITERATION)
229         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
230
231     if(count == 0)
232         count = HAPTIC_INFINITE_ITERATION;
233
234     if(!invalid_ivt(file_name))
235         RETURN_ERR(HAPTIC_ERROR_NOT_SUPPORTED_FORMAT);
236
237         ret = device_haptic_play_file(haptic_ids[device_index], file_name, count, _LEVEL[level]);
238
239         if(ret < 0){
240         if(ret == -2)
241             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
242         else
243             RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
244     }
245         
246         return HAPTIC_ERROR_NONE;
247 }
248
249 int haptic_vibrate_monotone(int device_index , int duration)
250 {
251         int ret;
252
253     if(device_index < 0 || device_index > max_device)
254         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
255
256     device_index = ((device_index < 3) ? device_index : 0); // xxx
257
258     if(!initialize)
259         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
260
261         ret = device_haptic_play_monotone(haptic_ids[device_index], duration);
262
263         if(ret < 0){
264         if(ret == -2)
265             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
266         else
267             RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
268     }
269         
270         return HAPTIC_ERROR_NONE;
271 }
272
273 int haptic_stop_device(int device_index)
274 {
275         int ret;
276
277     if(device_index < 0 || device_index > max_device)
278         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
279
280     device_index = ((device_index < 3) ? device_index : 0); // xxx
281
282     if(!initialize)
283         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
284
285         ret = device_haptic_stop_play(haptic_ids[device_index]);
286
287         if(ret < 0){
288         if(ret == -2)
289             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
290         else
291             RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
292     }
293         
294         return HAPTIC_ERROR_NONE;
295 }
296
297 static void _free_pattern_from_table(int index)
298 {
299     struct _vibe_pattern* p = g_array_index(pattern_table, struct _vibe_pattern *, index);
300     if(p == NULL)
301         return;
302     free(p->iters);
303     free(p);
304     g_array_index(pattern_table, struct _vibe_pattern *, index) = NULL;
305 }
306
307 static int _haptic_play_monotone(int device_index, long duration, haptic_level_e level)
308 {
309         int ret;
310
311     if(device_index < 0 || device_index > max_device)
312         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
313
314     device_index = ((device_index < 3) ? device_index : 0); // xxx
315
316     if(!initialize)
317         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
318
319
320         ret = device_haptic_play_monotone_with_feedback_level(haptic_ids[device_index], duration, _LEVEL[level]);
321
322         if(ret < 0){
323         if(ret == -2)
324             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
325         else
326             RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
327     }
328
329         return HAPTIC_ERROR_NONE;
330 }
331
332 static gboolean _haptic_play_iter(gpointer data)
333 {
334     int err;
335     struct _vibe_pattern* pattern = (struct _vibe_pattern*)data;
336
337     if(pattern->stop){
338         _free_pattern_from_table(pattern->pattern_index);
339         return false;
340     }
341     int current = pattern->current;
342
343     int device = pattern->iters[current].vibrator_index;
344     int level = pattern->iters[current].level;
345     long time = pattern->iters[current].time;
346     int level_change = pattern->level_change;
347     int iter_count = pattern->iter_count;
348     
349     // set default device, if can't find given device.
350     if(device >= max_device || device < 0)
351         device = 0;
352
353     if(level + level_change < HAPTIC_LEVEL_0)
354         level = HAPTIC_LEVEL_0;
355     if(level + level_change > HAPTIC_LEVEL_5)
356         level = HAPTIC_LEVEL_5;
357
358     if(level != HAPTIC_LEVEL_0 || time != 0){
359         err = _haptic_play_monotone(device, time, level);
360         if(err<0){
361             pattern->error = err;
362             return false;
363         }
364     }
365
366     pattern->current++;
367
368     // pattern play finish
369     if(pattern->current >= pattern->size){
370         if(iter_count <= 0){
371             _free_pattern_from_table(pattern->pattern_index);
372             return false; 
373         }else{
374             pattern->current = 0;
375             pattern->iter_count--;
376         }
377     }
378
379
380     g_timeout_add(time, _haptic_play_iter, data);
381
382     return false;
383 }
384
385 int haptic_play_pattern(haptic_vibration_iter_s* pattern, int pattern_size, int count, int level_change, int* id)
386 {
387     int i, key = -1;
388
389     if(id == NULL)
390         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
391
392     if(pattern == NULL)
393         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
394
395     if(!initialize)
396         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
397
398     haptic_vibration_iter_s* tmp_ptn = (haptic_vibration_iter_s*)
399         malloc(sizeof(haptic_vibration_iter_s) * pattern_size);
400     if(tmp_ptn == NULL){
401         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
402     }
403     memcpy(tmp_ptn, pattern, sizeof(haptic_vibration_iter_s) * pattern_size);
404
405     struct _vibe_pattern* vibe_p = (struct _vibe_pattern*)malloc(sizeof(struct _vibe_pattern));
406     if(vibe_p == NULL){
407         free(tmp_ptn);
408         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
409     }
410     vibe_p->iters = tmp_ptn;
411     vibe_p->size = pattern_size;
412     vibe_p->level_change = level_change;
413     vibe_p->iter_count = count;
414     vibe_p->current = 0;
415     vibe_p->stop = 0;
416     vibe_p->error= 0;
417
418     for(i=0; i< pattern_table->len; i++){
419         if(g_array_index(pattern_table, struct _vibe_pattern *, i) == NULL){
420             key = i;
421             break;
422         }
423     }
424     if(key == -1){
425         g_array_append_val(pattern_table, vibe_p);
426         key = pattern_table->len -1;
427     }else{
428         g_array_index(pattern_table, struct _vibe_pattern *, key) = vibe_p;
429     }
430
431     vibe_p->pattern_index = key;
432
433     _haptic_play_iter((gpointer)vibe_p);
434
435     if(vibe_p->error < 0){
436         _free_pattern_from_table(key);
437                 if(vibe_p->error == -2)
438             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
439         else
440             RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
441     }
442
443     *id = key;
444
445     return HAPTIC_ERROR_NONE;
446 }
447
448 int haptic_stop_pattern(int id)
449 {
450     if(id < 0)
451         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
452
453     if(!initialize || pattern_table == NULL)
454         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
455
456     if(id >= pattern_table->len)
457         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
458
459     struct _vibe_pattern* pattern = g_array_index(pattern_table, struct _vibe_pattern *, id);
460     if(pattern != NULL)
461         pattern->stop = 1;
462     else
463         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
464
465     return HAPTIC_ERROR_NONE;
466 }