GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
|
||||
/*
|
||||
* g_uvc.h -- USB Video Class Gadget driver API
|
||||
*
|
||||
* Copyright (C) 2009-2010 Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_USB_G_UVC_H
|
||||
#define __LINUX_USB_G_UVC_H
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
|
||||
#define UVC_EVENT_FIRST (V4L2_EVENT_PRIVATE_START + 0)
|
||||
#define UVC_EVENT_CONNECT (V4L2_EVENT_PRIVATE_START + 0)
|
||||
#define UVC_EVENT_DISCONNECT (V4L2_EVENT_PRIVATE_START + 1)
|
||||
#define UVC_EVENT_STREAMON (V4L2_EVENT_PRIVATE_START + 2)
|
||||
#define UVC_EVENT_STREAMOFF (V4L2_EVENT_PRIVATE_START + 3)
|
||||
#define UVC_EVENT_SETUP (V4L2_EVENT_PRIVATE_START + 4)
|
||||
#define UVC_EVENT_DATA (V4L2_EVENT_PRIVATE_START + 5)
|
||||
#define UVC_EVENT_LAST (V4L2_EVENT_PRIVATE_START + 5)
|
||||
|
||||
struct uvc_request_data {
|
||||
__s32 length;
|
||||
__u8 data[60];
|
||||
};
|
||||
|
||||
struct uvc_event {
|
||||
union {
|
||||
enum usb_device_speed speed;
|
||||
struct usb_ctrlrequest req;
|
||||
struct uvc_request_data data;
|
||||
};
|
||||
};
|
||||
|
||||
#define UVCIOC_SEND_RESPONSE _IOW('U', 1, struct uvc_request_data)
|
||||
|
||||
#endif /* __LINUX_USB_G_UVC_H */
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
#ifndef __UVC_ADAPTER_H__
|
||||
#define __UVC_ADAPTER_H__
|
||||
|
||||
/* For Requests */
|
||||
/* 和内核中的定义一致 */
|
||||
/* For VideoControl Requests */
|
||||
#define UVC_VC_INTERFACE_ID 0x00
|
||||
#define UVC_CAMERA_TERMINAL_ID 0x01
|
||||
#define UVC_PROCESSING_UNIT_ID 0x02
|
||||
#define UVC_SELECTOR_UNIT_ID 0x03
|
||||
#define UVC_OUTPUT_TERMINAL_ID 0x05
|
||||
#define UVC_EXTENSION_UNIT_H264_ID 0x0A
|
||||
#define UVC_EXTENSION_UNIT_CAMERA_ID 0x11
|
||||
#define UVC_EXTENSION_UNIT_VENDOR1_ID 0x0B
|
||||
|
||||
/* For VideoStreaming Requests*/
|
||||
#define UVC_VS_INTERFACE_ID 0x01
|
||||
|
||||
/* Requests Error Code */
|
||||
#define UVC_REC_NO_ERROR 0x00
|
||||
#define UVC_REC_NO_READY 0x01
|
||||
#define UVC_REC_WRONG_STATE 0x02
|
||||
#define UVC_REC_POWER 0x03
|
||||
#define UVC_REC_OUT_OF_RANGE 0x04
|
||||
#define UVC_REC_INVALID_UNIT 0x05
|
||||
#define UVC_REC_INVALID_CONTROL 0x06
|
||||
#define UVC_REC_INVALID_REQUEST 0x07
|
||||
#define UVC_REC_UNKNOW 0xFF
|
||||
|
||||
/* Stream Error Code */
|
||||
|
||||
/* CTRL id */
|
||||
#define XUID_SET_RESET 0x01
|
||||
#define XUID_SET_STREAM 0x02
|
||||
#define XUID_SET_RESOLUTION 0x03
|
||||
#define XUID_SET_IFRAME 0x04
|
||||
#define XUID_SET_BITRATE 0x05
|
||||
#define XUID_UPDATE_SYSTEM 0x06
|
||||
|
||||
/* VENDOR1 CTRL id */
|
||||
#define XUID_VENDOR_01 0x01
|
||||
#define XUID_VENDOR_02 0x02
|
||||
#define XUID_VENDOR_03 0x03
|
||||
#define XUID_VENDOR_04 0x04
|
||||
#define XUID_VENDOR_05 0x05
|
||||
#define XUID_VENDOR_06 0x06
|
||||
#define XUID_VENDOR_07 0x07
|
||||
#define XUID_VENDOR_08 0x08
|
||||
#define XUID_VENDOR_09 0x09
|
||||
#define XUID_VENDOR_10 0x0A
|
||||
// ...
|
||||
//#define XUID_VENDOR_32 0x20
|
||||
|
||||
/* */
|
||||
#define MASK_INTF_ID(usb_ctrl) ((usb_ctrl)->wIndex & 0xFF)
|
||||
#define MASK_ENTITY_ID(usb_ctrl) (((usb_ctrl)->wIndex & 0xFF00) >> 8)
|
||||
#define MASK_CS_CODE(usb_ctrl) ((usb_ctrl)->wValue >> 8)
|
||||
#define MASK_REQ_CODE(usb_ctrl) ((usb_ctrl)->bRequest)
|
||||
|
||||
void uvc_requests_infos(struct usb_ctrlrequest* ctrl);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,502 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "uvc_formats.h"
|
||||
#include "config_svc.h"
|
||||
#include "uvc_log.h"
|
||||
|
||||
#define FORMAT_NV12 "nv12"
|
||||
#define FORMAT_NV21 "nv21"
|
||||
#define FORMAT_YUYV "yuyv"
|
||||
#define FORMAT_H264 "h264"
|
||||
#define FORMAT_H265 "h265"
|
||||
#define FORMAT_MJPEG "mjpeg"
|
||||
|
||||
#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
|
||||
#define v4l2_fourcc(a, b, c, d)\
|
||||
((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24))
|
||||
|
||||
#define V4L2_PIX_FMT_H265 v4l2_fourcc('H', '2', '6', '5') /* H265 with start codes */
|
||||
|
||||
|
||||
struct node {
|
||||
void* data;
|
||||
struct node* row;
|
||||
struct node* column;
|
||||
};
|
||||
|
||||
static struct node g_formats_list_head = {
|
||||
.data = NULL,
|
||||
.row = NULL,
|
||||
.column = NULL,
|
||||
};
|
||||
|
||||
static int g_malloc_count = 0;
|
||||
|
||||
static char* fcc_to_string(int fcc)
|
||||
{
|
||||
switch (fcc) {
|
||||
case V4L2_PIX_FMT_YUYV:
|
||||
return "yuyv";
|
||||
|
||||
case V4L2_PIX_FMT_NV21:
|
||||
return "nv21";
|
||||
|
||||
case V4L2_PIX_FMT_NV12:
|
||||
return "nv12";
|
||||
|
||||
case V4L2_PIX_FMT_MJPEG:
|
||||
return "mjpeg";
|
||||
|
||||
case V4L2_PIX_FMT_H264:
|
||||
return "h264";
|
||||
|
||||
case V4L2_PIX_FMT_H265:
|
||||
return "h265";
|
||||
|
||||
default:
|
||||
return "Unknow";
|
||||
}
|
||||
}
|
||||
|
||||
static int string_to_fcc(char* str)
|
||||
{
|
||||
if (memcmp(str, FORMAT_YUYV, strlen(str)) == 0) {
|
||||
return V4L2_PIX_FMT_YUYV;
|
||||
}
|
||||
|
||||
if (memcmp(str, FORMAT_NV21, strlen(str)) == 0) {
|
||||
return V4L2_PIX_FMT_NV21;
|
||||
}
|
||||
|
||||
if (memcmp(str, FORMAT_NV12, strlen(str)) == 0) {
|
||||
return V4L2_PIX_FMT_NV12;
|
||||
}
|
||||
|
||||
if (memcmp(str, FORMAT_MJPEG, strlen(str)) == 0) {
|
||||
return V4L2_PIX_FMT_MJPEG;
|
||||
}
|
||||
|
||||
if (memcmp(str, FORMAT_H264, strlen(str)) == 0) {
|
||||
return V4L2_PIX_FMT_H264;
|
||||
}
|
||||
|
||||
if (memcmp(str, FORMAT_H265, strlen(str)) == 0) {
|
||||
return V4L2_PIX_FMT_H265;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void show_formats_info(void)
|
||||
{
|
||||
int i, j;
|
||||
struct node* list_head = &g_formats_list_head;
|
||||
struct node* fmt_n = NULL;
|
||||
struct node* frm_n = NULL;
|
||||
struct uvc_format_info* fmt_info = NULL;
|
||||
struct uvc_frame_info* frm_info = NULL;
|
||||
|
||||
printf("\n");
|
||||
printf("Formats info:\n");
|
||||
fmt_n = list_head->row;
|
||||
i = 1;
|
||||
while (fmt_n) {
|
||||
fmt_info = (struct uvc_format_info*)fmt_n->data;
|
||||
printf("\tFormat %d: %s\n", i, fcc_to_string(fmt_info->fcc));
|
||||
frm_n = fmt_n->column;
|
||||
j = 1;
|
||||
while (frm_n) {
|
||||
frm_info = (struct uvc_frame_info*)frm_n->data;
|
||||
printf("\tFrame %d: \t%d x %d \t@ %d.\n",
|
||||
j, frm_info->width, frm_info->height, frm_info->intervals[0]);
|
||||
frm_n = frm_n->column;
|
||||
j++;
|
||||
}
|
||||
|
||||
fmt_n = fmt_n->row;
|
||||
i++;
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
static struct node* new_node(void* data)
|
||||
{
|
||||
struct node* new = malloc(sizeof(struct node));
|
||||
|
||||
if (new == NULL) {
|
||||
uvc_loge("Out of memory\n");
|
||||
} else {
|
||||
g_malloc_count++;
|
||||
new->data = data;
|
||||
new->row = NULL;
|
||||
new->column = NULL;
|
||||
}
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
static struct node* new_format(int fcc)
|
||||
{
|
||||
struct node* new_fmt = NULL;
|
||||
struct uvc_format_info* fmt = malloc(sizeof(struct uvc_format_info));
|
||||
|
||||
if (fmt == NULL) {
|
||||
uvc_loge("Out of memory.\n");
|
||||
} else {
|
||||
g_malloc_count++;
|
||||
fmt->fcc = fcc;
|
||||
fmt->frames = NULL;
|
||||
fmt->frm_nums = 0;
|
||||
new_fmt = new_node(fmt);
|
||||
if (new_fmt == NULL) {
|
||||
free(fmt);
|
||||
g_malloc_count--;
|
||||
fmt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return new_fmt;
|
||||
}
|
||||
|
||||
static struct node* new_frame(int w, int h, int interval)
|
||||
{
|
||||
struct node* new_frm = NULL;
|
||||
struct uvc_frame_info* frm = malloc(sizeof(struct uvc_frame_info));
|
||||
|
||||
if (frm == NULL) {
|
||||
uvc_loge("Out of memory.\n");
|
||||
} else {
|
||||
g_malloc_count++;
|
||||
memset(frm, 0, sizeof(struct uvc_frame_info));
|
||||
frm->width = w;
|
||||
frm->height = h;
|
||||
frm->intervals[0] = interval;
|
||||
|
||||
new_frm = new_node(frm);
|
||||
if (new_frm == NULL) {
|
||||
free(frm);
|
||||
g_malloc_count--;
|
||||
frm = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return new_frm;
|
||||
}
|
||||
|
||||
static void add_format_tail(struct node* list_head, struct node* new_fmt)
|
||||
{
|
||||
struct node* cur = list_head;
|
||||
|
||||
while (cur->row) {
|
||||
cur = cur->row;
|
||||
}
|
||||
|
||||
cur->row = new_fmt;
|
||||
}
|
||||
|
||||
static void add_frame_tail(struct node* list_head, int fcc, struct node* new_frm)
|
||||
{
|
||||
struct node* frm = NULL;
|
||||
struct node* fmt = list_head->row;
|
||||
struct uvc_format_info* fmt_info = NULL;
|
||||
|
||||
while (fmt) {
|
||||
fmt_info = (struct uvc_format_info*)fmt->data;
|
||||
if (fmt_info->fcc == fcc) {
|
||||
fmt_info->frm_nums++;
|
||||
break;
|
||||
} else {
|
||||
fmt = fmt->row;
|
||||
}
|
||||
}
|
||||
|
||||
if (fmt == NULL) {
|
||||
uvc_loge("Not found format: %d.\n", fcc);
|
||||
return;
|
||||
}
|
||||
|
||||
frm = fmt;
|
||||
while (frm->column) {
|
||||
frm = frm->column;
|
||||
}
|
||||
|
||||
frm->column = new_frm;
|
||||
}
|
||||
|
||||
static void add_format(struct node* list_head, int fcc)
|
||||
{
|
||||
struct node* new_fmt = new_format(fcc);
|
||||
|
||||
add_format_tail(list_head, new_fmt);
|
||||
}
|
||||
|
||||
static void add_frame(struct node* list_head, int fcc, struct uvc_frame_info frm)
|
||||
{
|
||||
struct node* new_frm = new_frame(frm.width, frm.height, frm.intervals[0]);
|
||||
|
||||
add_frame_tail(list_head, fcc, new_frm);
|
||||
}
|
||||
|
||||
static char* parser_sub(char* in, char* out, char k)
|
||||
{
|
||||
char* tmp = in;
|
||||
|
||||
while (1) {
|
||||
if (*tmp == '\0') {
|
||||
tmp = NULL;
|
||||
break;
|
||||
} else if (*tmp == k) {
|
||||
/* step k */
|
||||
tmp++;
|
||||
break;
|
||||
} else {
|
||||
*out++ = *tmp++;
|
||||
}
|
||||
}
|
||||
|
||||
*out = '\0';
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
static char* parser_format(char* str, char* format)
|
||||
{
|
||||
char k = ',';
|
||||
return parser_sub(str, format, k);
|
||||
}
|
||||
|
||||
static char* parser_frame(char* formats, char* frame)
|
||||
{
|
||||
char k = ',';
|
||||
return parser_sub(formats, frame, k);
|
||||
}
|
||||
|
||||
static int frame_interval(int fps)
|
||||
{
|
||||
return ((1000 * 10000) / fps);
|
||||
}
|
||||
|
||||
static void parser_whf(char* frame, struct uvc_frame_info* frm_info)
|
||||
{
|
||||
int i;
|
||||
char param[16];
|
||||
char* tmp = frame;
|
||||
char k = '-';
|
||||
|
||||
/* width */
|
||||
bzero(param, sizeof(param));
|
||||
tmp = parser_sub(tmp, param, k);
|
||||
frm_info->width = atoi(param);
|
||||
|
||||
/* height */
|
||||
bzero(param, sizeof(param));
|
||||
tmp = parser_sub(tmp, param, k);
|
||||
frm_info->height = atoi(param);
|
||||
|
||||
/* fps */
|
||||
i = 0;
|
||||
do {
|
||||
bzero(param, sizeof(param));
|
||||
tmp = parser_sub(tmp, param, k);
|
||||
|
||||
if (i == ARRAY_SIZE(frm_info->intervals)) {
|
||||
break;
|
||||
}
|
||||
|
||||
frm_info->intervals[i++] = frame_interval(atoi(param));
|
||||
} while (tmp != NULL);
|
||||
}
|
||||
|
||||
static int init_format(char* key)
|
||||
{
|
||||
int rc, fcc;
|
||||
char str[256];
|
||||
char frame[256];
|
||||
char format[16];
|
||||
char stream[32] = "stream:";
|
||||
char* tmp = NULL;
|
||||
struct uvc_frame_info frm_info= {0};
|
||||
|
||||
strcat(stream, key);
|
||||
bzero(str, sizeof(str));
|
||||
rc = get_config_string(stream, str, sizeof(str));
|
||||
if (rc < 0) {
|
||||
uvc_logd("Not found %s\n", stream);
|
||||
return -1;
|
||||
}
|
||||
|
||||
tmp = (char*)str;
|
||||
|
||||
bzero(format, sizeof(format));
|
||||
tmp = parser_format(tmp, format);
|
||||
if (tmp == NULL) {
|
||||
uvc_loge("parser_format fail\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uvc_logd("Format %s: %s\n", format, tmp);
|
||||
|
||||
fcc = string_to_fcc(format);
|
||||
add_format(&g_formats_list_head, fcc);
|
||||
do {
|
||||
bzero(frame, sizeof(frame));
|
||||
tmp = parser_frame(tmp, frame);
|
||||
|
||||
parser_whf(frame, &frm_info);
|
||||
|
||||
add_frame(&g_formats_list_head, fcc, frm_info);
|
||||
} while (tmp != NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int frame_min(int* fmt_index, int* frm_index)
|
||||
{
|
||||
*fmt_index = 1;
|
||||
*frm_index = 1;
|
||||
|
||||
uvc_logd("Format min {format %d, frame %d}\n", *fmt_index, *frm_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int frame_max(int* fmt_index, int* frm_index)
|
||||
{
|
||||
struct node* list_head = &g_formats_list_head;
|
||||
struct node* tmp = list_head;
|
||||
int index;
|
||||
|
||||
index = 0;
|
||||
while (tmp->row) {
|
||||
tmp = tmp->row;
|
||||
index++;
|
||||
}
|
||||
*fmt_index = index;
|
||||
|
||||
index = 0;
|
||||
while (tmp->column) {
|
||||
tmp = tmp->column;
|
||||
index++;
|
||||
}
|
||||
*frm_index = index;
|
||||
|
||||
uvc_logd("Format max {format %d, frame %d}\n", *fmt_index, *frm_index);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int find_frame(int* fmt_index, int* frm_index, int* fcc, struct uvc_frame_info* frame)
|
||||
{
|
||||
struct node* list_head = &g_formats_list_head;
|
||||
struct node* tmp = list_head;
|
||||
struct uvc_format_info* fmt = NULL;
|
||||
struct uvc_frame_info* frm = NULL;
|
||||
int index;
|
||||
|
||||
if (list_head->row == NULL) {
|
||||
uvc_loge("UVC formats is not initialized.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (*fmt_index == 0) {
|
||||
frame_min(fmt_index, frm_index);
|
||||
} else if (*fmt_index < 0) {
|
||||
frame_max(fmt_index, frm_index);
|
||||
}
|
||||
|
||||
if (frame == NULL || fcc == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Find format */
|
||||
index = *fmt_index;
|
||||
while (index-- && tmp) {
|
||||
tmp = tmp->row;
|
||||
}
|
||||
|
||||
if (tmp == NULL) {
|
||||
uvc_logw("Not found {format %d , frame %d }, Use {format 1, frame 1}\n", *fmt_index, *frm_index);
|
||||
show_formats_info();
|
||||
fflush(stdout);
|
||||
|
||||
*fmt_index = 1;
|
||||
*frm_index = 1;
|
||||
|
||||
return find_frame(fmt_index, frm_index, fcc, frame);
|
||||
}
|
||||
|
||||
fmt = (struct uvc_format_info*)tmp->data;
|
||||
*fcc = fmt->fcc;
|
||||
|
||||
/* Find frame */
|
||||
index = *frm_index;
|
||||
while (index-- && tmp) {
|
||||
tmp = tmp->column;
|
||||
}
|
||||
|
||||
if (tmp == NULL) {
|
||||
uvc_logw("Not found {format %d, frame %d}, Use {format %d, frame 1}\n", *fmt_index, *frm_index, *fmt_index);
|
||||
show_formats_info();
|
||||
fflush(stdout);
|
||||
|
||||
*frm_index = 1;
|
||||
|
||||
return find_frame(fmt_index, frm_index, fcc, frame);
|
||||
}
|
||||
|
||||
frm = (struct uvc_frame_info*)tmp->data;
|
||||
memcpy(frame, frm, sizeof(struct uvc_frame_info));
|
||||
|
||||
uvc_logd("Find {format %d, frame %d} : %s, %dx%d @ %d\n", *fmt_index, *frm_index,
|
||||
fcc_to_string(*fcc), frame->width, frame->height, frame->intervals[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uvc_formats_init(void)
|
||||
{
|
||||
int i, ret;
|
||||
char key[16];
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
bzero(key, sizeof(key));
|
||||
i++;
|
||||
snprintf(key, sizeof(key), "fmt%d", i);
|
||||
ret = init_format(key);
|
||||
} while (ret == 0);
|
||||
}
|
||||
|
||||
void uvc_formats_deinit(void)
|
||||
{
|
||||
struct node* list_head = &g_formats_list_head;
|
||||
struct node* row = list_head->row;
|
||||
struct node* tmp = NULL;
|
||||
struct node* column = NULL;
|
||||
|
||||
while (row) {
|
||||
list_head->row = row->row;
|
||||
|
||||
/* release resources */
|
||||
column = row;
|
||||
while (column) {
|
||||
tmp = column->column;
|
||||
free(column->data);
|
||||
g_malloc_count--;
|
||||
free(column);
|
||||
g_malloc_count--;
|
||||
column = tmp;
|
||||
}
|
||||
|
||||
row = list_head->row;
|
||||
}
|
||||
|
||||
if (g_malloc_count) {
|
||||
uvc_logw("Resource leakage.\n");
|
||||
} else {
|
||||
uvc_logi("Release resources ok.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* uvc formats
|
||||
*/
|
||||
|
||||
#ifndef __UVC_FORMATS_H__
|
||||
#define __UVC_FORMATS_H__
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#if 1
|
||||
struct uvc_frame_info {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int intervals[8];
|
||||
};
|
||||
|
||||
struct uvc_format_info {
|
||||
unsigned int fcc;
|
||||
unsigned int frm_nums;
|
||||
const struct uvc_frame_info* frames;
|
||||
};
|
||||
|
||||
void uvc_formats_init(void);
|
||||
|
||||
void uvc_formats_deinit(void);
|
||||
|
||||
int find_frame(int* fmt_index, int* frm_index, int* fcc, struct uvc_frame_info* frame);
|
||||
|
||||
#else
|
||||
struct uvc_frame_info {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int intervals[8];
|
||||
};
|
||||
|
||||
struct uvc_format_info {
|
||||
unsigned int fcc;
|
||||
const struct uvc_frame_info* frames;
|
||||
};
|
||||
|
||||
static const struct uvc_frame_info uvc_frames_yuv[] = {
|
||||
{ 640, 360, {333333, 0 }, },
|
||||
{ 1280, 720, {333333, 0 }, },
|
||||
{ 1920, 1080, {333333, 0 }, },
|
||||
{ 3840, 2160, {333333, 0 }, },
|
||||
{ 0, 0, { 0, }, },
|
||||
};
|
||||
|
||||
static const struct uvc_frame_info uvc_frames_mjpeg[] = {
|
||||
{ 640, 360, {333333, 0 }, },
|
||||
{ 1280, 720, {333333, 0 }, },
|
||||
{ 1920, 1080, {333333, 0 }, },
|
||||
{ 3840, 2160, {333333, 0 }, },
|
||||
{ 0, 0, { 0, }, },
|
||||
};
|
||||
|
||||
static const struct uvc_frame_info uvc_frames_h264[] = {
|
||||
{ 640, 360, {333333, 0 }, },
|
||||
{ 1280, 720, {333333, 0 }, },
|
||||
{ 1920, 1080, {333333, 0 }, },
|
||||
{ 3840, 2160, {333333, 0 }, },
|
||||
{ 0, 0, { 0, }, },
|
||||
};
|
||||
|
||||
static const struct uvc_format_info uvc_formats[] = {
|
||||
{V4L2_PIX_FMT_YUYV, uvc_frames_yuv},
|
||||
{V4L2_PIX_FMT_MJPEG, uvc_frames_mjpeg},
|
||||
{V4L2_PIX_FMT_H264, uvc_frames_h264},
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __UVC_HAL_H__
|
||||
#define __UVC_HAL_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <linux/usb/g_uvc.h>
|
||||
#include <linux/usb/video.h>
|
||||
|
||||
typedef struct uvc_probe_t {
|
||||
unsigned char set;
|
||||
unsigned char get;
|
||||
unsigned char max;
|
||||
unsigned char min;
|
||||
} uvc_probe_t;
|
||||
|
||||
struct uvc_device {
|
||||
int fd;
|
||||
int streaming;
|
||||
|
||||
unsigned int req;
|
||||
unsigned int control;
|
||||
unsigned int unit_id;
|
||||
unsigned int interface_id;
|
||||
|
||||
unsigned int fcc;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int fps;
|
||||
unsigned int bulk;
|
||||
unsigned int bulk_size;
|
||||
unsigned int nbufs;
|
||||
unsigned int imgsize;
|
||||
unsigned int max_payload_size;
|
||||
unsigned char color;
|
||||
|
||||
/* USB speed specific */
|
||||
int mult;
|
||||
int burst;
|
||||
int maxpkt;
|
||||
enum usb_device_speed speed;
|
||||
|
||||
uvc_probe_t probe_status;
|
||||
struct uvc_streaming_control probe;
|
||||
struct uvc_streaming_control commit;
|
||||
|
||||
struct uvc_request_data request_error_code;
|
||||
};
|
||||
|
||||
int open_uvc_device();
|
||||
int close_uvc_device();
|
||||
int run_uvc_device();
|
||||
int run_uvc_data();
|
||||
|
||||
#endif //__UVC_HAL_H__
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* Copyright (c) XMEDIA. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/video.h>
|
||||
|
||||
#include "uvc_log.h"
|
||||
#include "uvc_adapter.h"
|
||||
|
||||
/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* +++++++++++++++++++ Requests infos +++++++++++++++++++++++++++
|
||||
*/
|
||||
|
||||
/* 4.2.2.1 Camera Terminal Control Requests */
|
||||
static char* vc_camera_terminal_cs(unsigned char cs_code)
|
||||
{
|
||||
switch (cs_code) {
|
||||
case UVC_CT_SCANNING_MODE_CONTROL:
|
||||
return "Sanning Mode";
|
||||
case UVC_CT_AE_MODE_CONTROL:
|
||||
return "Auto-Exposure Mode";
|
||||
case UVC_CT_AE_PRIORITY_CONTROL:
|
||||
return "Auto-Exposure Priority";
|
||||
case UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
|
||||
return "Exposure Time(Absolute)";
|
||||
case UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL:
|
||||
return "Exposure Time(Relative)";
|
||||
case UVC_CT_FOCUS_ABSOLUTE_CONTROL:
|
||||
return "Focus(Absolute)";
|
||||
case UVC_CT_FOCUS_RELATIVE_CONTROL:
|
||||
return "Focus(Relative)";
|
||||
case UVC_CT_FOCUS_AUTO_CONTROL:
|
||||
return "Focus(Auto)";
|
||||
case UVC_CT_IRIS_ABSOLUTE_CONTROL:
|
||||
return "Iris(Absolute)";
|
||||
case UVC_CT_IRIS_RELATIVE_CONTROL:
|
||||
return "Iris(Relative)";
|
||||
case UVC_CT_ZOOM_ABSOLUTE_CONTROL:
|
||||
return "Zoom(Absolute)";
|
||||
case UVC_CT_ZOOM_RELATIVE_CONTROL:
|
||||
return "Zoom(Relative)";
|
||||
case UVC_CT_PANTILT_ABSOLUTE_CONTROL:
|
||||
return "PanTilt(Absolute)";
|
||||
case UVC_CT_PANTILT_RELATIVE_CONTROL:
|
||||
return "PanTilt(Relative)";
|
||||
case UVC_CT_ROLL_ABSOLUTE_CONTROL:
|
||||
return "Roll(Absolute)";
|
||||
case UVC_CT_ROLL_RELATIVE_CONTROL:
|
||||
return "Roll(Relative)";
|
||||
case UVC_CT_PRIVACY_CONTROL:
|
||||
return "Privacy Shutter";
|
||||
case UVC_CT_CONTROL_UNDEFINED:
|
||||
default:
|
||||
return "Invalid control";
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.2.2 Selector Unit Control Requests */
|
||||
static char* vc_selector_unit_cs(unsigned char cs_code)
|
||||
{
|
||||
switch (cs_code) {
|
||||
case UVC_SU_INPUT_SELECT_CONTROL:
|
||||
return "Selector Unit";
|
||||
case UVC_SU_CONTROL_UNDEFINED:
|
||||
default:
|
||||
return "Invalid control";
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.2.3 Processing Unit Control Requests */
|
||||
static char* vc_processing_unit_cs(unsigned char cs_code)
|
||||
{
|
||||
switch (cs_code) {
|
||||
case UVC_PU_BACKLIGHT_COMPENSATION_CONTROL:
|
||||
return "Backlight compensation";
|
||||
case UVC_PU_BRIGHTNESS_CONTROL:
|
||||
return "Brightness";
|
||||
case UVC_PU_CONTRAST_CONTROL:
|
||||
return "Contrast";
|
||||
case UVC_PU_GAIN_CONTROL:
|
||||
return "Gain";
|
||||
case UVC_PU_POWER_LINE_FREQUENCY_CONTROL:
|
||||
return "Power Line Frequency";
|
||||
case UVC_PU_HUE_CONTROL:
|
||||
return "Hue";
|
||||
case UVC_PU_HUE_AUTO_CONTROL:
|
||||
return "Hue,Auto";
|
||||
case UVC_PU_SATURATION_CONTROL:
|
||||
return "Saturation";
|
||||
case UVC_PU_SHARPNESS_CONTROL:
|
||||
return "Sharpness";
|
||||
case UVC_PU_GAMMA_CONTROL:
|
||||
return "Gamma";
|
||||
case UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
|
||||
return "White Balance Temperature";
|
||||
case UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
|
||||
return "White Balance Temperature,Auto";
|
||||
case UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL:
|
||||
return "White Balance Component";
|
||||
case UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL:
|
||||
return "White Balance Component,Auto";
|
||||
case UVC_PU_DIGITAL_MULTIPLIER_CONTROL:
|
||||
return "Digital Multiplier";
|
||||
case UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL:
|
||||
return "Digital Multiplier Limit";
|
||||
case UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL:
|
||||
return "Analog Video Standard";
|
||||
case UVC_PU_ANALOG_LOCK_STATUS_CONTROL:
|
||||
return "Analog Video Lock Status";
|
||||
case UVC_PU_CONTROL_UNDEFINED:
|
||||
default:
|
||||
return "Invalid control";
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.2.4 Extension Unit Control Requests */
|
||||
static char* vc_extension_unit_h264_cs(unsigned char cs_code)
|
||||
{
|
||||
return "Invalid control";
|
||||
}
|
||||
|
||||
/* 4.2.1 Intercace Control Requests */
|
||||
static char* vc_interface_cs(unsigned char cs_code)
|
||||
{
|
||||
switch (cs_code) {
|
||||
case UVC_VC_VIDEO_POWER_MODE_CONTROL:
|
||||
return "Device Power Mode";
|
||||
case UVC_VC_REQUEST_ERROR_CODE_CONTROL:
|
||||
return "Request Error Code Control";
|
||||
case UVC_VC_CONTROL_UNDEFINED:
|
||||
default:
|
||||
return "Invalid control";
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.3.1 Interface Control Requests */
|
||||
static char* vs_interface_cs(unsigned char cs_code)
|
||||
{
|
||||
switch (cs_code) {
|
||||
case UVC_VS_PROBE_CONTROL:
|
||||
return "Video Probe";
|
||||
case UVC_VS_COMMIT_CONTROL:
|
||||
return "Video Commit";
|
||||
case UVC_VS_STILL_PROBE_CONTROL:
|
||||
return "Video Still Probe";
|
||||
case UVC_VS_STILL_COMMIT_CONTROL:
|
||||
return "Video Still Commit";
|
||||
case UVC_VS_STILL_IMAGE_TRIGGER_CONTROL:
|
||||
return "Still Image Trigger";
|
||||
case UVC_VS_STREAM_ERROR_CODE_CONTROL:
|
||||
return "Stream Error Code";
|
||||
case UVC_VS_GENERATE_KEY_FRAME_CONTROL:
|
||||
return "Generate Key Frame";
|
||||
case UVC_VS_UPDATE_FRAME_SEGMENT_CONTROL:
|
||||
return "Update Frame Segment";
|
||||
case UVC_VS_SYNC_DELAY_CONTROL:
|
||||
return "Sync Delay";
|
||||
case UVC_VS_CONTROL_UNDEFINED:
|
||||
default:
|
||||
return "Invalid control";
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.2 Unit and Terminal Control Requests */
|
||||
static char* vc_entity_name(unsigned char entity_id)
|
||||
{
|
||||
switch (entity_id) {
|
||||
case UVC_CAMERA_TERMINAL_ID:
|
||||
return "Camera Terminal";
|
||||
case UVC_PROCESSING_UNIT_ID:
|
||||
return "Processing Unit";
|
||||
case UVC_OUTPUT_TERMINAL_ID:
|
||||
return "Output Terminal";
|
||||
case UVC_SELECTOR_UNIT_ID:
|
||||
return "Selector Unit";
|
||||
case UVC_EXTENSION_UNIT_H264_ID:
|
||||
return "Extension Unit H264";
|
||||
default:
|
||||
return "Invalid Unit";
|
||||
}
|
||||
}
|
||||
|
||||
static char* control_entity_cs(unsigned char entity_id, unsigned char cs_code)
|
||||
{
|
||||
switch (entity_id) {
|
||||
case UVC_CAMERA_TERMINAL_ID:
|
||||
return vc_camera_terminal_cs(cs_code);
|
||||
case UVC_PROCESSING_UNIT_ID:
|
||||
return vc_processing_unit_cs(cs_code);
|
||||
case UVC_OUTPUT_TERMINAL_ID:
|
||||
return "Unsupported unit";
|
||||
case UVC_SELECTOR_UNIT_ID:
|
||||
return vc_selector_unit_cs(cs_code);
|
||||
case UVC_EXTENSION_UNIT_H264_ID:
|
||||
return vc_extension_unit_h264_cs(cs_code);
|
||||
default:
|
||||
return "Invalid unit";
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.1 Intercace Control Requests */
|
||||
/* 4.3.1 Interface Control Requests */
|
||||
static char* control_interface_name(unsigned char interface_id)
|
||||
{
|
||||
switch (interface_id) {
|
||||
case UVC_VS_INTERFACE_ID:
|
||||
return "VS Interface";
|
||||
case UVC_VC_INTERFACE_ID:
|
||||
return "VC Interface";
|
||||
default:
|
||||
return "Invalid Interface";
|
||||
}
|
||||
}
|
||||
|
||||
static char* control_interface_cs(unsigned char interface_id, unsigned char cs_code)
|
||||
{
|
||||
switch (interface_id) {
|
||||
case UVC_VC_INTERFACE_ID:
|
||||
return vc_interface_cs(cs_code);
|
||||
case UVC_VS_INTERFACE_ID:
|
||||
return vs_interface_cs(cs_code);
|
||||
default:
|
||||
return "Invalid Interface";
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.1 Requests Layout */
|
||||
static char* request_name(unsigned char req_id)
|
||||
{
|
||||
switch (req_id) {
|
||||
case UVC_SET_CUR:
|
||||
return "Set Cur";
|
||||
case UVC_GET_CUR:
|
||||
return "Get Cur";
|
||||
case UVC_GET_MIN:
|
||||
return "Get Min";
|
||||
case UVC_GET_MAX:
|
||||
return "Get Max";
|
||||
case UVC_GET_RES:
|
||||
return "Get Res";
|
||||
case UVC_GET_LEN:
|
||||
return "Get Len";
|
||||
case UVC_GET_INFO:
|
||||
return "Get Info";
|
||||
case UVC_GET_DEF:
|
||||
return "Get Def";
|
||||
case UVC_RC_UNDEFINED:
|
||||
default:
|
||||
return "Invalid request";
|
||||
}
|
||||
}
|
||||
|
||||
/* +++++++++++++++++++ Requests infos +++++++++++++++++++++++++++
|
||||
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
*/
|
||||
|
||||
/* Requests Debug */
|
||||
/*
|
||||
* Node: f_uvc.c 中定义 entity_id,各entity的ID不会为0;
|
||||
* f_uvc.c 中定义 video control interface 为 0;
|
||||
* f_uvc.c 中定义 video streaming interface 为1;
|
||||
*/
|
||||
void uvc_requests_infos(struct usb_ctrlrequest* ctrl)
|
||||
{
|
||||
// unit_id != 0, video Control
|
||||
unsigned char entity_id = MASK_ENTITY_ID(ctrl);
|
||||
|
||||
// interface_id == 0 : video control interface
|
||||
// interface_id == 1 : video streaming interface
|
||||
unsigned char interface_id = MASK_INTF_ID(ctrl);
|
||||
|
||||
unsigned char cs_code = MASK_CS_CODE(ctrl);
|
||||
unsigned char req_id = MASK_REQ_CODE(ctrl);
|
||||
|
||||
uvc_logd("reqeust type : INTERFACE.\n");
|
||||
uvc_logd("class-specific : 0x%02x(%s).\n",
|
||||
interface_id, interface_id ? "Video Streaming" : "Video Control");
|
||||
if (entity_id) {
|
||||
uvc_logd("entity id : 0x%02x(%s)\n", entity_id, vc_entity_name(entity_id));
|
||||
uvc_logd("control selector : 0x%02x(%s)\n", cs_code, control_entity_cs(entity_id, cs_code));
|
||||
} else {
|
||||
uvc_logd("interface : 0x%02x(%s)\n", interface_id, control_interface_name(interface_id));
|
||||
uvc_logd("control selector : 0x%02x(%s)\n", cs_code, control_interface_cs(interface_id, cs_code));
|
||||
}
|
||||
uvc_logd("requests : 0x%02x(%s)\n",req_id, request_name(req_id));
|
||||
}
|
||||
Reference in New Issue
Block a user