|
@@ -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);
|
|
|
|
|
|
list_for_each_entry_continue(entity, &dev->entities, list) {
|
|
|
- switch (UVC_ENTITY_TYPE(entity)) {
|
|
|
- case UVC_TT_STREAMING:
|
|
|
- if (entity->output.bSourceID == id)
|
|
|
- return entity;
|
|
|
- break;
|
|
|
-
|
|
|
- case UVC_VC_PROCESSING_UNIT:
|
|
|
- if (entity->processing.bSourceID == id)
|
|
|
+ for (i = 0; i < entity->bNrInPins; ++i)
|
|
|
+ if (entity->baSourceID[i] == id)
|
|
|
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;
|
|
@@ -785,6 +765,28 @@ error:
|
|
|
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. */
|
|
|
static int uvc_parse_vendor_control(struct uvc_device *dev,
|
|
|
const unsigned char *buffer, int buflen)
|
|
@@ -836,21 +838,18 @@ static int uvc_parse_vendor_control(struct uvc_device *dev,
|
|
|
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)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- unit->id = buffer[3];
|
|
|
- unit->type = UVC_VC_EXTENSION_UNIT;
|
|
|
memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
|
|
|
unit->extension.bNumControls = buffer[20];
|
|
|
- unit->extension.bNrInPins = buffer[21];
|
|
|
- unit->extension.baSourceID = (__u8 *)unit + sizeof *unit;
|
|
|
- memcpy(unit->extension.baSourceID, &buffer[22], p);
|
|
|
+ memcpy(unit->baSourceID, &buffer[22], p);
|
|
|
unit->extension.bControlSize = buffer[22+p];
|
|
|
- unit->extension.bmControls = (__u8 *)unit + sizeof *unit + p;
|
|
|
- unit->extension.bmControlsType = (__u8 *)unit + sizeof *unit
|
|
|
- + p + n;
|
|
|
+ unit->extension.bmControls = (__u8 *)unit + sizeof(*unit);
|
|
|
+ unit->extension.bmControlsType = (__u8 *)unit + sizeof(*unit)
|
|
|
+ + n;
|
|
|
memcpy(unit->extension.bmControls, &buffer[23+p], 2*n);
|
|
|
|
|
|
if (buffer[24+p+2*n] != 0)
|
|
@@ -947,13 +946,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
|
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)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- term->id = buffer[3];
|
|
|
- term->type = type | UVC_TERM_INPUT;
|
|
|
-
|
|
|
if (UVC_ENTITY_TYPE(term) == UVC_ITT_CAMERA) {
|
|
|
term->camera.bControlSize = n;
|
|
|
term->camera.bmControls = (__u8 *)term + sizeof *term;
|
|
@@ -1008,13 +1005,12 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- term = kzalloc(sizeof *term, GFP_KERNEL);
|
|
|
+ term = uvc_alloc_entity(type | UVC_TERM_OUTPUT, buffer[3],
|
|
|
+ 1, 0);
|
|
|
if (term == NULL)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- term->id = buffer[3];
|
|
|
- term->type = type | UVC_TERM_OUTPUT;
|
|
|
- term->output.bSourceID = buffer[7];
|
|
|
+ memcpy(term->baSourceID, &buffer[7], 1);
|
|
|
|
|
|
if (buffer[8] != 0)
|
|
|
usb_string(udev, buffer[8], term->name,
|
|
@@ -1035,15 +1031,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- unit = kzalloc(sizeof *unit + p, GFP_KERNEL);
|
|
|
+ unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, 0);
|
|
|
if (unit == NULL)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- unit->id = buffer[3];
|
|
|
- unit->type = buffer[2];
|
|
|
- unit->selector.bNrInPins = buffer[4];
|
|
|
- unit->selector.baSourceID = (__u8 *)unit + sizeof *unit;
|
|
|
- memcpy(unit->selector.baSourceID, &buffer[5], p);
|
|
|
+ memcpy(unit->baSourceID, &buffer[5], p);
|
|
|
|
|
|
if (buffer[5+p] != 0)
|
|
|
usb_string(udev, buffer[5+p], unit->name,
|
|
@@ -1065,13 +1057,11 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- unit = kzalloc(sizeof *unit + n, GFP_KERNEL);
|
|
|
+ unit = uvc_alloc_entity(buffer[2], buffer[3], 2, n);
|
|
|
if (unit == NULL)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- unit->id = buffer[3];
|
|
|
- unit->type = buffer[2];
|
|
|
- unit->processing.bSourceID = buffer[4];
|
|
|
+ memcpy(unit->baSourceID, &buffer[4], 1);
|
|
|
unit->processing.wMaxMultiplier =
|
|
|
get_unaligned_le16(&buffer[5]);
|
|
|
unit->processing.bControlSize = buffer[7];
|
|
@@ -1100,19 +1090,15 @@ static int uvc_parse_standard_control(struct uvc_device *dev,
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
- unit = kzalloc(sizeof *unit + p + n, GFP_KERNEL);
|
|
|
+ unit = uvc_alloc_entity(buffer[2], buffer[3], p + 1, n);
|
|
|
if (unit == NULL)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- unit->id = buffer[3];
|
|
|
- unit->type = buffer[2];
|
|
|
memcpy(unit->extension.guidExtensionCode, &buffer[4], 16);
|
|
|
unit->extension.bNumControls = buffer[20];
|
|
|
- unit->extension.bNrInPins = buffer[21];
|
|
|
- unit->extension.baSourceID = (__u8 *)unit + sizeof *unit;
|
|
|
- memcpy(unit->extension.baSourceID, &buffer[22], p);
|
|
|
+ memcpy(unit->baSourceID, &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);
|
|
|
|
|
|
if (buffer[23+p+n] != 0)
|
|
@@ -1218,7 +1204,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
|
|
|
if (uvc_trace_param & UVC_TRACE_PROBE)
|
|
|
printk(" <- XU %d", entity->id);
|
|
|
|
|
|
- if (entity->extension.bNrInPins != 1) {
|
|
|
+ if (entity->bNrInPins != 1) {
|
|
|
uvc_trace(UVC_TRACE_DESCR, "Extension unit %d has more "
|
|
|
"than 1 input pin.\n", entity->id);
|
|
|
return -1;
|
|
@@ -1244,7 +1230,7 @@ static int uvc_scan_chain_entity(struct uvc_video_chain *chain,
|
|
|
printk(" <- SU %d", entity->id);
|
|
|
|
|
|
/* Single-input selector units are ignored. */
|
|
|
- if (entity->selector.bNrInPins == 1)
|
|
|
+ if (entity->bNrInPins == 1)
|
|
|
break;
|
|
|
|
|
|
if (chain->selector != NULL) {
|
|
@@ -1305,7 +1291,7 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain,
|
|
|
|
|
|
switch (UVC_ENTITY_TYPE(forward)) {
|
|
|
case UVC_VC_EXTENSION_UNIT:
|
|
|
- if (forward->extension.bNrInPins != 1) {
|
|
|
+ if (forward->bNrInPins != 1) {
|
|
|
uvc_trace(UVC_TRACE_DESCR, "Extension unit %d "
|
|
|
"has more than 1 input pin.\n",
|
|
|
entity->id);
|
|
@@ -1358,17 +1344,14 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
|
|
|
|
|
|
switch (UVC_ENTITY_TYPE(entity)) {
|
|
|
case UVC_VC_EXTENSION_UNIT:
|
|
|
- id = entity->extension.baSourceID[0];
|
|
|
- break;
|
|
|
-
|
|
|
case UVC_VC_PROCESSING_UNIT:
|
|
|
- id = entity->processing.bSourceID;
|
|
|
+ id = entity->baSourceID[0];
|
|
|
break;
|
|
|
|
|
|
case UVC_VC_SELECTOR_UNIT:
|
|
|
/* Single-input selector units are ignored. */
|
|
|
- if (entity->selector.bNrInPins == 1) {
|
|
|
- id = entity->selector.baSourceID[0];
|
|
|
+ if (entity->bNrInPins == 1) {
|
|
|
+ id = entity->baSourceID[0];
|
|
|
break;
|
|
|
}
|
|
|
|
|
@@ -1376,8 +1359,8 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
|
|
|
printk(" <- IT");
|
|
|
|
|
|
chain->selector = entity;
|
|
|
- for (i = 0; i < entity->selector.bNrInPins; ++i) {
|
|
|
- id = entity->selector.baSourceID[i];
|
|
|
+ for (i = 0; i < entity->bNrInPins; ++i) {
|
|
|
+ id = entity->baSourceID[i];
|
|
|
term = uvc_entity_by_id(chain->dev, id);
|
|
|
if (term == NULL || !UVC_ENTITY_IS_ITERM(term)) {
|
|
|
uvc_trace(UVC_TRACE_DESCR, "Selector unit %d "
|
|
@@ -1406,7 +1389,7 @@ static int uvc_scan_chain_backward(struct uvc_video_chain *chain,
|
|
|
case UVC_OTT_DISPLAY:
|
|
|
case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
|
|
|
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;
|
|
|
}
|
|
|
|