📄 pwc-ctrl.c
字号:
unsigned char buf; ret = RecvControlMsg(GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER, 1); if (ret < 0) return ret; *backlight = buf; return 0;}static inline int pwc_set_flicker(struct pwc_device *pdev, int flicker){ unsigned char buf; if (flicker) buf = 0xff; else buf = 0x0; return SendControlMsg(SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1);}static inline int pwc_get_flicker(struct pwc_device *pdev, int *flicker){ int ret; unsigned char buf; ret = RecvControlMsg(GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, 1); if (ret < 0) return ret; *flicker = buf; return 0;}static inline int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise){ unsigned char buf; if (noise < 0) noise = 0; if (noise > 3) noise = 3; buf = noise; return SendControlMsg(SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1);}static inline int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise){ int ret; unsigned char buf; ret = RecvControlMsg(GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER, 1); if (ret < 0) return ret; *noise = buf; return 0;}static int pwc_mpt_reset(struct pwc_device *pdev, int flags){ unsigned char buf; buf = flags & 0x03; // only lower two bits are currently used return SendControlMsg(SET_MPT_CTL, PT_RESET_CONTROL_FORMATTER, 1);}static inline 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);}static inline 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 */ /* ************************************************* */int 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: { int *qual = arg; if (*qual < 0 || *qual > 3) ret = -EINVAL; else ret = pwc_try_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, *qual, pdev->vsnapshot); if (ret >= 0) pdev->vcompression = *qual; break; } case VIDIOCPWCGCQUAL: { int *qual = arg; *qual = pdev->vcompression; break; } case VIDIOCPWCPROBE: { struct pwc_probe *probe = arg; strcpy(probe->name, pdev->vdev->name); probe->type = pdev->type; break; } case VIDIOCPWCGSERIAL: { struct pwc_serial *serial = arg; strcpy(serial->serial, pdev->serial); break; } case VIDIOCPWCSAGC: { int *agc = arg; if (pwc_set_agc(pdev, *agc < 0 ? 1 : 0, *agc)) ret = -EINVAL; break; } case VIDIOCPWCGAGC: { int *agc = arg; if (pwc_get_agc(pdev, agc)) ret = -EINVAL; break; } case VIDIOCPWCSSHUTTER: { int *shutter_speed = arg; ret = pwc_set_shutter_speed(pdev, *shutter_speed < 0 ? 1 : 0, *shutter_speed); break; } case VIDIOCPWCSAWB: { struct pwc_whitebalance *wb = arg; ret = pwc_set_awb(pdev, wb->mode); if (ret >= 0 && wb->mode == PWC_WB_MANUAL) { pwc_set_red_gain(pdev, wb->manual_red); pwc_set_blue_gain(pdev, wb->manual_blue); } break; } case VIDIOCPWCGAWB: { struct pwc_whitebalance *wb = arg; memset(wb, 0, sizeof(struct pwc_whitebalance)); wb->mode = pwc_get_awb(pdev); if (wb->mode < 0) ret = -EINVAL; else { if (wb->mode == PWC_WB_MANUAL) { ret = pwc_get_red_gain(pdev, &wb->manual_red); if (ret < 0) break; ret = pwc_get_blue_gain(pdev, &wb->manual_blue); if (ret < 0) break; } if (wb->mode == PWC_WB_AUTO) { ret = pwc_read_red_gain(pdev, &wb->read_red); if (ret < 0) break; ret = pwc_read_blue_gain(pdev, &wb->read_blue); if (ret < 0) break; } } break; } case VIDIOCPWCSAWBSPEED: { struct pwc_wb_speed *wbs = arg; if (wbs->control_speed > 0) { ret = pwc_set_wb_speed(pdev, wbs->control_speed); } if (wbs->control_delay > 0) { ret = pwc_set_wb_delay(pdev, wbs->control_delay); } break; } case VIDIOCPWCGAWBSPEED: { struct pwc_wb_speed *wbs = arg; ret = pwc_get_wb_speed(pdev, &wbs->control_speed); if (ret < 0) break; ret = pwc_get_wb_delay(pdev, &wbs->control_delay); if (ret < 0) break; break; } case VIDIOCPWCSLED: { struct pwc_leds *leds = arg; ret = pwc_set_leds(pdev, leds->led_on, leds->led_off); break; } case VIDIOCPWCGLED: { struct pwc_leds *leds = arg; ret = pwc_get_leds(pdev, &leds->led_on, &leds->led_off); break; } case VIDIOCPWCSCONTOUR: { int *contour = arg; ret = pwc_set_contour(pdev, *contour); break; } case VIDIOCPWCGCONTOUR: { int *contour = arg; ret = pwc_get_contour(pdev, contour); break; } case VIDIOCPWCSBACKLIGHT: { int *backlight = arg; ret = pwc_set_backlight(pdev, *backlight); break; } case VIDIOCPWCGBACKLIGHT: { int *backlight = arg; ret = pwc_get_backlight(pdev, backlight); break; } case VIDIOCPWCSFLICKER: { int *flicker = arg; ret = pwc_set_flicker(pdev, *flicker); break; } case VIDIOCPWCGFLICKER: { int *flicker = arg; ret = pwc_get_flicker(pdev, flicker); break; } case VIDIOCPWCSDYNNOISE: { int *dynnoise = arg; ret = pwc_set_dynamic_noise(pdev, *dynnoise); break; } case VIDIOCPWCGDYNNOISE: { int *dynnoise = arg; ret = pwc_get_dynamic_noise(pdev, dynnoise); break; } case VIDIOCPWCGREALSIZE: { struct pwc_imagesize *size = arg; size->width = pdev->image.x; size->height = pdev->image.y; break; } case VIDIOCPWCMPTRESET: { if (pdev->features & FEATURE_MOTOR_PANTILT) { int *flags = arg; ret = pwc_mpt_reset(pdev, *flags); if (ret >= 0) { pdev->pan_angle = 0; pdev->tilt_angle = 0; } } else { ret = -ENXIO; } break; } case VIDIOCPWCMPTGRANGE: { if (pdev->features & FEATURE_MOTOR_PANTILT) { struct pwc_mpt_range *range = arg; *range = pdev->angle_range; } else { ret = -ENXIO; } break; } case VIDIOCPWCMPTSANGLE: { int new_pan, new_tilt; if (pdev->features & FEATURE_MOTOR_PANTILT) { struct pwc_mpt_angles *angles = arg; /* The camera can only set relative angles, so do some calculations when getting an absolute angle . */ if (angles->absolute) { new_pan = angles->pan; new_tilt = angles->tilt; } else { new_pan = pdev->pan_angle + angles->pan; new_tilt = pdev->tilt_angle + angles->tilt; } /* check absolute ranges */ if (new_pan < pdev->angle_range.pan_min || new_pan > pdev->angle_range.pan_max || new_tilt < pdev->angle_range.tilt_min || new_tilt > pdev->angle_range.tilt_max) { ret = -ERANGE; } else { /* go to relative range, check again */ new_pan -= pdev->pan_angle; new_tilt -= pdev->tilt_angle; /* angles are specified in degrees * 100, thus the limit = 36000 */ if (new_pan < -36000 || new_pan > 36000 || new_tilt < -36000 || new_tilt > 36000) ret = -ERANGE; } if (ret == 0) /* no errors so far */ { ret = pwc_mpt_set_angle(pdev, new_pan, new_tilt); if (ret >= 0) { pdev->pan_angle += new_pan; pdev->tilt_angle += new_tilt; } if (ret == -EPIPE) /* stall -> out of range */ ret = -ERANGE; } } else { ret = -ENXIO; } break; } case VIDIOCPWCMPTGANGLE: { if (pdev->features & FEATURE_MOTOR_PANTILT) { struct pwc_mpt_angles *angles = arg; angles->absolute = 1; angles->pan = pdev->pan_angle; angles->tilt = pdev->tilt_angle; } else { ret = -ENXIO; } break; } case VIDIOCPWCMPTSTATUS: { if (pdev->features & FEATURE_MOTOR_PANTILT) { struct pwc_mpt_status *status = arg; ret = pwc_mpt_get_status(pdev, status); } else { ret = -ENXIO; } break; } case VIDIOCPWCGVIDCMD: { struct pwc_video_command *cmd = arg; cmd->type = pdev->type; cmd->release = pdev->release; cmd->command_len = pdev->cmd_len; memcpy(&cmd->command_buf, pdev->cmd_buf, pdev->cmd_len); cmd->bandlength = pdev->vbandlength; cmd->frame_size = pdev->frame_size; break; } /* case VIDIOCPWCGVIDTABLE: { struct pwc_table_init_buffer *table = arg; table->len = pdev->cmd_len; memcpy(&table->buffer, pdev->decompress_data, pdev->decompressor->table_size); break; } */ default: ret = -ENOIOCTLCMD; break; } if (ret > 0) return 0; return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -