73static void modesetting_track_value (
const char *path,
const char *text);
74void modesetting_verify_values (
void);
75static char *modesetting_strip (
char *str);
76static char *modesetting_read_from_file (
const char *path,
size_t maxsize);
77int modesetting_write_to_file_real (
const char *file,
int line,
const char *func,
const char *path,
const char *text);
78bool modesetting_is_mounted (
const char *mountpoint);
79bool modesetting_mount (
const char *mountpoint);
80bool modesetting_unmount (
const char *mountpoint);
81static gchar *modesetting_mountdev (
const char *mountpoint);
83static storage_info_t *modesetting_get_storage_info (
size_t *pcount);
84static bool modesetting_enter_mass_storage_mode (
const modedata_t *data);
85static int modesetting_leave_mass_storage_mode (
const modedata_t *data);
86static void modesetting_report_mass_storage_blocker(
const char *mountpoint,
int try);
87bool modesetting_enter_dynamic_mode (
void);
88void modesetting_leave_dynamic_mode (
void);
96static GHashTable *tracked_values = 0;
102static void modesetting_track_value(
const char *path,
const char *text)
104 LOG_REGISTER_CONTEXT;
106 if( !tracked_values || !path )
110 g_hash_table_replace(tracked_values, g_strdup(path), g_strdup(text));
112 g_hash_table_remove(tracked_values, path);
118void modesetting_verify_values(
void)
120 LOG_REGISTER_CONTEXT;
125 if( !tracked_values )
128 g_hash_table_iter_init(&iter, tracked_values);
129 while( g_hash_table_iter_next(&iter, &key, &value) )
131 const char *path = key;
132 const char *text = value;
134 char *curr = modesetting_read_from_file(path, 0x1000);
136 if( g_strcmp0(text, curr) ) {
140 if( text && curr && !g_ascii_strcasecmp(text, curr) ) {
141 log_debug(
"unexpected change '%s' : '%s' -> '%s' (case diff only)", path,
146 log_warning(
"unexpected change '%s' : '%s' -> '%s'", path,
150 modesetting_track_value(path, curr);
160static char *modesetting_strip(
char *str)
162 LOG_REGISTER_CONTEXT;
164 unsigned char *src = (
unsigned char *)str;
165 unsigned char *dst = (
unsigned char *)str;
167 while( *src > 0 && *src <= 32 ) ++src;
171 while( *src > 32 ) *dst++ = *src++;
172 while( *src > 0 && *src <= 32 ) ++src;
173 if( *src == 0 )
break;
180static char *modesetting_read_from_file(
const char *path,
size_t maxsize)
182 LOG_REGISTER_CONTEXT;
189 if((fd = open(path, O_RDONLY)) == -1)
193 if( errno != ENOENT && errno != EACCES )
194 log_warning(
"%s: open: %m", path);
198 if( !(data = malloc(maxsize + 1)) )
201 if((done = read(fd, data, maxsize)) == -1)
203 log_warning(
"%s: read: %m", path);
207 text = realloc(data, done + 1), data = 0;
209 modesetting_strip(text);
213 if(fd != -1) close(fd);
217int modesetting_write_to_file_real(
const char *file,
int line,
const char *func,
218 const char *path,
const char *text)
220 LOG_REGISTER_CONTEXT;
245 if( !strcmp(path, ANDROID0_FUNCTIONS) ) {
246 if( !strcmp(text,
"") || !strcmp(text,
"none") ) {
252 repr = g_strdup(text);
253 modesetting_strip(repr);
257 if( (prev = modesetting_read_from_file(path, 0x1000)) )
258 modesetting_track_value(path, clear ?
"" : repr);
260 log_debug(
"%s:%d: %s(): WRITE '%s' : '%s' --> '%s'",
262 path, prev ?:
"???", repr);
267 if( (fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY))) == -1 )
269 log_warning(
"open(%s): %m", path);
275 ssize_t n = TEMP_FAILURE_RETRY(write(fd, text, todo));
278 if( clear && errno == EINVAL )
279 log_debug(
"write(%s): %m (expected failure)", path);
281 log_warning(
"write(%s): %m", path);
292 if( fd != -1 ) TEMP_FAILURE_RETRY(close(fd));
300bool modesetting_is_mounted(
const char *mountpoint)
302 LOG_REGISTER_CONTEXT;
305 snprintf(cmd,
sizeof cmd,
"/bin/mountpoint -q '%s'", mountpoint);
306 return common_system(cmd) == 0;
309bool modesetting_mount(
const char *mountpoint)
311 LOG_REGISTER_CONTEXT;
314 snprintf(cmd,
sizeof cmd,
"/bin/mount '%s'", mountpoint);
315 return common_system(cmd) == 0;
318bool modesetting_unmount(
const char *mountpoint)
320 LOG_REGISTER_CONTEXT;
323 snprintf(cmd,
sizeof cmd,
"/bin/umount '%s'", mountpoint);
324 return common_system(cmd) == 0;
327static gchar *modesetting_mountdev(
const char *mountpoint)
329 LOG_REGISTER_CONTEXT;
335 if( !(fh = setmntent(
"/etc/fstab",
"r")) )
338 while( (me = getmntent(fh)) ) {
339 if( !strcmp(me->mnt_dir, mountpoint) ) {
340 res = g_strdup(me->mnt_fsname);
349 log_debug(
"%s -> %s", mountpoint, res);
357 LOG_REGISTER_CONTEXT;
361 g_free(info[i].si_mountpoint);
362 g_free(info[i].si_mountdevice);
369modesetting_get_storage_info(
size_t *pcount)
371 LOG_REGISTER_CONTEXT;
380 if( !(setting = config_find_mounts()) ) {
381 log_warning(
"no mount points configuration");
386 array = g_strsplit(setting,
",", 0);
387 while( array[count] )
391 log_warning(
"no mount points configured");
398 for(
size_t i = 0; i < count; ++i ) {
399 const gchar *mountpnt = info[i].
si_mountpoint = g_strdup(array[i]);
401 if( access(mountpnt, F_OK) == -1 ) {
402 log_warning(
"mountpoint %s does not exist", mountpnt);
406 const gchar *mountdev = info[i].
si_mountdevice = modesetting_mountdev(mountpnt);
409 log_warning(
"can't find device for %s", mountpnt);
413 if( access(mountdev, F_OK) == -1 ) {
414 log_warning(
"mount device %s does not exist", mountdev);
423 modesetting_free_storage_info(info), info = 0, count = 0;
428 return *pcount = count, info;
431static bool modesetting_enter_mass_storage_mode(
const modedata_t *data)
433 LOG_REGISTER_CONTEXT;
443 if( !(info = modesetting_get_storage_info(&count)) )
450 nofua = config_find_sync();
453 if( android_in_use()&& count > 1 ) {
454 log_warning(
"ignoring excess mountpoints");
459 for(
size_t i = 0 ; i < count; ++i )
462 for(
int tries = 0; ; ) {
464 if( !modesetting_is_mounted(mountpnt) ) {
465 log_debug(
"%s is not mounted", mountpnt);
469 if( modesetting_unmount(mountpnt) ) {
470 log_debug(
"unmounted %s", mountpnt);
475 log_err(
"failed to unmount %s - giving up", mountpnt);
476 modesetting_report_mass_storage_blocker(mountpnt, 2);
481 log_warning(
"failed to unmount %s - wait a bit", mountpnt);
482 modesetting_report_mass_storage_blocker(mountpnt, 1);
488 if( android_in_use() ) {
490 android_set_enabled(
false);
491 android_set_function(
"mass_storage");
494 android_set_enabled(
true);
496 else if( configfs_in_use() ) {
497 configfs_set_udc(
false);
498 configfs_set_function(0);
500 for(
size_t i = 0 ; i < count; ++i ) {
502 if( configfs_add_mass_storage_lun(i) ) {
503 configfs_set_mass_storage_attr(i,
"cdrom",
"0");
504 configfs_set_mass_storage_attr(i,
"nofua", nofua ?
"1" :
"0");
505 configfs_set_mass_storage_attr(i,
"removable",
"1");
506 configfs_set_mass_storage_attr(i,
"ro",
"0");
507 configfs_set_mass_storage_attr(i,
"file", mountdev);
510 configfs_set_function(
"mass_storage");
511 configfs_set_udc(
true);
513 else if( modules_in_use() ) {
517 snprintf(tmp,
sizeof tmp,
518 "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%zd/file",
521 if( access(tmp, R_OK) == -1 )
523 log_debug(
"%s does not exist, unloading and reloading mass_storage\n", tmp);
525 snprintf(tmp,
sizeof tmp,
"modprobe %s luns=%zd", MODULE_MASS_STORAGE, count);
526 log_debug(
"usb-load command = %s", tmp);
527 if( common_system(tmp) != 0 )
534 for(
size_t i = 0 ; i < count; ++i ) {
537 snprintf(tmp,
sizeof tmp,
"/sys/devices/platform/musb_hdrc/gadget/gadget-lun%zd/nofua", i);
538 write_to_file(tmp, nofua ?
"1" :
"0");
540 snprintf(tmp,
sizeof tmp,
"/sys/devices/platform/musb_hdrc/gadget/gadget-lun%zd/file", i);
541 write_to_file(tmp, mountdev);
542 log_debug(
"usb lun = %s active\n", mountdev);
546 log_err(
"no suitable backend for mass-storage mode");
555 modesetting_free_storage_info(info);
563 modesetting_leave_mass_storage_mode(data);
569static int modesetting_leave_mass_storage_mode(
const modedata_t *data)
571 LOG_REGISTER_CONTEXT;
583 if( !(info = modesetting_get_storage_info(&count)) )
587 if( android_in_use() ) {
588 log_debug(
"Disable android mass storage\n");
589 android_set_enabled(
false);
592 else if( configfs_in_use() ) {
593 log_debug(
"Disable configfs mass storage\n");
594 configfs_set_udc(
false);
595 configfs_set_function(0);
598 for(
size_t i = 0 ; i < count; ++i ) {
600 configfs_set_mass_storage_attr(i,
"cdrom",
"0");
601 configfs_set_mass_storage_attr(i,
"nofua",
"0");
602 configfs_set_mass_storage_attr(i,
"removable",
"1");
603 configfs_set_mass_storage_attr(i,
"ro",
"0");
604 configfs_set_mass_storage_attr(i,
"file",
"");
607 configfs_remove_mass_storage_lun(i);
610 else if( modules_in_use() ) {
611 for(
size_t i = 0 ; i < count; ++i ) {
612 snprintf(tmp,
sizeof tmp,
"/sys/devices/platform/musb_hdrc/gadget/gadget-lun%zd/file", i);
613 write_to_file(tmp,
"");
614 log_debug(
"usb lun = %s inactive\n", tmp);
618 log_err(
"no suitable backend for mass-storage mode");
628 alt_path = config_find_alt_mount();
630 for(
size_t i = 0 ; i < count; ++i ) {
633 if( modesetting_is_mounted(mountpnt) ) {
634 log_debug(
"%s is already mounted", mountpnt);
638 if( modesetting_mount(mountpnt) ) {
639 log_debug(
"mounted %s", mountpnt);
647 log_err(
"failed to mount %s - no alt mountpoint defined", mountpnt);
651 log_err(
"failed to mount %s - trying ro tmpfs as %s", mountpnt, alt_path);
652 snprintf(tmp,
sizeof tmp,
"mount -t tmpfs tmpfs -o ro --size=512K %s", alt_path);
657 modesetting_free_storage_info(info);
666static void modesetting_report_mass_storage_blocker(
const char *mountpoint,
int try)
668 LOG_REGISTER_CONTEXT;
671 gchar *lsof_command = 0;
674 lsof_command = g_strconcat(
"lsof ", mountpoint, NULL);
676 if( (stream = common_popen(lsof_command,
"r")) )
681 while( getline(&text, &size, stream) >= 0 )
687 split = g_strsplit((
const gchar*)text,
" ", 2);
688 log_err(
"Mass storage blocked by process %s\n", split[0]);
697 g_free(lsof_command);
699 log_err(
"Setting Mass storage blocked. Giving up.\n");
703bool modesetting_enter_dynamic_mode(
void)
705 LOG_REGISTER_CONTEXT;
711 log_debug(
"DYNAMIC MODE: SETUP");
718 log_debug(
"No dynamic mode data to setup");
722 log_debug(
"data->mode_name = %s", data->
mode_name);
723 log_debug(
"data->mass_storage = %d", data->
mass_storage);
725 log_debug(
"data->connman_tethering = %s", data->connman_tethering ?:
"n/a");
727 log_debug(
"data->appsync = %d", data->
appsync);
728 log_debug(
"data->network = %d", data->
network);
732 log_debug(
"data->idProduct = %s", data->
idProduct ?:
"n/a");
734 log_debug(
"data->nat = %d", data->
nat);
735 log_debug(
"data->dhcp_server = %d", data->
dhcp_server);
742 log_debug(
"Dynamic mode is mass storage");
743 ack = modesetting_enter_mass_storage_mode(data);
753 log_debug(
"Dynamic mode is appsync: do pre actions");
755 log_debug(
"Appsync failure");
765 if( configfs_in_use() ) {
769 char *
id = config_get_android_vendor_id();
772 if( !configfs_set_udc(
true) )
775 else if( android_in_use() ) {
779 char *
id = config_get_android_vendor_id();
784 if( !android_set_enabled(
true) )
787 else if( modules_in_use() ) {
794 log_crit(
"no backend is selected, can't set dynamic mode");
805 log_debug(
"Dynamic mode is network");
810 common_system(command);
816 for(
int i = 0; error && i < 3; ++i ) {
817 log_warning(
"Retry setting up the network");
818 if( !common_msleep(1000) )
821 log_warning(
"Setting up the network succeeded");
824 log_err(
"Setting up the network failed");
848 log_debug(
"Dynamic mode is appsync: do post actions");
859 if( data->connman_tethering ) {
860 log_debug(
"Dynamic mode is tethering");
861 if( !connman_set_tethering(data->connman_tethering,
true) )
874void modesetting_leave_dynamic_mode(
void)
876 LOG_REGISTER_CONTEXT;
878 log_debug(
"DYNAMIC MODE: CLEANUP");
886 log_debug(
"No dynamic mode data to cleanup");
890 log_debug(
"data->mass_storage = %d", data->
mass_storage);
892 log_debug(
"data->connman_tethering = %s", data->connman_tethering ?:
"n/a");
894 log_debug(
"data->appsync = %d", data->
appsync);
895 log_debug(
"data->network = %d", data->
network);
902 log_debug(
"Dynamic mode is mass storage");
903 modesetting_leave_mass_storage_mode(data);
912 if( data->connman_tethering ) {
913 log_debug(
"Dynamic mode was tethering");
914 connman_set_tethering(data->connman_tethering,
false);
923 log_debug(
"Dynamic mode was appsync: undo post actions");
933 log_debug(
"Dynamic mode was network");
941 if( configfs_in_use() ) {
946 else if( android_in_use() ) {
951 else if( modules_in_use() ) {
955 log_crit(
"no backend is selected, can't unset dynamic mode");
964 log_debug(
"Dynamic mode was appsync: undo all actions");
978 LOG_REGISTER_CONTEXT;
980 if( !tracked_values ) {
981 tracked_values = g_hash_table_new_full(g_str_hash, g_str_equal,
990 LOG_REGISTER_CONTEXT;
992 if( tracked_values ) {
993 g_hash_table_unref(tracked_values), tracked_values = 0;
gchar * android_extra_sysfs_path
gchar * network_interface
gchar * android_extra_sysfs_value2
gchar * android_extra_sysfs_value
gchar * android_extra_sysfs_path2
bool android_set_attr(const char *function, const char *attr, const char *value)
void appsync_deactivate_all(bool force)
int appsync_activate_post(const char *mode)
void appsync_deactivate_post(void)
int appsync_activate_pre(const char *mode)
void umdbus_send_event_signal(const char *state_ind)
int umdbus_send_error_signal(const char *error)
void modesetting_init(void)
void modesetting_quit(void)
int modules_unload_module(const char *module)
int network_up(const modedata_t *data)
int network_update_udhcpd_config(const modedata_t *data)
void network_down(const modedata_t *data)
const modedata_t * worker_get_usb_mode_data(void)