Skip to content

Latest commit

 

History

History
972 lines (797 loc) · 28.3 KB

usb_moded-modesetting.c

File metadata and controls

972 lines (797 loc) · 28.3 KB
 
Mar 22, 2011
Mar 22, 2011
1
/**
Aug 24, 2018
Aug 24, 2018
2
3
4
* @file usb_moded-modesetting.c
*
* Copyright (C) 2010 Nokia Corporation. All rights reserved.
Feb 7, 2019
Feb 7, 2019
5
* Copyright (C) 2013-2019 Jolla Ltd.
Aug 24, 2018
Aug 24, 2018
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
*
* @author: Philippe De Swert <philippe.de-swert@nokia.com>
* @author: Philippe De Swert <phdeswer@lumi.maa>
* @author: Philippe De Swert <philippedeswert@gmail.com>
* @author: Philippe De Swert <philippe.deswert@jollamobile.com>
* @author: Bernd Wachter <bernd.wachter@jollamobile.com>
* @author: Slava Monich <slava.monich@jolla.com>
* @author: Thomas Perl <m@thp.io>
* @author: Simo Piiroinen <simo.piiroinen@jollamobile.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Lesser GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the Lesser GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
Sep 5, 2018
Sep 5, 2018
31
#include "usb_moded-modesetting.h"
Mar 22, 2011
Mar 22, 2011
32
33
#include "usb_moded.h"
Sep 5, 2018
Sep 5, 2018
34
35
#include "usb_moded-android.h"
Mar 22, 2011
Mar 22, 2011
36
#include "usb_moded-appsync.h"
Sep 5, 2018
Sep 5, 2018
37
#include "usb_moded-common.h"
Aug 24, 2018
Aug 24, 2018
38
39
#include "usb_moded-config-private.h"
#include "usb_moded-configfs.h"
Sep 5, 2018
Sep 5, 2018
40
41
42
43
#include "usb_moded-dbus-private.h"
#include "usb_moded-log.h"
#include "usb_moded-modules.h"
#include "usb_moded-network.h"
Sep 5, 2018
Sep 5, 2018
44
#include "usb_moded-worker.h"
Sep 5, 2018
Sep 5, 2018
45
46
47
48
49
50
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
Apr 9, 2019
Apr 9, 2019
51
#include <mntent.h>
Aug 24, 2018
Aug 24, 2018
52
53
/* ========================================================================= *
Apr 9, 2019
Apr 9, 2019
54
* Types
Aug 24, 2018
Aug 24, 2018
55
56
* ========================================================================= */
Apr 9, 2019
Apr 9, 2019
57
58
59
60
61
typedef struct storage_info_t
{
gchar *si_mountpoint;
gchar *si_mountdevice;;
} storage_info_t;
Aug 24, 2018
Aug 24, 2018
62
Apr 9, 2019
Apr 9, 2019
63
64
65
/* ========================================================================= *
* Prototypes
* ========================================================================= */
Aug 24, 2018
Aug 24, 2018
66
Apr 9, 2019
Apr 9, 2019
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/* ------------------------------------------------------------------------- *
* MODESETTING
* ------------------------------------------------------------------------- */
static void modesetting_track_value (const char *path, const char *text);
void modesetting_verify_values (void);
static char *modesetting_strip (char *str);
static char *modesetting_read_from_file (const char *path, size_t maxsize);
int modesetting_write_to_file_real (const char *file, int line, const char *func, const char *path, const char *text);
bool modesetting_is_mounted (const char *mountpoint);
bool modesetting_mount (const char *mountpoint);
bool modesetting_unmount (const char *mountpoint);
static gchar *modesetting_mountdev (const char *mountpoint);
static void modesetting_free_storage_info (storage_info_t *info);
static storage_info_t *modesetting_get_storage_info (size_t *pcount);
Apr 9, 2019
Apr 9, 2019
82
83
static bool modesetting_enter_mass_storage_mode (const modedata_t *data);
static int modesetting_leave_mass_storage_mode (const modedata_t *data);
Apr 9, 2019
Apr 9, 2019
84
85
86
87
88
static void modesetting_report_mass_storage_blocker(const char *mountpoint, int try);
bool modesetting_enter_dynamic_mode (void);
void modesetting_leave_dynamic_mode (void);
void modesetting_init (void);
void modesetting_quit (void);
Aug 24, 2018
Aug 24, 2018
89
90
91
92
/* ========================================================================= *
* Data
* ========================================================================= */
Apr 26, 2017
Apr 26, 2017
93
94
95
static GHashTable *tracked_values = 0;
Aug 24, 2018
Aug 24, 2018
96
97
98
99
100
/* ========================================================================= *
* Functions
* ========================================================================= */
static void modesetting_track_value(const char *path, const char *text)
Apr 26, 2017
Apr 26, 2017
101
{
Feb 20, 2019
Feb 20, 2019
102
103
LOG_REGISTER_CONTEXT;
Apr 26, 2017
Apr 26, 2017
104
105
106
107
108
109
110
111
112
113
114
115
if( !tracked_values || !path )
goto EXIT;
if( text )
g_hash_table_replace(tracked_values, g_strdup(path), g_strdup(text));
else
g_hash_table_remove(tracked_values, path);
EXIT:
return;
}
Aug 24, 2018
Aug 24, 2018
116
void modesetting_verify_values(void)
Apr 26, 2017
Apr 26, 2017
117
{
Feb 20, 2019
Feb 20, 2019
118
119
LOG_REGISTER_CONTEXT;
Apr 26, 2017
Apr 26, 2017
120
121
122
123
124
125
126
127
128
129
130
131
GHashTableIter iter;
gpointer key, value;
if( !tracked_values )
goto EXIT;
g_hash_table_iter_init(&iter, tracked_values);
while( g_hash_table_iter_next(&iter, &key, &value) )
{
const char *path = key;
const char *text = value;
Aug 24, 2018
Aug 24, 2018
132
char *curr = modesetting_read_from_file(path, 0x1000);
Apr 26, 2017
Apr 26, 2017
133
134
135
136
137
138
if( g_strcmp0(text, curr) ) {
/* There might be case mismatch between hexadecimal
* values used in configuration files vs what we get
* back when reading from kernel interfaces. */
if( text && curr && !g_ascii_strcasecmp(text, curr) ) {
Aug 17, 2017
Aug 17, 2017
139
log_debug("unexpected change '%s' : '%s' -> '%s' (case diff only)", path,
Apr 26, 2017
Apr 26, 2017
140
141
142
143
144
145
146
147
text ?: "???",
curr ?: "???");
}
else {
log_warning("unexpected change '%s' : '%s' -> '%s'", path,
text ?: "???",
curr ?: "???");
}
Aug 24, 2018
Aug 24, 2018
148
modesetting_track_value(path, curr);
Apr 26, 2017
Apr 26, 2017
149
150
151
152
153
154
155
156
157
}
free(curr);
}
EXIT:
return;
}
Aug 24, 2018
Aug 24, 2018
158
static char *modesetting_strip(char *str)
Jul 7, 2016
Jul 7, 2016
159
{
Feb 20, 2019
Feb 20, 2019
160
161
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
162
163
unsigned char *src = (unsigned char *)str;
unsigned char *dst = (unsigned char *)str;
Jul 7, 2016
Jul 7, 2016
164
165
while( *src > 0 && *src <= 32 ) ++src;
Aug 24, 2018
Aug 24, 2018
166
167
168
169
170
171
172
173
174
175
for( ;; )
{
while( *src > 32 ) *dst++ = *src++;
while( *src > 0 && *src <= 32 ) ++src;
if( *src == 0 ) break;
*dst++ = ' ';
}
*dst = 0;
return str;
Jul 7, 2016
Jul 7, 2016
176
177
}
Aug 24, 2018
Aug 24, 2018
178
static char *modesetting_read_from_file(const char *path, size_t maxsize)
Jul 7, 2016
Jul 7, 2016
179
{
Feb 20, 2019
Feb 20, 2019
180
181
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
int fd = -1;
ssize_t done = 0;
char *data = 0;
char *text = 0;
if((fd = open(path, O_RDONLY)) == -1)
{
/* Silently ignore things that could result
* from missing / read-only files */
if( errno != ENOENT && errno != EACCES )
log_warning("%s: open: %m", path);
goto cleanup;
}
if( !(data = malloc(maxsize + 1)) )
goto cleanup;
if((done = read(fd, data, maxsize)) == -1)
{
log_warning("%s: read: %m", path);
goto cleanup;
}
text = realloc(data, done + 1), data = 0;
text[done] = 0;
modesetting_strip(text);
Jul 7, 2016
Jul 7, 2016
208
209
cleanup:
Aug 24, 2018
Aug 24, 2018
210
211
212
free(data);
if(fd != -1) close(fd);
return text;
Jul 7, 2016
Jul 7, 2016
213
214
}
Aug 24, 2018
Aug 24, 2018
215
216
int modesetting_write_to_file_real(const char *file, int line, const char *func,
const char *path, const char *text)
Apr 21, 2011
Apr 21, 2011
217
{
Feb 20, 2019
Feb 20, 2019
218
219
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
220
221
222
223
224
int err = -1;
int fd = -1;
size_t todo = 0;
char *prev = 0;
bool clear = false;
Aug 24, 2018
Aug 24, 2018
225
gchar *repr = 0;
Sep 30, 2013
Sep 30, 2013
226
Aug 24, 2018
Aug 24, 2018
227
/* if either path or the text to be written are not there
Aug 24, 2018
Aug 24, 2018
228
* we return an error */
Aug 24, 2018
Aug 24, 2018
229
if(!text || !path)
Aug 24, 2018
Aug 24, 2018
230
goto cleanup;
Aug 24, 2018
Aug 24, 2018
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/* When attempting to clear ffs function list, writing an
* empty string is ignored and accomplishes nothing - while
* writing non-existing function clears the list but returns
* write error.
*
* Treat "none" (which is used as place-holder value in both
* configuration files and usb-moded sources) and "" similarly:
* - Write invalid function name to sysfs
* - Ignore resulting write error under default logging level
* - Assume reading from sysfs will result in empty string
*/
if( !strcmp(path, ANDROID0_FUNCTIONS) ) {
if( !strcmp(text, "") || !strcmp(text, "none") ) {
text = "none";
clear = true;
}
}
Aug 24, 2018
Aug 24, 2018
250
251
252
repr = g_strdup(text);
modesetting_strip(repr);
Aug 24, 2018
Aug 24, 2018
253
254
255
/* If the file can be read, it also means we can later check that
* the file retains the value we are about to write here. */
if( (prev = modesetting_read_from_file(path, 0x1000)) )
Aug 24, 2018
Aug 24, 2018
256
modesetting_track_value(path, clear ? "" : repr);
Aug 24, 2018
Aug 24, 2018
257
258
259
log_debug("%s:%d: %s(): WRITE '%s' : '%s' --> '%s'",
file, line, func,
Aug 24, 2018
Aug 24, 2018
260
path, prev ?: "???", repr);
Aug 24, 2018
Aug 24, 2018
261
262
263
264
265
266
267
268
todo = strlen(text);
/* no O_CREAT -> writes only to already existing files */
if( (fd = TEMP_FAILURE_RETRY(open(path, O_WRONLY))) == -1 )
{
log_warning("open(%s): %m", path);
goto cleanup;
Aug 17, 2017
Aug 17, 2017
269
}
Aug 24, 2018
Aug 24, 2018
270
271
while( todo > 0 )
Apr 21, 2011
Apr 21, 2011
272
{
Aug 24, 2018
Aug 24, 2018
273
274
275
276
277
278
279
280
281
282
283
ssize_t n = TEMP_FAILURE_RETRY(write(fd, text, todo));
if( n < 0 )
{
if( clear && errno == EINVAL )
log_debug("write(%s): %m (expected failure)", path);
else
log_warning("write(%s): %m", path);
goto cleanup;
}
todo -= n;
text += n;
Apr 21, 2011
Apr 21, 2011
284
285
}
Aug 24, 2018
Aug 24, 2018
286
err = 0;
Apr 21, 2011
Apr 21, 2011
287
288
289
cleanup:
Aug 24, 2018
Aug 24, 2018
290
if( fd != -1 ) TEMP_FAILURE_RETRY(close(fd));
Apr 21, 2011
Apr 21, 2011
291
Aug 24, 2018
Aug 24, 2018
292
free(prev);
Aug 24, 2018
Aug 24, 2018
293
free(repr);
Apr 26, 2017
Apr 26, 2017
294
Aug 24, 2018
Aug 24, 2018
295
return err;
Apr 21, 2011
Apr 21, 2011
296
297
}
Aug 24, 2018
Aug 24, 2018
298
299
bool modesetting_is_mounted(const char *mountpoint)
{
Feb 20, 2019
Feb 20, 2019
300
301
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
302
303
char cmd[256];
snprintf(cmd, sizeof cmd, "/bin/mountpoint -q '%s'", mountpoint);
Sep 5, 2018
Sep 5, 2018
304
return common_system(cmd) == 0;
Aug 24, 2018
Aug 24, 2018
305
306
307
308
}
bool modesetting_mount(const char *mountpoint)
{
Feb 20, 2019
Feb 20, 2019
309
310
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
311
312
char cmd[256];
snprintf(cmd, sizeof cmd, "/bin/mount '%s'", mountpoint);
Sep 5, 2018
Sep 5, 2018
313
return common_system(cmd) == 0;
Aug 24, 2018
Aug 24, 2018
314
315
316
317
}
bool modesetting_unmount(const char *mountpoint)
{
Feb 20, 2019
Feb 20, 2019
318
319
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
320
321
char cmd[256];
snprintf(cmd, sizeof cmd, "/bin/umount '%s'", mountpoint);
Sep 5, 2018
Sep 5, 2018
322
return common_system(cmd) == 0;
Aug 24, 2018
Aug 24, 2018
323
324
}
Apr 9, 2019
Apr 9, 2019
325
static gchar *modesetting_mountdev(const char *mountpoint)
Mar 22, 2011
Mar 22, 2011
326
{
Feb 20, 2019
Feb 20, 2019
327
328
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
char *res = 0;
FILE *fh = 0;
struct mntent *me;
if( !(fh = setmntent("/etc/fstab", "r")) )
goto EXIT;
while( (me = getmntent(fh)) ) {
if( !strcmp(me->mnt_dir, mountpoint) ) {
res = g_strdup(me->mnt_fsname);
break;
}
}
EXIT:
if( fh )
endmntent(fh);
log_debug("%s -> %s", mountpoint, res);
return res;
}
static void
modesetting_free_storage_info(storage_info_t *info)
{
Feb 20, 2019
Feb 20, 2019
355
356
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
357
358
359
360
361
362
363
364
365
366
367
368
if( info ) {
for( size_t i = 0; info[i].si_mountpoint; ++i ) {
g_free(info[i].si_mountpoint);
g_free(info[i].si_mountdevice);
}
g_free(info);
}
}
static storage_info_t *
modesetting_get_storage_info(size_t *pcount)
{
Feb 20, 2019
Feb 20, 2019
369
370
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
bool ack = false;
storage_info_t *info = 0;
size_t count = 0;
char *setting = 0;
gchar **array = 0;
/* Get comma separated mountpoint list from config */
if( !(setting = config_find_mounts()) ) {
log_warning("no mount points configuration");
goto EXIT;
}
/* Split mountpoint list to array and count number of items */
array = g_strsplit(setting, ",", 0);
while( array[count] )
++count;
if( count < 1 ) {
log_warning("no mount points configured");
goto EXIT;
}
/* Convert into array of storage_info_t objects */
info = g_new0(storage_info_t, count + 1);
for( size_t i = 0; i < count; ++i ) {
const gchar *mountpnt = info[i].si_mountpoint = g_strdup(array[i]);
if( access(mountpnt, F_OK) == -1 ) {
log_warning("mountpoint %s does not exist", mountpnt);
goto EXIT;
}
const gchar *mountdev = info[i].si_mountdevice = modesetting_mountdev(mountpnt);
if( !mountdev ) {
log_warning("can't find device for %s", mountpnt);
goto EXIT;
}
if( access(mountdev, F_OK) == -1 ) {
log_warning("mount device %s does not exist", mountdev);
goto EXIT;
}
}
ack = true;
EXIT:
if( !ack )
modesetting_free_storage_info(info), info = 0, count = 0;
g_strfreev(array);
g_free(setting);
return *pcount = count, info;
}
Apr 9, 2019
Apr 9, 2019
429
static bool modesetting_enter_mass_storage_mode(const modedata_t *data)
Aug 24, 2018
Aug 24, 2018
430
{
Feb 20, 2019
Feb 20, 2019
431
432
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
433
434
435
436
437
438
439
440
441
442
bool ack = false;
size_t count = 0;
storage_info_t *info = 0;
int nofua = 0;
char tmp[256];
/* Get mountpoint info */
if( !(info = modesetting_get_storage_info(&count)) )
goto EXIT;
Aug 24, 2018
Aug 24, 2018
443
444
/* send unmount signal so applications can release their grasp on the fs, do this here so they have time to act */
Feb 7, 2019
Feb 7, 2019
445
umdbus_send_event_signal(USB_PRE_UNMOUNT);
Aug 24, 2018
Aug 24, 2018
446
447
448
449
450
451
452
453
454
455
456
457
/* Get "No Force Unit Access" from config */
nofua = config_find_sync();
/* Android usb mass-storage is expected to support only onle lun */
if( android_in_use()&& count > 1 ) {
log_warning("ignoring excess mountpoints");
count = 1;
}
/* Umount filesystems */
for( size_t i = 0 ; i < count; ++i )
Aug 24, 2018
Aug 24, 2018
458
{
Aug 24, 2018
Aug 24, 2018
459
460
const gchar *mountpnt = info[i].si_mountpoint;
for( int tries = 0; ; ) {
Mar 22, 2011
Mar 22, 2011
461
Aug 24, 2018
Aug 24, 2018
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
if( !modesetting_is_mounted(mountpnt) ) {
log_debug("%s is not mounted", mountpnt);
break;
}
if( modesetting_unmount(mountpnt) ) {
log_debug("unmounted %s", mountpnt);
break;
}
if( ++tries == 3 ) {
log_err("failed to unmount %s - giving up", mountpnt);
modesetting_report_mass_storage_blocker(mountpnt, 2);
umdbus_send_error_signal(UMOUNT_ERROR);
goto EXIT;
Aug 24, 2018
Aug 24, 2018
477
}
Aug 24, 2018
Aug 24, 2018
478
479
480
log_warning("failed to unmount %s - wait a bit", mountpnt);
modesetting_report_mass_storage_blocker(mountpnt, 1);
Sep 5, 2018
Sep 5, 2018
481
common_sleep(1);
Aug 24, 2018
Aug 24, 2018
482
}
Aug 24, 2018
Aug 24, 2018
483
484
485
486
487
488
489
}
/* Backend specific actions */
if( android_in_use() ) {
const gchar *mountdev = info[0].si_mountdevice;
android_set_enabled(false);
android_set_function("mass_storage");
Aug 24, 2018
Aug 24, 2018
490
491
android_set_attr("f_mass_storage", "lun/nofua", nofua ? "1" : "0");
android_set_attr("f_mass_storage", "lun/file", mountdev);
Aug 24, 2018
Aug 24, 2018
492
493
494
android_set_enabled(true);
}
else if( configfs_in_use() ) {
Aug 24, 2018
Aug 24, 2018
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
configfs_set_udc(false);
configfs_set_function(0);
for( size_t i = 0 ; i < count; ++i ) {
const gchar *mountdev = info[i].si_mountdevice;
if( configfs_add_mass_storage_lun(i) ) {
configfs_set_mass_storage_attr(i, "cdrom", "0");
configfs_set_mass_storage_attr(i, "nofua", nofua ? "1" : "0");
configfs_set_mass_storage_attr(i, "removable", "1");
configfs_set_mass_storage_attr(i, "ro", "0");
configfs_set_mass_storage_attr(i, "file", mountdev);
}
}
configfs_set_function("mass_storage");
configfs_set_udc(true);
Aug 24, 2018
Aug 24, 2018
510
511
512
513
514
515
516
517
518
519
}
else if( modules_in_use() ) {
/* check if the file storage module has been loaded with sufficient luns in the parameter,
* if not, unload and reload or load it. Since mountpoints start at 0 the amount of them is one more than their id */
snprintf(tmp, sizeof tmp,
"/sys/devices/platform/musb_hdrc/gadget/gadget-lun%zd/file",
count - 1);
if( access(tmp, R_OK) == -1 )
Aug 24, 2018
Aug 24, 2018
520
{
Aug 24, 2018
Aug 24, 2018
521
522
523
524
log_debug("%s does not exist, unloading and reloading mass_storage\n", tmp);
modules_unload_module(MODULE_MASS_STORAGE);
snprintf(tmp, sizeof tmp, "modprobe %s luns=%zd \n", MODULE_MASS_STORAGE, count);
log_debug("usb-load command = %s \n", tmp);
Sep 5, 2018
Sep 5, 2018
525
if( common_system(tmp) != 0 )
Aug 24, 2018
Aug 24, 2018
526
goto EXIT;
Aug 24, 2018
Aug 24, 2018
527
528
529
}
/* activate mounts after sleeping 1s to be sure enumeration happened and autoplay will work in windows*/
Sep 5, 2018
Sep 5, 2018
530
common_sleep(1);
Aug 24, 2018
Aug 24, 2018
531
Aug 24, 2018
Aug 24, 2018
532
533
for( size_t i = 0 ; i < count; ++i ) {
const gchar *mountdev = info[i].si_mountdevice;
Aug 24, 2018
Aug 24, 2018
534
Aug 24, 2018
Aug 24, 2018
535
536
537
538
539
540
snprintf(tmp, sizeof tmp, "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%zd/nofua", i);
write_to_file(tmp, nofua ? "1" : "0");
snprintf(tmp, sizeof tmp, "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%zd/file", i);
write_to_file(tmp, mountdev);
log_debug("usb lun = %s active\n", mountdev);
Aug 24, 2018
Aug 24, 2018
541
}
Aug 24, 2018
Aug 24, 2018
542
543
544
545
}
else {
log_err("no suitable backend for mass-storage mode");
goto EXIT;
Aug 24, 2018
Aug 24, 2018
546
547
}
Aug 24, 2018
Aug 24, 2018
548
549
550
551
/* Success */
ack = true;
EXIT:
Aug 24, 2018
Aug 24, 2018
552
Aug 24, 2018
Aug 24, 2018
553
modesetting_free_storage_info(info);
Mar 22, 2011
Mar 22, 2011
554
Aug 24, 2018
Aug 24, 2018
555
556
if( ack ) {
/* only send data in use signal in case we actually succeed */
Feb 7, 2019
Feb 7, 2019
557
umdbus_send_event_signal(DATA_IN_USE);
Aug 24, 2018
Aug 24, 2018
558
559
560
561
562
563
564
}
else {
/* Try to undo any unmounts we might have managed to make */
modesetting_leave_mass_storage_mode(data);
}
return ack;
Mar 22, 2011
Mar 22, 2011
565
566
}
Apr 9, 2019
Apr 9, 2019
567
static int modesetting_leave_mass_storage_mode(const modedata_t *data)
Jul 1, 2013
Jul 1, 2013
568
{
Feb 20, 2019
Feb 20, 2019
569
570
LOG_REGISTER_CONTEXT;
Sep 5, 2018
Sep 5, 2018
571
572
(void)data;
Aug 24, 2018
Aug 24, 2018
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
bool ack = false;
size_t count = 0;
storage_info_t *info = 0;
gchar *alt_path = 0;
char tmp[256];
/* Get mountpoint info */
if( !(info = modesetting_get_storage_info(&count)) )
goto EXIT;
/* Backend specific actions */
if( android_in_use() ) {
log_debug("Disable android mass storage\n");
android_set_enabled(false);
Aug 24, 2018
Aug 24, 2018
588
android_set_attr("f_mass_storage", "lun/file", "");
Aug 24, 2018
Aug 24, 2018
589
590
}
else if( configfs_in_use() ) {
Aug 24, 2018
Aug 24, 2018
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
log_debug("Disable configfs mass storage\n");
configfs_set_udc(false);
configfs_set_function(0);
// reset lun0, remove the rest altogether
for( size_t i = 0 ; i < count; ++i ) {
// reset
configfs_set_mass_storage_attr(i, "cdrom", "0");
configfs_set_mass_storage_attr(i, "nofua", "0");
configfs_set_mass_storage_attr(i, "removable", "1");
configfs_set_mass_storage_attr(i, "ro", "0");
configfs_set_mass_storage_attr(i, "file", "");
// remove
if( i > 0 )
configfs_remove_mass_storage_lun(i);
}
Aug 24, 2018
Aug 24, 2018
607
608
609
610
611
612
}
else if( modules_in_use() ) {
for( size_t i = 0 ; i < count; ++i ) {
snprintf(tmp, sizeof tmp, "/sys/devices/platform/musb_hdrc/gadget/gadget-lun%zd/file", i);
write_to_file(tmp, "");
log_debug("usb lun = %s inactive\n", tmp);
Jul 1, 2013
Jul 1, 2013
613
}
Aug 24, 2018
Aug 24, 2018
614
615
616
}
else {
log_err("no suitable backend for mass-storage mode");
Aug 24, 2018
Aug 24, 2018
617
}
Jul 1, 2013
Jul 1, 2013
618
Aug 24, 2018
Aug 24, 2018
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
/* Assume success i.e. all the mountpoints that could have been
* unmounted due to mass-storage mode are mounted again. */
ack = true;
/* Remount filesystems */
/* TODO FIXME list of mountpoints, but singular alt mountpoint? */
alt_path = config_find_alt_mount();
for( size_t i = 0 ; i < count; ++i ) {
const char *mountpnt = info[i].si_mountpoint;
if( modesetting_is_mounted(mountpnt) ) {
log_debug("%s is already mounted", mountpnt);
continue;
}
if( modesetting_mount(mountpnt) ) {
log_debug("mounted %s", mountpnt);
continue;
}
/* At least one mountpoint could not be restored = failure */
ack = false;
Jul 1, 2013
Jul 1, 2013
643
Aug 24, 2018
Aug 24, 2018
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
if( !alt_path ) {
log_err("failed to mount %s - no alt mountpoint defined", mountpnt);
}
else {
// TODO what is the point of this all???
log_err("failed to mount %s - trying ro tmpfs as %s", mountpnt, alt_path);
snprintf(tmp, sizeof tmp, "mount -t tmpfs tmpfs -o ro --size=512K %s", alt_path);
}
}
EXIT:
modesetting_free_storage_info(info);
free(alt_path);
if( !ack )
umdbus_send_error_signal(RE_MOUNT_FAILED);
return ack;
Jul 1, 2013
Jul 1, 2013
662
663
}
Aug 24, 2018
Aug 24, 2018
664
static void modesetting_report_mass_storage_blocker(const char *mountpoint, int try)
May 10, 2011
May 10, 2011
665
{
Feb 20, 2019
Feb 20, 2019
666
667
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
668
669
670
FILE *stream = 0;
gchar *lsof_command = 0;
int count = 0;
May 10, 2011
May 10, 2011
671
Aug 24, 2018
Aug 24, 2018
672
lsof_command = g_strconcat("lsof ", mountpoint, NULL);
May 10, 2011
May 10, 2011
673
Sep 5, 2018
Sep 5, 2018
674
if( (stream = common_popen(lsof_command, "r")) )
May 10, 2011
May 10, 2011
675
{
Aug 24, 2018
Aug 24, 2018
676
677
678
679
char *text = 0;
size_t size = 0;
while( getline(&text, &size, stream) >= 0 )
May 10, 2011
May 10, 2011
680
{
Aug 24, 2018
Aug 24, 2018
681
682
683
684
685
686
687
688
689
690
/* skip the first line as it does not contain process info */
if(count != 0)
{
gchar **split = 0;
split = g_strsplit((const gchar*)text, " ", 2);
log_err("Mass storage blocked by process %s\n", split[0]);
umdbus_send_error_signal(split[0]);
g_strfreev(split);
}
count++;
May 10, 2011
May 10, 2011
691
}
Aug 24, 2018
Aug 24, 2018
692
pclose(stream);
Aug 24, 2018
Aug 24, 2018
693
free(text);
May 10, 2011
May 10, 2011
694
}
Aug 24, 2018
Aug 24, 2018
695
696
697
g_free(lsof_command);
if(try == 2)
log_err("Setting Mass storage blocked. Giving up.\n");
May 10, 2011
May 10, 2011
698
699
700
}
Aug 24, 2018
Aug 24, 2018
701
bool modesetting_enter_dynamic_mode(void)
May 10, 2011
May 10, 2011
702
{
Feb 20, 2019
Feb 20, 2019
703
704
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
705
706
bool ack = false;
Apr 9, 2019
Apr 9, 2019
707
const modedata_t *data;
Jun 19, 2013
Jun 19, 2013
708
Aug 24, 2018
Aug 24, 2018
709
log_debug("DYNAMIC MODE: SETUP");
Jun 19, 2013
Jun 19, 2013
710
Aug 24, 2018
Aug 24, 2018
711
712
713
/* - - - - - - - - - - - - - - - - - - - *
* Is a dynamic mode?
* - - - - - - - - - - - - - - - - - - - */
Jul 1, 2013
Jul 1, 2013
714
Sep 5, 2018
Sep 5, 2018
715
if( !(data = worker_get_usb_mode_data()) ) {
Aug 24, 2018
Aug 24, 2018
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
log_debug("No dynamic mode data to setup");
goto EXIT;
}
log_debug("data->mass_storage = %d", data->mass_storage);
log_debug("data->connman_tethering = %d", data->connman_tethering);
log_debug("data->appsync = %d", data->appsync);
log_debug("data->network = %d", data->network);
/* - - - - - - - - - - - - - - - - - - - *
* Is a mass storage dynamic mode?
* - - - - - - - - - - - - - - - - - - - */
if( data->mass_storage ) {
log_debug("Dynamic mode is mass storage");
Aug 24, 2018
Aug 24, 2018
731
ack = modesetting_enter_mass_storage_mode(data);
Aug 24, 2018
Aug 24, 2018
732
goto EXIT;
Aug 24, 2018
Aug 24, 2018
733
}
Jul 1, 2013
Jul 1, 2013
734
Aug 24, 2018
Aug 24, 2018
735
736
737
738
/* - - - - - - - - - - - - - - - - - - - *
* Start pre-enum app sync
* - - - - - - - - - - - - - - - - - - - */
May 27, 2013
May 27, 2013
739
#ifdef APP_SYNC
Aug 24, 2018
Aug 24, 2018
740
741
742
if( data->appsync ) {
log_debug("Dynamic mode is appsync: do pre actions");
if( appsync_activate_sync(data->mode_name) != 0 ) {
Aug 24, 2018
Aug 24, 2018
743
log_debug("Appsync failure");
Aug 24, 2018
Aug 24, 2018
744
goto EXIT;
Aug 24, 2018
Aug 24, 2018
745
}
Aug 24, 2018
Aug 24, 2018
746
}
May 27, 2013
May 27, 2013
747
#endif
Aug 24, 2018
Aug 24, 2018
748
749
750
751
752
/* - - - - - - - - - - - - - - - - - - - *
* Configure gadget
* - - - - - - - - - - - - - - - - - - - */
Aug 24, 2018
Aug 24, 2018
753
754
if( configfs_in_use() ) {
/* Configfs based gadget configuration */
Aug 24, 2018
Aug 24, 2018
755
configfs_set_function(data->sysfs_value);
Aug 24, 2018
Aug 24, 2018
756
configfs_set_productid(data->idProduct);
Aug 24, 2018
Aug 24, 2018
757
char *id = config_get_android_vendor_id();
Aug 24, 2018
Aug 24, 2018
758
759
configfs_set_vendorid(data->idVendorOverride ?: id);
free(id);
Aug 24, 2018
Aug 24, 2018
760
761
if( !configfs_set_udc(true) )
goto EXIT;
Aug 24, 2018
Aug 24, 2018
762
763
764
}
else if( android_in_use() ) {
/* Android USB based gadget configuration */
Aug 24, 2018
Aug 24, 2018
765
android_set_function(data->sysfs_value);
Aug 24, 2018
Aug 24, 2018
766
android_set_productid(data->idProduct);
Aug 24, 2018
Aug 24, 2018
767
768
769
770
771
772
773
char *id = config_get_android_vendor_id();
android_set_vendorid(data->idVendorOverride ?: id);
free(id);
write_to_file(data->android_extra_sysfs_path, data->android_extra_sysfs_value);
write_to_file(data->android_extra_sysfs_path2, data->android_extra_sysfs_value2);
if( !android_set_enabled(true) )
goto EXIT;
Aug 24, 2018
Aug 24, 2018
774
775
776
777
778
}
else if( modules_in_use() ) {
/* Assume relevant module has already been successfully loaded
* from somewhere else.
*/
Aug 24, 2018
Aug 24, 2018
779
// nop
Aug 24, 2018
Aug 24, 2018
780
781
782
}
else {
log_crit("no backend is selected, can't set dynamic mode");
Aug 24, 2018
Aug 24, 2018
783
goto EXIT;
Aug 24, 2018
Aug 24, 2018
784
785
}
Aug 24, 2018
Aug 24, 2018
786
787
788
789
/* - - - - - - - - - - - - - - - - - - - *
* Setup network
* - - - - - - - - - - - - - - - - - - - */
Aug 24, 2018
Aug 24, 2018
790
791
792
/* functionality should be enabled, so we can enable the network now */
if(data->network)
{
Aug 24, 2018
Aug 24, 2018
793
log_debug("Dynamic mode is network");
Oct 2, 2012
Oct 2, 2012
794
#ifdef DEBIAN
Aug 24, 2018
Aug 24, 2018
795
char command[256];
Jun 19, 2013
Jun 19, 2013
796
Aug 24, 2018
Aug 24, 2018
797
g_snprintf(command, 256, "ifdown %s ; ifup %s", data->network_interface, data->network_interface);
Sep 5, 2018
Sep 5, 2018
798
common_system(command);
Oct 2, 2012
Oct 2, 2012
799
#else
Aug 24, 2018
Aug 24, 2018
800
network_down(data);
Sep 5, 2018
Sep 5, 2018
801
802
803
804
805
int error = network_up(data);
/* In case of failure, retry upto 3 times */
for( int i = 0; error && i < 3; ++i ) {
log_warning("Retry setting up the network");
Sep 5, 2018
Sep 5, 2018
806
807
if( !common_msleep(1000) )
break;
Sep 5, 2018
Sep 5, 2018
808
809
810
811
812
if( !(error = network_up(data)) )
log_warning("Setting up the network succeeded");
}
if( error )
log_err("Setting up the network failed");
Oct 2, 2012
Oct 2, 2012
813
#endif /* DEBIAN */
Aug 24, 2018
Aug 24, 2018
814
}
Dec 12, 2013
Dec 12, 2013
815
Aug 24, 2018
Aug 24, 2018
816
/* Needs to be called before application post synching so
Aug 24, 2018
Aug 24, 2018
817
* that the dhcp server has the right config */
Aug 24, 2018
Aug 24, 2018
818
819
if(data->nat || data->dhcp_server)
network_set_up_dhcpd(data);
Jul 2, 2015
Jul 2, 2015
820
Aug 24, 2018
Aug 24, 2018
821
822
823
824
/* - - - - - - - - - - - - - - - - - - - *
* Start post-enum app sync
* - - - - - - - - - - - - - - - - - - - */
Aug 24, 2018
Aug 24, 2018
825
/* no need to execute the post sync if there was an error setting the mode */
Aug 24, 2018
Aug 24, 2018
826
if(data->appsync )
Aug 24, 2018
Aug 24, 2018
827
{
Aug 24, 2018
Aug 24, 2018
828
log_debug("Dynamic mode is appsync: do post actions");
Aug 24, 2018
Aug 24, 2018
829
/* let's sleep for a bit (350ms) to allow interfaces to settle before running postsync */
Sep 5, 2018
Sep 5, 2018
830
common_msleep(350);
Aug 24, 2018
Aug 24, 2018
831
832
appsync_activate_sync_post(data->mode_name);
}
Jul 2, 2015
Jul 2, 2015
833
Aug 24, 2018
Aug 24, 2018
834
835
836
837
/* - - - - - - - - - - - - - - - - - - - *
* Start tethering
* - - - - - - - - - - - - - - - - - - - */
Apr 15, 2015
Apr 15, 2015
838
#ifdef CONNMAN
Aug 24, 2018
Aug 24, 2018
839
840
if( data->connman_tethering ) {
log_debug("Dynamic mode is tethering");
Aug 24, 2018
Aug 24, 2018
841
connman_set_tethering(data->connman_tethering, TRUE);
Aug 24, 2018
Aug 24, 2018
842
}
Apr 15, 2015
Apr 15, 2015
843
844
#endif
Aug 24, 2018
Aug 24, 2018
845
846
847
848
ack = true;
EXIT:
if( !ack )
Aug 24, 2018
Aug 24, 2018
849
umdbus_send_error_signal(MODE_SETTING_FAILED);
Aug 24, 2018
Aug 24, 2018
850
return ack;
May 10, 2011
May 10, 2011
851
}
Mar 22, 2011
Mar 22, 2011
852
Aug 24, 2018
Aug 24, 2018
853
void modesetting_leave_dynamic_mode(void)
Aug 24, 2018
Aug 24, 2018
854
{
Feb 20, 2019
Feb 20, 2019
855
856
LOG_REGISTER_CONTEXT;
Aug 24, 2018
Aug 24, 2018
857
858
log_debug("DYNAMIC MODE: CLEANUP");
Apr 9, 2019
Apr 9, 2019
859
const modedata_t *data = worker_get_usb_mode_data();
Jun 19, 2013
Jun 19, 2013
860
Aug 24, 2018
Aug 24, 2018
861
862
863
864
865
866
867
/* - - - - - - - - - - - - - - - - - - - *
* Is a dynamic mode?
* - - - - - - - - - - - - - - - - - - - */
if( !data ) {
log_debug("No dynamic mode data to cleanup");
goto EXIT;
}
Jun 6, 2013
Jun 6, 2013
868
Aug 24, 2018
Aug 24, 2018
869
870
871
872
873
874
875
876
877
878
879
log_debug("data->mass_storage = %d", data->mass_storage);
log_debug("data->connman_tethering = %d", data->connman_tethering);
log_debug("data->appsync = %d", data->appsync);
log_debug("data->network = %d", data->network);
/* - - - - - - - - - - - - - - - - - - - *
* Is a mass storage dynamic mode?
* - - - - - - - - - - - - - - - - - - - */
if( data->mass_storage ) {
log_debug("Dynamic mode is mass storage");
Aug 24, 2018
Aug 24, 2018
880
modesetting_leave_mass_storage_mode(data);
Aug 24, 2018
Aug 24, 2018
881
goto EXIT;
Aug 24, 2018
Aug 24, 2018
882
}
Jul 1, 2013
Jul 1, 2013
883
Aug 24, 2018
Aug 24, 2018
884
885
886
887
/* - - - - - - - - - - - - - - - - - - - *
* Stop tethering
* - - - - - - - - - - - - - - - - - - - */
Apr 15, 2015
Apr 15, 2015
888
#ifdef CONNMAN
Aug 24, 2018
Aug 24, 2018
889
890
if( data->connman_tethering ) {
log_debug("Dynamic mode was tethering");
Aug 24, 2018
Aug 24, 2018
891
connman_set_tethering(data->connman_tethering, FALSE);
Aug 24, 2018
Aug 24, 2018
892
}
Apr 15, 2015
Apr 15, 2015
893
894
#endif
Aug 24, 2018
Aug 24, 2018
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
/* - - - - - - - - - - - - - - - - - - - *
* Stop post-enum app sync
* - - - - - - - - - - - - - - - - - - - */
if(data->appsync ) {
log_debug("Dynamic mode was appsync: undo post actions");
/* Just stop post enum appsync apps */
appsync_stop_apps(1);
}
/* - - - - - - - - - - - - - - - - - - - *
* Teardown network
* - - - - - - - - - - - - - - - - - - - */
if( data->network ) {
log_debug("Dynamic mode was network");
Aug 24, 2018
Aug 24, 2018
911
912
913
network_down(data);
}
Aug 24, 2018
Aug 24, 2018
914
915
916
917
/* - - - - - - - - - - - - - - - - - - - *
* Configure gadget
* - - - - - - - - - - - - - - - - - - - */
Aug 24, 2018
Aug 24, 2018
918
919
920
921
922
923
if( configfs_in_use() ) {
/* Leave as is. We will reprogram wnen mode is
* set, not when it is unset.
*/
}
else if( android_in_use() ) {
Aug 24, 2018
Aug 24, 2018
924
925
926
/* Leave as is. We will reprogram wnen mode is
* set, not when it is unset.
*/
Aug 24, 2018
Aug 24, 2018
927
928
929
930
931
932
933
}
else if( modules_in_use() ) {
/* Assume unloading happens somewhere else */
}
else {
log_crit("no backend is selected, can't unset dynamic mode");
}
Mar 22, 2011
Mar 22, 2011
934
Aug 24, 2018
Aug 24, 2018
935
936
937
/* - - - - - - - - - - - - - - - - - - - *
* Stop pre-enum app sync
* - - - - - - - - - - - - - - - - - - - */
Aug 15, 2013
Aug 15, 2013
938
Jun 6, 2013
Jun 6, 2013
939
#ifdef APP_SYNC
Aug 24, 2018
Aug 24, 2018
940
941
942
943
if( data->appsync ) {
log_debug("Dynamic mode was appsync: undo all actions");
/* Do full appsync cleanup */
appsync_stop(false);
Aug 24, 2018
Aug 24, 2018
944
}
Aug 24, 2018
Aug 24, 2018
945
#endif
Mar 22, 2011
Mar 22, 2011
946
Aug 24, 2018
Aug 24, 2018
947
948
EXIT:
return;
Mar 22, 2011
Mar 22, 2011
949
950
}
Apr 26, 2017
Apr 26, 2017
951
952
/** Allocate modesetting related dynamic resouces
*/
Aug 24, 2018
Aug 24, 2018
953
void modesetting_init(void)
Apr 26, 2017
Apr 26, 2017
954
{
Feb 20, 2019
Feb 20, 2019
955
956
LOG_REGISTER_CONTEXT;
Apr 26, 2017
Apr 26, 2017
957
958
959
960
961
962
963
964
if( !tracked_values ) {
tracked_values = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
}
}
/** Release modesetting related dynamic resouces
*/
Aug 24, 2018
Aug 24, 2018
965
void modesetting_quit(void)
Apr 26, 2017
Apr 26, 2017
966
{
Feb 20, 2019
Feb 20, 2019
967
968
LOG_REGISTER_CONTEXT;
Apr 26, 2017
Apr 26, 2017
969
970
971
972
if( tracked_values ) {
g_hash_table_unref(tracked_values), tracked_values = 0;
}
}