d9d94cb477a5dc53aef37cb883ce5f494bae3317
[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(_DEV[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(_DEV[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) ? _DEV[device_index] : DEV_IDX_ALL); // 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) ? _DEV[device_index] : DEV_IDX_ALL); // 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) ? _DEV[device_index] : DEV_IDX_ALL); // 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) ? _DEV[device_index] : DEV_IDX_ALL); // 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 gboolean _haptic_play_iter(gpointer data)
308 {
309     int err;
310     struct _vibe_pattern* pattern = (struct _vibe_pattern*)data;
311
312     if(pattern->stop){
313         _free_pattern_from_table(pattern->pattern_index);
314         return false;
315     }
316     int current = pattern->current;
317
318     int device = pattern->iters[current].vibrator_index;
319     int level = pattern->iters[current].level;
320     long time = pattern->iters[current].time;
321     int level_change = pattern->level_change;
322     int iter_count = pattern->iter_count;
323     
324     // set default device, if can't find given device.
325     if(device >= max_device || device < 0)
326         device = 0;
327
328     if(level + level_change < HAPTIC_LEVEL_0)
329         level = HAPTIC_LEVEL_0;
330     if(level + level_change > HAPTIC_LEVEL_5)
331         level = HAPTIC_LEVEL_5;
332
333     if(level != HAPTIC_LEVEL_0 || time != 0){
334 //        err = _haptic_play_monotone(device, time, level);
335         err = haptic_vibrate_monotone(device, time);
336         if(err<0){
337             pattern->error = err;
338             return false;
339         }
340     }
341
342     pattern->current++;
343
344     // pattern play finish
345     if(pattern->current >= pattern->size){
346         if(iter_count <= 0){
347             _free_pattern_from_table(pattern->pattern_index);
348             return false; 
349         }else{
350             pattern->current = 0;
351             pattern->iter_count--;
352         }
353     }
354
355
356     g_timeout_add(time, _haptic_play_iter, data);
357
358     return false;
359 }
360
361 int haptic_play_pattern(haptic_vibration_iter_s* pattern, int pattern_size, int count, int level_change, int* id)
362 {
363     int i, key = -1;
364
365     if(id == NULL)
366         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
367
368     if(pattern == NULL)
369         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
370
371     if(!initialize)
372         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
373
374     haptic_vibration_iter_s* tmp_ptn = (haptic_vibration_iter_s*)
375         malloc(sizeof(haptic_vibration_iter_s) * pattern_size);
376     if(tmp_ptn == NULL){
377         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
378     }
379     memcpy(tmp_ptn, pattern, sizeof(haptic_vibration_iter_s) * pattern_size);
380
381     struct _vibe_pattern* vibe_p = (struct _vibe_pattern*)malloc(sizeof(struct _vibe_pattern));
382     if(vibe_p == NULL){
383         free(tmp_ptn);
384         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
385     }
386     vibe_p->iters = tmp_ptn;
387     vibe_p->size = pattern_size;
388     vibe_p->level_change = level_change;
389     vibe_p->iter_count = count;
390     vibe_p->current = 0;
391     vibe_p->stop = 0;
392     vibe_p->error= 0;
393
394     for(i=0; i< pattern_table->len; i++){
395         if(g_array_index(pattern_table, struct _vibe_pattern *, i) == NULL){
396             key = i;
397             break;
398         }
399     }
400     if(key == -1){
401         g_array_append_val(pattern_table, vibe_p);
402         key = pattern_table->len -1;
403     }else{
404         g_array_index(pattern_table, struct _vibe_pattern *, key) = vibe_p;
405     }
406
407     vibe_p->pattern_index = key;
408
409     _haptic_play_iter((gpointer)vibe_p);
410
411     if(vibe_p->error < 0){
412         _free_pattern_from_table(key);
413                 if(vibe_p->error == -2)
414             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
415         else
416             RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
417     }
418
419     *id = key;
420
421     return HAPTIC_ERROR_NONE;
422 }
423
424 int haptic_stop_pattern(int id)
425 {
426     if(id < 0)
427         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
428
429     if(!initialize || pattern_table == NULL)
430         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
431
432     if(id >= pattern_table->len)
433         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
434
435     struct _vibe_pattern* pattern = g_array_index(pattern_table, struct _vibe_pattern *, id);
436     if(pattern != NULL)
437         pattern->stop = 1;
438     else
439         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
440
441     return HAPTIC_ERROR_NONE;
442 }