|
@@ -9,9 +9,16 @@
|
|
*
|
|
*
|
|
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
|
* Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
|
|
*/
|
|
*/
|
|
|
|
+
|
|
|
|
+#include <linux/sort.h>
|
|
|
|
+
|
|
#include "u_uvc.h"
|
|
#include "u_uvc.h"
|
|
#include "uvc_configfs.h"
|
|
#include "uvc_configfs.h"
|
|
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * Global Utility Structures and Macros
|
|
|
|
+ */
|
|
|
|
+
|
|
#define UVCG_STREAMING_CONTROL_SIZE 1
|
|
#define UVCG_STREAMING_CONTROL_SIZE 1
|
|
|
|
|
|
#define UVC_ATTR(prefix, cname, aname) \
|
|
#define UVC_ATTR(prefix, cname, aname) \
|
|
@@ -31,13 +38,93 @@ static struct configfs_attribute prefix##attr_##cname = { \
|
|
.show = prefix##cname##_show, \
|
|
.show = prefix##cname##_show, \
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#define le8_to_cpu(x) (x)
|
|
|
|
+#define cpu_to_le8(x) (x)
|
|
|
|
+
|
|
|
|
+static int uvcg_config_compare_u32(const void *l, const void *r)
|
|
|
|
+{
|
|
|
|
+ u32 li = *(const u32 *)l;
|
|
|
|
+ u32 ri = *(const u32 *)r;
|
|
|
|
+
|
|
|
|
+ return li < ri ? -1 : li == ri ? 0 : 1;
|
|
|
|
+}
|
|
|
|
+
|
|
static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
|
|
static inline struct f_uvc_opts *to_f_uvc_opts(struct config_item *item)
|
|
{
|
|
{
|
|
return container_of(to_config_group(item), struct f_uvc_opts,
|
|
return container_of(to_config_group(item), struct f_uvc_opts,
|
|
func_inst.group);
|
|
func_inst.group);
|
|
}
|
|
}
|
|
|
|
|
|
-/* control/header/<NAME> */
|
|
|
|
|
|
+struct uvcg_config_group_type {
|
|
|
|
+ struct config_item_type type;
|
|
|
|
+ const char *name;
|
|
|
|
+ const struct uvcg_config_group_type **children;
|
|
|
|
+ int (*create_children)(struct config_group *group);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static void uvcg_config_item_release(struct config_item *item)
|
|
|
|
+{
|
|
|
|
+ struct config_group *group = to_config_group(item);
|
|
|
|
+
|
|
|
|
+ kfree(group);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static struct configfs_item_operations uvcg_config_item_ops = {
|
|
|
|
+ .release = uvcg_config_item_release,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static int uvcg_config_create_group(struct config_group *parent,
|
|
|
|
+ const struct uvcg_config_group_type *type);
|
|
|
|
+
|
|
|
|
+static int uvcg_config_create_children(struct config_group *group,
|
|
|
|
+ const struct uvcg_config_group_type *type)
|
|
|
|
+{
|
|
|
|
+ const struct uvcg_config_group_type **child;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (type->create_children)
|
|
|
|
+ return type->create_children(group);
|
|
|
|
+
|
|
|
|
+ for (child = type->children; child && *child; ++child) {
|
|
|
|
+ ret = uvcg_config_create_group(group, *child);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static int uvcg_config_create_group(struct config_group *parent,
|
|
|
|
+ const struct uvcg_config_group_type *type)
|
|
|
|
+{
|
|
|
|
+ struct config_group *group;
|
|
|
|
+
|
|
|
|
+ group = kzalloc(sizeof(*group), GFP_KERNEL);
|
|
|
|
+ if (!group)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ config_group_init_type_name(group, type->name, &type->type);
|
|
|
|
+ configfs_add_default_group(group, parent);
|
|
|
|
+
|
|
|
|
+ return uvcg_config_create_children(group, type);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void uvcg_config_remove_children(struct config_group *group)
|
|
|
|
+{
|
|
|
|
+ struct config_group *child, *n;
|
|
|
|
+
|
|
|
|
+ list_for_each_entry_safe(child, n, &group->default_groups, group_entry) {
|
|
|
|
+ list_del(&child->group_entry);
|
|
|
|
+ uvcg_config_remove_children(child);
|
|
|
|
+ config_item_put(&child->cg_item);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/header/<NAME>
|
|
|
|
+ * control/header
|
|
|
|
+ */
|
|
|
|
+
|
|
DECLARE_UVC_HEADER_DESCRIPTOR(1);
|
|
DECLARE_UVC_HEADER_DESCRIPTOR(1);
|
|
|
|
|
|
struct uvcg_control_header {
|
|
struct uvcg_control_header {
|
|
@@ -51,9 +138,9 @@ static struct uvcg_control_header *to_uvcg_control_header(struct config_item *it
|
|
return container_of(item, struct uvcg_control_header, item);
|
|
return container_of(item, struct uvcg_control_header, item);
|
|
}
|
|
}
|
|
|
|
|
|
-#define UVCG_CTRL_HDR_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
|
|
|
|
|
|
+#define UVCG_CTRL_HDR_ATTR(cname, aname, bits, limit) \
|
|
static ssize_t uvcg_control_header_##cname##_show( \
|
|
static ssize_t uvcg_control_header_##cname##_show( \
|
|
- struct config_item *item, char *page) \
|
|
|
|
|
|
+ struct config_item *item, char *page) \
|
|
{ \
|
|
{ \
|
|
struct uvcg_control_header *ch = to_uvcg_control_header(item); \
|
|
struct uvcg_control_header *ch = to_uvcg_control_header(item); \
|
|
struct f_uvc_opts *opts; \
|
|
struct f_uvc_opts *opts; \
|
|
@@ -67,7 +154,7 @@ static ssize_t uvcg_control_header_##cname##_show( \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(ch->desc.aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(ch->desc.aname));\
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -83,7 +170,7 @@ uvcg_control_header_##cname##_store(struct config_item *item, \
|
|
struct config_item *opts_item; \
|
|
struct config_item *opts_item; \
|
|
struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
|
|
struct mutex *su_mutex = &ch->item.ci_group->cg_subsys->su_mutex;\
|
|
int ret; \
|
|
int ret; \
|
|
- uxx num; \
|
|
|
|
|
|
+ u##bits num; \
|
|
\
|
|
\
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
\
|
|
\
|
|
@@ -96,7 +183,7 @@ uvcg_control_header_##cname##_store(struct config_item *item, \
|
|
goto end; \
|
|
goto end; \
|
|
} \
|
|
} \
|
|
\
|
|
\
|
|
- ret = str2u(page, 0, &num); \
|
|
|
|
|
|
+ ret = kstrtou##bits(page, 0, &num); \
|
|
if (ret) \
|
|
if (ret) \
|
|
goto end; \
|
|
goto end; \
|
|
\
|
|
\
|
|
@@ -104,7 +191,7 @@ uvcg_control_header_##cname##_store(struct config_item *item, \
|
|
ret = -EINVAL; \
|
|
ret = -EINVAL; \
|
|
goto end; \
|
|
goto end; \
|
|
} \
|
|
} \
|
|
- ch->desc.aname = vnoc(num); \
|
|
|
|
|
|
+ ch->desc.aname = cpu_to_le##bits(num); \
|
|
ret = len; \
|
|
ret = len; \
|
|
end: \
|
|
end: \
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
@@ -114,11 +201,9 @@ end: \
|
|
\
|
|
\
|
|
UVC_ATTR(uvcg_control_header_, cname, aname)
|
|
UVC_ATTR(uvcg_control_header_, cname, aname)
|
|
|
|
|
|
-UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, le16_to_cpu, kstrtou16, u16, cpu_to_le16,
|
|
|
|
- 0xffff);
|
|
|
|
|
|
+UVCG_CTRL_HDR_ATTR(bcd_uvc, bcdUVC, 16, 0xffff);
|
|
|
|
|
|
-UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, le32_to_cpu, kstrtou32,
|
|
|
|
- u32, cpu_to_le32, 0x7fffffff);
|
|
|
|
|
|
+UVCG_CTRL_HDR_ATTR(dw_clock_frequency, dwClockFrequency, 32, 0x7fffffff);
|
|
|
|
|
|
#undef UVCG_CTRL_HDR_ATTR
|
|
#undef UVCG_CTRL_HDR_ATTR
|
|
|
|
|
|
@@ -129,6 +214,7 @@ static struct configfs_attribute *uvcg_control_header_attrs[] = {
|
|
};
|
|
};
|
|
|
|
|
|
static const struct config_item_type uvcg_control_header_type = {
|
|
static const struct config_item_type uvcg_control_header_type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
.ct_attrs = uvcg_control_header_attrs,
|
|
.ct_attrs = uvcg_control_header_attrs,
|
|
.ct_owner = THIS_MODULE,
|
|
.ct_owner = THIS_MODULE,
|
|
};
|
|
};
|
|
@@ -153,60 +239,42 @@ static struct config_item *uvcg_control_header_make(struct config_group *group,
|
|
return &h->item;
|
|
return &h->item;
|
|
}
|
|
}
|
|
|
|
|
|
-static void uvcg_control_header_drop(struct config_group *group,
|
|
|
|
- struct config_item *item)
|
|
|
|
-{
|
|
|
|
- struct uvcg_control_header *h = to_uvcg_control_header(item);
|
|
|
|
-
|
|
|
|
- kfree(h);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/* control/header */
|
|
|
|
-static struct uvcg_control_header_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_control_header_grp;
|
|
|
|
-
|
|
|
|
static struct configfs_group_operations uvcg_control_header_grp_ops = {
|
|
static struct configfs_group_operations uvcg_control_header_grp_ops = {
|
|
.make_item = uvcg_control_header_make,
|
|
.make_item = uvcg_control_header_make,
|
|
- .drop_item = uvcg_control_header_drop,
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-static const struct config_item_type uvcg_control_header_grp_type = {
|
|
|
|
- .ct_group_ops = &uvcg_control_header_grp_ops,
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_control_header_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_group_ops = &uvcg_control_header_grp_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "header",
|
|
};
|
|
};
|
|
|
|
|
|
-/* control/processing/default */
|
|
|
|
-static struct uvcg_default_processing {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_default_processing;
|
|
|
|
-
|
|
|
|
-static inline struct uvcg_default_processing
|
|
|
|
-*to_uvcg_default_processing(struct config_item *item)
|
|
|
|
-{
|
|
|
|
- return container_of(to_config_group(item),
|
|
|
|
- struct uvcg_default_processing, group);
|
|
|
|
-}
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/processing/default
|
|
|
|
+ */
|
|
|
|
|
|
-#define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, conv) \
|
|
|
|
|
|
+#define UVCG_DEFAULT_PROCESSING_ATTR(cname, aname, bits) \
|
|
static ssize_t uvcg_default_processing_##cname##_show( \
|
|
static ssize_t uvcg_default_processing_##cname##_show( \
|
|
struct config_item *item, char *page) \
|
|
struct config_item *item, char *page) \
|
|
{ \
|
|
{ \
|
|
- struct uvcg_default_processing *dp = to_uvcg_default_processing(item); \
|
|
|
|
|
|
+ struct config_group *group = to_config_group(item); \
|
|
struct f_uvc_opts *opts; \
|
|
struct f_uvc_opts *opts; \
|
|
struct config_item *opts_item; \
|
|
struct config_item *opts_item; \
|
|
- struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex; \
|
|
|
|
|
|
+ struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
|
|
struct uvc_processing_unit_descriptor *pd; \
|
|
struct uvc_processing_unit_descriptor *pd; \
|
|
int result; \
|
|
int result; \
|
|
\
|
|
\
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
\
|
|
\
|
|
- opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent; \
|
|
|
|
|
|
+ opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
pd = &opts->uvc_processing; \
|
|
pd = &opts->uvc_processing; \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(pd->aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(pd->aname)); \
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -215,37 +283,33 @@ static ssize_t uvcg_default_processing_##cname##_show( \
|
|
\
|
|
\
|
|
UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
|
|
UVC_ATTR_RO(uvcg_default_processing_, cname, aname)
|
|
|
|
|
|
-#define identity_conv(x) (x)
|
|
|
|
-
|
|
|
|
-UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, identity_conv);
|
|
|
|
-UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, identity_conv);
|
|
|
|
-UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, le16_to_cpu);
|
|
|
|
-UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, identity_conv);
|
|
|
|
-
|
|
|
|
-#undef identity_conv
|
|
|
|
|
|
+UVCG_DEFAULT_PROCESSING_ATTR(b_unit_id, bUnitID, 8);
|
|
|
|
+UVCG_DEFAULT_PROCESSING_ATTR(b_source_id, bSourceID, 8);
|
|
|
|
+UVCG_DEFAULT_PROCESSING_ATTR(w_max_multiplier, wMaxMultiplier, 16);
|
|
|
|
+UVCG_DEFAULT_PROCESSING_ATTR(i_processing, iProcessing, 8);
|
|
|
|
|
|
#undef UVCG_DEFAULT_PROCESSING_ATTR
|
|
#undef UVCG_DEFAULT_PROCESSING_ATTR
|
|
|
|
|
|
static ssize_t uvcg_default_processing_bm_controls_show(
|
|
static ssize_t uvcg_default_processing_bm_controls_show(
|
|
struct config_item *item, char *page)
|
|
struct config_item *item, char *page)
|
|
{
|
|
{
|
|
- struct uvcg_default_processing *dp = to_uvcg_default_processing(item);
|
|
|
|
|
|
+ struct config_group *group = to_config_group(item);
|
|
struct f_uvc_opts *opts;
|
|
struct f_uvc_opts *opts;
|
|
struct config_item *opts_item;
|
|
struct config_item *opts_item;
|
|
- struct mutex *su_mutex = &dp->group.cg_subsys->su_mutex;
|
|
|
|
|
|
+ struct mutex *su_mutex = &group->cg_subsys->su_mutex;
|
|
struct uvc_processing_unit_descriptor *pd;
|
|
struct uvc_processing_unit_descriptor *pd;
|
|
int result, i;
|
|
int result, i;
|
|
char *pg = page;
|
|
char *pg = page;
|
|
|
|
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */
|
|
|
|
|
|
- opts_item = dp->group.cg_item.ci_parent->ci_parent->ci_parent;
|
|
|
|
|
|
+ opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
|
|
opts = to_f_uvc_opts(opts_item);
|
|
opts = to_f_uvc_opts(opts_item);
|
|
pd = &opts->uvc_processing;
|
|
pd = &opts->uvc_processing;
|
|
|
|
|
|
mutex_lock(&opts->lock);
|
|
mutex_lock(&opts->lock);
|
|
for (result = 0, i = 0; i < pd->bControlSize; ++i) {
|
|
for (result = 0, i = 0; i < pd->bControlSize; ++i) {
|
|
- result += sprintf(pg, "%d\n", pd->bmControls[i]);
|
|
|
|
|
|
+ result += sprintf(pg, "%u\n", pd->bmControls[i]);
|
|
pg = page + result;
|
|
pg = page + result;
|
|
}
|
|
}
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
@@ -266,54 +330,55 @@ static struct configfs_attribute *uvcg_default_processing_attrs[] = {
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
|
|
-static const struct config_item_type uvcg_default_processing_type = {
|
|
|
|
- .ct_attrs = uvcg_default_processing_attrs,
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_default_processing_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_attrs = uvcg_default_processing_attrs,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "default",
|
|
};
|
|
};
|
|
|
|
|
|
-/* struct uvcg_processing {}; */
|
|
|
|
-
|
|
|
|
-/* control/processing */
|
|
|
|
-static struct uvcg_processing_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_processing_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/processing
|
|
|
|
+ */
|
|
|
|
|
|
-static const struct config_item_type uvcg_processing_grp_type = {
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_processing_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "processing",
|
|
|
|
+ .children = (const struct uvcg_config_group_type*[]) {
|
|
|
|
+ &uvcg_default_processing_type,
|
|
|
|
+ NULL,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
-/* control/terminal/camera/default */
|
|
|
|
-static struct uvcg_default_camera {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_default_camera;
|
|
|
|
-
|
|
|
|
-static inline struct uvcg_default_camera
|
|
|
|
-*to_uvcg_default_camera(struct config_item *item)
|
|
|
|
-{
|
|
|
|
- return container_of(to_config_group(item),
|
|
|
|
- struct uvcg_default_camera, group);
|
|
|
|
-}
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/terminal/camera/default
|
|
|
|
+ */
|
|
|
|
|
|
-#define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, conv) \
|
|
|
|
|
|
+#define UVCG_DEFAULT_CAMERA_ATTR(cname, aname, bits) \
|
|
static ssize_t uvcg_default_camera_##cname##_show( \
|
|
static ssize_t uvcg_default_camera_##cname##_show( \
|
|
struct config_item *item, char *page) \
|
|
struct config_item *item, char *page) \
|
|
{ \
|
|
{ \
|
|
- struct uvcg_default_camera *dc = to_uvcg_default_camera(item); \
|
|
|
|
|
|
+ struct config_group *group = to_config_group(item); \
|
|
struct f_uvc_opts *opts; \
|
|
struct f_uvc_opts *opts; \
|
|
struct config_item *opts_item; \
|
|
struct config_item *opts_item; \
|
|
- struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
|
|
|
|
|
|
+ struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
|
|
struct uvc_camera_terminal_descriptor *cd; \
|
|
struct uvc_camera_terminal_descriptor *cd; \
|
|
int result; \
|
|
int result; \
|
|
\
|
|
\
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
\
|
|
\
|
|
- opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent-> \
|
|
|
|
|
|
+ opts_item = group->cg_item.ci_parent->ci_parent->ci_parent-> \
|
|
ci_parent; \
|
|
ci_parent; \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
cd = &opts->uvc_camera_terminal; \
|
|
cd = &opts->uvc_camera_terminal; \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(cd->aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -323,44 +388,40 @@ static ssize_t uvcg_default_camera_##cname##_show( \
|
|
\
|
|
\
|
|
UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
|
|
UVC_ATTR_RO(uvcg_default_camera_, cname, aname)
|
|
|
|
|
|
-#define identity_conv(x) (x)
|
|
|
|
-
|
|
|
|
-UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, identity_conv);
|
|
|
|
-UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, le16_to_cpu);
|
|
|
|
-UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, identity_conv);
|
|
|
|
-UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, identity_conv);
|
|
|
|
|
|
+UVCG_DEFAULT_CAMERA_ATTR(b_terminal_id, bTerminalID, 8);
|
|
|
|
+UVCG_DEFAULT_CAMERA_ATTR(w_terminal_type, wTerminalType, 16);
|
|
|
|
+UVCG_DEFAULT_CAMERA_ATTR(b_assoc_terminal, bAssocTerminal, 8);
|
|
|
|
+UVCG_DEFAULT_CAMERA_ATTR(i_terminal, iTerminal, 8);
|
|
UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin,
|
|
UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_min, wObjectiveFocalLengthMin,
|
|
- le16_to_cpu);
|
|
|
|
|
|
+ 16);
|
|
UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax,
|
|
UVCG_DEFAULT_CAMERA_ATTR(w_objective_focal_length_max, wObjectiveFocalLengthMax,
|
|
- le16_to_cpu);
|
|
|
|
|
|
+ 16);
|
|
UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
|
|
UVCG_DEFAULT_CAMERA_ATTR(w_ocular_focal_length, wOcularFocalLength,
|
|
- le16_to_cpu);
|
|
|
|
-
|
|
|
|
-#undef identity_conv
|
|
|
|
|
|
+ 16);
|
|
|
|
|
|
#undef UVCG_DEFAULT_CAMERA_ATTR
|
|
#undef UVCG_DEFAULT_CAMERA_ATTR
|
|
|
|
|
|
static ssize_t uvcg_default_camera_bm_controls_show(
|
|
static ssize_t uvcg_default_camera_bm_controls_show(
|
|
struct config_item *item, char *page)
|
|
struct config_item *item, char *page)
|
|
{
|
|
{
|
|
- struct uvcg_default_camera *dc = to_uvcg_default_camera(item);
|
|
|
|
|
|
+ struct config_group *group = to_config_group(item);
|
|
struct f_uvc_opts *opts;
|
|
struct f_uvc_opts *opts;
|
|
struct config_item *opts_item;
|
|
struct config_item *opts_item;
|
|
- struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex;
|
|
|
|
|
|
+ struct mutex *su_mutex = &group->cg_subsys->su_mutex;
|
|
struct uvc_camera_terminal_descriptor *cd;
|
|
struct uvc_camera_terminal_descriptor *cd;
|
|
int result, i;
|
|
int result, i;
|
|
char *pg = page;
|
|
char *pg = page;
|
|
|
|
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */
|
|
|
|
|
|
- opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent->
|
|
|
|
|
|
+ opts_item = group->cg_item.ci_parent->ci_parent->ci_parent->
|
|
ci_parent;
|
|
ci_parent;
|
|
opts = to_f_uvc_opts(opts_item);
|
|
opts = to_f_uvc_opts(opts_item);
|
|
cd = &opts->uvc_camera_terminal;
|
|
cd = &opts->uvc_camera_terminal;
|
|
|
|
|
|
mutex_lock(&opts->lock);
|
|
mutex_lock(&opts->lock);
|
|
for (result = 0, i = 0; i < cd->bControlSize; ++i) {
|
|
for (result = 0, i = 0; i < cd->bControlSize; ++i) {
|
|
- result += sprintf(pg, "%d\n", cd->bmControls[i]);
|
|
|
|
|
|
+ result += sprintf(pg, "%u\n", cd->bmControls[i]);
|
|
pg = page + result;
|
|
pg = page + result;
|
|
}
|
|
}
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
@@ -383,54 +444,55 @@ static struct configfs_attribute *uvcg_default_camera_attrs[] = {
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
|
|
-static const struct config_item_type uvcg_default_camera_type = {
|
|
|
|
- .ct_attrs = uvcg_default_camera_attrs,
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_default_camera_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_attrs = uvcg_default_camera_attrs,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "default",
|
|
};
|
|
};
|
|
|
|
|
|
-/* struct uvcg_camera {}; */
|
|
|
|
-
|
|
|
|
-/* control/terminal/camera */
|
|
|
|
-static struct uvcg_camera_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_camera_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/terminal/camera
|
|
|
|
+ */
|
|
|
|
|
|
-static const struct config_item_type uvcg_camera_grp_type = {
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_camera_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "camera",
|
|
|
|
+ .children = (const struct uvcg_config_group_type*[]) {
|
|
|
|
+ &uvcg_default_camera_type,
|
|
|
|
+ NULL,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
-/* control/terminal/output/default */
|
|
|
|
-static struct uvcg_default_output {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_default_output;
|
|
|
|
-
|
|
|
|
-static inline struct uvcg_default_output
|
|
|
|
-*to_uvcg_default_output(struct config_item *item)
|
|
|
|
-{
|
|
|
|
- return container_of(to_config_group(item),
|
|
|
|
- struct uvcg_default_output, group);
|
|
|
|
-}
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/terminal/output/default
|
|
|
|
+ */
|
|
|
|
|
|
-#define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, conv) \
|
|
|
|
|
|
+#define UVCG_DEFAULT_OUTPUT_ATTR(cname, aname, bits) \
|
|
static ssize_t uvcg_default_output_##cname##_show( \
|
|
static ssize_t uvcg_default_output_##cname##_show( \
|
|
- struct config_item *item, char *page) \
|
|
|
|
|
|
+ struct config_item *item, char *page) \
|
|
{ \
|
|
{ \
|
|
- struct uvcg_default_output *dout = to_uvcg_default_output(item); \
|
|
|
|
|
|
+ struct config_group *group = to_config_group(item); \
|
|
struct f_uvc_opts *opts; \
|
|
struct f_uvc_opts *opts; \
|
|
struct config_item *opts_item; \
|
|
struct config_item *opts_item; \
|
|
- struct mutex *su_mutex = &dout->group.cg_subsys->su_mutex; \
|
|
|
|
|
|
+ struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
|
|
struct uvc_output_terminal_descriptor *cd; \
|
|
struct uvc_output_terminal_descriptor *cd; \
|
|
int result; \
|
|
int result; \
|
|
\
|
|
\
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
\
|
|
\
|
|
- opts_item = dout->group.cg_item.ci_parent->ci_parent-> \
|
|
|
|
|
|
+ opts_item = group->cg_item.ci_parent->ci_parent-> \
|
|
ci_parent->ci_parent; \
|
|
ci_parent->ci_parent; \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
cd = &opts->uvc_output_terminal; \
|
|
cd = &opts->uvc_output_terminal; \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(cd->aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -440,15 +502,11 @@ static ssize_t uvcg_default_output_##cname##_show( \
|
|
\
|
|
\
|
|
UVC_ATTR_RO(uvcg_default_output_, cname, aname)
|
|
UVC_ATTR_RO(uvcg_default_output_, cname, aname)
|
|
|
|
|
|
-#define identity_conv(x) (x)
|
|
|
|
-
|
|
|
|
-UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, identity_conv);
|
|
|
|
-UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, le16_to_cpu);
|
|
|
|
-UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, identity_conv);
|
|
|
|
-UVCG_DEFAULT_OUTPUT_ATTR(b_source_id, bSourceID, identity_conv);
|
|
|
|
-UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, identity_conv);
|
|
|
|
-
|
|
|
|
-#undef identity_conv
|
|
|
|
|
|
+UVCG_DEFAULT_OUTPUT_ATTR(b_terminal_id, bTerminalID, 8);
|
|
|
|
+UVCG_DEFAULT_OUTPUT_ATTR(w_terminal_type, wTerminalType, 16);
|
|
|
|
+UVCG_DEFAULT_OUTPUT_ATTR(b_assoc_terminal, bAssocTerminal, 8);
|
|
|
|
+UVCG_DEFAULT_OUTPUT_ATTR(b_source_id, bSourceID, 8);
|
|
|
|
+UVCG_DEFAULT_OUTPUT_ATTR(i_terminal, iTerminal, 8);
|
|
|
|
|
|
#undef UVCG_DEFAULT_OUTPUT_ATTR
|
|
#undef UVCG_DEFAULT_OUTPUT_ATTR
|
|
|
|
|
|
@@ -461,47 +519,68 @@ static struct configfs_attribute *uvcg_default_output_attrs[] = {
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
|
|
-static const struct config_item_type uvcg_default_output_type = {
|
|
|
|
- .ct_attrs = uvcg_default_output_attrs,
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_default_output_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_attrs = uvcg_default_output_attrs,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "default",
|
|
};
|
|
};
|
|
|
|
|
|
-/* struct uvcg_output {}; */
|
|
|
|
-
|
|
|
|
-/* control/terminal/output */
|
|
|
|
-static struct uvcg_output_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_output_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/terminal/output
|
|
|
|
+ */
|
|
|
|
|
|
-static const struct config_item_type uvcg_output_grp_type = {
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_output_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "output",
|
|
|
|
+ .children = (const struct uvcg_config_group_type*[]) {
|
|
|
|
+ &uvcg_default_output_type,
|
|
|
|
+ NULL,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
-/* control/terminal */
|
|
|
|
-static struct uvcg_terminal_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_terminal_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/terminal
|
|
|
|
+ */
|
|
|
|
|
|
-static const struct config_item_type uvcg_terminal_grp_type = {
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_terminal_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "terminal",
|
|
|
|
+ .children = (const struct uvcg_config_group_type*[]) {
|
|
|
|
+ &uvcg_camera_grp_type,
|
|
|
|
+ &uvcg_output_grp_type,
|
|
|
|
+ NULL,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
-/* control/class/{fs} */
|
|
|
|
-static struct uvcg_control_class {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_control_class_fs, uvcg_control_class_ss;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/class/{fs|ss}
|
|
|
|
+ */
|
|
|
|
|
|
|
|
+struct uvcg_control_class_group {
|
|
|
|
+ struct config_group group;
|
|
|
|
+ const char *name;
|
|
|
|
+};
|
|
|
|
|
|
static inline struct uvc_descriptor_header
|
|
static inline struct uvc_descriptor_header
|
|
**uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o)
|
|
**uvcg_get_ctl_class_arr(struct config_item *i, struct f_uvc_opts *o)
|
|
{
|
|
{
|
|
- struct uvcg_control_class *cl = container_of(to_config_group(i),
|
|
|
|
- struct uvcg_control_class, group);
|
|
|
|
|
|
+ struct uvcg_control_class_group *group =
|
|
|
|
+ container_of(i, struct uvcg_control_class_group,
|
|
|
|
+ group.cg_item);
|
|
|
|
|
|
- if (cl == &uvcg_control_class_fs)
|
|
|
|
|
|
+ if (!strcmp(group->name, "fs"))
|
|
return o->uvc_fs_control_cls;
|
|
return o->uvc_fs_control_cls;
|
|
|
|
|
|
- if (cl == &uvcg_control_class_ss)
|
|
|
|
|
|
+ if (!strcmp(group->name, "ss"))
|
|
return o->uvc_ss_control_cls;
|
|
return o->uvc_ss_control_cls;
|
|
|
|
|
|
return NULL;
|
|
return NULL;
|
|
@@ -544,6 +623,7 @@ static int uvcg_control_class_allow_link(struct config_item *src,
|
|
unlock:
|
|
unlock:
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
out:
|
|
out:
|
|
|
|
+ config_item_put(header);
|
|
mutex_unlock(su_mutex);
|
|
mutex_unlock(su_mutex);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -579,10 +659,12 @@ static void uvcg_control_class_drop_link(struct config_item *src,
|
|
unlock:
|
|
unlock:
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
out:
|
|
out:
|
|
|
|
+ config_item_put(header);
|
|
mutex_unlock(su_mutex);
|
|
mutex_unlock(su_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
static struct configfs_item_operations uvcg_control_class_item_ops = {
|
|
static struct configfs_item_operations uvcg_control_class_item_ops = {
|
|
|
|
+ .release = uvcg_config_item_release,
|
|
.allow_link = uvcg_control_class_allow_link,
|
|
.allow_link = uvcg_control_class_allow_link,
|
|
.drop_link = uvcg_control_class_drop_link,
|
|
.drop_link = uvcg_control_class_drop_link,
|
|
};
|
|
};
|
|
@@ -592,37 +674,99 @@ static const struct config_item_type uvcg_control_class_type = {
|
|
.ct_owner = THIS_MODULE,
|
|
.ct_owner = THIS_MODULE,
|
|
};
|
|
};
|
|
|
|
|
|
-/* control/class */
|
|
|
|
-static struct uvcg_control_class_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_control_class_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control/class
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static int uvcg_control_class_create_children(struct config_group *parent)
|
|
|
|
+{
|
|
|
|
+ static const char * const names[] = { "fs", "ss" };
|
|
|
|
+ unsigned int i;
|
|
|
|
|
|
-static const struct config_item_type uvcg_control_class_grp_type = {
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(names); ++i) {
|
|
|
|
+ struct uvcg_control_class_group *group;
|
|
|
|
+
|
|
|
|
+ group = kzalloc(sizeof(*group), GFP_KERNEL);
|
|
|
|
+ if (!group)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
+
|
|
|
|
+ group->name = names[i];
|
|
|
|
+
|
|
|
|
+ config_group_init_type_name(&group->group, group->name,
|
|
|
|
+ &uvcg_control_class_type);
|
|
|
|
+ configfs_add_default_group(&group->group, parent);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const struct uvcg_config_group_type uvcg_control_class_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "class",
|
|
|
|
+ .create_children = uvcg_control_class_create_children,
|
|
};
|
|
};
|
|
|
|
|
|
-/* control */
|
|
|
|
-static struct uvcg_control_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_control_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * control
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static ssize_t uvcg_default_control_b_interface_number_show(
|
|
|
|
+ struct config_item *item, char *page)
|
|
|
|
+{
|
|
|
|
+ struct config_group *group = to_config_group(item);
|
|
|
|
+ struct mutex *su_mutex = &group->cg_subsys->su_mutex;
|
|
|
|
+ struct config_item *opts_item;
|
|
|
|
+ struct f_uvc_opts *opts;
|
|
|
|
+ int result = 0;
|
|
|
|
+
|
|
|
|
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
|
|
|
|
+
|
|
|
|
+ opts_item = item->ci_parent;
|
|
|
|
+ opts = to_f_uvc_opts(opts_item);
|
|
|
|
+
|
|
|
|
+ mutex_lock(&opts->lock);
|
|
|
|
+ result += sprintf(page, "%u\n", opts->control_interface);
|
|
|
|
+ mutex_unlock(&opts->lock);
|
|
|
|
+
|
|
|
|
+ mutex_unlock(su_mutex);
|
|
|
|
+
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+UVC_ATTR_RO(uvcg_default_control_, b_interface_number, bInterfaceNumber);
|
|
|
|
|
|
-static const struct config_item_type uvcg_control_grp_type = {
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static struct configfs_attribute *uvcg_default_control_attrs[] = {
|
|
|
|
+ &uvcg_default_control_attr_b_interface_number,
|
|
|
|
+ NULL,
|
|
};
|
|
};
|
|
|
|
|
|
-/* streaming/uncompressed */
|
|
|
|
-static struct uvcg_uncompressed_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_uncompressed_grp;
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_control_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_attrs = uvcg_default_control_attrs,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "control",
|
|
|
|
+ .children = (const struct uvcg_config_group_type*[]) {
|
|
|
|
+ &uvcg_control_header_grp_type,
|
|
|
|
+ &uvcg_processing_grp_type,
|
|
|
|
+ &uvcg_terminal_grp_type,
|
|
|
|
+ &uvcg_control_class_grp_type,
|
|
|
|
+ NULL,
|
|
|
|
+ },
|
|
|
|
+};
|
|
|
|
|
|
-/* streaming/mjpeg */
|
|
|
|
-static struct uvcg_mjpeg_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_mjpeg_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming/uncompressed
|
|
|
|
+ * streaming/mjpeg
|
|
|
|
+ */
|
|
|
|
|
|
-static struct config_item *fmt_parent[] = {
|
|
|
|
- &uvcg_uncompressed_grp.group.cg_item,
|
|
|
|
- &uvcg_mjpeg_grp.group.cg_item,
|
|
|
|
|
|
+static const char * const uvcg_format_names[] = {
|
|
|
|
+ "uncompressed",
|
|
|
|
+ "mjpeg",
|
|
};
|
|
};
|
|
|
|
|
|
enum uvcg_format_type {
|
|
enum uvcg_format_type {
|
|
@@ -706,7 +850,11 @@ struct uvcg_format_ptr {
|
|
struct list_head entry;
|
|
struct list_head entry;
|
|
};
|
|
};
|
|
|
|
|
|
-/* streaming/header/<NAME> */
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming/header/<NAME>
|
|
|
|
+ * streaming/header
|
|
|
|
+ */
|
|
|
|
+
|
|
struct uvcg_streaming_header {
|
|
struct uvcg_streaming_header {
|
|
struct config_item item;
|
|
struct config_item item;
|
|
struct uvc_input_header_descriptor desc;
|
|
struct uvc_input_header_descriptor desc;
|
|
@@ -720,6 +868,8 @@ static struct uvcg_streaming_header *to_uvcg_streaming_header(struct config_item
|
|
return container_of(item, struct uvcg_streaming_header, item);
|
|
return container_of(item, struct uvcg_streaming_header, item);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void uvcg_format_set_indices(struct config_group *fmt);
|
|
|
|
+
|
|
static int uvcg_streaming_header_allow_link(struct config_item *src,
|
|
static int uvcg_streaming_header_allow_link(struct config_item *src,
|
|
struct config_item *target)
|
|
struct config_item *target)
|
|
{
|
|
{
|
|
@@ -744,10 +894,22 @@ static int uvcg_streaming_header_allow_link(struct config_item *src,
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
- for (i = 0; i < ARRAY_SIZE(fmt_parent); ++i)
|
|
|
|
- if (target->ci_parent == fmt_parent[i])
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Linking is only allowed to direct children of the format nodes
|
|
|
|
+ * (streaming/uncompressed or streaming/mjpeg nodes). First check that
|
|
|
|
+ * the grand-parent of the target matches the grand-parent of the source
|
|
|
|
+ * (the streaming node), and then verify that the target parent is a
|
|
|
|
+ * format node.
|
|
|
|
+ */
|
|
|
|
+ if (src->ci_parent->ci_parent != target->ci_parent->ci_parent)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(uvcg_format_names); ++i) {
|
|
|
|
+ if (!strcmp(target->ci_parent->ci_name, uvcg_format_names[i]))
|
|
break;
|
|
break;
|
|
- if (i == ARRAY_SIZE(fmt_parent))
|
|
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (i == ARRAY_SIZE(uvcg_format_names))
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
target_fmt = container_of(to_config_group(target), struct uvcg_format,
|
|
target_fmt = container_of(to_config_group(target), struct uvcg_format,
|
|
@@ -755,6 +917,8 @@ static int uvcg_streaming_header_allow_link(struct config_item *src,
|
|
if (!target_fmt)
|
|
if (!target_fmt)
|
|
goto out;
|
|
goto out;
|
|
|
|
|
|
|
|
+ uvcg_format_set_indices(to_config_group(target));
|
|
|
|
+
|
|
format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
|
|
format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
|
|
if (!format_ptr) {
|
|
if (!format_ptr) {
|
|
ret = -ENOMEM;
|
|
ret = -ENOMEM;
|
|
@@ -764,6 +928,7 @@ static int uvcg_streaming_header_allow_link(struct config_item *src,
|
|
format_ptr->fmt = target_fmt;
|
|
format_ptr->fmt = target_fmt;
|
|
list_add_tail(&format_ptr->entry, &src_hdr->formats);
|
|
list_add_tail(&format_ptr->entry, &src_hdr->formats);
|
|
++src_hdr->num_fmt;
|
|
++src_hdr->num_fmt;
|
|
|
|
+ ++target_fmt->linked;
|
|
|
|
|
|
out:
|
|
out:
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
@@ -801,19 +966,22 @@ static void uvcg_streaming_header_drop_link(struct config_item *src,
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ --target_fmt->linked;
|
|
|
|
+
|
|
out:
|
|
out:
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(su_mutex);
|
|
mutex_unlock(su_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
static struct configfs_item_operations uvcg_streaming_header_item_ops = {
|
|
static struct configfs_item_operations uvcg_streaming_header_item_ops = {
|
|
- .allow_link = uvcg_streaming_header_allow_link,
|
|
|
|
- .drop_link = uvcg_streaming_header_drop_link,
|
|
|
|
|
|
+ .release = uvcg_config_item_release,
|
|
|
|
+ .allow_link = uvcg_streaming_header_allow_link,
|
|
|
|
+ .drop_link = uvcg_streaming_header_drop_link,
|
|
};
|
|
};
|
|
|
|
|
|
-#define UVCG_STREAMING_HEADER_ATTR(cname, aname, conv) \
|
|
|
|
|
|
+#define UVCG_STREAMING_HEADER_ATTR(cname, aname, bits) \
|
|
static ssize_t uvcg_streaming_header_##cname##_show( \
|
|
static ssize_t uvcg_streaming_header_##cname##_show( \
|
|
- struct config_item *item, char *page) \
|
|
|
|
|
|
+ struct config_item *item, char *page) \
|
|
{ \
|
|
{ \
|
|
struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
|
|
struct uvcg_streaming_header *sh = to_uvcg_streaming_header(item); \
|
|
struct f_uvc_opts *opts; \
|
|
struct f_uvc_opts *opts; \
|
|
@@ -827,7 +995,7 @@ static ssize_t uvcg_streaming_header_##cname##_show( \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(sh->desc.aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(sh->desc.aname));\
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -836,16 +1004,11 @@ static ssize_t uvcg_streaming_header_##cname##_show( \
|
|
\
|
|
\
|
|
UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
|
|
UVC_ATTR_RO(uvcg_streaming_header_, cname, aname)
|
|
|
|
|
|
-#define identity_conv(x) (x)
|
|
|
|
-
|
|
|
|
-UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, identity_conv);
|
|
|
|
-UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, identity_conv);
|
|
|
|
-UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod,
|
|
|
|
- identity_conv);
|
|
|
|
-UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, identity_conv);
|
|
|
|
-UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, identity_conv);
|
|
|
|
-
|
|
|
|
-#undef identity_conv
|
|
|
|
|
|
+UVCG_STREAMING_HEADER_ATTR(bm_info, bmInfo, 8);
|
|
|
|
+UVCG_STREAMING_HEADER_ATTR(b_terminal_link, bTerminalLink, 8);
|
|
|
|
+UVCG_STREAMING_HEADER_ATTR(b_still_capture_method, bStillCaptureMethod, 8);
|
|
|
|
+UVCG_STREAMING_HEADER_ATTR(b_trigger_support, bTriggerSupport, 8);
|
|
|
|
+UVCG_STREAMING_HEADER_ATTR(b_trigger_usage, bTriggerUsage, 8);
|
|
|
|
|
|
#undef UVCG_STREAMING_HEADER_ATTR
|
|
#undef UVCG_STREAMING_HEADER_ATTR
|
|
|
|
|
|
@@ -884,31 +1047,26 @@ static struct config_item
|
|
return &h->item;
|
|
return &h->item;
|
|
}
|
|
}
|
|
|
|
|
|
-static void uvcg_streaming_header_drop(struct config_group *group,
|
|
|
|
- struct config_item *item)
|
|
|
|
-{
|
|
|
|
- struct uvcg_streaming_header *h = to_uvcg_streaming_header(item);
|
|
|
|
-
|
|
|
|
- kfree(h);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/* streaming/header */
|
|
|
|
-static struct uvcg_streaming_header_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_streaming_header_grp;
|
|
|
|
-
|
|
|
|
static struct configfs_group_operations uvcg_streaming_header_grp_ops = {
|
|
static struct configfs_group_operations uvcg_streaming_header_grp_ops = {
|
|
.make_item = uvcg_streaming_header_make,
|
|
.make_item = uvcg_streaming_header_make,
|
|
- .drop_item = uvcg_streaming_header_drop,
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-static const struct config_item_type uvcg_streaming_header_grp_type = {
|
|
|
|
- .ct_group_ops = &uvcg_streaming_header_grp_ops,
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_streaming_header_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_group_ops = &uvcg_streaming_header_grp_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "header",
|
|
};
|
|
};
|
|
|
|
|
|
-/* streaming/<mode>/<format>/<NAME> */
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming/<mode>/<format>/<NAME>
|
|
|
|
+ */
|
|
|
|
+
|
|
struct uvcg_frame {
|
|
struct uvcg_frame {
|
|
|
|
+ struct config_item item;
|
|
|
|
+ enum uvcg_format_type fmt_type;
|
|
struct {
|
|
struct {
|
|
u8 b_length;
|
|
u8 b_length;
|
|
u8 b_descriptor_type;
|
|
u8 b_descriptor_type;
|
|
@@ -924,8 +1082,6 @@ struct uvcg_frame {
|
|
u8 b_frame_interval_type;
|
|
u8 b_frame_interval_type;
|
|
} __attribute__((packed)) frame;
|
|
} __attribute__((packed)) frame;
|
|
u32 *dw_frame_interval;
|
|
u32 *dw_frame_interval;
|
|
- enum uvcg_format_type fmt_type;
|
|
|
|
- struct config_item item;
|
|
|
|
};
|
|
};
|
|
|
|
|
|
static struct uvcg_frame *to_uvcg_frame(struct config_item *item)
|
|
static struct uvcg_frame *to_uvcg_frame(struct config_item *item)
|
|
@@ -933,7 +1089,7 @@ static struct uvcg_frame *to_uvcg_frame(struct config_item *item)
|
|
return container_of(item, struct uvcg_frame, item);
|
|
return container_of(item, struct uvcg_frame, item);
|
|
}
|
|
}
|
|
|
|
|
|
-#define UVCG_FRAME_ATTR(cname, aname, to_cpu_endian, to_little_endian, bits) \
|
|
|
|
|
|
+#define UVCG_FRAME_ATTR(cname, aname, bits) \
|
|
static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
|
|
static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
|
|
{ \
|
|
{ \
|
|
struct uvcg_frame *f = to_uvcg_frame(item); \
|
|
struct uvcg_frame *f = to_uvcg_frame(item); \
|
|
@@ -948,7 +1104,7 @@ static ssize_t uvcg_frame_##cname##_show(struct config_item *item, char *page)\
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", to_cpu_endian(f->frame.cname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", f->frame.cname); \
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -963,8 +1119,8 @@ static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
|
|
struct config_item *opts_item; \
|
|
struct config_item *opts_item; \
|
|
struct uvcg_format *fmt; \
|
|
struct uvcg_format *fmt; \
|
|
struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
|
|
struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;\
|
|
|
|
+ typeof(f->frame.cname) num; \
|
|
int ret; \
|
|
int ret; \
|
|
- u##bits num; \
|
|
|
|
\
|
|
\
|
|
ret = kstrtou##bits(page, 0, &num); \
|
|
ret = kstrtou##bits(page, 0, &num); \
|
|
if (ret) \
|
|
if (ret) \
|
|
@@ -982,7 +1138,7 @@ static ssize_t uvcg_frame_##cname##_store(struct config_item *item, \
|
|
goto end; \
|
|
goto end; \
|
|
} \
|
|
} \
|
|
\
|
|
\
|
|
- f->frame.cname = to_little_endian(num); \
|
|
|
|
|
|
+ f->frame.cname = num; \
|
|
ret = len; \
|
|
ret = len; \
|
|
end: \
|
|
end: \
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
@@ -992,20 +1148,48 @@ end: \
|
|
\
|
|
\
|
|
UVC_ATTR(uvcg_frame_, cname, aname);
|
|
UVC_ATTR(uvcg_frame_, cname, aname);
|
|
|
|
|
|
-#define noop_conversion(x) (x)
|
|
|
|
|
|
+static ssize_t uvcg_frame_b_frame_index_show(struct config_item *item,
|
|
|
|
+ char *page)
|
|
|
|
+{
|
|
|
|
+ struct uvcg_frame *f = to_uvcg_frame(item);
|
|
|
|
+ struct uvcg_format *fmt;
|
|
|
|
+ struct f_uvc_opts *opts;
|
|
|
|
+ struct config_item *opts_item;
|
|
|
|
+ struct config_item *fmt_item;
|
|
|
|
+ struct mutex *su_mutex = &f->item.ci_group->cg_subsys->su_mutex;
|
|
|
|
+ int result;
|
|
|
|
+
|
|
|
|
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
|
|
|
|
+
|
|
|
|
+ fmt_item = f->item.ci_parent;
|
|
|
|
+ fmt = to_uvcg_format(fmt_item);
|
|
|
|
|
|
-UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, noop_conversion,
|
|
|
|
- noop_conversion, 8);
|
|
|
|
-UVCG_FRAME_ATTR(w_width, wWidth, le16_to_cpu, cpu_to_le16, 16);
|
|
|
|
-UVCG_FRAME_ATTR(w_height, wHeight, le16_to_cpu, cpu_to_le16, 16);
|
|
|
|
-UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, le32_to_cpu, cpu_to_le32, 32);
|
|
|
|
-UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, le32_to_cpu, cpu_to_le32, 32);
|
|
|
|
-UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize,
|
|
|
|
- le32_to_cpu, cpu_to_le32, 32);
|
|
|
|
-UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval,
|
|
|
|
- le32_to_cpu, cpu_to_le32, 32);
|
|
|
|
|
|
+ if (!fmt->linked) {
|
|
|
|
+ result = -EBUSY;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
|
|
-#undef noop_conversion
|
|
|
|
|
|
+ opts_item = fmt_item->ci_parent->ci_parent->ci_parent;
|
|
|
|
+ opts = to_f_uvc_opts(opts_item);
|
|
|
|
+
|
|
|
|
+ mutex_lock(&opts->lock);
|
|
|
|
+ result = sprintf(page, "%u\n", f->frame.b_frame_index);
|
|
|
|
+ mutex_unlock(&opts->lock);
|
|
|
|
+
|
|
|
|
+out:
|
|
|
|
+ mutex_unlock(su_mutex);
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+UVC_ATTR_RO(uvcg_frame_, b_frame_index, bFrameIndex);
|
|
|
|
+
|
|
|
|
+UVCG_FRAME_ATTR(bm_capabilities, bmCapabilities, 8);
|
|
|
|
+UVCG_FRAME_ATTR(w_width, wWidth, 16);
|
|
|
|
+UVCG_FRAME_ATTR(w_height, wHeight, 16);
|
|
|
|
+UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32);
|
|
|
|
+UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32);
|
|
|
|
+UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32);
|
|
|
|
+UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32);
|
|
|
|
|
|
#undef UVCG_FRAME_ATTR
|
|
#undef UVCG_FRAME_ATTR
|
|
|
|
|
|
@@ -1026,8 +1210,7 @@ static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
|
|
|
|
|
|
mutex_lock(&opts->lock);
|
|
mutex_lock(&opts->lock);
|
|
for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) {
|
|
for (result = 0, i = 0; i < frm->frame.b_frame_interval_type; ++i) {
|
|
- result += sprintf(pg, "%d\n",
|
|
|
|
- le32_to_cpu(frm->dw_frame_interval[i]));
|
|
|
|
|
|
+ result += sprintf(pg, "%u\n", frm->dw_frame_interval[i]);
|
|
pg = page + result;
|
|
pg = page + result;
|
|
}
|
|
}
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
@@ -1052,7 +1235,7 @@ static inline int __uvcg_fill_frm_intrv(char *buf, void *priv)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
interv = priv;
|
|
interv = priv;
|
|
- **interv = cpu_to_le32(num);
|
|
|
|
|
|
+ **interv = num;
|
|
++*interv;
|
|
++*interv;
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
@@ -1129,6 +1312,8 @@ static ssize_t uvcg_frame_dw_frame_interval_store(struct config_item *item,
|
|
kfree(ch->dw_frame_interval);
|
|
kfree(ch->dw_frame_interval);
|
|
ch->dw_frame_interval = frm_intrv;
|
|
ch->dw_frame_interval = frm_intrv;
|
|
ch->frame.b_frame_interval_type = n;
|
|
ch->frame.b_frame_interval_type = n;
|
|
|
|
+ sort(ch->dw_frame_interval, n, sizeof(*ch->dw_frame_interval),
|
|
|
|
+ uvcg_config_compare_u32, NULL);
|
|
ret = len;
|
|
ret = len;
|
|
|
|
|
|
end:
|
|
end:
|
|
@@ -1140,6 +1325,7 @@ end:
|
|
UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
|
|
UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
|
|
|
|
|
|
static struct configfs_attribute *uvcg_frame_attrs[] = {
|
|
static struct configfs_attribute *uvcg_frame_attrs[] = {
|
|
|
|
+ &uvcg_frame_attr_b_frame_index,
|
|
&uvcg_frame_attr_bm_capabilities,
|
|
&uvcg_frame_attr_bm_capabilities,
|
|
&uvcg_frame_attr_w_width,
|
|
&uvcg_frame_attr_w_width,
|
|
&uvcg_frame_attr_w_height,
|
|
&uvcg_frame_attr_w_height,
|
|
@@ -1152,6 +1338,7 @@ static struct configfs_attribute *uvcg_frame_attrs[] = {
|
|
};
|
|
};
|
|
|
|
|
|
static const struct config_item_type uvcg_frame_type = {
|
|
static const struct config_item_type uvcg_frame_type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
.ct_attrs = uvcg_frame_attrs,
|
|
.ct_attrs = uvcg_frame_attrs,
|
|
.ct_owner = THIS_MODULE,
|
|
.ct_owner = THIS_MODULE,
|
|
};
|
|
};
|
|
@@ -1170,12 +1357,12 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
|
|
|
|
|
|
h->frame.b_descriptor_type = USB_DT_CS_INTERFACE;
|
|
h->frame.b_descriptor_type = USB_DT_CS_INTERFACE;
|
|
h->frame.b_frame_index = 1;
|
|
h->frame.b_frame_index = 1;
|
|
- h->frame.w_width = cpu_to_le16(640);
|
|
|
|
- h->frame.w_height = cpu_to_le16(360);
|
|
|
|
- h->frame.dw_min_bit_rate = cpu_to_le32(18432000);
|
|
|
|
- h->frame.dw_max_bit_rate = cpu_to_le32(55296000);
|
|
|
|
- h->frame.dw_max_video_frame_buffer_size = cpu_to_le32(460800);
|
|
|
|
- h->frame.dw_default_frame_interval = cpu_to_le32(666666);
|
|
|
|
|
|
+ h->frame.w_width = 640;
|
|
|
|
+ h->frame.w_height = 360;
|
|
|
|
+ h->frame.dw_min_bit_rate = 18432000;
|
|
|
|
+ h->frame.dw_max_bit_rate = 55296000;
|
|
|
|
+ h->frame.dw_max_video_frame_buffer_size = 460800;
|
|
|
|
+ h->frame.dw_default_frame_interval = 666666;
|
|
|
|
|
|
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
|
|
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
|
|
opts = to_f_uvc_opts(opts_item);
|
|
opts = to_f_uvc_opts(opts_item);
|
|
@@ -1203,7 +1390,6 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
|
|
|
|
|
|
static void uvcg_frame_drop(struct config_group *group, struct config_item *item)
|
|
static void uvcg_frame_drop(struct config_group *group, struct config_item *item)
|
|
{
|
|
{
|
|
- struct uvcg_frame *h = to_uvcg_frame(item);
|
|
|
|
struct uvcg_format *fmt;
|
|
struct uvcg_format *fmt;
|
|
struct f_uvc_opts *opts;
|
|
struct f_uvc_opts *opts;
|
|
struct config_item *opts_item;
|
|
struct config_item *opts_item;
|
|
@@ -1214,11 +1400,31 @@ static void uvcg_frame_drop(struct config_group *group, struct config_item *item
|
|
mutex_lock(&opts->lock);
|
|
mutex_lock(&opts->lock);
|
|
fmt = to_uvcg_format(&group->cg_item);
|
|
fmt = to_uvcg_format(&group->cg_item);
|
|
--fmt->num_frames;
|
|
--fmt->num_frames;
|
|
- kfree(h);
|
|
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
|
|
+
|
|
|
|
+ config_item_put(item);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void uvcg_format_set_indices(struct config_group *fmt)
|
|
|
|
+{
|
|
|
|
+ struct config_item *ci;
|
|
|
|
+ unsigned int i = 1;
|
|
|
|
+
|
|
|
|
+ list_for_each_entry(ci, &fmt->cg_children, ci_entry) {
|
|
|
|
+ struct uvcg_frame *frm;
|
|
|
|
+
|
|
|
|
+ if (ci->ci_type != &uvcg_frame_type)
|
|
|
|
+ continue;
|
|
|
|
+
|
|
|
|
+ frm = to_uvcg_frame(ci);
|
|
|
|
+ frm->frame.b_frame_index = i++;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-/* streaming/uncompressed/<NAME> */
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming/uncompressed/<NAME>
|
|
|
|
+ */
|
|
|
|
+
|
|
struct uvcg_uncompressed {
|
|
struct uvcg_uncompressed {
|
|
struct uvcg_format fmt;
|
|
struct uvcg_format fmt;
|
|
struct uvc_format_uncompressed desc;
|
|
struct uvc_format_uncompressed desc;
|
|
@@ -1290,7 +1496,7 @@ end:
|
|
|
|
|
|
UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
|
|
UVC_ATTR(uvcg_uncompressed_, guid_format, guidFormat);
|
|
|
|
|
|
-#define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, conv) \
|
|
|
|
|
|
+#define UVCG_UNCOMPRESSED_ATTR_RO(cname, aname, bits) \
|
|
static ssize_t uvcg_uncompressed_##cname##_show( \
|
|
static ssize_t uvcg_uncompressed_##cname##_show( \
|
|
struct config_item *item, char *page) \
|
|
struct config_item *item, char *page) \
|
|
{ \
|
|
{ \
|
|
@@ -1306,7 +1512,7 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(u->desc.aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -1315,7 +1521,7 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
|
|
\
|
|
\
|
|
UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
|
|
UVC_ATTR_RO(uvcg_uncompressed_, cname, aname);
|
|
|
|
|
|
-#define UVCG_UNCOMPRESSED_ATTR(cname, aname, conv) \
|
|
|
|
|
|
+#define UVCG_UNCOMPRESSED_ATTR(cname, aname, bits) \
|
|
static ssize_t uvcg_uncompressed_##cname##_show( \
|
|
static ssize_t uvcg_uncompressed_##cname##_show( \
|
|
struct config_item *item, char *page) \
|
|
struct config_item *item, char *page) \
|
|
{ \
|
|
{ \
|
|
@@ -1331,7 +1537,7 @@ static ssize_t uvcg_uncompressed_##cname##_show( \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(u->desc.aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -1378,16 +1584,12 @@ end: \
|
|
\
|
|
\
|
|
UVC_ATTR(uvcg_uncompressed_, cname, aname);
|
|
UVC_ATTR(uvcg_uncompressed_, cname, aname);
|
|
|
|
|
|
-#define identity_conv(x) (x)
|
|
|
|
-
|
|
|
|
-UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, identity_conv);
|
|
|
|
-UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex,
|
|
|
|
- identity_conv);
|
|
|
|
-UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv);
|
|
|
|
-UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv);
|
|
|
|
-UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
|
|
|
|
-
|
|
|
|
-#undef identity_conv
|
|
|
|
|
|
+UVCG_UNCOMPRESSED_ATTR_RO(b_format_index, bFormatIndex, 8);
|
|
|
|
+UVCG_UNCOMPRESSED_ATTR(b_bits_per_pixel, bBitsPerPixel, 8);
|
|
|
|
+UVCG_UNCOMPRESSED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
|
|
|
|
+UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
|
|
|
|
+UVCG_UNCOMPRESSED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
|
|
|
|
+UVCG_UNCOMPRESSED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
|
|
|
|
|
|
#undef UVCG_UNCOMPRESSED_ATTR
|
|
#undef UVCG_UNCOMPRESSED_ATTR
|
|
#undef UVCG_UNCOMPRESSED_ATTR_RO
|
|
#undef UVCG_UNCOMPRESSED_ATTR_RO
|
|
@@ -1410,6 +1612,7 @@ uvcg_uncompressed_bma_controls_store(struct config_item *item,
|
|
UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
|
|
UVC_ATTR(uvcg_uncompressed_, bma_controls, bmaControls);
|
|
|
|
|
|
static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
|
|
static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
|
|
|
|
+ &uvcg_uncompressed_attr_b_format_index,
|
|
&uvcg_uncompressed_attr_guid_format,
|
|
&uvcg_uncompressed_attr_guid_format,
|
|
&uvcg_uncompressed_attr_b_bits_per_pixel,
|
|
&uvcg_uncompressed_attr_b_bits_per_pixel,
|
|
&uvcg_uncompressed_attr_b_default_frame_index,
|
|
&uvcg_uncompressed_attr_b_default_frame_index,
|
|
@@ -1421,6 +1624,7 @@ static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
|
|
};
|
|
};
|
|
|
|
|
|
static const struct config_item_type uvcg_uncompressed_type = {
|
|
static const struct config_item_type uvcg_uncompressed_type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
.ct_group_ops = &uvcg_uncompressed_group_ops,
|
|
.ct_group_ops = &uvcg_uncompressed_group_ops,
|
|
.ct_attrs = uvcg_uncompressed_attrs,
|
|
.ct_attrs = uvcg_uncompressed_attrs,
|
|
.ct_owner = THIS_MODULE,
|
|
.ct_owner = THIS_MODULE,
|
|
@@ -1457,25 +1661,23 @@ static struct config_group *uvcg_uncompressed_make(struct config_group *group,
|
|
return &h->fmt.group;
|
|
return &h->fmt.group;
|
|
}
|
|
}
|
|
|
|
|
|
-static void uvcg_uncompressed_drop(struct config_group *group,
|
|
|
|
- struct config_item *item)
|
|
|
|
-{
|
|
|
|
- struct uvcg_uncompressed *h = to_uvcg_uncompressed(item);
|
|
|
|
-
|
|
|
|
- kfree(h);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static struct configfs_group_operations uvcg_uncompressed_grp_ops = {
|
|
static struct configfs_group_operations uvcg_uncompressed_grp_ops = {
|
|
.make_group = uvcg_uncompressed_make,
|
|
.make_group = uvcg_uncompressed_make,
|
|
- .drop_item = uvcg_uncompressed_drop,
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-static const struct config_item_type uvcg_uncompressed_grp_type = {
|
|
|
|
- .ct_group_ops = &uvcg_uncompressed_grp_ops,
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_uncompressed_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_group_ops = &uvcg_uncompressed_grp_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "uncompressed",
|
|
};
|
|
};
|
|
|
|
|
|
-/* streaming/mjpeg/<NAME> */
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming/mjpeg/<NAME>
|
|
|
|
+ */
|
|
|
|
+
|
|
struct uvcg_mjpeg {
|
|
struct uvcg_mjpeg {
|
|
struct uvcg_format fmt;
|
|
struct uvcg_format fmt;
|
|
struct uvc_format_mjpeg desc;
|
|
struct uvc_format_mjpeg desc;
|
|
@@ -1493,7 +1695,7 @@ static struct configfs_group_operations uvcg_mjpeg_group_ops = {
|
|
.drop_item = uvcg_frame_drop,
|
|
.drop_item = uvcg_frame_drop,
|
|
};
|
|
};
|
|
|
|
|
|
-#define UVCG_MJPEG_ATTR_RO(cname, aname, conv) \
|
|
|
|
|
|
+#define UVCG_MJPEG_ATTR_RO(cname, aname, bits) \
|
|
static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
|
|
static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
|
|
{ \
|
|
{ \
|
|
struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
|
|
struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
|
|
@@ -1508,7 +1710,7 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(u->desc.aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -1517,7 +1719,7 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
|
|
\
|
|
\
|
|
UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
|
|
UVC_ATTR_RO(uvcg_mjpeg_, cname, aname)
|
|
|
|
|
|
-#define UVCG_MJPEG_ATTR(cname, aname, conv) \
|
|
|
|
|
|
+#define UVCG_MJPEG_ATTR(cname, aname, bits) \
|
|
static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
|
|
static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
|
|
{ \
|
|
{ \
|
|
struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
|
|
struct uvcg_mjpeg *u = to_uvcg_mjpeg(item); \
|
|
@@ -1532,7 +1734,7 @@ static ssize_t uvcg_mjpeg_##cname##_show(struct config_item *item, char *page)\
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(u->desc.aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -1579,16 +1781,12 @@ end: \
|
|
\
|
|
\
|
|
UVC_ATTR(uvcg_mjpeg_, cname, aname)
|
|
UVC_ATTR(uvcg_mjpeg_, cname, aname)
|
|
|
|
|
|
-#define identity_conv(x) (x)
|
|
|
|
-
|
|
|
|
-UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex,
|
|
|
|
- identity_conv);
|
|
|
|
-UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, identity_conv);
|
|
|
|
-UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, identity_conv);
|
|
|
|
-UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, identity_conv);
|
|
|
|
-UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, identity_conv);
|
|
|
|
-
|
|
|
|
-#undef identity_conv
|
|
|
|
|
|
+UVCG_MJPEG_ATTR_RO(b_format_index, bFormatIndex, 8);
|
|
|
|
+UVCG_MJPEG_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
|
|
|
|
+UVCG_MJPEG_ATTR_RO(bm_flags, bmFlags, 8);
|
|
|
|
+UVCG_MJPEG_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
|
|
|
|
+UVCG_MJPEG_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
|
|
|
|
+UVCG_MJPEG_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
|
|
|
|
|
|
#undef UVCG_MJPEG_ATTR
|
|
#undef UVCG_MJPEG_ATTR
|
|
#undef UVCG_MJPEG_ATTR_RO
|
|
#undef UVCG_MJPEG_ATTR_RO
|
|
@@ -1611,6 +1809,7 @@ uvcg_mjpeg_bma_controls_store(struct config_item *item,
|
|
UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
|
|
UVC_ATTR(uvcg_mjpeg_, bma_controls, bmaControls);
|
|
|
|
|
|
static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
|
|
static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
|
|
|
|
+ &uvcg_mjpeg_attr_b_format_index,
|
|
&uvcg_mjpeg_attr_b_default_frame_index,
|
|
&uvcg_mjpeg_attr_b_default_frame_index,
|
|
&uvcg_mjpeg_attr_bm_flags,
|
|
&uvcg_mjpeg_attr_bm_flags,
|
|
&uvcg_mjpeg_attr_b_aspect_ratio_x,
|
|
&uvcg_mjpeg_attr_b_aspect_ratio_x,
|
|
@@ -1621,6 +1820,7 @@ static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
|
|
};
|
|
};
|
|
|
|
|
|
static const struct config_item_type uvcg_mjpeg_type = {
|
|
static const struct config_item_type uvcg_mjpeg_type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
.ct_group_ops = &uvcg_mjpeg_group_ops,
|
|
.ct_group_ops = &uvcg_mjpeg_group_ops,
|
|
.ct_attrs = uvcg_mjpeg_attrs,
|
|
.ct_attrs = uvcg_mjpeg_attrs,
|
|
.ct_owner = THIS_MODULE,
|
|
.ct_owner = THIS_MODULE,
|
|
@@ -1651,56 +1851,42 @@ static struct config_group *uvcg_mjpeg_make(struct config_group *group,
|
|
return &h->fmt.group;
|
|
return &h->fmt.group;
|
|
}
|
|
}
|
|
|
|
|
|
-static void uvcg_mjpeg_drop(struct config_group *group,
|
|
|
|
- struct config_item *item)
|
|
|
|
-{
|
|
|
|
- struct uvcg_mjpeg *h = to_uvcg_mjpeg(item);
|
|
|
|
-
|
|
|
|
- kfree(h);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
static struct configfs_group_operations uvcg_mjpeg_grp_ops = {
|
|
static struct configfs_group_operations uvcg_mjpeg_grp_ops = {
|
|
.make_group = uvcg_mjpeg_make,
|
|
.make_group = uvcg_mjpeg_make,
|
|
- .drop_item = uvcg_mjpeg_drop,
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-static const struct config_item_type uvcg_mjpeg_grp_type = {
|
|
|
|
- .ct_group_ops = &uvcg_mjpeg_grp_ops,
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_group_ops = &uvcg_mjpeg_grp_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "mjpeg",
|
|
};
|
|
};
|
|
|
|
|
|
-/* streaming/color_matching/default */
|
|
|
|
-static struct uvcg_default_color_matching {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_default_color_matching;
|
|
|
|
-
|
|
|
|
-static inline struct uvcg_default_color_matching
|
|
|
|
-*to_uvcg_default_color_matching(struct config_item *item)
|
|
|
|
-{
|
|
|
|
- return container_of(to_config_group(item),
|
|
|
|
- struct uvcg_default_color_matching, group);
|
|
|
|
-}
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming/color_matching/default
|
|
|
|
+ */
|
|
|
|
|
|
-#define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, conv) \
|
|
|
|
|
|
+#define UVCG_DEFAULT_COLOR_MATCHING_ATTR(cname, aname, bits) \
|
|
static ssize_t uvcg_default_color_matching_##cname##_show( \
|
|
static ssize_t uvcg_default_color_matching_##cname##_show( \
|
|
- struct config_item *item, char *page) \
|
|
|
|
|
|
+ struct config_item *item, char *page) \
|
|
{ \
|
|
{ \
|
|
- struct uvcg_default_color_matching *dc = \
|
|
|
|
- to_uvcg_default_color_matching(item); \
|
|
|
|
|
|
+ struct config_group *group = to_config_group(item); \
|
|
struct f_uvc_opts *opts; \
|
|
struct f_uvc_opts *opts; \
|
|
struct config_item *opts_item; \
|
|
struct config_item *opts_item; \
|
|
- struct mutex *su_mutex = &dc->group.cg_subsys->su_mutex; \
|
|
|
|
|
|
+ struct mutex *su_mutex = &group->cg_subsys->su_mutex; \
|
|
struct uvc_color_matching_descriptor *cd; \
|
|
struct uvc_color_matching_descriptor *cd; \
|
|
int result; \
|
|
int result; \
|
|
\
|
|
\
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
|
|
\
|
|
\
|
|
- opts_item = dc->group.cg_item.ci_parent->ci_parent->ci_parent; \
|
|
|
|
|
|
+ opts_item = group->cg_item.ci_parent->ci_parent->ci_parent; \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
opts = to_f_uvc_opts(opts_item); \
|
|
cd = &opts->uvc_color_matching; \
|
|
cd = &opts->uvc_color_matching; \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(cd->aname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(cd->aname)); \
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
mutex_unlock(su_mutex); \
|
|
mutex_unlock(su_mutex); \
|
|
@@ -1709,16 +1895,10 @@ static ssize_t uvcg_default_color_matching_##cname##_show( \
|
|
\
|
|
\
|
|
UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
|
|
UVC_ATTR_RO(uvcg_default_color_matching_, cname, aname)
|
|
|
|
|
|
-#define identity_conv(x) (x)
|
|
|
|
-
|
|
|
|
-UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries,
|
|
|
|
- identity_conv);
|
|
|
|
|
|
+UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_color_primaries, bColorPrimaries, 8);
|
|
UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics,
|
|
UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_transfer_characteristics,
|
|
- bTransferCharacteristics, identity_conv);
|
|
|
|
-UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients,
|
|
|
|
- identity_conv);
|
|
|
|
-
|
|
|
|
-#undef identity_conv
|
|
|
|
|
|
+ bTransferCharacteristics, 8);
|
|
|
|
+UVCG_DEFAULT_COLOR_MATCHING_ATTR(b_matrix_coefficients, bMatrixCoefficients, 8);
|
|
|
|
|
|
#undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
|
|
#undef UVCG_DEFAULT_COLOR_MATCHING_ATTR
|
|
|
|
|
|
@@ -1729,41 +1909,54 @@ static struct configfs_attribute *uvcg_default_color_matching_attrs[] = {
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
|
|
-static const struct config_item_type uvcg_default_color_matching_type = {
|
|
|
|
- .ct_attrs = uvcg_default_color_matching_attrs,
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_default_color_matching_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_attrs = uvcg_default_color_matching_attrs,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "default",
|
|
};
|
|
};
|
|
|
|
|
|
-/* struct uvcg_color_matching {}; */
|
|
|
|
-
|
|
|
|
-/* streaming/color_matching */
|
|
|
|
-static struct uvcg_color_matching_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_color_matching_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming/color_matching
|
|
|
|
+ */
|
|
|
|
|
|
-static const struct config_item_type uvcg_color_matching_grp_type = {
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvcg_color_matching_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "color_matching",
|
|
|
|
+ .children = (const struct uvcg_config_group_type*[]) {
|
|
|
|
+ &uvcg_default_color_matching_type,
|
|
|
|
+ NULL,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
-/* streaming/class/{fs|hs|ss} */
|
|
|
|
-static struct uvcg_streaming_class {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_streaming_class_fs, uvcg_streaming_class_hs, uvcg_streaming_class_ss;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming/class/{fs|hs|ss}
|
|
|
|
+ */
|
|
|
|
|
|
|
|
+struct uvcg_streaming_class_group {
|
|
|
|
+ struct config_group group;
|
|
|
|
+ const char *name;
|
|
|
|
+};
|
|
|
|
|
|
static inline struct uvc_descriptor_header
|
|
static inline struct uvc_descriptor_header
|
|
***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o)
|
|
***__uvcg_get_stream_class_arr(struct config_item *i, struct f_uvc_opts *o)
|
|
{
|
|
{
|
|
- struct uvcg_streaming_class *cl = container_of(to_config_group(i),
|
|
|
|
- struct uvcg_streaming_class, group);
|
|
|
|
|
|
+ struct uvcg_streaming_class_group *group =
|
|
|
|
+ container_of(i, struct uvcg_streaming_class_group,
|
|
|
|
+ group.cg_item);
|
|
|
|
|
|
- if (cl == &uvcg_streaming_class_fs)
|
|
|
|
|
|
+ if (!strcmp(group->name, "fs"))
|
|
return &o->uvc_fs_streaming_cls;
|
|
return &o->uvc_fs_streaming_cls;
|
|
|
|
|
|
- if (cl == &uvcg_streaming_class_hs)
|
|
|
|
|
|
+ if (!strcmp(group->name, "hs"))
|
|
return &o->uvc_hs_streaming_cls;
|
|
return &o->uvc_hs_streaming_cls;
|
|
|
|
|
|
- if (cl == &uvcg_streaming_class_ss)
|
|
|
|
|
|
+ if (!strcmp(group->name, "ss"))
|
|
return &o->uvc_ss_streaming_cls;
|
|
return &o->uvc_ss_streaming_cls;
|
|
|
|
|
|
return NULL;
|
|
return NULL;
|
|
@@ -1922,24 +2115,22 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
|
|
struct uvcg_format *fmt = priv1;
|
|
struct uvcg_format *fmt = priv1;
|
|
|
|
|
|
if (fmt->type == UVCG_UNCOMPRESSED) {
|
|
if (fmt->type == UVCG_UNCOMPRESSED) {
|
|
- struct uvc_format_uncompressed *unc = *dest;
|
|
|
|
struct uvcg_uncompressed *u =
|
|
struct uvcg_uncompressed *u =
|
|
container_of(fmt, struct uvcg_uncompressed,
|
|
container_of(fmt, struct uvcg_uncompressed,
|
|
fmt);
|
|
fmt);
|
|
|
|
|
|
|
|
+ u->desc.bFormatIndex = n + 1;
|
|
|
|
+ u->desc.bNumFrameDescriptors = fmt->num_frames;
|
|
memcpy(*dest, &u->desc, sizeof(u->desc));
|
|
memcpy(*dest, &u->desc, sizeof(u->desc));
|
|
*dest += sizeof(u->desc);
|
|
*dest += sizeof(u->desc);
|
|
- unc->bNumFrameDescriptors = fmt->num_frames;
|
|
|
|
- unc->bFormatIndex = n + 1;
|
|
|
|
} else if (fmt->type == UVCG_MJPEG) {
|
|
} else if (fmt->type == UVCG_MJPEG) {
|
|
- struct uvc_format_mjpeg *mjp = *dest;
|
|
|
|
struct uvcg_mjpeg *m =
|
|
struct uvcg_mjpeg *m =
|
|
container_of(fmt, struct uvcg_mjpeg, fmt);
|
|
container_of(fmt, struct uvcg_mjpeg, fmt);
|
|
|
|
|
|
|
|
+ m->desc.bFormatIndex = n + 1;
|
|
|
|
+ m->desc.bNumFrameDescriptors = fmt->num_frames;
|
|
memcpy(*dest, &m->desc, sizeof(m->desc));
|
|
memcpy(*dest, &m->desc, sizeof(m->desc));
|
|
*dest += sizeof(m->desc);
|
|
*dest += sizeof(m->desc);
|
|
- mjp->bNumFrameDescriptors = fmt->num_frames;
|
|
|
|
- mjp->bFormatIndex = n + 1;
|
|
|
|
} else {
|
|
} else {
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
}
|
|
}
|
|
@@ -2038,6 +2229,7 @@ static int uvcg_streaming_class_allow_link(struct config_item *src,
|
|
unlock:
|
|
unlock:
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
out:
|
|
out:
|
|
|
|
+ config_item_put(header);
|
|
mutex_unlock(su_mutex);
|
|
mutex_unlock(su_mutex);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -2078,10 +2270,12 @@ static void uvcg_streaming_class_drop_link(struct config_item *src,
|
|
unlock:
|
|
unlock:
|
|
mutex_unlock(&opts->lock);
|
|
mutex_unlock(&opts->lock);
|
|
out:
|
|
out:
|
|
|
|
+ config_item_put(header);
|
|
mutex_unlock(su_mutex);
|
|
mutex_unlock(su_mutex);
|
|
}
|
|
}
|
|
|
|
|
|
static struct configfs_item_operations uvcg_streaming_class_item_ops = {
|
|
static struct configfs_item_operations uvcg_streaming_class_item_ops = {
|
|
|
|
+ .release = uvcg_config_item_release,
|
|
.allow_link = uvcg_streaming_class_allow_link,
|
|
.allow_link = uvcg_streaming_class_allow_link,
|
|
.drop_link = uvcg_streaming_class_drop_link,
|
|
.drop_link = uvcg_streaming_class_drop_link,
|
|
};
|
|
};
|
|
@@ -2091,36 +2285,109 @@ static const struct config_item_type uvcg_streaming_class_type = {
|
|
.ct_owner = THIS_MODULE,
|
|
.ct_owner = THIS_MODULE,
|
|
};
|
|
};
|
|
|
|
|
|
-/* streaming/class */
|
|
|
|
-static struct uvcg_streaming_class_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_streaming_class_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming/class
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static int uvcg_streaming_class_create_children(struct config_group *parent)
|
|
|
|
+{
|
|
|
|
+ static const char * const names[] = { "fs", "hs", "ss" };
|
|
|
|
+ unsigned int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < ARRAY_SIZE(names); ++i) {
|
|
|
|
+ struct uvcg_streaming_class_group *group;
|
|
|
|
+
|
|
|
|
+ group = kzalloc(sizeof(*group), GFP_KERNEL);
|
|
|
|
+ if (!group)
|
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
-static const struct config_item_type uvcg_streaming_class_grp_type = {
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+ group->name = names[i];
|
|
|
|
+
|
|
|
|
+ config_group_init_type_name(&group->group, group->name,
|
|
|
|
+ &uvcg_streaming_class_type);
|
|
|
|
+ configfs_add_default_group(&group->group, parent);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static const struct uvcg_config_group_type uvcg_streaming_class_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "class",
|
|
|
|
+ .create_children = uvcg_streaming_class_create_children,
|
|
};
|
|
};
|
|
|
|
|
|
-/* streaming */
|
|
|
|
-static struct uvcg_streaming_grp {
|
|
|
|
- struct config_group group;
|
|
|
|
-} uvcg_streaming_grp;
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * streaming
|
|
|
|
+ */
|
|
|
|
|
|
-static const struct config_item_type uvcg_streaming_grp_type = {
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static ssize_t uvcg_default_streaming_b_interface_number_show(
|
|
|
|
+ struct config_item *item, char *page)
|
|
|
|
+{
|
|
|
|
+ struct config_group *group = to_config_group(item);
|
|
|
|
+ struct mutex *su_mutex = &group->cg_subsys->su_mutex;
|
|
|
|
+ struct config_item *opts_item;
|
|
|
|
+ struct f_uvc_opts *opts;
|
|
|
|
+ int result = 0;
|
|
|
|
+
|
|
|
|
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
|
|
|
|
+
|
|
|
|
+ opts_item = item->ci_parent;
|
|
|
|
+ opts = to_f_uvc_opts(opts_item);
|
|
|
|
+
|
|
|
|
+ mutex_lock(&opts->lock);
|
|
|
|
+ result += sprintf(page, "%u\n", opts->streaming_interface);
|
|
|
|
+ mutex_unlock(&opts->lock);
|
|
|
|
+
|
|
|
|
+ mutex_unlock(su_mutex);
|
|
|
|
+
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+UVC_ATTR_RO(uvcg_default_streaming_, b_interface_number, bInterfaceNumber);
|
|
|
|
+
|
|
|
|
+static struct configfs_attribute *uvcg_default_streaming_attrs[] = {
|
|
|
|
+ &uvcg_default_streaming_attr_b_interface_number,
|
|
|
|
+ NULL,
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static const struct uvcg_config_group_type uvcg_streaming_grp_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvcg_config_item_ops,
|
|
|
|
+ .ct_attrs = uvcg_default_streaming_attrs,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "streaming",
|
|
|
|
+ .children = (const struct uvcg_config_group_type*[]) {
|
|
|
|
+ &uvcg_streaming_header_grp_type,
|
|
|
|
+ &uvcg_uncompressed_grp_type,
|
|
|
|
+ &uvcg_mjpeg_grp_type,
|
|
|
|
+ &uvcg_color_matching_grp_type,
|
|
|
|
+ &uvcg_streaming_class_grp_type,
|
|
|
|
+ NULL,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
-static void uvc_attr_release(struct config_item *item)
|
|
|
|
|
|
+/* -----------------------------------------------------------------------------
|
|
|
|
+ * UVC function
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+static void uvc_func_item_release(struct config_item *item)
|
|
{
|
|
{
|
|
struct f_uvc_opts *opts = to_f_uvc_opts(item);
|
|
struct f_uvc_opts *opts = to_f_uvc_opts(item);
|
|
|
|
|
|
|
|
+ uvcg_config_remove_children(to_config_group(item));
|
|
usb_put_function_instance(&opts->func_inst);
|
|
usb_put_function_instance(&opts->func_inst);
|
|
}
|
|
}
|
|
|
|
|
|
-static struct configfs_item_operations uvc_item_ops = {
|
|
|
|
- .release = uvc_attr_release,
|
|
|
|
|
|
+static struct configfs_item_operations uvc_func_item_ops = {
|
|
|
|
+ .release = uvc_func_item_release,
|
|
};
|
|
};
|
|
|
|
|
|
-#define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit) \
|
|
|
|
|
|
+#define UVCG_OPTS_ATTR(cname, aname, limit) \
|
|
static ssize_t f_uvc_opts_##cname##_show( \
|
|
static ssize_t f_uvc_opts_##cname##_show( \
|
|
struct config_item *item, char *page) \
|
|
struct config_item *item, char *page) \
|
|
{ \
|
|
{ \
|
|
@@ -2128,7 +2395,7 @@ static ssize_t f_uvc_opts_##cname##_show( \
|
|
int result; \
|
|
int result; \
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
- result = sprintf(page, "%d\n", conv(opts->cname)); \
|
|
|
|
|
|
+ result = sprintf(page, "%u\n", opts->cname); \
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
\
|
|
\
|
|
return result; \
|
|
return result; \
|
|
@@ -2139,8 +2406,8 @@ f_uvc_opts_##cname##_store(struct config_item *item, \
|
|
const char *page, size_t len) \
|
|
const char *page, size_t len) \
|
|
{ \
|
|
{ \
|
|
struct f_uvc_opts *opts = to_f_uvc_opts(item); \
|
|
struct f_uvc_opts *opts = to_f_uvc_opts(item); \
|
|
|
|
+ unsigned int num; \
|
|
int ret; \
|
|
int ret; \
|
|
- uxx num; \
|
|
|
|
\
|
|
\
|
|
mutex_lock(&opts->lock); \
|
|
mutex_lock(&opts->lock); \
|
|
if (opts->refcnt) { \
|
|
if (opts->refcnt) { \
|
|
@@ -2148,7 +2415,7 @@ f_uvc_opts_##cname##_store(struct config_item *item, \
|
|
goto end; \
|
|
goto end; \
|
|
} \
|
|
} \
|
|
\
|
|
\
|
|
- ret = str2u(page, 0, &num); \
|
|
|
|
|
|
+ ret = kstrtouint(page, 0, &num); \
|
|
if (ret) \
|
|
if (ret) \
|
|
goto end; \
|
|
goto end; \
|
|
\
|
|
\
|
|
@@ -2156,7 +2423,7 @@ f_uvc_opts_##cname##_store(struct config_item *item, \
|
|
ret = -EINVAL; \
|
|
ret = -EINVAL; \
|
|
goto end; \
|
|
goto end; \
|
|
} \
|
|
} \
|
|
- opts->cname = vnoc(num); \
|
|
|
|
|
|
+ opts->cname = num; \
|
|
ret = len; \
|
|
ret = len; \
|
|
end: \
|
|
end: \
|
|
mutex_unlock(&opts->lock); \
|
|
mutex_unlock(&opts->lock); \
|
|
@@ -2165,16 +2432,9 @@ end: \
|
|
\
|
|
\
|
|
UVC_ATTR(f_uvc_opts_, cname, cname)
|
|
UVC_ATTR(f_uvc_opts_, cname, cname)
|
|
|
|
|
|
-#define identity_conv(x) (x)
|
|
|
|
-
|
|
|
|
-UVCG_OPTS_ATTR(streaming_interval, streaming_interval, identity_conv,
|
|
|
|
- kstrtou8, u8, identity_conv, 16);
|
|
|
|
-UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, le16_to_cpu,
|
|
|
|
- kstrtou16, u16, le16_to_cpu, 3072);
|
|
|
|
-UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, identity_conv,
|
|
|
|
- kstrtou8, u8, identity_conv, 15);
|
|
|
|
-
|
|
|
|
-#undef identity_conv
|
|
|
|
|
|
+UVCG_OPTS_ATTR(streaming_interval, streaming_interval, 16);
|
|
|
|
+UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, 3072);
|
|
|
|
+UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15);
|
|
|
|
|
|
#undef UVCG_OPTS_ATTR
|
|
#undef UVCG_OPTS_ATTR
|
|
|
|
|
|
@@ -2185,123 +2445,31 @@ static struct configfs_attribute *uvc_attrs[] = {
|
|
NULL,
|
|
NULL,
|
|
};
|
|
};
|
|
|
|
|
|
-static const struct config_item_type uvc_func_type = {
|
|
|
|
- .ct_item_ops = &uvc_item_ops,
|
|
|
|
- .ct_attrs = uvc_attrs,
|
|
|
|
- .ct_owner = THIS_MODULE,
|
|
|
|
|
|
+static const struct uvcg_config_group_type uvc_func_type = {
|
|
|
|
+ .type = {
|
|
|
|
+ .ct_item_ops = &uvc_func_item_ops,
|
|
|
|
+ .ct_attrs = uvc_attrs,
|
|
|
|
+ .ct_owner = THIS_MODULE,
|
|
|
|
+ },
|
|
|
|
+ .name = "",
|
|
|
|
+ .children = (const struct uvcg_config_group_type*[]) {
|
|
|
|
+ &uvcg_control_grp_type,
|
|
|
|
+ &uvcg_streaming_grp_type,
|
|
|
|
+ NULL,
|
|
|
|
+ },
|
|
};
|
|
};
|
|
|
|
|
|
int uvcg_attach_configfs(struct f_uvc_opts *opts)
|
|
int uvcg_attach_configfs(struct f_uvc_opts *opts)
|
|
{
|
|
{
|
|
- config_group_init_type_name(&uvcg_control_header_grp.group,
|
|
|
|
- "header",
|
|
|
|
- &uvcg_control_header_grp_type);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&uvcg_default_processing.group,
|
|
|
|
- "default", &uvcg_default_processing_type);
|
|
|
|
- config_group_init_type_name(&uvcg_processing_grp.group,
|
|
|
|
- "processing", &uvcg_processing_grp_type);
|
|
|
|
- configfs_add_default_group(&uvcg_default_processing.group,
|
|
|
|
- &uvcg_processing_grp.group);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&uvcg_default_camera.group,
|
|
|
|
- "default", &uvcg_default_camera_type);
|
|
|
|
- config_group_init_type_name(&uvcg_camera_grp.group,
|
|
|
|
- "camera", &uvcg_camera_grp_type);
|
|
|
|
- configfs_add_default_group(&uvcg_default_camera.group,
|
|
|
|
- &uvcg_camera_grp.group);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&uvcg_default_output.group,
|
|
|
|
- "default", &uvcg_default_output_type);
|
|
|
|
- config_group_init_type_name(&uvcg_output_grp.group,
|
|
|
|
- "output", &uvcg_output_grp_type);
|
|
|
|
- configfs_add_default_group(&uvcg_default_output.group,
|
|
|
|
- &uvcg_output_grp.group);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&uvcg_terminal_grp.group,
|
|
|
|
- "terminal", &uvcg_terminal_grp_type);
|
|
|
|
- configfs_add_default_group(&uvcg_camera_grp.group,
|
|
|
|
- &uvcg_terminal_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_output_grp.group,
|
|
|
|
- &uvcg_terminal_grp.group);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&uvcg_control_class_fs.group,
|
|
|
|
- "fs", &uvcg_control_class_type);
|
|
|
|
- config_group_init_type_name(&uvcg_control_class_ss.group,
|
|
|
|
- "ss", &uvcg_control_class_type);
|
|
|
|
- config_group_init_type_name(&uvcg_control_class_grp.group,
|
|
|
|
- "class",
|
|
|
|
- &uvcg_control_class_grp_type);
|
|
|
|
- configfs_add_default_group(&uvcg_control_class_fs.group,
|
|
|
|
- &uvcg_control_class_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_control_class_ss.group,
|
|
|
|
- &uvcg_control_class_grp.group);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&uvcg_control_grp.group,
|
|
|
|
- "control",
|
|
|
|
- &uvcg_control_grp_type);
|
|
|
|
- configfs_add_default_group(&uvcg_control_header_grp.group,
|
|
|
|
- &uvcg_control_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_processing_grp.group,
|
|
|
|
- &uvcg_control_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_terminal_grp.group,
|
|
|
|
- &uvcg_control_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_control_class_grp.group,
|
|
|
|
- &uvcg_control_grp.group);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&uvcg_streaming_header_grp.group,
|
|
|
|
- "header",
|
|
|
|
- &uvcg_streaming_header_grp_type);
|
|
|
|
- config_group_init_type_name(&uvcg_uncompressed_grp.group,
|
|
|
|
- "uncompressed",
|
|
|
|
- &uvcg_uncompressed_grp_type);
|
|
|
|
- config_group_init_type_name(&uvcg_mjpeg_grp.group,
|
|
|
|
- "mjpeg",
|
|
|
|
- &uvcg_mjpeg_grp_type);
|
|
|
|
- config_group_init_type_name(&uvcg_default_color_matching.group,
|
|
|
|
- "default",
|
|
|
|
- &uvcg_default_color_matching_type);
|
|
|
|
- config_group_init_type_name(&uvcg_color_matching_grp.group,
|
|
|
|
- "color_matching",
|
|
|
|
- &uvcg_color_matching_grp_type);
|
|
|
|
- configfs_add_default_group(&uvcg_default_color_matching.group,
|
|
|
|
- &uvcg_color_matching_grp.group);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&uvcg_streaming_class_fs.group,
|
|
|
|
- "fs", &uvcg_streaming_class_type);
|
|
|
|
- config_group_init_type_name(&uvcg_streaming_class_hs.group,
|
|
|
|
- "hs", &uvcg_streaming_class_type);
|
|
|
|
- config_group_init_type_name(&uvcg_streaming_class_ss.group,
|
|
|
|
- "ss", &uvcg_streaming_class_type);
|
|
|
|
- config_group_init_type_name(&uvcg_streaming_class_grp.group,
|
|
|
|
- "class", &uvcg_streaming_class_grp_type);
|
|
|
|
- configfs_add_default_group(&uvcg_streaming_class_fs.group,
|
|
|
|
- &uvcg_streaming_class_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_streaming_class_hs.group,
|
|
|
|
- &uvcg_streaming_class_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_streaming_class_ss.group,
|
|
|
|
- &uvcg_streaming_class_grp.group);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&uvcg_streaming_grp.group,
|
|
|
|
- "streaming", &uvcg_streaming_grp_type);
|
|
|
|
- configfs_add_default_group(&uvcg_streaming_header_grp.group,
|
|
|
|
- &uvcg_streaming_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_uncompressed_grp.group,
|
|
|
|
- &uvcg_streaming_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_mjpeg_grp.group,
|
|
|
|
- &uvcg_streaming_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_color_matching_grp.group,
|
|
|
|
- &uvcg_streaming_grp.group);
|
|
|
|
- configfs_add_default_group(&uvcg_streaming_class_grp.group,
|
|
|
|
- &uvcg_streaming_grp.group);
|
|
|
|
-
|
|
|
|
- config_group_init_type_name(&opts->func_inst.group,
|
|
|
|
- "",
|
|
|
|
- &uvc_func_type);
|
|
|
|
- configfs_add_default_group(&uvcg_control_grp.group,
|
|
|
|
- &opts->func_inst.group);
|
|
|
|
- configfs_add_default_group(&uvcg_streaming_grp.group,
|
|
|
|
- &opts->func_inst.group);
|
|
|
|
|
|
+ int ret;
|
|
|
|
|
|
- return 0;
|
|
|
|
|
|
+ config_group_init_type_name(&opts->func_inst.group, uvc_func_type.name,
|
|
|
|
+ &uvc_func_type.type);
|
|
|
|
+
|
|
|
|
+ ret = uvcg_config_create_children(&opts->func_inst.group,
|
|
|
|
+ &uvc_func_type);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ config_group_put(&opts->func_inst.group);
|
|
|
|
+
|
|
|
|
+ return ret;
|
|
}
|
|
}
|