-Description: Default color matching descriptors
+Description: color matching descriptors
All attributes read/write:
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 4fbc42d738a4..82c10f0dab71 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -769,6 +769,58 @@ static struct uvcg_cmd *uvcg_format_get_default_cmd(struct config_item *streamin
return cmd;
}
+static int uvcg_format_allow_link(struct config_item *src, struct config_item *tgt)
+{
+ struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
+ struct config_item *streaming, *color_matching;
+ struct uvcg_cmd *color_matching_desc;
+ struct uvcg_format *fmt;
+ int ret = 0;
+
+ mutex_lock(su_mutex);
+
+ streaming = src->ci_parent->ci_parent;
+ color_matching = config_group_find_item(to_config_group(streaming), "color_matching");
+ if (!color_matching || color_matching != tgt->ci_parent) {
+ ret = -EINVAL;
+ goto out_put_cm;
+ }
+
+ color_matching_desc = to_uvcg_cmd(to_config_group(tgt));
+ fmt = to_uvcg_format(src);
+ fmt->color_matching = color_matching_desc;
+
+out_put_cm:
+ config_item_put(color_matching);
+ mutex_unlock(su_mutex);
+
+ return ret;
+}
+
+static void uvcg_format_drop_link(struct config_item *src, struct config_item *tgt)
+{
+ struct config_item *streaming;
+ struct mutex *su_mutex = &src->ci_group->cg_subsys->su_mutex;
+ struct uvcg_format *fmt;
+ struct uvcg_cmd *cmd;
+
+ mutex_lock(su_mutex);
+
+ streaming = src->ci_parent->ci_parent;
+ cmd = uvcg_format_get_default_cmd(streaming);
+
+ fmt = to_uvcg_format(src);
+ fmt->color_matching = cmd;
+
+ mutex_unlock(su_mutex);
+}
+
+static struct configfs_item_operations uvcg_format_item_operations = {
+ .release = uvcg_config_item_release,
+ .allow_link = uvcg_format_allow_link,
+ .drop_link = uvcg_format_drop_link,
+};
+
static ssize_t uvcg_format_bma_controls_show(struct uvcg_format *f, char *page)
{
struct f_uvc_opts *opts;
@@ -1569,7 +1621,7 @@ static struct configfs_attribute *uvcg_uncompressed_attrs[] = {
};
static const struct config_item_type uvcg_uncompressed_type = {
- .ct_item_ops = &uvcg_config_item_ops,
+ .ct_item_ops = &uvcg_format_item_operations,
.ct_group_ops = &uvcg_uncompressed_group_ops,
.ct_attrs = uvcg_uncompressed_attrs,
.ct_owner = THIS_MODULE,
@@ -1764,7 +1816,7 @@ static struct configfs_attribute *uvcg_mjpeg_attrs[] = {
};
static const struct config_item_type uvcg_mjpeg_type = {
- .ct_item_ops = &uvcg_config_item_ops,
+ .ct_item_ops = &uvcg_format_item_operations,
.ct_group_ops = &uvcg_mjpeg_group_ops,
.ct_attrs = uvcg_mjpeg_attrs,
.ct_owner = THIS_MODULE,
@@ -1912,6 +1964,28 @@ static const struct config_item_type uvcg_color_matching_type = {
* streaming/color_matching
*/
+static struct config_group *uvcg_color_matching_make(struct config_group *group,
+ const char *name)
+{
+ struct uvcg_cmd *cmd;
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ return ERR_PTR(-ENOMEM);
+
+ cmd->desc.bLength = UVC_DT_COLOR_MATCHING_SIZE;
+ cmd->desc.bDescriptorType = USB_DT_CS_INTERFACE;
+ cmd->desc.bDescriptorSubType = UVC_VS_COLORFORMAT;
+
+ config_group_init_type_name(&cmd->group, name, &uvcg_color_matching_type);
+
+ return &cmd->group;
+}
+
+static struct configfs_group_operations uvcg_color_matching_grp_group_ops = {
+ .make_group = uvcg_color_matching_make,
+};
+
static int uvcg_color_matching_create_children(struct config_group *parent)
{
struct uvcg_cmd *cmd;
@@ -1937,6 +2011,7 @@ static int uvcg_color_matching_create_children(struct config_group *parent)
static const struct uvcg_config_group_type uvcg_color_matching_grp_type = {
.type = {
.ct_item_ops = &uvcg_config_item_ops,
+ .ct_group_ops = &uvcg_color_matching_grp_group_ops,
.ct_owner = THIS_MODULE,
},
.name = "color_matching",
--
2.34.1