tizen 2.4 release
[framework/system/libfeedback.git] / src / feedback.c
1 /*
2  * libfeedback
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 <stdbool.h>
21 #include <string.h>
22 #include <limits.h>
23
24 #include "feedback.h"
25 #include "profiles.h"
26 #include "devices.h"
27 #include "log.h"
28
29 #ifndef API
30 #define API __attribute__ ((visibility("default")))
31 #endif
32
33 static unsigned int init_cnt;
34 static pthread_mutex_t fmutex = PTHREAD_MUTEX_INITIALIZER;
35
36 API int feedback_initialize(void)
37 {
38         pthread_mutex_lock(&fmutex);
39         if (!profile) {
40                 _E("there is no valid profile module.");
41                 pthread_mutex_unlock(&fmutex);
42                 return FEEDBACK_ERROR_NOT_SUPPORTED;
43         }
44
45         if (init_cnt++ > 0) {
46                 pthread_mutex_unlock(&fmutex);
47                 return FEEDBACK_ERROR_NONE;
48         }
49
50         /* initialize device */
51         devices_init();
52
53         /* initialize profile feature */
54         if (profile->init)
55                 profile->init();
56
57         pthread_mutex_unlock(&fmutex);
58         return FEEDBACK_ERROR_NONE;
59 }
60
61 API int feedback_deinitialize(void)
62 {
63         pthread_mutex_lock(&fmutex);
64         if (!init_cnt) {
65                 pthread_mutex_unlock(&fmutex);
66                 return FEEDBACK_ERROR_NOT_INITIALIZED;
67         }
68
69         if (init_cnt-- > 1) {
70                 pthread_mutex_unlock(&fmutex);
71                 return FEEDBACK_ERROR_NONE;
72         }
73
74         /* deinitialize device */
75         devices_exit();
76
77         /* deinitialize profile feature */
78         if (profile->exit)
79                 profile->exit();
80
81         pthread_mutex_unlock(&fmutex);
82         return FEEDBACK_ERROR_NONE;
83 }
84
85 API int feedback_play(feedback_pattern_e pattern)
86 {
87         int err;
88         bool result;
89         int switched;
90
91         /* check initialize */
92         pthread_mutex_lock(&fmutex);
93         if (!init_cnt) {
94                 _E("Not initialized");
95                 pthread_mutex_unlock(&fmutex);
96                 return FEEDBACK_ERROR_NOT_INITIALIZED;
97         }
98         pthread_mutex_unlock(&fmutex);
99
100         if (pattern <= FEEDBACK_PATTERN_NONE ||
101             pattern >= profile->max_pattern) {
102                 _E("Invalid parameter : pattern(%d)", pattern);
103                 return FEEDBACK_ERROR_INVALID_PARAMETER;
104         }
105
106         /* if you need to switch pattern */
107         if (profile->get_switched_pattern) {
108                 result = profile->get_switched_pattern(pattern, &switched);
109                 if (result) {
110                         _W("pattern is changed : (%s) -> (%s)",
111                                         profile->str_pattern[pattern], profile->str_pattern[switched]);
112                         pattern = switched;
113                 }
114         }
115
116         /* play all device */
117         err = devices_play(pattern);
118         /**
119          * devices_play() returns error even if all devices are failed.
120          * It means if to play anything is successful,
121          * this function regards as success.
122          */
123         if (err == -ENOTSUP)
124                 return FEEDBACK_ERROR_NOT_SUPPORTED;
125         else if (err < 0)
126                 return FEEDBACK_ERROR_OPERATION_FAILED;
127
128         return FEEDBACK_ERROR_NONE;
129 }
130
131 API int feedback_play_type(feedback_type_e type, feedback_pattern_e pattern)
132 {
133         const struct device_ops *dev;
134         int err;
135         bool result;
136         int switched;
137
138         /* check initialize */
139         pthread_mutex_lock(&fmutex);
140         if (!init_cnt) {
141                 _E("Not initialized");
142                 pthread_mutex_unlock(&fmutex);
143                 return FEEDBACK_ERROR_NOT_INITIALIZED;
144         }
145         pthread_mutex_unlock(&fmutex);
146
147         if (type <= FEEDBACK_TYPE_NONE ||
148             type >= profile->max_type) {
149                 _E("Invalid parameter : type(%d)", type);
150                 return FEEDBACK_ERROR_INVALID_PARAMETER;
151         }
152
153         if (pattern <= FEEDBACK_PATTERN_NONE ||
154             pattern >= profile->max_pattern) {
155                 _E("Invalid parameter : pattern(%d)", pattern);
156                 return FEEDBACK_ERROR_INVALID_PARAMETER;
157         }
158
159         /* if you need to switch pattern */
160         if (profile->get_switched_pattern) {
161                 result = profile->get_switched_pattern(pattern, &switched);
162                 if (result) {
163                         _W("pattern is changed : (%s) -> (%s)",
164                                         profile->str_pattern[pattern], profile->str_pattern[switched]);
165                         pattern = switched;
166                 }
167         }
168
169         /* play proper device */
170         dev = find_device(type);
171         if (!dev) {
172                 _E("Not supported device : type(%s)", profile->str_type[type]);
173                 return FEEDBACK_ERROR_NOT_SUPPORTED;
174         }
175
176         err = dev->play(pattern);
177         if (err == -ENOTSUP)
178                 return FEEDBACK_ERROR_NOT_SUPPORTED;
179         else if (err == -ECOMM)
180                 return FEEDBACK_ERROR_PERMISSION_DENIED;
181         else if (err < 0)
182                 return FEEDBACK_ERROR_OPERATION_FAILED;
183
184         return FEEDBACK_ERROR_NONE;
185 }
186
187 API int feedback_stop(void)
188 {
189         int err;
190
191         /* check initialize */
192         pthread_mutex_lock(&fmutex);
193         if (!init_cnt) {
194                 _E("Not initialized");
195                 pthread_mutex_unlock(&fmutex);
196                 return FEEDBACK_ERROR_NOT_INITIALIZED;
197         }
198         pthread_mutex_unlock(&fmutex);
199
200         /* stop all device */
201         err = devices_stop();
202         if (err == -ENOTSUP)
203                 return FEEDBACK_ERROR_NOT_SUPPORTED;
204         else if (err == -ECOMM)
205                 return FEEDBACK_ERROR_PERMISSION_DENIED;
206         else if (err < 0)
207                 return FEEDBACK_ERROR_OPERATION_FAILED;
208
209         return FEEDBACK_ERROR_NONE;
210 }
211
212 API int feedback_is_supported_pattern(feedback_type_e type, feedback_pattern_e pattern, bool *status)
213 {
214         const struct device_ops *dev;
215         bool supported;
216         int err;
217         bool result;
218         int switched;
219
220         /* check initialize */
221         pthread_mutex_lock(&fmutex);
222         if (!init_cnt) {
223                 _E("Not initialized");
224                 pthread_mutex_unlock(&fmutex);
225                 return FEEDBACK_ERROR_NOT_INITIALIZED;
226         }
227         pthread_mutex_unlock(&fmutex);
228
229         if (!status) {
230                 _E("Invalid parameter : status(NULL)");
231                 return FEEDBACK_ERROR_INVALID_PARAMETER;
232         }
233
234         if (type <= FEEDBACK_TYPE_NONE ||
235             type >= profile->max_type) {
236                 _E("Invalid parameter : type(%d)", type);
237                 return FEEDBACK_ERROR_INVALID_PARAMETER;
238         }
239
240         if (pattern <= FEEDBACK_PATTERN_NONE ||
241             pattern >= profile->max_pattern) {
242                 _E("Invalid parameter : pattern(%d)", pattern);
243                 return FEEDBACK_ERROR_INVALID_PARAMETER;
244         }
245
246         /* if you need to switch pattern */
247         if (profile->get_switched_pattern) {
248                 result = profile->get_switched_pattern(pattern, &switched);
249                 if (result) {
250                         _W("pattern is changed : (%s) -> (%s)",
251                                         profile->str_pattern[pattern], profile->str_pattern[switched]);
252                         pattern = switched;
253                 }
254         }
255
256         /* play proper device */
257         dev = find_device(type);
258         if (!dev) {
259                 _E("Not supported device : type(%s)", profile->str_type[type]);
260                 return FEEDBACK_ERROR_NOT_SUPPORTED;
261         }
262
263         err = dev->is_supported(pattern, &supported);
264         if (err < 0) {
265                 _E("fail to invoke is_supported() : pattern(%s)", profile->str_pattern[pattern]);
266                 return FEEDBACK_ERROR_OPERATION_FAILED;
267         }
268
269         *status = supported;
270
271         return FEEDBACK_ERROR_NONE;
272 }
273
274 /* Internal APIs */
275 API int feedback_play_type_by_name(char *type, char *pattern)
276 {
277         feedback_type_e etype;
278         feedback_pattern_e epattern;
279         int type_max;
280         int pattern_max;
281
282         if (!type || !pattern) {
283                 _E("Invalid parameter : type(%x), pattern(%x)", type, pattern);
284                 return FEEDBACK_ERROR_INVALID_PARAMETER;
285         }
286
287         type_max = profile->max_type;
288         for (etype = 0; etype < type_max; ++etype) {
289                 if (!strncmp(type, profile->str_type[etype], strlen(type)))
290                         break;
291         }
292
293         if (etype == type_max) {
294                 _E("Invalid parameter : type(%s)", type);
295                 return FEEDBACK_ERROR_INVALID_PARAMETER;
296         }
297
298         pattern_max = profile->max_pattern;
299         for (epattern = 0; epattern < pattern_max; ++epattern) {
300                 if (!strncmp(pattern, profile->str_pattern[epattern], strlen(pattern)))
301                         break;
302         }
303
304         if (epattern == pattern_max) {
305                 _E("Invalid parameter : pattern(%s)", pattern);
306                 return FEEDBACK_ERROR_INVALID_PARAMETER;
307         }
308
309         return feedback_play_type(etype, epattern);
310 }
311
312 API int feedback_get_resource_path(feedback_type_e type, feedback_pattern_e pattern, char** path)
313 {
314         const struct device_ops *dev;
315         char buf[PATH_MAX] = {0,};
316         int err;
317
318         if (path == NULL) {
319                 _E("Invalid parameter : path(NULL)");
320                 return FEEDBACK_ERROR_INVALID_PARAMETER;
321         }
322
323         if (type <= FEEDBACK_TYPE_NONE ||
324             type >= profile->max_type) {
325                 _E("Invalid parameter : type(%d)", type);
326                 return FEEDBACK_ERROR_INVALID_PARAMETER;
327         }
328
329         if (pattern <= FEEDBACK_PATTERN_NONE ||
330             pattern >= profile->max_pattern) {
331                 _E("Invalid parameter : pattern(%d)", pattern);
332                 return FEEDBACK_ERROR_INVALID_PARAMETER;
333         }
334
335         /* proper device get path */
336         dev = find_device(type);
337         if (dev) {
338                 err = dev->get_path(pattern, buf, sizeof(buf));
339                 if (err < 0)
340                         return FEEDBACK_ERROR_OPERATION_FAILED;
341         }
342
343         *path = strdup(buf);
344         return FEEDBACK_ERROR_NONE;
345 }
346
347 API int feedback_set_resource_path(feedback_type_e type, feedback_pattern_e pattern, char *path)
348 {
349         const struct device_ops *dev;
350         int err;
351
352         if (type <= FEEDBACK_TYPE_NONE ||
353             type >= profile->max_type) {
354                 _E("Invalid parameter : type(%d)", type);
355                 return FEEDBACK_ERROR_INVALID_PARAMETER;
356         }
357
358         if (pattern <= FEEDBACK_PATTERN_NONE ||
359             pattern >= profile->max_pattern) {
360                 _E("Invalid parameter : pattern(%d)", pattern);
361                 return FEEDBACK_ERROR_INVALID_PARAMETER;
362         }
363
364         /* proper device set path */
365         dev = find_device(type);
366         if (dev) {
367                 err = dev->set_path(pattern, path);
368                 if (err < 0)
369                         return FEEDBACK_ERROR_OPERATION_FAILED;
370         }
371
372         return FEEDBACK_ERROR_NONE;
373 }