dbus: replace old dbus api with GVariant support api
[platform/core/system/libsvi.git] / src / vibrator.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 <stdlib.h>
21 #include <stdbool.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <assert.h>
25 #include <limits.h>
26 #include <vconf.h>
27 #include <sys/stat.h>
28 #include <system_info.h>
29
30 #include "feedback.h"
31 #include "profiles.h"
32 #include "parser.h"
33 #include "devices.h"
34 #include "log.h"
35 #include "dbus.h"
36
37 #define HAPTIC_DEVICE                           0
38
39 enum haptic_iteration {
40         HAPTIC_ITERATION_ONCE = 1,
41         HAPTIC_ITERATION_INFINITE = 256,
42 };
43
44 #define METHOD_OPEN                 "OpenDevice"
45 #define METHOD_CLOSE                "CloseDevice"
46 #define METHOD_VIBRATE_PATTERN      "VibratePattern"
47 #define METHOD_STOP                 "StopDevice"
48 #define METHOD_IS_SUPPORTED         "IsSupported"
49 #define METHOD_GET_EFFECT           "GetEffect"
50
51 #define DEFAULT_DURATION            100
52 #define SIP_DURATION                60
53 #define WHITESPACE                  " \t"
54
55 #define VIBRATION_FEATURE              "http://tizen.org/feature/feedback.vibration"
56
57 static int vibstatus;
58 static unsigned int v_handle;
59
60 static inline char *trim_str(char *s)
61 {
62         char *t;
63         /* left trim */
64         s += strspn(s, WHITESPACE);
65
66         /* right trim */
67         for (t = strchr(s, 0); t > s; t--)
68                 if (!strchr(WHITESPACE, t[-1]))
69                         break;
70         *t = 0;
71         return s;
72 }
73
74 inline int is_vibration_mode(void)
75 {
76         return vibstatus;
77 }
78
79 static int haptic_open(void)
80 {
81         return dbus_method_sync_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC,
82                         VIBRATOR_INTERFACE_HAPTIC, METHOD_OPEN,
83                         g_variant_new("(i)", HAPTIC_DEVICE));
84 }
85
86 static int haptic_close(unsigned int handle)
87 {
88         return dbus_method_sync_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC,
89                         VIBRATOR_INTERFACE_HAPTIC, METHOD_CLOSE,
90                         g_variant_new("(u)", handle));
91 }
92
93 static int haptic_is_supported(const char *pattern)
94 {
95         return dbus_method_sync_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC,
96                         VIBRATOR_INTERFACE_HAPTIC, METHOD_IS_SUPPORTED,
97                         g_variant_new("(s)", pattern));
98 }
99
100 static int haptic_vibrate_effect(unsigned int handle,
101                                                                 const char *pattern,
102                                                                 int feedback,
103                                                                 int priority)
104 {
105         return dbus_method_sync_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC,
106                         VIBRATOR_INTERFACE_HAPTIC, METHOD_VIBRATE_PATTERN,
107                         g_variant_new("(usii)", handle, pattern, feedback, priority));
108 }
109
110 static int haptic_vibrate_stop(unsigned int handle)
111 {
112         return dbus_method_sync_var(VIBRATOR_BUS_NAME, VIBRATOR_PATH_HAPTIC,
113                         VIBRATOR_INTERFACE_HAPTIC, METHOD_STOP,
114                         g_variant_new("(u)", handle));
115 }
116
117 static int get_priority(feedback_pattern_e pattern)
118 {
119         if (profile->get_priority)
120                 return profile->get_priority(pattern);
121         return PRIORITY_MIDDLE;
122 }
123
124 static void vibrator_init(void)
125 {
126         int ret;
127         bool haptic_avail;
128
129         ret = system_info_get_platform_bool(VIBRATION_FEATURE, &haptic_avail);
130         if (ret < 0) {
131                 v_handle = -ENOTSUP;
132                 return;
133         } else if (ret == 0 && !haptic_avail) {
134                 v_handle = -ENOTSUP;
135                 return;
136         }
137
138         /* Vibration Init */
139         ret = haptic_open();
140         if (ret == -EACCES || ret == -ECOMM || ret == -EPERM) {
141                 _E("haptic_open ==> FAIL!! : %d", ret); //LCOV_EXCL_LINE
142                 v_handle = -EACCES; //LCOV_EXCL_LINE System Error
143                 return; //LCOV_EXCL_LINE System Error
144         }
145         if (ret < 0) {
146                 _E("haptic_open ==> FAIL!! : %d", ret); //LCOV_EXCL_LINE
147                 v_handle = -ENOTSUP; //LCOV_EXCL_LINE System Error
148                 return; //LCOV_EXCL_LINE System Error
149         }
150
151         /* Set vibration handle */
152         v_handle = (unsigned int)ret;
153 }
154
155 static void vibrator_exit(void)
156 {
157         int ret;
158
159         if ((int)v_handle > 0) {
160                 ret = haptic_close(v_handle);
161                 if (ret < 0)
162                         _E("haptic_close is failed : %d", ret); //LCOV_EXCL_LINE
163                 v_handle = 0;
164         }
165
166 }
167
168 static int vibrator_play(feedback_pattern_e pattern)
169 {
170         char *temp;
171         char *data;
172         int ret;
173         int level;
174
175         if ((int)v_handle <= 0) {
176                 if (v_handle == 0) { //LCOV_EXCL_LINE System Error
177                         _E("Not initialized"); //LCOV_EXCL_LINE
178                         return -ENOENT; //LCOV_EXCL_LINE System Error
179                 }
180                 _E("Not supported vibration"); //LCOV_EXCL_LINE
181                 return v_handle; //LCOV_EXCL_LINE System Error
182         }
183
184         if (vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &vibstatus) < 0) {
185                 _D("fail to get vibration status, will work as turning off"); //LCOV_EXCL_LINE
186                 vibstatus = 0;
187         }
188
189         if (vibstatus == 0 && profile->get_always_alert_case &&
190             !profile->get_always_alert_case(FEEDBACK_TYPE_VIBRATION, pattern))  {
191                 _D("Vibration condition is OFF (vibstatus : %d)", vibstatus); //LCOV_EXCL_LINE
192                 return 0;
193         }
194
195         if (vibstatus && profile->get_always_off_case &&
196             profile->get_always_off_case(FEEDBACK_TYPE_VIBRATION, pattern)) {
197                 _D("Vibration always off condition"); //LCOV_EXCL_LINE
198                 return 0;
199         }
200
201         if (pattern <= FEEDBACK_PATTERN_NONE ||
202             pattern >= profile->max_pattern) {
203                 _E("Not supported vibration pattern"); //LCOV_EXCL_LINE
204                 return -ENOTSUP;
205         }
206
207         if (profile->get_strength_type)
208                 level = profile->get_strength_type(FEEDBACK_TYPE_VIBRATION, pattern);
209         else
210                 level = DEFAULT_VIB_LEVEL * HAPTIC_FEEDBACK_STEP;
211
212         temp = strdup(profile->str_pattern(pattern));
213         data = trim_str(temp);
214         if (!data) {
215                 free(temp);
216                 _E("Not supported vibration pattern"); //LCOV_EXCL_LINE
217                 return -ENOTSUP;
218         }
219
220         _D("pattern : %s", data);
221
222         ret = haptic_vibrate_effect(v_handle, data, level, get_priority(pattern));
223
224         if (ret < 0) {
225                 _E("fail to play vibration"); //LCOV_EXCL_LINE
226                 free(temp);
227                 if (ret == -ECOMM || ret == -ENOTSUP)
228                         return ret; //LCOV_EXCL_LINE System Error
229                 return -EPERM;
230         }
231
232         _D("Play success! Data is %s", data);
233         free(temp);
234         return 0;
235 }
236
237 static int vibrator_stop(void)
238 {
239         int ret;
240
241         if ((int)v_handle <= 0) {
242                 if (v_handle == 0) { //LCOV_EXCL_LINE System Error
243                         _E("Not initialized"); //LCOV_EXCL_LINE
244                         return -ENOENT; //LCOV_EXCL_LINE System Error
245                 }
246                 _E("Not supported vibration"); //LCOV_EXCL_LINE
247                 return v_handle; //LCOV_EXCL_LINE System Error
248         }
249
250         /* stop haptic device */
251         ret = haptic_vibrate_stop(v_handle);
252         if (ret < 0) {
253                 _E("haptic_vibrate_stop is failed"); //LCOV_EXCL_LINE
254                 if (ret == -ECOMM)
255                         return ret; //LCOV_EXCL_LINE System Error
256                 return -EPERM;
257         }
258
259         return 0;
260 }
261
262 static int vibrator_is_supported(int pattern, bool *supported)
263 {
264         char *temp;
265         char *data;
266         int ret = 0;
267
268         if (!supported) {
269                 _E("Invalid parameter : supported(NULL)"); //LCOV_EXCL_LINE
270                 return -EINVAL;
271         }
272
273         if ((int)v_handle <= 0) {
274                 if (v_handle == 0) { //LCOV_EXCL_LINE System Error
275                         _E("Not initialized"); //LCOV_EXCL_LINE
276                         return -ENOENT; //LCOV_EXCL_LINE System Error
277                 }
278                 _E("Not supported vibration"); //LCOV_EXCL_LINE
279                 *supported = false; //LCOV_EXCL_LINE System Error
280                 return v_handle;
281         }
282
283         if (pattern <= FEEDBACK_PATTERN_NONE ||
284             pattern >= profile->max_pattern) {
285                 _E("Not supported vibration pattern"); //LCOV_EXCL_LINE
286                 *supported = false;
287                 return 0;
288         }
289
290         /* get vibration data */
291         temp = strdup(profile->str_pattern(pattern));
292         data = trim_str(temp);
293         if (!data) {
294                 free(temp);
295                 *supported = false;
296                 return 0;
297         }
298
299         ret = haptic_is_supported(data);
300         free(temp);
301         if (ret < 0) {
302                 _E("fail to get support information"); //LCOV_EXCL_LINE
303                 if (ret == -ECOMM)
304                         return ret;
305                 return -EPERM;
306         }
307
308         _D("is_supported : %d", ret);
309         *supported = ret;
310         return 0;
311 }
312
313 //LCOV_EXCL_START Not Supported Feature
314 static int vibrator_get_path(feedback_pattern_e pattern, char *buf, unsigned int buflen)
315 {
316         return 0;
317 }
318
319 static int vibrator_set_path(feedback_pattern_e pattern, char *path)
320 {
321         return 0;
322 }
323 //LCOV_EXCL_STOP
324
325 static const struct device_ops vibrator_device_ops = {
326         .type = FEEDBACK_TYPE_VIBRATION,
327         .name = "Vibrator",
328         .init = vibrator_init,
329         .exit = vibrator_exit,
330         .play = vibrator_play,
331         .stop = vibrator_stop,
332         .is_supported = vibrator_is_supported,
333         .get_path = vibrator_get_path,
334         .set_path = vibrator_set_path,
335 };
336
337 DEVICE_OPS_REGISTER(&vibrator_device_ops);