42 #define DEFAULT_GADGET_BASE_DIRECTORY "/config/usb_gadget/g1"
43 #define DEFAULT_GADGET_FUNC_DIRECTORY "functions"
44 #define DEFAULT_GADGET_CONF_DIRECTORY "configs/b.1"
46 #define DEFAULT_GADGET_CTRL_UDC "UDC"
47 #define DEFAULT_GADGET_CTRL_ID_VENDOR "idVendor"
48 #define DEFAULT_GADGET_CTRL_ID_PRODUCT "idProduct"
49 #define DEFAULT_GADGET_CTRL_MANUFACTURER "strings/0x409/manufacturer"
50 #define DEFAULT_GADGET_CTRL_PRODUCT "strings/0x409/product"
51 #define DEFAULT_GADGET_CTRL_SERIAL "strings/0x409/serialnumber"
53 #define DEFAULT_FUNCTION_MASS_STORAGE "mass_storage.usb0"
54 #define DEFAULT_FUNCTION_RNDIS "rndis_bam.rndis"
55 #define DEFAULT_FUNCTION_MTP "ffs.mtp"
56 #define DEFAULT_FUNCTION_ADB "ffs.adb"
58 #define DEFAULT_RNDIS_CTRL_WCEIS "wceis"
59 #define DEFAULT_RNDIS_CTRL_ETHADDR "ethaddr"
69 static gchar *configfs_get_conf (
const char *key,
const char *def);
70 static void configfs_read_configuration (
void);
71 static int configfs_file_type (
const char *path);
72 static const char *configfs_function_path (
char *buff,
size_t size,
const char *func, ...);
73 static const char *configfs_unit_path (
char *buff,
size_t size,
const char *func,
const char *unit);
74 static const char *configfs_config_path (
char *buff,
size_t size,
const char *func);
75 static bool configfs_mkdir (
const char *path);
76 static bool configfs_rmdir (
const char *path);
77 static const char *configfs_register_function (
const char *
function);
79 static bool configfs_unregister_function (
const char *
function);
81 static const char *configfs_add_unit (
const char *
function,
const char *unit);
82 static bool configfs_remove_unit (
const char *
function,
const char *unit);
83 static bool configfs_enable_function (
const char *
function);
84 static bool configfs_disable_function (
const char *
function);
85 static bool configfs_disable_all_functions (
void);
86 static char *configfs_strip (
char *str);
87 bool configfs_in_use (
void);
88 static bool configfs_probe (
void);
89 static const char *configfs_udc_enable_value (
void);
90 static bool configfs_write_file (
const char *path,
const char *text);
91 static bool configfs_read_file (
const char *path,
char *buff,
size_t size);
93 static bool configfs_read_udc (
char *buff,
size_t size);
95 static bool configfs_write_udc (
const char *text);
96 bool configfs_set_udc (
bool enable);
99 bool configfs_set_charging_mode (
void);
100 bool configfs_set_productid (
const char *
id);
101 bool configfs_set_vendorid (
const char *
id);
102 static const char *configfs_map_function (
const char *func);
103 bool configfs_set_function (
const char *functions);
104 bool configfs_add_mass_storage_lun (
int lun);
105 bool configfs_remove_mass_storage_lun(
int lun);
106 bool configfs_set_mass_storage_attr (
int lun,
const char *attr,
const char *value);
112 static int configfs_probed = -1;
114 static gchar *GADGET_BASE_DIRECTORY = 0;
115 static gchar *GADGET_FUNC_DIRECTORY = 0;
116 static gchar *GADGET_CONF_DIRECTORY = 0;
118 static gchar *GADGET_CTRL_UDC = 0;
119 static gchar *GADGET_CTRL_ID_VENDOR = 0;
120 static gchar *GADGET_CTRL_ID_PRODUCT = 0;
121 static gchar *GADGET_CTRL_MANUFACTURER = 0;
122 static gchar *GADGET_CTRL_PRODUCT = 0;
123 static gchar *GADGET_CTRL_SERIAL = 0;
125 static gchar *FUNCTION_MASS_STORAGE = 0;
126 static gchar *FUNCTION_RNDIS = 0;
127 static gchar *FUNCTION_MTP = 0;
128 static gchar *FUNCTION_ADB = 0;
130 static gchar *RNDIS_CTRL_WCEIS = 0;
131 static gchar *RNDIS_CTRL_ETHADDR = 0;
137 static gchar *configfs_get_conf(
const char *key,
const char *def)
139 LOG_REGISTER_CONTEXT;
141 return config_get_conf_string(
"configfs", key) ?: g_strdup(def);
156 static void configfs_read_configuration(
void)
158 LOG_REGISTER_CONTEXT;
162 static bool done =
false;
173 GADGET_BASE_DIRECTORY =
174 configfs_get_conf(
"gadget_base_directory",
175 DEFAULT_GADGET_BASE_DIRECTORY);
177 temp_setting = configfs_get_conf(
"gadget_func_directory",
178 DEFAULT_GADGET_FUNC_DIRECTORY);
179 GADGET_FUNC_DIRECTORY = g_strdup_printf(
"%s/%s",
180 GADGET_BASE_DIRECTORY,
182 g_free(temp_setting);
184 temp_setting = configfs_get_conf(
"gadget_conf_directory",
185 DEFAULT_GADGET_CONF_DIRECTORY);
186 GADGET_CONF_DIRECTORY =
187 g_strdup_printf(
"%s/%s",
188 GADGET_BASE_DIRECTORY,
190 g_free(temp_setting);
195 g_strdup_printf(
"%s/%s",
196 GADGET_BASE_DIRECTORY,
197 DEFAULT_GADGET_CTRL_UDC);
199 GADGET_CTRL_ID_VENDOR =
200 g_strdup_printf(
"%s/%s",
201 GADGET_BASE_DIRECTORY,
202 DEFAULT_GADGET_CTRL_ID_VENDOR);
204 GADGET_CTRL_ID_PRODUCT =
205 g_strdup_printf(
"%s/%s",
206 GADGET_BASE_DIRECTORY,
207 DEFAULT_GADGET_CTRL_ID_PRODUCT);
209 GADGET_CTRL_MANUFACTURER =
210 g_strdup_printf(
"%s/%s",
211 GADGET_BASE_DIRECTORY,
212 DEFAULT_GADGET_CTRL_MANUFACTURER);
214 GADGET_CTRL_PRODUCT =
215 g_strdup_printf(
"%s/%s",
216 GADGET_BASE_DIRECTORY,
217 DEFAULT_GADGET_CTRL_PRODUCT);
220 g_strdup_printf(
"%s/%s",
221 GADGET_BASE_DIRECTORY,
222 DEFAULT_GADGET_CTRL_SERIAL);
226 FUNCTION_MASS_STORAGE =
227 configfs_get_conf(
"function_mass_storage",
228 DEFAULT_FUNCTION_MASS_STORAGE);
231 configfs_get_conf(
"function_rndis",
232 DEFAULT_FUNCTION_RNDIS);
235 configfs_get_conf(
"function_mtp",
236 DEFAULT_FUNCTION_MTP);
239 configfs_get_conf(
"function_adb",
240 DEFAULT_FUNCTION_ADB);
244 g_strdup_printf(
"%s/%s/%s",
245 GADGET_FUNC_DIRECTORY,
247 DEFAULT_RNDIS_CTRL_WCEIS);
250 g_strdup_printf(
"%s/%s/%s",
251 GADGET_FUNC_DIRECTORY,
253 DEFAULT_RNDIS_CTRL_ETHADDR);
263 static int configfs_file_type(
const char *path)
265 LOG_REGISTER_CONTEXT;
273 if( lstat(path, &st) == -1 )
276 type = st.st_mode & S_IFMT;
283 configfs_function_path(
char *buff,
size_t size,
const char *func, ...)
285 LOG_REGISTER_CONTEXT;
288 char *end = buff + size;
290 snprintf(pos, end-pos,
"%s", GADGET_FUNC_DIRECTORY);
295 pos = strchr(pos, 0);
296 snprintf(pos, end-pos,
"/%s", func);
297 func = va_arg(va,
char *);
305 configfs_unit_path(
char *buff,
size_t size,
const char *func,
const char *unit)
307 LOG_REGISTER_CONTEXT;
309 return configfs_function_path(buff, size, func, unit, NULL);
313 configfs_config_path(
char *buff,
size_t size,
const char *func)
315 LOG_REGISTER_CONTEXT;
317 snprintf(buff, size,
"%s/%s", GADGET_CONF_DIRECTORY, func);
322 configfs_mkdir(
const char *path)
324 LOG_REGISTER_CONTEXT;
328 if( mkdir(path, 0775) == -1 && errno != EEXIST ) {
329 log_err(
"%s: mkdir failed: %m", path);
333 if( configfs_file_type(path) != S_IFDIR ) {
334 log_err(
"%s: is not a directory", path);
345 configfs_rmdir(
const char *path)
347 LOG_REGISTER_CONTEXT;
351 if( rmdir(path) == -1 && errno != ENOENT ) {
352 log_err(
"%s: rmdir failed: %m", path);
363 configfs_register_function(
const char *
function)
365 LOG_REGISTER_CONTEXT;
369 static char fpath[PATH_MAX];
370 configfs_function_path(fpath,
sizeof fpath,
function, NULL);
372 if( !configfs_mkdir(fpath) )
375 log_debug(
"function %s is registered",
function);
385 configfs_unregister_function(
const char *
function)
387 LOG_REGISTER_CONTEXT;
391 char fpath[PATH_MAX];
392 configfs_function_path(fpath,
sizeof fpath,
function, NULL);
394 if( !configfs_rmdir(fpath) )
397 log_debug(
"function %s is unregistered",
function);
406 configfs_add_unit(
const char *
function,
const char *unit)
408 LOG_REGISTER_CONTEXT;
412 static char upath[PATH_MAX];
413 configfs_unit_path(upath,
sizeof upath,
function, unit);
415 if( !configfs_mkdir(upath) )
418 log_debug(
"function %s unit %s added",
function, unit);
427 configfs_remove_unit(
const char *
function,
const char *unit)
429 LOG_REGISTER_CONTEXT;
433 static char upath[PATH_MAX];
434 configfs_unit_path(upath,
sizeof upath,
function, unit);
436 if( !configfs_rmdir(upath) )
439 log_debug(
"function %s unit %s removed",
function, unit);
448 configfs_enable_function(
const char *
function)
450 LOG_REGISTER_CONTEXT;
454 const char *fpath = configfs_register_function(
function);
456 log_err(
"function %s is not registered",
function);
460 char cpath[PATH_MAX];
461 configfs_config_path(cpath,
sizeof cpath,
function);
463 switch( configfs_file_type(cpath) ) {
465 if( unlink(cpath) == -1 ) {
466 log_err(
"%s: unlink failed: %m", cpath);
471 if( symlink(fpath, cpath) == -1 ) {
472 log_err(
"%s: failed to symlink to %s: %m", cpath, fpath);
477 log_err(
"%s: is not a symlink", cpath);
481 log_debug(
"function %s is enabled",
function);
489 configfs_disable_function(
const char *
function)
491 LOG_REGISTER_CONTEXT;
495 char cpath[PATH_MAX];
496 configfs_config_path(cpath,
sizeof cpath,
function);
498 if( configfs_file_type(cpath) != S_IFLNK ) {
499 log_err(
"%s: is not a symlink", cpath);
503 if( unlink(cpath) == -1 ) {
504 log_err(
"%s: unlink failed: %m", cpath);
508 log_debug(
"function %s is disabled",
function);
516 configfs_disable_all_functions(
void)
518 LOG_REGISTER_CONTEXT;
523 if( !(dir = opendir(GADGET_CONF_DIRECTORY)) ) {
524 log_err(
"%s: opendir failed: %m", GADGET_CONF_DIRECTORY);
531 while( (de = readdir(dir)) ) {
532 if( de->d_type != DT_LNK )
535 if( !configfs_disable_function(de->d_name) )
540 log_debug(
"all functions are disabled");
549 static char *configfs_strip(
char *str)
551 LOG_REGISTER_CONTEXT;
553 unsigned char *src = (
unsigned char *)str;
554 unsigned char *dst = (
unsigned char *)str;
556 while( *src > 0 && *src <= 32 ) ++src;
560 while( *src > 32 ) *dst++ = *src++;
561 while( *src > 0 && *src <= 32 ) ++src;
562 if( *src == 0 )
break;
570 configfs_in_use(
void)
572 LOG_REGISTER_CONTEXT;
574 if( configfs_probed < 0 )
575 log_debug(
"configfs_in_use() called before configfs_probe()");
576 return configfs_probed > 0;
582 LOG_REGISTER_CONTEXT;
584 configfs_read_configuration();
586 if( configfs_probed <= 0 ) {
587 configfs_probed = (access(GADGET_BASE_DIRECTORY, F_OK) == 0 &&
588 access(GADGET_CTRL_UDC, F_OK) == 0);
589 log_warning(
"CONFIGFS %sdetected", configfs_probed ?
"" :
"not ");
591 return configfs_in_use();
595 configfs_udc_enable_value(
void)
597 LOG_REGISTER_CONTEXT;
599 static bool probed =
false;
600 static char *value = 0;
607 DIR *dir = opendir(
"/sys/class/udc");
609 while( (de = readdir(dir)) ) {
610 if( de->d_type != DT_LNK )
612 if( de->d_name[0] ==
'.' )
614 value = strdup(de->d_name);
625 configfs_write_file(
const char *path,
const char *text)
627 LOG_REGISTER_CONTEXT;
635 log_debug(
"WRITE %s '%s'", path, text);
638 snprintf(buff,
sizeof buff,
"%s\n", text);
639 size_t size = strlen(buff);
641 if( (fd = open(path, O_WRONLY)) == -1 ) {
642 log_err(
"%s: can't open for writing: %m", path);
646 int rc = write(fd, buff, size);
648 log_err(
"%s: write failure: %m", path);
652 if( (
size_t)rc != size ) {
653 log_err(
"%s: write failure: partial success", path);
667 configfs_read_file(
const char *path,
char *buff,
size_t size)
669 LOG_REGISTER_CONTEXT;
680 if( (fd = open(path, O_RDONLY)) == -1 ) {
681 log_err(
"%s: can't open for reading: %m", path);
685 int rc = read(fd, buff, size - 1);
687 log_err(
"%s: read failure: %m", path);
692 configfs_strip(buff);
696 log_debug(
"READ %s '%s'", path, buff);
707 configfs_read_udc(
char *buff,
size_t size)
709 LOG_REGISTER_CONTEXT;
711 return configfs_read_file(GADGET_CTRL_UDC, buff, size);
716 configfs_write_udc(
const char *text)
718 LOG_REGISTER_CONTEXT;
724 if( !configfs_read_file(GADGET_CTRL_UDC, prev,
sizeof prev) )
727 if( strcmp(prev, text) ) {
728 if( !configfs_write_file(GADGET_CTRL_UDC, text) )
740 configfs_set_udc(
bool enable)
742 LOG_REGISTER_CONTEXT;
744 log_debug(
"UDC - %s", enable ?
"ENABLE" :
"DISABLE");
746 const char *value =
"";
749 value = configfs_udc_enable_value();
751 return configfs_write_udc(value);
761 LOG_REGISTER_CONTEXT;
763 if( !configfs_probe() )
767 configfs_set_udc(
false);
771 if( (text = config_get_android_vendor_id()) ) {
772 configfs_write_file(GADGET_CTRL_ID_VENDOR, text);
776 if( (text = config_get_android_product_id()) ) {
777 configfs_write_file(GADGET_CTRL_ID_PRODUCT, text);
781 if( (text = config_get_android_manufacturer()) ) {
782 configfs_write_file(GADGET_CTRL_MANUFACTURER, text);
786 if( (text = config_get_android_product()) ) {
787 configfs_write_file(GADGET_CTRL_PRODUCT, text);
792 configfs_write_file(GADGET_CTRL_SERIAL, text);
797 configfs_register_function(FUNCTION_MASS_STORAGE);
800 configfs_register_function(FUNCTION_MTP);
803 configfs_register_function(FUNCTION_RNDIS);
804 if( (text = mac_read_mac()) ) {
805 configfs_write_file(RNDIS_CTRL_ETHADDR, text);
809 configfs_write_file(RNDIS_CTRL_WCEIS,
"1");
813 return configfs_in_use();
821 g_free(GADGET_BASE_DIRECTORY),
822 GADGET_BASE_DIRECTORY = 0;
823 g_free(GADGET_FUNC_DIRECTORY),
824 GADGET_FUNC_DIRECTORY = 0;
825 g_free(GADGET_CONF_DIRECTORY),
826 GADGET_CONF_DIRECTORY = 0;
828 g_free(GADGET_CTRL_UDC),
830 g_free(GADGET_CTRL_ID_VENDOR),
831 GADGET_CTRL_ID_VENDOR= 0;
832 g_free(GADGET_CTRL_ID_PRODUCT),
833 GADGET_CTRL_ID_PRODUCT= 0;
834 g_free(GADGET_CTRL_MANUFACTURER),
835 GADGET_CTRL_MANUFACTURER= 0;
836 g_free(GADGET_CTRL_PRODUCT),
837 GADGET_CTRL_PRODUCT = 0;
838 g_free(GADGET_CTRL_SERIAL),
839 GADGET_CTRL_SERIAL = 0;
841 g_free(FUNCTION_MASS_STORAGE),
842 FUNCTION_MASS_STORAGE = 0;
843 g_free(FUNCTION_RNDIS),
845 g_free(FUNCTION_MTP),
847 g_free(FUNCTION_ADB);
850 g_free(RNDIS_CTRL_WCEIS),
851 RNDIS_CTRL_WCEIS = 0;
852 g_free(RNDIS_CTRL_ETHADDR),
853 RNDIS_CTRL_ETHADDR= 0;
861 configfs_set_charging_mode(
void)
863 LOG_REGISTER_CONTEXT;
867 if( !configfs_set_function(
"mass_storage") )
871 configfs_set_productid(
"0AFE");
873 if( !configfs_set_udc(
true) )
879 log_debug(
"CONFIGFS %s() -> %d", __func__, ack);
888 configfs_set_productid(
const char *
id)
890 LOG_REGISTER_CONTEXT;
894 if(
id && configfs_in_use() ) {
898 unsigned num = strtol(
id, &end, 16);
900 if( end >
id && *end == 0 ) {
901 snprintf(str,
sizeof str,
"0x%04x", num);
904 ack = configfs_write_file(GADGET_CTRL_ID_PRODUCT,
id);
907 log_debug(
"CONFIGFS %s(%s) -> %d", __func__,
id, ack);
916 configfs_set_vendorid(
const char *
id)
918 LOG_REGISTER_CONTEXT;
922 if(
id && configfs_in_use() ) {
923 log_debug(
"%s(%s) was called", __func__,
id);
928 unsigned num = strtol(
id, &end, 16);
931 if( end >
id && *end == 0 ) {
932 snprintf(str,
sizeof str,
"0x%04x", num);
936 ack = configfs_write_file(GADGET_CTRL_ID_VENDOR,
id);
939 log_debug(
"CONFIGFS %s(%s) -> %d", __func__,
id, ack);
944 configfs_map_function(
const char *func)
946 LOG_REGISTER_CONTEXT;
950 else if( !strcmp(func,
"mass_storage") )
951 func = FUNCTION_MASS_STORAGE;
952 else if( !strcmp(func,
"rndis") )
953 func = FUNCTION_RNDIS;
954 else if( !strcmp(func,
"mtp") )
956 else if( !strcmp(func,
"ffs") )
958 else if( !strcmp(func,
"adb") )
971 configfs_set_function(
const char *functions)
973 LOG_REGISTER_CONTEXT;
979 if( !configfs_in_use() )
982 if( !configfs_set_udc(
false) )
985 if( !configfs_disable_all_functions() )
989 vec = g_strsplit(functions,
",", 0);
990 for(
size_t i = 0; vec[i]; ++i ) {
994 const char *use = configfs_map_function(vec[i]);
997 if( !configfs_enable_function(use) )
1008 log_debug(
"CONFIGFS %s(%s) -> %d", __func__, functions, ack);
1014 configfs_add_mass_storage_lun(
int lun)
1016 LOG_REGISTER_CONTEXT;
1020 if( !configfs_in_use() )
1024 snprintf(unit,
sizeof unit,
"lun.%d", lun);
1025 ack = configfs_add_unit(FUNCTION_MASS_STORAGE, unit) != 0;
1032 configfs_remove_mass_storage_lun(
int lun)
1034 LOG_REGISTER_CONTEXT;
1038 if( !configfs_in_use() )
1042 snprintf(unit,
sizeof unit,
"lun.%d", lun);
1043 ack = configfs_remove_unit(FUNCTION_MASS_STORAGE, unit);
1050 configfs_set_mass_storage_attr(
int lun,
const char *attr,
const char *value)
1052 LOG_REGISTER_CONTEXT;
1056 if( !configfs_in_use() )
1060 snprintf(unit,
sizeof unit,
"lun.%d", lun);
1061 char path[PATH_MAX];
1062 configfs_function_path(path,
sizeof path, FUNCTION_MASS_STORAGE,
1064 ack = configfs_write_file(path, value);