Files
TAIXIN/sdk/lib/video/uvc/uvc_host.c

1727 lines
49 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "sys_config.h"
#include "tx_platform.h"
#include "list.h"
#include "dev.h"
#include "typesdef.h"
#include "devid.h"
#include "osal/irq.h"
#include "osal/string.h"
#include "osal/semaphore.h"
#include "osal/mutex.h"
#include "osal/task.h"
#include "osal/work.h"
#include "osal/event.h"
#include "hal/usb_device.h"
#include "dev/usb/hgusb20_v1_dev_api.h"
#include "dev/usb/uvc_host.h"
#include "osal/semaphore.h"
#include "jpgdef.h"
#include "lib/lcd/lcd.h"
#include "lib/common/common.h"
#include "lib/heap/av_heap.h"
#include "lib/heap/av_psram_heap.h"
#include "stream_frame.h"
#include "utlist.h"
//兼容有psram和无psram的情况
#ifdef PSRAM_HEAP
#define UVC_MALLOC av_psram_malloc
#define UVC_FREE av_psram_free
#else
#define UVC_MALLOC av_malloc
#define UVC_FREE av_free
#endif
#if USB_EN
#define UVC_BLANK_LEN 16*1024
#ifdef PSRAM_HEAP
#define UVC_BLANK_NUM 8
#else
#define UVC_BLANK_NUM 8
#endif
#define UVC_FRAME_NUM 2
UVC_BLANK uvc_blank[UVC_BLANK_NUM];
//uint8 blank_space[UVC_BLANK_NUM][UVC_BLANK_LEN+UVC_HEAD_RESERVER]__attribute__ ((aligned(4)));
uint8 *blank_space[UVC_BLANK_NUM];
struct list_head free_uvc_tab[UVC_HOST_NUM];
struct list_head *uvc_p[UVC_HOST_NUM];
struct list_head *uvc_bnk[UVC_HOST_NUM];
UVC_MANAGE* uvc_msg[UVC_HOST_NUM];
UVC_MANAGE uvc_msg_frame[UVC_HOST_NUM][UVC_FRAME_NUM]; //2个frame就够了一个中断处正在收一个应用正在使用,带宽不足时一个frame的不同blank进行收发处理
#define NEXT_TGL ((uvc_msg[0]->uvc_head[1] & BIT(0)) ^ 1)
#define CURT_TGL (uvc_msg[0]->uvc_head[1] & BIT(0))
#define NEXT_TGL2 ((uvc_msg[1]->uvc_head[1] & BIT(0)) ^ 1)
#define CURT_TGL2 (uvc_msg[1]->uvc_head[1] & BIT(0))
uint32 frame_num[UVC_HOST_NUM];
volatile uint32 rx_packet_len;
volatile uint32 rx_packet_len_2;
volatile uint32 head_len;
int get_node_uvc_len()
{
return UVC_BLANK_LEN;
}
void *get_usb_jpeg_node_buf(void *d)
{
UVC_BLANK* uvc_b = (UVC_BLANK*)d;
return uvc_b->buf_ptr;
}
/**@brief
* 将传入的frame根节点下的buf池都送回空间池free_uvc_tab
*/
bool free_get_uvc_node_list(struct list_head *head,struct list_head *free){
if(list_empty(head)){
return 0;
}
list_splice_init(head,free);
return 1;
}
void del_usb_frame(void *get_f)
{
free_get_uvc_node_list(get_f,&free_uvc_tab[0]);
}
void del_usb_frame2(void *get_f)
{
free_get_uvc_node_list(get_f,&free_uvc_tab[1]);
}
int get_usb_node_count(struct list_head *head)
{
int count = 0;
struct list_head *first = (struct list_head *)head;
while(head->next != first)
{
head = head->next;
count++;
}
return count; //数量
}
/**@brief
* 从初始化的frame根节点中抽取其中一个空闲的根节点进行使用并标记frame的使用状态为正在使用
* @param 是否开启抢占模式,如果开启,则将上一帧已完成的帧节点删掉,并返回
*/
struct list_head* get_new_uvc_frame_head(int grab){
uint8 frame_num = 0;
for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){
if(uvc_msg_frame[0][frame_num].state == 0){
uvc_msg_frame[0][frame_num].state = 1;
uvc_msg_frame[0][frame_num].frame_end = 0;
return &uvc_msg_frame[0][frame_num].list;
}
}
if(grab) //是否开启抢占模式,开启抢占后肯定有frame返回上一帧没使用的frame肯定usable为2
{
for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){
if(uvc_msg_frame[0][frame_num].state == 2){
uvc_msg_frame[0][frame_num].state = 1;
uvc_msg_frame[0][frame_num].frame_end = 0;
free_get_uvc_node_list(&uvc_msg_frame[0][frame_num].list,&free_uvc_tab[0]);
return &uvc_msg_frame[0][frame_num].list;
}
}
}
return 0;
}
void set_uvc_frame_ready(UVC_MANAGE* uvc){
if(uvc->state != 3) //表示此frame正在被应用使用可以使用的状态不用切了
uvc->state = 2;
}
void set_uvc_frame_using(UVC_MANAGE* uvc){
uvc->state = 3;
}
void del_uvc_frame(UVC_MANAGE* uvc)
{
uvc->state = 0;
uvc->frame_len = 0;
uvc->frame_end = 0;
}
/*reset所有的frame包括正在填充的和正在使用的在填充和获取的线程或中断都关闭后调用*/
void force_reset_uvc_frame()
{
uint8 frame_num = 0;
for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){
del_usb_frame(&uvc_msg_frame[0][frame_num].list);
del_uvc_frame(&uvc_msg_frame[0][frame_num]);
}
}
/**@brief
* 从空间池中提取一个节点,放到队列中,并将此节点作为返回值返回
*/
struct list_head *get_blank_node(struct list_head *head,struct list_head *del){
if(list_empty(del)){
return 0;
}
list_move(del->prev,head);
return head->next; //返回最新的位置
}
bool put_blank_node(struct list_head *head,struct list_head *del){
irq_disable(USB20DMA_IRQn);
if(list_empty(del)){
irq_enable(USB20DMA_IRQn);
return 0;
}
list_move(del->prev,head);
irq_enable(USB20DMA_IRQn);
return 1;
}
//新增加,将节点归还到节点池
bool free_usb_node(struct list_head *del){
irq_disable(USB20DMA_IRQn);
list_move(del,&free_uvc_tab[0]);
irq_enable(USB20DMA_IRQn);
return 1;
}
//新增加,将节点归还到节点池
bool free_usb_node2(struct list_head *del){
irq_disable(USB20DMA_IRQn);
list_move(del,&free_uvc_tab[1]);
irq_enable(USB20DMA_IRQn);
return 1;
}
bool free_node2tab(UVC_BLANK* ubk,struct list_head *head,struct list_head *del)
{
put_blank_node(head,del);
return 0;
}
struct list_head* get_uvc_frame()
{
uint8 frame_num = 0;
irq_disable(USB20DMA_IRQn);
for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){
if(uvc_msg_frame[0][frame_num].state == 2) //将当前使用frame或者完成frame返回出去加以使用
{
uvc_msg_frame[0][frame_num].state = 1;
irq_enable(USB20DMA_IRQn);
return &uvc_msg_frame[0][frame_num].list;
}
}
#ifdef PSRAM_HEAP
for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){
if(uvc_msg_frame[0][frame_num].state == 1) //将当前使用frame或者完成frame返回出去加以使用
{
uvc_msg_frame[0][frame_num].state = 1;
irq_enable(USB20DMA_IRQn);
return &uvc_msg_frame[0][frame_num].list;
}
}
#endif
irq_enable(USB20DMA_IRQn);
return 0;
}
struct list_head* get_uvc_frame2()
{
uint8 frame_num = 0;
irq_disable(USB20DMA_IRQn);
for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){
if(uvc_msg_frame[1][frame_num].state == 2) //将当前使用frame或者完成frame返回出去加以使用
{
uvc_msg_frame[1][frame_num].state = 1;
irq_enable(USB20DMA_IRQn);
return &uvc_msg_frame[1][frame_num].list;
}
}
#ifdef PSRAM_HEAP
for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){
if(uvc_msg_frame[1][frame_num].state == 1) //将当前使用frame或者完成frame返回出去加以使用
{
uvc_msg_frame[1][frame_num].state = 1;
irq_enable(USB20DMA_IRQn);
return &uvc_msg_frame[1][frame_num].list;
}
}
#endif
irq_enable(USB20DMA_IRQn);
return 0;
}
void uvc_blank_init(uint8* buf, uint32 blank_len, uint8 blank_num)
{
uvc_blank[blank_num].blank_len = 0;
uvc_blank[blank_num].re_space = blank_len;
uvc_blank[blank_num].blank_loop = 0;
uvc_blank[blank_num].buf_ptr = buf;//buf+blank_num*(blank_len+UVC_HEAD_RESERVER)+UVC_HEAD_RESERVER;
uvc_blank[blank_num].busy = 0;
uvc_blank[blank_num].frame_counter = 0;
}
void uvc_blank_list_init(struct list_head *ftb,uint8 blank_num)
{
uint8 bcnt = 0;
INIT_LIST_HEAD(ftb);
for(bcnt = 0;bcnt < blank_num;bcnt++){
INIT_LIST_HEAD(&uvc_blank[bcnt].list);
list_add_tail(&uvc_blank[bcnt].list,ftb);
}
}
void uvc_blank_list_init2(struct list_head *ftb,uint8 blank_num)
{
uint8 bcnt = 0;
INIT_LIST_HEAD(ftb);
for(bcnt = 0;bcnt < blank_num;bcnt++){
os_printf("uvc blank list init2:%d\r\n",bcnt+UVC_BLANK_NUM/2);
INIT_LIST_HEAD(&uvc_blank[bcnt+UVC_BLANK_NUM/2].list);
list_add_tail(&uvc_blank[bcnt+UVC_BLANK_NUM/2].list,ftb);
}
}
void uvc_room_del(){
uint8 bcnt = 0;
for(bcnt = 0;bcnt < UVC_BLANK_NUM;bcnt++){
if(blank_space[bcnt]){
os_printf("blank del[%d]\r\n",bcnt);
UVC_FREE(blank_space[bcnt]);
blank_space[bcnt] = NULL;
}
}
}
void uvc_room_del_mjpeg(){
uint8 bcnt = 0;
for(bcnt = 0;bcnt < UVC_BLANK_NUM/2;bcnt++){
if(blank_space[bcnt]){
os_printf("h264 blank del[%d]\r\n",bcnt);
UVC_FREE(blank_space[bcnt]);
blank_space[bcnt] = NULL;
}
}
}
void uvc_room_del_h264(){
uint8 bcnt = 0;
for(bcnt = UVC_BLANK_NUM/2;bcnt < UVC_BLANK_NUM;bcnt++){
if(blank_space[bcnt]){
os_printf("mjpeg blank del[%d]\r\n",bcnt);
UVC_FREE(blank_space[bcnt]);
blank_space[bcnt] = NULL;
}
}
}
uint8_t *check_uvc_room()
{
return blank_space[0];
}
uint8_t *check_uvc_room2()
{
return blank_space[UVC_BLANK_NUM/2];
}
void uvc_room_malloc(){
uint8 bcnt = 0;
for(bcnt = 0;bcnt < UVC_BLANK_NUM;bcnt++){
if(blank_space[bcnt] == NULL){
blank_space[bcnt] = UVC_MALLOC(UVC_BLANK_LEN);
if(blank_space[bcnt] == NULL){
os_printf("uvc malloc fail\r\n");
return;
}
os_printf("blank_space[%d]:%x\r\n",bcnt,(unsigned int)blank_space[bcnt]);
}
uvc_blank_init(blank_space[bcnt],UVC_BLANK_LEN,bcnt);
}
}
void uvc_room_malloc_mjpeg(){
uint8 bcnt = 0;
for(bcnt = 0;bcnt < UVC_BLANK_NUM/2;bcnt++){
if(blank_space[bcnt] == NULL){
blank_space[bcnt] = UVC_MALLOC(UVC_BLANK_LEN);
if(blank_space[bcnt] == NULL){
os_printf("uvc malloc fail\r\n");
return;
}
os_printf("blank_space[%d]:%x\r\n",bcnt,(unsigned int)blank_space[bcnt]);
}
uvc_blank_init(blank_space[bcnt],UVC_BLANK_LEN,bcnt);
}
}
void uvc_room_malloc_h264(){
uint8 bcnt = 0;
for(bcnt = UVC_BLANK_NUM/2;bcnt < UVC_BLANK_NUM;bcnt++){
if(blank_space[bcnt] == NULL){
blank_space[bcnt] = UVC_MALLOC(UVC_BLANK_LEN);
if(blank_space[bcnt] == NULL){
os_printf("uvc malloc fail\r\n");
return;
}
os_printf("blank_space[%d]:%x\r\n",bcnt,(unsigned int)blank_space[bcnt]);
}
uvc_blank_init(blank_space[bcnt],UVC_BLANK_LEN,bcnt);
}
}
void uvc_reset_dev(uint8_t en){
if(en){
os_sleep_ms(5);
uvc_room_malloc();
_os_printf("room set");
}else{
uvc_msg_frame[0][0].frame_end = 2;
uvc_msg_frame[0][1].frame_end = 2;
uvc_msg_frame[1][0].frame_end = 2;
uvc_msg_frame[1][1].frame_end = 2;
os_sleep_ms(5);
uvc_room_del();
_os_printf("room del");
}
}
void uvc_reset_dev_mjpeg(uint8_t en){
if(en){
os_sleep_ms(5);
uvc_room_malloc_mjpeg();
_os_printf("room mjpeg set");
}else{
uvc_msg_frame[0][0].frame_end = 2;
uvc_msg_frame[0][1].frame_end = 2;
uvc_room_del_mjpeg();
_os_printf("room mjpeg del");
}
}
void uvc_reset_dev_h264(uint8_t en){
if(en){
os_sleep_ms(5);
uvc_room_malloc_h264();
_os_printf("room h264 set");
}else{
uvc_msg_frame[1][0].frame_end = 2;
uvc_msg_frame[1][1].frame_end = 2;
uvc_room_del_h264();
_os_printf("room h264 del");
}
}
extern void uvc_stream_open(struct hgusb20_dev *p_dev,uint8 enable);
struct list_head* get_new_uvc_frame_head2(int grab);
//初始化双数据流的节点空间
void uvc_room_init(void *p_dev)
{
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
//如果已经申请了空间,则不需要管,如果没有申请空间,则关闭
if(!check_uvc_room())
{
uvc_reset_dev(1);
}
uvc_blank_list_init(&free_uvc_tab[0],UVC_BLANK_NUM/2);
INIT_LIST_HEAD(&uvc_msg_frame[0][0].list);
INIT_LIST_HEAD(&uvc_msg_frame[0][1].list);
uvc_msg_frame[0][0].state = 0;
uvc_msg_frame[0][1].state = 0;
uvc_msg_frame[0][0].sta = 0;
uvc_msg_frame[0][1].sta = 0;
uvc_p[0] = get_new_uvc_frame_head(1);
uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0];
uvc_blank_list_init2(&free_uvc_tab[1],UVC_BLANK_NUM/2);
INIT_LIST_HEAD(&uvc_msg_frame[1][0].list);
INIT_LIST_HEAD(&uvc_msg_frame[1][1].list);
uvc_msg_frame[1][0].state = 0;
uvc_msg_frame[1][1].state = 0;
uvc_msg_frame[1][0].sta = 0;
uvc_msg_frame[1][1].sta = 0;
uvc_p[1] = get_new_uvc_frame_head2(1);
uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0];
}
//初始化mjpeg的节点空间
void uvc_room_init_mjpeg()
{
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
//如果已经申请了空间,则不需要管,如果没有申请空间,则关闭
if(!check_uvc_room())
{
uvc_reset_dev_mjpeg(1);
}
uvc_blank_list_init(&free_uvc_tab[0],UVC_BLANK_NUM/2);
INIT_LIST_HEAD(&uvc_msg_frame[0][0].list);
INIT_LIST_HEAD(&uvc_msg_frame[0][1].list);
uvc_msg_frame[0][0].state = 0;
uvc_msg_frame[0][1].state = 0;
uvc_msg_frame[0][0].sta = 0;
uvc_msg_frame[0][1].sta = 0;
uvc_p[0] = get_new_uvc_frame_head(1);
uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0];
}
void uvc_room_deinit_mjpeg()
{
uvc_reset_dev_mjpeg(0);
}
//初始化h264的节点空间
void uvc_room_init_h264()
{
os_printf("%s:%d\n",__FUNCTION__,__LINE__);
//如果已经申请了空间,则不需要管,如果没有申请空间,则关闭
if(!check_uvc_room2())
{
uvc_reset_dev_h264(1);
}
uvc_blank_list_init2(&free_uvc_tab[1],UVC_BLANK_NUM/2);
INIT_LIST_HEAD(&uvc_msg_frame[1][0].list);
INIT_LIST_HEAD(&uvc_msg_frame[1][1].list);
uvc_msg_frame[1][0].state = 0;
uvc_msg_frame[1][1].state = 0;
uvc_msg_frame[1][0].sta = 0;
uvc_msg_frame[1][1].sta = 0;
uvc_p[1] = get_new_uvc_frame_head2(1);
uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0];
}
void uvc_room_deinit_h264(void)
{
uvc_reset_dev_h264(0);
}
static uint8 uvc_irq_redy(UVC_MANAGE *uvc)
{
UVC_BLANK *blank;
uvc->tgl = NEXT_TGL;
uvc->sta = 1;
uvc->frame_end = 0;
uvc_bnk[0] = get_blank_node(&uvc->list,&free_uvc_tab[0]);
if(uvc_bnk[0] == NULL){
uvc->tgl = NEXT_TGL;
uvc->sta = 0;
}
else
{
blank = list_entry(uvc_bnk[0],UVC_BLANK,list);
blank->blank_loop = 0;
blank->re_space = UVC_BLANK_LEN;
blank->busy = 0;
blank->blank_len = 0;
}
return 0;
}
static uint8 uvc_irq_wait_next_frame(UVC_MANAGE *uvc)
{
if(uvc->tgl == CURT_TGL)
{
uvc->sta = 2;
}
return 0;
}
/****************************************************
0:立刻进行kcik(包含一些错误)
1:切换bank,不能立刻kick
******************************************************/
static uint8 uvc_data_handle(UVC_MANAGE *uvc,struct hgusb20_dev *p_dev,uint8_t* rx_buff,uint8 drop)
{
//static unsigned int uvc_time = 0;
//static unsigned int in_times = 0;
UVC_BLANK *blank;
uint32 data_len;
uint32 re_space;
uint32 tgl_mark;
uint8 blank_loop = 0;
uint8 ret = 0;
uint8 end_frame = 0;
data_len = rx_packet_len-head_len;
static uint8 last_frame_end = 0;
if(drop == 2){
//printf("_E_");
end_frame = 1;
drop = 0;
}
if(drop) //丢帧处理,帧异常的时候需要处理掉当前帧
{
_os_printf("_D3_");
if(uvc->state != 3){
uvc->state = 0;
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]);
}
uvc_p[0] = get_new_uvc_frame_head(1); //获取新的frame,然后检测下这个frame是不是已有blank有的话要先清
uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0];
uvc_msg[0]->sta = 0;
if(uvc_msg[0] == uvc){
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]);
del_uvc_frame(uvc);
uvc_msg[0]->state = 1;
}else{
uvc->frame_end = 2;
uvc->sta = 0;
}
return 0;
}
//in_times++;
if((uvc->tgl != CURT_TGL) || (last_frame_end==1)){
last_frame_end = 0;
uvc->sta = 2;
uvc->tgl = CURT_TGL;
tgl_mark = CURT_TGL;
#ifdef PSRAM_HEAP
set_uvc_frame_ready(uvc); //上一次frame已完成
//_os_printf("_1_");
blank = list_entry(uvc_bnk[0],UVC_BLANK,list);
blank->busy = 2;
//printf("t1:%d\n",in_times);
uvc->frame_end = 1;
// 无psram
#else
if(uvc->state == 1){ //防漏
set_uvc_frame_ready(uvc);
blank = list_entry(uvc_bnk[0],UVC_BLANK,list);
blank->busy = 2;
uvc->frame_end = 1;
}
#endif
// uvc_time = csi_kernel_get_ticks();
uvc_p[0] = get_new_uvc_frame_head(1); //获取新的frame,然后检测下这个frame是不是已有blank有的话要先清
uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0];
uvc_msg[0]->frame_counter = frame_num[0];
uvc_msg[0]->sta = 2;
uvc_msg[0]->tgl = tgl_mark;
uvc_msg[0]->frame_len = 0;
uvc_bnk[0] = get_blank_node(&uvc_msg[0]->list,&free_uvc_tab[0]); //提取新的可用blank旧的blank虽然还有可用空间但换帧后也直接抛出
// printf("GB");
uvc = uvc_msg[0];
if(uvc_bnk[0] != NULL)
{
blank = list_entry(uvc_bnk[0],UVC_BLANK,list);
blank->blank_len = 0;
blank->re_space = UVC_BLANK_LEN;
blank->busy = 0;
blank->blank_loop = blank_loop;
//切换洗一个bank,要延时kick
ret = 1;
//printf("nblank:%x %x\r\n",blank,blank_loop);
}else{
_os_printf("_D2_");
if(uvc->state != 3){
uvc->state = 0;
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]);
}
uvc_p[0] = get_new_uvc_frame_head(1); //获取新的frame,然后检测下这个frame是不是已有blank有的话要先清
uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0];
uvc_msg[0]->sta = 0;
if(uvc_msg[0] == uvc){
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]);
del_uvc_frame(uvc);
uvc_msg[0]->state = 1;
}else{
uvc->frame_end = 2;
uvc->sta = 0;
}
return 0;
}
frame_num[0]++;
}
//当前frame的数据处理
//1:通过当前frame找到当前blank的结构体
//printf("uvc_bnk:%x\r\n",uvc_bnk);
blank = list_entry(uvc_bnk[0],UVC_BLANK,list);
blank->busy = 1;
if(blank->re_space < data_len){ //当前blank剩余空间不足
//printf("a2:%x %d %d\r\n",blank->buf_ptr+blank->blank_len,blank->blank_len,blank->re_space);
hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[head_len],blank->re_space);
if((rx_buff[rx_packet_len-2] == 0xFF)&&(rx_buff[rx_packet_len-1] == 0xD9)) {
last_frame_end = 1;
}
//printf("buf:%x\r\n",blank->buf_ptr+blank->blank_len);
re_space = blank->re_space;
blank->blank_len +=blank->re_space;
blank->re_space = 0;
blank->busy = 2;
//printf("t2:%d\n",in_times);
//uvc_time = csi_kernel_get_ticks();
blank_loop = blank->blank_loop;
if(uvc == NULL)
_os_printf("uvc hehe\r\n");
uvc_bnk[0] = get_blank_node(&uvc->list,&free_uvc_tab[0]); //重新获取一个新的blank将剩余数据回填进去
// _os_printf("GB");
if(uvc_bnk[0] != 0)
{
blank = list_entry(uvc_bnk[0],UVC_BLANK,list);
blank->blank_len = 0;
blank->re_space = UVC_BLANK_LEN;
blank->busy = 0;
blank_loop++;
blank->blank_loop = blank_loop;
ret = 1;
//_os_printf("blank:%x %x\r\n",blank,blank_loop);
}else{
_os_printf("_D1_"); //一个frame就将所有的内存都占光了没有新的内存可以存放此帧图像了
if(uvc->state != 3){
uvc->state = 0;
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]);
}
uvc_p[0] = get_new_uvc_frame_head(1); //获取新的frame,然后检测下这个frame是不是已有blank有的话要先清
uvc_msg[0] = list_entry(uvc_p[0],UVC_MANAGE,list);//&uvc_msg_frame[0];
uvc_msg[0]->sta = 0;
if(uvc == NULL)
_os_printf("hehe\r\n");
if(uvc_msg[0] == uvc){
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[0]);
del_uvc_frame(uvc);
uvc_msg[0]->state = 1;
}else{
uvc->frame_end = 2;
uvc->sta = 0;
}
return 0;
}
hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[re_space+head_len],data_len - re_space);
if((rx_buff[rx_packet_len-2] == 0xFF)&&(rx_buff[rx_packet_len-1] == 0xD9)) {
last_frame_end = 1;
}
blank->re_space -=(data_len - re_space);
blank->blank_len +=(data_len - re_space);
blank->busy = 1;
uvc->frame_len += data_len;
}else{ //当前blank剩余空间足够
//printf("a1:%x %d %d\r\n",blank->buf_ptr+blank->blank_len,blank->blank_len,data_len);
hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[head_len],data_len);
if((rx_buff[rx_packet_len-2] == 0xFF)&&(rx_buff[rx_packet_len-1] == 0xD9)) {
last_frame_end = 1;
}
uvc->frame_len += data_len;
blank->re_space -=data_len;
blank->blank_len +=data_len;
//printf(".");
}
if(end_frame){
set_uvc_frame_ready(uvc);
blank->busy = 2;
uvc->frame_end = 1;
}
return ret;
}
bool uvc_data_deal(struct hgusb20_dev *p_dev)
{
uint32 hgusb20_ep_get_dma_rx_len(struct hgusb20_dev *p_dev, uint8 ep);
uint32 rx_len = hgusb20_ep_get_dma_rx_len(p_dev, UVC_EP);
if(rx_len == 0){
return 1;
}
rx_packet_len = rx_len;
//printf("rx_len:%d ",rx_packet_len);
return 0;
}
struct list_head* get_new_uvc_frame_head2(int grab){
uint8 frame_num = 0;
for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){
if(uvc_msg_frame[1][frame_num].state == 0){
uvc_msg_frame[1][frame_num].state = 1;
uvc_msg_frame[1][frame_num].frame_end = 0;
return &uvc_msg_frame[1][frame_num].list;
}
}
if(grab) //是否开启抢占模式,开启抢占后肯定有frame返回上一帧没使用的frame肯定usable为2
{
for(frame_num = 0;frame_num < UVC_FRAME_NUM;frame_num++){
if(uvc_msg_frame[1][frame_num].state == 2){
uvc_msg_frame[1][frame_num].state = 1;
uvc_msg_frame[1][frame_num].frame_end = 0;
free_get_uvc_node_list(&uvc_msg_frame[1][frame_num].list,&free_uvc_tab[1]);
return &uvc_msg_frame[1][frame_num].list;
}
}
}
return 0;
}
bool uvc_data_deal2(struct hgusb20_dev *p_dev)
{
uint32 hgusb20_ep_get_dma_rx_len(struct hgusb20_dev *p_dev, uint8 ep);
uint32 rx_len = hgusb20_ep_get_dma_rx_len(p_dev, UVC2_EP);
if(rx_len == 0){
return 1;
}
rx_packet_len_2 = rx_len;
//printf("rx_len:%d ",rx_packet_len_2);
return 0;
}
static uint8 uvc_irq_redy2(UVC_MANAGE *uvc)
{
UVC_BLANK *blank;
uvc->tgl = NEXT_TGL2;
uvc->sta = 1;
uvc->frame_end = 0;
uvc_bnk[1] = get_blank_node(&uvc->list,&free_uvc_tab[1]);
if(uvc_bnk[1] == NULL){
uvc->tgl = NEXT_TGL2;
uvc->sta = 0;
}
else
{
blank = list_entry(uvc_bnk[1],UVC_BLANK,list);
blank->blank_loop = 0;
blank->re_space = UVC_BLANK_LEN;
blank->busy = 0;
blank->blank_len = 0;
}
return 0;
}
static uint8 uvc_irq_wait_next_frame2(UVC_MANAGE *uvc)
{
if(uvc->tgl == CURT_TGL2)
{
uvc->sta = 2;
}
return 0;
}
static uint8 uvc_data_handle2(UVC_MANAGE *uvc,struct hgusb20_dev *p_dev,uint8_t* rx_buff,uint8 drop)
{
//static unsigned int uvc_time = 0;
static unsigned int in_times = 0;
UVC_BLANK *blank;
uint32 data_len;
uint32 re_space;
uint32 tgl_mark;
uint8 blank_loop = 0;
uint8 ret = 0;
uint8 end_frame = 0;
data_len = rx_packet_len_2-head_len;
static uint8 last_frame_end = 0;
if(drop == 2){
//printf("_E_");
end_frame = 1;
drop = 0;
}
if(drop) //丢帧处理,帧异常的时候需要处理掉当前帧
{
_os_printf("_D3_2");
if(uvc->state != 3){
uvc->state = 0;
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]);
}
uvc_p[1] = get_new_uvc_frame_head2(1); //获取新的frame,然后检测下这个frame是不是已有blank有的话要先清
uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0];
uvc_msg[1]->sta = 0;
if(uvc_msg[1] == uvc){
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]);
del_uvc_frame(uvc);
uvc_msg[1]->state = 1;
}else{
uvc->frame_end = 2;
uvc->sta = 0;
}
return 0;
}
in_times++;
if((uvc->tgl != CURT_TGL2) || (last_frame_end==1)){
last_frame_end = 0;
uvc->sta = 2;
uvc->tgl = CURT_TGL2;
tgl_mark = CURT_TGL2;
#ifdef PSRAM_HEAP
set_uvc_frame_ready(uvc); //上一次frame已完成
//_os_printf("_O_");
blank = list_entry(uvc_bnk[1],UVC_BLANK,list);
blank->busy = 2;
//printf("t1:%d\n",in_times);
uvc->frame_end = 1;
// 无psram
#else
if(uvc->state == 1){ //防漏
set_uvc_frame_ready(uvc);
blank = list_entry(uvc_bnk[1],UVC_BLANK,list);
blank->busy = 2;
uvc->frame_end = 1;
}
#endif
//uvc_time = os_jiffies();
uvc_p[1] = get_new_uvc_frame_head2(1); //获取新的frame,然后检测下这个frame是不是已有blank有的话要先清
uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0];
uvc_msg[1]->frame_counter = frame_num[1];
uvc_msg[1]->sta = 2;
uvc_msg[1]->tgl = tgl_mark;
uvc_msg[1]->frame_len = 0;
uvc_bnk[1] = get_blank_node(&uvc_msg[1]->list,&free_uvc_tab[1]); //提取新的可用blank旧的blank虽然还有可用空间但换帧后也直接抛出
// printf("GB");
uvc = uvc_msg[1];
if(uvc_bnk[1] != NULL)
{
blank = list_entry(uvc_bnk[1],UVC_BLANK,list);
blank->blank_len = 0;
blank->re_space = UVC_BLANK_LEN;
blank->busy = 0;
blank->blank_loop = blank_loop;
//切换洗一个bank,要延时kick
ret = 1;
//printf("nblank:%x %x\r\n",blank,blank_loop);
}else{
_os_printf("_D2_2");
if(uvc->state != 3){
uvc->state = 0;
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]);
}
uvc_p[1] = get_new_uvc_frame_head2(1); //获取新的frame,然后检测下这个frame是不是已有blank有的话要先清
uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0];
uvc_msg[1]->sta = 0;
if(uvc_msg[1] == uvc){
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]);
del_uvc_frame(uvc);
uvc_msg[1]->state = 1;
}else{
uvc->frame_end = 2;
uvc->sta = 0;
}
return 0;
}
frame_num[1]++;
}
//当前frame的数据处理
//1:通过当前frame找到当前blank的结构体
//printf("uvc_bnk:%x\r\n",uvc_bnk);
blank = list_entry(uvc_bnk[1],UVC_BLANK,list);
blank->busy = 1;
if(blank->re_space < data_len){ //当前blank剩余空间不足
//printf("a2:%x %d %d\r\n",blank->buf_ptr+blank->blank_len,blank->blank_len,blank->re_space);
hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[head_len],blank->re_space);
if((rx_buff[rx_packet_len_2-2] == 0xFF)&&(rx_buff[rx_packet_len_2-1] == 0xD9)) {
last_frame_end = 1;
}
//printf("buf:%x\r\n",blank->buf_ptr+blank->blank_len);
re_space = blank->re_space;
blank->blank_len +=blank->re_space;
blank->re_space = 0;
blank->busy = 2;
//printf("t2:%d\n",in_times);
//uvc_time = csi_kernel_get_ticks();
blank_loop = blank->blank_loop;
if(uvc == NULL)
_os_printf("uvc hehe\r\n");
uvc_bnk[1] = get_blank_node(&uvc->list,&free_uvc_tab[1]); //重新获取一个新的blank将剩余数据回填进去
// _os_printf("GB");
if(uvc_bnk[1] != 0)
{
blank = list_entry(uvc_bnk[1],UVC_BLANK,list);
blank->blank_len = 0;
blank->re_space = UVC_BLANK_LEN;
blank->busy = 0;
blank_loop++;
blank->blank_loop = blank_loop;
ret = 1;
//_os_printf("blank:%x %x\r\n",blank,blank_loop);
//return 0;
}else{
_os_printf("_D1_2"); //一个frame就将所有的内存都占光了没有新的内存可以存放此帧图像了
if(uvc->state != 3){
uvc->state = 0;
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]);
}
uvc_p[1] = get_new_uvc_frame_head2(1); //获取新的frame,然后检测下这个frame是不是已有blank有的话要先清
uvc_msg[1] = list_entry(uvc_p[1],UVC_MANAGE,list);//&uvc_msg_frame[0];
uvc_msg[1]->sta = 0;
if(uvc == NULL)
_os_printf("hehe\r\n");
if(uvc_msg[1] == uvc){
free_get_uvc_node_list(&uvc->list,&free_uvc_tab[1]);
del_uvc_frame(uvc);
uvc_msg[1]->state = 1;
}else{
uvc->frame_end = 2;
uvc->sta = 0;
}
return 0;
}
hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[re_space+head_len],data_len - re_space);
if((rx_buff[rx_packet_len_2-2] == 0xFF)&&(rx_buff[rx_packet_len_2-1] == 0xD9)) {
last_frame_end = 1;
}
blank->re_space -=(data_len - re_space);
blank->blank_len +=(data_len - re_space);
blank->busy = 1;
uvc->frame_len += data_len;
//os_printf("1");
}else{ //当前blank剩余空间足够
//printf("a1:%x %d %d\r\n",blank->buf_ptr+blank->blank_len,blank->blank_len,data_len);
hw_memcpy(blank->buf_ptr+blank->blank_len,&rx_buff[head_len],data_len);
if((rx_buff[rx_packet_len_2-2] == 0xFF)&&(rx_buff[rx_packet_len_2-1] == 0xD9)) {
last_frame_end = 1;
}
uvc->frame_len += data_len;
blank->re_space -=data_len;
blank->blank_len +=data_len;
//printf(".");
}
if(end_frame){
set_uvc_frame_ready(uvc);
blank->busy = 2;
uvc->frame_end = 1;
}
return ret;
}
int uvc_deal_mjpeg(struct hgusb20_dev *p_dev, uint8_t* rx_buff, uint8_t ep, uint8_t ep_type)
{
uint8 drop = 0;
int ret = 0;
uint32 data_len;
static uint8_t bulk_head[12];
static uint8_t recv_start = 0;
uint8_t *uvc_cache = NULL;
static uint32_t uvc_cache_buff[256+3];
if((ep_type & 0X03) == USB_ENDPOINT_XFER_BULK){
uvc_cache = (uint8_t *)&uvc_cache_buff;
hw_memcpy(uvc_msg[0]->uvc_head,rx_buff+BULK_HEAD,16);
if((uvc_msg[0]->uvc_head[0] == 0x02)&&((uvc_msg[0]->uvc_head[1]&0X80) == 0x80)&&(uvc_msg[0]->uvc_head[2] == 0xFF)&&(uvc_msg[0]->uvc_head[3] == 0xD8)){
_os_printf("P2");
hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD);
hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len);
hw_memcpy(rx_buff,uvc_cache,rx_packet_len);
uvc_msg[0]->uvc_head[0] = 12;
bulk_head[0] = 12;
}
else if((uvc_msg[0]->uvc_head[0] == 0x0c)&&((uvc_msg[0]->uvc_head[1]&0XFE) == 0x8c)&&(uvc_msg[0]->uvc_head[12] == 0xFF)&&(uvc_msg[0]->uvc_head[13] == 0xD8)){
_os_printf("P:%x ",uvc_msg[0]->uvc_head[2]);
hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD);
hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len);
hw_memcpy(rx_buff,uvc_cache,rx_packet_len);
recv_start = 1;
}else if((uvc_msg[0]->uvc_head[0] == 0x0c)&&((uvc_msg[0]->uvc_head[1]&0XFE) == 0x82)&&
(uvc_msg[0]->uvc_head[12] == 0x00)&&(uvc_msg[0]->uvc_head[13] == 0x00)&&
(uvc_msg[0]->uvc_head[14] == 0x00)&&(uvc_msg[0]->uvc_head[15] == 0x01)){
hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD);
hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len);
hw_memcpy(rx_buff,uvc_cache,rx_packet_len);
}
else{
uint8 same_cnt = 0;
if(recv_start==1) {
for(uint8 i=0; i<6; i++)
{
if(uvc_msg[0]->uvc_head[i] == bulk_head[i])
same_cnt++;
}
}
if(same_cnt < 6) {
hw_memcpy(rx_buff,bulk_head,12);
rx_packet_len+=12;
}
else {
hw_memcpy(uvc_cache+BULK_HEAD,rx_buff+BULK_HEAD*2,rx_packet_len-BULK_HEAD);
hw_memcpy(uvc_cache,bulk_head,BULK_HEAD);
hw_memcpy(rx_buff, uvc_cache, rx_packet_len);
}
}
}
hw_memcpy(uvc_msg[0]->uvc_head,rx_buff,16);
head_len = uvc_msg[0]->uvc_head[0];
if(head_len > rx_packet_len){
drop = 1;
}
data_len = rx_packet_len-head_len;
if((data_len == 0) && (uvc_msg[0]->uvc_head[1] & (BIT(6))))
{
drop = 1;
}
else if(data_len == 0)
{
return ret;
}
//无psram
#ifndef PSRAM_HEAP
if(uvc_msg[0]->uvc_head[1]&BIT(1)){
drop = 2;
}
#endif
if (hgusb20_host_is_crc_err(p_dev, ep)) {
drop = 1;
}
if((uvc_msg[0]->uvc_head[0] != 0x0c)&&(uvc_msg[0]->uvc_head[0] != 0x02)){//head[0] is head len
drop = 1;
}
if(uvc_msg[0]->uvc_head[1] & (BIT(6) | BIT(5))){//error packe
drop = 1;
}
switch(uvc_msg[0]->sta){
case 0: uvc_irq_redy(uvc_msg[0]);
case 1: ret = uvc_irq_wait_next_frame(uvc_msg[0]);
if(uvc_msg[0]->sta != 2) break;
case 2: ret = uvc_data_handle(uvc_msg[0],p_dev,rx_buff,drop); break;
}
return ret;
}
int uvc_deal_h264(struct hgusb20_dev *p_dev, uint8_t* rx_buff, uint8_t ep, uint8 ep_type)
{
uint8 drop = 0;
int ret = 0;
uint32 data_len;
static uint8_t bulk_head[12];
static uint8_t recv_start = 0;
uint8_t *uvc_cache = NULL;
static uint32_t uvc_cache_buff[256+3];
if((ep_type & 0X03) == USB_ENDPOINT_XFER_BULK){
uvc_cache = (uint8_t *)&uvc_cache_buff;
hw_memcpy(uvc_msg[1]->uvc_head,rx_buff+BULK_HEAD,16);
if((uvc_msg[1]->uvc_head[0] == 0x02)&&((uvc_msg[1]->uvc_head[1]&0X80) == 0x80)&&(uvc_msg[1]->uvc_head[2] == 0xFF)&&(uvc_msg[1]->uvc_head[3] == 0xD8)){
_os_printf("P2");
hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD);
hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len_2);
hw_memcpy(rx_buff,uvc_cache,rx_packet_len_2);
uvc_msg[1]->uvc_head[0] = 12;
bulk_head[0] = 12;
}
else if((uvc_msg[1]->uvc_head[0] == 0x0c)&&((uvc_msg[1]->uvc_head[1]&0XFE) == 0x8c)&&(uvc_msg[1]->uvc_head[12] == 0xFF)&&(uvc_msg[1]->uvc_head[13] == 0xD8)){
_os_printf("P:%x ",uvc_msg[1]->uvc_head[2]);
hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD);
hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len_2);
hw_memcpy(rx_buff,uvc_cache,rx_packet_len_2);
recv_start = 1;
}else if((uvc_msg[1]->uvc_head[0] == 0x0c)&&((uvc_msg[1]->uvc_head[1]&0XFE) == 0x82)&&
(uvc_msg[1]->uvc_head[12] == 0x00)&&(uvc_msg[1]->uvc_head[13] == 0x00)&&
(uvc_msg[1]->uvc_head[14] == 0x00)&&(uvc_msg[1]->uvc_head[15] == 0x01)){
hw_memcpy(bulk_head,rx_buff+BULK_HEAD,BULK_HEAD);
hw_memcpy(uvc_cache,rx_buff+BULK_HEAD,rx_packet_len_2);
hw_memcpy(rx_buff,uvc_cache,rx_packet_len_2);
}
else{
uint8 same_cnt = 0;
if(recv_start==1) {
for(uint8 i=0; i<6; i++)
{
if(uvc_msg[1]->uvc_head[i] == bulk_head[i])
same_cnt++;
}
}
if(same_cnt < 6) {
hw_memcpy(rx_buff,bulk_head,12);
rx_packet_len_2+=12;
}
else {
hw_memcpy(uvc_cache+BULK_HEAD,rx_buff+BULK_HEAD*2,rx_packet_len_2-BULK_HEAD);
hw_memcpy(uvc_cache,bulk_head,BULK_HEAD);
hw_memcpy(rx_buff, uvc_cache, rx_packet_len_2);
}
}
}
hw_memcpy(uvc_msg[1]->uvc_head,rx_buff,16);
head_len = uvc_msg[1]->uvc_head[0];
if(head_len > rx_packet_len_2){
drop = 1;
}
data_len = rx_packet_len_2-head_len;
if((data_len == 0) && (uvc_msg[1]->uvc_head[1] & (BIT(6))))
{
drop = 1;
}
else if(data_len == 0)
{
return ret;
}
//无psram
#ifndef PSRAM_HEAP
if(uvc_msg[1]->uvc_head[1]&BIT(1)){
drop = 2;
}
#endif
if (hgusb20_host_is_crc_err(p_dev, ep)) {
drop = 1;
}
if((uvc_msg[1]->uvc_head[0] != 0x0c)&&(uvc_msg[1]->uvc_head[0] != 0x02)){//head[0] is head len
drop = 1;
}
if(uvc_msg[1]->uvc_head[1] & (BIT(6) | BIT(5))){//error packe
drop = 1;
}
switch(uvc_msg[1]->sta){
case 0: uvc_irq_redy2(uvc_msg[1]);
case 1: ret = uvc_irq_wait_next_frame2(uvc_msg[1]);
if(uvc_msg[1]->sta != 2) break;
case 2: ret = uvc_data_handle2(uvc_msg[1],p_dev,rx_buff,drop); break;
}
return ret;
}
int usb_dma_irq_times= 0;
void usb_dma_irq(void * dev, uint8_t* uvc_rx_buff, uint8_t uvc_head_res, uint8_t ep_type)
{
uint32 ret;
usb_dma_irq_times++;
struct hgusb20_dev *p_dev = (struct hgusb20_dev *)dev;
if (!p_dev)
return;
ret = uvc_data_deal(p_dev);
if(ret == 0){
ret = uvc_deal_mjpeg(p_dev, (uint8_t*)uvc_rx_buff, UVC_EP, ep_type);
}
hgusb20_ep_rx_kick(p_dev, UVC_EP, (uint32)(uvc_rx_buff+uvc_head_res),0x400);
}
//暂时会比较简单去实现,定义都是比较随便,如果可以,jpeg与uvc能统一最好
//mjpeg信号量创建
static struct os_semaphore uvc_sem = {0};
static int uvc_sem_init = 0;
void uvc_sema_init()
{
os_sema_init(&uvc_sem,0);
uvc_sem_init = 1;
}
void uvc_sema_down(int32 tmo_ms)
{
if(!uvc_sem_init)
{
return;
}
os_sema_down(&uvc_sem,tmo_ms);
//printf("$\n");
}
void uvc_sema_up()
{
if(!uvc_sem_init)
{
return;
}
os_sema_up(&uvc_sem);
}
UVC_MANAGE* uvc_message_gloal;
void set_uvc_message_gloal(UVC_MANAGE* uvc_message){
uvc_message_gloal = uvc_message;
}
UVC_MANAGE* get_uvc_message_gloal(){
return uvc_message_gloal;
}
void free_uvc_message_gloal(){
uvc_message_gloal = NULL;
}
uint32 get_uvc_frame_len(){
return uvc_message_gloal->frame_len;
}
UVC_BLANK* get_uvc_blank(){
UVC_BLANK* uvc_b;
if((list_empty(&uvc_message_gloal->list) != TRUE )||(uvc_message_gloal->frame_end == 0)){
uvc_b = list_entry(uvc_message_gloal->list.prev,UVC_BLANK,list);
return uvc_b;
}
return NULL;
}
uint8 free_uvc_blank(UVC_BLANK* uvc_b){
if(uvc_b == NULL) return 0;
free_node2tab(uvc_b,(struct list_head*)&free_uvc_tab,&uvc_message_gloal->list);
return 1;
}
uint8 free_uvc_blank_nopsram(UVC_MANAGE* uvc_message){
UVC_BLANK* uvc_b = NULL;
if((list_empty(&uvc_message->list) != TRUE )||(uvc_message->frame_end == 0)){
uvc_b = list_entry(uvc_message->list.prev,UVC_BLANK,list);
}
if(uvc_b == NULL) return 0;
free_node2tab(uvc_b,(struct list_head*)&free_uvc_tab,&uvc_message->list);
return 1;
}
uint8* get_uvc_buf(){
UVC_BLANK* uvc_b;
uvc_b = get_uvc_blank();
if(uvc_b == NULL)
return NULL;
return uvc_b->buf_ptr;
}
uint8_t uvc_open = 1;
#if 0
UVC_BLANK* uvc_global = NULL;
UVC_MANAGE*uvc_message_global = NULL;
void uvc_stream_open(struct hgusb20_dev *p_dev,uint8 enable);
extern volatile uint8 scale2_finish;
#if DVP_EN
uint8 *psram_uvc_buf[2];
extern uint8 psram_ybuf_src[480*640+480*640/2];
#else
__psram_data uint8 psram_uvc_buf[2][200*1024] __aligned(4);
#endif
#if LCD_EN == 1
void jpg_decode_to_lcd(uint32 photo,uint32 jpg_w,uint32 jpg_h,uint32 video_w,uint32 video_h);
void uvc_user4(void *d)
{
//uint8 msgbuf[10];
//u16* pt;
uint8_t uvc_state = 2;
os_sleep_ms(5);
struct uvc_user_arg *arg = (struct uvc_user_arg*)d;
uint32 tick_num = 0;
UVC_MANAGE* uvc_message;
UVC_BLANK* uvc_b;
struct usb_device *dev = (struct usb_device *)dev_get(HG_USBDEV_DEVID);
struct list_head* get_f;
int del_times = 0;
int err = 0;
uint32 dnum = 0;
uint8* buf = NULL;
int irq_time = 0;
//struct list_head* get_analy_node = NULL;
uint8 pingpang = 0;
#if DVP_EN
psram_uvc_buf[0] = psram_ybuf_src;
psram_uvc_buf[1] = psram_ybuf_src+200*1024;
#endif
//os_sleep_ms(6000);
while(1){
get_f = get_uvc_frame();
if(get_f == 0)
{
//state=2,代表有通知需要删除任务
if(arg->state == 2)
{
err = 1;
goto uvc_user4_exit;
}
if(uvc_open==1){
if(uvc_state != uvc_open){
uvc_stream_open((struct hgusb20_dev *)dev,1);
uvc_state = uvc_open;
}
}
//释放cpu
os_sleep_ms(1);
continue;
}
if(uvc_open==0){
if(uvc_state != uvc_open){
uvc_stream_open((struct hgusb20_dev *)dev,0);
uvc_state = uvc_open;
}
}
err = 0;
irq_time = 0;
tick_num++;
uvc_message = list_entry(get_f,UVC_MANAGE,list);
set_uvc_frame_using(uvc_message);
uvc_message_global = uvc_message;
while((list_empty(&uvc_message->list) != TRUE )||(uvc_message->frame_end == 0)){
if(uvc_open==0)
break;
irq_disable(USB20DMA_IRQn);
uvc_b = list_entry(uvc_message->list.prev,UVC_BLANK,list);
if(uvc_message->frame_end == 2){
break;
}
irq_enable(USB20DMA_IRQn);
//if(arg->state == 2)
//{
// err = 1;
// goto uvc_user4_exit;
//}
if(uvc_message->state != 3)
_os_printf("state_err\r\n");
uvc_global = uvc_b;
if(uvc_b && uvc_b->busy == 2)
{
//数据头,所以要申请一帧数据
if(uvc_b->blank_loop == 0)
{
//正常不可能进来这里的
//获取下一帧
//u = f_get_uvc_frame_current_task();
//get_analy_node = get_app_analyze_node(&uvc_app_analyze);
//if(get_analy_node)
// buf = get_real_buf_adr(get_analy_node);
//else
// buf = NULL;
if(pingpang == 0){
buf = psram_uvc_buf[0];
//pingpang = 1;
}else{
buf = psram_uvc_buf[1];
//pingpang = 0;
}
}
//没有帧,那么只能将bank删除,应该是rtsp处理速度不够
if(1)//(get_analy_node)
{
#if 0
if(uvc_b->buf_ptr[0] == 0xFF && uvc_b->buf_ptr[1] == 0xD8 && uvc_b->blank_loop != 0)
{
//printf("loop:%d\t%X\n",uvc_b->blank_loop,get_f);
}
#endif
hw_memcpy0(buf,uvc_b->buf_ptr,uvc_b->blank_len);
buf += uvc_b->blank_len;
}
else
{
_os_printf("=");
}
free_node2tab(uvc_b,(struct list_head*)&free_uvc_tab,&uvc_message->list);
}
else
{
//释放cpu
os_sleep_ms(1);
irq_time++;
if(irq_time>200)
{
irq_time = 0;
if(!usb_dma_irq_times)
{
//err = 1;
_os_printf("%s usb maybe disconnect\n",__FUNCTION__);
uvc_message->frame_end = 2;
uvc_message->sta = 0;
int32 usb_host_uvc_ioctl(struct usb_device *p_usb_d, uint32 cmd, uint32 param1, uint32 param2);
usb_host_uvc_ioctl(dev, USB_HOST_IO_CMD_RESET,0,0);
break;
}
usb_dma_irq_times = 0;
}
}
//continue;
}
if(err)
{
#if 0
if(get_analy_node)
{
//f_del_uvc_frame(u);
free_real_msg(get_analy_node,&uvc_app_analyze.free_list);
get_analy_node = NULL;
}
continue;
#endif
goto uvc_user4_exit;
}
//异常退出,对应frame也del
if(uvc_message->frame_end == 2)
{
//printf("get_F:%x\r\n",get_f);
free_get_uvc_node_list(get_f,&free_uvc_tab[0]);
del_uvc_frame(uvc_message);
//if(get_analy_node)
//{
//f_del_uvc_frame(u);
// free_real_msg(get_analy_node,&uvc_app_analyze.free_list);
// get_analy_node = NULL;
//}
}
//正常退出
else
{
//设置状态,等于发送frame
// if(get_analy_node)
{
//关闭usb中断,打印对应的数据出来
//u->frame_len = uvc_message->frame_len;
// set_app_buf_len(get_analy_node,uvc_message->frame_len);
#if 1
//f_set_uvc_frame_status(u);
#else
f_set_uvc_frame_status(u);
f_del_uvc_frame(u);
#endif
//printf("frame_len:%d\n",uvc_message->frame_len);
del_times++;
// map_realnode_2_app_node_msg(&uvc_app_analyze,get_analy_node);
if(uvc_open==1){
if(scale2_finish){
scale2_finish = 0;
if(pingpang == 0){
jpg_decode_to_lcd((uint32)psram_uvc_buf[0],1280,720,160,120);
pingpang = 1;
}else{
jpg_decode_to_lcd((uint32)psram_uvc_buf[1],1280,720,160,120);
pingpang = 0;
}
dnum = 0;
}else{
dnum++;
if(dnum > 8){
scale2_finish = 1;
}
}
}
_os_printf("M");
// wake_up_analyze_list_app(&uvc_app_analyze);
// get_analy_node = NULL;
// uvc_sema_up();
}
//printf("del frame:%x %d %d\r\n",uvc_message,uvc_message->frame_len);
//printf("=");
//printf("?");
del_uvc_frame(uvc_message);
}
}
uvc_user4_exit:
if(err)
{
// if(get_analy_node)
{
//f_del_uvc_frame(u);
// free_real_msg(get_analy_node,&uvc_app_analyze.free_list);
// get_analy_node = NULL;
}
_os_printf("%s exit\n",__FUNCTION__);
//代表任务已经被删除,可以重新启动
arg->state = 0;
return;
}
}
#endif
#endif
#if 0
void uvc_user()
{
UVC_MANAGE* uvc_message;
UVC_BLANK* uvc_b;
// uint32 len = 0;
// uint32 itk = 0;
// uint8 printf_uvc_jpg = 0;
// struct list_head *uvc_bk;
struct list_head* get_f;
while(1){
get_f = get_uvc_frame();
if(get_f == 0)
{
//释放cpu
os_sleep_ms(1);
continue;
}
uvc_message = list_entry(get_f,UVC_MANAGE,list);
set_uvc_frame_using(uvc_message);
set_uvc_message_gloal(uvc_message);
uvc_sema_down(-1);
while((list_empty(&uvc_message->list) != TRUE )||(uvc_message->frame_end == 0)){
uvc_b = list_entry(uvc_message->list.prev,UVC_BLANK,list);
if(uvc_b->busy == 2)
{
free_node2tab(uvc_b,(struct list_head*)&free_uvc_tab,&uvc_message->list);
}
}
//printf("del frame:%x %d %d\r\n",uvc_message,uvc_message->frame_len,len);
free_uvc_message_gloal();
del_uvc_frame(uvc_message);
}
}
#endif
#endif