usb_moded 0.86.0+mer64
usb_moded.c
Go to the documentation of this file.
1
37
38#include "usb_moded.h"
39
40#include "usb_moded-android.h"
41#include "usb_moded-appsync.h"
43#include "usb_moded-configfs.h"
44#include "usb_moded-control.h"
47#include "usb_moded-log.h"
48#include "usb_moded-mac.h"
50#include "usb_moded-modules.h"
51#include "usb_moded-sigpipe.h"
52#include "usb_moded-systemd.h"
53#include "usb_moded-trigger.h"
54#include "usb_moded-udev.h"
55#include "usb_moded-worker.h"
56#include "usb_moded-modes.h"
57
58#ifdef MEEGOLOCK
59# include "usb_moded-dsme.h"
60# include "usb_moded-user.h"
61#endif
62
63#include <getopt.h>
64#include <unistd.h>
65
66#ifdef SAILFISH_ACCESS_CONTROL
67# include <sailfishaccesscontrol.h>
68#endif
69
70#ifdef SYSTEMD
71# include <systemd/sd-daemon.h>
72#endif
73
74/* ========================================================================= *
75 * Constants
76 * ========================================================================= */
77
78/* Wakelogging is noisy, do not log it by default */
79#ifndef VERBOSE_WAKELOCKING
80# define VERBOSE_WAKELOCKING 0
81#endif
82
90#define CABLE_CONNECTION_DELAY_DEFAULT 0
91
101
102#define CABLE_CONNECTION_DELAY_MAXIMUM 4000
103
104/* ========================================================================= *
105 * Prototypes
106 * ========================================================================= */
107
108/* ------------------------------------------------------------------------- *
109 * USBMODED
110 * ------------------------------------------------------------------------- */
111
112GList *usbmoded_get_modelist (void);
113void usbmoded_load_modelist (void);
114void usbmoded_free_modelist (void);
115static modedata_t *usbmoded_lookup_modedata (const char *modename);
116const modedata_t *usbmoded_get_modedata (const char *modename);
117void usbmoded_refresh_modedata (const char *modename);
118modedata_t *usbmoded_dup_modedata (const char *modename);
119bool usbmoded_get_rescue_mode (void);
120void usbmoded_set_rescue_mode (bool rescue_mode);
121bool usbmoded_get_diag_mode (void);
122void usbmoded_set_diag_mode (bool diag_mode);
123bool usbmoded_is_mode_permitted (const char *modename, uid_t uid);
124void usbmoded_set_cable_connection_delay(int delay_ms);
126static gboolean usbmoded_allow_suspend_timer_cb (gpointer aptr);
127void usbmoded_allow_suspend (void);
128void usbmoded_delay_suspend (void);
129bool usbmoded_in_usermode (void);
130bool usbmoded_in_shutdown (void);
131uid_t usbmoded_get_current_user (void);
132bool usbmoded_can_export (void);
133bool usbmoded_init_done_p (void);
134void usbmoded_set_init_done (bool reached);
135void usbmoded_probe_init_done (void);
136void usbmoded_exit_mainloop (int exitcode);
137void usbmoded_handle_signal (int signum);
138static bool usbmoded_init (void);
139static void usbmoded_cleanup (void);
140static void usbmoded_usage (void);
141static void usbmoded_parse_options (int argc, char *argv[]);
142
143/* ------------------------------------------------------------------------- *
144 * MAIN
145 * ------------------------------------------------------------------------- */
146
147int main(int argc, char *argv[]);
148
149/* ========================================================================= *
150 * Data
151 * ========================================================================= */
152
153static int usbmoded_exitcode = EXIT_FAILURE;
154static GMainLoop *usbmoded_mainloop = NULL;
155
156static bool usbmoded_hw_fallback = false;
157#ifdef SYSTEMD
158static bool usbmoded_systemd_notify = false;
159#endif
160static bool usbmoded_auto_exit = false;
161
162static pthread_mutex_t usbmoded_mutex = PTHREAD_MUTEX_INITIALIZER;
163
164#define USBMODED_LOCKED_ENTER do {\
165 if( pthread_mutex_lock(&usbmoded_mutex) != 0 ) { \
166 log_crit("USBMODED LOCK FAILED");\
167 _exit(EXIT_FAILURE);\
168 }\
169}while(0)
170
171#define USBMODED_LOCKED_LEAVE do {\
172 if( pthread_mutex_unlock(&usbmoded_mutex) != 0 ) { \
173 log_crit("USBMODED UNLOCK FAILED");\
174 _exit(EXIT_FAILURE);\
175 }\
176}while(0)
177
178/* ========================================================================= *
179 * Functions
180 * ========================================================================= */
181
182/* ------------------------------------------------------------------------- *
183 * MODELIST
184 * ------------------------------------------------------------------------- */
185
190static GList *usbmoded_modelist = 0;
191
198GList *
200{
201 LOG_REGISTER_CONTEXT;
202
203 return usbmoded_modelist;
204}
205
210void
212{
213 LOG_REGISTER_CONTEXT;
214
215 USBMODED_LOCKED_ENTER;
216
217 if( !usbmoded_modelist ) {
218 log_notice("load modelist");
219 usbmoded_modelist = modelist_load(usbmoded_get_diag_mode());
220 }
221
222 USBMODED_LOCKED_LEAVE;
223}
224
229void
231{
232 LOG_REGISTER_CONTEXT;
233
234 USBMODED_LOCKED_ENTER;
235
236 if( usbmoded_modelist ) {
237 log_notice("free modelist");
238 modelist_free(usbmoded_modelist),
239 usbmoded_modelist = 0;
240 }
241
242 USBMODED_LOCKED_LEAVE;
243}
244
253static modedata_t *
254usbmoded_lookup_modedata(const char *modename)
255{
256 LOG_REGISTER_CONTEXT;
257
258 modedata_t *modedata = 0;
259
260 for( GList *iter = usbmoded_get_modelist(); iter; iter = g_list_next(iter) ) {
261 modedata_t *data = iter->data;
262 if( !g_strcmp0(data->mode_name, modename) ) {
263 modedata = data;
264 break;
265 }
266 }
267 return modedata;
268}
269
278const modedata_t *
279usbmoded_get_modedata(const char *modename)
280{
281 LOG_REGISTER_CONTEXT;
282
283 return usbmoded_lookup_modedata(modename);
284}
285
294void
295usbmoded_refresh_modedata(const char *modename)
296{
297 LOG_REGISTER_CONTEXT;
298
299 modedata_t *modedata = usbmoded_lookup_modedata(modename);
300 if( modedata )
301 modedata_cache_settings(modedata);
302}
303
315usbmoded_dup_modedata(const char *modename)
316{
317 LOG_REGISTER_CONTEXT;
318
319 USBMODED_LOCKED_ENTER;
320
321 modedata_t *modedata = modedata_copy(usbmoded_get_modedata(modename));
322
323 USBMODED_LOCKED_LEAVE;
324
325 return modedata;
326}
327
328/* ------------------------------------------------------------------------- *
329 * RESCUE_MODE
330 * ------------------------------------------------------------------------- */
331
338static bool usbmoded_rescue_mode = false;
339
340bool usbmoded_get_rescue_mode(void)
341{
342 LOG_REGISTER_CONTEXT;
343
344 return usbmoded_rescue_mode;
345}
346
347void usbmoded_set_rescue_mode(bool rescue_mode)
348{
349 LOG_REGISTER_CONTEXT;
350
351 if( usbmoded_rescue_mode != rescue_mode ) {
352 log_info("rescue_mode: %d -> %d", usbmoded_rescue_mode, rescue_mode);
353 usbmoded_rescue_mode = rescue_mode;
354 }
355}
356
357/* ------------------------------------------------------------------------- *
358 * DIAG_MODE
359 * ------------------------------------------------------------------------- */
360
366static int usbmoded_diag_mode = -1;
367
368bool usbmoded_get_diag_mode(void)
369{
370 LOG_REGISTER_CONTEXT;
371
372 if( usbmoded_diag_mode == -1 ) {
373 usbmoded_diag_mode = false;
374 log_info("diag_mode: locked to %d", usbmoded_diag_mode);
375 }
376
377 return usbmoded_diag_mode;
378}
379
380void usbmoded_set_diag_mode(bool diag_mode)
381{
382 LOG_REGISTER_CONTEXT;
383
384 if( usbmoded_diag_mode != diag_mode ) {
385 if( usbmoded_diag_mode == -1 ) {
386 usbmoded_diag_mode = diag_mode;
387 log_info("diag_mode: set to %d", usbmoded_diag_mode);
388 }
389 else {
390 log_err("dig_mode: already locked to %d", usbmoded_diag_mode);
391 }
392 }
393}
394
395/* ------------------------------------------------------------------------- *
396 * ACCESS_CHECKS
397 * ------------------------------------------------------------------------- */
398
399bool usbmoded_is_mode_permitted(const char *modename, uid_t uid)
400{
401#ifdef SAILFISH_ACCESS_CONTROL
402 LOG_REGISTER_CONTEXT;
403
404 bool allowed = true;
405 modedata_t *data = 0;
406 char *group = 0;
407
408 /* all modes are allowed for root */
409 if( uid == 0 )
410 goto EXIT;
411
412 /* non-existing special value, deny everything */
413 if( uid == UID_UNKNOWN ) {
414 allowed = false;
415 goto EXIT;
416 }
417
418 /* non-dynamic modes are allowed for all */
419 if( !(data = usbmoded_dup_modedata(modename)) )
420 goto EXIT;
421
422 /* dynamic modes are allowed based on group,
423 * which defaults to sailfish-system meaning device owner only */
424 group = config_get_group_for_mode(modename);
425 allowed = sailfish_access_control_hasgroup(uid, group);
426
427EXIT:
428
429 g_free(group);
430 modedata_free(data);
431
432 return allowed;
433
434#else
435 return true;
436
437#endif
438}
439
440/* ------------------------------------------------------------------------- *
441 * CABLE_CONNECT_DELAY
442 * ------------------------------------------------------------------------- */
443
451static int usbmoded_cable_connection_delay = CABLE_CONNECTION_DELAY_DEFAULT;
452
457void
459{
460 LOG_REGISTER_CONTEXT;
461
462 if( delay_ms > CABLE_CONNECTION_DELAY_MAXIMUM )
464 if( delay_ms < 0 )
465 delay_ms = 0;
466
467 if( usbmoded_cable_connection_delay != delay_ms ) {
468 log_info("cable_connection_delay: %d -> %d",
469 usbmoded_cable_connection_delay,
470 delay_ms);
471 usbmoded_cable_connection_delay = delay_ms;
472 }
473}
474
477int
479{
480 LOG_REGISTER_CONTEXT;
481
482 return usbmoded_cable_connection_delay;
483}
484
485/* ------------------------------------------------------------------------- *
486 * SUSPEND_BLOCKING
487 * ------------------------------------------------------------------------- */
488
490static bool usbmoded_blocking_suspend = false;
491
493static guint usbmoded_allow_suspend_timer_id = 0;
494
499static gboolean usbmoded_allow_suspend_timer_cb(gpointer aptr)
500{
501 LOG_REGISTER_CONTEXT;
502
503 (void)aptr;
504
505 usbmoded_allow_suspend_timer_id = 0;
506
508
509 return FALSE;
510}
511
518{
519 LOG_REGISTER_CONTEXT;
520
521 if( usbmoded_allow_suspend_timer_id ) {
522 g_source_remove(usbmoded_allow_suspend_timer_id),
523 usbmoded_allow_suspend_timer_id = 0;
524 }
525
526 if( usbmoded_blocking_suspend ) {
527 usbmoded_blocking_suspend = false;
529 }
530}
531
543{
544 LOG_REGISTER_CONTEXT;
545
546 /* Use of automatically terminating wakelocks also means we need
547 * to renew the wakelock when extending the suspend delay. */
549
550 usbmoded_blocking_suspend = true;
551
552 if( usbmoded_allow_suspend_timer_id )
553 g_source_remove(usbmoded_allow_suspend_timer_id);
554
555 usbmoded_allow_suspend_timer_id =
557 usbmoded_allow_suspend_timer_cb, 0);
558}
559
560/* ------------------------------------------------------------------------- *
561 * DEVICE_STATE
562 * ------------------------------------------------------------------------- */
563
568bool
570{
571 LOG_REGISTER_CONTEXT;
572
573#ifdef MEEGOLOCK
574 return dsme_state_is_user();
575#else
576 return true;
577#endif
578}
579
584bool
586{
587 LOG_REGISTER_CONTEXT;
588
589#ifdef MEEGOLOCK
590 return dsme_state_is_shutdown();
591#else
592 return false;
593#endif
594}
595
596/* ------------------------------------------------------------------------- *
597 * CURRENT_USER
598 * ------------------------------------------------------------------------- */
599
607uid_t
609{
610 LOG_REGISTER_CONTEXT;
611
612#ifdef MEEGOLOCK
613 return user_get_current_user();
614#else
615 return 0;
616#endif
617}
618
619/* ------------------------------------------------------------------------- *
620 * CAN_EXPORT
621 * ------------------------------------------------------------------------- */
622
628{
629 LOG_REGISTER_CONTEXT;
630
631 bool can_export = true;
632
633#ifdef MEEGOLOCK
634 /* Modes that potentially expose data are allowed only when
635 * device is running in user mode and device is unlocked */
636 can_export = (usbmoded_in_usermode() &&
638
639 /* Having bootup rescue mode active is an exception */
640 if( usbmoded_get_rescue_mode() )
641 can_export = true;
642#endif
643
644 return can_export;
645}
646
647/* ------------------------------------------------------------------------- *
648 * INIT_DONE
649 * ------------------------------------------------------------------------- */
650
652static const char usbmoded_init_done_flagfile[] = "/run/systemd/boot-status/init-done";
653
655static bool usbmoded_init_done_reached = false;
656
662{
663 LOG_REGISTER_CONTEXT;
664
665 return usbmoded_init_done_reached;
666}
667
669void usbmoded_set_init_done(bool reached)
670{
671 LOG_REGISTER_CONTEXT;
672
673 if( usbmoded_init_done_reached != reached ) {
674 usbmoded_init_done_reached = reached;
675 log_warning("init_done -> %s",
676 usbmoded_init_done_reached ? "reached" : "not reached");
677
678 /* Auto-disable rescue mode when bootup is finished */
679 if( usbmoded_init_done_reached )
680 usbmoded_set_rescue_mode(false);
681
683 }
684}
685
688{
689 LOG_REGISTER_CONTEXT;
690
691 usbmoded_set_init_done(access(usbmoded_init_done_flagfile, F_OK) == 0);
692}
693
694/* ------------------------------------------------------------------------- *
695 * MAINLOOP
696 * ------------------------------------------------------------------------- */
697
700void usbmoded_exit_mainloop(int exitcode)
701{
702 LOG_REGISTER_CONTEXT;
703
704 /* In case multiple exit request get done, retain the
705 * highest exit code used. */
706 if( usbmoded_exitcode < exitcode )
707 usbmoded_exitcode = exitcode;
708
709 /* If there is no mainloop to exit, terminate immediately */
710 if( !usbmoded_mainloop )
711 {
712 log_warning("exit requested outside mainloop; exit(%d) now",
713 usbmoded_exitcode);
714 exit(usbmoded_exitcode);
715 }
716
717 log_debug("stopping usb-moded mainloop");
718 g_main_loop_quit(usbmoded_mainloop);
719}
720
721void usbmoded_handle_signal(int signum)
722{
723 LOG_REGISTER_CONTEXT;
724
725 log_debug("handle signal: %s\n", strsignal(signum));
726
727 if( signum == SIGTERM )
728 {
729 /* Assume: Stopped by init process */
730 usbmoded_exit_mainloop(EXIT_SUCCESS);
731 }
732 else if( signum == SIGHUP )
733 {
734 /* Reload mode list
735 *
736 * Note that copy of mode data related to the current
737 * mode is stored separately and that copy is used
738 * when making exit from current mode.
739 */
740 log_debug("reloading dynamic mode configuration");
743
744 /* Reload appsync configuration files
745 *
746 * Updated configuration is loaded and set aside.
747 *
748 * Switch happens when applications started based
749 * on currently active configuration have been
750 * stopped.
751 */
752#ifdef APP_SYNC
753 log_debug("reloading appsync configuration");
755#endif
756 /* If default mode selection became invalid,
757 * revert setting to "ask" */
758 uid_t current_user = usbmoded_get_current_user();
759 gchar *config = config_get_mode_setting(current_user);
760 if( g_strcmp0(config, MODE_ASK) &&
761 common_valid_mode(config) ) {
762 log_warning("default mode '%s' is not valid, reset to '%s'",
763 config, MODE_ASK);
764 config_set_mode_setting(MODE_ASK, current_user);
765 }
766 else {
767 log_debug("default mode '%s' is still valid", config);
768 }
769 g_free(config);
770
771 /* If current mode became invalid, select appropriate mode.
772 *
773 * Use target mode so that we catch also situations where
774 * we are making transition to invalid state.
775 */
776 const char *current = control_get_target_mode();
777 if( common_modename_is_internal(current) ) {
778 /* Internal modes are not affected by configuration
779 * file changes - no changes required. */
780 log_debug("current mode '%s' is internal", current);
781 }
782 else if( common_valid_mode(current) ) {
783 /* Dynamic mode that is no longer valid - choose
784 * something else. */
785 log_warning("current mode '%s' is not valid, re-evaluating",
786 current);
788 }
789 else {
790 /* Dynamic mode that is still valid - do nothing.
791 *
792 * Note: While the mode details /might/ have changed,
793 * skipping immediate usb reprogramming is assumed to
794 * be less harmful than potentially cutting developer
795 * mode connection during upgrade, etc. */
796 log_debug("current mode '%s' is still valid", current);
797 }
798
799 /* Signal availability */
800 log_debug("broadcast mode availability lists");
803 }
804 else
805 {
806 usbmoded_exit_mainloop(EXIT_FAILURE);
807 }
808}
809
810/* Prepare usb-moded for running the mainloop */
811static bool usbmoded_init(void)
812{
813 LOG_REGISTER_CONTEXT;
814
815 bool ack = false;
816
817 /* Check if we are in mid-bootup */
819
820 if( !worker_init() ) {
821 log_crit("worker thread init failed");
822 goto EXIT;
823 }
824
825 if( !sigpipe_init() ) {
826 log_crit("signal handler init failed");
827 goto EXIT;
828 }
829
830 if( usbmoded_get_rescue_mode() && usbmoded_init_done_p() ) {
831 usbmoded_set_rescue_mode(false);
832 log_warning("init done passed; rescue mode ignored");
833 }
834
835 /* Connect to SystemBus */
836 if( !umdbus_init_connection() ) {
837 log_crit("dbus systembus connection failed");
838 goto EXIT;
839 }
840
841 /* Start DBus trackers that do async initialization
842 * so that initial method calls are on the way while
843 * we do initialization actions that might block. */
844
845 /* DSME listener maintains in-user-mode state and is relevant
846 * only when MEEGOLOCK configure option has been chosen. */
847#ifdef MEEGOLOCK
848 if( !dsme_start_listener() ) {
849 log_crit("dsme tracking could not be started");
850 goto EXIT;
851 }
852#endif
853
854 /* Devicelock listener maintains devicelock state and is relevant
855 * only when MEEGOLOCK configure option has been chosen. */
856#ifdef MEEGOLOCK
857 if( !devicelock_start_listener() ) {
858 log_crit("devicelock tracking could not be started");
859 goto EXIT;
860 }
861#endif
862
863 /* Set daemon config/state data to sane state */
865
866 /* check config, merge or create if outdated */
867 if( !config_init() ) {
868 log_crit("Cannot create or find a valid configuration");
869 goto EXIT;
870 }
871
872#ifdef APP_SYNC
874#endif
875
876 /* always read dyn modes even if appsync is not used */
878
879 if(config_check_trigger())
880 trigger_init();
881
882 /* Set-up mac address before kmod */
883 if(access("/etc/modprobe.d/g_ether.conf", F_OK) != 0)
884 {
885 mac_generate_random_mac();
886 }
887
888 /* During bootup the sysfs control structures might
889 * not be already in there when usb-moded starts up.
890 * Retry few times unless init done is / gets reached
891 * while waiting.
892 *
893 * Note that waiting here delays also systemd notification
894 * -> changes in wait time might require adjustemnts to
895 * startup timeout value in usb-moded.service file.
896 */
897 for( int i = 10; ; ) {
898 if( configfs_init() )
899 break;
900
901 if( android_init() )
902 break;
903
904 /* Must probe / poll since we're not yet running mainloop */
906
907 if( usbmoded_init_done_p() || --i <= 0 ) {
908 if( !modules_init() )
909 log_crit("No supported usb control mechanisms found");
910 break;
911 }
912
913 common_msleep(2000);
914 }
915
916 /* Allow making systemd control ipc */
917 if( !systemd_control_start() ) {
918 log_crit("systemd control could not be started");
919 goto EXIT;
920 }
921
922 /* If usb-moded happens to crash, it could leave appsync processes
923 * running. To make sure things are in the order expected by usb-moded
924 * force stopping of appsync processes during usb-moded startup.
925 *
926 * The exception is: When usb-moded starts as a part of bootup. Then
927 * we can be relatively sure that usb-moded has not been running yet
928 * and therefore no appsync processes have been started and we can
929 * skip the blocking ipc required to stop the appsync systemd units. */
930#ifdef APP_SYNC
931 if( usbmoded_init_done_p() ) {
932 log_warning("usb-moded started after init-done; "
933 "forcing appsync stop");
935 }
936#endif
937
938 /* Claim D-Bus service name before proceeding with things that
939 * could result in dbus signal broadcasts from usb-moded interface.
940 */
941 if( !umdbus_init_service() ) {
942 log_crit("usb-moded dbus service init failed");
943 goto EXIT;
944 }
945
946 /* Initialize udev listener. Can cause mode changes.
947 *
948 * Failing here is allowed if '--fallback' commandline option is used.
949 */
950 if( !umudev_init() && !usbmoded_hw_fallback ) {
951 log_crit("hwal init failed");
952 goto EXIT;
953 }
954
955#ifdef MEEGOLOCK
956 /* Initialize current user tracking. Can cause mode changes */
957 if ( !user_watch_init() ) {
958 log_crit("user watch init failed");
959 goto EXIT;
960 }
961#endif
962
963 /* Broadcast supported / hidden modes */
964 // TODO: should this happen before umudev_init()?
969
970 /* Act on '--fallback' commandline option */
971 if( usbmoded_hw_fallback ) {
972 log_warning("Forcing USB state to connected always. ASK mode non functional!");
973 /* Since there will be no disconnect signals coming from hw the state should not change */
974 control_set_cable_state(CABLE_STATE_PC_CONNECTED);
975 }
976
977 ack = true;
978
979EXIT:
980 return ack;
981}
982
985static void usbmoded_cleanup(void)
986{
987 LOG_REGISTER_CONTEXT;
988
989 /* Stop user change listener */
990#ifdef MEEGOLOCK
991 user_watch_stop();
992#endif
993
994 /* Stop the worker thread first to avoid confusion about shared
995 * resources we are just about to release. */
996 worker_quit();
997
998 /* Detach from SystemBus. Components that hold reference to the
999 * shared bus connection can still perform cleanup tasks, but new
1000 * references can't be obtained anymore and usb-moded myethod call
1001 * processing no longer occurs. */
1003
1004 /* Stop appsync processes that have been started by usb-moded */
1005#ifdef APP_SYNC
1007#endif
1008
1009 /* Deny making systemd control ipc */
1010 systemd_control_stop();
1011
1012 /* Stop tracking devicelock status */
1013#ifdef MEEGOLOCK
1014 devicelock_stop_listener();
1015#endif
1016
1017 /* Stop tracking device state */
1018#ifdef MEEGOLOCK
1019 dsme_stop_listener();
1020#endif
1021
1022 /* Stop udev listener */
1023 umudev_quit();
1024
1025 /* Do backend specific cleanup */
1026 modules_quit();
1027 android_quit();
1028 configfs_quit();
1029
1030 /* Undo trigger_init() */
1031 trigger_stop();
1032
1033 /* Undo usbmoded_load_modelist() */
1035
1036#ifdef APP_SYNC
1037 /* Undo appsync_load_configuration() */
1039#endif
1040
1041 /* Release dynamic memory */
1042 worker_clear_kernel_module();
1043 worker_clear_hardware_mode();
1044 control_clear_cable_state();
1045 control_clear_internal_mode();
1046 control_clear_external_mode();
1047 control_clear_target_mode();
1048
1050
1051 /* Detach from SessionBus connection used for APP_SYNC_DBUS.
1052 *
1053 * Can be handled separately from SystemBus side wind down. */
1054#ifdef APP_SYNC
1055# ifdef APP_SYNC_DBUS
1057# endif
1058#endif
1059}
1060
1061/* ========================================================================= *
1062 * MAIN ENTRY
1063 * ========================================================================= */
1064
1065static const char usbmoded_usage_info[] =
1066"Usage: usb_moded [OPTION]...\n"
1067"USB mode daemon\n"
1068"\n"
1069" -a, --android_usb_broken\n"
1070" keep gadget active on broken android kernels\n"
1071" -i, --android_usb_broken_udev_events\n"
1072" ignore incorrect disconnect events after mode setting\n"
1073" -f, --fallback\n"
1074" assume always connected\n"
1075" -s, --force-syslog\n"
1076" log to syslog\n"
1077" -T, --force-stderr\n"
1078" log to stderr\n"
1079" -l, --log-line-info\n"
1080" log to stderr and show origin of logging\n"
1081" -D, --debug\n"
1082" turn on debug printing\n"
1083" -d, --diag\n"
1084" turn on diag mode\n"
1085" -h, --help\n"
1086" display this help and exit\n"
1087" -r, --rescue\n"
1088" rescue mode\n"
1089#ifdef SYSTEMD
1090" -n, --systemd\n"
1091" notify systemd when started up\n"
1092#endif
1093" -v, --version\n"
1094" output version information and exit\n"
1095" -m, --max-cable-delay=<ms>\n"
1096" maximum delay before accepting cable connection\n"
1097" -b, --android-bootup-function=<function>\n"
1098" Setup given function during bootup. Might be required\n"
1099" on some devices to make enumeration work on the 1st\n"
1100" cable connect.\n"
1101" -I --dbus-introspect-xml\n"
1102" Dump usb-moded D-Bus introspect data to stdout.\n"
1103" -B --dbus-busconfig-xml\n"
1104" Dump usb-moded D-Bus busconfig data to stdout.\n"
1105"\n";
1106
1107static const struct option usbmoded_long_options[] =
1108{
1109 { "android_usb_broken", no_argument, 0, 'a' },
1110 { "android_usb_broken_udev_events", no_argument, 0, 'i' },
1111 { "fallback", no_argument, 0, 'd' },
1112 { "force-syslog", no_argument, 0, 's' },
1113 { "force-stderr", no_argument, 0, 'T' },
1114 { "log-line-info", no_argument, 0, 'l' },
1115 { "debug", no_argument, 0, 'D' },
1116 { "diag", no_argument, 0, 'd' },
1117 { "help", no_argument, 0, 'h' },
1118 { "rescue", no_argument, 0, 'r' },
1119 { "systemd", no_argument, 0, 'n' },
1120 { "version", no_argument, 0, 'v' },
1121 { "max-cable-delay", required_argument, 0, 'm' },
1122 { "android-bootup-function", required_argument, 0, 'b' },
1123 { "auto-exit", no_argument, 0, 'Q' },
1124 { "dbus-introspect-xml", no_argument, 0, 'I' },
1125 { "dbus-busconfig-xml", no_argument, 0, 'B' },
1126 { 0, 0, 0, 0 }
1127};
1128
1129static const char usbmoded_short_options[] = "aifsTlDdhrnvm:b:QIB";
1130
1131/* Display usbmoded_usage information */
1132static void usbmoded_usage(void)
1133{
1134 LOG_REGISTER_CONTEXT;
1135
1136 fprintf(stdout, "%s", usbmoded_usage_info);
1137}
1138
1139static void usbmoded_parse_options(int argc, char* argv[])
1140{
1141 LOG_REGISTER_CONTEXT;
1142
1143 /* Parse the command-line options */
1144 for( ;; ) {
1145 int opt = getopt_long(argc, argv,
1146 usbmoded_short_options,
1147 usbmoded_long_options,
1148 0);
1149 if( opt == -1 )
1150 break;
1151
1152 switch (opt)
1153 {
1154 case 'a':
1155 log_warning("Deprecated option: --android_usb_broken");
1156 break;
1157 case 'i':
1158 log_warning("Deprecated option: --android_usb_broken_udev_events");
1159 break;
1160 case 'f':
1161 usbmoded_hw_fallback = true;
1162 break;
1163 case 's':
1164 log_set_type(LOG_TO_SYSLOG);
1165 break;
1166
1167 case 'T':
1168 log_set_type(LOG_TO_STDERR);
1169 break;
1170
1171 case 'D':
1172 log_set_level(LOG_DEBUG);
1173 break;
1174
1175 case 'l':
1176 log_set_type(LOG_TO_STDERR);
1177 log_set_lineinfo(true);
1178 break;
1179
1180 case 'd':
1181 usbmoded_set_diag_mode(true);
1182 break;
1183
1184 case 'h':
1185 usbmoded_usage();
1186 exit(EXIT_SUCCESS);
1187
1188 case 'r':
1189 usbmoded_set_rescue_mode(true);
1190 break;
1191#ifdef SYSTEMD
1192 case 'n':
1193 usbmoded_systemd_notify = true;
1194 break;
1195#endif
1196 case 'v':
1197 printf("USB mode daemon version: %s\n", VERSION);
1198 exit(EXIT_SUCCESS);
1199
1200 case 'm':
1201 usbmoded_set_cable_connection_delay(strtol(optarg, 0, 0));
1202 break;
1203
1204 case 'b':
1205 log_warning("Deprecated option: --android-bootup-function");
1206 break;
1207
1208 case 'Q':
1209 usbmoded_auto_exit = true;
1210 break;
1211
1212 case 'I':
1214 exit(EXIT_SUCCESS);
1215
1216 case 'B':
1218 exit(EXIT_SUCCESS);
1219
1220 default:
1221 usbmoded_usage();
1222 exit(EXIT_FAILURE);
1223 }
1224 }
1225}
1226
1227int main(int argc, char* argv[])
1228{
1229 LOG_REGISTER_CONTEXT;
1230
1231 /* Library init calls that should be made before
1232 * using library functionality.
1233 */
1234#if !GLIB_CHECK_VERSION(2, 36, 0)
1235 g_type_init();
1236#endif
1237#if !GLIB_CHECK_VERSION(2, 31, 0)
1238 g_thread_init(NULL);
1239#endif
1240 dbus_threads_init_default();
1241
1242 /* - - - - - - - - - - - - - - - - - - - *
1243 * OPTIONS
1244 * - - - - - - - - - - - - - - - - - - - */
1245
1246 /* Set logging defaults */
1247 log_init();
1248 log_set_name(basename(*argv));
1249
1250 /* Parse command line options */
1251 usbmoded_parse_options(argc, argv);
1252
1253 fprintf(stderr, "usb_moded %s starting\n", VERSION);
1254 fflush(stderr);
1255
1256 /* Silence common_system() calls */
1257 if( log_get_type() != LOG_TO_STDERR && log_get_level() != LOG_DEBUG )
1258 {
1259 if( !freopen("/dev/null", "a", stdout) ) {
1260 log_err("can't redirect stdout: %m");
1261 }
1262 if( !freopen("/dev/null", "a", stderr) ) {
1263 log_err("can't redirect stderr: %m");
1264 }
1265 }
1266
1267 /* - - - - - - - - - - - - - - - - - - - *
1268 * INITIALIZE
1269 * - - - - - - - - - - - - - - - - - - - */
1270
1271 if( !usbmoded_init() )
1272 goto EXIT;
1273
1274 /* - - - - - - - - - - - - - - - - - - - *
1275 * EXECUTE
1276 * - - - - - - - - - - - - - - - - - - - */
1277
1278 /* Tell systemd that we have started up */
1279#ifdef SYSTEMD
1280 if( usbmoded_systemd_notify ) {
1281 log_debug("notifying systemd");
1282 sd_notify(0, "READY=1");
1283 }
1284#endif
1285
1286 /* init succesful, run main loop */
1287 usbmoded_exitcode = EXIT_SUCCESS;
1288
1289 control_set_enabled(true);
1290
1291 if( usbmoded_auto_exit )
1292 goto EXIT;
1293
1294 usbmoded_mainloop = g_main_loop_new(NULL, FALSE);
1295
1296 log_debug("enter usb-moded mainloop");
1297 g_main_loop_run(usbmoded_mainloop);
1298 log_debug("leave usb-moded mainloop");
1299
1300 g_main_loop_unref(usbmoded_mainloop),
1301 usbmoded_mainloop = 0;
1302
1303 /* - - - - - - - - - - - - - - - - - - - *
1304 * CLEANUP
1305 * - - - - - - - - - - - - - - - - - - - */
1306EXIT:
1307 usbmoded_cleanup();
1308
1309 /* Memory leak debugging - instruct libdbus to flush resources. */
1310#if 0
1311 dbus_shutdown();
1312#endif
1313
1314 /* - - - - - - - - - - - - - - - - - - - *
1315 * EXIT
1316 * - - - - - - - - - - - - - - - - - - - */
1317
1318 /* Must be done just before exit to make sure no more wakelocks
1319 * are taken and left behind on exit path */
1321
1322 log_debug("usb-moded return from main, with exit code %d",
1323 usbmoded_exitcode);
1324 return usbmoded_exitcode;
1325}
bool android_init(void)
void android_quit(void)
void dbusappsync_cleanup(void)
void appsync_free_configuration(void)
void appsync_deactivate_all(bool force)
void appsync_load_configuration(void)
void common_release_wakelock(const char *wakelock_name)
int common_valid_mode(const char *mode)
void common_send_available_modes_signal(void)
void common_send_whitelisted_modes_signal(void)
void common_send_hidden_modes_signal(void)
bool common_modename_is_internal(const char *modename)
void common_acquire_wakelock(const char *wakelock_name)
void common_send_supported_modes_signal(void)
bool config_init(void)
void configfs_quit(void)
bool configfs_init(void)
void control_settings_changed(void)
void control_set_cable_state(cable_state_t cable_state)
void control_init_done_changed(void)
void control_set_enabled(bool enable)
void umdbus_dump_introspect_xml(void)
void umdbus_cleanup(void)
gboolean umdbus_init_service(void)
void umdbus_dump_busconfig_xml(void)
gboolean umdbus_init_connection(void)
bool devicelock_have_export_permission(void)
bool dsme_state_is_user(void)
bool dsme_state_is_shutdown(void)
void modelist_free(GList *modelist)
void modedata_free(modedata_t *self)
modedata_t * modedata_copy(const modedata_t *that)
GList * modelist_load(bool diag)
int log_get_type(void)
void log_init(void)
void log_set_level(int lev)
void log_set_name(const char *name)
int log_get_level(void)
void log_set_lineinfo(bool lineinfo)
#define MODE_ASK
void modesetting_init(void)
void modesetting_quit(void)
bool modules_init(void)
bool sigpipe_init(void)
uid_t user_get_current_user(void)
void usbmoded_set_cable_connection_delay(int delay_ms)
Definition usb_moded.c:458
void usbmoded_exit_mainloop(int exitcode)
Definition usb_moded.c:700
void usbmoded_refresh_modedata(const char *modename)
Definition usb_moded.c:295
bool usbmoded_in_usermode(void)
Definition usb_moded.c:569
#define CABLE_CONNECTION_DELAY_DEFAULT
Definition usb_moded.c:90
#define CABLE_CONNECTION_DELAY_MAXIMUM
Definition usb_moded.c:102
void usbmoded_set_init_done(bool reached)
Definition usb_moded.c:669
const modedata_t * usbmoded_get_modedata(const char *modename)
Definition usb_moded.c:279
GList * usbmoded_get_modelist(void)
Definition usb_moded.c:199
bool usbmoded_init_done_p(void)
Definition usb_moded.c:661
void usbmoded_delay_suspend(void)
Definition usb_moded.c:542
int usbmoded_get_cable_connection_delay(void)
Definition usb_moded.c:478
bool usbmoded_in_shutdown(void)
Definition usb_moded.c:585
void usbmoded_load_modelist(void)
Definition usb_moded.c:211
modedata_t * usbmoded_dup_modedata(const char *modename)
Definition usb_moded.c:315
bool usbmoded_can_export(void)
Definition usb_moded.c:627
void usbmoded_allow_suspend(void)
Definition usb_moded.c:517
void usbmoded_probe_init_done(void)
Definition usb_moded.c:687
uid_t usbmoded_get_current_user(void)
Definition usb_moded.c:608
void usbmoded_free_modelist(void)
Definition usb_moded.c:230
#define USB_MODED_SUSPEND_DELAY_DEFAULT_MS
Definition usb_moded.h:53
#define USB_MODED_WAKELOCK_STATE_CHANGE
Definition usb_moded.h:47