diff options
author | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2010-10-09 08:41:29 +0000 |
---|---|---|
committer | Jacob Meuser <jakemsr@cvs.openbsd.org> | 2010-10-09 08:41:29 +0000 |
commit | bcd4823f87530d3274c3d026c0f489cd65154296 (patch) | |
tree | 82bc15ff48a96e9f6965771306b41c4297142959 /sys/dev/usb/uvideo.c | |
parent | 6a48b42d970d42e49e886286dc5c86640f7cea6d (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.c | 133 |
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); } |