usb_moded  0.86.0+mer57
usb_moded-common.c
Go to the documentation of this file.
1 
27 #include "usb_moded-common.h"
28 
29 #include "usb_moded.h"
31 #include "usb_moded-dbus-private.h"
32 #include "usb_moded-log.h"
33 #include "usb_moded-modes.h"
34 #include "usb_moded-worker.h"
35 
36 #include <sys/wait.h>
37 
38 #include <unistd.h>
39 #include <fcntl.h>
40 
41 /* ========================================================================= *
42  * Types
43  * ========================================================================= */
44 
46 typedef struct modemapping_t
47 {
49  const char *internal_mode;
50 
52  const char *hardware_mode;
53 
55  const char *external_mode;
57 
58 /* ========================================================================= *
59  * Prototypes
60  * ========================================================================= */
61 
62 /* ------------------------------------------------------------------------- *
63  * CABLE_STATE
64  * ------------------------------------------------------------------------- */
65 
66 const char *cable_state_repr(cable_state_t state);
67 
68 /* ------------------------------------------------------------------------- *
69  * COMMON
70  * ------------------------------------------------------------------------- */
71 
72 const char *common_map_mode_to_hardware (const char *internal_mode);
73 const char *common_map_mode_to_external (const char *internal_mode);
78 static void common_write_to_sysfs_file (const char *path, const char *text);
79 void common_acquire_wakelock (const char *wakelock_name);
80 void common_release_wakelock (const char *wakelock_name);
81 int common_system_ (const char *file, int line, const char *func, const char *command);
82 FILE *common_popen_ (const char *file, int line, const char *func, const char *command, const char *type);
83 waitres_t common_wait (unsigned tot_ms, bool (*ready_cb)(void *aptr), void *aptr);
84 bool common_msleep_ (const char *file, int line, const char *func, unsigned msec);
85 static bool common_mode_in_list (const char *mode, char *const *modes);
86 bool common_modename_is_internal (const char *modename);
87 bool common_modename_is_static (const char *modename);
88 int common_valid_mode (const char *mode);
89 gchar *common_get_mode_list (mode_list_type_t type, uid_t uid);
90 
91 /* ========================================================================= *
92  * Functions
93  * ========================================================================= */
94 
95 /* ------------------------------------------------------------------------- *
96  * CABLE_STATE
97  * ------------------------------------------------------------------------- */
98 
99 const char *cable_state_repr(cable_state_t state)
100 {
101  LOG_REGISTER_CONTEXT;
102 
103  static const char * const lut[CABLE_STATE_NUMOF] = {
104  [CABLE_STATE_UNKNOWN] = "unknown",
105  [CABLE_STATE_DISCONNECTED] = "disconnected",
106  [CABLE_STATE_CHARGER_CONNECTED] = "charger_connected",
107  [CABLE_STATE_PC_CONNECTED] = "pc_connected",
108  };
109  return lut[state];
110 }
111 
112 /* ------------------------------------------------------------------------- *
113  * MODE_MAPPING
114  * ------------------------------------------------------------------------- */
115 
116 static const modemapping_t common_modemapping[] =
117 {
118  {
120  .hardware_mode = MODE_CHARGING,
121  .external_mode = 0,
122  },
123  {
124  .internal_mode = MODE_ASK,
125  .hardware_mode = MODE_CHARGING,
126  .external_mode = 0,
127  },
128  {
129  .internal_mode = MODE_MASS_STORAGE,
130  .hardware_mode = 0,
131  .external_mode = 0,
132  },
133  {
134  .internal_mode = MODE_DEVELOPER,
135  .hardware_mode = 0,
136  .external_mode = 0,
137  },
138  {
139  .internal_mode = MODE_MTP,
140  .hardware_mode = 0,
141  .external_mode = 0,
142  },
143  {
144  .internal_mode = MODE_HOST,
145  .hardware_mode = 0,
146  .external_mode = 0,
147  },
148  {
149  .internal_mode = MODE_CONNECTION_SHARING,
150  .hardware_mode = 0,
151  .external_mode = 0,
152  },
153  {
154  .internal_mode = MODE_DIAG,
155  .hardware_mode = 0,
156  .external_mode = 0,
157  },
158  {
159  .internal_mode = MODE_ADB,
160  .hardware_mode = 0,
161  .external_mode = 0,
162  },
163  {
164  .internal_mode = MODE_PC_SUITE,
165  .hardware_mode = 0,
166  .external_mode = 0,
167  },
168  {
169  .internal_mode = MODE_CHARGING,
170  .hardware_mode = MODE_CHARGING,
171  .external_mode = 0,
172  },
173  {
174  .internal_mode = MODE_CHARGING_FALLBACK,
175  .hardware_mode = MODE_CHARGING,
176  .external_mode = 0,
177  },
178  {
179  .internal_mode = MODE_CHARGER,
180  .hardware_mode = MODE_CHARGING,
181  .external_mode = 0,
182  },
183  // sentinel
184  {
185  .internal_mode = 0,
186  .hardware_mode = 0,
187  .external_mode = 0,
188  }
189 };
190 
191 const char *
192 common_map_mode_to_hardware(const char *internal_mode)
193 {
194  LOG_REGISTER_CONTEXT;
195 
196  const char *hardware_mode = 0;
197 
198  for( size_t i = 0; common_modemapping[i].internal_mode; ++i ) {
199  if( strcmp(common_modemapping[i].internal_mode, internal_mode) )
200  continue;
201  hardware_mode = common_modemapping[i].hardware_mode;
202  break;
203  }
204  return hardware_mode ?: internal_mode;
205 }
206 
207 const char *
208 common_map_mode_to_external(const char *internal_mode)
209 {
210  LOG_REGISTER_CONTEXT;
211 
212  const char *external_mode = 0;
213 
214  for( size_t i = 0; common_modemapping[i].internal_mode; ++i ) {
215  if( strcmp(common_modemapping[i].internal_mode, internal_mode) )
216  continue;
217  external_mode = common_modemapping[i].external_mode;
218  break;
219  }
220  return external_mode ?: internal_mode;
221 }
222 
223 /* ------------------------------------------------------------------------- *
224  * DBUS_NOTIFICATIONS
225  * ------------------------------------------------------------------------- */
226 
230 {
231  LOG_REGISTER_CONTEXT;
232 
233  gchar *mode_list = common_get_mode_list(SUPPORTED_MODES_LIST, 0);
235  g_free(mode_list);
236 }
237 
241 {
242  LOG_REGISTER_CONTEXT;
243 
244  gchar *mode_list = common_get_mode_list(AVAILABLE_MODES_LIST, 0);
246  g_free(mode_list);
247 }
248 
252 {
253  LOG_REGISTER_CONTEXT;
254 
255  gchar *mode_list = config_get_hidden_modes();
257  g_free(mode_list);
258 }
259 
263 {
264  LOG_REGISTER_CONTEXT;
265 
266  gchar *mode_list = config_get_mode_whitelist();
268  g_free(mode_list);
269 }
270 
271 /* ------------------------------------------------------------------------- *
272  * SYSFS_IO
273  * ------------------------------------------------------------------------- */
274 
282 static void common_write_to_sysfs_file(const char *path, const char *text)
283 {
284  LOG_REGISTER_CONTEXT;
285 
286  int fd = -1;
287 
288  if (!path || !text)
289  goto EXIT;
290 
291  if ((fd = open(path, O_WRONLY)) == -1) {
292  if (errno != ENOENT) {
293  log_warning("%s: open for writing failed: %m", path);
294  }
295  goto EXIT;
296  }
297 
298  if (write(fd, text, strlen(text)) == -1) {
299  log_warning("%s: write failed : %m", path);
300  goto EXIT;
301  }
302 EXIT:
303  if (fd != -1)
304  close(fd);
305 }
306 
307 /* ------------------------------------------------------------------------- *
308  * WAKELOCKS
309  * ------------------------------------------------------------------------- */
310 
323 void common_acquire_wakelock(const char *wakelock_name)
324 {
325  LOG_REGISTER_CONTEXT;
326 
327  char buff[256];
328  snprintf(buff, sizeof buff, "%s %lld",
329  wakelock_name,
331  common_write_to_sysfs_file("/sys/power/wake_lock", buff);
332 
333 #if VERBOSE_WAKELOCKING
334  log_debug("common_acquire_wakelock %s", wakelock_name);
335 #endif
336 }
337 
342 void common_release_wakelock(const char *wakelock_name)
343 {
344  LOG_REGISTER_CONTEXT;
345 
346 #if VERBOSE_WAKELOCKING
347  log_debug("common_release_wakelock %s", wakelock_name);
348 #endif
349 
350  common_write_to_sysfs_file("/sys/power/wake_unlock", wakelock_name);
351 }
352 
353 /* ------------------------------------------------------------------------- *
354  * BLOCKING_OPERATION
355  * ------------------------------------------------------------------------- */
356 
359 int
360 common_system_(const char *file, int line, const char *func,
361  const char *command)
362 {
363  LOG_REGISTER_CONTEXT;
364 
365  int result = -1;
366  int status = -1;
367  char exited[32] = "";
368  char trapped[32] = "";
369  const char *dumped = "";
370 
371  log_debug("EXEC %s; from %s:%d: %s()", command, file, line, func);
372 
373  if( (status = system(command)) == -1 ) {
374  snprintf(exited, sizeof exited, " exec=failed");
375  }
376  else {
377  if( WIFSIGNALED(status) ) {
378  snprintf(trapped, sizeof trapped, " signal=%s",
379  strsignal(WTERMSIG(status)));
380  }
381 
382  if( WCOREDUMP(status) )
383  dumped = " core=dumped";
384 
385  if( WIFEXITED(status) ) {
386  result = WEXITSTATUS(status);
387  snprintf(exited, sizeof exited, " exit_code=%d", result);
388  }
389  }
390 
391  if( result != 0 ) {
392  log_warning("EXEC %s; from %s:%d: %s();%s%s%s result=%d",
393  command, file, line, func,
394  exited, trapped, dumped, result);
395  }
396 
397  return result;
398 }
399 
402 FILE *
403 common_popen_(const char *file, int line, const char *func,
404  const char *command, const char *type)
405 {
406  LOG_REGISTER_CONTEXT;
407 
408  log_debug("EXEC %s; from %s:%d: %s()",
409  command, file, line, func);
410 
411  return popen(command, type);
412 }
413 
414 waitres_t
415 common_wait(unsigned tot_ms, bool (*ready_cb)(void *aptr), void *aptr)
416 {
417  LOG_REGISTER_CONTEXT;
418 
419  struct timespec ts;
420 
421  waitres_t res = WAIT_FAILED;
422 
423  for( ;; ) {
424  unsigned nap_ms = (tot_ms > 200) ? 200 : tot_ms;
425 
426  ts.tv_sec = (nap_ms / 1000);
427  ts.tv_nsec = (nap_ms % 1000);
428  ts.tv_nsec *= 1000 * 1000;
429 
430  for( ;; ) {
431  if( ready_cb && ready_cb(aptr) ) {
432  res = WAIT_READY;
433  goto EXIT;
434  }
435 
436  if( tot_ms <= 0 ) {
437  res = WAIT_TIMEOUT;
438  goto EXIT;
439  }
440 
441  if( worker_bailing_out() ) {
442  log_warning("wait canceled");
443  goto EXIT;
444  }
445 
446  if( nanosleep(&ts, &ts) == 0 )
447  break;
448 
449  if( errno != EINTR ) {
450  log_warning("wait failed: %m");
451  goto EXIT;
452  }
453  }
454 
455  tot_ms -= nap_ms;
456  }
457 
458 EXIT:
459  return res;
460 }
461 
464 bool
465 common_msleep_(const char *file, int line, const char *func, unsigned msec)
466 {
467  LOG_REGISTER_CONTEXT;
468 
469  log_debug("SLEEP %u.%03u seconds; from %s:%d: %s()",
470  msec / 1000u, msec % 1000u,file, line, func);
471  return common_wait(msec, 0, 0) == WAIT_TIMEOUT;
472 }
473 
474 /* ------------------------------------------------------------------------- *
475  * MISC
476  * ------------------------------------------------------------------------- */
477 
478 /* check if a mode is in a list */
479 static bool common_mode_in_list(const char *mode, char * const *modes)
480 {
481  LOG_REGISTER_CONTEXT;
482 
483  int i;
484 
485  if (!modes)
486  return false;
487 
488  for(i = 0; modes[i] != NULL; i++)
489  {
490  if(!strcmp(modes[i], mode))
491  return true;
492  }
493  return false;
494 }
495 
502 bool
503 common_modename_is_internal(const char *modename)
504 {
505  LOG_REGISTER_CONTEXT;
506 
507  return (common_modename_is_static(modename) ||
508  !g_strcmp0(modename, MODE_ASK) ||
509  !g_strcmp0(modename, MODE_BUSY));
510 }
511 
518 bool
519 common_modename_is_static(const char *modename)
520 {
521  LOG_REGISTER_CONTEXT;
522 
523  return (!g_strcmp0(modename, MODE_UNDEFINED) ||
524  !g_strcmp0(modename, MODE_CHARGER) ||
525  !g_strcmp0(modename, MODE_CHARGING_FALLBACK) ||
526  !g_strcmp0(modename, MODE_CHARGING));
527 }
528 
535 int common_valid_mode(const char *mode)
536 {
537  LOG_REGISTER_CONTEXT;
538 
539  int valid = 1;
540  /* MODE_ASK, MODE_CHARGER and MODE_CHARGING_FALLBACK are not modes that are settable seen their special 'internal' status
541  * so we only check the modes that are announed outside. Only exception is the built in MODE_CHARGING */
542  if(!strcmp(MODE_CHARGING, mode)) {
543  valid = 0;
544  }
545  else
546  {
547  const modedata_t *data = usbmoded_get_modedata(mode);
548 
549  if( data ) {
550  gchar *whitelist_value = 0;
551  gchar **whitelist_array = 0;
552 
553  if( (whitelist_value = config_get_mode_whitelist()) )
554  whitelist_array = g_strsplit(whitelist_value, ",", 0);
555 
556  if (!whitelist_array || common_mode_in_list(data->mode_name, whitelist_array))
557  valid = 0;
558 
559  g_strfreev(whitelist_array);
560  g_free(whitelist_value);
561  }
562  }
563  return valid;
564 }
565 
574 gchar *common_get_mode_list(mode_list_type_t type, uid_t uid)
575 {
576  LOG_REGISTER_CONTEXT;
577 
578  GString *mode_list_str = g_string_new(NULL);
579 
580  gchar *hidden_modes_value = 0;
581  gchar **hidden_modes_array = 0;
582 
583  gchar *whitelist_value = 0;
584  gchar **whitelist_array = 0;
585 
586  if( usbmoded_get_diag_mode() )
587  {
588  /* diag mode. there is only one active mode */
589  g_string_append(mode_list_str, MODE_DIAG);
590  goto EXIT;
591  }
592 
593  if( (hidden_modes_value = config_get_hidden_modes()) )
594  hidden_modes_array = g_strsplit(hidden_modes_value, ",", 0);
595 
596  switch( type ) {
598  /* All modes that are not hidden */
599  break;
600 
602  /* All whitelisted modes that are not hidden */
603  if( (whitelist_value = config_get_mode_whitelist()) )
604  whitelist_array = g_strsplit(whitelist_value, ",", 0);
605  break;
606  }
607 
608  for( GList *iter = usbmoded_get_modelist(); iter; iter = g_list_next(iter) )
609  {
610  modedata_t *data = iter->data;
611 
612  /* skip dynamic modes that are not allowed */
613  if (!usbmoded_is_mode_permitted(data->mode_name, uid))
614  continue;
615 
616  /* skip items in the hidden list */
617  if (common_mode_in_list(data->mode_name, hidden_modes_array))
618  continue;
619 
620  /* if there is a whitelist skip items not in the list */
621  if (whitelist_array && !common_mode_in_list(data->mode_name, whitelist_array))
622  continue;
623 
624  g_string_append(mode_list_str, data->mode_name);
625  g_string_append(mode_list_str, ", ");
626  }
627 
628  /* End with charging mode */
629  g_string_append(mode_list_str, MODE_CHARGING);
630 
631 EXIT:
632  g_strfreev(whitelist_array);
633  g_free(whitelist_value);
634 
635  g_strfreev(hidden_modes_array);
636  g_free(hidden_modes_value);
637 
638  return g_string_free(mode_list_str, false);
639 }
modedata_t::mode_name
gchar * mode_name
Definition: usb_moded-dyn-config.h:102
usb_moded-dbus-private.h
usb_moded-modes.h
common_msleep_
bool common_msleep_(const char *file, int line, const char *func, unsigned msec)
Definition: usb_moded-common.c:465
MODE_BUSY
#define MODE_BUSY
Definition: usb_moded-modes.h:57
modemapping_t::hardware_mode
const char * hardware_mode
Definition: usb_moded-common.c:52
common_send_whitelisted_modes_signal
void common_send_whitelisted_modes_signal(void)
Definition: usb_moded-common.c:262
umdbus_send_supported_modes_signal
int umdbus_send_supported_modes_signal(const char *supported_modes)
Definition: usb_moded-dbus.c:1832
common_modename_is_internal
bool common_modename_is_internal(const char *modename)
Definition: usb_moded-common.c:503
AVAILABLE_MODES_LIST
@ AVAILABLE_MODES_LIST
Definition: usb_moded-common.h:45
MODE_ASK
#define MODE_ASK
Definition: usb_moded-modes.h:74
common_modename_is_static
bool common_modename_is_static(const char *modename)
Definition: usb_moded-common.c:519
MODE_CHARGING_FALLBACK
#define MODE_CHARGING_FALLBACK
Definition: usb_moded-modes.h:67
usb_moded-config-private.h
usb_moded.h
MODE_CHARGER
#define MODE_CHARGER
Definition: usb_moded-modes.h:60
usbmoded_get_modedata
const modedata_t * usbmoded_get_modedata(const char *modename)
Definition: usb_moded.c:252
common_valid_mode
int common_valid_mode(const char *mode)
Definition: usb_moded-common.c:535
modemapping_t
Definition: usb_moded-common.c:46
umdbus_send_whitelisted_modes_signal
int umdbus_send_whitelisted_modes_signal(const char *whitelist)
Definition: usb_moded-dbus.c:1873
modemapping_t::external_mode
const char * external_mode
Definition: usb_moded-common.c:55
common_send_available_modes_signal
void common_send_available_modes_signal(void)
Definition: usb_moded-common.c:240
umdbus_send_available_modes_signal
int umdbus_send_available_modes_signal(const char *available_modes)
Definition: usb_moded-dbus.c:1846
common_acquire_wakelock
void common_acquire_wakelock(const char *wakelock_name)
Definition: usb_moded-common.c:323
USB_MODED_SUSPEND_DELAY_MAXIMUM_MS
#define USB_MODED_SUSPEND_DELAY_MAXIMUM_MS
Definition: usb_moded.h:56
MODE_UNDEFINED
#define MODE_UNDEFINED
Definition: usb_moded-modes.h:51
common_get_mode_list
gchar * common_get_mode_list(mode_list_type_t type, uid_t uid)
Definition: usb_moded-common.c:574
modemapping_t
struct modemapping_t modemapping_t
umdbus_send_hidden_modes_signal
int umdbus_send_hidden_modes_signal(const char *hidden_modes)
Definition: usb_moded-dbus.c:1860
usb_moded-common.h
usb_moded-log.h
modemapping_t::internal_mode
const char * internal_mode
Definition: usb_moded-common.c:49
usbmoded_get_modelist
GList * usbmoded_get_modelist(void)
Definition: usb_moded.c:197
modedata_t
Definition: usb_moded-dyn-config.h:100
common_popen_
FILE * common_popen_(const char *file, int line, const char *func, const char *command, const char *type)
Definition: usb_moded-common.c:403
SUPPORTED_MODES_LIST
@ SUPPORTED_MODES_LIST
Definition: usb_moded-common.h:43
MODE_CHARGING
#define MODE_CHARGING
Definition: usb_moded-modes.h:77
common_send_supported_modes_signal
void common_send_supported_modes_signal(void)
Definition: usb_moded-common.c:229
usb_moded-worker.h
mode_list_type_t
mode_list_type_t
Definition: usb_moded-common.h:41
common_send_hidden_modes_signal
void common_send_hidden_modes_signal(void)
Definition: usb_moded-common.c:251
common_system_
int common_system_(const char *file, int line, const char *func, const char *command)
Definition: usb_moded-common.c:360
common_release_wakelock
void common_release_wakelock(const char *wakelock_name)
Definition: usb_moded-common.c:342