usb_moded  0.86.0+mer57
usb_moded-modules.c
Go to the documentation of this file.
1 
31 #include "usb_moded-modules.h"
32 
33 #include "usb_moded-log.h"
34 
35 #include <libkmod.h>
36 
37 #include <glib.h>
38 
39 /* ========================================================================= *
40  * Prototypes
41  * ========================================================================= */
42 
43 /* ------------------------------------------------------------------------- *
44  * MODULES
45  * ------------------------------------------------------------------------- */
46 
47 static bool modules_have_module (const char *module);
48 bool modules_in_use (void);
49 static bool modules_probe (void);
50 bool modules_init (void);
51 void modules_quit (void);
52 int modules_load_module (const char *module);
53 int modules_unload_module(const char *module);
54 
55 /* ========================================================================= *
56  * Data
57  * ========================================================================= */
58 
65 static int modules_probed = -1;
66 
67 /* kmod context - initialized at start in usbmoded_init by ctx_init()
68  * and cleaned up by ctx_cleanup() functions */
69 static struct kmod_ctx *modules_ctx = 0;
70 
71 /* ========================================================================= *
72  * Functions
73  * ========================================================================= */
74 
75 static bool modules_have_module(const char *module)
76 {
77  LOG_REGISTER_CONTEXT;
78 
79  // TODO: not fully untested due to lack of suitable hw
80 
81  bool ack = false;
82  struct kmod_list *list = 0;
83 
84  if( kmod_module_new_from_lookup(modules_ctx, module, &list) < 0 )
85  goto EXIT;
86 
87  if( list == 0 )
88  goto EXIT;
89 
90  ack = true;
91 
92 EXIT:
93  if( list )
94  kmod_module_unref_list(list);
95 
96  log_debug("module %s does%s exist", module, ack ? "" : "not ");
97  return ack;
98 
99 }
100 
101 bool modules_in_use(void)
102 {
103  LOG_REGISTER_CONTEXT;
104 
105  if( modules_probed < 0 )
106  log_debug("modules_in_use() called before modules_probe()");
107 
108  return modules_probed > 0;
109 }
110 
111 static bool modules_probe(void)
112 {
113  LOG_REGISTER_CONTEXT;
114 
115  static const char * const lut[] = {
116  MODULE_MASS_STORAGE,
117  MODULE_FILE_STORAGE,
118  MODULE_DEVELOPER,
119  MODULE_MTP,
120  0
121  };
122 
123  if( modules_probed == -1 ) {
124  modules_probed = false;
125  /* Check if we have at least one of the kernel modules we
126  * expect to use for something.
127  */
128  for( size_t i = 0; lut[i] ; ++i ) {
129  if( modules_have_module(lut[i]) ) {
130  modules_probed = true;
131  break;
132  }
133  }
134  log_warning("MODULES %sdetected", modules_probed ? "" : "not ");
135  }
136 
137  return modules_in_use();
138 }
139 
144 bool modules_init(void)
145 {
146  LOG_REGISTER_CONTEXT;
147 
148  bool ack = false;
149 
150  if( !modules_ctx ) {
151  if( !(modules_ctx = kmod_new(NULL, NULL)) )
152  goto EXIT;
153  }
154 
155  if( kmod_load_resources(modules_ctx) < 0 )
156  goto EXIT;
157 
158  if( !modules_probe() )
159  goto EXIT;
160 
161  ack = true;
162 EXIT:
163  return ack;
164 }
165 
166 /* kmod module cleanup */
167 void modules_quit(void)
168 {
169  LOG_REGISTER_CONTEXT;
170 
171  if( modules_ctx )
172  kmod_unref(modules_ctx), modules_ctx = 0;
173 }
174 
181 int modules_load_module(const char *module)
182 {
183  LOG_REGISTER_CONTEXT;
184 
185  int ret = 0;
186 
187  const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
188  struct kmod_module *mod;
189  char *charging_args = NULL;
190  char *load = NULL;
191 
192  if(!strcmp(module, MODULE_NONE))
193  return 0;
194 
195  if( !modules_in_use() ) {
196  log_warning("load module %s - without module support", module);
197  return -1;
198  }
199 
200  /* copy module to load as it might be modified if we're trying charging mode */
201  load = strdup(module);
202  if(!strcmp(module, MODULE_CHARGING) || !strcmp(module, MODULE_CHARGE_FALLBACK))
203  {
204  /* split the string in module name and argument, they are the same for MODULE_CHARGE_FALLBACK
205  * so no need to handle them separately */
206  gchar **strings;
207 
208  /* since the mass_storage module is the newer one and we check against it to avoid
209  * loading failures we use it here, as we fall back to g_file_storage if g_mass_storage
210  * fails to load */
211  strings = g_strsplit(MODULE_CHARGE_FALLBACK, " ", 2);
212  //log_debug("module args = %s, module = %s\n", strings[1], strings[0]);
213  charging_args = strdup(strings[1]);
214  /* load was already assigned. Free it to re-assign */
215  free(load);
216  load = strdup(strings[0]);
217  g_strfreev(strings);
218 
219  }
220  ret = kmod_module_new_from_name(modules_ctx, load, &mod);
221  /* since kmod_module_new_from_name does not check if the module
222  * exists we test it's path in case we deal with the mass-storage one */
223  if(!strcmp(module, MODULE_MASS_STORAGE) &&
224  (kmod_module_get_path(mod) == NULL))
225  {
226  log_debug("Fallback on older g_file_storage\n");
227  ret = kmod_module_new_from_name(modules_ctx, MODULE_FILE_STORAGE, &mod);
228  }
229 
230  if(!charging_args)
231  ret = kmod_module_probe_insert_module(mod, probe_flags, NULL, NULL, NULL, NULL);
232  else
233  {
234  ret = kmod_module_probe_insert_module(mod, probe_flags, charging_args, NULL, NULL, NULL);
235  free(charging_args);
236  }
237  kmod_module_unref(mod);
238  free(load);
239 
240  if( ret == 0)
241  log_info("Module %s loaded successfully\n", module);
242  else
243  log_info("Module %s failed to load\n", module);
244  return ret;
245 }
246 
253 int modules_unload_module(const char *module)
254 {
255  LOG_REGISTER_CONTEXT;
256 
257  int ret = 0;
258 
259  struct kmod_module *mod;
260 
261  if(!strcmp(module, MODULE_NONE))
262  return 0;
263 
264  if( !modules_in_use() ) {
265  log_warning("unload module %s - without module support", module);
266  return -1;
267  }
268 
269  kmod_module_new_from_name(modules_ctx, module, &mod);
270  ret = kmod_module_remove_module(mod, KMOD_REMOVE_NOWAIT);
271  kmod_module_unref(mod);
272 
273  return ret;
274 }
modules_load_module
int modules_load_module(const char *module)
Definition: usb_moded-modules.c:181
usb_moded-modules.h
modules_init
bool modules_init(void)
Definition: usb_moded-modules.c:144
modules_unload_module
int modules_unload_module(const char *module)
Definition: usb_moded-modules.c:253
usb_moded-log.h