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"
57#define DEFAULT_RNDIS_CTRL_WCEIS "wceis"
58#define DEFAULT_RNDIS_CTRL_ETHADDR "ethaddr"
68static gchar *configfs_get_conf (
const char *key,
const char *def);
69static void configfs_read_configuration (
void);
70static int configfs_file_type (
const char *path);
71static const char *configfs_function_path (
char *buff,
size_t size,
const char *func, ...);
72static const char *configfs_unit_path (
char *buff,
size_t size,
const char *func,
const char *unit);
73static const char *configfs_config_path (
char *buff,
size_t size,
const char *func);
74static bool configfs_mkdir (
const char *path);
75static bool configfs_rmdir (
const char *path);
76static const char *configfs_register_function (
const char *function);
78static bool configfs_unregister_function (
const char *function);
80static const char *configfs_add_unit (
const char *function,
const char *unit);
81static bool configfs_remove_unit (
const char *function,
const char *unit);
82static bool configfs_enable_function (
const char *function);
83static bool configfs_disable_function (
const char *function);
84static bool configfs_disable_all_functions (
void);
85static char *configfs_strip (
char *str);
86bool configfs_in_use (
void);
87static bool configfs_probe (
void);
88static const char *configfs_udc_enable_value (
void);
89static bool configfs_write_file (
const char *path,
const char *text);
90static bool configfs_read_file (
const char *path,
char *buff,
size_t size);
92static bool configfs_read_udc (
char *buff,
size_t size);
94static bool configfs_write_udc (
const char *text);
95bool configfs_set_udc (
bool enable);
98bool configfs_set_charging_mode (
void);
99bool configfs_set_productid (
const char *
id);
100bool configfs_set_vendorid (
const char *
id);
101static const char *configfs_map_function (
const char *func);
102bool configfs_set_function (
const char *functions);
103bool configfs_add_mass_storage_lun (
int lun);
104bool configfs_remove_mass_storage_lun(
int lun);
105bool configfs_set_mass_storage_attr (
int lun,
const char *attr,
const char *value);
111static int configfs_probed = -1;
113static gchar *GADGET_BASE_DIRECTORY = 0;
114static gchar *GADGET_FUNC_DIRECTORY = 0;
115static gchar *GADGET_CONF_DIRECTORY = 0;
117static gchar *GADGET_CTRL_UDC = 0;
118static gchar *GADGET_CTRL_ID_VENDOR = 0;
119static gchar *GADGET_CTRL_ID_PRODUCT = 0;
120static gchar *GADGET_CTRL_MANUFACTURER = 0;
121static gchar *GADGET_CTRL_PRODUCT = 0;
122static gchar *GADGET_CTRL_SERIAL = 0;
124static gchar *FUNCTION_MASS_STORAGE = 0;
125static gchar *FUNCTION_RNDIS = 0;
126static gchar *FUNCTION_MTP = 0;
128static gchar *RNDIS_CTRL_WCEIS = 0;
129static gchar *RNDIS_CTRL_ETHADDR = 0;
135static gchar *configfs_get_conf(
const char *key,
const char *def)
137 LOG_REGISTER_CONTEXT;
139 return config_get_conf_string(
"configfs", key) ?: g_strdup(def);
154static void configfs_read_configuration(
void)
156 LOG_REGISTER_CONTEXT;
160 static bool done =
false;
171 GADGET_BASE_DIRECTORY =
172 configfs_get_conf(
"gadget_base_directory",
173 DEFAULT_GADGET_BASE_DIRECTORY);
175 temp_setting = configfs_get_conf(
"gadget_func_directory",
176 DEFAULT_GADGET_FUNC_DIRECTORY);
177 GADGET_FUNC_DIRECTORY = g_strdup_printf(
"%s/%s",
178 GADGET_BASE_DIRECTORY,
180 g_free(temp_setting);
182 temp_setting = configfs_get_conf(
"gadget_conf_directory",
183 DEFAULT_GADGET_CONF_DIRECTORY);
184 GADGET_CONF_DIRECTORY =
185 g_strdup_printf(
"%s/%s",
186 GADGET_BASE_DIRECTORY,
188 g_free(temp_setting);
193 g_strdup_printf(
"%s/%s",
194 GADGET_BASE_DIRECTORY,
195 DEFAULT_GADGET_CTRL_UDC);
197 GADGET_CTRL_ID_VENDOR =
198 g_strdup_printf(
"%s/%s",
199 GADGET_BASE_DIRECTORY,
200 DEFAULT_GADGET_CTRL_ID_VENDOR);
202 GADGET_CTRL_ID_PRODUCT =
203 g_strdup_printf(
"%s/%s",
204 GADGET_BASE_DIRECTORY,
205 DEFAULT_GADGET_CTRL_ID_PRODUCT);
207 GADGET_CTRL_MANUFACTURER =
208 g_strdup_printf(
"%s/%s",
209 GADGET_BASE_DIRECTORY,
210 DEFAULT_GADGET_CTRL_MANUFACTURER);
212 GADGET_CTRL_PRODUCT =
213 g_strdup_printf(
"%s/%s",
214 GADGET_BASE_DIRECTORY,
215 DEFAULT_GADGET_CTRL_PRODUCT);
218 g_strdup_printf(
"%s/%s",
219 GADGET_BASE_DIRECTORY,
220 DEFAULT_GADGET_CTRL_SERIAL);
224 FUNCTION_MASS_STORAGE =
225 configfs_get_conf(
"function_mass_storage",
226 DEFAULT_FUNCTION_MASS_STORAGE);
229 configfs_get_conf(
"function_rndis",
230 DEFAULT_FUNCTION_RNDIS);
233 configfs_get_conf(
"function_mtp",
234 DEFAULT_FUNCTION_MTP);
238 g_strdup_printf(
"%s/%s/%s",
239 GADGET_FUNC_DIRECTORY,
241 DEFAULT_RNDIS_CTRL_WCEIS);
244 g_strdup_printf(
"%s/%s/%s",
245 GADGET_FUNC_DIRECTORY,
247 DEFAULT_RNDIS_CTRL_ETHADDR);
257static int configfs_file_type(
const char *path)
259 LOG_REGISTER_CONTEXT;
267 if( lstat(path, &st) == -1 )
270 type = st.st_mode & S_IFMT;
277configfs_function_path(
char *buff,
size_t size,
const char *func, ...)
279 LOG_REGISTER_CONTEXT;
282 char *end = buff + size;
284 snprintf(pos, end-pos,
"%s", GADGET_FUNC_DIRECTORY);
289 pos = strchr(pos, 0);
290 snprintf(pos, end-pos,
"/%s", func);
291 func = va_arg(va,
char *);
299configfs_unit_path(
char *buff,
size_t size,
const char *func,
const char *unit)
301 LOG_REGISTER_CONTEXT;
303 return configfs_function_path(buff, size, func, unit, NULL);
307configfs_config_path(
char *buff,
size_t size,
const char *func)
309 LOG_REGISTER_CONTEXT;
311 snprintf(buff, size,
"%s/%s", GADGET_CONF_DIRECTORY, func);
316configfs_mkdir(
const char *path)
318 LOG_REGISTER_CONTEXT;
322 if( mkdir(path, 0775) == -1 && errno != EEXIST ) {
323 log_err(
"%s: mkdir failed: %m", path);
327 if( configfs_file_type(path) != S_IFDIR ) {
328 log_err(
"%s: is not a directory", path);
339configfs_rmdir(
const char *path)
341 LOG_REGISTER_CONTEXT;
345 if( rmdir(path) == -1 && errno != ENOENT ) {
346 log_err(
"%s: rmdir failed: %m", path);
357configfs_register_function(
const char *function)
359 LOG_REGISTER_CONTEXT;
363 static char fpath[PATH_MAX];
364 configfs_function_path(fpath,
sizeof fpath, function, NULL);
366 if( !configfs_mkdir(fpath) )
369 log_debug(
"function %s is registered", function);
379configfs_unregister_function(
const char *function)
381 LOG_REGISTER_CONTEXT;
385 char fpath[PATH_MAX];
386 configfs_function_path(fpath,
sizeof fpath, function, NULL);
388 if( !configfs_rmdir(fpath) )
391 log_debug(
"function %s is unregistered", function);
400configfs_add_unit(
const char *function,
const char *unit)
402 LOG_REGISTER_CONTEXT;
406 static char upath[PATH_MAX];
407 configfs_unit_path(upath,
sizeof upath, function, unit);
409 if( !configfs_mkdir(upath) )
412 log_debug(
"function %s unit %s added", function, unit);
421configfs_remove_unit(
const char *function,
const char *unit)
423 LOG_REGISTER_CONTEXT;
427 static char upath[PATH_MAX];
428 configfs_unit_path(upath,
sizeof upath, function, unit);
430 if( !configfs_rmdir(upath) )
433 log_debug(
"function %s unit %s removed", function, unit);
442configfs_enable_function(
const char *function)
444 LOG_REGISTER_CONTEXT;
448 const char *fpath = configfs_register_function(function);
450 log_err(
"function %s is not registered", function);
454 char cpath[PATH_MAX];
455 configfs_config_path(cpath,
sizeof cpath, function);
457 switch( configfs_file_type(cpath) ) {
459 if( unlink(cpath) == -1 ) {
460 log_err(
"%s: unlink failed: %m", cpath);
465 if( symlink(fpath, cpath) == -1 ) {
466 log_err(
"%s: failed to symlink to %s: %m", cpath, fpath);
471 log_err(
"%s: is not a symlink", cpath);
475 log_debug(
"function %s is enabled", function);
483configfs_disable_function(
const char *function)
485 LOG_REGISTER_CONTEXT;
489 char cpath[PATH_MAX];
490 configfs_config_path(cpath,
sizeof cpath, function);
492 if( configfs_file_type(cpath) != S_IFLNK ) {
493 log_err(
"%s: is not a symlink", cpath);
497 if( unlink(cpath) == -1 ) {
498 log_err(
"%s: unlink failed: %m", cpath);
502 log_debug(
"function %s is disabled", function);
510configfs_disable_all_functions(
void)
512 LOG_REGISTER_CONTEXT;
517 if( !(dir = opendir(GADGET_CONF_DIRECTORY)) ) {
518 log_err(
"%s: opendir failed: %m", GADGET_CONF_DIRECTORY);
525 while( (de = readdir(dir)) ) {
526 if( de->d_type != DT_LNK )
529 if( !configfs_disable_function(de->d_name) )
534 log_debug(
"all functions are disabled");
543static char *configfs_strip(
char *str)
545 LOG_REGISTER_CONTEXT;
547 unsigned char *src = (
unsigned char *)str;
548 unsigned char *dst = (
unsigned char *)str;
550 while( *src > 0 && *src <= 32 ) ++src;
554 while( *src > 32 ) *dst++ = *src++;
555 while( *src > 0 && *src <= 32 ) ++src;
556 if( *src == 0 )
break;
566 LOG_REGISTER_CONTEXT;
568 if( configfs_probed < 0 )
569 log_debug(
"configfs_in_use() called before configfs_probe()");
570 return configfs_probed > 0;
576 LOG_REGISTER_CONTEXT;
578 configfs_read_configuration();
580 if( configfs_probed <= 0 ) {
581 configfs_probed = (access(GADGET_BASE_DIRECTORY, F_OK) == 0 &&
582 access(GADGET_CTRL_UDC, F_OK) == 0);
583 log_warning(
"CONFIGFS %sdetected", configfs_probed ?
"" :
"not ");
585 return configfs_in_use();
589configfs_udc_enable_value(
void)
591 LOG_REGISTER_CONTEXT;
593 static bool probed =
false;
594 static char *value = 0;
601 DIR *dir = opendir(
"/sys/class/udc");
603 while( (de = readdir(dir)) ) {
604 if( de->d_type != DT_LNK )
606 if( de->d_name[0] ==
'.' )
608 value = strdup(de->d_name);
619configfs_write_file(
const char *path,
const char *text)
621 LOG_REGISTER_CONTEXT;
629 log_debug(
"WRITE %s '%s'", path, text);
632 snprintf(buff,
sizeof buff,
"%s\n", text);
633 size_t size = strlen(buff);
635 if( (fd = open(path, O_WRONLY)) == -1 ) {
636 log_err(
"%s: can't open for writing: %m", path);
640 int rc = write(fd, buff, size);
642 log_err(
"%s: write failure: %m", path);
646 if( (
size_t)rc != size ) {
647 log_err(
"%s: write failure: partial success", path);
661configfs_read_file(
const char *path,
char *buff,
size_t size)
663 LOG_REGISTER_CONTEXT;
674 if( (fd = open(path, O_RDONLY)) == -1 ) {
675 log_err(
"%s: can't open for reading: %m", path);
679 int rc = read(fd, buff, size - 1);
681 log_err(
"%s: read failure: %m", path);
686 configfs_strip(buff);
690 log_debug(
"READ %s '%s'", path, buff);
701configfs_read_udc(
char *buff,
size_t size)
703 LOG_REGISTER_CONTEXT;
705 return configfs_read_file(GADGET_CTRL_UDC, buff, size);
710configfs_write_udc(
const char *text)
712 LOG_REGISTER_CONTEXT;
718 if( !configfs_read_file(GADGET_CTRL_UDC, prev,
sizeof prev) )
721 if( strcmp(prev, text) ) {
722 if( !configfs_write_file(GADGET_CTRL_UDC, text) )
734configfs_set_udc(
bool enable)
736 LOG_REGISTER_CONTEXT;
738 log_debug(
"UDC - %s", enable ?
"ENABLE" :
"DISABLE");
740 const char *value =
"";
743 value = configfs_udc_enable_value();
745 return configfs_write_udc(value);
755 LOG_REGISTER_CONTEXT;
757 if( !configfs_probe() )
761 configfs_set_udc(
false);
765 if( (text = config_get_android_vendor_id()) ) {
766 configfs_write_file(GADGET_CTRL_ID_VENDOR, text);
770 if( (text = config_get_android_product_id()) ) {
771 configfs_write_file(GADGET_CTRL_ID_PRODUCT, text);
775 if( (text = config_get_android_manufacturer()) ) {
776 configfs_write_file(GADGET_CTRL_MANUFACTURER, text);
780 if( (text = config_get_android_product()) ) {
781 configfs_write_file(GADGET_CTRL_PRODUCT, text);
786 configfs_write_file(GADGET_CTRL_SERIAL, text);
791 configfs_register_function(FUNCTION_MASS_STORAGE);
794 configfs_register_function(FUNCTION_MTP);
797 configfs_register_function(FUNCTION_RNDIS);
798 if( (text = mac_read_mac()) ) {
799 configfs_write_file(RNDIS_CTRL_ETHADDR, text);
803 configfs_write_file(RNDIS_CTRL_WCEIS,
"1");
807 return configfs_in_use();
815 g_free(GADGET_BASE_DIRECTORY),
816 GADGET_BASE_DIRECTORY = 0;
817 g_free(GADGET_FUNC_DIRECTORY),
818 GADGET_FUNC_DIRECTORY = 0;
819 g_free(GADGET_CONF_DIRECTORY),
820 GADGET_CONF_DIRECTORY = 0;
822 g_free(GADGET_CTRL_UDC),
824 g_free(GADGET_CTRL_ID_VENDOR),
825 GADGET_CTRL_ID_VENDOR= 0;
826 g_free(GADGET_CTRL_ID_PRODUCT),
827 GADGET_CTRL_ID_PRODUCT= 0;
828 g_free(GADGET_CTRL_MANUFACTURER),
829 GADGET_CTRL_MANUFACTURER= 0;
830 g_free(GADGET_CTRL_PRODUCT),
831 GADGET_CTRL_PRODUCT = 0;
832 g_free(GADGET_CTRL_SERIAL),
833 GADGET_CTRL_SERIAL = 0;
835 g_free(FUNCTION_MASS_STORAGE),
836 FUNCTION_MASS_STORAGE = 0;
837 g_free(FUNCTION_RNDIS),
839 g_free(FUNCTION_MTP),
842 g_free(RNDIS_CTRL_WCEIS),
843 RNDIS_CTRL_WCEIS = 0;
844 g_free(RNDIS_CTRL_ETHADDR),
845 RNDIS_CTRL_ETHADDR= 0;
853configfs_set_charging_mode(
void)
855 LOG_REGISTER_CONTEXT;
859 if( !configfs_set_function(
"mass_storage") )
863 configfs_set_productid(
"0AFE");
865 if( !configfs_set_udc(
true) )
871 log_debug(
"CONFIGFS %s() -> %d", __func__, ack);
880configfs_set_productid(
const char *
id)
882 LOG_REGISTER_CONTEXT;
886 if(
id && configfs_in_use() ) {
890 unsigned num = strtol(
id, &end, 16);
892 if( end >
id && *end == 0 ) {
893 snprintf(str,
sizeof str,
"0x%04x", num);
896 ack = configfs_write_file(GADGET_CTRL_ID_PRODUCT,
id);
899 log_debug(
"CONFIGFS %s(%s) -> %d", __func__,
id, ack);
908configfs_set_vendorid(
const char *
id)
910 LOG_REGISTER_CONTEXT;
914 if(
id && configfs_in_use() ) {
915 log_debug(
"%s(%s) was called", __func__,
id);
920 unsigned num = strtol(
id, &end, 16);
923 if( end >
id && *end == 0 ) {
924 snprintf(str,
sizeof str,
"0x%04x", num);
928 ack = configfs_write_file(GADGET_CTRL_ID_VENDOR,
id);
931 log_debug(
"CONFIGFS %s(%s) -> %d", __func__,
id, ack);
936configfs_map_function(
const char *func)
938 LOG_REGISTER_CONTEXT;
942 else if( !strcmp(func,
"mass_storage") )
943 func = FUNCTION_MASS_STORAGE;
944 else if( !strcmp(func,
"rndis") )
945 func = FUNCTION_RNDIS;
946 else if( !strcmp(func,
"mtp") )
948 else if( !strcmp(func,
"ffs") )
961configfs_set_function(
const char *functions)
963 LOG_REGISTER_CONTEXT;
969 if( !configfs_in_use() )
972 if( !configfs_set_udc(
false) )
975 if( !configfs_disable_all_functions() )
979 vec = g_strsplit(functions,
",", 0);
980 for(
size_t i = 0; vec[i]; ++i ) {
984 const char *use = configfs_map_function(vec[i]);
987 if( !configfs_enable_function(use) )
998 log_debug(
"CONFIGFS %s(%s) -> %d", __func__, functions, ack);
1004configfs_add_mass_storage_lun(
int lun)
1006 LOG_REGISTER_CONTEXT;
1010 if( !configfs_in_use() )
1014 snprintf(unit,
sizeof unit,
"lun.%d", lun);
1015 ack = configfs_add_unit(FUNCTION_MASS_STORAGE, unit) != 0;
1022configfs_remove_mass_storage_lun(
int lun)
1024 LOG_REGISTER_CONTEXT;
1028 if( !configfs_in_use() )
1032 snprintf(unit,
sizeof unit,
"lun.%d", lun);
1033 ack = configfs_remove_unit(FUNCTION_MASS_STORAGE, unit);
1040configfs_set_mass_storage_attr(
int lun,
const char *attr,
const char *value)
1042 LOG_REGISTER_CONTEXT;
1046 if( !configfs_in_use() )
1050 snprintf(unit,
sizeof unit,
"lun.%d", lun);
1051 char path[PATH_MAX];
1052 configfs_function_path(path,
sizeof path, FUNCTION_MASS_STORAGE,
1054 ack = configfs_write_file(path, value);
gchar * android_get_serial(void)