#include <libsyscommon/dbus-systemd.h>
#include <hw/shared.h>
+#include <hw/usb_gadget.h>
#include <hw/usb_client.h>
#define MAX_GADGET_STR_LEN 256
#define EXPORT __attribute__ ((visibility("default")))
#endif
-static bool legacy_is_function_supported(struct usb_client *usb,
- const struct usb_function *func)
+static bool legacy_is_function_supported(struct usb_function *func)
{
- /*
- * TODO
- * Instead of only checking whether we know this function
- * we should also parse sysfs to check if it is build into
- * slp-gadget.
- */
- if (find_usb_function_by_name(func->name))
- return true;
- else
+ char buf[PATH_MAX];
+
+ snprintf (buf, sizeof(buf), "%s/f_%s", LEGACY_ROOTPATH, func->name);
+ if (access(buf, F_OK))
return false;
+
+ return true;
}
-static bool legacy_is_gadget_supported(struct usb_client *usb,
- struct usb_gadget *gadget)
+static bool legacy_is_gadget_supported(struct usb_gadget *gadget)
{
int i, j;
+ struct usb_configuration *config;
- if (!gadget || !gadget->configs || !gadget->funcs)
+ if (!gadget || !gadget->configs || !gadget->configs[0] || !gadget->configs[0]->funcs[0])
return false;
- /*
- * TODO
- * Here is a good place to ensure that serial is immutable
- */
- if (gadget->strs) {
- /* only strings in US_en are allowed */
- if (gadget->strs[0].lang_code != 0x409 ||
- gadget->strs[1].lang_code)
+ if (!gadget->attrs.idVendor || !gadget->attrs.idProduct || !gadget->attrs.bcdDevice)
return false;
- }
-
- for (j = 0; gadget->configs[j]; ++j) {
- struct usb_configuration *config = gadget->configs[j];
- if (config->strs && config->strs[0].lang_code)
+ /* only strings in US_en are allowed */
+ if (gadget->strs.lang_code != DEFAULT_LANG)
return false;
+ if (!gadget->strs.manufacturer || !gadget->strs.product)
+ return false;
+
+ for (j = 0; gadget->configs[j]; ++j) {
+ config = gadget->configs[j];
+
if (!config->funcs)
return false;
for (i = 0; config->funcs[i]; ++i)
- if (!legacy_is_function_supported(usb, config->funcs[i]))
+ if (!legacy_is_function_supported(config->funcs[i]))
return false;
}
- if (j == 0 || j > 2)
- return false;
-
return true;
}
/* TODO. Maybe move this to sys ? */
static int legacy_set_int_hex(char *path, int val)
{
- char buf[MAX_GADGET_STR_LEN];
int r;
+ char buf[MAX_GADGET_STR_LEN];
if (!path)
return -EINVAL;
return ret;
ret = legacy_set_int_hex(LEGACY_BCD_DEVICE_PATH, attrs->bcdDevice);
+ if (ret)
+ return ret;
- return ret;
+ return 0;
}
static int legacy_set_gadget_strs(struct usb_gadget_strings *strs)
{
- int ret = 0;
+ int ret;
- /*
- * TODO
- * Here is a good place to ensure that serial is immutable
- */
+ if (!strs->manufacturer || !strs->product)
+ return -EINVAL;
- if (strs->manufacturer) {
- ret = sys_set_str(LEGACY_IMANUFACTURER_PATH, strs->manufacturer);
- if (ret)
- return ret;
- }
+ ret = sys_set_str(LEGACY_IMANUFACTURER_PATH, strs->manufacturer);
+ if (ret)
+ return ret;
- if (strs->product) {
- ret = sys_set_str(LEGACY_IPRODUCT_PATH, strs->product);
- if (ret)
- return ret;
- }
+ ret = sys_set_str(LEGACY_IPRODUCT_PATH, strs->product);
+ if (ret)
+ return ret;
- return ret;
+ /* The serial is written by the slp gadget kernel driver */
+
+ return 0;
}
static int legacy_set_gadget_config(char *cpath,
return sys_set_str(cpath, buf);
}
-static int legacy_reconfigure_gadget(struct usb_client *usb,
- struct usb_gadget *gadget)
+static int legacy_reconfigure_gadget(struct usb_client *usb, struct usb_gadget *gadget)
{
int ret;
- if (!usb || !gadget || !legacy_is_gadget_supported(usb, gadget))
+ if (!usb || !gadget)
return -EINVAL;
+ /* Verify the gadget and check if function is supported */
+ if (!legacy_is_gadget_supported(gadget))
+ return -ENOTSUP;
+
ret = legacy_set_gadget_attrs(&gadget->attrs);
if (ret)
return ret;
- if (gadget->strs) {
- ret = legacy_set_gadget_strs(gadget->strs + 0);
- if (ret)
- return ret;
- }
+ ret = legacy_set_gadget_strs(&gadget->strs);
+ if (ret)
+ return ret;
ret = legacy_set_gadget_config(LEGACY_CONFIG_1_PATH, gadget->configs[0]);
if (ret)
return ret;
ret = legacy_set_gadget_config(LEGACY_CONFIG_2_PATH, gadget->configs[1]);
+ if (ret)
+ return ret;
- return ret;
+ return 0;
}
static void legacy_start_stop_service_and_handler(bool start)
char *fname;
char *sep = LEGACY_FUNC_SEP;
char buf[MAX_GADGET_STR_LEN];
- const struct usb_function *func;
- const struct usb_function *funcs[USB_FUNCTION_IDX_MAX];
+ struct usb_function *func;
+ struct usb_function *funcs[USB_FUNCTION_IDX_MAX];
/* SLP gadget uses two USB configuration.
* (/sys/class/usb_mode/usb0/funcs_fconf and /sys/class/usb_mode/usb0/funcs_sconf)