Skip to content

Commit

Permalink
uvc: add isoc parameter settings
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
mgrzeschik committed Jul 11, 2022
1 parent 50fe6a7 commit 8b91dbb
Show file tree
Hide file tree
Showing 2 changed files with 190 additions and 0 deletions.
23 changes: 23 additions & 0 deletions include/usbg/function/uvc.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@ extern "C" {
struct usbg_f_uvc;
typedef struct usbg_f_uvc usbg_f_uvc;

struct usbg_f_uvc_config_attrs
{
int streaming_maxburst;
int streaming_maxpacket;
int streaming_interval;
const char *function_name;
};

struct usbg_f_uvc_frame_attrs
{
int bFrameIndex;
Expand Down Expand Up @@ -52,6 +60,15 @@ struct usbg_f_uvc_attrs
struct usbg_f_uvc_format_attrs **formats;
};

enum usbg_f_uvc_config_attr {
USBG_F_UVC_CONFIG_ATTR_MIN = 0,
USBG_F_UVC_CONFIG_MAXBURST = USBG_F_UVC_CONFIG_ATTR_MIN,
USBG_F_UVC_CONFIG_MAXPACKET,
USBG_F_UVC_CONFIG_INTERVAL,
USBG_F_UVC_CONFIG_FUNCTION_NAME,
USBG_F_UVC_CONFIG_ATTR_MAX
};

enum usbg_f_uvc_frame_attr {
USBG_F_UVC_FRAME_ATTR_MIN = 0,
USBG_F_UVC_FRAME_INDEX = USBG_F_UVC_FRAME_ATTR_MIN,
Expand All @@ -77,6 +94,12 @@ enum usbg_f_uvc_format_attr {
USBG_F_UVC_FORMAT_ATTR_MAX
};

union usbg_f_uvc_config_attr_val {
int streaming_maxburst;
int streaming_maxpacket;
int streaming_interval;
const char *function_name;
};

union usbg_f_uvc_frame_attr_val {
int bmCapabilities;
Expand Down
167 changes: 167 additions & 0 deletions src/function/uvc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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, \
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -646,6 +747,41 @@ static int uvc_import_format(struct usbg_f_uvc *uvcf, const char *format, bool *
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);
Expand Down Expand Up @@ -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;
Expand All @@ -708,6 +848,31 @@ static int uvc_libconfig_import(struct usbg_function *f, config_setting_t *root)

}

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)
{
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 8b91dbb

Please sign in to comment.