1
0
Fork 0
mirror of https://github.com/linux-usb-gadgets/libusbgx.git synced 2025-07-26 03:05:06 +03:00

uvc: add isoc parameter settings

The functions config parameters like maxburst, maxpacket, interval
and function_name are possible to be set by scheme file
as well. This patch adds support to import and export
these variables.

Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de>
This commit is contained in:
Michael Grzeschik 2022-06-27 01:21:43 +02:00
parent 50fe6a79bc
commit 8b91dbb3da
2 changed files with 190 additions and 0 deletions

View file

@ -52,6 +52,42 @@ struct usbg_f_uvc
bool formats_initiated;
};
#define UVC_DEC_ATTR(_name) \
{ \
.name = #_name, \
.offset = offsetof(struct usbg_f_uvc_config_attrs, _name), \
.get = usbg_get_dec, \
.set = usbg_set_dec, \
.import = usbg_get_config_node_int, \
.export = usbg_set_config_node_int, \
}
#define UVC_STRING_ATTR(_name) \
{ \
.name = #_name, \
.offset = offsetof(struct usbg_f_uvc_config_attrs, _name), \
.get = usbg_get_string, \
.set = usbg_set_string, \
.export = usbg_set_config_node_string, \
.import = usbg_get_config_node_string, \
}
struct {
const char *name;
size_t offset;
usbg_attr_get_func get;
usbg_attr_set_func set;
usbg_import_node_func import;
usbg_export_node_func export;
} uvc_config_attr[USBG_F_UVC_CONFIG_ATTR_MAX] = {
[USBG_F_UVC_CONFIG_MAXBURST] = UVC_DEC_ATTR(streaming_maxburst),
[USBG_F_UVC_CONFIG_MAXPACKET] = UVC_DEC_ATTR(streaming_maxpacket),
[USBG_F_UVC_CONFIG_INTERVAL] = UVC_DEC_ATTR(streaming_interval),
[USBG_F_UVC_CONFIG_FUNCTION_NAME] = UVC_STRING_ATTR(function_name),
};
#undef UVC_DEC_ATTR
#define UVC_DEC_ATTR(_name) \
{ \
.name = #_name, \
@ -250,6 +286,71 @@ static void uvc_cleanup_attrs(struct usbg_function *f, void *f_attrs)
return usbg_f_uvc_cleanup_attrs(f_attrs);
}
int usbg_f_uvc_get_config_attr_val(usbg_f_uvc *uvcf, enum usbg_f_uvc_config_attr iattr,
union usbg_f_uvc_config_attr_val *val)
{
char ipath[USBG_MAX_PATH_LENGTH];
int nmb;
nmb = snprintf(ipath, sizeof(ipath), "%s/%s/",
uvcf->func.path, uvcf->func.name);
if (nmb >= sizeof(ipath))
return USBG_ERROR_PATH_TOO_LONG;
return uvc_config_attr[iattr].get(ipath, "",
uvc_config_attr[iattr].name, val);
}
int usbg_f_uvc_set_config_attr_val(usbg_f_uvc *uvcf, enum usbg_f_uvc_config_attr iattr,
union usbg_f_uvc_config_attr_val val)
{
char ipath[USBG_MAX_PATH_LENGTH];
int nmb;
nmb = snprintf(ipath, sizeof(ipath), "%s/%s/",
uvcf->func.path, uvcf->func.name);
if (nmb >= sizeof(ipath))
return USBG_ERROR_PATH_TOO_LONG;
return uvc_config_attr[iattr].set(ipath, "",
uvc_config_attr[iattr].name, &val);
}
int usbg_f_uvc_get_config_attrs(usbg_f_uvc *uvcf, struct usbg_f_uvc_config_attrs *iattrs)
{
int i;
int ret = 0;
for (i = USBG_F_UVC_CONFIG_ATTR_MIN; i < USBG_F_UVC_CONFIG_ATTR_MAX; ++i) {
ret = usbg_f_uvc_get_config_attr_val(uvcf, i,
(union usbg_f_uvc_config_attr_val *)
((char *)iattrs
+ uvc_config_attr[i].offset));
if (ret)
break;
}
return ret;
}
int usbg_f_uvc_set_config_attrs(usbg_f_uvc *uvcf, const struct usbg_f_uvc_config_attrs *iattrs)
{
int i;
int ret = 0;
for (i = USBG_F_UVC_FRAME_ATTR_MIN; i < USBG_F_UVC_FRAME_ATTR_MAX; ++i) {
ret = usbg_f_uvc_set_config_attr_val(uvcf, i,
*(union usbg_f_uvc_config_attr_val *)
((char *)iattrs
+ uvc_config_attr[i].offset));
if (ret)
break;
}
return ret;
}
int usbg_f_uvc_get_frame_attr_val(usbg_f_uvc *uvcf, const char* format, int frame_id,
enum usbg_f_uvc_frame_attr fattr,
union usbg_f_uvc_frame_attr_val *val)
@ -646,6 +747,41 @@ out:
return ret;
};
static int uvc_import_config(struct usbg_f_uvc *uvcf, config_setting_t *root)
{
union usbg_f_uvc_config_attr_val val;
config_setting_t *config_node;
int ret = 0;
int i;
config_node = config_setting_get_member(root, "config");
if (!config_node) {
ret = USBG_ERROR_INVALID_PARAM;
return ret;
}
if (!config_setting_is_group(config_node)) {
ret = USBG_ERROR_INVALID_TYPE;
return ret;
}
for (i = USBG_F_UVC_CONFIG_ATTR_MIN; i < USBG_F_UVC_CONFIG_ATTR_MAX; ++i) {
ret = uvc_config_attr[i].import(config_node, uvc_config_attr[i].name, &val);
/* node not found */
if (ret == 0)
continue;
/* error */
if (ret < 0)
break;
ret = usbg_f_uvc_set_config_attr_val(uvcf, i, val);
if (ret)
break;
}
return ret;
}
static int uvc_libconfig_import(struct usbg_function *f, config_setting_t *root)
{
struct usbg_f_uvc *uvcf = usbg_to_uvc_function(f);
@ -695,6 +831,10 @@ static int uvc_libconfig_import(struct usbg_function *f, config_setting_t *root)
goto out;
}
ret = uvc_import_config(uvcf, root);
if (ret != USBG_SUCCESS)
return ret;
ret = uvc_set_class(uvcf, UVC_PATH_CONTROL);
if (ret != USBG_SUCCESS)
return ret;
@ -708,6 +848,31 @@ out:
}
static int uvc_export_config(struct usbg_f_uvc *uvcf, config_setting_t *root)
{
config_setting_t *config_node;
union usbg_f_uvc_config_attr_val val;
int i;
int ret = 0;
config_node = config_setting_add(root, "config", CONFIG_TYPE_GROUP);
if (!config_node)
goto out;
for (i = USBG_F_UVC_CONFIG_ATTR_MIN; i < USBG_F_UVC_CONFIG_ATTR_MAX; ++i) {
ret = usbg_f_uvc_get_config_attr_val(uvcf, i, &val);
if (ret)
break;
ret = uvc_config_attr[i].export(config_node, uvc_config_attr[i].name, &val);
if (ret)
break;
}
out:
return ret;
};
static int uvc_export_format_attrs(struct usbg_f_uvc *uvcf, const char *format,
config_setting_t *root)
{
@ -819,6 +984,8 @@ static int uvc_libconfig_export(struct usbg_function *f, config_setting_t *root)
goto out;
}
ret = uvc_export_config(uvcf, root);
out:
return ret;
}