Skip to content

Latest commit

 

History

History
479 lines (401 loc) · 11.5 KB

usb_moded-appsync.c

File metadata and controls

479 lines (401 loc) · 11.5 KB
 
Mar 22, 2011
Mar 22, 2011
1
/**
Apr 6, 2011
Apr 6, 2011
2
@file usb_moded-appsync.c
Apr 21, 2011
Apr 21, 2011
3
Mar 22, 2011
Mar 22, 2011
4
Copyright (C) 2010 Nokia Corporation. All rights reserved.
Nov 7, 2016
Nov 7, 2016
5
Copyright (C) 2013-2016 Jolla Ltd.
Mar 22, 2011
Mar 22, 2011
6
7
@author: Philippe De Swert <philippe.de-swert@nokia.com>
Nov 7, 2016
Nov 7, 2016
8
9
@author: Philippe De Swert <philippe.deswert@jollamobile.com>
@author: Simo Piiroinen <simo.piiroinen@jollamobile.com>
Mar 22, 2011
Mar 22, 2011
10
11
This program is free software; you can redistribute it and/or
Apr 21, 2011
Apr 21, 2011
12
13
modify it under the terms of the Lesser GNU General Public License
version 2 as published by the Free Software Foundation.
Mar 22, 2011
Mar 22, 2011
14
15
16
17
18
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.
Apr 21, 2011
Apr 21, 2011
19
Mar 22, 2011
Mar 22, 2011
20
21
22
23
24
25
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
*/
Apr 21, 2011
Apr 21, 2011
26
27
#define _GNU_SOURCE
Mar 22, 2011
Mar 22, 2011
28
29
30
31
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
Apr 21, 2011
Apr 21, 2011
32
33
#include <fcntl.h>
#include <errno.h>
May 10, 2011
May 10, 2011
34
#include <sys/time.h>
Mar 22, 2011
Mar 22, 2011
35
36
37
38
39
40
41
#include <glib.h>
#include <glib/gstdio.h>
#include "usb_moded-appsync.h"
#include "usb_moded-appsync-dbus.h"
#include "usb_moded-appsync-dbus-private.h"
Apr 21, 2011
Apr 21, 2011
42
#include "usb_moded-modesetting.h"
Mar 22, 2011
Mar 22, 2011
43
#include "usb_moded-log.h"
Jun 5, 2013
Jun 5, 2013
44
#include "usb_moded-systemd.h"
Mar 22, 2011
Mar 22, 2011
45
Mar 11, 2014
Mar 11, 2014
46
static struct list_elem *read_file(const gchar *filename, int diag);
Jul 7, 2016
Jul 7, 2016
47
48
49
50
static void enumerate_usb(void);
static gboolean enumerate_usb_cb(gpointer data);
static void start_enumerate_usb_timer(void);
static void cancel_enumerate_usb_timer(void);
Mar 22, 2011
Mar 22, 2011
51
Apr 21, 2011
Apr 21, 2011
52
53
static GList *sync_list = NULL;
Jul 7, 2016
Jul 7, 2016
54
static guint enumerate_usb_id = 0;
May 10, 2011
May 10, 2011
55
static struct timeval sync_tv;
Nov 25, 2013
Nov 25, 2013
56
57
58
59
60
61
#ifdef APP_SYNC_DBUS
static int no_dbus = 0;
#else
static int no_dbus = 0;
#endif /* APP_SYNC_DBUS */
May 10, 2011
May 10, 2011
62
Jul 7, 2016
Jul 7, 2016
63
static void free_elem(struct list_elem *elem)
Mar 22, 2011
Mar 22, 2011
64
{
Jul 7, 2016
Jul 7, 2016
65
66
67
g_free(elem->name);
g_free(elem->launch);
g_free(elem->mode);
Apr 21, 2011
Apr 21, 2011
68
69
free(elem);
}
Mar 22, 2011
Mar 22, 2011
70
Jul 7, 2016
Jul 7, 2016
71
72
73
74
75
76
static void free_elem_cb(gpointer elem, gpointer user_data)
{
(void)user_data;
free_elem(elem);
}
Oct 22, 2013
Oct 22, 2013
77
void free_appsync_list(void)
Apr 21, 2011
Apr 21, 2011
78
79
{
if( sync_list != 0 )
Mar 22, 2011
Mar 22, 2011
80
{
May 16, 2011
May 16, 2011
81
/*g_list_free_full(sync_list, free_elem); */
Jul 7, 2016
Jul 7, 2016
82
g_list_foreach (sync_list, free_elem_cb, NULL);
May 16, 2011
May 16, 2011
83
g_list_free (sync_list);
Apr 21, 2011
Apr 21, 2011
84
sync_list = 0;
Oct 22, 2013
Oct 22, 2013
85
log_debug("Appsync list freed\n");
Mar 22, 2011
Mar 22, 2011
86
87
88
}
}
Jul 2, 2015
Jul 2, 2015
89
90
91
92
93
static gint list_sort_func(gconstpointer a, gconstpointer b)
{
return strcasecmp( (char*)a, (char*)b );
}
Mar 10, 2014
Mar 10, 2014
94
void readlist(int diag)
Mar 22, 2011
Mar 22, 2011
95
{
Apr 21, 2011
Apr 21, 2011
96
97
98
99
100
GDir *confdir = 0;
const gchar *dirname;
struct list_elem *list_item;
Oct 22, 2013
Oct 22, 2013
101
free_appsync_list();
Mar 22, 2011
Mar 22, 2011
102
Mar 10, 2014
Mar 10, 2014
103
104
105
106
107
108
109
110
111
112
if(diag)
{
if( !(confdir = g_dir_open(CONF_DIR_DIAG_PATH, 0, NULL)) )
goto cleanup;
}
else
{
if( !(confdir = g_dir_open(CONF_DIR_PATH, 0, NULL)) )
goto cleanup;
}
Mar 22, 2011
Mar 22, 2011
113
Apr 21, 2011
Apr 21, 2011
114
while( (dirname = g_dir_read_name(confdir)) )
Mar 22, 2011
Mar 22, 2011
115
{
Apr 21, 2011
Apr 21, 2011
116
log_debug("Read file %s\n", dirname);
Mar 11, 2014
Mar 11, 2014
117
if( (list_item = read_file(dirname, diag)) )
Apr 21, 2011
Apr 21, 2011
118
sync_list = g_list_append(sync_list, list_item);
Mar 22, 2011
Mar 22, 2011
119
}
Apr 21, 2011
Apr 21, 2011
120
121
122
123
cleanup:
if( confdir ) g_dir_close(confdir);
Jul 2, 2015
Jul 2, 2015
124
125
126
127
/* sort list alphabetically so services for a mode
can be run in a certain order */
sync_list=g_list_sort(sync_list, list_sort_func);
Apr 21, 2011
Apr 21, 2011
128
129
130
131
132
/* set up session bus connection if app sync in use
* so we do not need to make the time consuming connect
* operation at enumeration time ... */
if( sync_list )
Mar 22, 2011
Mar 22, 2011
133
{
Jul 12, 2013
Jul 12, 2013
134
log_debug("Sync list valid\n");
Nov 25, 2013
Nov 25, 2013
135
#ifdef APP_SYN_DBUS
Apr 21, 2011
Apr 21, 2011
136
usb_moded_app_sync_init_connection();
Nov 25, 2013
Nov 25, 2013
137
#endif
Mar 22, 2011
Mar 22, 2011
138
}
Apr 21, 2011
Apr 21, 2011
139
140
}
Mar 11, 2014
Mar 11, 2014
141
static struct list_elem *read_file(const gchar *filename, int diag)
Apr 21, 2011
Apr 21, 2011
142
143
144
145
146
{
gchar *full_filename = NULL;
GKeyFile *settingsfile = NULL;
struct list_elem *list_item = NULL;
Mar 11, 2014
Mar 11, 2014
147
148
149
150
151
152
153
154
155
156
if(diag)
{
if( !(full_filename = g_strconcat(CONF_DIR_DIAG_PATH, "/", filename, NULL)) )
goto cleanup;
}
else
{
if( !(full_filename = g_strconcat(CONF_DIR_PATH, "/", filename, NULL)) )
goto cleanup;
}
Apr 21, 2011
Apr 21, 2011
157
158
159
160
161
162
163
164
165
166
167
168
169
if( !(settingsfile = g_key_file_new()) )
goto cleanup;
if( !g_key_file_load_from_file(settingsfile, full_filename, G_KEY_FILE_NONE, NULL) )
goto cleanup;
if( !(list_item = calloc(1, sizeof *list_item)) )
goto cleanup;
list_item->name = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, APP_INFO_NAME_KEY, NULL);
log_debug("Appname = %s\n", list_item->name);
list_item->launch = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, APP_INFO_LAUNCH_KEY, NULL);
May 10, 2011
May 10, 2011
170
171
172
log_debug("Launch = %s\n", list_item->launch);
list_item->mode = g_key_file_get_string(settingsfile, APP_INFO_ENTRY, APP_INFO_MODE_KEY, NULL);
log_debug("Launch mode = %s\n", list_item->mode);
Jun 5, 2013
Jun 5, 2013
173
174
list_item->systemd = g_key_file_get_integer(settingsfile, APP_INFO_ENTRY, APP_INFO_SYSTEMD_KEY, NULL);
log_debug("Systemd control = %d\n", list_item->systemd);
Dec 11, 2013
Dec 11, 2013
175
list_item->post = g_key_file_get_integer(settingsfile, APP_INFO_ENTRY, APP_INFO_POST, NULL);
Jul 7, 2016
Jul 7, 2016
176
list_item->state = APP_STATE_DONTCARE;
Apr 21, 2011
Apr 21, 2011
177
178
179
180
181
182
183
cleanup:
if(settingsfile)
g_key_file_free(settingsfile);
g_free(full_filename);
Jul 12, 2013
Jul 12, 2013
184
185
/* if a minimum set of required elements is not filled in we discard the list_item */
if( list_item && !(list_item->name && list_item->mode) )
Mar 22, 2011
Mar 22, 2011
186
{
Jul 12, 2013
Jul 12, 2013
187
188
189
log_debug("Element invalid, discarding\n");
free_elem(list_item);
list_item = 0;
Mar 22, 2011
Mar 22, 2011
190
}
Apr 21, 2011
Apr 21, 2011
191
192
return list_item;
Mar 22, 2011
Mar 22, 2011
193
}
Dec 11, 2013
Dec 11, 2013
194
Oct 22, 2013
Oct 22, 2013
195
/* @return 0 on succes, 1 if there is a failure */
May 10, 2011
May 10, 2011
196
int activate_sync(const char *mode)
Mar 22, 2011
Mar 22, 2011
197
{
Apr 21, 2011
Apr 21, 2011
198
GList *iter;
Jul 7, 2016
Jul 7, 2016
199
int count = 0;
Apr 20, 2011
Apr 20, 2011
200
May 10, 2011
May 10, 2011
201
202
log_debug("activate sync");
Jul 7, 2016
Jul 7, 2016
203
204
/* Get start of activation timestamp */
gettimeofday(&sync_tv, 0);
May 10, 2011
May 10, 2011
205
Apr 21, 2011
Apr 21, 2011
206
207
if( sync_list == 0 )
{
Jul 12, 2013
Jul 12, 2013
208
log_debug("No sync list! Enumerating\n");
Jul 7, 2016
Jul 7, 2016
209
enumerate_usb();
Apr 21, 2011
Apr 21, 2011
210
211
212
return 0;
}
Jul 7, 2016
Jul 7, 2016
213
214
/* Count apps that need to be activated for this mode and
* mark them as currently inactive */
Apr 21, 2011
Apr 21, 2011
215
216
217
for( iter = sync_list; iter; iter = g_list_next(iter) )
{
struct list_elem *data = iter->data;
May 16, 2011
May 16, 2011
218
May 10, 2011
May 10, 2011
219
if(!strcmp(data->mode, mode))
Jul 7, 2016
Jul 7, 2016
220
221
222
223
{
++count;
data->state = APP_STATE_INACTIVE;
}
May 10, 2011
May 10, 2011
224
else
May 16, 2011
May 16, 2011
225
{
Jul 7, 2016
Jul 7, 2016
226
data->state = APP_STATE_DONTCARE;
May 16, 2011
May 16, 2011
227
}
Apr 21, 2011
Apr 21, 2011
228
}
Mar 22, 2011
Mar 22, 2011
229
Jul 7, 2016
Jul 7, 2016
230
231
/* If there is nothing to activate, enumerate immediately */
if(count <= 0)
May 16, 2011
May 16, 2011
232
233
{
log_debug("Nothing to launch.\n");
Jul 7, 2016
Jul 7, 2016
234
enumerate_usb();
Oct 22, 2013
Oct 22, 2013
235
return(0);
May 16, 2011
May 16, 2011
236
237
}
Nov 25, 2013
Nov 25, 2013
238
#ifdef APP_SYNC_DBUS
Jul 12, 2013
Jul 12, 2013
239
/* check dbus initialisation, skip dbus activated services if this fails */
Apr 21, 2011
Apr 21, 2011
240
241
if(!usb_moded_app_sync_init())
{
Jul 12, 2013
Jul 12, 2013
242
243
log_debug("dbus setup failed => skipping dbus launched apps \n");
no_dbus = 1;
Mar 22, 2011
Mar 22, 2011
244
}
Nov 25, 2013
Nov 25, 2013
245
#endif /* APP_SYNC_DBUS */
Mar 22, 2011
Mar 22, 2011
246
May 10, 2011
May 10, 2011
247
/* start timer */
Jul 7, 2016
Jul 7, 2016
248
start_enumerate_usb_timer();
May 10, 2011
May 10, 2011
249
Mar 22, 2011
Mar 22, 2011
250
/* go through list and launch apps */
Apr 21, 2011
Apr 21, 2011
251
252
253
for( iter = sync_list; iter; iter = g_list_next(iter) )
{
struct list_elem *data = iter->data;
May 10, 2011
May 10, 2011
254
255
if(!strcmp(mode, data->mode))
{
Apr 9, 2014
Apr 9, 2014
256
/* do not launch items marked as post, will be launched after usb is up */
Dec 11, 2013
Dec 11, 2013
257
258
259
260
if(data->post)
{
continue;
}
Jul 7, 2016
Jul 7, 2016
261
log_debug("launching pre-enum-app %s\n", data->name);
Jun 5, 2013
Jun 5, 2013
262
263
if(data->systemd)
{
Jun 5, 2013
Jun 5, 2013
264
if(!systemd_control_service(data->name, SYSTEMD_START))
Oct 22, 2013
Oct 22, 2013
265
goto error;
Nov 7, 2016
Nov 7, 2016
266
mark_active(data->name, 0);
Jun 5, 2013
Jun 5, 2013
267
}
Jul 12, 2013
Jul 12, 2013
268
else if(data->launch)
Oct 22, 2013
Oct 22, 2013
269
{
Nov 25, 2013
Nov 25, 2013
270
271
/* skipping if dbus session bus is not available,
or not compiled in */
Jul 12, 2013
Jul 12, 2013
272
if(no_dbus)
Sep 24, 2015
Sep 24, 2015
273
mark_active(data->name, 0);
Nov 25, 2013
Nov 25, 2013
274
#ifdef APP_SYNC_DBUS
Jul 12, 2013
Jul 12, 2013
275
else
Dec 11, 2013
Dec 11, 2013
276
if(!usb_moded_dbus_app_launch(data->launch))
Sep 24, 2015
Sep 24, 2015
277
mark_active(data->name, 0);
Oct 22, 2013
Oct 22, 2013
278
279
else
goto error;
Nov 25, 2013
Nov 25, 2013
280
#endif /* APP_SYNC_DBUS */
Oct 22, 2013
Oct 22, 2013
281
}
May 10, 2011
May 10, 2011
282
}
Apr 21, 2011
Apr 21, 2011
283
}
Mar 22, 2011
Mar 22, 2011
284
285
return(0);
Oct 22, 2013
Oct 22, 2013
286
287
288
289
error:
log_warning("Error launching a service!\n");
return(1);
Mar 22, 2011
Mar 22, 2011
290
291
}
Dec 11, 2013
Dec 11, 2013
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
int activate_sync_post(const char *mode)
{
GList *iter;
log_debug("activate post sync");
if( sync_list == 0 )
{
log_debug("No sync list! skipping post sync\n");
return 0;
}
#ifdef APP_SYNC_DBUS
/* check dbus initialisation, skip dbus activated services if this fails */
if(!usb_moded_app_sync_init())
{
log_debug("dbus setup failed => skipping dbus launched apps \n");
no_dbus = 1;
}
#endif /* APP_SYNC_DBUS */
/* go through list and launch apps */
for( iter = sync_list; iter; iter = g_list_next(iter) )
{
struct list_elem *data = iter->data;
if(!strcmp(mode, data->mode))
{
/* launch only items marked as post, others are already running */
if(!data->post)
continue;
Jul 7, 2016
Jul 7, 2016
322
log_debug("launching post-enum-app %s\n", data->name);
Dec 11, 2013
Dec 11, 2013
323
324
if(data->systemd)
{
Nov 7, 2016
Nov 7, 2016
325
if(!systemd_control_service(data->name, SYSTEMD_START))
Dec 11, 2013
Dec 11, 2013
326
goto error;
Jul 7, 2016
Jul 7, 2016
327
mark_active(data->name, 1);
Dec 11, 2013
Dec 11, 2013
328
329
330
331
332
333
334
335
336
}
else if(data->launch)
{
/* skipping if dbus session bus is not available,
or not compiled in */
if(no_dbus)
continue;
#ifdef APP_SYNC_DBUS
else
Dec 30, 2014
Dec 30, 2014
337
if(usb_moded_dbus_app_launch(data->launch) != 0)
Dec 11, 2013
Dec 11, 2013
338
339
340
341
342
343
344
345
346
347
348
349
350
goto error;
#endif /* APP_SYNC_DBUS */
}
}
}
return(0);
error:
log_warning("Error launching a service!\n");
return(1);
}
Sep 24, 2015
Sep 24, 2015
351
int mark_active(const gchar *name, int post)
Mar 22, 2011
Mar 22, 2011
352
{
Apr 21, 2011
Apr 21, 2011
353
354
355
356
int ret = -1; // assume name not found
int missing = 0;
GList *iter;
Mar 22, 2011
Mar 22, 2011
357
Jul 7, 2016
Jul 7, 2016
358
log_debug("%s-enum-app %s is started\n", post ? "post" : "pre", name);
Apr 21, 2011
Apr 21, 2011
359
360
361
362
for( iter = sync_list; iter; iter = g_list_next(iter) )
{
struct list_elem *data = iter->data;
Jul 7, 2016
Jul 7, 2016
363
Apr 21, 2011
Apr 21, 2011
364
if(!strcmp(data->name, name))
Mar 22, 2011
Mar 22, 2011
365
{
Apr 21, 2011
Apr 21, 2011
366
/* TODO: do we need to worry about duplicate names in the list? */
Jul 7, 2016
Jul 7, 2016
367
368
ret = (data->state != APP_STATE_ACTIVE);
data->state = APP_STATE_ACTIVE;
Apr 21, 2011
Apr 21, 2011
369
370
371
/* updated + missing -> not going to enumerate */
if( missing ) break;
Mar 22, 2011
Mar 22, 2011
372
}
Jul 7, 2016
Jul 7, 2016
373
else if( data->state == APP_STATE_INACTIVE && data->post == post )
Apr 21, 2011
Apr 21, 2011
374
375
{
missing = 1;
Mar 22, 2011
Mar 22, 2011
376
Apr 21, 2011
Apr 21, 2011
377
378
379
380
/* updated + missing -> not going to enumerate */
if( ret != -1 ) break;
}
}
Jul 7, 2016
Jul 7, 2016
381
if( !post && !missing )
Apr 21, 2011
Apr 21, 2011
382
{
Jul 7, 2016
Jul 7, 2016
383
log_debug("All pre-enum-apps active. Let's enumerate\n");
Jul 7, 2016
Jul 7, 2016
384
enumerate_usb();
Apr 21, 2011
Apr 21, 2011
385
386
387
388
}
/* -1=not found, 0=already active, 1=activated now */
return ret;
Mar 22, 2011
Mar 22, 2011
389
390
}
Jul 7, 2016
Jul 7, 2016
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
static gboolean enumerate_usb_cb(gpointer data)
{
(void)data;
enumerate_usb_id = 0;
log_debug("handling enumeration timeout");
enumerate_usb();
/* return false to stop the timer from repeating */
return FALSE;
}
static void start_enumerate_usb_timer(void)
{
log_debug("scheduling enumeration timeout");
if( enumerate_usb_id )
g_source_remove(enumerate_usb_id), enumerate_usb_id = 0;
enumerate_usb_id = g_timeout_add_seconds(2, enumerate_usb_cb, NULL);
}
static void cancel_enumerate_usb_timer(void)
{
if( enumerate_usb_id )
{
log_debug("canceling enumeration timeout");
g_source_remove(enumerate_usb_id), enumerate_usb_id = 0;
}
}
static void enumerate_usb(void)
Mar 22, 2011
Mar 22, 2011
419
{
May 10, 2011
May 10, 2011
420
421
struct timeval tv;
Jul 7, 2016
Jul 7, 2016
422
423
424
/* Stop the timer in case of explicit enumeration call */
cancel_enumerate_usb_timer();
Jul 7, 2016
Jul 7, 2016
425
426
427
428
/* Debug: how long it took from sync start to get here */
gettimeofday(&tv, 0);
timersub(&tv, &sync_tv, &tv);
log_debug("sync to enum: %.3f seconds", tv.tv_sec + tv.tv_usec * 1e-6);
May 10, 2011
May 10, 2011
429
Nov 25, 2013
Nov 25, 2013
430
#ifdef APP_SYNC_DBUS
Jul 7, 2016
Jul 7, 2016
431
432
/* remove dbus service */
usb_moded_appsync_cleanup();
Nov 25, 2013
Nov 25, 2013
433
#endif /* APP_SYNC_DBUS */
Mar 22, 2011
Mar 22, 2011
434
}
Mar 1, 2012
Mar 1, 2012
435
Jul 7, 2016
Jul 7, 2016
436
static void appsync_stop_apps(int post)
Mar 1, 2012
Mar 1, 2012
437
438
439
440
441
442
{
GList *iter = 0;
for( iter = sync_list; iter; iter = g_list_next(iter) )
{
struct list_elem *data = iter->data;
Jun 5, 2013
Jun 5, 2013
443
Jul 7, 2016
Jul 7, 2016
444
if(data->systemd && data->state == APP_STATE_ACTIVE && data->post == post)
Jun 5, 2013
Jun 5, 2013
445
{
Jul 7, 2016
Jul 7, 2016
446
log_debug("stopping %s-enum-app %s", post ? "post" : "pre", data->name);
Nov 7, 2016
Nov 7, 2016
447
if(!systemd_control_service(data->name, SYSTEMD_STOP))
Sep 19, 2013
Sep 19, 2013
448
log_debug("Failed to stop %s\n", data->name);
Jul 7, 2016
Jul 7, 2016
449
data->state = APP_STATE_DONTCARE;
Jul 7, 2016
Jul 7, 2016
450
451
452
453
}
}
}
Nov 7, 2016
Nov 7, 2016
454
int appsync_stop(gboolean force)
Jul 7, 2016
Jul 7, 2016
455
456
457
458
459
460
461
462
463
464
465
{
/* If force arg is used, stop all applications that
* could have been started by usb-moded */
if(force)
{
GList *iter;
log_debug("assuming all applications are active");
for( iter = sync_list; iter; iter = g_list_next(iter) )
{
struct list_elem *data = iter->data;
Jul 7, 2016
Jul 7, 2016
466
data->state = APP_STATE_ACTIVE;
Jun 5, 2013
Jun 5, 2013
467
}
Mar 1, 2012
Mar 1, 2012
468
469
}
Jul 7, 2016
Jul 7, 2016
470
471
472
473
474
475
/* Stop post-apps 1st */
appsync_stop_apps(1);
/* Then pre-apps */
appsync_stop_apps(0);
Jul 7, 2016
Jul 7, 2016
476
477
/* Do not leave active timers behind */
cancel_enumerate_usb_timer();
Mar 1, 2012
Mar 1, 2012
478
479
return(0);
}