?? pwc-ctrl.c
字號:
buf = flags & 0x03; // only lower two bits are currently used return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);}int pwc_mpt_reset(struct pwc_device *pdev, int flags){ int ret; ret = _pwc_mpt_reset(pdev, flags); if (ret >= 0) { pdev->pan_angle = 0; pdev->tilt_angle = 0; } return ret;}static int _pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt){ unsigned char buf[4]; /* set new relative angle; angles are expressed in degrees * 100, but cam as .5 degree resolution, hence divide by 200. Also the angle must be multiplied by 64 before it's send to the cam (??) */ pan = 64 * pan / 100; tilt = -64 * tilt / 100; /* positive tilt is down, which is not what the user would expect */ buf[0] = pan & 0xFF; buf[1] = (pan >> 8) & 0xFF; buf[2] = tilt & 0xFF; buf[3] = (tilt >> 8) & 0xFF; return SendControlMsg(SET_MPT_CTL, PT_RELATIVE_CONTROL_FORMATTER, 4);}int pwc_mpt_set_angle(struct pwc_device *pdev, int pan, int tilt){ int ret; /* check absolute ranges */ if (pan < pdev->angle_range.pan_min || pan > pdev->angle_range.pan_max || tilt < pdev->angle_range.tilt_min || tilt > pdev->angle_range.tilt_max) return -ERANGE; /* go to relative range, check again */ pan -= pdev->pan_angle; tilt -= pdev->tilt_angle; /* angles are specified in degrees * 100, thus the limit = 36000 */ if (pan < -36000 || pan > 36000 || tilt < -36000 || tilt > 36000) return -ERANGE; ret = _pwc_mpt_set_angle(pdev, pan, tilt); if (ret >= 0) { pdev->pan_angle += pan; pdev->tilt_angle += tilt; } if (ret == -EPIPE) /* stall -> out of range */ ret = -ERANGE; return ret;}static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *status){ int ret; unsigned char buf[5]; ret = RecvControlMsg(GET_MPT_CTL, PT_STATUS_FORMATTER, 5); if (ret < 0) return ret; status->status = buf[0] & 0x7; // 3 bits are used for reporting status->time_pan = (buf[1] << 8) + buf[2]; status->time_tilt = (buf[3] << 8) + buf[4]; return 0;}int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor){ unsigned char buf; int ret = -1, request; if (pdev->type < 675) request = SENSOR_TYPE_FORMATTER1; else if (pdev->type < 730) return -1; /* The Vesta series doesn't have this call */ else request = SENSOR_TYPE_FORMATTER2; ret = RecvControlMsg(GET_STATUS_CTL, request, 1); if (ret < 0) return ret; if (pdev->type < 675) *sensor = buf | 0x100; else *sensor = buf; return 0;} /* End of Add-Ons */ /* ************************************************* *//* Linux 2.5.something and 2.6 pass direct pointers to arguments of ioctl() calls. With 2.4, you have to do tedious copy_from_user() and copy_to_user() calls. With these macros we circumvent this, and let me maintain only one source file. The functionality is exactly the same otherwise. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)/* define local variable for arg */#define ARG_DEF(ARG_type, ARG_name)\ ARG_type *ARG_name = arg;/* copy arg to local variable */ #define ARG_IN(ARG_name) /* nothing *//* argument itself (referenced) */#define ARGR(ARG_name) (*ARG_name)/* argument address */#define ARGA(ARG_name) ARG_name/* copy local variable to arg */#define ARG_OUT(ARG_name) /* nothing */#else#define ARG_DEF(ARG_type, ARG_name)\ ARG_type ARG_name;#define ARG_IN(ARG_name)\ if (copy_from_user(&ARG_name, arg, sizeof(ARG_name))) {\ ret = -EFAULT;\ break;\ }#define ARGR(ARG_name) ARG_name#define ARGA(ARG_name) &ARG_name#define ARG_OUT(ARG_name)\ if (copy_to_user(arg, &ARG_name, sizeof(ARG_name))) {\ ret = -EFAULT;\ break;\ }#endifint pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg){ int ret = 0; switch(cmd) { case VIDIOCPWCRUSER: { if (pwc_restore_user(pdev)) ret = -EINVAL; break; } case VIDIOCPWCSUSER: { if (pwc_save_user(pdev)) ret = -EINVAL; break; } case VIDIOCPWCFACTORY: { if (pwc_restore_factory(pdev)) ret = -EINVAL; break; } case VIDIOCPWCSCQUAL: { ARG_DEF(int, qual) ARG_IN(qual) if (ARGR(qual) < 0 || ARGR(qual) > 3) ret = -EINVAL; else ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); if (ret >= 0) pdev->vcompression = ARGR(qual); break; } case VIDIOCPWCGCQUAL: { ARG_DEF(int, qual) ARGR(qual) = pdev->vcompression; ARG_OUT(qual) break; } case VIDIOCPWCPROBE: { ARG_DEF(struct pwc_probe, probe) strcpy(ARGR(probe).name, pdev->vdev->name); ARGR(probe).type = pdev->type; ARG_OUT(probe) break; } case VIDIOCPWCGSERIAL: { ARG_DEF(struct pwc_serial, serial) strcpy(ARGR(serial).serial, pdev->serial); ARG_OUT(serial) break; } case VIDIOCPWCSAGC: { ARG_DEF(int, agc) ARG_IN(agc) if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc))) ret = -EINVAL; break; } case VIDIOCPWCGAGC: { ARG_DEF(int, agc) if (pwc_get_agc(pdev, ARGA(agc))) ret = -EINVAL; ARG_OUT(agc) break; } case VIDIOCPWCSSHUTTER: { ARG_DEF(int, shutter_speed) ARG_IN(shutter_speed) ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed)); break; } case VIDIOCPWCSAWB: { ARG_DEF(struct pwc_whitebalance, wb) ARG_IN(wb) ret = pwc_set_awb(pdev, ARGR(wb).mode); if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) { pwc_set_red_gain(pdev, ARGR(wb).manual_red); pwc_set_blue_gain(pdev, ARGR(wb).manual_blue); } break; } case VIDIOCPWCGAWB: { ARG_DEF(struct pwc_whitebalance, wb) memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance)); ARGR(wb).mode = pwc_get_awb(pdev); if (ARGR(wb).mode < 0) ret = -EINVAL; else { if (ARGR(wb).mode == PWC_WB_MANUAL) { ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red); if (ret < 0) break; ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue); if (ret < 0) break; } if (ARGR(wb).mode == PWC_WB_AUTO) { ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red); if (ret < 0) break; ret =pwc_read_blue_gain(pdev, &ARGR(wb).read_blue); if (ret < 0) break; } } ARG_OUT(wb) break; } case VIDIOCPWCSAWBSPEED: { ARG_DEF(struct pwc_wb_speed, wbs) if (ARGR(wbs).control_speed > 0) { ret = pwc_set_wb_speed(pdev, ARGR(wbs).control_speed); } if (ARGR(wbs).control_delay > 0) { ret = pwc_set_wb_delay(pdev, ARGR(wbs).control_delay); } break; } case VIDIOCPWCGAWBSPEED: { ARG_DEF(struct pwc_wb_speed, wbs) ret = pwc_get_wb_speed(pdev, &ARGR(wbs).control_speed); if (ret < 0) break; ret = pwc_get_wb_delay(pdev, &ARGR(wbs).control_delay); if (ret < 0) break; ARG_OUT(wbs) break; } case VIDIOCPWCSLED: { ARG_DEF(struct pwc_leds, leds) ARG_IN(leds) ret = pwc_set_leds(pdev, ARGR(leds).led_on, ARGR(leds).led_off); break; } case VIDIOCPWCGLED: { ARG_DEF(struct pwc_leds, leds) ret = pwc_get_leds(pdev, &ARGR(leds).led_on, &ARGR(leds).led_off); ARG_OUT(leds) break; } case VIDIOCPWCSCONTOUR: { ARG_DEF(int, contour) ARG_IN(contour) ret = pwc_set_contour(pdev, ARGR(contour)); break; } case VIDIOCPWCGCONTOUR: { ARG_DEF(int, contour) ret = pwc_get_contour(pdev, ARGA(contour)); ARG_OUT(contour) break; } case VIDIOCPWCSBACKLIGHT: { ARG_DEF(int, backlight) ARG_IN(backlight) ret = pwc_set_backlight(pdev, ARGR(backlight)); break; } case VIDIOCPWCGBACKLIGHT: { ARG_DEF(int, backlight) ret = pwc_get_backlight(pdev, ARGA(backlight)); ARG_OUT(backlight) break; } case VIDIOCPWCSFLICKER: { ARG_DEF(int, flicker) ARG_IN(flicker) ret = pwc_set_flicker(pdev, ARGR(flicker)); break; } case VIDIOCPWCGFLICKER: { ARG_DEF(int, flicker) ret = pwc_get_flicker(pdev, ARGA(flicker)); ARG_OUT(flicker) break; } case VIDIOCPWCSDYNNOISE: { ARG_DEF(int, dynnoise) ARG_IN(dynnoise) ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise)); break; } case VIDIOCPWCGDYNNOISE: { ARG_DEF(int, dynnoise) ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise)); ARG_OUT(dynnoise); break; } case VIDIOCPWCGREALSIZE: { ARG_DEF(struct pwc_imagesize, size) ARGR(size).width = pdev->image.x; ARGR(size).height = pdev->image.y; ARG_OUT(size) break; } case VIDIOCPWCMPTRESET: { if (pdev->features & FEATURE_MOTOR_PANTILT) { ARG_DEF(int, flags) ARG_IN(flags) ret = pwc_mpt_reset(pdev, ARGR(flags)); } else { ret = -ENXIO; } break; } case VIDIOCPWCMPTGRANGE: { if (pdev->features & FEATURE_MOTOR_PANTILT) { ARG_DEF(struct pwc_mpt_range, range) ARGR(range) = pdev->angle_range; ARG_OUT(range) } else { ret = -ENXIO; } break; } case VIDIOCPWCMPTSANGLE: { int new_pan, new_tilt; if (pdev->features & FEATURE_MOTOR_PANTILT) { ARG_DEF(struct pwc_mpt_angles, angles) ARG_IN(angles) /* The camera can only set relative angles, so do some calculations when getting an absolute angle . */ if (ARGR(angles).absolute) { new_pan = ARGR(angles).pan; new_tilt = ARGR(angles).tilt; } else { new_pan = pdev->pan_angle + ARGR(angles).pan; new_tilt = pdev->tilt_angle + ARGR(angles).tilt; } ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt); } else { ret = -ENXIO; } break; } case VIDIOCPWCMPTGANGLE: { if (pdev->features & FEATURE_MOTOR_PANTILT) { ARG_DEF(struct pwc_mpt_angles, angles) ARGR(angles).absolute = 1; ARGR(angles).pan = pdev->pan_angle; ARGR(angles).tilt = pdev->tilt_angle; ARG_OUT(angles) } else { ret = -ENXIO; } break; } case VIDIOCPWCMPTSTATUS: { if (pdev->features & FEATURE_MOTOR_PANTILT) { ARG_DEF(struct pwc_mpt_status, status) ret = pwc_mpt_get_status(pdev, ARGA(status)); ARG_OUT(status) } else { ret = -ENXIO; } break; } case VIDIOCPWCGVIDCMD: { ARG_DEF(struct pwc_video_command, cmd); ARGR(cmd).type = pdev->type; ARGR(cmd).release = pdev->release; ARGR(cmd).command_len = pdev->cmd_len; memcpy(&ARGR(cmd).command_buf, pdev->cmd_buf, pdev->cmd_len); ARGR(cmd).bandlength = pdev->vbandlength; ARGR(cmd).frame_size = pdev->frame_size; ARG_OUT(cmd) break; } /* case VIDIOCPWCGVIDTABLE: { ARG_DEF(struct pwc_table_init_buffer, table); ARGR(table).len = pdev->cmd_len; memcpy(&ARGR(table).buffer, pdev->decompress_data, pdev->decompressor->table_size); ARG_OUT(table) break; } */ default: ret = -ENOIOCTLCMD; break; } if (ret > 0) return 0; return ret;}/* vim: set cinoptions= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -