43#define DEFAULT_GADGET_BASE_DIRECTORY "/config/usb_gadget/g1"
44#define DEFAULT_GADGET_FUNC_DIRECTORY "functions"
45#define DEFAULT_GADGET_CONF_DIRECTORY "configs/b.1"
46#define DEFAULT_GADGET_UDC_DEVICE ""
48#define DEFAULT_GADGET_CTRL_UDC "UDC"
49#define DEFAULT_GADGET_CTRL_ID_VENDOR "idVendor"
50#define DEFAULT_GADGET_CTRL_ID_PRODUCT "idProduct"
51#define DEFAULT_GADGET_CTRL_MANUFACTURER "strings/0x409/manufacturer"
52#define DEFAULT_GADGET_CTRL_PRODUCT "strings/0x409/product"
53#define DEFAULT_GADGET_CTRL_SERIAL "strings/0x409/serialnumber"
55#define DEFAULT_FUNCTION_MASS_STORAGE "mass_storage.usb0"
56#define DEFAULT_FUNCTION_RNDIS "rndis_bam.rndis"
57#define DEFAULT_FUNCTION_MTP "ffs.mtp"
59#define DEFAULT_RNDIS_CTRL_WCEIS "wceis"
60#define DEFAULT_RNDIS_CTRL_ETHADDR "ethaddr"
70static gchar *configfs_get_conf (
const char *key,
const char *def);
71static void configfs_read_configuration (
void);
72static int configfs_file_type (
const char *path);
73static const char *configfs_function_path (
char *buff,
size_t size,
const char *func, ...);
74static const char *configfs_unit_path (
char *buff,
size_t size,
const char *func,
const char *unit);
75static const char *configfs_config_path (
char *buff,
size_t size,
const char *func);
76static bool configfs_mkdir (
const char *path);
77static bool configfs_rmdir (
const char *path);
78static const char *configfs_register_function (
const char *function);
80static bool configfs_unregister_function (
const char *function);
82static const char *configfs_add_unit (
const char *function,
const char *unit);
83static bool configfs_remove_unit (
const char *function,
const char *unit);
84static bool configfs_enable_function (
const char *function);
85static bool configfs_disable_function (
const char *function);
86static bool configfs_disable_all_functions (
void);
87static char *configfs_strip (
char *str);
88bool configfs_in_use (
void);
89static bool configfs_probe (
void);
90static const char *configfs_udc_enable_value (
void);
91static bool configfs_write_file (
const char *path,
const char *text);
92static bool configfs_read_file (
const char *path,
char *buff,
size_t size);
94static bool configfs_read_udc (
char *buff,
size_t size);
96static bool configfs_write_udc (
const char *text);
97bool configfs_set_udc (
bool enable);
100bool configfs_set_charging_mode (
void);
101bool configfs_set_productid (
const char *
id);
102bool configfs_set_vendorid (
const char *
id);
103static const char *configfs_map_function (
const char *func);
104bool configfs_set_function (
const char *functions);
105bool configfs_add_mass_storage_lun (
int lun);
106bool configfs_remove_mass_storage_lun(
int lun);
107bool configfs_set_mass_storage_attr (
int lun,
const char *attr,
const char *value);
113static int configfs_probed = -1;
115static gchar *GADGET_BASE_DIRECTORY = 0;
116static gchar *GADGET_FUNC_DIRECTORY = 0;
117static gchar *GADGET_CONF_DIRECTORY = 0;
118static gchar *GADGET_UDC_DEVICE = 0;
120static gchar *GADGET_CTRL_UDC = 0;
121static gchar *GADGET_CTRL_ID_VENDOR = 0;
122static gchar *GADGET_CTRL_ID_PRODUCT = 0;
123static gchar *GADGET_CTRL_MANUFACTURER = 0;
124static gchar *GADGET_CTRL_PRODUCT = 0;
125static gchar *GADGET_CTRL_SERIAL = 0;
127static gchar *FUNCTION_MASS_STORAGE = 0;
128static gchar *FUNCTION_RNDIS = 0;
129static gchar *FUNCTION_MTP = 0;
131static gchar *RNDIS_CTRL_WCEIS = 0;
132static gchar *RNDIS_CTRL_ETHADDR = 0;
138static gchar *configfs_get_conf(
const char *key,
const char *def)
140 LOG_REGISTER_CONTEXT;
142 return config_get_conf_string(
"configfs", key) ?: g_strdup(def);
157static void configfs_read_configuration(
void)
159 LOG_REGISTER_CONTEXT;
163 static bool done =
false;
174 GADGET_BASE_DIRECTORY =
175 configfs_get_conf(
"gadget_base_directory",
176 DEFAULT_GADGET_BASE_DIRECTORY);
178 temp_setting = configfs_get_conf(
"gadget_func_directory",
179 DEFAULT_GADGET_FUNC_DIRECTORY);
180 GADGET_FUNC_DIRECTORY = g_strdup_printf(
"%s/%s",
181 GADGET_BASE_DIRECTORY,
183 g_free(temp_setting);
185 temp_setting = configfs_get_conf(
"gadget_conf_directory",
186 DEFAULT_GADGET_CONF_DIRECTORY);
187 GADGET_CONF_DIRECTORY =
188 g_strdup_printf(
"%s/%s",
189 GADGET_BASE_DIRECTORY,
191 g_free(temp_setting);
194 configfs_get_conf(
"gadget_udc_device",
195 DEFAULT_GADGET_UDC_DEVICE);
200 g_strdup_printf(
"%s/%s",
201 GADGET_BASE_DIRECTORY,
202 DEFAULT_GADGET_CTRL_UDC);
204 GADGET_CTRL_ID_VENDOR =
205 g_strdup_printf(
"%s/%s",
206 GADGET_BASE_DIRECTORY,
207 DEFAULT_GADGET_CTRL_ID_VENDOR);
209 GADGET_CTRL_ID_PRODUCT =
210 g_strdup_printf(
"%s/%s",
211 GADGET_BASE_DIRECTORY,
212 DEFAULT_GADGET_CTRL_ID_PRODUCT);
214 GADGET_CTRL_MANUFACTURER =
215 g_strdup_printf(
"%s/%s",
216 GADGET_BASE_DIRECTORY,
217 DEFAULT_GADGET_CTRL_MANUFACTURER);
219 GADGET_CTRL_PRODUCT =
220 g_strdup_printf(
"%s/%s",
221 GADGET_BASE_DIRECTORY,
222 DEFAULT_GADGET_CTRL_PRODUCT);
225 g_strdup_printf(
"%s/%s",
226 GADGET_BASE_DIRECTORY,
227 DEFAULT_GADGET_CTRL_SERIAL);
231 FUNCTION_MASS_STORAGE =
232 configfs_get_conf(
"function_mass_storage",
233 DEFAULT_FUNCTION_MASS_STORAGE);
236 configfs_get_conf(
"function_rndis",
237 DEFAULT_FUNCTION_RNDIS);
240 configfs_get_conf(
"function_mtp",
241 DEFAULT_FUNCTION_MTP);
245 g_strdup_printf(
"%s/%s/%s",
246 GADGET_FUNC_DIRECTORY,
248 DEFAULT_RNDIS_CTRL_WCEIS);
251 g_strdup_printf(
"%s/%s/%s",
252 GADGET_FUNC_DIRECTORY,
254 DEFAULT_RNDIS_CTRL_ETHADDR);
264static int configfs_file_type(
const char *path)
266 LOG_REGISTER_CONTEXT;
274 if( lstat(path, &st) == -1 )
277 type = st.st_mode & S_IFMT;
284configfs_function_path(
char *buff,
size_t size,
const char *func, ...)
286 LOG_REGISTER_CONTEXT;
289 char *end = buff + size;
291 snprintf(pos, end-pos,
"%s", GADGET_FUNC_DIRECTORY);
296 pos = strchr(pos, 0);
297 snprintf(pos, end-pos,
"/%s", func);
298 func = va_arg(va,
char *);
306configfs_unit_path(
char *buff,
size_t size,
const char *func,
const char *unit)
308 LOG_REGISTER_CONTEXT;
310 return configfs_function_path(buff, size, func, unit, NULL);
314configfs_config_path(
char *buff,
size_t size,
const char *func)
316 LOG_REGISTER_CONTEXT;
318 snprintf(buff, size,
"%s/%s", GADGET_CONF_DIRECTORY, func);
323configfs_mkdir(
const char *path)
325 LOG_REGISTER_CONTEXT;
329 if( mkdir(path, 0775) == -1 && errno != EEXIST ) {
330 log_err(
"%s: mkdir failed: %m", path);
334 if( configfs_file_type(path) != S_IFDIR ) {
335 log_err(
"%s: is not a directory", path);
346configfs_rmdir(
const char *path)
348 LOG_REGISTER_CONTEXT;
352 if( rmdir(path) == -1 && errno != ENOENT ) {
353 log_err(
"%s: rmdir failed: %m", path);
364configfs_register_function(
const char *function)
366 LOG_REGISTER_CONTEXT;
370 static char fpath[PATH_MAX];
371 configfs_function_path(fpath,
sizeof fpath, function, NULL);
373 if( !configfs_mkdir(fpath) )
376 log_debug(
"function %s is registered", function);
386configfs_unregister_function(
const char *function)
388 LOG_REGISTER_CONTEXT;
392 char fpath[PATH_MAX];
393 configfs_function_path(fpath,
sizeof fpath, function, NULL);
395 if( !configfs_rmdir(fpath) )
398 log_debug(
"function %s is unregistered", function);
407configfs_add_unit(
const char *function,
const char *unit)
409 LOG_REGISTER_CONTEXT;
413 static char upath[PATH_MAX];
414 configfs_unit_path(upath,
sizeof upath, function, unit);
416 if( !configfs_mkdir(upath) )
419 log_debug(
"function %s unit %s added", function, unit);
428configfs_remove_unit(
const char *function,
const char *unit)
430 LOG_REGISTER_CONTEXT;
434 static char upath[PATH_MAX];
435 configfs_unit_path(upath,
sizeof upath, function, unit);
437 if( !configfs_rmdir(upath) )
440 log_debug(
"function %s unit %s removed", function, unit);
449configfs_enable_function(
const char *function)
451 LOG_REGISTER_CONTEXT;
455 const char *fpath = configfs_register_function(function);
457 log_err(
"function %s is not registered", function);
461 char cpath[PATH_MAX];
462 configfs_config_path(cpath,
sizeof cpath, function);
464 switch( configfs_file_type(cpath) ) {
466 if( unlink(cpath) == -1 ) {
467 log_err(
"%s: unlink failed: %m", cpath);
472 if( symlink(fpath, cpath) == -1 ) {
473 log_err(
"%s: failed to symlink to %s: %m", cpath, fpath);
478 log_err(
"%s: is not a symlink", cpath);
482 log_debug(
"function %s is enabled", function);
490configfs_disable_function(
const char *function)
492 LOG_REGISTER_CONTEXT;
496 char cpath[PATH_MAX];
497 configfs_config_path(cpath,
sizeof cpath, function);
499 if( configfs_file_type(cpath) != S_IFLNK ) {
500 log_err(
"%s: is not a symlink", cpath);
504 if( unlink(cpath) == -1 ) {
505 log_err(
"%s: unlink failed: %m", cpath);
509 log_debug(
"function %s is disabled", function);
517configfs_disable_all_functions(
void)
519 LOG_REGISTER_CONTEXT;
524 if( !(dir = opendir(GADGET_CONF_DIRECTORY)) ) {
525 log_err(
"%s: opendir failed: %m", GADGET_CONF_DIRECTORY);
532 while( (de = readdir(dir)) ) {
533 if( de->d_type != DT_LNK )
536 if( !configfs_disable_function(de->d_name) )
541 log_debug(
"all functions are disabled");
550static char *configfs_strip(
char *str)
552 LOG_REGISTER_CONTEXT;
554 unsigned char *src = (
unsigned char *)str;
555 unsigned char *dst = (
unsigned char *)str;
557 while( *src > 0 && *src <= 32 ) ++src;
561 while( *src > 32 ) *dst++ = *src++;
562 while( *src > 0 && *src <= 32 ) ++src;
563 if( *src == 0 )
break;
573 LOG_REGISTER_CONTEXT;
575 if( configfs_probed < 0 )
576 log_debug(
"configfs_in_use() called before configfs_probe()");
577 return configfs_probed > 0;
583 LOG_REGISTER_CONTEXT;
585 configfs_read_configuration();
587 if( configfs_probed <= 0 ) {
588 configfs_probed = (access(GADGET_BASE_DIRECTORY, F_OK) == 0 &&
589 access(GADGET_CTRL_UDC, F_OK) == 0);
590 log_warning(
"CONFIGFS %sdetected", configfs_probed ?
"" :
"not ");
592 return configfs_in_use();
596configfs_udc_enable_value(
void)
598 LOG_REGISTER_CONTEXT;
600 static bool probed =
false;
601 static char *value = 0;
606 if (*GADGET_UDC_DEVICE) {
607 value = strdup(GADGET_UDC_DEVICE);
612 DIR *dir = opendir(
"/sys/class/udc");
614 while( (de = readdir(dir)) ) {
615 if( de->d_type != DT_LNK )
617 if( de->d_name[0] ==
'.' )
619 value = strdup(de->d_name);
631configfs_write_file(
const char *path,
const char *text)
633 LOG_REGISTER_CONTEXT;
641 log_debug(
"WRITE %s '%s'", path, text);
644 snprintf(buff,
sizeof buff,
"%s\n", text);
645 size_t size = strlen(buff);
647 if( (fd = open(path, O_WRONLY)) == -1 ) {
648 log_err(
"%s: can't open for writing: %m", path);
652 int rc = write(fd, buff, size);
654 log_err(
"%s: write failure: %m", path);
658 if( (
size_t)rc != size ) {
659 log_err(
"%s: write failure: partial success", path);
673configfs_read_file(
const char *path,
char *buff,
size_t size)
675 LOG_REGISTER_CONTEXT;
686 if( (fd = open(path, O_RDONLY)) == -1 ) {
687 log_err(
"%s: can't open for reading: %m", path);
691 int rc = read(fd, buff, size - 1);
693 log_err(
"%s: read failure: %m", path);
698 configfs_strip(buff);
702 log_debug(
"READ %s '%s'", path, buff);
713configfs_read_udc(
char *buff,
size_t size)
715 LOG_REGISTER_CONTEXT;
717 return configfs_read_file(GADGET_CTRL_UDC, buff, size);
722configfs_write_udc(
const char *text)
724 LOG_REGISTER_CONTEXT;
730 if( !configfs_read_file(GADGET_CTRL_UDC, prev,
sizeof prev) )
733 if( strcmp(prev, text) ) {
734 if( !configfs_write_file(GADGET_CTRL_UDC, text) )
746configfs_set_udc(
bool enable)
748 LOG_REGISTER_CONTEXT;
750 log_debug(
"UDC - %s", enable ?
"ENABLE" :
"DISABLE");
752 const char *value =
"";
755 value = configfs_udc_enable_value();
757 return configfs_write_udc(value);
767 LOG_REGISTER_CONTEXT;
769 if( !configfs_probe() )
773 configfs_set_udc(
false);
777 if( (text = config_get_android_vendor_id()) ) {
778 configfs_write_file(GADGET_CTRL_ID_VENDOR, text);
782 if( (text = config_get_android_product_id()) ) {
783 configfs_write_file(GADGET_CTRL_ID_PRODUCT, text);
787 if( (text = config_get_android_manufacturer()) ) {
788 configfs_write_file(GADGET_CTRL_MANUFACTURER, text);
792 if( (text = config_get_android_product()) ) {
793 configfs_write_file(GADGET_CTRL_PRODUCT, text);
798 configfs_write_file(GADGET_CTRL_SERIAL, text);
803 configfs_register_function(FUNCTION_MASS_STORAGE);
806 configfs_register_function(FUNCTION_MTP);
809 configfs_register_function(FUNCTION_RNDIS);
810 if( (text = mac_read_mac()) ) {
811 configfs_write_file(RNDIS_CTRL_ETHADDR, text);
815 configfs_write_file(RNDIS_CTRL_WCEIS,
"1");
819 return configfs_in_use();
827 g_free(GADGET_BASE_DIRECTORY),
828 GADGET_BASE_DIRECTORY = 0;
829 g_free(GADGET_FUNC_DIRECTORY),
830 GADGET_FUNC_DIRECTORY = 0;
831 g_free(GADGET_CONF_DIRECTORY),
832 GADGET_CONF_DIRECTORY = 0;
834 g_free(GADGET_CTRL_UDC),
836 g_free(GADGET_CTRL_ID_VENDOR),
837 GADGET_CTRL_ID_VENDOR= 0;
838 g_free(GADGET_CTRL_ID_PRODUCT),
839 GADGET_CTRL_ID_PRODUCT= 0;
840 g_free(GADGET_CTRL_MANUFACTURER),
841 GADGET_CTRL_MANUFACTURER= 0;
842 g_free(GADGET_CTRL_PRODUCT),
843 GADGET_CTRL_PRODUCT = 0;
844 g_free(GADGET_CTRL_SERIAL),
845 GADGET_CTRL_SERIAL = 0;
847 g_free(FUNCTION_MASS_STORAGE),
848 FUNCTION_MASS_STORAGE = 0;
849 g_free(FUNCTION_RNDIS),
851 g_free(FUNCTION_MTP),
854 g_free(RNDIS_CTRL_WCEIS),
855 RNDIS_CTRL_WCEIS = 0;
856 g_free(RNDIS_CTRL_ETHADDR),
857 RNDIS_CTRL_ETHADDR= 0;
865configfs_set_charging_mode(
void)
867 LOG_REGISTER_CONTEXT;
871 if( !configfs_set_function(
"mass_storage") )
875 configfs_set_productid(
"0AFE");
877 if( !configfs_set_udc(
true) )
883 log_debug(
"CONFIGFS %s() -> %d", __func__, ack);
892configfs_set_productid(
const char *
id)
894 LOG_REGISTER_CONTEXT;
898 if(
id && configfs_in_use() ) {
902 unsigned num = strtol(
id, &end, 16);
904 if( end >
id && *end == 0 ) {
905 snprintf(str,
sizeof str,
"0x%04x", num);
908 ack = configfs_write_file(GADGET_CTRL_ID_PRODUCT,
id);
911 log_debug(
"CONFIGFS %s(%s) -> %d", __func__,
id, ack);
920configfs_set_vendorid(
const char *
id)
922 LOG_REGISTER_CONTEXT;
926 if(
id && configfs_in_use() ) {
927 log_debug(
"%s(%s) was called", __func__,
id);
932 unsigned num = strtol(
id, &end, 16);
935 if( end >
id && *end == 0 ) {
936 snprintf(str,
sizeof str,
"0x%04x", num);
940 ack = configfs_write_file(GADGET_CTRL_ID_VENDOR,
id);
943 log_debug(
"CONFIGFS %s(%s) -> %d", __func__,
id, ack);
948configfs_map_function(
const char *func)
950 LOG_REGISTER_CONTEXT;
954 else if( !strcmp(func,
"mass_storage") )
955 func = FUNCTION_MASS_STORAGE;
956 else if( !strcmp(func,
"rndis") )
957 func = FUNCTION_RNDIS;
958 else if( !strcmp(func,
"mtp") )
960 else if( !strcmp(func,
"ffs") )
973configfs_set_function(
const char *functions)
975 LOG_REGISTER_CONTEXT;
981 if( !configfs_in_use() )
984 if( !configfs_set_udc(
false) )
987 if( !configfs_disable_all_functions() )
991 vec = g_strsplit(functions,
",", 0);
992 for(
size_t i = 0; vec[i]; ++i ) {
996 const char *use = configfs_map_function(vec[i]);
999 if( !configfs_enable_function(use) )
1010 log_debug(
"CONFIGFS %s(%s) -> %d", __func__, functions, ack);
1016configfs_add_mass_storage_lun(
int lun)
1018 LOG_REGISTER_CONTEXT;
1022 if( !configfs_in_use() )
1026 snprintf(unit,
sizeof unit,
"lun.%d", lun);
1027 ack = configfs_add_unit(FUNCTION_MASS_STORAGE, unit) != 0;
1034configfs_remove_mass_storage_lun(
int lun)
1036 LOG_REGISTER_CONTEXT;
1040 if( !configfs_in_use() )
1044 snprintf(unit,
sizeof unit,
"lun.%d", lun);
1045 ack = configfs_remove_unit(FUNCTION_MASS_STORAGE, unit);
1052configfs_set_mass_storage_attr(
int lun,
const char *attr,
const char *value)
1054 LOG_REGISTER_CONTEXT;
1058 if( !configfs_in_use() )
1062 snprintf(unit,
sizeof unit,
"lun.%d", lun);
1063 char path[PATH_MAX];
1064 configfs_function_path(path,
sizeof path, FUNCTION_MASS_STORAGE,
1066 ack = configfs_write_file(path, value);
gchar * android_get_serial(void)