1324 lines
34 KiB
C
1324 lines
34 KiB
C
/*
|
|
* Copyright (c) XMEDIA. All rights reserved.
|
|
*/
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
|
|
#include "video_stream.h"
|
|
|
|
#include "uvc_log.h"
|
|
#include "uvc_adapter.h"
|
|
|
|
static struct stream __stream = {
|
|
.mpi_sc_ops = NULL,
|
|
.mpi_pu_ops = NULL,
|
|
.mpi_it_ops = NULL,
|
|
.mpi_eu_ops = NULL,
|
|
.streaming = 0,
|
|
.exposure_auto_stall = 0,
|
|
.brightness_stall = 0,
|
|
};
|
|
|
|
static uint32_t focus_absolute_value = 0;
|
|
|
|
static stream *get_stream(void)
|
|
{
|
|
return &__stream;
|
|
}
|
|
|
|
static void update_req_err_code(struct uvc_device *dev, unsigned char code)
|
|
{
|
|
dev->request_error_code.length = 1;
|
|
dev->request_error_code.data[0] = code;
|
|
}
|
|
|
|
/* stream Stream Control Operation Functions End */
|
|
static void _stream_event_default_setup(uint8_t req, struct uvc_request_data *resp)
|
|
{
|
|
switch (req) {
|
|
case UVC_GET_MIN:
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x04;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->length = 1;
|
|
resp->data[0] = 0x01;
|
|
break;
|
|
default:
|
|
resp->length = 1;
|
|
resp->data[0] = 0x06;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*******************************************************
|
|
* stream Processing Unit Operation Functions
|
|
*******************************************************/
|
|
static void _stream_pu_brightness_ctrl(struct uvc_device *dev, uint8_t req, struct uvc_request_data *resp)
|
|
{
|
|
uint16_t v;
|
|
uint8_t err_code = UVC_REC_NO_ERROR;
|
|
|
|
v = (uint16_t)stream_pu_get_brightness();
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
if(get_stream()->brightness_stall) {
|
|
err_code = UVC_REC_WRONG_STATE;
|
|
resp->length = -EL2HLT;
|
|
get_stream()->brightness_stall = 0;
|
|
} else {
|
|
resp->length = 2;
|
|
resp->data[0] = (v & 0xff);
|
|
resp->data[1] = ((v >> 8) & 0xff);
|
|
}
|
|
break;
|
|
case UVC_GET_MIN:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x00;
|
|
resp->data[1] = 0x00;
|
|
break;
|
|
case UVC_GET_MAX:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x64;
|
|
resp->data[1] = 0x00;
|
|
break;
|
|
case UVC_GET_DEF:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x32;
|
|
resp->data[1] = 0x00;
|
|
break;
|
|
case UVC_GET_RES:
|
|
resp->data[0] = 0x01;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
err_code = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
update_req_err_code(dev, err_code);
|
|
}
|
|
|
|
static void _stream_pu_brightness_set(struct uvc_request_data *data)
|
|
{
|
|
uint16_t v;
|
|
|
|
v = data->data[0] + (data->data[1] << 8);
|
|
stream_pu_set_brightness(v);
|
|
}
|
|
|
|
void _stream_pu_contrast_ctrl(struct uvc_device *dev, uint8_t req, struct uvc_request_data *resp)
|
|
{
|
|
uint8_t err_code = UVC_REC_NO_ERROR;
|
|
uint16_t v = stream_pu_get_contrast();
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->length = 2;
|
|
resp->data[0] = (v & 0xff);
|
|
resp->data[1] = ((v >> 8) & 0xff);
|
|
break;
|
|
case UVC_GET_MIN:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x00;
|
|
resp->data[1] = 0x00;
|
|
break;
|
|
case UVC_GET_MAX:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x64;
|
|
resp->data[1] = 0x00;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x02;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
err_code = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
update_req_err_code(dev, err_code);
|
|
}
|
|
|
|
static void _stream_pu_contrast_set(struct uvc_request_data *data)
|
|
{
|
|
uint16_t v = 0;
|
|
|
|
if (get_stream()->streaming != 1) {
|
|
return;
|
|
}
|
|
|
|
v = data->data[0] + (data->data[1] << 8);
|
|
stream_pu_set_contrast(v);
|
|
}
|
|
|
|
void _stream_pu_hue_ctrl(struct uvc_device *dev, uint8_t req, struct uvc_request_data *resp)
|
|
{
|
|
uint16_t v = 50;
|
|
uint8_t err_code = UVC_REC_NO_ERROR;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->hue_get)
|
|
v = get_stream()->mpi_pu_ops->hue_get();
|
|
}
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->length = 2;
|
|
resp->data[0] = (v & 0xff);
|
|
resp->data[1] = ((v >> 8) & 0xff);
|
|
break;
|
|
case UVC_GET_MIN:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x00;
|
|
resp->data[1] = 0x00;
|
|
break;
|
|
case UVC_GET_MAX:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x64;
|
|
resp->data[1] = 0x00;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x02;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
err_code = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
update_req_err_code(dev, err_code);
|
|
}
|
|
|
|
static void _stream_pu_hue_set(struct uvc_request_data *data)
|
|
{
|
|
uint16_t v = 0;
|
|
|
|
if (get_stream()->streaming != 1) {
|
|
return;
|
|
}
|
|
|
|
v = data->data[0] + (data->data[1] << 8);
|
|
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->hue_set) {
|
|
get_stream()->mpi_pu_ops->hue_set(v);
|
|
}
|
|
}
|
|
|
|
void _stream_pu_power_line_frequency_ctrl(struct uvc_device *dev, uint8_t req, struct uvc_request_data *resp)
|
|
{
|
|
uint8_t v = 0;
|
|
uint8_t err_code = UVC_REC_NO_ERROR;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->power_line_frequency_get)
|
|
v = get_stream()->mpi_pu_ops->power_line_frequency_get();
|
|
}
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 1;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->length = 1;
|
|
resp->data[0] = v;
|
|
break;
|
|
case UVC_GET_DEF:
|
|
resp->length = 1;
|
|
resp->data[0] = 0x1;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
err_code = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
update_req_err_code(dev, err_code);
|
|
}
|
|
|
|
static void _stream_pu_power_line_frequency_set(struct uvc_request_data *data)
|
|
{
|
|
uint8_t v = 0;
|
|
|
|
if (get_stream()->streaming != 1) {
|
|
return;
|
|
}
|
|
|
|
v = data->data[0];
|
|
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->power_line_frequency_set) {
|
|
get_stream()->mpi_pu_ops->power_line_frequency_set(v);
|
|
}
|
|
}
|
|
|
|
void _stream_pu_saturation_ctrl(struct uvc_device *dev, uint8_t req, struct uvc_request_data *resp)
|
|
{
|
|
uint16_t v = 50;
|
|
uint8_t err_code = UVC_REC_NO_ERROR;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->saturation_get)
|
|
v = get_stream()->mpi_pu_ops->saturation_get();
|
|
}
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->length = 2;
|
|
resp->data[0] = (v & 0xff);
|
|
resp->data[1] = ((v >> 8) & 0xff);
|
|
break;
|
|
case UVC_GET_MIN:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x00;
|
|
resp->data[1] = 0x00;
|
|
break;
|
|
case UVC_GET_MAX:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x64;
|
|
resp->data[1] = 0x00;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x02;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
err_code = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
update_req_err_code(dev, err_code);
|
|
}
|
|
|
|
static void _stream_pu_saturation_set(struct uvc_request_data *data)
|
|
{
|
|
uint16_t v = 0;
|
|
|
|
if (get_stream()->streaming != 1) {
|
|
return;
|
|
}
|
|
|
|
v = data->data[0] + (data->data[1] << 8);
|
|
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->saturation_set) {
|
|
get_stream()->mpi_pu_ops->saturation_set(v);
|
|
}
|
|
}
|
|
|
|
void _stream_pu_white_balance_temperature_auto_ctrl(struct uvc_device *dev, uint8_t req, struct uvc_request_data *resp)
|
|
{
|
|
uint8_t v = 0;
|
|
uint8_t err_code = UVC_REC_NO_ERROR;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->white_balance_temperature_auto_get)
|
|
v = get_stream()->mpi_pu_ops->white_balance_temperature_auto_get();
|
|
}
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 1;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->length = 1;
|
|
resp->data[0] = v;
|
|
break;
|
|
case UVC_GET_DEF:
|
|
resp->length = 1;
|
|
resp->data[0] = 0x1;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
err_code = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
update_req_err_code(dev, err_code);
|
|
}
|
|
|
|
static void _stream_pu_white_balance_temperature_auto_set(struct uvc_request_data *data)
|
|
{
|
|
uint8_t v = 0;
|
|
|
|
if (get_stream()->streaming != 1) {
|
|
return;
|
|
}
|
|
|
|
v = data->data[0];
|
|
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->white_balance_temperature_auto_set) {
|
|
get_stream()->mpi_pu_ops->white_balance_temperature_auto_set(v);
|
|
}
|
|
}
|
|
|
|
void _stream_pu_white_balance_temperature_ctrl(struct uvc_device *dev, uint8_t req, struct uvc_request_data *resp)
|
|
{
|
|
uint16_t v = 15000;
|
|
uint8_t err_code = UVC_REC_NO_ERROR;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->white_balance_temperature_get)
|
|
v = get_stream()->mpi_pu_ops->white_balance_temperature_get();
|
|
}
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->length = 2;
|
|
resp->data[0] = (v & 0xff);
|
|
resp->data[1] = ((v >> 8) & 0xff);
|
|
break;
|
|
case UVC_GET_MIN:
|
|
resp->length = 2;
|
|
resp->data[0] = (1500 & 0xff);
|
|
resp->data[1] = (1500 / 256);
|
|
break;
|
|
case UVC_GET_MAX:
|
|
resp->length = 2;
|
|
resp->data[0] = (15000 & 0xff);
|
|
resp->data[1] = (15000 / 256);
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x02;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
err_code = UVC_REC_INVALID_REQUEST;
|
|
return;
|
|
}
|
|
|
|
update_req_err_code(dev, err_code);
|
|
}
|
|
|
|
static void _stream_pu_white_balance_temperature_set(struct uvc_request_data *data)
|
|
{
|
|
uint16_t v = 0;
|
|
|
|
if (get_stream()->streaming != 1) {
|
|
return;
|
|
}
|
|
|
|
v = data->data[0] + (data->data[1] << 8);
|
|
|
|
if (get_stream()->mpi_pu_ops &&
|
|
get_stream()->mpi_pu_ops->white_balance_temperature_set) {
|
|
get_stream()->mpi_pu_ops->white_balance_temperature_set(v);
|
|
}
|
|
}
|
|
|
|
void stream_event_pu_setup(struct uvc_device *dev,
|
|
uint8_t req,
|
|
uint8_t unit_id,
|
|
uint8_t cs,
|
|
struct uvc_request_data* resp)
|
|
{
|
|
if (unit_id != UVC_PROCESSING_UNIT_ID) {
|
|
uvc_loge("Invalid unit.\n");
|
|
update_req_err_code(dev, UVC_REC_INVALID_UNIT);
|
|
return ;
|
|
}
|
|
|
|
switch(cs) {
|
|
case UVC_PU_BRIGHTNESS_CONTROL:
|
|
_stream_pu_brightness_ctrl(dev, req, resp);
|
|
break;
|
|
case UVC_PU_HUE_CONTROL:
|
|
_stream_pu_hue_ctrl(dev, req, resp);
|
|
break;
|
|
case UVC_PU_CONTRAST_CONTROL:
|
|
_stream_pu_contrast_ctrl(dev, req, resp);
|
|
break;
|
|
case UVC_PU_SATURATION_CONTROL:
|
|
_stream_pu_saturation_ctrl(dev, req, resp);
|
|
break;
|
|
case UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL:
|
|
break;
|
|
case UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL:
|
|
break;
|
|
case UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
|
|
_stream_pu_white_balance_temperature_ctrl(dev, req, resp);
|
|
break;
|
|
case UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
|
|
_stream_pu_white_balance_temperature_auto_ctrl(dev, req, resp);
|
|
break;
|
|
case UVC_PU_POWER_LINE_FREQUENCY_CONTROL:
|
|
_stream_pu_power_line_frequency_ctrl(dev, req, resp);
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
update_req_err_code(dev, UVC_REC_INVALID_CONTROL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void stream_event_pu_data(int unit_id, int control, struct uvc_request_data *data)
|
|
{
|
|
if (unit_id != UVC_PROCESSING_UNIT_ID)
|
|
return ;
|
|
|
|
switch(control) {
|
|
case UVC_PU_BRIGHTNESS_CONTROL:
|
|
return _stream_pu_brightness_set(data);
|
|
case UVC_PU_CONTRAST_CONTROL:
|
|
return _stream_pu_contrast_set(data);
|
|
case UVC_PU_HUE_CONTROL:
|
|
return _stream_pu_hue_set(data);
|
|
case UVC_PU_SATURATION_CONTROL:
|
|
return _stream_pu_saturation_set(data);
|
|
case UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
|
|
return _stream_pu_white_balance_temperature_auto_set(data);
|
|
case UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
|
|
return _stream_pu_white_balance_temperature_set(data);
|
|
case UVC_PU_POWER_LINE_FREQUENCY_CONTROL:
|
|
return _stream_pu_power_line_frequency_set(data);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
/* stream Processing Unit Operation Functions End */
|
|
|
|
/*******************************************************
|
|
* stream Input Terminal Operation Functions
|
|
*******************************************************/
|
|
static void _stream_it_exposure_auto_mode_ctrl(struct uvc_device *dev,
|
|
uint8_t req,
|
|
struct uvc_request_data *resp)
|
|
{
|
|
uint8_t v = 0x04;
|
|
uint8_t e = UVC_REC_NO_ERROR;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
if (get_stream()->mpi_it_ops &&
|
|
get_stream()->mpi_it_ops->exposure_auto_mode_get)
|
|
v = get_stream()->mpi_it_ops->exposure_auto_mode_get();
|
|
}
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 1;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
if (get_stream()->exposure_auto_stall) {
|
|
resp->length = -EL2HLT;
|
|
get_stream()->exposure_auto_stall = 0;
|
|
e = UVC_REC_WRONG_STATE;
|
|
} else {
|
|
resp->data[0] = v;
|
|
resp->length = 1;
|
|
}
|
|
break;
|
|
case UVC_GET_RES:
|
|
resp->data[0] = 0x05;
|
|
resp->length = 1;
|
|
break;
|
|
case UVC_GET_DEF:
|
|
resp->data[0] = 0x04;
|
|
resp->length = 1;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x3;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
e = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
update_req_err_code(dev, e);
|
|
}
|
|
|
|
static void _stream_it_exposure_auto_mode_set(struct uvc_request_data *data)
|
|
{
|
|
uint8_t v = 0x04;
|
|
|
|
if (get_stream()->streaming != 1) {
|
|
return;
|
|
}
|
|
|
|
v = data->data[0];
|
|
switch(v) {
|
|
case 0x01:
|
|
case 0x02:
|
|
case 0x04:
|
|
case 0x08:
|
|
get_stream()->exposure_auto_stall = 0;
|
|
break;
|
|
default:
|
|
get_stream()->exposure_auto_stall = 1;
|
|
return;
|
|
}
|
|
|
|
if (get_stream()->mpi_it_ops &&
|
|
get_stream()->mpi_it_ops->exposure_auto_mode_set) {
|
|
get_stream()->mpi_it_ops->exposure_auto_mode_set(v);
|
|
}
|
|
}
|
|
|
|
static void _stream_it_exposure_absolute_time_ctrl(struct uvc_device *dev,
|
|
uint8_t req,
|
|
struct uvc_request_data *resp)
|
|
{
|
|
uint32_t v = 2000;
|
|
uint8_t e = UVC_REC_NO_ERROR;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
if (get_stream()->mpi_it_ops &&
|
|
get_stream()->mpi_it_ops->exposure_ansolute_time_get)
|
|
v = get_stream()->mpi_it_ops->exposure_ansolute_time_get();
|
|
}
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->length = 4;
|
|
resp->data[0] = (v & 0xff);
|
|
resp->data[1] = ((v >> 8) & 0xff);
|
|
resp->data[2] = ((v >> 16) & 0xff);
|
|
resp->data[3] = ((v >> 24) & 0xff);
|
|
break;
|
|
case UVC_GET_MAX:
|
|
resp->length = 4;
|
|
resp->data[0] = (2000 & 0xff);
|
|
resp->data[1] = ((2000 >> 8) & 0xff);
|
|
resp->data[2] = 0x0;
|
|
resp->data[3] = 0x0;
|
|
break;
|
|
case UVC_GET_MIN:
|
|
resp->length = 4;
|
|
resp->data[0] = 0x0a;
|
|
resp->data[1] = 0x0;
|
|
resp->data[2] = 0x0;
|
|
resp->data[3] = 0x0;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x04;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_RES:
|
|
resp->data[0] = 0x0a;
|
|
resp->data[1] = 0x0;
|
|
resp->data[2] = 0x0;
|
|
resp->data[3] = 0x0;
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_DEF:
|
|
resp->data[0] = 0x64;
|
|
resp->data[1] = 0x0;
|
|
resp->data[2] = 0x0;
|
|
resp->data[3] = 0x0;
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0xF;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
e = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
update_req_err_code(dev, e);
|
|
}
|
|
|
|
static void _stream_it_exposure_absolute_time_set(struct uvc_request_data *data)
|
|
{
|
|
uint32_t v = 0;
|
|
|
|
if (get_stream()->streaming != 1) {
|
|
return;
|
|
}
|
|
|
|
v = (data->data[0] +
|
|
(data->data[1] << 8) +
|
|
(data->data[2] << 16) +
|
|
(data->data[3] << 24)) * 100;
|
|
|
|
if (get_stream()->mpi_it_ops &&
|
|
get_stream()->mpi_it_ops->exposure_ansolute_time_set) {
|
|
get_stream()->mpi_it_ops->exposure_ansolute_time_set(v);
|
|
}
|
|
}
|
|
|
|
static void _stream_it_focus_absolute_value_ctrl(struct uvc_device *dev,
|
|
uint8_t req,
|
|
struct uvc_request_data *resp)
|
|
{
|
|
uint32_t v = 0;
|
|
uint8_t e = UVC_REC_NO_ERROR;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
v = focus_absolute_value;
|
|
}
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->length = 2;
|
|
resp->data[0] = (v & 0xff);
|
|
resp->data[1] = ((v >> 8) & 0xff);
|
|
break;
|
|
case UVC_GET_MAX:
|
|
resp->length = 2;
|
|
resp->data[0] = (0x20 & 0xff);
|
|
resp->data[1] = (0x00 & 0xff);
|
|
break;
|
|
case UVC_GET_MIN:
|
|
resp->length = 2;
|
|
resp->data[0] = 0x0;
|
|
resp->data[1] = 0x0;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x02;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_RES:
|
|
resp->data[0] = 0x1;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_DEF:
|
|
resp->data[0] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x3;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
e = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
|
|
update_req_err_code(dev, e);
|
|
}
|
|
|
|
static void _stream_it_focus_absolute_value_set(struct uvc_request_data *data)
|
|
{
|
|
uint32_t v = 0;
|
|
|
|
if (get_stream()->streaming != 1) {
|
|
return;
|
|
}
|
|
|
|
v = data->data[0] + (data->data[1] << 8);
|
|
focus_absolute_value = v;
|
|
uvc_logi("focus_absolute: %u.\n", focus_absolute_value);
|
|
}
|
|
|
|
void stream_event_it_setup(struct uvc_device *dev,
|
|
uint8_t req,
|
|
uint8_t unit_id,
|
|
uint8_t cs,
|
|
struct uvc_request_data *resp)
|
|
{
|
|
if (unit_id != UVC_CAMERA_TERMINAL_ID) {
|
|
resp->length = -EL2HLT;
|
|
update_req_err_code(dev, UVC_REC_INVALID_UNIT);
|
|
uvc_loge("Invalid unit.\n");
|
|
return;
|
|
}
|
|
|
|
if (get_stream()->exposure_auto_stall) {
|
|
resp->length = -EL2HLT;
|
|
get_stream()->exposure_auto_stall = 0;
|
|
update_req_err_code(dev, UVC_REC_WRONG_STATE);
|
|
uvc_loge("Wrong state.\n");
|
|
return;
|
|
}
|
|
|
|
switch(cs) {
|
|
case UVC_CT_AE_MODE_CONTROL:
|
|
_stream_it_exposure_auto_mode_ctrl(dev, req, resp);
|
|
break;
|
|
case UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
|
|
_stream_it_exposure_absolute_time_ctrl(dev, req, resp);
|
|
break;
|
|
case UVC_CT_FOCUS_ABSOLUTE_CONTROL:
|
|
_stream_it_focus_absolute_value_ctrl(dev, req, resp);
|
|
break;
|
|
case UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL:
|
|
case UVC_CT_AE_PRIORITY_CONTROL:
|
|
default:
|
|
resp->length = -EL2HLT;
|
|
update_req_err_code(dev, UVC_REC_INVALID_CONTROL);
|
|
uvc_logd("Invalid control.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void stream_event_it_data(int unit_id, int control, struct uvc_request_data *data)
|
|
{
|
|
if (unit_id != UVC_CAMERA_TERMINAL_ID) {
|
|
uvc_loge("Invalid unit.\n");
|
|
return ;
|
|
}
|
|
|
|
switch(control) {
|
|
case UVC_CT_AE_MODE_CONTROL:
|
|
_stream_it_exposure_auto_mode_set(data);
|
|
break;
|
|
case UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
|
|
_stream_it_exposure_absolute_time_set(data);
|
|
break;
|
|
case UVC_CT_FOCUS_ABSOLUTE_CONTROL:
|
|
_stream_it_focus_absolute_value_set(data);
|
|
break;
|
|
default:
|
|
uvc_loge("Invalid control.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* stream Input Terminal Operation Functions End */
|
|
|
|
/*******************************************************
|
|
* stream Extension Unit vendor1 Operation Functions
|
|
*******************************************************/
|
|
static uint32_t g_vctrl01_test = 0;
|
|
static void _stream_eu_vendor1_ctrl01_setup(struct uvc_device *dev, uint8_t req, struct uvc_request_data* resp)
|
|
{
|
|
uint32_t v = g_vctrl01_test;
|
|
uint8_t e = UVC_REC_NO_ERROR;
|
|
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_CUR:
|
|
resp->data[0] = v & 0xFF;
|
|
resp->data[1] = ((v >> 8) & 0xFF);
|
|
resp->data[2] = ((v >> 16) & 0xFF);
|
|
resp->data[3] = ((v >> 24) & 0xFF);
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_MIN:
|
|
v = 0;
|
|
resp->data[0] = v & 0xFF;
|
|
resp->data[1] = ((v >> 8) & 0xFF);
|
|
resp->data[2] = ((v >> 16) & 0xFF);
|
|
resp->data[3] = ((v >> 24) & 0xFF);
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_MAX:
|
|
v = 100;
|
|
resp->data[0] = v & 0xFF;
|
|
resp->data[1] = ((v >> 8) & 0xFF);
|
|
resp->data[2] = ((v >> 16) & 0xFF);
|
|
resp->data[3] = ((v >> 24) & 0xFF);
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_RES:
|
|
v = 1;
|
|
resp->data[0] = v & 0xFF;
|
|
resp->data[1] = ((v >> 8) & 0xFF);
|
|
resp->data[2] = ((v >> 16) & 0xFF);
|
|
resp->data[3] = ((v >> 24) & 0xFF);
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x04;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
case UVC_GET_DEF:
|
|
v = 50;
|
|
resp->data[0] = v & 0xFF;
|
|
resp->data[1] = ((v >> 8) & 0xFF);
|
|
resp->data[2] = ((v >> 16) & 0xFF);
|
|
resp->data[3] = ((v >> 24) & 0xFF);
|
|
resp->length = 4;
|
|
break;
|
|
default:
|
|
uvc_loge("Invalid request.\n");
|
|
resp->length = -EL2HLT;
|
|
e = UVC_REC_INVALID_REQUEST;
|
|
break;
|
|
}
|
|
update_req_err_code(dev, e);
|
|
}
|
|
|
|
void stream_event_eu_vendor1_setup(struct uvc_device *dev,
|
|
uint8_t req,
|
|
uint8_t unit_id,
|
|
uint8_t cs,
|
|
struct uvc_request_data* resp)
|
|
{
|
|
if (unit_id != UVC_EXTENSION_UNIT_VENDOR1_ID) {
|
|
uvc_loge("Invalid unit.\n");
|
|
return;
|
|
}
|
|
|
|
switch (cs) {
|
|
case XUID_VENDOR_01:
|
|
_stream_eu_vendor1_ctrl01_setup(dev, req, resp);
|
|
break;
|
|
default:
|
|
uvc_loge("Invalid control selector: %02x\n", cs);
|
|
resp->length = -EL2HLT;
|
|
update_req_err_code(dev, UVC_REC_INVALID_CONTROL);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void _stream_eu_vendor1_ctrl01_set(struct uvc_request_data* resp)
|
|
{
|
|
uint32_t i, v;
|
|
|
|
v = 0;
|
|
uvc_logi("length = %u\n", resp->length);
|
|
for (i = 0; i < resp->length; i++) {
|
|
v |= (resp->data[i] << (i * 8));
|
|
}
|
|
|
|
g_vctrl01_test = v;
|
|
uvc_logi("set val=%u\n", g_vctrl01_test);
|
|
}
|
|
|
|
void stream_event_eu_vendor1_data(int unit_id, int control, struct uvc_request_data *data)
|
|
{
|
|
if (unit_id != UVC_EXTENSION_UNIT_VENDOR1_ID) {
|
|
uvc_loge("Invalid unit.\n");
|
|
return;
|
|
}
|
|
|
|
switch (control) {
|
|
case XUID_VENDOR_01:
|
|
_stream_eu_vendor1_ctrl01_set(data);
|
|
break;
|
|
default:
|
|
uvc_loge("Invalid control.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* stream Extension Unit vendor1 Operation Functions End */
|
|
|
|
/*******************************************************
|
|
* stream Extension Unit H264 Operation Functions
|
|
*******************************************************/
|
|
static void _stream_eu_h264_picture_type_setup(uint8_t req, struct uvc_request_data* resp)
|
|
{
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x04;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
uvc_loge("Invalid request.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void stream_event_eu_h264_setup(uint8_t req,
|
|
uint8_t unit_id,
|
|
uint8_t cs,
|
|
struct uvc_request_data* resp)
|
|
{
|
|
if (unit_id != UVC_EXTENSION_UNIT_H264_ID) {
|
|
uvc_loge("Invalid unit.\n");
|
|
return;
|
|
}
|
|
|
|
switch (cs) {
|
|
case UVCX_PICTURE_TYPE_CONTROL:
|
|
_stream_eu_h264_picture_type_setup(req, resp);
|
|
break;
|
|
default:
|
|
_stream_event_default_setup(req, resp);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void stream_event_eu_h264_data(int unit_id, int control, struct uvc_request_data *data)
|
|
{
|
|
if (unit_id != UVC_EXTENSION_UNIT_H264_ID) {
|
|
uvc_loge("Invalid unit.\n");
|
|
return;
|
|
}
|
|
|
|
switch (control) {
|
|
case UVCX_PICTURE_TYPE_CONTROL:
|
|
/*todo*/
|
|
default:
|
|
uvc_loge("Invalid control.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* stream Extension Unit H264 Operation Functions End */
|
|
|
|
/*******************************************************
|
|
* stream Extension Unit Camera Operation Functions
|
|
*******************************************************/
|
|
static void _stream_eu_camera_iframe_setup(uint8_t req,
|
|
struct uvc_request_data *resp)
|
|
{
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x04;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
uvc_loge("Invalid request.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void _stream_eu_camera_stream_setup(uint8_t req,
|
|
struct uvc_request_data *resp)
|
|
{
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x04;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
uvc_loge("Invalid request.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void _stream_eu_camera_reset_setup(uint8_t req,
|
|
struct uvc_request_data *resp)
|
|
{
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x04;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
uvc_loge("Invalid request.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void _stream_eu_camera_update_system(uint8_t req,
|
|
struct uvc_request_data *resp)
|
|
{
|
|
switch (req) {
|
|
case UVC_SET_CUR:
|
|
resp->length = 4;
|
|
break;
|
|
case UVC_GET_LEN:
|
|
resp->data[0] = 0x04;
|
|
resp->data[1] = 0x00;
|
|
resp->length = 2;
|
|
break;
|
|
case UVC_GET_INFO:
|
|
resp->data[0] = 0x03;
|
|
resp->length = 1;
|
|
break;
|
|
default:
|
|
uvc_loge("Invalid request.\n");
|
|
break;
|
|
}
|
|
}
|
|
|
|
void stream_event_eu_camera_setup(uint8_t req,
|
|
uint8_t unit_id,
|
|
uint8_t cs,
|
|
struct uvc_request_data* resp)
|
|
{
|
|
if (unit_id != UVC_EXTENSION_UNIT_CAMERA_ID) {
|
|
uvc_loge("Invalid unit.\n");
|
|
return;
|
|
}
|
|
|
|
switch (cs) {
|
|
case XUID_SET_RESET:
|
|
_stream_eu_camera_reset_setup(req, resp);
|
|
break;
|
|
|
|
case XUID_SET_STREAM:
|
|
_stream_eu_camera_stream_setup(req, resp);
|
|
break;
|
|
|
|
case XUID_SET_IFRAME:
|
|
_stream_eu_camera_iframe_setup(req, resp);
|
|
break;
|
|
|
|
case XUID_UPDATE_SYSTEM:
|
|
_stream_eu_camera_update_system(req, resp);
|
|
break;
|
|
|
|
default:
|
|
_stream_event_default_setup(req, resp);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void stream_event_eu_camera_data(int unit_id, int control, struct uvc_request_data *data)
|
|
{
|
|
if (unit_id != UVC_EXTENSION_UNIT_CAMERA_ID) {
|
|
uvc_loge("Invalid unit.\n");
|
|
return;
|
|
}
|
|
|
|
switch (control) {
|
|
case XUID_SET_RESET:
|
|
/*todo*/
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
/* stream Extension Unit Camera Operation Functions End */
|
|
|
|
/*******************************************************
|
|
* stream Stream Control Operation Functions
|
|
*******************************************************/
|
|
int video_stream_init(void)
|
|
{
|
|
if (get_stream()->mpi_sc_ops && get_stream()->mpi_sc_ops->init) {
|
|
return get_stream()->mpi_sc_ops->init();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int video_stream_deinit(void)
|
|
{
|
|
if (get_stream()->mpi_sc_ops && get_stream()->mpi_sc_ops->init) {
|
|
return get_stream()->mpi_sc_ops->deinit();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int video_stream_startup(void)
|
|
{
|
|
int ret = -1;
|
|
|
|
uvc_logi("UVC stream startup.\n");
|
|
if (get_stream()->mpi_sc_ops && get_stream()->mpi_sc_ops->startup) {
|
|
ret = get_stream()->mpi_sc_ops->startup();
|
|
}
|
|
|
|
if (ret == 0) {
|
|
get_stream()->streaming = 1;
|
|
uvc_logi("UVC stream startup ok.\n");
|
|
} else {
|
|
uvc_logw("UVC stream startup fail.\n");
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int video_stream_shutdown(void)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (get_stream()->mpi_sc_ops && get_stream()->mpi_sc_ops->shutdown) {
|
|
ret = get_stream()->mpi_sc_ops->shutdown();
|
|
}
|
|
|
|
if (ret == 0) {
|
|
get_stream()->streaming = 0;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int video_stream_set_enc_property(struct encoder_property *p)
|
|
{
|
|
if (get_stream()->mpi_sc_ops && get_stream()->mpi_sc_ops->set_property) {
|
|
return get_stream()->mpi_sc_ops->set_property(p);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int video_stream_set_enc_idr(void)
|
|
{
|
|
if (get_stream()->mpi_sc_ops && get_stream()->mpi_sc_ops->set_idr) {
|
|
return get_stream()->mpi_sc_ops->set_idr();
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
unsigned int stream_pu_get_brightness(void)
|
|
{
|
|
unsigned int val = 50;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
if (get_stream()->mpi_pu_ops && get_stream()->mpi_pu_ops->brightness_get) {
|
|
val = get_stream()->mpi_pu_ops->brightness_get();
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
void stream_pu_set_brightness(unsigned int val)
|
|
{
|
|
if (val > 0x64 || val < 0) {
|
|
get_stream()->brightness_stall = 1;
|
|
}
|
|
|
|
if (get_stream()->mpi_pu_ops && get_stream()->mpi_pu_ops->brightness_set) {
|
|
get_stream()->mpi_pu_ops->brightness_set(val);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
unsigned int stream_pu_get_contrast(void)
|
|
{
|
|
unsigned int val = 50;
|
|
|
|
if (get_stream()->streaming == 1) {
|
|
if (get_stream()->mpi_pu_ops && get_stream()->mpi_pu_ops->contrast_get) {
|
|
val = get_stream()->mpi_pu_ops->contrast_get();
|
|
}
|
|
}
|
|
|
|
return val;
|
|
}
|
|
|
|
void stream_pu_set_contrast(unsigned int val)
|
|
{
|
|
if (get_stream()->mpi_pu_ops && get_stream()->mpi_pu_ops->contrast_set) {
|
|
get_stream()->mpi_pu_ops->contrast_set(val);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
int stream_register_mpi_ops(struct stream_control_ops *sc_ops,
|
|
struct processing_unit_ops *pu_ops,
|
|
struct input_terminal_ops *it_ops,
|
|
struct extension_unit_ops *eu_ops)
|
|
{
|
|
if (sc_ops) {
|
|
get_stream()->mpi_sc_ops = sc_ops;
|
|
}
|
|
|
|
if (pu_ops) {
|
|
get_stream()->mpi_pu_ops = pu_ops;
|
|
}
|
|
|
|
if (it_ops) {
|
|
get_stream()->mpi_it_ops = it_ops;
|
|
}
|
|
|
|
if (eu_ops) {
|
|
get_stream()->mpi_eu_ops = eu_ops;
|
|
}
|
|
|
|
return 0;
|
|
}
|