00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "internal.h"
00031 #include "eripc_support.h"
00032
00033 #define DBUS_SERVICE_SYSTEM_CONTROL "com.irexnet.sysd"
00034 #define DBUS_SERVICE_POPUP_MENU "com.irexnet.popupmenu"
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #define MAKE_VARARG_CALL(destination, message, ...) \
00047 { \
00048 g_assert( ccontext ); \
00049 if (eripc_send_varargs( \
00050 ccontext->context, \
00051 NULL, \
00052 NULL, \
00053 ERIPC_BUS_SESSION, \
00054 destination, \
00055 message, \
00056 __VA_ARGS__) != ERIPC_ERROR_SUCCESS) \
00057 { \
00058 ULOG_DEBUG_F("eripc_send_varargs failed"); \
00059 return FALSE; \
00060 } \
00061 return TRUE; \
00062 }
00063
00064
00065
00066
00067 #define MAKE_VARARG_CALL_1S(destination, message, s1) \
00068 MAKE_VARARG_CALL(destination, message, \
00069 ERIPC_TYPE_STRING, s1, \
00070 ERIPC_TYPE_INVALID);
00071
00072
00073
00074
00075 #define MAKE_VARARG_CALL_2S(destination, message, s1, s2) \
00076 MAKE_VARARG_CALL(destination, message, \
00077 ERIPC_TYPE_STRING, s1, \
00078 ERIPC_TYPE_STRING, s2, \
00079 ERIPC_TYPE_INVALID);
00080
00081
00082
00083
00084 #define MAKE_VARARG_CALL_3S(destination, message, s1, s2, s3) \
00085 MAKE_VARARG_CALL(destination, message, \
00086 ERIPC_TYPE_STRING, s1, \
00087 ERIPC_TYPE_STRING, s2, \
00088 ERIPC_TYPE_STRING, s3, \
00089 ERIPC_TYPE_INVALID);
00090
00091
00092
00093
00094
00095
00096
00097 #define MAKE_SIGNAL_VARARG_CALL(interface, message, ...) \
00098 { \
00099 g_assert( ccontext ); \
00100 if (eripc_send_signal_varargs( \
00101 ccontext->context, \
00102 ERIPC_BUS_SESSION, \
00103 ccontext->path, \
00104 interface, \
00105 message, \
00106 __VA_ARGS__) != ERIPC_ERROR_SUCCESS) \
00107 { \
00108 ULOG_DEBUG_F("eripc_send_signal_varargs failed"); \
00109 return FALSE; \
00110 } \
00111 return TRUE; \
00112 }
00113
00114
00115
00116
00117
00118
00119
00120 #define MAKE_VARARG_WAIT_CALL(interface, message, reply_parser, ...) \
00121 { \
00122 eripc_event_info_t *reply = NULL; \
00123 result = eripc_send_varargs_and_wait( \
00124 ccontext->context, \
00125 &reply, \
00126 ERIPC_BUS_SESSION, \
00127 interface, \
00128 message, \
00129 __VA_ARGS__); \
00130 if (result != ERIPC_ERROR_SUCCESS) \
00131 ULOG_DEBUG_F("eripc_send_varargs_and_wait failed"); \
00132 else if (reply == NULL || reply->args == NULL) \
00133 ULOG_DEBUG_F("sysd returns OK but no reply structure"); \
00134 else \
00135 retval = reply_parser; \
00136 eripc_event_info_free(ccontext->context, reply); \
00137 }
00138
00139
00140
00141
00142 #define MAKE_BUSY_TIMEOUT_START(seconds) \
00143 { \
00144 result = eripc_get_timeout(ccontext->context, &old_timeout); \
00145 if (result == ERIPC_ERROR_SUCCESS) \
00146 { \
00147 result = eripc_set_timeout(ccontext->context, (seconds)*1000); \
00148 timeout_set = (result == ERIPC_ERROR_SUCCESS); \
00149 } \
00150 }
00151
00152
00153
00154
00155
00156 #define MAKE_BUSY_TIMEOUT_END() \
00157 { \
00158 if (timeout_set) \
00159 eripc_set_timeout(ccontext->context, old_timeout); \
00160 }
00161
00162
00163 static int parse_reply_capabilities( eripc_event_info_t *reply, eripc_device_caps_t *dev_caps );
00164 static int parse_reply_start(eripc_event_info_t *reply, char **err_message);
00165
00166 static char *fix_name(const char* raw_name)
00167 {
00168 char *name = strdup(raw_name);
00169 if (name == NULL) {
00170 ULOG_CRIT_F("fix_name failed: out of memory");
00171 return NULL;
00172 }
00173
00174
00175 unsigned int i;
00176 for (i=0; i<strlen(name); i++)
00177 {
00178 if (name[i] == '-')
00179 name[i] = '_';
00180 }
00181 return name;
00182 }
00183
00184
00185
00186
00187
00188
00189 eripc_client_context_t *eripc_client_context_new( const char *raw_name,
00190 const char *version,
00191 const char *raw_service,
00192 const char *raw_path,
00193 const char *raw_interface,
00194 eripc_callback_function_t *callbacks )
00195 {
00196 int retval;
00197 eripc_client_context_t* ccontext;
00198
00199 ccontext = (eripc_client_context_t*)malloc(sizeof(eripc_client_context_t));
00200
00201 char *name = fix_name(raw_name);
00202 char *service = fix_name(raw_service);
00203 char *path = fix_name(raw_path);
00204 char *interface = fix_name(raw_interface);
00205
00206 ccontext->context = eripc_init(name, version, NULL);
00207 if (ccontext->context == NULL)
00208 {
00209
00210 ULOG_ERR("Failed to initialize eripc context");
00211 free(ccontext);
00212 return NULL;
00213 }
00214
00215 if (callbacks != NULL)
00216 {
00217 for (int i = 0 ; callbacks[i].handler != NULL ; i++)
00218 {
00219 if (callbacks[i].interface)
00220 {
00221
00222 char *cb_interface = fix_name(callbacks[i].interface);
00223 retval = eripc_set_signal_handler( ccontext->context,
00224 callbacks[i].handler,
00225 NULL,
00226 ERIPC_BUS_SESSION,
00227 cb_interface,
00228 callbacks[i].message_name,
00229 &(callbacks[i].handler_id) );
00230
00231 free(cb_interface);
00232 if (retval != ERIPC_ERROR_SUCCESS)
00233 {
00234 ULOG_DEBUG_F( "eripc_set_signal_handler %s returns %d",
00235 callbacks[i].message_name,
00236 retval );
00237 }
00238 }
00239 else
00240 {
00241
00242 retval = eripc_set_message_handler( ccontext->context,
00243 callbacks[i].handler,
00244 NULL,
00245 ERIPC_BUS_SESSION,
00246 interface,
00247 callbacks[i].message_name,
00248 &(callbacks[i].handler_id) );
00249
00250 if (retval != ERIPC_ERROR_SUCCESS)
00251 {
00252 ULOG_DEBUG_F( "eripc_set_message_handler %s returns %d",
00253 callbacks[i].message_name,
00254 retval );
00255 }
00256 }
00257 }
00258 }
00259
00260 free(interface);
00261
00262 ccontext->name = name;
00263 ccontext->service = service;
00264 ccontext->path = path;
00265 return ccontext;
00266 }
00267
00268
00269 void eripc_client_context_free( eripc_client_context_t *ccontext,
00270 eripc_callback_function_t *callbacks )
00271 {
00272 if (callbacks != NULL)
00273 {
00274 for (int i = 0 ; callbacks[i].handler_id != 0 ; i++)
00275 {
00276 eripc_unset_handler(ccontext->context, callbacks[i].handler_id);
00277 }
00278 }
00279
00280 if (ccontext)
00281 {
00282 free(ccontext->name);
00283 free(ccontext->service);
00284 free(ccontext->path);
00285 free(ccontext);
00286 }
00287 }
00288
00289
00290 const gchar* eripc_error_string(eripc_error_t errorcode)
00291 {
00292 switch (errorcode)
00293 {
00294 case ERIPC_ERROR_SUCCESS:
00295 return "No error (ERIPC_ERROR_SUCCESS)";
00296 case ERIPC_ERROR:
00297 return "Some kind of error occurred (ERIPC_ERROR)";
00298 case ERIPC_ERROR_INVALID:
00299 return "At least one parameter is invalid (ERIPC_ERROR_INVALID)";
00300 case ERIPC_ERROR_OOM:
00301 return "Out of memory error (ERIPC_ERROR_OOM)";
00302 case ERIPC_ERROR_TIMEOUT:
00303 return "Timeout error (ERIPC_ERROR_TIMEOUT)";
00304 default:
00305 return "Unknown/Undefined";
00306 }
00307 }
00308
00309
00310
00311
00312
00313
00314 gboolean eripc_menu_add_menu( eripc_client_context_t *ccontext,
00315 const char *name,
00316 const char *group1,
00317 const char *group2,
00318 const char *group3,
00319 const char *group4 )
00320 {
00321 MAKE_VARARG_CALL(DBUS_SERVICE_POPUP_MENU, "addMenu",
00322 ERIPC_TYPE_STRING, name,
00323 ERIPC_TYPE_STRING, "",
00324 ERIPC_TYPE_STRING, ccontext->service,
00325 ERIPC_TYPE_STRING, group1,
00326 ERIPC_TYPE_STRING, group2,
00327 ERIPC_TYPE_STRING, group3,
00328 ERIPC_TYPE_STRING, group4,
00329 ERIPC_TYPE_INVALID );
00330 }
00331
00332
00333 gboolean eripc_menu_remove_menu( eripc_client_context_t *ccontext,
00334 const char *name )
00335 {
00336 MAKE_VARARG_CALL_1S(DBUS_SERVICE_POPUP_MENU, "removeMenu", name);
00337 }
00338
00339
00340 gboolean eripc_menu_add_group( eripc_client_context_t *ccontext,
00341 const char *name,
00342 const char *parent,
00343 const char *image )
00344 {
00345 MAKE_VARARG_CALL(DBUS_SERVICE_POPUP_MENU, "addGroup",
00346 ERIPC_TYPE_STRING, name,
00347 ERIPC_TYPE_STRING, parent,
00348 ERIPC_TYPE_STRING, "",
00349 ERIPC_TYPE_STRING, image,
00350 ERIPC_TYPE_INVALID );
00351 }
00352
00353
00354 gboolean eripc_menu_add_item( eripc_client_context_t *ccontext,
00355 const char *name,
00356 const char *parent,
00357 const char *image )
00358 {
00359 MAKE_VARARG_CALL(DBUS_SERVICE_POPUP_MENU, "addItem",
00360 ERIPC_TYPE_STRING, name,
00361 ERIPC_TYPE_STRING, parent,
00362 ERIPC_TYPE_STRING, "",
00363 ERIPC_TYPE_STRING, image,
00364 ERIPC_TYPE_INVALID );
00365 }
00366
00367
00368 gboolean eripc_menu_set_menu_label ( eripc_client_context_t *ccontext,
00369 const char *name,
00370 const char *label )
00371 {
00372 MAKE_VARARG_CALL_2S(DBUS_SERVICE_POPUP_MENU, "setMenuLabel", name, label);
00373 }
00374
00375
00376 gboolean eripc_menu_set_group_label ( eripc_client_context_t *ccontext,
00377 const char *name,
00378 const char *label )
00379 {
00380 MAKE_VARARG_CALL_2S(DBUS_SERVICE_POPUP_MENU, "setGroupLabel", name, label);
00381 }
00382
00383
00384 gboolean eripc_menu_set_item_label ( eripc_client_context_t *ccontext,
00385 const char *name,
00386 const char *parent,
00387 const char *label )
00388 {
00389 MAKE_VARARG_CALL_3S(DBUS_SERVICE_POPUP_MENU, "setItemLabel",
00390 name, parent, label);
00391 }
00392
00393
00394 gboolean eripc_menu_show_menu( eripc_client_context_t *ccontext,
00395 const char *name )
00396 {
00397 MAKE_VARARG_CALL_1S(DBUS_SERVICE_POPUP_MENU, "showMenu", name);
00398 }
00399
00400
00401 gboolean eripc_menu_set_group_state( eripc_client_context_t *ccontext,
00402 const char *name,
00403 const char *state )
00404 {
00405 MAKE_VARARG_CALL_2S(DBUS_SERVICE_POPUP_MENU, "setGroupState", name, state);
00406 }
00407
00408
00409 gboolean eripc_menu_set_item_state( eripc_client_context_t *ccontext,
00410 const char *name,
00411 const char *parent,
00412 const char *state )
00413 {
00414 MAKE_VARARG_CALL_3S(DBUS_SERVICE_POPUP_MENU, "setItemState",
00415 name, parent, state);
00416 }
00417
00418 gboolean eripc_menu_set_pagecounter( eripc_client_context_t *ccontext,
00419 int cur_page,
00420 int num_pages,
00421 gboolean boundary_check )
00422 {
00423 MAKE_VARARG_CALL(DBUS_SERVICE_POPUP_MENU, "updatePageCounter",
00424 ERIPC_TYPE_INT, cur_page,
00425 ERIPC_TYPE_INT, num_pages,
00426 ERIPC_TYPE_BOOL, boundary_check,
00427 ERIPC_TYPE_INVALID );
00428 }
00429
00430
00431 gboolean eripc_menu_set_statusitem_state( eripc_client_context_t *ccontext,
00432 const char *item,
00433 const char *state )
00434 {
00435 MAKE_VARARG_CALL_2S(DBUS_SERVICE_POPUP_MENU, "setStatusItemState", item, state);
00436 }
00437
00438
00439
00440
00441
00442 gboolean eripc_sysd_set_menu_state( eripc_client_context_t *ccontext,
00443 const char *state )
00444 {
00445 MAKE_VARARG_CALL_1S(DBUS_SERVICE_SYSTEM_CONTROL, "menuRequestPopup", state);
00446 }
00447
00448
00449 gboolean eripc_sysd_mount_sd_card( eripc_client_context_t *ccontext , gboolean show_index_splash)
00450 {
00451 MAKE_VARARG_CALL(DBUS_SERVICE_SYSTEM_CONTROL, "sysCardMount",
00452 ERIPC_TYPE_BOOL, show_index_splash, ERIPC_TYPE_INVALID );
00453 }
00454
00455
00456 gboolean eripc_sysd_unmount_sd_card( eripc_client_context_t *ccontext )
00457 {
00458 MAKE_VARARG_CALL(DBUS_SERVICE_SYSTEM_CONTROL, "sysCardUnmount",
00459 ERIPC_TYPE_INVALID );
00460 }
00461
00462
00463 gboolean eripc_sysd_set_busy( eripc_client_context_t *ccontext,
00464 const char *state,
00465 const char *message )
00466 {
00467 MAKE_VARARG_CALL_2S(DBUS_SERVICE_SYSTEM_CONTROL, "sysSetBusy", state, message);
00468 }
00469
00470 gboolean eripc_sysd_reset_busy( eripc_client_context_t *ccontext )
00471 {
00472 MAKE_VARARG_CALL(DBUS_SERVICE_SYSTEM_CONTROL, "sysResetBusy",
00473 ERIPC_TYPE_INVALID );
00474 }
00475
00476 gboolean eripc_sysd_set_bg_busy( eripc_client_context_t *ccontext )
00477 {
00478 MAKE_VARARG_CALL(DBUS_SERVICE_SYSTEM_CONTROL, "sysSetBgBusy",
00479 ERIPC_TYPE_INVALID );
00480 }
00481
00482 gboolean eripc_sysd_reset_bg_busy( eripc_client_context_t *ccontext )
00483 {
00484 MAKE_VARARG_CALL(DBUS_SERVICE_SYSTEM_CONTROL, "sysResetBgBusy",
00485 ERIPC_TYPE_INVALID );
00486 }
00487
00488 gboolean eripc_sysd_set_keyboard( eripc_client_context_t *ccontext,
00489 const char *state)
00490 {
00491 MAKE_VARARG_CALL_1S(DBUS_SERVICE_SYSTEM_CONTROL, "sysSetKeyboard", state);
00492 }
00493
00494 gboolean eripc_sysd_startup_complete( eripc_client_context_t *ccontext,
00495 const int pid,
00496 const gboolean is_multidoc,
00497 const int xid)
00498 {
00499 MAKE_SIGNAL_VARARG_CALL(DBUS_SERVICE_SYSTEM_CONTROL, "startupComplete",
00500 ERIPC_TYPE_STRING, ccontext->name,
00501 ERIPC_TYPE_INT, pid,
00502 ERIPC_TYPE_BOOL, is_multidoc,
00503 ERIPC_TYPE_STRING, ccontext->service,
00504 ERIPC_TYPE_INT, xid,
00505 ERIPC_TYPE_INVALID );
00506 }
00507
00508
00509
00510
00511 static int parse_reply_start(eripc_event_info_t *reply, char **err_message)
00512 {
00513 int retval = 0;
00514 if (reply->args[0].type == ERIPC_TYPE_INT)
00515 {
00516 retval = reply->args[0].value.i;
00517 if (reply->args[1].type == ERIPC_TYPE_STRING)
00518 {
00519 gchar *message = reply->args[1].value.s;
00520 if ( (message != NULL) && (err_message != NULL))
00521 {
00522 *err_message = g_strdup(message);
00523 }
00524 }
00525 }
00526 else
00527 {
00528 ULOG_DEBUG_F("unexpected reply argument");
00529 }
00530 return retval;
00531 }
00532
00533 gint eripc_sysd_start_task( eripc_client_context_t *ccontext,
00534 const gchar *cmd_line,
00535 const gchar *work_dir,
00536 const gchar *label,
00537 const gchar *thumbnail_path,
00538 gchar **err_message )
00539 {
00540 int old_timeout;
00541 int timeout_set = 0;
00542 int retval = 0;
00543 eripc_error_t result;
00544
00545 MAKE_BUSY_TIMEOUT_START(60);
00546 MAKE_VARARG_WAIT_CALL(DBUS_SERVICE_SYSTEM_CONTROL, "startTask",
00547 parse_reply_start(reply, err_message),
00548 ERIPC_TYPE_STRING, cmd_line,
00549 ERIPC_TYPE_STRING, work_dir,
00550 ERIPC_TYPE_STRING, label,
00551 ERIPC_TYPE_STRING, thumbnail_path,
00552 ERIPC_TYPE_INVALID );
00553 MAKE_BUSY_TIMEOUT_END();
00554 return retval;
00555 }
00556
00557 gboolean eripc_sysd_stop_task( eripc_client_context_t *ccontext,
00558 const char *cmd_line )
00559 {
00560 MAKE_VARARG_CALL_1S(DBUS_SERVICE_SYSTEM_CONTROL, "stopTask", cmd_line);
00561 }
00562
00563 gint eripc_sysd_open_url ( eripc_client_context_t *ccontext,
00564 const gchar *url,
00565 const gchar *label,
00566 const gchar *back_text,
00567 gchar **err_message )
00568 {
00569 int old_timeout;
00570 int timeout_set = 0;
00571 int retval = 0;
00572 eripc_error_t result;
00573
00574 MAKE_BUSY_TIMEOUT_START(60);
00575 MAKE_VARARG_WAIT_CALL(DBUS_SERVICE_SYSTEM_CONTROL, "openUrl",
00576 parse_reply_start(reply, err_message),
00577 ERIPC_TYPE_STRING, url,
00578 ERIPC_TYPE_STRING, label,
00579 ERIPC_TYPE_STRING, back_text,
00580 ERIPC_TYPE_INVALID );
00581 MAKE_BUSY_TIMEOUT_END();
00582 return retval;
00583 }
00584
00585 static int parse_reply_capabilities( eripc_event_info_t *reply, eripc_device_caps_t *dev_caps )
00586 {
00587 int i;
00588 gboolean ok = TRUE;
00589 const eripc_arg_t *arg = NULL;
00590
00591
00592 for ( i = 0, arg = reply->args ;
00593 arg->type != ERIPC_TYPE_INVALID ;
00594 i++, arg++ )
00595 {
00596 ok = FALSE;
00597 switch (i)
00598 {
00599 case 0:
00600 if (arg->type == ERIPC_TYPE_BOOL)
00601 {
00602 dev_caps->has_stylus = arg->value.b ? TRUE : FALSE;
00603 ok = TRUE;
00604 }
00605 break;
00606 case 1:
00607 if (arg->type == ERIPC_TYPE_BOOL)
00608 {
00609 dev_caps->has_wifi = arg->value.b ? TRUE : FALSE;
00610 ok = TRUE;
00611 }
00612 break;
00613 case 2:
00614 if (arg->type == ERIPC_TYPE_BOOL)
00615 {
00616 dev_caps->has_bluetooth = arg->value.b ? TRUE : FALSE;
00617 ok = TRUE;
00618 }
00619 break;
00620 case 3:
00621 if (arg->type == ERIPC_TYPE_BOOL)
00622 {
00623 dev_caps->has_3g = arg->value.b ? TRUE : FALSE;
00624 ok = TRUE;
00625 }
00626 break;
00627 default:
00628 ;
00629 }
00630 if (!ok)
00631 {
00632 ULOG_DEBUG_F("unexpected argument");
00633 }
00634 }
00635 return ok ? 0 : 1;
00636 }
00637
00638 gboolean eripc_sysd_get_device_capabilities ( eripc_client_context_t *ccontext,
00639 eripc_device_caps_t *caps )
00640 {
00641 int old_timeout;
00642 int timeout_set = 0;
00643 int retval = 0;
00644 eripc_error_t result;
00645
00646
00647 caps->has_stylus = FALSE;
00648 caps->has_wifi = FALSE;
00649 caps->has_bluetooth = FALSE;
00650 caps->has_3g = FALSE;
00651
00652 result = eripc_get_timeout(ccontext->context, &old_timeout);
00653 if (result == ERIPC_ERROR_SUCCESS)
00654 {
00655 result = eripc_set_timeout(ccontext->context, 5*1000);
00656 timeout_set = (result == ERIPC_ERROR_SUCCESS);
00657 }
00658
00659 MAKE_VARARG_WAIT_CALL(DBUS_SERVICE_SYSTEM_CONTROL, "sysGetDeviceCapabilities",
00660 parse_reply_capabilities(reply, caps),
00661 ERIPC_TYPE_INVALID );
00662
00663 if (timeout_set)
00664 eripc_set_timeout(ccontext->context, old_timeout);
00665
00666 return retval;
00667 }
00668
00669 gboolean eripc_sysd_conn_connect ( eripc_client_context_t *ccontext,
00670 const char *medium,
00671 const char *profile )
00672 {
00673 MAKE_VARARG_CALL_3S(DBUS_SERVICE_SYSTEM_CONTROL, "connConnect",
00674 ccontext->service, medium, profile);
00675 }
00676
00677 gboolean eripc_sysd_conn_disconnect ( eripc_client_context_t *ccontext )
00678 {
00679 MAKE_VARARG_CALL_1S(DBUS_SERVICE_SYSTEM_CONTROL, "connDisconnect", ccontext->service);
00680 }
00681
00682 gboolean eripc_sysd_conn_status_request ( eripc_client_context_t *ccontext )
00683 {
00684 MAKE_VARARG_CALL_1S(DBUS_SERVICE_SYSTEM_CONTROL, "connConnectionStatusRequest", ccontext->name);
00685 }
00686