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