Revert "modify default plugin's behavior by emulator"
[sdk/target/sdbd.git] / src / plugin.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 #include <string.h>
18 #include <dlfcn.h>
19
20 #define TRACE_TAG TRACE_SDB
21 #include "log.h"
22
23 #include "sdb.h"
24
25 #include "hashtable.h"
26 #include "parameter.h"
27 #include "plugin.h"
28 #include "sdbd_plugin.h"
29
30 static void* plugin_handle = NULL;
31
32 PLUGIN_INIT plugin_init_proc = NULL;
33 PLUGIN_SYNCHRONOUS_CMD_PROC plugin_sync_proc = NULL;
34 PLUGIN_ASYNCHRONOUS_CMD_PROC plugin_async_proc = NULL;
35
36 hashtable* plugin_cmd_hashtable = NULL;
37
38 typedef struct _async_parameter {
39     int cmd;
40     parameters* in;
41     int out_fd;
42 } async_parameter;
43
44 // handler of event to be detected by plugin
45 int plugin_event_handler ( int event_type, parameters* data )
46 {
47     // TODO : implement event handler
48     if ( event_type == PLUGIN_EVENT_PWLOCK || event_type == PLUGIN_EVENT_FMMLOCK ) {
49         if ( data != NULL && data->number_of_parameter == 1 && data->array_of_parameter != NULL
50                 && data->array_of_parameter[0].type == type_int32 ) {
51
52             if ( data->array_of_parameter[0].v_int32 == PLUGIN_RET_ON ) {
53                 // locked
54                 is_pwlocked = 1;
55             } else {
56                 // unlocked
57                 is_pwlocked = 0;
58             }
59
60             send_device_status();
61
62             if ( data != NULL ) {
63                 release_parameters ( data );
64                 free ( data );
65             }
66         }
67     }
68
69     return 0;
70 }
71
72 // register commands that are supported by plugin
73 static int plugin_register_command ( int command, priority cmd_priority )
74 {
75     if ( plugin_cmd_hashtable ) {
76         hashtable_put ( plugin_cmd_hashtable, command, cmd_priority );
77     }
78     return 0;
79 }
80
81 // return 0 if fail to load sdbd plugin (use default plugin)
82 // return 1 if succeed to load sdbd plugin and get function pointer of plugin_init
83 static int load_plugin_not_default()
84 {
85     plugin_init_proc = NULL;
86     plugin_sync_proc = NULL;
87     plugin_async_proc = NULL;
88
89     plugin_handle = dlopen ( PLUGIN_PATH, RTLD_NOW );
90     if ( plugin_handle == NULL ) {
91         D ( "failed to dlopen(%s). error: %s\n", PLUGIN_PATH, dlerror() );
92         return 0;
93     }
94
95     plugin_init_proc = dlsym ( plugin_handle, PLUGIN_PROC_NAME_INIT );
96     if ( plugin_init_proc == NULL ) {
97         D ( "failed to get the sdbd plugin init function. error: %s\n", dlerror() );
98         dlclose ( plugin_handle );
99         plugin_handle = NULL;
100         return 0;
101     }
102
103     // if there is no implementation of plugin_sync_proc and plugin_async_proc,
104     // then use default_plugin_sync_proc and default_plugin_async_proc
105     plugin_sync_proc = dlsym ( plugin_handle, PLUGIN_PROC_NAME_SYNC_CMD );
106     if ( plugin_sync_proc == NULL ) {
107         plugin_sync_proc = default_plugin_sync_proc;
108     }
109
110     plugin_async_proc = dlsym ( plugin_handle, PLUGIN_PROC_NAME_ASYNC_CMD );
111     if ( plugin_async_proc == NULL ) {
112         plugin_async_proc = default_plugin_async_proc;
113     }
114
115     return 1;
116 }
117
118 void load_sdbd_plugin()
119 {
120     int ret;
121
122     plugin_cmd_hashtable = hashtable_create ( ht_size_31 );
123
124     ret = load_plugin_not_default();
125     if ( ret == 0 ) {
126         // use default plugin
127         plugin_init_proc = default_plugin_init;
128         plugin_sync_proc = default_plugin_sync_proc;
129         plugin_async_proc = default_plugin_async_proc;
130
131         D ( "using default plugin interface.\n" );
132     } else {
133         D ( "using sdbd plugin interface.(%s)\n", PLUGIN_PATH );
134
135         plugin_init_proc ( plugin_event_handler, plugin_register_command );
136     }
137
138     // use default plugin feature for the commands or events that are not supported by plugin
139     default_plugin_init ( plugin_event_handler, plugin_register_command );
140 }
141
142 void unload_sdbd_plugin()
143 {
144     if ( plugin_cmd_hashtable ) {
145         hashtable_destroy ( plugin_cmd_hashtable );
146         plugin_cmd_hashtable = NULL;
147     }
148
149     if ( plugin_handle ) {
150         dlclose ( plugin_handle );
151         plugin_handle = NULL;
152     }
153 }
154
155 // return 1 if plugin support given command
156 // return 0 if plugin does not support given command
157 int is_supported_by_plugin ( int cmd )
158 {
159     int ret = 0;
160
161     if ( plugin_cmd_hashtable ) {
162         int value;
163         ret = hashtable_get ( plugin_cmd_hashtable, cmd, &value );
164     }
165
166     return ret;
167 }
168
169 static int request_sync_cmd ( int cmd, parameters* in, parameters* out )
170 {
171     int ret, pr;
172
173     out->number_of_parameter = 0;
174     out->array_of_parameter = NULL;
175
176     ret = hashtable_get ( plugin_cmd_hashtable, cmd, &pr );
177     if ( ret == 1 ) {
178         // supported by plugin
179         ret = plugin_sync_proc ( cmd, in, out );
180         if ( ret == PLUGIN_CMD_NOT_SUPPORT ) {
181             // not supported by plugin
182             ret = default_plugin_sync_proc ( cmd, in, out );
183         }
184     } else {
185         // not supported by plugin
186         ret = default_plugin_sync_proc ( cmd, in, out );
187     }
188
189     return ret;
190 }
191
192 static void request_async_cmd ( int cmd, parameters* in, int out_fd )
193 {
194     int ret, pr;
195
196     ret = hashtable_get ( plugin_cmd_hashtable, cmd, &pr );
197     if ( ret == 1 ) {
198         // supported by plugin
199         ret = plugin_async_proc ( cmd, in, out_fd );
200         if ( ret == PLUGIN_CMD_NOT_SUPPORT ) {
201             // not supported by plugin
202             ret = default_plugin_async_proc ( cmd, in, out_fd );
203         }
204     } else {
205         // not supported by plugin
206         ret = default_plugin_async_proc ( cmd, in, out_fd );
207     }
208
209     release_parameters ( in );
210     if ( in != NULL ) {
211         free( in );
212     }
213     sdb_close(out_fd);
214 }
215
216 static void *async_proc_bootstrap_func(void *x)
217 {
218     async_parameter *p = x;
219     request_async_cmd(p->cmd, p->in, p->out_fd);
220     free(p);
221     return 0;
222 }
223
224 static int create_async_proc_thread( int cmd, parameters* in )
225 {
226     async_parameter* async_param;
227     sdb_thread_t t;
228     int s[2];
229
230     if( sdb_socketpair(s) ) {
231         D("cannot create async proc socket pair\n");
232         return -1;
233     }
234
235     async_param = ( async_parameter* ) malloc(sizeof(async_parameter));
236     if( async_param == NULL ) fatal("cannot allocate async_parameter");
237     async_param->cmd = cmd;
238     async_param->in = in;
239     async_param->out_fd = s[1];
240
241     if(sdb_thread_create( &t, async_proc_bootstrap_func, async_param)){
242         free(async_param);
243         sdb_close(s[0]);
244         sdb_close(s[1]);
245         D("cannot create async proc thread\n");
246         return -1;
247     }
248
249     D("async proc thread started, %d:%d\n",s[0], s[1]);
250     return s[0];
251 }
252
253 // return 1 if succeed to get capability from plugin
254 // return 0 otherwise
255 int request_capability_to_plugin ( int cap, char* out_buf, unsigned int out_len )
256 {
257     int success = 0;
258     int ret;
259     parameters in, out;
260
261     in.number_of_parameter = 1;
262     in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
263     in.array_of_parameter[0].type = type_int32;
264     in.array_of_parameter[0].v_int32 = cap;
265
266     ret = request_sync_cmd ( PLUGIN_SYNC_CMD_CAPABILITY, &in, &out );
267     if ( ret == PLUGIN_CMD_SUCCESS ) {
268         strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
269         out_buf[out_len - 1] = '\0';
270         success = 1;
271         release_parameters ( &out );
272     }
273
274     release_parameters ( &in );
275     return success;
276 }
277
278 // return 1 if allowed by plugin (valid)
279 // return 0 if disallowed by plugin (invalid)
280 int request_validity_to_plugin ( int cmd, const char* in_buf )
281 {
282     int success = 0;
283     int ret;
284     parameters in, out;
285
286     if ( in_buf != NULL ) {
287         in.number_of_parameter = 1;
288         in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
289         in.array_of_parameter[0].type = type_string;
290         in.array_of_parameter[0].v_string.length = strlen ( in_buf );
291         in.array_of_parameter[0].v_string.data = strdup ( in_buf );
292     } else {
293         in.number_of_parameter = 0;
294         in.array_of_parameter = NULL;
295     }
296
297     ret = request_sync_cmd ( cmd, &in, &out );
298     if ( ret == PLUGIN_CMD_SUCCESS ) {
299         success = ( out.array_of_parameter[0].v_int32 == PLUGIN_RET_VALID ) ? 1 : 0;
300         release_parameters ( &out );
301     }
302
303     release_parameters ( &in );
304     return success;
305 }
306
307 // return 1 if succeed to convert
308 // return 0 otherwise
309 int request_conversion_to_plugin ( int cmd, const char* in_buf, char* out_buf, unsigned int out_len )
310 {
311     int success = 0;
312     int ret;
313     parameters in, out;
314
315     in.number_of_parameter = 1;
316     in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
317     in.array_of_parameter[0].type = type_string;
318     in.array_of_parameter[0].v_string.length = strlen ( in_buf );
319     in.array_of_parameter[0].v_string.data = strdup ( in_buf );
320
321     ret = request_sync_cmd ( cmd, &in, &out );
322     if ( ret == PLUGIN_CMD_SUCCESS ) {
323         strncpy ( out_buf, out.array_of_parameter[0].v_string.data, out_len - 1 );
324         out_buf[out_len - 1] = '\0';
325         success = 1;
326         release_parameters ( &out );
327     }
328
329     release_parameters ( &in );
330     return success;
331 }
332
333 // return 1 if locked
334 // return 0 if unlocked
335 // return -1 if request failed
336 int request_lock_state_to_plugin ( int lock_type )
337 {
338     int result = -1;
339     int ret;
340     parameters in, out;
341
342     in.number_of_parameter = 1;
343     in.array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
344     in.array_of_parameter[0].type = type_int32;
345     in.array_of_parameter[0].v_int32 = lock_type;
346
347     ret = request_sync_cmd ( PLUGIN_SYNC_CMD_GET_LOCK_STATE, &in, &out );
348     if ( ret == PLUGIN_CMD_SUCCESS ) {
349         if ( out.array_of_parameter[0].v_int32 == PLUGIN_RET_ON ) {
350             result = 1;
351         } else {
352             result = 0;
353         }
354         is_pwlocked = result;
355         release_parameters ( &out );
356     }
357
358     release_parameters ( &in );
359
360     return result;
361 }
362
363 // return nonnegative integer that is a socket descriptor for communication
364 //        with async proc thread if success to create async proc thread
365 // return -1 if failed to create async proc thread
366 int request_appcmd_to_plugin ( const char* in_buf )
367 {
368     parameters* in;
369     int fd;
370
371     in = ( parameters* ) malloc ( sizeof ( parameters ) );
372     if ( in_buf != NULL ) {
373         in->number_of_parameter = 1;
374         in->array_of_parameter = ( parameter* ) malloc ( sizeof ( parameter ) );
375         in->array_of_parameter[0].type = type_string;
376         in->array_of_parameter[0].v_string.length = strlen ( in_buf );
377         in->array_of_parameter[0].v_string.data = strdup ( in_buf );
378     } else {
379         in->number_of_parameter = 0;
380         in->array_of_parameter = NULL;
381     }
382
383     fd = create_async_proc_thread( PLUGIN_ASYNC_CMD_APPCMD_SERVICE, in );
384
385     return fd;
386 }