summaryrefslogtreecommitdiff
path: root/sys/dev/usb/uvideo.c
diff options
context:
space:
mode:
authorJacob Meuser <jakemsr@cvs.openbsd.org>2010-10-09 08:41:29 +0000
committerJacob Meuser <jakemsr@cvs.openbsd.org>2010-10-09 08:41:29 +0000
commitbcd4823f87530d3274c3d026c0f489cd65154296 (patch)
tree82bc15ff48a96e9f6965771306b41c4297142959 /sys/dev/usb/uvideo.c
parent6a48b42d970d42e49e886286dc5c86640f7cea6d (diff)
control values can be 1 or 2 bytes, signed or unsigned. fixes hue
control.
Diffstat (limited to 'sys/dev/usb/uvideo.c')
-rw-r--r--sys/dev/usb/uvideo.c133
1 files changed, 123 insertions, 10 deletions
diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c
index dc36e5fe2f1..aaa42f919cd 100644
--- a/sys/dev/usb/uvideo.c
+++ b/sys/dev/usb/uvideo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvideo.c,v 1.140 2010/10/08 21:41:44 jakemsr Exp $ */
+/* $OpenBSD: uvideo.c,v 1.141 2010/10/09 08:41:28 jakemsr Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
@@ -3073,12 +3073,25 @@ uvideo_queryctrl(void *v, struct v4l2_queryctrl *qctrl)
struct uvideo_softc *sc = v;
int i;
usbd_status error;
- uint8_t ctrl_data[2];
+ uint8_t *ctrl_data;
+ uint16_t ctrl_len;
i = uvideo_find_ctrl(sc, qctrl->id);
if (i == EINVAL)
return (i);
+ ctrl_len = uvideo_ctrls[i].ctrl_len;
+ if (ctrl_len < 1 || ctrl_len > 2) {
+ printf("%s: invalid control length: %d\n", __func__, ctrl_len);
+ return (EINVAL);
+ }
+
+ ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK);
+ if (ctrl_data == NULL) {
+ printf("%s: could not allocate control data\n", __func__);
+ return (ENOMEM);
+ }
+
/* set type */
qctrl->type = uvideo_ctrls[i].type;
@@ -3091,7 +3104,18 @@ uvideo_queryctrl(void *v, struct v4l2_queryctrl *qctrl)
uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
if (error != USBD_NORMAL_COMPLETION)
return (EINVAL);
- qctrl->minimum = letoh16(*(uint16_t *)ctrl_data);
+ switch (ctrl_len) {
+ case 1:
+ qctrl->minimum = uvideo_ctrls[i].sig ?
+ *(int8_t *)ctrl_data :
+ *ctrl_data;
+ break;
+ case 2:
+ qctrl->minimum = uvideo_ctrls[i].sig ?
+ letoh16(*(int16_t *)ctrl_data) :
+ letoh16(*(uint16_t *)ctrl_data);
+ break;
+ }
/* set maximum */
error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_MAX,
@@ -3099,7 +3123,18 @@ uvideo_queryctrl(void *v, struct v4l2_queryctrl *qctrl)
uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
if (error != USBD_NORMAL_COMPLETION)
return (EINVAL);
- qctrl->maximum = letoh16(*(uint16_t *)ctrl_data);
+ switch(ctrl_len) {
+ case 1:
+ qctrl->maximum = uvideo_ctrls[i].sig ?
+ *(int8_t *)ctrl_data :
+ *ctrl_data;
+ break;
+ case 2:
+ qctrl->maximum = uvideo_ctrls[i].sig ?
+ letoh16(*(int16_t *)ctrl_data) :
+ letoh16(*(uint16_t *)ctrl_data);
+ break;
+ }
/* set resolution */
error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_RES,
@@ -3107,7 +3142,18 @@ uvideo_queryctrl(void *v, struct v4l2_queryctrl *qctrl)
uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
if (error != USBD_NORMAL_COMPLETION)
return (EINVAL);
- qctrl->step = letoh16(*(uint16_t *)ctrl_data);
+ switch(ctrl_len) {
+ case 1:
+ qctrl->step = uvideo_ctrls[i].sig ?
+ *(int8_t *)ctrl_data:
+ *ctrl_data;
+ break;
+ case 2:
+ qctrl->step = uvideo_ctrls[i].sig ?
+ letoh16(*(int16_t *)ctrl_data) :
+ letoh16(*(uint16_t *)ctrl_data);
+ break;
+ }
/* set default */
error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_DEF,
@@ -3115,11 +3161,24 @@ uvideo_queryctrl(void *v, struct v4l2_queryctrl *qctrl)
uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
if (error != USBD_NORMAL_COMPLETION)
return (EINVAL);
- qctrl->default_value = letoh16(*(uint16_t *)ctrl_data);
+ switch(ctrl_len) {
+ case 1:
+ qctrl->default_value = uvideo_ctrls[i].sig ?
+ *(int8_t *)ctrl_data :
+ *ctrl_data;
+ break;
+ case 2:
+ qctrl->default_value = uvideo_ctrls[i].sig ?
+ letoh16(*(int16_t *)ctrl_data) :
+ letoh16(*(uint16_t *)ctrl_data);
+ break;
+ }
/* set flags */
qctrl->flags = 0;
+ free(ctrl_data, M_USBDEV);
+
return (0);
}
@@ -3129,18 +3188,44 @@ uvideo_g_ctrl(void *v, struct v4l2_control *gctrl)
struct uvideo_softc *sc = v;
int i;
usbd_status error;
- uint8_t ctrl_data[2];
+ int8_t *ctrl_data;
+ uint16_t ctrl_len;
i = uvideo_find_ctrl(sc, gctrl->id);
if (i == EINVAL)
return (i);
+ ctrl_len = uvideo_ctrls[i].ctrl_len;
+ if (ctrl_len < 1 || ctrl_len > 2) {
+ printf("%s: invalid control length: %d\n", __func__, ctrl_len);
+ return (EINVAL);
+ }
+
+ ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK);
+ if (ctrl_data == NULL) {
+ printf("%s: could not allocate control data\n", __func__);
+ return (ENOMEM);
+ }
+
error = uvideo_vc_get_ctrl(sc, ctrl_data, GET_CUR,
sc->sc_desc_vc_pu_cur->bUnitID,
uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
if (error != USBD_NORMAL_COMPLETION)
return (EINVAL);
- gctrl->value = letoh16(*(uint16_t *)ctrl_data);
+ switch(ctrl_len) {
+ case 1:
+ gctrl->value = uvideo_ctrls[i].sig ?
+ *(int8_t *)ctrl_data :
+ *ctrl_data;
+ break;
+ case 2:
+ gctrl->value = uvideo_ctrls[i].sig ?
+ letoh16(*(int16_t *)ctrl_data) :
+ letoh16(*(uint16_t *)ctrl_data);
+ break;
+ }
+
+ free(ctrl_data, M_USBDEV);
return (0);
}
@@ -3151,19 +3236,47 @@ uvideo_s_ctrl(void *v, struct v4l2_control *sctrl)
struct uvideo_softc *sc = v;
int i;
usbd_status error;
- uint8_t ctrl_data[2];
+ int8_t *ctrl_data;
+ uint16_t ctrl_len;
i = uvideo_find_ctrl(sc, sctrl->id);
if (i == EINVAL)
return (i);
- *(uint16_t *)ctrl_data = htole16(sctrl->value);
+ ctrl_len = uvideo_ctrls[i].ctrl_len;
+ if (ctrl_len < 1 || ctrl_len > 2) {
+ printf("%s: invalid control length: %d\n", __func__, ctrl_len);
+ return (EINVAL);
+ }
+
+ ctrl_data = malloc(ctrl_len, M_USBDEV, M_WAITOK);
+ if (ctrl_data == NULL) {
+ printf("%s: could not allocate control data\n", __func__);
+ return (ENOMEM);
+ }
+
+ switch(ctrl_len) {
+ case 1:
+ if (uvideo_ctrls[i].sig)
+ *(int8_t *)ctrl_data = sctrl->value;
+ else
+ *ctrl_data = sctrl->value;
+ break;
+ case 2:
+ if (uvideo_ctrls[i].sig)
+ *(int16_t *)ctrl_data = htole16(sctrl->value);
+ else
+ *(uint16_t *)ctrl_data = htole16(sctrl->value);
+ break;
+ }
error = uvideo_vc_set_ctrl(sc, ctrl_data, SET_CUR,
sc->sc_desc_vc_pu_cur->bUnitID,
uvideo_ctrls[i].ctrl_selector, uvideo_ctrls[i].ctrl_len);
if (error != USBD_NORMAL_COMPLETION)
return (EINVAL);
+ free(ctrl_data, M_USBDEV);
+
return (0);
}