46#define PROP_CAPACITY "POWER_SUPPLY_CAPACITY"
48#define PROP_ONLINE "POWER_SUPPLY_ONLINE"
49#define PROP_TYPE "POWER_SUPPLY_TYPE"
50#define PROP_REAL_TYPE "POWER_SUPPLY_REAL_TYPE"
52#define PROP_STATUS "POWER_SUPPLY_STATUS"
53#define PROP_PRESENT "POWER_SUPPLY_PRESENT"
63static const char *umudev_pretty_string(
const char *str);
64static bool umudev_white_p (
int ch);
65static bool umudev_black_p (
int ch);
66static char *umudev_strip (
char *str);
67static char *umudev_extract_token(
char **ppos);
68static gchar *umudev_read_textfile(
const char *dirpath,
const char *filename);
69static gchar *umudev_get_config (
const char *key);
70static struct udev_device **umudev_get_devices (
const char *subsystem);
71static void umudev_free_devices (
struct udev_device **devices);
77static bool umudev_charger_set_online (
const char *online);
78static bool umudev_charger_set_type (
const char *type);
79static void umudev_charger_update_from (
struct udev_device *dev);
80static int umudev_charger_get_score (
struct udev_device *dev);
81static void umudev_charger_find_device (
void);
82static void umudev_charger_schedule_poll(
void);
83static void umudev_charger_cancel_poll (
void);
84static gboolean umudev_charger_poll_cb (gpointer aptr);
85static void umudev_charger_poll_now (
void);
91static gchar *umudev_extcon_parse_state(
const char *rawstate);
92static void umudev_extcon_set_state (
const char *rawstate);
93static void umudev_extcon_read_from (
const char *syspath);
94static void umudev_extcon_update_from(
struct udev_device *dev);
95static void umudev_extcon_find_device(
void);
101static gchar *umudev_android_parse_state(
const char *rawstate);
102static void umudev_android_set_state (
const char *rawstate);
103static void umudev_android_read_from (
const char *syspath);
104static void umudev_android_update_from(
struct udev_device *dev);
105static void umudev_android_find_device(
void);
111static gboolean umudev_cable_state_timer_cb (gpointer aptr);
112static void umudev_cable_state_stop_timer (
void);
113static void umudev_cable_state_start_timer(gint delay);
114static bool umudev_cable_state_connected (
void);
115static cable_state_t umudev_cable_state_get (
void);
116static void umudev_cable_state_set (cable_state_t state);
117static void umudev_cable_state_changed (
void);
118static void umudev_cable_state_from_udev (cable_state_t curr);
124static void umudev_io_error_cb (gpointer data);
125static gboolean umudev_io_input_cb (GIOChannel *iochannel, GIOCondition cond, gpointer data);
126static void umudev_evaluate_state(
void);
127gboolean umudev_init (
void);
128void umudev_quit (
void);
135static struct udev *umudev_object = 0;
136static struct udev_monitor *umudev_monitor = 0;
139static gchar *umudev_charger_syspath = 0;
140static gchar *umudev_charger_subsystem = 0;
141static gchar *umudev_charger_online = 0;
142static gchar *umudev_charger_type = 0;
151static guint umudev_charger_poll_id = 0;
152static gint umudev_charger_poll_delay = 1000;
155static gchar *umudev_extcon_syspath = 0;
156static gchar *umudev_extcon_subsystem = 0;
157static gchar *umudev_extcon_state = NULL;
160static gchar *umudev_android_syspath = 0;
161static gchar *umudev_android_subsystem = 0;
162static gchar *umudev_android_state = NULL;
164static guint umudev_watch_id = 0;
165static bool umudev_in_cleanup =
false;
168static cable_state_t umudev_cable_state_current = CABLE_STATE_UNKNOWN;
171static cable_state_t umudev_cable_state_active = CABLE_STATE_UNKNOWN;
174static cable_state_t umudev_cable_state_previous = CABLE_STATE_UNKNOWN;
177static guint umudev_cable_state_timer_id = 0;
178static gint umudev_cable_state_timer_delay = -1;
184static const char *umudev_pretty_string(
const char *str)
186 return !str ?
"<null>" : !*str ?
"<empty>" : str;
189static bool umudev_white_p(
int ch)
191 return (ch > 0) && (ch <= 32);
194static bool umudev_black_p(
int ch)
196 return (ch < 0) || (ch > 32);
199static char *umudev_strip(
char *str)
204 while( umudev_white_p(*src) )
207 while( umudev_black_p(*src) )
209 while( umudev_white_p(*src) )
220static char *umudev_extract_token(
char **ppos)
223 while( umudev_white_p(*beg) )
226 while( umudev_black_p(*end) )
234static gchar *umudev_read_textfile(
const char *dirpath,
const char *filename)
237 if( dirpath && filename ) {
238 gchar *path = g_strdup_printf(
"%s/%s", dirpath, filename);
239 if( !g_file_get_contents(path, &data, NULL, NULL) )
240 log_warning(
"%s: could not read file", path);
246static gchar *umudev_get_config(
const char *key)
248 gchar *val = config_get_conf_string(UDEV_ENTRY, key);
250 if( !*val || !strcmp(val,
"none") || !strcmp(val,
"null") )
251 g_free(val), val = NULL;
256static struct udev_device **umudev_get_devices(
const char *subsystem)
258 struct udev_device **devices = NULL;
260 struct udev_enumerate *list;
261 if( (list = udev_enumerate_new(umudev_object)) ) {
262 udev_enumerate_add_match_subsystem(list, subsystem);
263 udev_enumerate_scan_devices(list);
264 struct udev_list_entry *iter;
266 udev_list_entry_foreach(iter, udev_enumerate_get_list_entry(list)) {
269 devices = g_malloc_n(count + 1,
sizeof *devices);
271 udev_list_entry_foreach(iter, udev_enumerate_get_list_entry(list)) {
272 const char *syspath = udev_list_entry_get_name(iter);
273 struct udev_device *dev =
274 udev_device_new_from_syspath(umudev_object, syspath);
276 devices[count++] = dev;
278 devices[count] = NULL;
283static void umudev_free_devices(
struct udev_device **devices)
286 for(
size_t i = 0; devices[i]; ++i )
287 udev_device_unref(devices[i]);
296static bool umudev_charger_set_online(
const char *online)
298 bool changed =
false;
299 if( g_strcmp0(umudev_charger_online, online) ) {
300 log_debug(
"umudev_charger_online: %s -> %s",
301 umudev_pretty_string(umudev_charger_online),
302 umudev_pretty_string(online));
303 g_free(umudev_charger_online),
304 umudev_charger_online = g_strdup(online);
310static bool umudev_charger_set_type(
const char *type)
312 bool changed =
false;
313 if( g_strcmp0(umudev_charger_type, type) ) {
314 log_debug(
"umudev_charger_type: %s -> %s",
315 umudev_pretty_string(umudev_charger_type),
316 umudev_pretty_string(type));
317 g_free(umudev_charger_type),
318 umudev_charger_type = g_strdup(type);
324static void umudev_charger_update_from(
struct udev_device *dev)
326 LOG_REGISTER_CONTEXT;
329 const char *power_supply_online = 0;
330 const char *power_supply_type = 0;
336 power_supply_online = udev_device_get_property_value(dev, PROP_PRESENT);
337 if( !power_supply_online )
338 power_supply_online = udev_device_get_property_value(dev, PROP_ONLINE);
344 power_supply_type = udev_device_get_property_value(dev, PROP_REAL_TYPE);
345 if( !power_supply_type )
346 power_supply_type = udev_device_get_property_value(dev, PROP_TYPE);
348 umudev_charger_set_online(power_supply_online);
349 umudev_charger_set_type(power_supply_type);
351 umudev_evaluate_state();
354static int umudev_charger_get_score(
struct udev_device *dev)
356 LOG_REGISTER_CONTEXT;
359 const char *sysname = NULL;
364 if( !(sysname = udev_device_get_sysname(dev)) )
368 if( udev_device_get_property_value(dev, PROP_CAPACITY) )
372 const char *online = udev_device_get_property_value(dev, PROP_ONLINE);
373 const char *present = udev_device_get_property_value(dev, PROP_PRESENT);
374 if( !online && !present )
380 if( strstr(sysname,
"usb") )
384 if( strstr(sysname,
"charger") )
395 if( udev_device_get_property_value(dev, PROP_STATUS) )
400 if( udev_device_get_property_value(dev, PROP_TYPE) ||
401 udev_device_get_property_value(dev, PROP_REAL_TYPE) )
405 log_debug(
"score: %2d; for: %s", score, umudev_pretty_string(sysname));
410static void umudev_charger_find_device(
void)
412 LOG_REGISTER_CONTEXT;
414 gchar *tracking = NULL;
415 gchar *syspath = NULL;
416 gchar *subsystem = NULL;
417 struct udev_device *dev = NULL;
419 if( !(tracking = umudev_get_config(UDEV_CHARGER_TRACKING_KEY)) )
420 tracking = g_strdup(UDEV_CHARGER_TRACKING_FALLBACK);
422 log_debug(
"tracking=%s", umudev_pretty_string(tracking));
424 if( !g_strcmp0(tracking,
"0") )
427 if( !(syspath = umudev_get_config(UDEV_CHARGER_PATH_KEY)) )
428 syspath = g_strdup(UDEV_CHARGER_PATH_FALLBACK);
431 if( !(dev = udev_device_new_from_syspath(umudev_object, syspath)) )
432 log_warning(
"Unable to find $charger device '%s'", syspath);
434 subsystem = g_strdup(udev_device_get_subsystem(dev));
438 if( !(subsystem = umudev_get_config(UDEV_CHARGER_SUBSYSTEM_KEY)) )
439 subsystem = g_strdup(UDEV_CHARGER_SUBSYSTEM_FALLBACK);
443 log_warning(
"Unable to determine $charger subsystem.");
447 if( udev_monitor_filter_add_match_subsystem_devtype(umudev_monitor,
450 log_err(
"Unable to add $charger match");
454 umudev_charger_subsystem = g_strdup(subsystem);
458 log_debug(
"Trying to guess $charger device.\n");
459 struct udev_device **devices = umudev_get_devices(subsystem);
463 for(
int i = 0; devices[i]; ++i ) {
464 int score = umudev_charger_get_score(devices[i]);
465 if( best_score < score ) {
470 if( best_index != -1 )
471 dev = udev_device_ref(devices[best_index]);
472 umudev_free_devices(devices);
477 umudev_charger_syspath = g_strdup(udev_device_get_syspath(dev));
480 log_debug(
"charger device: subsystem=%s syspath=%s",
481 umudev_pretty_string(umudev_charger_subsystem),
482 umudev_pretty_string(umudev_charger_syspath));
485 udev_device_unref(dev);
491static void umudev_charger_schedule_poll(
void)
493 LOG_REGISTER_CONTEXT;
495 if( !umudev_charger_poll_id ) {
496 umudev_charger_poll_id = g_timeout_add(umudev_charger_poll_delay,
497 umudev_charger_poll_cb,
502static void umudev_charger_cancel_poll(
void)
504 LOG_REGISTER_CONTEXT;
506 if( umudev_charger_poll_id ) {
507 g_source_remove(umudev_charger_poll_id),
508 umudev_charger_poll_id = 0;
512static gboolean umudev_charger_poll_cb(gpointer aptr)
514 LOG_REGISTER_CONTEXT;
516 umudev_charger_poll_id = 0;
517 umudev_charger_poll_now();
518 return G_SOURCE_REMOVE;
521static void umudev_charger_poll_now(
void)
523 LOG_REGISTER_CONTEXT;
525 umudev_charger_cancel_poll();
527 struct udev_device *dev = NULL;
529 if( umudev_charger_syspath )
530 dev = udev_device_new_from_syspath(umudev_object,
531 umudev_charger_syspath);
534 umudev_charger_update_from(dev);
535 udev_device_unref(dev);
538 umudev_evaluate_state();
546static gchar *umudev_extcon_parse_state(
const char *rawstate)
550 gchar *tmp = g_strdup(rawstate);
552 while( pos && *pos ) {
553 char *tok = umudev_extract_token(&pos);
554 if( !strncmp(tok,
"USB=", 4) ) {
555 state = g_strdup(tok);
563static void umudev_extcon_set_state(
const char *rawstate)
565 LOG_REGISTER_CONTEXT;
567 gchar *state = umudev_extcon_parse_state(rawstate);
568 if( g_strcmp0(umudev_extcon_state, state) ) {
569 log_debug(
"umudev_extcon_state: %s -> %s",
570 umudev_pretty_string(umudev_extcon_state),
571 umudev_pretty_string(state));
572 g_free(umudev_extcon_state),
573 umudev_extcon_state = state,
575 umudev_charger_schedule_poll();
580static void umudev_extcon_read_from(
const char *syspath)
585 LOG_REGISTER_CONTEXT;
586 gchar *rawstate = umudev_read_textfile(syspath,
"state");
588 umudev_extcon_set_state(rawstate);
592static void umudev_extcon_update_from(
struct udev_device *dev)
594 const char *state = udev_device_get_property_value(dev,
"STATE");
596 umudev_extcon_set_state(state);
599static void umudev_extcon_find_device(
void)
601 LOG_REGISTER_CONTEXT;
603 gchar *tracking = NULL;
604 gchar *syspath = NULL;
605 gchar *subsystem = NULL;
606 struct udev_device *dev = NULL;
608 if( !(tracking = umudev_get_config(UDEV_EXTCON_TRACKING_KEY)) )
609 tracking = g_strdup(UDEV_EXTCON_TRACKING_FALLBACK);
611 log_debug(
"tracking=%s", umudev_pretty_string(tracking));
613 if( !g_strcmp0(tracking,
"0") )
616 if( !(syspath = umudev_get_config(UDEV_EXTCON_PATH_KEY)) )
617 syspath = g_strdup(UDEV_EXTCON_PATH_FALLBACK);
620 if( !(dev = udev_device_new_from_syspath(umudev_object, syspath)) )
621 log_warning(
"Unable to find $extcon device '%s'", syspath);
623 subsystem = g_strdup(udev_device_get_subsystem(dev));
627 if( !(subsystem = umudev_get_config(UDEV_EXTCON_SUBSYSTEM_KEY)) )
628 subsystem = g_strdup(UDEV_EXTCON_SUBSYSTEM_FALLBACK);
632 log_warning(
"Unable to determine $extcon subsystem.");
636 if( udev_monitor_filter_add_match_subsystem_devtype(umudev_monitor,
639 log_err(
"Unable to add $extcon match");
643 umudev_extcon_subsystem = g_strdup(subsystem);
647 umudev_extcon_syspath = g_strdup(udev_device_get_syspath(dev));
648 umudev_extcon_read_from(umudev_extcon_syspath);
652 struct udev_device **devices = umudev_get_devices(subsystem);
654 for(
size_t i = 0; devices[i]; ++i )
655 umudev_extcon_read_from(udev_device_get_syspath(devices[i]));
656 umudev_free_devices(devices);
661 log_debug(
"extcon device: subsystem=%s syspath=%s",
662 umudev_pretty_string(umudev_extcon_subsystem),
663 umudev_pretty_string(umudev_extcon_syspath));
666 udev_device_unref(dev);
676static gchar *umudev_android_parse_state(
const char *rawstate)
679 return umudev_strip(g_strdup(rawstate));
682static void umudev_android_set_state(
const char *rawstate)
684 LOG_REGISTER_CONTEXT;
686 gchar *state = umudev_android_parse_state(rawstate);
687 if( g_strcmp0(umudev_android_state, state) ) {
688 log_debug(
"umudev_android_state: %s -> %s",
689 umudev_pretty_string(umudev_android_state),
690 umudev_pretty_string(state));
691 g_free(umudev_android_state),
692 umudev_android_state = state,
694 umudev_charger_schedule_poll();
699static void umudev_android_read_from(
const char *syspath)
704 LOG_REGISTER_CONTEXT;
706 gchar *rawstate = umudev_read_textfile(syspath,
"state");
708 umudev_android_set_state(rawstate);
712static void umudev_android_update_from(
struct udev_device *dev)
714 const char *state = udev_device_get_property_value(dev,
"USB_STATE");
716 umudev_android_set_state(state);
719static void umudev_android_find_device(
void)
721 LOG_REGISTER_CONTEXT;
723 gchar *tracking = NULL;
724 gchar *syspath = NULL;
725 gchar *subsystem = NULL;
726 struct udev_device *dev = NULL;
728 if( !(tracking = umudev_get_config(UDEV_ANDROID_TRACKING_KEY)) )
729 tracking = g_strdup(UDEV_ANDROID_TRACKING_FALLBACK);
731 log_debug(
"tracking=%s", umudev_pretty_string(tracking));
733 if( !g_strcmp0(tracking,
"0") )
736 if( !(syspath = umudev_get_config(UDEV_ANDROID_PATH_KEY)) )
737 syspath = g_strdup(UDEV_ANDROID_PATH_FALLBACK);
740 if( !(dev = udev_device_new_from_syspath(umudev_object, syspath)) )
741 log_warning(
"Unable to find $android device '%s'", syspath);
743 subsystem = g_strdup(udev_device_get_subsystem(dev));
747 if( !(subsystem = umudev_get_config(UDEV_ANDROID_SUBSYSTEM_KEY)) )
748 subsystem = g_strdup(UDEV_ANDROID_SUBSYSTEM_FALLBACK);
752 log_warning(
"Unable to determine $android subsystem.");
756 if( udev_monitor_filter_add_match_subsystem_devtype(umudev_monitor,
759 log_err(
"Unable to add $android match");
763 umudev_android_subsystem = g_strdup(subsystem);
767 umudev_android_syspath = g_strdup(udev_device_get_syspath(dev));
768 umudev_android_read_from(umudev_android_syspath);
772 struct udev_device **devices = umudev_get_devices(subsystem);
774 for(
size_t i = 0; devices[i]; ++i )
775 umudev_android_read_from(udev_device_get_syspath(devices[i]));
776 umudev_free_devices(devices);
781 log_debug(
"android device: subsystem=%s syspath=%s",
782 umudev_pretty_string(umudev_android_subsystem),
783 umudev_pretty_string(umudev_android_syspath));
786 udev_device_unref(dev);
796static gboolean umudev_cable_state_timer_cb(gpointer aptr)
798 LOG_REGISTER_CONTEXT;
801 umudev_cable_state_timer_id = 0;
802 umudev_cable_state_timer_delay = -1;
804 log_debug(
"trigger delayed transfer to: %s",
805 cable_state_repr(umudev_cable_state_current));
806 umudev_cable_state_set(umudev_cable_state_current);
810static void umudev_cable_state_stop_timer(
void)
812 LOG_REGISTER_CONTEXT;
814 if( umudev_cable_state_timer_id ) {
815 log_debug(
"cancel delayed transfer to: %s",
816 cable_state_repr(umudev_cable_state_current));
817 g_source_remove(umudev_cable_state_timer_id),
818 umudev_cable_state_timer_id = 0;
819 umudev_cable_state_timer_delay = -1;
823static void umudev_cable_state_start_timer(gint delay)
825 LOG_REGISTER_CONTEXT;
827 if( umudev_cable_state_timer_delay != delay ) {
828 umudev_cable_state_stop_timer();
831 if( !umudev_cable_state_timer_id ) {
832 log_debug(
"schedule delayed transfer to: %s",
833 cable_state_repr(umudev_cable_state_current));
834 umudev_cable_state_timer_id =
836 umudev_cable_state_timer_cb, 0);
837 umudev_cable_state_timer_delay = delay;
842umudev_cable_state_connected(
void)
844 LOG_REGISTER_CONTEXT;
846 bool connected =
false;
847 switch( umudev_cable_state_get() ) {
850 case CABLE_STATE_CHARGER_CONNECTED:
851 case CABLE_STATE_PC_CONNECTED:
858static cable_state_t umudev_cable_state_get(
void)
860 LOG_REGISTER_CONTEXT;
862 return umudev_cable_state_active;
865static void umudev_cable_state_set(cable_state_t state)
867 LOG_REGISTER_CONTEXT;
869 umudev_cable_state_stop_timer();
871 if( umudev_cable_state_active == state )
874 umudev_cable_state_previous = umudev_cable_state_active;
875 umudev_cable_state_active = state;
877 log_debug(
"cable_state: %s -> %s",
878 cable_state_repr(umudev_cable_state_previous),
879 cable_state_repr(umudev_cable_state_active));
881 umudev_cable_state_changed();
887static void umudev_cable_state_changed(
void)
889 LOG_REGISTER_CONTEXT;
898 switch( umudev_cable_state_previous ) {
900 case CABLE_STATE_DISCONNECTED:
903 case CABLE_STATE_CHARGER_CONNECTED:
906 case CABLE_STATE_PC_CONNECTED:
915 switch( umudev_cable_state_active ) {
917 case CABLE_STATE_DISCONNECTED:
920 case CABLE_STATE_CHARGER_CONNECTED:
923 case CABLE_STATE_PC_CONNECTED:
932static void umudev_cable_state_from_udev(cable_state_t curr)
934 LOG_REGISTER_CONTEXT;
936 cable_state_t prev = umudev_cable_state_current;
937 umudev_cable_state_current = curr;
942 log_debug(
"reported cable state: %s -> %s",
943 cable_state_repr(prev),
944 cable_state_repr(curr));
953 if( curr == CABLE_STATE_DISCONNECTED ) {
957 umudev_cable_state_set(curr);
966 if( curr == CABLE_STATE_PC_CONNECTED && prev != CABLE_STATE_UNKNOWN ) {
971 umudev_cable_state_start_timer(delay);
982static void umudev_io_error_cb(gpointer data)
984 LOG_REGISTER_CONTEXT;
989 if( !umudev_in_cleanup ) {
990 log_debug(
"USB connection watch destroyed, restarting it\n!");
997static gboolean umudev_io_input_cb(GIOChannel *iochannel, GIOCondition cond, gpointer data)
999 LOG_REGISTER_CONTEXT;
1004 gboolean continue_watching = TRUE;
1009 if( cond & G_IO_IN )
1012 struct udev_device *dev = udev_monitor_receive_device(umudev_monitor);
1015 continue_watching = FALSE;
1018 const char *syspath = udev_device_get_syspath(dev);
1019 const char *subsystem = udev_device_get_subsystem(dev);
1020 const char *action = udev_device_get_action(dev);
1021 log_debug(
"action=%s subsystem=%s syspath=%s",
1022 umudev_pretty_string(action),
1023 umudev_pretty_string(subsystem),
1024 umudev_pretty_string(syspath));
1026 if( g_strcmp0(action,
"change") ) {
1029 else if( umudev_android_subsystem && !g_strcmp0(umudev_android_subsystem, subsystem) ) {
1030 if( !umudev_android_syspath || !g_strcmp0(umudev_android_syspath, syspath) )
1031 umudev_android_update_from(dev);
1033 else if( umudev_extcon_subsystem && !g_strcmp0(umudev_extcon_subsystem, subsystem) ) {
1034 if( !umudev_extcon_syspath || !g_strcmp0(umudev_extcon_syspath, syspath) )
1035 umudev_extcon_update_from(dev);
1037 else if( umudev_charger_subsystem && !g_strcmp0(umudev_charger_subsystem, subsystem) ) {
1038 if( !umudev_charger_syspath || !g_strcmp0(umudev_charger_syspath, syspath) ) {
1039 umudev_charger_cancel_poll();
1040 umudev_charger_update_from(dev);
1043 udev_device_unref(dev);
1047 if( cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL) ) {
1049 continue_watching = FALSE;
1052 if( !continue_watching && umudev_watch_id ) {
1053 umudev_watch_id = 0;
1054 log_crit(
"udev io watch disabled");
1059 return continue_watching;
1062static void umudev_evaluate_state(
void)
1065 const char *charger_online = umudev_charger_online;
1066 const char *charger_type = umudev_charger_type;
1087 const char *override_online = NULL;
1088 const char *override_type = NULL;
1090 if( umudev_extcon_state ) {
1091 if( !strcmp(umudev_extcon_state,
"USB=1") ) {
1092 override_online =
"1";
1093 override_type =
"USB";
1095 else if( !strcmp(umudev_extcon_state,
"USB=0") ) {
1096 override_type =
"USB_DCP";
1100 if( umudev_android_state ) {
1101 if( !strcmp(umudev_android_state,
"DISCONNECTED") ) {
1102 override_type =
"USB_DCP";
1105 override_type =
"USB";
1106 override_online =
"1";
1110 if( override_type && g_strcmp0(override_type, charger_type) ) {
1111 log_debug(
"override charger_type: %s -> %s",
1112 umudev_pretty_string(charger_type),
1113 umudev_pretty_string(override_type));
1114 charger_type = override_type;
1117 if( override_online && g_strcmp0(override_online, charger_online) ) {
1118 log_debug(
"override charger_online: %s -> %s",
1119 umudev_pretty_string(charger_online),
1120 umudev_pretty_string(override_online));
1121 charger_online = override_online;
1126 log_debug(
"evaluate online=%s type=%s extcon=%s android=%s",
1127 umudev_pretty_string(charger_online),
1128 umudev_pretty_string(charger_type),
1129 umudev_pretty_string(umudev_extcon_state),
1130 umudev_pretty_string(umudev_android_state));
1132 bool connected = !g_strcmp0(charger_online,
"1");
1140 bool warnings =
log_p(LOG_DEBUG);
1154 if( warnings && !charger_online )
1155 log_err(
"No usable power supply indicator\n");
1156 umudev_cable_state_from_udev(CABLE_STATE_DISCONNECTED);
1164 if( !charger_type ) {
1166 log_warning(
"Fallback since cable detection might not be accurate. "
1167 "Will connect on any voltage on charger.\n");
1168 umudev_cable_state_from_udev(CABLE_STATE_PC_CONNECTED);
1170 else if( !strcmp(charger_type,
"USB") ||
1171 !strcmp(charger_type,
"USB_CDP") ) {
1172 umudev_cable_state_from_udev(CABLE_STATE_PC_CONNECTED);
1174 else if( !strcmp(charger_type,
"USB_DCP") ||
1175 !strcmp(charger_type,
"USB_HVDCP") ||
1176 !strcmp(charger_type,
"USB_HVDCP_3") ) {
1177 umudev_cable_state_from_udev(CABLE_STATE_CHARGER_CONNECTED);
1179 else if( !strcmp(charger_type,
"USB_PD") ) {
1196 if( umudev_cable_state_current != CABLE_STATE_CHARGER_CONNECTED )
1197 umudev_cable_state_from_udev(CABLE_STATE_PC_CONNECTED);
1199 else if( !strcmp(charger_type,
"USB_FLOAT") ) {
1200 if( !umudev_cable_state_connected() )
1201 log_warning(
"connection type detection failed, assuming charger");
1202 umudev_cable_state_from_udev(CABLE_STATE_CHARGER_CONNECTED);
1204 else if( !strcmp(charger_type,
"Unknown") ) {
1205 log_warning(
"connection type 'Unknown' reported, assuming disconnected");
1206 umudev_cable_state_from_udev(CABLE_STATE_DISCONNECTED);
1210 log_warning(
"unhandled power supply type: %s", charger_type);
1211 umudev_cable_state_from_udev(CABLE_STATE_DISCONNECTED);
1216gboolean umudev_init(
void)
1218 LOG_REGISTER_CONTEXT;
1220 gboolean success = FALSE;
1222 GIOChannel *iochannel = 0;
1225 umudev_in_cleanup =
false;
1228 if( !(umudev_object = udev_new()) ) {
1229 log_err(
"Can't create umudev_object\n");
1234 umudev_monitor = udev_monitor_new_from_netlink(umudev_object,
"udev");
1235 if( !umudev_monitor )
1237 log_err(
"Unable to monitor the netlink\n");
1243 umudev_charger_find_device();
1244 umudev_extcon_find_device();
1245 umudev_android_find_device();
1247 if( !umudev_charger_syspath ) {
1248 if( !umudev_extcon_subsystem && !umudev_android_subsystem ) {
1249 log_warning(
"no charger device found, bailing out");
1252 log_debug(
"no charger device found, using alternative sources");
1255 if( udev_monitor_enable_receiving(umudev_monitor) != 0 ) {
1256 log_err(
"Failed to enable monitor recieving.\n");
1260 iochannel = g_io_channel_unix_new(udev_monitor_get_fd(umudev_monitor));
1264 umudev_watch_id = g_io_add_watch_full(iochannel, 0, G_IO_IN,
1265 umudev_io_input_cb, NULL,
1266 umudev_io_error_cb);
1267 if( !umudev_watch_id )
1274 umudev_charger_poll_now();
1279 g_io_channel_unref(iochannel);
1288void umudev_quit(
void)
1290 LOG_REGISTER_CONTEXT;
1292 umudev_in_cleanup =
true;
1294 log_debug(
"HWhal cleanup\n");
1296 if( umudev_watch_id )
1298 g_source_remove(umudev_watch_id),
1299 umudev_watch_id = 0;
1302 if( umudev_monitor ) {
1303 udev_monitor_unref(umudev_monitor),
1307 if( umudev_object ) {
1308 udev_unref(umudev_object),
1312 g_free(umudev_charger_syspath),
1313 umudev_charger_syspath = 0;
1314 g_free(umudev_charger_subsystem),
1315 umudev_charger_subsystem = 0;
1317 g_free(umudev_extcon_syspath),
1318 umudev_extcon_syspath = 0;
1319 g_free(umudev_extcon_subsystem),
1320 umudev_extcon_subsystem = 0;
1322 g_free(umudev_android_syspath),
1323 umudev_android_syspath = 0;
1324 g_free(umudev_android_subsystem),
1325 umudev_android_subsystem = 0;
1327 umudev_cable_state_stop_timer();
1329 umudev_extcon_set_state(NULL);
1330 umudev_android_set_state(NULL);
1331 umudev_charger_set_online(NULL);
1332 umudev_charger_set_type(NULL);
1333 umudev_charger_cancel_poll();
void common_release_wakelock(const char *wakelock_name)
void common_acquire_wakelock(const char *wakelock_name)
void control_set_cable_state(cable_state_t cable_state)
bool control_get_connection_state(void)
void umdbus_send_event_signal(const char *state_ind)
void usbmoded_delay_suspend(void)
int usbmoded_get_cable_connection_delay(void)
#define USB_MODED_WAKELOCK_PROCESS_INPUT