summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/usb/uvideo.c133
-rw-r--r--sys/dev/usb/uvideo.h41
2 files changed, 153 insertions, 21 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);
}
diff --git a/sys/dev/usb/uvideo.h b/sys/dev/usb/uvideo.h
index d0326eab9da..509f6f8deb4 100644
--- a/sys/dev/usb/uvideo.h
+++ b/sys/dev/usb/uvideo.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvideo.h,v 1.48 2010/09/29 09:33:26 jakemsr Exp $ */
+/* $OpenBSD: uvideo.h,v 1.49 2010/10/09 08:41:28 jakemsr Exp $ */
/*
* Copyright (c) 2007 Robert Nagy <robert@openbsd.org>
@@ -500,6 +500,7 @@ struct uvideo_controls {
uint8_t ctrl_bit;
uint16_t ctrl_selector;
uint16_t ctrl_len;
+ int sig;
} uvideo_ctrls[] = {
/*
* Processing Unit Controls
@@ -510,7 +511,8 @@ struct uvideo_controls {
"Brightness",
0,
PU_BRIGHTNESS_CONTROL,
- 2
+ 2,
+ 1
},
{
V4L2_CID_CONTRAST,
@@ -518,7 +520,8 @@ struct uvideo_controls {
"Contrast",
1,
PU_CONTRAST_CONTROL,
- 2
+ 2,
+ 0
},
{
V4L2_CID_HUE,
@@ -526,7 +529,8 @@ struct uvideo_controls {
"Hue",
2,
PU_HUE_CONTROL,
- 2
+ 2,
+ 1
},
{
V4L2_CID_SATURATION,
@@ -534,7 +538,8 @@ struct uvideo_controls {
"Saturation",
3,
PU_SATURATION_CONTROL,
- 2
+ 2,
+ 0
},
{
V4L2_CID_SHARPNESS,
@@ -542,7 +547,8 @@ struct uvideo_controls {
"Sharpness",
4,
PU_SHARPNESS_CONTROL,
- 2
+ 2,
+ 0
},
{
V4L2_CID_GAMMA,
@@ -550,7 +556,8 @@ struct uvideo_controls {
"Gamma",
5,
PU_GAMMA_CONTROL,
- 2
+ 2,
+ 0
},
{
V4L2_CID_WHITE_BALANCE_TEMPERATURE,
@@ -558,7 +565,8 @@ struct uvideo_controls {
"White Balance Temperature",
6,
PU_WHITE_BALANCE_TEMPERATURE_CONTROL,
- 2
+ 2,
+ 0
},
#if 0
/* XXX Two V4L2 ids mapping one UVC control */
@@ -568,7 +576,8 @@ struct uvideo_controls {
"White Balance Red Component", /* Blue Component */
7,
PU_WHITE_BALANCE_COMPONENT_CONTROL,
- 4
+ 4,
+ 0
},
#endif
{
@@ -578,6 +587,7 @@ struct uvideo_controls {
8,
PU_BACKLIGHT_COMPENSATION_CONTROL,
2,
+ 0
},
{
V4L2_CID_GAIN,
@@ -586,6 +596,7 @@ struct uvideo_controls {
9,
PU_GAIN_CONTROL,
2,
+ 0
},
{
V4L2_CID_POWER_LINE_FREQUENCY,
@@ -593,7 +604,8 @@ struct uvideo_controls {
"Power Line Frequency",
10,
PU_POWER_LINE_FREQUENCY_CONTROL,
- 1,
+ 2,
+ 0
},
{
V4L2_CID_HUE_AUTO,
@@ -602,6 +614,7 @@ struct uvideo_controls {
11,
PU_HUE_AUTO_CONTROL,
1,
+ 0
},
{
V4L2_CID_AUTO_WHITE_BALANCE,
@@ -610,6 +623,7 @@ struct uvideo_controls {
12,
PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL,
1,
+ 0
},
{
V4L2_CID_AUTO_WHITE_BALANCE,
@@ -618,6 +632,7 @@ struct uvideo_controls {
13,
PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL,
1,
+ 0
},
#if 0
/* XXX No V4L2 CID for these controls? */
@@ -628,6 +643,7 @@ struct uvideo_controls {
14,
PU_DIGITAL_MULTIPLIER_CONTROL,
2,
+ 0
},
{
V4L2_CID_XXX,
@@ -636,6 +652,7 @@ struct uvideo_controls {
15,
PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL,
2,
+ 0
},
{
V4L2_CID_XXX,
@@ -644,6 +661,7 @@ struct uvideo_controls {
16,
PU_ANALOG_VIDEO_STANDARD_CONTROL,
1,
+ 0
},
{
V4L2_CID_XXX,
@@ -652,9 +670,10 @@ struct uvideo_controls {
17,
PU_ANALOG_LOCK_STATUS_CONTROL,
1,
+ 0
},
#endif
- { 0, 0, "", 0, 0, 0 }
+ { 0, 0, "", 0, 0, 0, 0 }
};
struct uvideo_softc {