Commit 8ca5a639 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab

V4L/DVB (13506): uvcvideo: Factorize common field in uvc_entity structure

The bNrInPins and baSourceID fields are common among all entities (some
of use bSourceID but this is conceptually the same). Move those two
fields out of entity type-specific unions into the uvc_entity structure
top level.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 4057ac6c
...@@ -249,29 +249,9 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev, ...@@ -249,29 +249,9 @@ static struct uvc_entity *uvc_entity_by_reference(struct uvc_device *dev,
entity = list_entry(&dev->entities, struct uvc_entity, list); entity = list_entry(&dev->entities, struct uvc_entity, list);
list_for_each_entry_continue(entity, &dev->entities, list) { list_for_each_entry_continue(entity, &dev->entities, list) {
switch (UVC_ENTITY_TYPE(entity)) { for (i = 0; i < entity->bNrInPins; ++i)
case UVC_TT_STREAMING: if (entity->baSourceID[i] == id)
if (entity->output.bSourceID == id)
return entity;
break;
case UVC_VC_PROCESSING_UNIT:
if (entity->processing.bSourceID == id)
return entity; return entity;
break;
case UVC_VC_SELECTOR_UNIT:
for (i = 0; i < entity->selector.bNrInPins; ++i)
if (entity->selector.baSourceID[i] == id)
return entity;
break;
case UVC_VC_EXTENSION_UNIT:
for (i = 0; i < entity->extension.bNrInPins; ++i)
if (entity->extension.baSourceID[i] == id)
return entity;
break;
}
} }
return NULL; return NULL;
...@@ -785,6 +765,28 @@ static int uvc_parse_streaming(struct uvc_device *dev, ...@@ -785,6 +765,28 @@ static int uvc_parse_streaming(struct uvc_device *dev,
return ret; return ret;
} }
static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id,
unsigned int num_pads, unsigned int extra_size)
{
struct uvc_entity *entity;
unsigned int num_inputs;
unsigned int size;
num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1;
size = sizeof(*entity) + extra_size + num_inputs;
entity = kzalloc(size, GFP_KERNEL);
if (entity == NULL)
return NULL;
entity->id = id;
entity->type = type;
entity->bNrInPins = num_inputs;
entity->baSourceID = ((__u8 *)entity) + sizeof(*entity) + extra_size;
return entity;
}
/* Parse vendor-specific extensions. */ /* Parse vendor-specific extensions. */
static int uvc_parse_vendor_control(struct uvc_device *dev, static int uvc_parse_vendor_control(struct uvc_device *dev,
const unsigned char *buffer, int buflen) const unsigned char *buffer, int buflen)
...@@ -836,21 +838,18 @@ static int uvc_parse_vendor_control(struct uvc_device *dev, ...@@ -836,21 +838,18 @@ static int uvc_parse_vendor_control(struct uvc_device *dev,
break; break;
} }
unit = kzalloc(sizeof *unit + p + 2*n, GFP_KERNEL); unit = uvc_alloc_entity(UVC_VC_EXTENSION_UNIT, buffer[3],
p + 1, 2*n);
if (unit == NULL) if (unit == NULL)
return -ENOMEM; return -ENOMEM;
unit->id = buffer[3];
unit->type = UVC_VC_EXTENSION_UNIT;
memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
unit->extension.bNumControls = buffer[20]; unit->extension.bNumControls = buffer[20];
unit->extension.bNrInPins = buffer[21]; memcpy(unit->baSourceID, &buffer[22], p);
unit->extension.baSourceID = (__u8 *)unit + sizeof *unit;
memcpy(unit->extension.baSourceID, &buffer[22], p);
unit->extension.bControlSize = buffer[22+p]; unit->extension.bControlSize = buffer[22+p];
unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; unit->extension.bmControls = (__u8 *)unit + sizeof(*unit);
unit->extension.bmControlsType = (__u8 *)unit + sizeof *unit unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit)
+ p + n; + n;
memcpy(unit->extension.bmControls, &buffer[23+p], 2*n); memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
if (buffer[24+p+2*n] != 0) if (buffer[24+p+2*n] != 0)
...@@ -947,13 +946,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, ...@@ -947,13 +946,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return -EINVAL; return -EINVAL;
} }
term = kzalloc(sizeof *term + n + p, GFP_KERNEL); term = uvc_alloc_entity(type | UVC_TERM_INPUT, buffer[3],
1, n + p);
if (term == NULL) if (term == NULL)
return -ENOMEM; return -ENOMEM;
term->id = buffer[3];
term->type = type | UVC_TERM_INPUT;
if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) { if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
term->camera.bControlSize = n; term->camera.bControlSize = n;
term->camera.bmControls = (__u8 *)term + sizeof *term; term->camera.bmControls = (__u8 *)term + sizeof *term;
...@@ -1008,13 +1005,12 @@ static int uvc_parse_standard_control(struct uvc_device *dev, ...@@ -1008,13 +1005,12 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return 0; return 0;
} }
term = kzalloc(sizeof *term, GFP_KERNEL); term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
1, 0);
if (term == NULL) if (term == NULL)
return -ENOMEM; return -ENOMEM;
term->id = buffer[3]; memcpy(term->baSourceID, &buffer[7], 1);
term->type = type | UVC_TERM_OUTPUT;
term->output.bSourceID = buffer[7];
if (buffer[8] != 0) if (buffer[8] != 0)
usb_string(udev, buffer[8], term->name, usb_string(udev, buffer[8], term->name,
...@@ -1035,15 +1031,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, ...@@ -1035,15 +1031,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return -EINVAL; return -EINVAL;
} }
unit = kzalloc(sizeof *unit + p, GFP_KERNEL); unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
if (unit == NULL) if (unit == NULL)
return -ENOMEM; return -ENOMEM;
unit->id = buffer[3]; memcpy(unit->baSourceID, &buffer[5], p);
unit->type = buffer[2];
unit->selector.bNrInPins = buffer[4];
unit->selector.baSourceID = (__u8 *)unit + sizeof *unit;
memcpy(unit->selector.baSourceID, &buffer[5], p);
if (buffer[5+p] != 0) if (buffer[5+p] != 0)
usb_string(udev, buffer[5+p], unit->name, usb_string(udev, buffer[5+p], unit->name,
...@@ -1065,13 +1057,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev, ...@@ -1065,13 +1057,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return -EINVAL; return -EINVAL;
} }
unit = kzalloc(sizeof *unit + n, GFP_KERNEL); unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
if (unit == NULL) if (unit == NULL)
return -ENOMEM; return -ENOMEM;
unit->id = buffer[3]; memcpy(unit->baSourceID, &buffer[4], 1);
unit->type = buffer[2];
unit->processing.bSourceID = buffer[4];
unit->processing.wMaxMultiplier = unit->processing.wMaxMultiplier =
get_unaligned_le16(&buffer[5]); get_unaligned_le16(&buffer[5]);
unit->processing.bControlSize = buffer[7]; unit->processing.bControlSize = buffer[7];
...@@ -1100,19 +1090,15 @@ static int uvc_parse_standard_control(struct uvc_device *dev, ...@@ -1100,19 +1090,15 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
return -EINVAL; return -EINVAL;
} }
unit = kzalloc(sizeof *unit + p + n, GFP_KERNEL); unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
if (unit == NULL) if (unit == NULL)
return -ENOMEM; return -ENOMEM;
unit->id = buffer[3];
unit->type = buffer[2];
memcpy(unit->extension.guidExtensionCode, &buffer[4], 16); memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
unit->extension.bNumControls = buffer[20]; unit->extension.bNumControls = buffer[20];
unit->extension.bNrInPins = buffer[21]; memcpy(unit->baSourceID, &buffer[22], p);
unit->extension.baSourceID = (__u8 *)unit + sizeof *unit;
memcpy(unit->extension.baSourceID, &buffer[22], p);
unit->extension.bControlSize = buffer[22+p]; unit->extension.bControlSize = buffer[22+p];
unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p; unit->extension.bmControls = (__u8 *)unit + sizeof *unit;
memcpy(unit->extension.bmControls, &buffer[23+p], n); memcpy(unit->extension.bmControls, &buffer[23+p], n);
if (buffer[23+p+n] != 0) if (buffer[23+p+n] != 0)
...@@ -1218,7 +1204,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, ...@@ -1218,7 +1204,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
if (uvc_trace_param & UVC_TRACE_PROBE) if (uvc_trace_param & UVC_TRACE_PROBE)
printk(" <- XU %d", entity->id); printk(" <- XU %d", entity->id);
if (entity->extension.bNrInPins != 1) { if (entity->bNrInPins != 1) {
uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more " uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
"than 1 input pin.\n", entity->id); "than 1 input pin.\n", entity->id);
return -1; return -1;
...@@ -1244,7 +1230,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain, ...@@ -1244,7 +1230,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
printk(" <- SU %d", entity->id); printk(" <- SU %d", entity->id);
/* Single-input selector units are ignored. */ /* Single-input selector units are ignored. */
if (entity->selector.bNrInPins == 1) if (entity->bNrInPins == 1)
break; break;
if (chain->selector != NULL) { if (chain->selector != NULL) {
...@@ -1305,7 +1291,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, ...@@ -1305,7 +1291,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
switch (UVC_ENTITY_TYPE(forward)) { switch (UVC_ENTITY_TYPE(forward)) {
case UVC_VC_EXTENSION_UNIT: case UVC_VC_EXTENSION_UNIT:
if (forward->extension.bNrInPins != 1) { if (forward->bNrInPins != 1) {
uvc_trace(UVC_TRACE_DESCR, "Extension unit %d " uvc_trace(UVC_TRACE_DESCR, "Extension unit %d "
"has more than 1 input pin.\n", "has more than 1 input pin.\n",
entity->id); entity->id);
...@@ -1358,17 +1344,14 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, ...@@ -1358,17 +1344,14 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
switch (UVC_ENTITY_TYPE(entity)) { switch (UVC_ENTITY_TYPE(entity)) {
case UVC_VC_EXTENSION_UNIT: case UVC_VC_EXTENSION_UNIT:
id = entity->extension.baSourceID[0];
break;
case UVC_VC_PROCESSING_UNIT: case UVC_VC_PROCESSING_UNIT:
id = entity->processing.bSourceID; id = entity->baSourceID[0];
break; break;
case UVC_VC_SELECTOR_UNIT: case UVC_VC_SELECTOR_UNIT:
/* Single-input selector units are ignored. */ /* Single-input selector units are ignored. */
if (entity->selector.bNrInPins == 1) { if (entity->bNrInPins == 1) {
id = entity->selector.baSourceID[0]; id = entity->baSourceID[0];
break; break;
} }
...@@ -1376,8 +1359,8 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, ...@@ -1376,8 +1359,8 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
printk(" <- IT"); printk(" <- IT");
chain->selector = entity; chain->selector = entity;
for (i = 0; i < entity->selector.bNrInPins; ++i) { for (i = 0; i < entity->bNrInPins; ++i) {
id = entity->selector.baSourceID[i]; id = entity->baSourceID[i];
term = uvc_entity_by_id(chain->dev, id); term = uvc_entity_by_id(chain->dev, id);
if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) { if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
uvc_trace(UVC_TRACE_DESCR, "Selector unit %d " uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
...@@ -1406,7 +1389,7 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain, ...@@ -1406,7 +1389,7 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
case UVC_OTT_DISPLAY: case UVC_OTT_DISPLAY:
case UVC_OTT_MEDIA_TRANSPORT_OUTPUT: case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
case UVC_TT_STREAMING: case UVC_TT_STREAMING:
id = UVC_ENTITY_IS_OTERM(entity) ? entity->output.bSourceID : 0; id = UVC_ENTITY_IS_OTERM(entity) ? entity->baSourceID[0] : 0;
break; break;
} }
......
...@@ -625,8 +625,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ...@@ -625,8 +625,8 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
break; break;
} }
pin = iterm->id; pin = iterm->id;
} else if (pin < selector->selector.bNrInPins) { } else if (pin < selector->bNrInPins) {
pin = selector->selector.baSourceID[index]; pin = selector->baSourceID[index];
list_for_each_entry(iterm, &chain->entities, chain) { list_for_each_entry(iterm, &chain->entities, chain) {
if (!UVC_ENTITY_IS_ITERM(iterm)) if (!UVC_ENTITY_IS_ITERM(iterm))
continue; continue;
...@@ -680,7 +680,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) ...@@ -680,7 +680,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
break; break;
} }
if (input == 0 || input > chain->selector->selector.bNrInPins) if (input == 0 || input > chain->selector->bNrInPins)
return -EINVAL; return -EINVAL;
return uvc_query_ctrl(chain->dev, UVC_SET_CUR, return uvc_query_ctrl(chain->dev, UVC_SET_CUR,
......
...@@ -293,11 +293,9 @@ struct uvc_entity { ...@@ -293,11 +293,9 @@ struct uvc_entity {
} media; } media;
struct { struct {
__u8 bSourceID;
} output; } output;
struct { struct {
__u8 bSourceID;
__u16 wMaxMultiplier; __u16 wMaxMultiplier;
__u8 bControlSize; __u8 bControlSize;
__u8 *bmControls; __u8 *bmControls;
...@@ -305,21 +303,20 @@ struct uvc_entity { ...@@ -305,21 +303,20 @@ struct uvc_entity {
} processing; } processing;
struct { struct {
__u8 bNrInPins;
__u8 *baSourceID;
} selector; } selector;
struct { struct {
__u8 guidExtensionCode[16]; __u8 guidExtensionCode[16];
__u8 bNumControls; __u8 bNumControls;
__u8 bNrInPins;
__u8 *baSourceID;
__u8 bControlSize; __u8 bControlSize;
__u8 *bmControls; __u8 *bmControls;
__u8 *bmControlsType; __u8 *bmControlsType;
} extension; } extension;
}; };
__u8 bNrInPins;
__u8 *baSourceID;
unsigned int ncontrols; unsigned int ncontrols;
struct uvc_control *controls; struct uvc_control *controls;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment