186a92f5f97b4d5b4a59e0784e6d79e5ad5adc80
[platform/core/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 struct _vibe_pattern {
62     haptic_vibration_iter_s *iters;
63     int current;
64     int size;
65     int level;
66     int iter_count;
67     int pattern_index;
68     int error;
69 };
70
71 static const int UNDEFINED = 0;
72 static const int START = 1;
73
74 GArray *pattern_table = NULL;
75
76 static int initialize = 0;
77 static int max_device = 0;
78
79 static int* haptic_ids = NULL;
80
81 int haptic_get_count(int* vibrator_number)
82 {
83     int count;
84     if(vibrator_number == NULL)
85         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
86
87     count = device_haptic_get_device_count();
88     if(count < 0)
89         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
90
91     *vibrator_number = count;
92
93     return HAPTIC_ERROR_NONE;
94 }
95
96 int haptic_initialize()
97 {
98     int i, j; 
99     int id;
100
101     if(initialize)
102         return HAPTIC_ERROR_NONE;
103
104
105     if( haptic_get_count(&max_device) < 0)
106         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
107
108     haptic_ids = (int*)malloc(sizeof(int)*max_device+1); // max + zero
109
110     if(haptic_ids == NULL){
111         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
112     }
113
114     for(i=0; i<=max_device; i++){
115         id = device_haptic_open(_DEV[i], 0);
116         if(id < 0) {
117             for (j=i; i>=0; i--){
118                 device_haptic_close(haptic_ids[i]);
119             }
120             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
121         }
122
123         haptic_ids[i] = id;
124     }
125
126     initialize = 1;
127
128     pattern_table = g_array_new(FALSE, TRUE, sizeof(int));
129
130     _haptic_init();
131
132     return HAPTIC_ERROR_NONE;
133 }
134
135 int haptic_deinitialize()
136 {
137     int err, i;
138
139     if(!initialize)
140         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
141
142     for(i=0; i<=max_device; i++){
143         err = device_haptic_close(haptic_ids[i]);
144     }
145     initialize = 0;
146     if(haptic_ids != NULL)
147         free(haptic_ids);
148
149     g_array_free(pattern_table, TRUE);
150     pattern_table = NULL;
151
152     _haptic_deinit();
153
154     return HAPTIC_ERROR_NONE;
155 }
156
157
158 int haptic_vibrate_monotone(int device_index, int duration_ms, int level)
159 {
160         int ret;
161
162         if(device_index < 0 || device_index > max_device)
163                 RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
164
165         if(level < HAPTIC_LEVEL_AUTO || level > HAPTIC_LEVEL_5)
166                 RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
167
168         device_index = ((device_index < 3) ? device_index : 0); // xxx
169
170         if(!initialize)
171                 RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
172
173         if(level == HAPTIC_LEVEL_0)
174                 return HAPTIC_ERROR_NONE;
175
176         ret = device_haptic_play_monotone_with_detail_feedback_level(haptic_ids[device_index], duration_ms, level);
177
178         if(ret < 0){
179                 if(ret == -2)
180                         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
181                 else
182                         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
183         }
184         
185         return HAPTIC_ERROR_NONE;
186 }
187
188 int haptic_stop_device(int device_index)
189 {
190         int ret;
191
192     if(device_index < 0 || device_index > max_device)
193         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
194
195     device_index = ((device_index < 3) ? device_index : 0); // xxx
196
197     if(!initialize)
198         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
199
200         ret = device_haptic_stop_play(haptic_ids[device_index]);
201
202         if(ret < 0){
203         if(ret == -2)
204             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
205         else
206             RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
207     }
208         
209         return HAPTIC_ERROR_NONE;
210 }
211
212 static int _haptic_play_monotone(int device_index, long duration, int level)
213 {
214         int ret;
215
216     if(device_index < 0 || device_index > max_device)
217         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
218
219     device_index = ((device_index < 3) ? device_index : 0); // xxx
220
221     if(!initialize)
222         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
223
224     if(level == HAPTIC_LEVEL_AUTO) {
225         level = HAPTIC_FEEDBACK_LEVEL_AUTO;
226     }else {
227         level = level > 100 ? 100 : (level < 0 ? 0 : level); 
228     }
229
230         ret = device_haptic_play_monotone_with_detail_feedback_level(haptic_ids[device_index], duration, level);
231
232         if(ret < 0){
233         if(ret == -2)
234             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
235         else
236             RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
237     }
238
239         return HAPTIC_ERROR_NONE;
240 }
241
242 static gboolean _haptic_play_iter(gpointer data)
243 {
244     int err;
245     struct _vibe_pattern* pattern = NULL;
246     
247     pattern = (struct _vibe_pattern*)data;
248
249     if(pattern == NULL)
250         return false;
251
252     if(pattern_table == NULL || g_array_index(pattern_table, int, pattern->pattern_index) != START) {
253         free(pattern->iters);
254         free(pattern);
255         return false;
256     }
257     if(pattern->iters == NULL)
258         return false;
259     int current = pattern->current;
260
261     int device = pattern->iters[current].vibrator_index;
262     long time = pattern->iters[current].time;
263     int level = pattern->level;
264     
265     // set default device, if can't find given device.
266     if(device >= max_device || device < 0)
267         device = 0;
268
269     if(level != 0 || time != 0){
270         err = _haptic_play_monotone(device, time, level);
271         if(err<0){
272             pattern->error = err;
273             return false;
274         }
275     }
276     // pattern play finish
277     if(++pattern->current >= pattern->size){
278         if(pattern->iter_count <= 0){
279             free(pattern->iters);
280             free(pattern);
281             return false; 
282         }else{
283             pattern->current = 0;
284             pattern->iter_count--;
285         }
286     }
287     g_timeout_add(time, _haptic_play_iter, data);
288
289     return false;
290 }
291
292 int haptic_play_pattern(haptic_vibration_iter_s* pattern, int pattern_size, int count, int level, int* id)
293 {
294     int i, key = -1;
295
296     if(id == NULL)
297         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
298
299     if(pattern == NULL)
300         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
301
302     if(!initialize)
303         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
304
305     haptic_vibration_iter_s* tmp_ptn = (haptic_vibration_iter_s*)
306         malloc(sizeof(haptic_vibration_iter_s) * pattern_size);
307     if(tmp_ptn == NULL){
308         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
309     }
310     memcpy(tmp_ptn, pattern, sizeof(haptic_vibration_iter_s) * pattern_size);
311
312     struct _vibe_pattern* vibe_p = (struct _vibe_pattern*)malloc(sizeof(struct _vibe_pattern));
313     if(vibe_p == NULL){
314         free(tmp_ptn);
315         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
316     }
317     vibe_p->iters = tmp_ptn;
318     vibe_p->size = pattern_size;
319     vibe_p->level = level;
320     vibe_p->iter_count = count;
321     vibe_p->current = 0;
322     vibe_p->error= 0;
323
324     for(i=0; i< pattern_table->len; i++){
325         if(g_array_index(pattern_table, int, i) == UNDEFINED){
326             key = i;
327             break;
328         }
329     }
330     if(key == -1){
331         g_array_append_val(pattern_table, START);
332         key = pattern_table->len -1;
333     }else{
334         g_array_index(pattern_table, int, key) = START;
335     }
336
337     vibe_p->pattern_index = key;
338
339     _haptic_play_iter((gpointer)vibe_p);
340
341     int error = vibe_p->error;
342     if(error < 0){
343         free(vibe_p->iters);
344         free(vibe_p);
345
346                 if(error == -2)
347             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
348         else
349             RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
350     }
351
352     *id = key;
353
354     return HAPTIC_ERROR_NONE;
355 }
356
357 int haptic_stop_pattern(int id)
358 {
359     if(id < 0)
360         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
361
362     if(!initialize || pattern_table == NULL)
363         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
364
365     if(id >= pattern_table->len)
366         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
367
368    g_array_index(pattern_table, int, id) = UNDEFINED;
369
370     return HAPTIC_ERROR_NONE;
371 }