usb_moded  0.86.0+mer57
usb_moded.c
Go to the documentation of this file.
1 
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"
45 #include "usb_moded-dbus-private.h"
46 #include "usb_moded-devicelock.h"
47 #include "usb_moded-log.h"
48 #include "usb_moded-mac.h"
49 #include "usb_moded-modesetting.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 
102 #define CABLE_CONNECTION_DELAY_MAXIMUM 4000
103 
104 /* ========================================================================= *
105  * Prototypes
106  * ========================================================================= */
107 
108 /* ------------------------------------------------------------------------- *
109  * USBMODED
110  * ------------------------------------------------------------------------- */
111 
112 GList *usbmoded_get_modelist (void);
113 void usbmoded_load_modelist (void);
114 void usbmoded_free_modelist (void);
115 const modedata_t *usbmoded_get_modedata (const char *modename);
116 modedata_t *usbmoded_dup_modedata (const char *modename);
117 bool usbmoded_get_rescue_mode (void);
118 void usbmoded_set_rescue_mode (bool rescue_mode);
119 bool usbmoded_get_diag_mode (void);
120 void usbmoded_set_diag_mode (bool diag_mode);
121 bool usbmoded_is_mode_permitted (const char *modename, uid_t uid);
122 void usbmoded_set_cable_connection_delay(int delay_ms);
124 static gboolean usbmoded_allow_suspend_timer_cb (gpointer aptr);
125 void usbmoded_allow_suspend (void);
126 void usbmoded_delay_suspend (void);
127 bool usbmoded_in_usermode (void);
128 bool usbmoded_in_shutdown (void);
129 uid_t usbmoded_get_current_user (void);
130 bool usbmoded_can_export (void);
131 bool usbmoded_init_done_p (void);
132 void usbmoded_set_init_done (bool reached);
133 void usbmoded_probe_init_done (void);
134 void usbmoded_exit_mainloop (int exitcode);
135 void usbmoded_handle_signal (int signum);
136 static bool usbmoded_init (void);
137 static void usbmoded_cleanup (void);
138 static void usbmoded_usage (void);
139 static void usbmoded_parse_options (int argc, char *argv[]);
140 
141 /* ------------------------------------------------------------------------- *
142  * MAIN
143  * ------------------------------------------------------------------------- */
144 
145 int main(int argc, char *argv[]);
146 
147 /* ========================================================================= *
148  * Data
149  * ========================================================================= */
150 
151 static int usbmoded_exitcode = EXIT_FAILURE;
152 static GMainLoop *usbmoded_mainloop = NULL;
153 
154 static bool usbmoded_hw_fallback = false;
155 #ifdef SYSTEMD
156 static bool usbmoded_systemd_notify = false;
157 #endif
158 static bool usbmoded_auto_exit = false;
159 
160 static 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 
188 static GList *usbmoded_modelist = 0;
189 
196 GList *
198 {
199  LOG_REGISTER_CONTEXT;
200 
201  return usbmoded_modelist;
202 }
203 
208 void
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 
227 void
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 
251 const modedata_t *
252 usbmoded_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 
278 modedata_t *
279 usbmoded_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 
302 static bool usbmoded_rescue_mode = false;
303 
304 bool usbmoded_get_rescue_mode(void)
305 {
306  LOG_REGISTER_CONTEXT;
307 
308  return usbmoded_rescue_mode;
309 }
310 
311 void 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 
330 static int usbmoded_diag_mode = -1;
331 
332 bool 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 
344 void 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 
363 bool 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 
391 EXIT:
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 
415 static int usbmoded_cable_connection_delay = CABLE_CONNECTION_DELAY_DEFAULT;
416 
421 void
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 
441 int
443 {
444  LOG_REGISTER_CONTEXT;
445 
446  return usbmoded_cable_connection_delay;
447 }
448 
449 /* ------------------------------------------------------------------------- *
450  * SUSPEND_BLOCKING
451  * ------------------------------------------------------------------------- */
452 
454 static bool usbmoded_blocking_suspend = false;
455 
457 static guint usbmoded_allow_suspend_timer_id = 0;
458 
463 static 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 
532 bool
534 {
535  LOG_REGISTER_CONTEXT;
536 
537 #ifdef MEEGOLOCK
538  return dsme_state_is_user();
539 #else
540  return true;
541 #endif
542 }
543 
548 bool
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 
571 uid_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 
616 static const char usbmoded_init_done_flagfile[] = "/run/systemd/boot-status/init-done";
617 
619 static bool usbmoded_init_done_reached = false;
620 
626 {
627  LOG_REGISTER_CONTEXT;
628 
629  return usbmoded_init_done_reached;
630 }
631 
633 void 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 
664 void 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 
685 void 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 */
775 static 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 
943 EXIT:
944  return ack;
945 }
946 
949 static 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. */
966  umdbus_cleanup();
967 
968  /* Stop appsync processes that have been started by usb-moded */
969 #ifdef APP_SYNC
970  appsync_deactivate_all(false);
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();
992  configfs_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 
1013  modesetting_quit();
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 
1029 static 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 
1071 static 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 
1093 static const char usbmoded_short_options[] = "aifsTlDdhrnvm:b:QIB";
1094 
1095 /* Display usbmoded_usage information */
1096 static void usbmoded_usage(void)
1097 {
1098  LOG_REGISTER_CONTEXT;
1099 
1100  fprintf(stdout, "%s", usbmoded_usage_info);
1101 }
1102 
1103 static 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 
1191 int 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  * - - - - - - - - - - - - - - - - - - - */
1270 EXIT:
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 }
modedata_free
void modedata_free(modedata_t *self)
Definition: usb_moded-dyn-config.c:76
modedata_t::mode_name
gchar * mode_name
Definition: usb_moded-dyn-config.h:102
umdbus_init_connection
gboolean umdbus_init_connection(void)
Definition: usb_moded-dbus.c:1341
modelist_free
void modelist_free(GList *modelist)
Definition: usb_moded-dyn-config.c:279
usb_moded-dbus-private.h
usb_moded-modes.h
usb_moded-modules.h
usbmoded_get_cable_connection_delay
int usbmoded_get_cable_connection_delay(void)
Definition: usb_moded.c:442
umdbus_dump_introspect_xml
void umdbus_dump_introspect_xml(void)
Definition: usb_moded-dbus.c:1136
usbmoded_free_modelist
void usbmoded_free_modelist(void)
Definition: usb_moded.c:228
usbmoded_set_cable_connection_delay
void usbmoded_set_cable_connection_delay(int delay_ms)
Definition: usb_moded.c:422
umdbus_cleanup
void umdbus_cleanup(void)
Definition: usb_moded-dbus.c:1438
usb_moded-modesetting.h
control_init_done_changed
void control_init_done_changed(void)
Definition: usb_moded-control.c:505
modules_init
bool modules_init(void)
Definition: usb_moded-modules.c:144
control_set_cable_state
void control_set_cable_state(cable_state_t cable_state)
Definition: usb_moded-control.c:822
common_send_whitelisted_modes_signal
void common_send_whitelisted_modes_signal(void)
Definition: usb_moded-common.c:262
CABLE_CONNECTION_DELAY_DEFAULT
#define CABLE_CONNECTION_DELAY_DEFAULT
Definition: usb_moded.c:90
modelist_load
GList * modelist_load(bool diag)
Definition: usb_moded-dyn-config.c:294
common_modename_is_internal
bool common_modename_is_internal(const char *modename)
Definition: usb_moded-common.c:503
usb_moded-sigpipe.h
MODE_ASK
#define MODE_ASK
Definition: usb_moded-modes.h:74
sigpipe_init
bool sigpipe_init(void)
Definition: usb_moded-sigpipe.c:204
usb_moded-configfs.h
appsync_load_configuration
void appsync_load_configuration(void)
Definition: usb_moded-appsync.c:384
configfs_init
bool configfs_init(void)
Definition: usb_moded-configfs.c:759
control_settings_changed
void control_settings_changed(void)
Definition: usb_moded-control.c:496
usb_moded-mac.h
usb_moded-android.h
usbmoded_dup_modedata
modedata_t * usbmoded_dup_modedata(const char *modename)
Definition: usb_moded.c:279
usbmoded_load_modelist
void usbmoded_load_modelist(void)
Definition: usb_moded.c:209
dsme_state_is_shutdown
bool dsme_state_is_shutdown(void)
Definition: usb_moded-dsme.c:231
configfs_quit
void configfs_quit(void)
Definition: usb_moded-configfs.c:819
CABLE_CONNECTION_DELAY_MAXIMUM
#define CABLE_CONNECTION_DELAY_MAXIMUM
Definition: usb_moded.c:102
usb_moded-trigger.h
usb_moded-config-private.h
log_init
void log_init(void)
Definition: usb_moded-log.c:407
usbmoded_can_export
bool usbmoded_can_export(void)
Definition: usb_moded.c:591
umdbus_dump_busconfig_xml
void umdbus_dump_busconfig_xml(void)
Definition: usb_moded-dbus.c:1151
usb_moded.h
usbmoded_get_modedata
const modedata_t * usbmoded_get_modedata(const char *modename)
Definition: usb_moded.c:252
common_valid_mode
int common_valid_mode(const char *mode)
Definition: usb_moded-common.c:535
log_get_type
int log_get_type(void)
Definition: usb_moded-log.c:356
appsync_deactivate_all
void appsync_deactivate_all(bool force)
Definition: usb_moded-appsync.c:842
usb_moded-appsync.h
usb_moded-control.h
dbusappsync_cleanup
void dbusappsync_cleanup(void)
Definition: usb_moded-appsync-dbus.c:352
USB_MODED_WAKELOCK_STATE_CHANGE
#define USB_MODED_WAKELOCK_STATE_CHANGE
Definition: usb_moded.h:47
common_send_available_modes_signal
void common_send_available_modes_signal(void)
Definition: usb_moded-common.c:240
modedata_copy
modedata_t * modedata_copy(const modedata_t *that)
Definition: usb_moded-dyn-config.c:111
usbmoded_delay_suspend
void usbmoded_delay_suspend(void)
Definition: usb_moded.c:506
common_acquire_wakelock
void common_acquire_wakelock(const char *wakelock_name)
Definition: usb_moded-common.c:323
log_set_level
void log_set_level(int lev)
Definition: usb_moded-log.c:336
control_set_enabled
void control_set_enabled(bool enable)
Definition: usb_moded-control.c:521
modesetting_init
void modesetting_init(void)
Definition: usb_moded-modesetting.c:973
usbmoded_init_done_p
bool usbmoded_init_done_p(void)
Definition: usb_moded.c:625
usb_moded-udev.h
modesetting_quit
void modesetting_quit(void)
Definition: usb_moded-modesetting.c:985
user_get_current_user
uid_t user_get_current_user(void)
Definition: usb_moded-user.c:104
usbmoded_get_current_user
uid_t usbmoded_get_current_user(void)
Definition: usb_moded.c:572
usbmoded_probe_init_done
void usbmoded_probe_init_done(void)
Definition: usb_moded.c:651
USB_MODED_SUSPEND_DELAY_DEFAULT_MS
#define USB_MODED_SUSPEND_DELAY_DEFAULT_MS
Definition: usb_moded.h:53
devicelock_have_export_permission
bool devicelock_have_export_permission(void)
Definition: usb_moded-devicelock.c:129
usbmoded_in_usermode
bool usbmoded_in_usermode(void)
Definition: usb_moded.c:533
usb_moded-log.h
modedata_t
Definition: usb_moded-dyn-config.h:100
usbmoded_get_modelist
GList * usbmoded_get_modelist(void)
Definition: usb_moded.c:197
usbmoded_allow_suspend
void usbmoded_allow_suspend(void)
Definition: usb_moded.c:481
appsync_free_configuration
void appsync_free_configuration(void)
Definition: usb_moded-appsync.c:351
usbmoded_exit_mainloop
void usbmoded_exit_mainloop(int exitcode)
Definition: usb_moded.c:664
usb_moded-user.h
config_init
bool config_init(void)
Definition: usb_moded-config.c:1007
dsme_state_is_user
bool dsme_state_is_user(void)
Definition: usb_moded-dsme.c:243
log_set_name
void log_set_name(const char *name)
Definition: usb_moded-log.c:383
common_send_supported_modes_signal
void common_send_supported_modes_signal(void)
Definition: usb_moded-common.c:229
umdbus_init_service
gboolean umdbus_init_service(void)
Definition: usb_moded-dbus.c:1381
usb_moded-worker.h
usbmoded_in_shutdown
bool usbmoded_in_shutdown(void)
Definition: usb_moded.c:549
log_get_level
int log_get_level(void)
Definition: usb_moded-log.c:327
android_init
bool android_init(void)
Definition: usb_moded-android.c:171
usb_moded-dsme.h
usb_moded-systemd.h
android_quit
void android_quit(void)
Definition: usb_moded-android.c:235
usb_moded-devicelock.h
common_send_hidden_modes_signal
void common_send_hidden_modes_signal(void)
Definition: usb_moded-common.c:251
usbmoded_set_init_done
void usbmoded_set_init_done(bool reached)
Definition: usb_moded.c:633
log_set_lineinfo
void log_set_lineinfo(bool lineinfo)
Definition: usb_moded-log.c:392
common_release_wakelock
void common_release_wakelock(const char *wakelock_name)
Definition: usb_moded-common.c:342