diff options
-rw-r--r-- | sys/dev/usb/uvideo.c | 133 | ||||
-rw-r--r-- | sys/dev/usb/uvideo.h | 41 |
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 { |