c05fd2a61157e292ffe906eaf77151ad131b0fc8
[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 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         level = (level == HAPTIC_LEVEL_AUTO) ? 0 : level;
177         ret = device_haptic_play_monotone_with_detail_feedback_level(haptic_ids[device_index], duration_ms, level);
178
179         if(ret < 0){
180                 if(ret == -2)
181                         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
182                 else
183                         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
184         }
185         
186         return HAPTIC_ERROR_NONE;
187 }
188
189 int haptic_stop_device(int device_index)
190 {
191         int ret;
192
193     if(device_index < 0 || device_index > max_device)
194         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
195
196     device_index = ((device_index < 3) ? device_index : 0); // xxx
197
198     if(!initialize)
199         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
200
201         ret = device_haptic_stop_play(haptic_ids[device_index]);
202
203         if(ret < 0){
204         if(ret == -2)
205             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
206         else
207             RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
208     }
209         
210         return HAPTIC_ERROR_NONE;
211 }
212
213 static int _haptic_play_monotone(int device_index, long duration, int level)
214 {
215         int ret;
216
217     if(device_index < 0 || device_index > max_device)
218         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
219
220     device_index = ((device_index < 3) ? device_index : 0); // xxx
221
222     if(!initialize)
223         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
224
225     if(level == HAPTIC_LEVEL_AUTO) {
226         level = HAPTIC_FEEDBACK_LEVEL_AUTO;
227     }else {
228         level = level > 100 ? 100 : (level < 0 ? 0 : level); 
229     }
230
231         ret = device_haptic_play_monotone_with_detail_feedback_level(haptic_ids[device_index], duration, level);
232
233         if(ret < 0){
234         if(ret == -2)
235             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
236         else
237             RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
238     }
239
240         return HAPTIC_ERROR_NONE;
241 }
242
243 static gboolean _haptic_play_iter(gpointer data)
244 {
245     int err;
246     struct _vibe_pattern* pattern = NULL;
247     
248     pattern = (struct _vibe_pattern*)data;
249
250     if(pattern == NULL)
251         return false;
252
253     if(pattern_table == NULL || g_array_index(pattern_table, int, pattern->pattern_index) != START) {
254         free(pattern->iters);
255         free(pattern);
256         return false;
257     }
258     if(pattern->iters == NULL)
259         return false;
260     int current = pattern->current;
261
262     int device = pattern->iters[current].vibrator_index;
263     long time = pattern->iters[current].time;
264     int level = pattern->level;
265     
266     // set default device, if can't find given device.
267     if(device >= max_device || device < 0)
268         device = 0;
269
270     if(level != 0 || time != 0){
271         err = _haptic_play_monotone(device, time, level);
272         if(err<0){
273             pattern->error = err;
274             return false;
275         }
276     }
277     // pattern play finish
278     if(++pattern->current >= pattern->size){
279         if(pattern->iter_count <= 0){
280             free(pattern->iters);
281             free(pattern);
282             return false; 
283         }else{
284             pattern->current = 0;
285             pattern->iter_count--;
286         }
287     }
288     g_timeout_add(time, _haptic_play_iter, data);
289
290     return false;
291 }
292
293 int haptic_play_pattern(haptic_vibration_iter_s* pattern, int pattern_size, int count, int level, int* id)
294 {
295     int i, key = -1;
296
297     if(id == NULL)
298         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
299
300     if(pattern == NULL)
301         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
302
303     if(!initialize)
304         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
305
306     haptic_vibration_iter_s* tmp_ptn = (haptic_vibration_iter_s*)
307         malloc(sizeof(haptic_vibration_iter_s) * pattern_size);
308     if(tmp_ptn == NULL){
309         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
310     }
311     memcpy(tmp_ptn, pattern, sizeof(haptic_vibration_iter_s) * pattern_size);
312
313     struct _vibe_pattern* vibe_p = (struct _vibe_pattern*)malloc(sizeof(struct _vibe_pattern));
314     if(vibe_p == NULL){
315         free(tmp_ptn);
316         RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
317     }
318     vibe_p->iters = tmp_ptn;
319     vibe_p->size = pattern_size;
320     vibe_p->level = level;
321     vibe_p->iter_count = count;
322     vibe_p->current = 0;
323     vibe_p->error= 0;
324
325     for(i=0; i< pattern_table->len; i++){
326         if(g_array_index(pattern_table, int, i) == UNDEFINED){
327             key = i;
328             break;
329         }
330     }
331     if(key == -1){
332         g_array_append_val(pattern_table, START);
333         key = pattern_table->len -1;
334     }else{
335         g_array_index(pattern_table, int, key) = START;
336     }
337
338     vibe_p->pattern_index = key;
339
340     _haptic_play_iter((gpointer)vibe_p);
341
342     int error = vibe_p->error;
343     if(error < 0){
344         free(vibe_p->iters);
345         free(vibe_p);
346
347                 if(error == -2)
348             RETURN_ERR(HAPTIC_ERROR_OPERATION_FAILED);
349         else
350             RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
351     }
352
353     *id = key;
354
355     return HAPTIC_ERROR_NONE;
356 }
357
358 int haptic_stop_pattern(int id)
359 {
360     if(id < 0)
361         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
362
363     if(!initialize || pattern_table == NULL)
364         RETURN_ERR(HAPTIC_ERROR_NOT_INITIALIZED);
365
366     if(id >= pattern_table->len)
367         RETURN_ERR(HAPTIC_ERROR_INVALID_PARAMETER);
368
369    g_array_index(pattern_table, int, id) = UNDEFINED;
370
371     return HAPTIC_ERROR_NONE;
372 }