tizen 2.3 release
[framework/system/deviced.git] / src / core / buxton-helper.c
1 /*
2  * deviced
3  *
4  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 /*
21  * @file buxton-helper.c
22  *
23  * @desc Helper function for simplification of using and
24  * for looking like vconf interface
25  *
26  *
27  * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
28  *
29  */
30
31 #include <errno.h>
32 #include <string.h>
33 #include <stdbool.h>
34 #include <stdlib.h>
35
36 #include "buxton-helper.h"
37 #include "log.h"
38 #include "common.h"
39
40 #define BUXTON_ATTEMPT_NUMBER 5
41
42 static BuxtonClient client;
43
44 struct callback_context {
45         struct buxton_variant *b_variant;
46         int error_code;
47 };
48
49 void general_get_callback(BuxtonResponse response, void *data)
50 {
51         BuxtonKey key;
52         struct buxton_variant *b_variant;
53         struct callback_context *context;
54         void *p;
55         uint32_t ret;
56         BuxtonDataType key_type;
57
58         ret_msg_if(data == NULL,
59                 "Invalid pointer argument!");
60         context = (struct callback_context *)data;
61         ret_msg_if(context->b_variant == NULL,
62                 "Invalid b_variant argument!");
63
64         b_variant = context->b_variant;
65         context->error_code = -1;
66
67         ret = buxton_response_status(response);
68         ret_msg_if(ret, "Invalid buxton response");
69
70         p = buxton_response_value(response);
71
72         ret_msg_if(p == NULL, "Bad buxton response: %s", strerror(errno));
73
74         key = buxton_response_key(response);
75         if (!key) {
76                 free(p);
77                 return;
78         }
79
80         key_type = buxton_key_get_type(key);
81         if(key_type != b_variant->type) {
82                 _E("Not proper type");
83                 goto out;
84         }
85
86         switch (key_type) {
87         case STRING:
88                 b_variant->string_value = (char *)p;
89                 break;
90         case INT32:
91                 b_variant->int32_value = *(int32_t *)p;
92                 break;
93         case UINT32:
94                 b_variant->uint32_value = *(uint32_t *)p;
95                 break;
96         case INT64:
97                 b_variant->int64_value = *(int64_t *)p;
98                 break;
99         case UINT64:
100                 b_variant->uint64_value = *(uint64_t *)p;
101                 break;
102         case FLOAT:
103                 b_variant->float_value = *(float *)p;
104                 break;
105         case DOUBLE:
106                 b_variant->double_value = *(double *)p;
107                 break;
108         case BOOLEAN:
109                 b_variant->bool_value = *(bool *)p;
110                 break;
111         default:
112                 break;
113         }
114
115         context->error_code = 0;
116 out:
117         /* we need to free only in case of data types which was copied by
118          * _value_, string's pointer will be used by client */
119         if (key_type != STRING)
120                 free(p);
121         free(key);
122 }
123
124 static int init_buxton_client(void)
125 {
126         int ret;
127
128         if(client != NULL)
129                 return 0;
130
131         ret = buxton_open(&client);
132         ret_value_msg_if(ret <= 0, -1, "couldn't connect to buxton server");
133
134         return 0;
135 }
136
137 void finilize_buxton_client(void)
138 {
139         /* buxton_close is robust to null pointer */
140         buxton_close(client);
141 }
142
143 int buxton_get_var(char *layer_name, char *group_name,
144          char *key_name, struct buxton_variant *value)
145 {
146         BuxtonKey key;
147         int ret;
148         int attempts = 0;
149
150         struct callback_context context = {
151                 .b_variant = value,
152                 .error_code = 0,
153         };
154
155         ret_value_msg_if(value == NULL, -1,
156                 "Please provide valid pointer!");
157
158 get_init:
159         ret = init_buxton_client();
160         ++attempts;
161         ret_value_if(ret, ret);
162
163         key = buxton_key_create(group_name, key_name,
164                 layer_name, value->type);
165
166         ret = buxton_get_value(client, key, general_get_callback, &context,
167                 true);
168         buxton_key_free(key);
169         /* don't return buxton error code, need to return internal error
170          * code */
171         if (errno == EPIPE && attempts < BUXTON_ATTEMPT_NUMBER) {
172                 buxton_close(client);
173                 client = NULL;
174                 goto get_init;
175         }
176         return ret || context.error_code ? -1 : 0;
177 }
178
179 void general_set_callback(BuxtonResponse response, void *data)
180 {
181         BuxtonKey key;
182         char *name;
183         int *ret;
184         int resp_ret;
185
186         ret_msg_if(data == NULL, "Please provide *data for return value!");
187         ret = data;
188         resp_ret = buxton_response_status(response);
189
190         if (resp_ret != 0) {
191                 _E("Failed to set value\n");
192                 *ret = resp_ret;
193                 return;
194         }
195
196         key = buxton_response_key(response);
197         name = buxton_key_get_name(key);
198         _I("Set value for key %s\n", name);
199         buxton_key_free(key);
200         free(name);
201         *ret = 0;
202 }
203
204 /* for avoid ptr unligtment */
205 static void *get_variant_align(struct buxton_variant *b_variant)
206 {
207         switch (b_variant->type) {
208         case CONF_STRING:
209                 return b_variant->string_value;
210         case CONF_INT32:
211                 return &b_variant->int32_value;
212         case CONF_UINT32:
213                 return &b_variant->uint32_value;
214         case CONF_INT64:
215                 return &b_variant->int64_value;
216         case CONF_UINT64:
217                 return &b_variant->uint64_value;
218         case CONF_FLOAT:
219                 return &b_variant->float_value;
220         case CONF_DOUBLE:
221                 return &b_variant->double_value;
222         case CONF_BOOLEAN:
223                 return &b_variant->bool_value;
224         }
225         return NULL;
226 }
227
228 int buxton_set_var(char *layer_name, char *group_name,
229         char *key_name, struct buxton_variant *value)
230 {
231         int ret_data = -1;
232         BuxtonKey key;
233         int ret;
234         int attempts = 0;
235         ret_value_msg_if(value == NULL, -1, "Please provide valid pointer");
236
237 set_init:
238         ret = init_buxton_client();
239         ++attempts;
240         ret_value_if(ret, ret);
241
242         key = buxton_key_create(group_name, key_name,
243                 layer_name, value->type);
244
245         ret = buxton_set_value(client, key, get_variant_align(value),
246                 general_set_callback, &ret_data, true);
247         buxton_key_free(key);
248
249         if (errno == EPIPE && attempts < BUXTON_ATTEMPT_NUMBER) {
250                 buxton_close(client);
251                 client = NULL;
252                 goto set_init;
253         }
254
255         return ret || ret_data ? -1 : 0;
256 }
257