35 #include <dsme/state.h>
36 #include <dsme/protocol.h>
37 #include <dsme/processwd.h>
43 #define DSME_DBUS_SERVICE "com.nokia.dsme"
45 #define DSME_DBUS_REQUEST_PATH "/com/nokia/dsme/request"
46 #define DSME_DBUS_REQUEST_IFACE "com.nokia.dsme.request"
47 #define DSME_DBUS_GET_STATE_REQ "get_state"
49 #define DSME_DBUS_SIGNAL_PATH "/com/nokia/dsme/signal"
50 #define DSME_DBUS_SIGNAL_IFACE "com.nokia.dsme.signal"
51 #define DSME_STATE_CHANGE_SIG "state_change_ind"
53 #define DSME_STATE_CHANGE_MATCH\
55 ",interface='"DSME_DBUS_SIGNAL_IFACE"'"\
56 ",member='"DSME_STATE_CHANGE_SIG"'"
58 #define DSME_OWNER_CHANGE_MATCH\
60 ",interface='"DBUS_INTERFACE_DBUS"'"\
61 ",member='"DBUS_NAME_OWNER_CHANGED_SIG"'"\
62 ",arg0='"DSME_DBUS_SERVICE"'"
72 static const char *dsme_state_repr (dsme_state_t state);
73 static dsme_state_t dsme_state_parse (
const char *name);
74 static void dsme_state_update (dsme_state_t state);
82 static bool dsme_socket_send_message (gpointer msg);
83 static void dsme_socket_processwd_pong(
void);
84 static void dsme_socket_processwd_init(
void);
85 static void dsme_socket_processwd_quit(
void);
86 static void dsme_socket_query_state (
void);
87 static gboolean dsme_socket_recv_cb (GIOChannel *source, GIOCondition condition, gpointer data);
88 static bool dsme_socket_is_connected (
void);
89 static bool dsme_socket_connect (
void);
90 static void dsme_socket_disconnect (
void);
96 static void dsme_dbus_device_state_update (
const char *state);
97 static void dsme_dbus_device_state_query_cb(DBusPendingCall *pending,
void *aptr);
98 static void dsme_dbus_device_state_query (
void);
99 static void dsme_dbus_device_state_cancel (
void);
100 static void dsme_dbus_device_state_signal (DBusMessage *msg);
101 static bool dsme_dbus_name_owner_available (
void);
102 static void dsme_dbus_name_owner_update (
const char *owner);
103 static void dsme_dbus_name_owner_query_cb (
const char *owner);
104 static void dsme_dbus_name_owner_query (
void);
105 static void dsme_dbus_name_owner_cancel (
void);
106 static void dsme_dbus_name_owner_signal (DBusMessage *msg);
107 static DBusHandlerResult dsme_dbus_filter_cb (DBusConnection *con, DBusMessage *msg,
void *user_data);
108 static bool dsme_dbus_init (
void);
109 static void dsme_dbus_quit (
void);
115 bool dsme_start_listener(
void);
116 void dsme_stop_listener (
void);
129 #define DSME_STATE(NAME, VALUE) { #NAME, DSME_STATE_##NAME },
130 #include <dsme/state_states.h>
135 static dsme_state_t dsme_state_val = DSME_STATE_NOT_SET;
138 static bool dsme_user_state =
false;
141 static bool dsme_shutdown_state =
false;
146 dsme_state_repr(dsme_state_t state)
148 LOG_REGISTER_CONTEXT;
150 const char *repr =
"DSME_STATE_UNKNOWN";
152 for(
size_t i = 0; i < G_N_ELEMENTS(dsme_states); ++i ) {
153 if( dsme_states[i].state == state ) {
154 repr = dsme_states[i].name;
165 dsme_state_parse(
const char *name)
167 LOG_REGISTER_CONTEXT;
169 dsme_state_t state = DSME_STATE_NOT_SET;
171 for(
size_t i = 0; i < G_N_ELEMENTS(dsme_states); ++i ) {
172 if( !strcmp(dsme_states[i].name, name) ) {
173 state = dsme_states[i].state;
184 dsme_state_update(dsme_state_t state)
186 LOG_REGISTER_CONTEXT;
189 if( dsme_state_val != state ) {
190 log_debug(
"dsme_state: %s -> %s",
191 dsme_state_repr(dsme_state_val),
192 dsme_state_repr(state));
193 dsme_state_val = state;
196 bool device_state_changed =
false;
199 bool user_state = (state == DSME_STATE_USER);
201 if( dsme_user_state != user_state ) {
202 dsme_user_state = user_state;
203 log_debug(
"in user state: %s", dsme_user_state ?
"true" :
"false");
204 device_state_changed =
true;
208 bool shutdown_state = (state == DSME_STATE_SHUTDOWN ||
209 state == DSME_STATE_REBOOT);
211 if( dsme_shutdown_state != shutdown_state ) {
212 dsme_shutdown_state = shutdown_state;
213 log_debug(
"in shutdown: %s", dsme_shutdown_state ?
"true" :
"false");
216 if( !dsme_shutdown_state )
217 dsme_socket_connect();
219 device_state_changed =
true;
222 if( device_state_changed )
233 LOG_REGISTER_CONTEXT;
235 return dsme_shutdown_state;
245 LOG_REGISTER_CONTEXT;
247 return dsme_user_state;
255 static dsmesock_connection_t *dsme_socket_con = NULL;
258 static guint dsme_socket_iowatch = 0;
265 dsme_socket_send_message(gpointer msg)
267 LOG_REGISTER_CONTEXT;
271 if( !dsme_socket_con ) {
272 log_warning(
"failed to send %s to dsme; %s",
273 dsmemsg_name(msg),
"not connected");
277 if( dsmesock_send(dsme_socket_con, msg) == -1) {
278 log_err(
"failed to send %s to dsme; %m",
282 log_debug(
"%s sent to DSME", dsmemsg_name(msg));
293 dsme_socket_processwd_pong(
void)
295 LOG_REGISTER_CONTEXT;
297 DSM_MSGTYPE_PROCESSWD_PONG msg =
298 DSME_MSG_INIT(DSM_MSGTYPE_PROCESSWD_PONG);
302 dsme_socket_send_message(&msg);
308 dsme_socket_processwd_init(
void)
310 LOG_REGISTER_CONTEXT;
312 DSM_MSGTYPE_PROCESSWD_CREATE msg =
313 DSME_MSG_INIT(DSM_MSGTYPE_PROCESSWD_CREATE);
317 dsme_socket_send_message(&msg);
323 dsme_socket_processwd_quit(
void)
325 LOG_REGISTER_CONTEXT;
327 DSM_MSGTYPE_PROCESSWD_DELETE msg =
328 DSME_MSG_INIT(DSM_MSGTYPE_PROCESSWD_DELETE);
332 dsme_socket_send_message(&msg);
338 dsme_socket_query_state(
void)
340 LOG_REGISTER_CONTEXT;
342 DSM_MSGTYPE_STATE_QUERY msg =
343 DSME_MSG_INIT(DSM_MSGTYPE_STATE_QUERY);
345 dsme_socket_send_message(&msg);
357 dsme_socket_recv_cb(GIOChannel *source,
358 GIOCondition condition,
361 LOG_REGISTER_CONTEXT;
363 gboolean keep_going = TRUE;
364 dsmemsg_generic_t *msg = 0;
366 DSM_MSGTYPE_STATE_CHANGE_IND *msg2;
371 if( condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL) ) {
373 log_crit(
"DSME socket hangup/error");
378 if( !(msg = dsmesock_receive(dsme_socket_con)) )
381 if( DSMEMSG_CAST(DSM_MSGTYPE_CLOSE, msg) ) {
383 log_warning(
"DSME socket closed");
386 else if( DSMEMSG_CAST(DSM_MSGTYPE_PROCESSWD_PING, msg) ) {
387 dsme_socket_processwd_pong();
390 modesetting_verify_values();
392 else if( (msg2 = DSMEMSG_CAST(DSM_MSGTYPE_STATE_CHANGE_IND, msg)) ) {
393 dsme_state_update(msg2->state);
396 log_debug(
"Unhandled %s message received from DSME",
405 log_warning(
"DSME i/o notifier disabled;"
406 " assuming dsme was stopped");
410 dsme_socket_iowatch = 0;
413 dsme_socket_disconnect();
424 dsme_socket_is_connected(
void)
426 LOG_REGISTER_CONTEXT;
428 return dsme_socket_iowatch;
436 dsme_socket_connect(
void)
438 LOG_REGISTER_CONTEXT;
440 GIOChannel *iochan = NULL;
447 if( !dsme_dbus_name_owner_available() )
451 if( dsme_socket_iowatch )
454 log_debug(
"Opening DSME socket");
456 if( !(dsme_socket_con = dsmesock_connect()) ) {
457 log_err(
"Failed to open DSME socket");
461 log_debug(
"Adding DSME socket notifier");
463 if( !(iochan = g_io_channel_unix_new(dsme_socket_con->fd)) ) {
464 log_err(
"Failed to set up I/O channel for DSME socket");
468 dsme_socket_iowatch =
469 g_io_add_watch(iochan,
470 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
471 dsme_socket_recv_cb, NULL);
474 dsme_socket_processwd_init();
477 dsme_socket_query_state();
480 if( iochan ) g_io_channel_unref(iochan);
483 if( !dsme_socket_iowatch )
484 dsme_socket_disconnect();
486 return dsme_socket_is_connected();
492 dsme_socket_disconnect(
void)
494 LOG_REGISTER_CONTEXT;
496 if( dsme_socket_iowatch ) {
497 log_debug(
"Removing DSME socket notifier");
498 g_source_remove(dsme_socket_iowatch);
499 dsme_socket_iowatch = 0;
504 dsme_socket_processwd_quit();
507 if( dsme_socket_con ) {
508 log_debug(
"Closing DSME socket");
509 dsmesock_close(dsme_socket_con);
519 static DBusConnection *dsme_dbus_con = NULL;
526 dsme_dbus_device_state_update(
const char *state)
528 LOG_REGISTER_CONTEXT;
530 dsme_state_update(dsme_state_parse(state));
533 static DBusPendingCall *dsme_dbus_device_state_query_pc = 0;
536 dsme_dbus_device_state_query_cb(DBusPendingCall *pending,
void *aptr)
538 LOG_REGISTER_CONTEXT;
540 DBusMessage *rsp = 0;
542 DBusError err = DBUS_ERROR_INIT;
546 if( !(rsp = dbus_pending_call_steal_reply(pending)) ) {
547 log_err(
"did not get reply");
551 if( dbus_set_error_from_message(&err, rsp) )
553 log_err(
"error reply: %s: %s", err.name, err.message);
557 if( !dbus_message_get_args(rsp, &err,
558 DBUS_TYPE_STRING, &dta,
561 if( strcmp(err.name, DBUS_ERROR_NAME_HAS_NO_OWNER) )
562 log_err(
"parse error: %s: %s", err.name, err.message);
566 dsme_dbus_device_state_update(dta);
570 if( rsp ) dbus_message_unref(rsp);
572 dbus_error_free(&err);
574 dbus_pending_call_unref(dsme_dbus_device_state_query_pc),
575 dsme_dbus_device_state_query_pc = 0;
579 dsme_dbus_device_state_query(
void)
581 LOG_REGISTER_CONTEXT;
583 DBusMessage *req = NULL;
584 DBusPendingCall *pc = 0;
586 dsme_dbus_device_state_cancel();
588 if( !dsme_dbus_con ) {
589 log_err(
"not connected to system bus; skip device state query");
593 req = dbus_message_new_method_call(DSME_DBUS_SERVICE,
594 DSME_DBUS_REQUEST_PATH,
595 DSME_DBUS_REQUEST_IFACE,
596 DSME_DBUS_GET_STATE_REQ);
598 log_err(
"failed to construct %s.%s request",
599 DSME_DBUS_REQUEST_IFACE,
600 DSME_DBUS_GET_STATE_REQ);
604 if( !dbus_connection_send_with_reply(dsme_dbus_con, req, &pc, -1) )
610 if( !dbus_pending_call_set_notify(pc, dsme_dbus_device_state_query_cb, 0, 0) )
613 dsme_dbus_device_state_query_pc = pc, pc = 0;
617 if( pc ) dbus_pending_call_unref(pc);
618 if( req ) dbus_message_unref(req);
622 dsme_dbus_device_state_cancel(
void)
624 LOG_REGISTER_CONTEXT;
626 if( dsme_dbus_device_state_query_pc ) {
627 dbus_pending_call_cancel(dsme_dbus_device_state_query_pc);
628 dbus_pending_call_unref(dsme_dbus_device_state_query_pc),
629 dsme_dbus_device_state_query_pc = 0;
634 dsme_dbus_device_state_signal(DBusMessage *msg)
636 LOG_REGISTER_CONTEXT;
638 DBusError err = DBUS_ERROR_INIT;
641 if( !dbus_message_get_args(msg, &err,
642 DBUS_TYPE_STRING, &dta,
645 log_err(
"failed to parse signal: %s: %s",
646 err.name, err.message);
650 dsme_dbus_device_state_update(dta);
652 dbus_error_free(&err);
660 static gchar *dsme_dbus_name_owner_val = 0;
663 dsme_dbus_name_owner_available(
void)
665 LOG_REGISTER_CONTEXT;
667 return dsme_dbus_name_owner_val != 0;
671 dsme_dbus_name_owner_update(
const char *owner)
673 LOG_REGISTER_CONTEXT;
675 if( owner && !*owner )
678 if( g_strcmp0(dsme_dbus_name_owner_val, owner) ) {
679 log_debug(
"dsme dbus name owner: %s -> %s",
680 dsme_dbus_name_owner_val ?:
"none",
683 g_free(dsme_dbus_name_owner_val),
684 dsme_dbus_name_owner_val = owner ? g_strdup(owner) : 0;
689 if( dsme_dbus_name_owner_val ) {
690 dsme_dbus_device_state_query();
691 dsme_socket_connect();
696 static DBusPendingCall *dsme_dbus_name_owner_query_pc = 0;
699 dsme_dbus_name_owner_query_cb(
const char *owner)
701 LOG_REGISTER_CONTEXT;
703 dsme_dbus_name_owner_update(owner);
705 dbus_pending_call_unref(dsme_dbus_name_owner_query_pc),
706 dsme_dbus_name_owner_query_pc = 0;
710 dsme_dbus_name_owner_query(
void)
712 LOG_REGISTER_CONTEXT;
714 dsme_dbus_name_owner_cancel();
717 dsme_dbus_name_owner_query_cb,
718 &dsme_dbus_name_owner_query_pc);
722 dsme_dbus_name_owner_cancel(
void)
724 LOG_REGISTER_CONTEXT;
726 if( dsme_dbus_name_owner_query_pc )
728 dbus_pending_call_cancel(dsme_dbus_name_owner_query_pc);
729 dbus_pending_call_unref(dsme_dbus_name_owner_query_pc),
730 dsme_dbus_name_owner_query_pc = 0;
735 dsme_dbus_name_owner_signal(DBusMessage *msg)
737 LOG_REGISTER_CONTEXT;
739 DBusError err = DBUS_ERROR_INIT;
740 const char *name = 0;
741 const char *prev = 0;
742 const char *curr = 0;
744 if( !dbus_message_get_args(msg, &err,
745 DBUS_TYPE_STRING, &name,
746 DBUS_TYPE_STRING, &prev,
747 DBUS_TYPE_STRING, &curr,
750 log_err(
"failed to parse signal: %s: %s",
751 err.name, err.message);
753 else if( !strcmp(name, DSME_DBUS_SERVICE) )
755 dsme_dbus_name_owner_update(curr);
757 dbus_error_free(&err);
764 static DBusHandlerResult
765 dsme_dbus_filter_cb(DBusConnection *con, DBusMessage *msg,
void *user_data)
767 LOG_REGISTER_CONTEXT;
772 if( dbus_message_is_signal(msg,
773 DSME_DBUS_SIGNAL_IFACE,
774 DSME_STATE_CHANGE_SIG) )
776 dsme_dbus_device_state_signal(msg);
778 else if( dbus_message_is_signal(msg,
782 dsme_dbus_name_owner_signal(msg);
785 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
791 LOG_REGISTER_CONTEXT;
796 if( (dsme_dbus_con = umdbus_get_connection()) == 0 )
798 log_err(
"Could not connect to dbus for dsme\n");
803 if( !dbus_connection_add_filter(dsme_dbus_con,
804 dsme_dbus_filter_cb , 0, 0) )
806 log_err(
"adding system dbus filter for dsme failed");
811 dbus_bus_add_match(dsme_dbus_con, DSME_STATE_CHANGE_MATCH, 0);
812 dbus_bus_add_match(dsme_dbus_con, DSME_OWNER_CHANGE_MATCH, 0);
815 dsme_dbus_name_owner_query();
827 LOG_REGISTER_CONTEXT;
830 dsme_dbus_name_owner_cancel();
831 dsme_dbus_device_state_cancel();
837 dbus_connection_remove_filter(dsme_dbus_con,
838 dsme_dbus_filter_cb, 0);
840 if( dbus_connection_get_is_connected(dsme_dbus_con) ) {
842 dbus_bus_remove_match(dsme_dbus_con, DSME_STATE_CHANGE_MATCH, 0);
843 dbus_bus_remove_match(dsme_dbus_con, DSME_OWNER_CHANGE_MATCH, 0);
847 dbus_connection_unref(dsme_dbus_con),
852 g_free(dsme_dbus_name_owner_val),
853 dsme_dbus_name_owner_val = 0;
861 dsme_start_listener(
void)
863 LOG_REGISTER_CONTEXT;
865 return dsme_dbus_init();
869 dsme_stop_listener(
void)
871 LOG_REGISTER_CONTEXT;
874 dsme_socket_disconnect();