android 枚举成uvc设备,UVC摄像头枚举过程分析——D881HD720P

#include "app_cfg.h"

#include "app_type.h"

#include "interfaces.h"

#include "tool/buffer/buffer.h"

#include "stack/usb/core/vsfusbh.h"

#include "stack/usb/class/host/UVC/vsfusbh_UVC.h"

#define UVC_PROBE_CRTL_DATA_SIZE 36

enum uav_evt_t

{

UAV_RESET_STREAM_PARAM = VSFSM_EVT_USER_LOCAL + 1,

UAV_ISO_ENABLE,

UAV_ISO_DISABLE,

};

enum uav_request_t

{

RC_UNDEFINED = 0x00,

SET_CUR = 0x01,

GET_CUR = 0x81,

GET_MIN = 0x82,

GET_MAX = 0x83,

GET_RES = 0x84,

GET_LEN = 0x85,

GET_INFO = 0x86,

GET_DEF = 0x87,

};

struct vsfusbh_uvc_t

{

struct vsfusbh_t *usbh;

struct vsfusbh_device_t *dev;

struct vsfsm_t init_sm;

struct vsfsm_pt_t init_pt;

struct vsfsm_t ctrl_sm;

struct vsfsm_pt_t ctrl_pt;

struct vsfsm_t video_sm;

//struct vsfsm_t audio_sm;

struct vsfusbh_urb_t ctrl_urb;

struct vsfusbh_urb_t video_urb;

//struct vsfusbh_urb_t audio_urb;

uint8_t *ctrl_urb_buf;

uint8_t *video_urb_buf;

//uint8_t *audio_urb_buf;

struct vsfusbh_uvc_payload_t video_payload;

//struct vsfusbh_uvc_payload_t audio_payload;

struct vsfusbh_uvc_param_t set_param;

struct vsfusbh_uvc_param_t cur_param;

uint16_t video_iso_packet_len;

//uint16_t audio_iso_packet_len;

uint8_t video_iso_ep;

//uint8_t audio_iso_ep;

};

void (*vsfusbh_uvc_report)(void *dev_data, struct vsfusbh_uvc_param_t *param,

struct vsfusbh_uvc_payload_t *payload) = NULL;

static vsf_err_t uvc_init_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)

{

vsf_err_t err;

struct vsfusbh_uvc_t *hdata = (struct vsfusbh_uvc_t *)pt->user_data;

struct vsfusbh_urb_t *vsfurb = &hdata->ctrl_urb;

vsfsm_pt_begin(pt);

// reset interfaces 1 (video)

vsfurb->transfer_buffer = NULL;

vsfurb->transfer_length = 0;

err = vsfusbh_set_interface(hdata->usbh, vsfurb, 1, 0);

if (err != VSFERR_NONE)

return err;

vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);

if (vsfurb->status != URB_OK)

return VSFERR_FAIL;

vsfsm_pt_end(pt);

return VSFERR_NONE;

}

static struct vsfsm_state_t *uvc_evt_handler_init(struct vsfsm_t *sm,

vsfsm_evt_t evt)

{

vsf_err_t err;

struct vsfusbh_uvc_t *hdata = (struct vsfusbh_uvc_t *)sm->user_data;

switch (evt)

{

case VSFSM_EVT_INIT:

case VSFSM_EVT_URB_COMPLETE:

case VSFSM_EVT_DELAY_DONE:

err = hdata->init_pt.thread(&hdata->init_pt, evt);

if (err < 0)

{

// TODO

}

else if (err == 0)

{

hdata->ctrl_urb.sm = &hdata->ctrl_sm;

if (vsfusbh_uvc_report)

vsfusbh_uvc_report(hdata, &hdata->cur_param, NULL);

}

break;

default:

break;

}

return NULL;

}

const uint8_t negotiate_temp[26] =

{

0x00, 0x00, 0x01, 0x03, 0x15, 0x16, 0x05, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00

};

static vsf_err_t uvc_ctrl_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt)

{

vsf_err_t err;

struct vsfusbh_uvc_t *hdata = (struct vsfusbh_uvc_t *)pt->user_data;

struct vsfusbh_urb_t *vsfurb = &hdata->ctrl_urb;

vsfsm_pt_begin(pt);

if (hdata->set_param.video_enable)

{

// negotiate

hdata->video_iso_packet_len = 1024;

hdata->video_iso_ep = 1;

// commit param

vsfurb->transfer_buffer = hdata->ctrl_urb_buf;

memcpy(vsfurb->transfer_buffer, negotiate_temp, 26);

vsfurb->transfer_length = 26;

vsfurb->pipe = usb_sndctrlpipe(vsfurb->vsfdev, 0);

err =  vsfusbh_control_msg(hdata->usbh, vsfurb,

USB_TYPE_CLASS |USB_RECIP_INTERFACE | USB_DIR_OUT, SET_CUR,

0x0200, 0x0001);

if (err != VSFERR_NONE)

return err;

vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);

if (vsfurb->status != URB_OK)

return VSFERR_FAIL;

// set interfaces

vsfurb->transfer_buffer = NULL;

vsfurb->transfer_length = 0;

err = vsfusbh_set_interface(hdata->usbh, vsfurb, 1, 4);

if (err != VSFERR_NONE)

return err;

vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);

if (vsfurb->status != URB_OK)

return VSFERR_FAIL;

// enable video

vsfsm_post_evt_pending(&hdata->video_sm, UAV_ISO_ENABLE);

}

else

{

vsfurb->transfer_buffer = NULL;

vsfurb->transfer_length = 0;

err = vsfusbh_set_interface(hdata->usbh, vsfurb, 1, 0);

if (err != VSFERR_NONE)

return err;

vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE);

if (vsfurb->status != URB_OK)

return VSFERR_FAIL;

}

vsf_bufmgr_free(hdata->ctrl_urb_buf);

hdata->ctrl_urb_buf = NULL;

memcpy(&hdata->cur_param, &hdata->set_param,

sizeof(struct vsfusbh_uvc_param_t));

vsfusbh_uvc_report(hdata, &hdata->cur_param, NULL);

vsfsm_pt_end(pt);

return VSFERR_NONE;

}

static struct vsfsm_state_t *uvc_evt_handler_ctrl(struct vsfsm_t *sm,

vsfsm_evt_t evt)

{

vsf_err_t err;

struct vsfusbh_uvc_t *hdata = (struct vsfusbh_uvc_t *)sm->user_data;

switch (evt)

{

case VSFSM_EVT_INIT:

break;

case UAV_RESET_STREAM_PARAM:

hdata->ctrl_pt.state = 0;

if (hdata->ctrl_urb_buf == NULL)

{

hdata->ctrl_urb_buf = vsf_bufmgr_malloc(UVC_PROBE_CRTL_DATA_SIZE);

if (hdata->ctrl_urb_buf == NULL)

return NULL;

}

case VSFSM_EVT_URB_COMPLETE:

case VSFSM_EVT_DELAY_DONE:

err = hdata->ctrl_pt.thread(&hdata->ctrl_pt, evt);

if (err < 0)

{

// TODO

vsf_bufmgr_free(hdata->ctrl_urb_buf);

hdata->ctrl_urb_buf = NULL;

}

else if (err == 0)

{

vsf_bufmgr_free(hdata->ctrl_urb_buf);

hdata->ctrl_urb_buf = NULL;

}

break;

default:

break;

}

return NULL;

}

static struct vsfsm_state_t *uvc_evt_handler_video(struct vsfsm_t *sm,

vsfsm_evt_t evt)

{

vsf_err_t err;

struct vsfusbh_uvc_t *hdata = (struct vsfusbh_uvc_t *)sm->user_data;

struct vsfusbh_t *usbh = hdata->usbh;

struct vsfusbh_urb_t *vsfurb = &hdata->video_urb;

switch (evt)

{

case VSFSM_EVT_INIT:

break;

case UAV_ISO_ENABLE:

if (hdata->video_urb_buf == NULL)

{

vsfurb->vsfdev->epmaxpacketin[hdata->video_iso_ep] = hdata->video_iso_packet_len;

hdata->video_urb_buf = vsf_bufmgr_malloc(hdata->video_iso_packet_len);

if (hdata->video_urb_buf == NULL)

return NULL;

vsfurb->transfer_buffer = hdata->video_urb_buf;

vsfurb->transfer_length = hdata->video_iso_packet_len;

vsfurb->pipe = usb_rcvisocpipe(vsfurb->vsfdev, hdata->video_iso_ep);

vsfurb->transfer_flags |= USB_ISO_ASAP;

vsfurb->number_of_packets = 1;

vsfurb->iso_frame_desc[0].offset = 0;

vsfurb->iso_frame_desc[0].length = hdata->video_iso_packet_len;

err = vsfusbh_submit_urb(usbh, vsfurb);

if (err != VSFERR_NONE)

goto error;

}

break;

case UAV_ISO_DISABLE:

// TODO

break;

case VSFSM_EVT_URB_COMPLETE:

if (vsfurb->status == URB_OK)

{

hdata->video_payload.len = vsfurb->actual_length;

vsfusbh_uvc_report(hdata, &hdata->cur_param, &hdata->video_payload);

}

else

{

goto error;

}

err = vsfusbh_relink_urb(usbh, vsfurb);

if (err != VSFERR_NONE)

goto error;

break;

default:

break;

}

return NULL;

error:

vsf_bufmgr_free(hdata->video_urb_buf);

hdata->video_urb_buf = NULL;

return NULL;

}

static void *vsfusbh_uvc_init(struct vsfusbh_t *usbh, struct vsfusbh_device_t *dev)

{

struct vsfusbh_class_data_t *cdata;

struct vsfusbh_uvc_t *hdata;

cdata = vsf_bufmgr_malloc(sizeof(struct vsfusbh_class_data_t));

if (NULL == cdata)

return NULL;

hdata = vsf_bufmgr_malloc(sizeof(struct vsfusbh_uvc_t));

if (NULL == hdata)

{

vsf_bufmgr_free(cdata);

return NULL;

}

memset(cdata, 0, sizeof(struct vsfusbh_class_data_t));

memset(hdata, 0, sizeof(struct vsfusbh_uvc_t));

cdata->dev = dev;

hdata->dev = dev;

hdata->usbh = usbh;

cdata->param = hdata;

hdata->video_payload.type = VSFUSBH_UVC_PAYLOAD_VIDEO;

hdata->video_payload.buf = hdata->video_urb_buf;

hdata->init_sm.init_state.evt_handler = uvc_evt_handler_init;

hdata->init_sm.user_data = (void*)hdata;

hdata->init_pt.thread = uvc_init_thread;

hdata->init_pt.user_data = hdata;

hdata->init_pt.sm = &hdata->init_sm;

hdata->init_pt.state = 0;

hdata->ctrl_sm.init_state.evt_handler = uvc_evt_handler_ctrl;

hdata->ctrl_sm.user_data = (void*)hdata;

hdata->ctrl_pt.thread = uvc_ctrl_thread;

hdata->ctrl_pt.user_data = hdata;

hdata->ctrl_pt.sm = &hdata->ctrl_sm;

hdata->ctrl_pt.state = 0;

hdata->ctrl_urb.vsfdev = dev;

hdata->ctrl_urb.timeout = 200;

hdata->ctrl_urb.sm = &hdata->init_sm;

hdata->video_sm.init_state.evt_handler = uvc_evt_handler_video;

hdata->video_sm.user_data = (void*)hdata;

hdata->video_urb.vsfdev = dev;

hdata->video_urb.timeout = 200;

hdata->video_urb.sm = &hdata->video_sm;

vsfsm_init(&hdata->init_sm);

vsfsm_init(&hdata->ctrl_sm);

vsfsm_init(&hdata->video_sm);

return cdata;

}

static vsf_err_t vsfusbh_uvc_match(struct vsfusbh_device_t *dev)

{

if ((dev->descriptor.idVendor == 0x04f2) &&

(dev->descriptor.idProduct == 0xb130))

{

return VSFERR_NONE;

}

return VSFERR_FAIL;

}

static void vsfusbh_uvc_free(struct vsfusbh_device_t *dev)

{

struct vsfusbh_class_data_t *cdata = (struct vsfusbh_class_data_t *)(dev->priv);

struct vsfusbh_uvc_t *hdata = (struct vsfusbh_uvc_t *)cdata->param;

// TODO

// free urb

vsf_bufmgr_free(hdata);

vsf_bufmgr_free(cdata);

}

const struct vsfusbh_class_drv_t vsfusbh_uvc_drv = {

vsfusbh_uvc_init,

vsfusbh_uvc_free,

vsfusbh_uvc_match,

};

vsf_err_t vsfusbh_uvc_set(void *dev_data, struct vsfusbh_uvc_param_t *param)

{

struct vsfusbh_uvc_t *hdata = (struct vsfusbh_uvc_t *)dev_data;

hdata->set_param = *param;

vsfsm_post_evt_pending(&hdata->ctrl_sm, UAV_RESET_STREAM_PARAM);

return VSFERR_NONE;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值