usb_moded 0.86.0+mer64
usb_moded-modules.c
Go to the documentation of this file.
1
30
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
47static bool modules_have_module (const char *module);
48bool modules_in_use (void);
49static bool modules_probe (void);
50bool modules_init (void);
51void modules_quit (void);
52int modules_load_module (const char *module);
53int modules_unload_module(const char *module);
54
55/* ========================================================================= *
56 * Data
57 * ========================================================================= */
58
65static 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 */
69static struct kmod_ctx *modules_ctx = 0;
70
71/* ========================================================================= *
72 * Functions
73 * ========================================================================= */
74
75static 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
92EXIT:
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
101bool 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
111static 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
144bool 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;
162EXIT:
163 return ack;
164}
165
166/* kmod module cleanup */
167void modules_quit(void)
168{
169 LOG_REGISTER_CONTEXT;
170
171 if( modules_ctx )
172 kmod_unref(modules_ctx), modules_ctx = 0;
173}
174
181int 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
253int 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}
int modules_load_module(const char *module)
int modules_unload_module(const char *module)
bool modules_init(void)