Skip to content

Commit

Permalink
* More robust udev (especially for N900)
Browse files Browse the repository at this point in the history
* Improved and faster appsync courtesy of Simo Piiroinen

Signed-off-by: Philippe De Swert <phdeswer@lumi.maa>
  • Loading branch information
Philippe De Swert committed Apr 21, 2011
1 parent 0b9df5b commit 408170b
Show file tree
Hide file tree
Showing 9 changed files with 367 additions and 203 deletions.
5 changes: 3 additions & 2 deletions src/usb_moded-appsync-dbus-private.h
Expand Up @@ -18,6 +18,7 @@
02110-1301 USA
*/

gboolean usb_moded_app_sync_init(GList *list);
void usb_moded_appsync_cleanup(GList *list);
gboolean usb_moded_app_sync_init(void);
void usb_moded_appsync_cleanup(void);
int usb_moded_dbus_app_launch(const char *launch);
gboolean usb_moded_app_sync_init_connection(void);
250 changes: 182 additions & 68 deletions src/usb_moded-appsync-dbus.c
Expand Up @@ -37,22 +37,36 @@
#include "usb_moded-appsync-dbus.h"
#include "usb_moded-appsync-dbus-private.h"

static DBusConnection *dbus_connection_ses = NULL;
static DBusConnection *dbus_connection_ses = NULL; // connection
static gboolean dbus_connection_name = FALSE; // have name
static gboolean dbus_connection_disc = FALSE; // got disconnected

static void usb_moded_app_sync_cleanup_connection(void);

static DBusHandlerResult handle_disconnect(DBusConnection *conn, DBusMessage *msg, void *user_data);
static DBusHandlerResult msg_handler(DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data);

/**
* Handle USB_MODE_INTERFACE method calls
*/

static DBusHandlerResult msg_handler(DBusConnection *const connection, DBusMessage *const msg, gpointer const user_data)
{
DBusHandlerResult status = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
DBusMessage *reply = 0;
int type = dbus_message_get_type(msg);
const char *interface = dbus_message_get_interface(msg);
const char *member = dbus_message_get_member(msg);
const char *object = dbus_message_get_path(msg);
int type = dbus_message_get_type(msg);

if(!interface || !member || !object) goto IGNORE;

if(!interface || !member || !object) goto EXIT;
if( type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
!strcmp(interface, USB_MODE_INTERFACE) &&
!strcmp(object, USB_MODE_OBJECT) )

if( type == DBUS_MESSAGE_TYPE_METHOD_CALL && !strcmp(interface, USB_MODE_INTERFACE) && !strcmp(object, USB_MODE_OBJECT))
{
DBusMessage *reply = 0;

status = DBUS_HANDLER_RESULT_HANDLED;

if(!strcmp(member, USB_MODE_APP_STATE))
Expand All @@ -61,94 +75,175 @@ static DBusHandlerResult msg_handler(DBusConnection *const connection, DBusMessa
DBusError err = DBUS_ERROR_INIT;

if(!dbus_message_get_args(msg, &err, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID))
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
else
{

if(mark_active((GList *)user_data, use))
goto error_reply;
else
// could not parse method call args
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
}
else if( mark_active(use) < 0 )
{
if((reply = dbus_message_new_method_return(msg)))
// name could not be marked active
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
}
else if((reply = dbus_message_new_method_return(msg)))
{
// generate normal reply
dbus_message_append_args (reply, DBUS_TYPE_STRING, &use, DBUS_TYPE_INVALID);
}
else
error_reply:
reply = dbus_message_new_error(msg, DBUS_ERROR_INVALID_ARGS, member);
}
dbus_error_free(&err);
}
}
}
else
{
/*unknown methods are handled here */
reply = dbus_message_new_error(msg, DBUS_ERROR_UNKNOWN_METHOD, member);
}

if( !dbus_message_get_no_reply(msg) )
{
if( !reply )
{
// we failed to generate reply above -> generate one
reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, member);
}
if( !reply || !dbus_connection_send(connection, reply, 0) )
{
log_debug("Failed sending reply. Out Of Memory!\n");
}
}

if( reply ) dbus_message_unref(reply);
}

IGNORE:

EXIT:
return status;
}

if(reply)
/**
* Handle disconnect signals
*/
static DBusHandlerResult handle_disconnect(DBusConnection *conn, DBusMessage *msg, void *user_data)
{
if( !dbus_message_get_no_reply(msg) )
if( dbus_message_is_signal(msg, DBUS_INTERFACE_LOCAL, "Disconnected") )
{
if( !dbus_connection_send(connection, reply, 0) )
log_debug("Failed sending reply. Out Of Memory!\n");
log_warning("disconnected from session bus - expecting restart/stop soon\n");
dbus_connection_disc = TRUE;
usb_moded_app_sync_cleanup_connection();
}
dbus_message_unref(reply);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}

return status;
/**
* Detach from session bus
*/
static void usb_moded_app_sync_cleanup_connection(void)
{
if( dbus_connection_ses != 0 )
{
/* Remove message filters */
dbus_connection_remove_filter(dbus_connection_ses, msg_handler, 0);
dbus_connection_remove_filter(dbus_connection_ses, handle_disconnect, 0);

/* Release name, if we can still talk to dbus daemon */
if( !dbus_connection_disc )
{
DBusError error = DBUS_ERROR_INIT;
dbus_bus_release_name(dbus_connection_ses, USB_MODE_SERVICE, &error);
dbus_error_free(&error);
}

dbus_connection_unref(dbus_connection_ses);
dbus_connection_ses = NULL;
//dbus_connection_disc = FALSE;
}
log_debug("succesfully cleaned up appsync dbus\n");
}

/**
* Init dbus for usb_moded application synchronisation
*
* @return TRUE when everything went ok
* Attach to session bus
*/
gboolean usb_moded_app_sync_init(GList *list)
gboolean usb_moded_app_sync_init_connection(void)
{
gboolean status = FALSE;
DBusError error;
int ret;
gboolean result = FALSE;
DBusError error = DBUS_ERROR_INIT;

if( dbus_connection_ses != 0 )
{
result = TRUE;
goto EXIT;
}

dbus_error_init(&error);
if( dbus_connection_disc )
{
// we've already observed death of session
goto EXIT;
}

/* connect to session bus */
if ((dbus_connection_ses = dbus_bus_get_private(DBUS_BUS_SESSION, &error)) == NULL)
/* Connect to session bus */
if ((dbus_connection_ses = dbus_bus_get(DBUS_BUS_SESSION, &error)) == NULL)
{
log_err("Failed to open connection to session message bus; %s\n", error.message);
goto EXIT;
}

/* make sure we do not get forced to exit if dbus session dies or stops */
/* Add disconnect handler */
dbus_connection_add_filter(dbus_connection_ses, handle_disconnect, 0, 0);

/* Add method call handler */
dbus_connection_add_filter(dbus_connection_ses, msg_handler, 0, 0);

/* Make sure we do not get forced to exit if dbus session dies or stops */
dbus_connection_set_exit_on_disconnect(dbus_connection_ses, FALSE);

/* Initialise message handlers */
if (!dbus_connection_add_filter(dbus_connection_ses, msg_handler, list, NULL))
/* Connect D-Bus to the mainloop */
dbus_connection_setup_with_g_main(dbus_connection_ses, NULL);

/* everything went fine */
result = TRUE;

EXIT:
dbus_error_free(&error);
return result;
}

/**
* Init dbus for usb_moded application synchronisation
*
* @return TRUE when everything went ok
*/
gboolean usb_moded_app_sync_init(void)
{
gboolean status = FALSE;
DBusError error = DBUS_ERROR_INIT;
int ret;

if( !usb_moded_app_sync_init_connection() )
{
log_err("failed to add filter\n");
goto EXIT;
}
/* Acquire D-Bus service */
ret = dbus_bus_request_name(dbus_connection_ses, USB_MODE_SERVICE, DBUS_NAME_FLAG_REPLACE_EXISTING | DBUS_NAME_FLAG_ALLOW_REPLACEMENT , &error);
if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)

/* Acquire D-Bus service name */
ret = dbus_bus_request_name(dbus_connection_ses, USB_MODE_SERVICE, DBUS_NAME_FLAG_DO_NOT_QUEUE , &error);

switch( ret )
{
case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
// expected result
break;

case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
// functionally ok, but we do have a logic error somewhere
log_warning("already owning '%s'", USB_MODE_SERVICE);
break;

default:
// something odd
log_err("failed claiming dbus name\n");
if( dbus_error_is_set(&error) )
log_debug("DBUS ERROR: %s, %s \n", error.name, error.message);
goto EXIT;
}

/* Connect D-Bus to the mainloop */
dbus_connection_setup_with_g_main(dbus_connection_ses, NULL);
dbus_connection_name = TRUE;

/* everything went fine */
status = TRUE;
Expand All @@ -162,43 +257,62 @@ gboolean usb_moded_app_sync_init(GList *list)
* Clean up the dbus connections for the application
* synchronisation after sync is done
*/
void usb_moded_appsync_cleanup(GList *list)
void usb_moded_appsync_cleanup(void)
{
DBusError error;

dbus_error_init(&error);
/* clean up system bus connection */
/* Drop the service name - if we have it */
if (dbus_connection_ses != NULL )
{
dbus_bus_release_name(dbus_connection_ses, USB_MODE_SERVICE, &error);
dbus_connection_remove_filter(dbus_connection_ses, msg_handler, list);
dbus_connection_close(dbus_connection_ses);
dbus_connection_unref(dbus_connection_ses);
dbus_connection_ses = NULL;
log_debug("succesfully cleaned up appsync dbus\n");
if( dbus_connection_name )
{
DBusError error = DBUS_ERROR_INIT;
int ret = dbus_bus_release_name(dbus_connection_ses, USB_MODE_SERVICE, &error);

switch( ret )
{
case DBUS_RELEASE_NAME_REPLY_RELEASED:
// as expected
break;
case DBUS_RELEASE_NAME_REPLY_NON_EXISTENT:
// weird, but since nobody owns the name ...
break;
case DBUS_RELEASE_NAME_REPLY_NOT_OWNER:
log_warning("somebody else owns '%s'", USB_MODE_SERVICE);
}

dbus_connection_name = FALSE;

if( dbus_error_is_set(&error) )
{
log_debug("DBUS ERROR: %s, %s \n", error.name, error.message);
dbus_error_free(&error);
}
}
}
}

/**
* Launch applications over dbus that need to be synchronized
*/
int usb_moded_dbus_app_launch(const char *launch)
{
DBusConnection *dbus_conn = NULL;
DBusError error;
int ret = 0;
int ret = -1; // assume failure

dbus_error_init(&error);

if( (dbus_conn = dbus_bus_get(DBUS_BUS_SESSION, &error)) == 0 )
if( dbus_connection_ses == 0 )
{
log_err("Could not connect to dbus session\n");
log_err("could not start '%s': no session bus connection", launch);
}

dbus_bus_start_service_by_name(dbus_conn, launch, 0, NULL, &error);

dbus_connection_unref(dbus_conn);

return(ret);
else
{
DBusError error = DBUS_ERROR_INIT;
if( !dbus_bus_start_service_by_name(dbus_connection_ses, launch, 0, NULL, &error) )
{
log_err("could not start '%s': %s: %s", launch, error.name, error.message);
dbus_error_free(&error);
}
else
{
ret = 0; // success
}
}
return ret;
}

0 comments on commit 408170b

Please sign in to comment.