UVC host library
Dependents: LifeCam WebcamServer
uvc/uvcini.cpp
- Committer:
- va009039
- Date:
- 2012-08-15
- Revision:
- 3:3eb41d749f9a
- Parent:
- 2:812d604caad4
File content as of revision 3:3eb41d749f9a:
#include "mbed.h" #include "uvc.h" #define __DEBUG #include "mydbg.h" #include "stcamcfg.h" #define UNDEF_VAL (0) const struct stcamcfg stcamcfg_table[] = { /* {0x045e, 0x074a, "Microsoft LifeCam VX-700", 160,120, PAYLOAD_MJPEG, 0x81, 128, 1, 5, 2000000, // 160x120 5.0fps 1, 1, 8, 3, },*/ /* {0x0c45, 0x62c0, "UVCA130AF", 160,120, PAYLOAD_MJPEG, 0x81, 128, 1, 5, 2000000, // 160x120 5.0fps 1, 1, 8, 3, },*/ {0x046d, 0x0994, "Logitech QuickCam Orbit AF", 160,120, PAYLOAD_MJPEG, UNDEF_VAL, UNDEF_VAL, UNDEF_VAL, UNDEF_VAL, 2000000, // 160x120 10.0fps UNDEF_VAL, UNDEF_VAL, UNDEF_VAL, 3, }, {0x0000, 0x0000, "default", 160,120, PAYLOAD_MJPEG, UNDEF_VAL, UNDEF_VAL, UNDEF_VAL, UNDEF_VAL, 2000000, UNDEF_VAL, UNDEF_VAL, UNDEF_VAL, 3, }, }; inline void LE32(uint32_t n, uint8_t* d) { d[0] = (uint8_t)n; d[1] = (uint8_t)(n >> 8); d[2] = (uint8_t)(n >> 16); d[3] = (uint8_t)(n >> 24); } void uvc::SetFormatIndex(int index) { DBG_ASSERT(index >= 1); DBG_ASSERT(index <= 2); m_FormatIndex = index; } void uvc::SetFrameIndex(int index) { DBG_ASSERT(index >= 1); DBG_ASSERT(index <= 8); m_FrameIndex = index; } void uvc::SetFrameInterval(int val) { DBG_ASSERT(val >= 333333); DBG_ASSERT(val <= 10000000); m_FrameInterval = val; } void uvc::SetPacketSize(int size) { DBG_ASSERT(size >= 128); DBG_ASSERT(size <= 1024); m_PacketSize = size; } void uvc::SetImageSize(int width, int height) { DBG_ASSERT(width >= 160); DBG_ASSERT(width <= 800); DBG_ASSERT(height >= 120); DBG_ASSERT(height <= 600); m_width = width; m_height = height; } void uvc::SetPayload(int payload) { DBG_ASSERT(payload == PAYLOAD_MJPEG || payload == PAYLOAD_YUY2); m_payload = payload; } void uvc::poll() { isochronous(); } int uvc::_init() { m_init = true; UsbErr rc; for(int i = 0; i < 2; i++) { m_pDev = m_pHost->getDeviceByClass(CLASS_VIDEO, m_cam); // UVC if (m_pDev || i > 0) { break; } rc = Usb_poll(); if (rc == USBERR_PROCESSING) { VERBOSE("%p USBERR_PROCESSING\n", this); return -1; } } DBG("m_pDev=%p\n", m_pDev); if (!m_pDev) { VERBOSE("%p UVC CAMERA(%d) NOT FOUND\n", this, m_cam); return -1; } DBG_ASSERT(m_pDev); struct stcamcfg cfg; for(int i = 0; ; i++) { cfg = stcamcfg_table[i]; if (cfg.idVender == 0x0000) { DBG("not cam config\n"); DBG("vid: %04X\n", m_pDev->getVid()); DBG("pid: %04X\n", m_pDev->getPid()); break; } if (cfg.idVender == m_pDev->getVid() && cfg.idProduct == m_pDev->getPid()) { DBG_ASSERT(cfg.name); DBG("found %s\n", cfg.name); break; } } if (m_width) { cfg.width = m_width; } if (m_height) { cfg.height = m_height; } if (m_payload != PAYLOAD_UNDEF) { cfg.payload = m_payload; } if (m_FormatIndex) { cfg.FormatIndex = m_FormatIndex; } if (m_FrameIndex) { cfg.FrameIndex = m_FrameIndex; } if (m_FrameInterval) { cfg.dwFrameInterval = m_FrameInterval; } if (m_PacketSize) { cfg.wMaxPacketSize = m_PacketSize; } _config(&cfg); if (cfg.FormatIndex == UNDEF_VAL) { if (cfg.payload == PAYLOAD_MJPEG) { VERBOSE("MJPG(Motion JPEG) FORMAT NOT FOUND\n"); } else if (cfg.payload == PAYLOAD_YUY2) { VERBOSE("YUY2 FORMAT NOT FOUND\n"); } else { VERBOSE("??? FORMAT NOT FOUND\n"); } return -1; } if (cfg.bInterface == UNDEF_VAL) { VERBOSE("PacketSize(%d) CONFIG ERROR\n", cfg.wMaxPacketSize); return -1; } if (cfg.iso_FrameCount == 0) { int c = usb_bp_size() / cfg.wMaxPacketSize; if (c > 8) { c = 8; } cfg.iso_FrameCount = c; } DBG_ASSERT(cfg.iso_FrameCount >= 1); DBG_ASSERT(cfg.iso_FrameCount <= 8); DBG_ASSERT((cfg.iso_FrameCount * cfg.wMaxPacketSize) <= usb_bp_size()); if (cfg.iso_itdCount == 0) { cfg.iso_itdCount = 3; } DBG_ASSERT(cfg.iso_itdCount >= 1); DBG("cfg.wMaxPacketSize=%d\n", cfg.wMaxPacketSize); DBG("cfg.iso_FrameCount=%d\n", cfg.iso_FrameCount); DBG("cfg.iso_itdCount=%d\n", cfg.iso_itdCount); DBG_ASSERT(cfg.iso_FrameCount >= 1 && cfg.iso_FrameCount <= 8); //m_pEpIntIn = new UsbEndpoint(m_pDev, 0x83, true, USB_INT, 16); //DBG_ASSERT(m_pEpIntIn); DBG_ASSERT(cfg.bEndpointAddress & 0x80); DBG_ASSERT(cfg.wMaxPacketSize >= 128); DBG_ASSERT(cfg.wMaxPacketSize <= 1020); m_PacketSize = cfg.wMaxPacketSize; DBG_ASSERT(m_PacketSize); m_pEpIsoIn = new UsbEndpoint(m_pDev, cfg.bEndpointAddress, true, USB_ISO, m_PacketSize); DBG_ASSERT(m_pEpIsoIn); DBG_ASSERT(cfg.FormatIndex >= 1); DBG_ASSERT(cfg.FormatIndex <= 2); DBG_ASSERT(cfg.FrameIndex >= 1); DBG_ASSERT(cfg.FrameIndex <= 12); DBG_ASSERT(cfg.dwFrameInterval <= 10000000); DBG_ASSERT(cfg.dwFrameInterval >= 333333); probe_commit_control(&cfg); DBG("cfg.bInterface = %d, cfg.bAlternate = %d\n", cfg.bInterface, cfg.bAlternate); //USBH_SET_INTERFACE(1, 1); // alt=1 size=128 DBG_ASSERT(cfg.bInterface >= 1); DBG_ASSERT(cfg.bAlternate >= 1); DBG_ASSERT(cfg.bAlternate <= 7); rc = m_pDev->SetInterfaceAlternate(cfg.bInterface, cfg.bAlternate); DBG_ASSERT(rc == USBERR_OK); DBG_ASSERT(cfg.iso_FrameCount >= 1); DBG_ASSERT(cfg.iso_FrameCount <= 8); m_FrameCount = cfg.iso_FrameCount; DBG_ASSERT(cfg.iso_itdCount >= 1); DBG_ASSERT(cfg.iso_itdCount <= 8); m_itdCount = cfg.iso_itdCount; LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable LPC_USB->HcControl |= OR_CONTROL_IE; // IsochronousEnable m_connect = true; return 0; } static void dump_param(uint8_t* buf) { VERBOSE("Hint: %04x\n", LE16(buf+0)); VERBOSE("FormatIndex: %d\n", buf[2]); VERBOSE("FrameIndex: %d\n", buf[3]); VERBOSE("FrameInterval: %d\n", LE32(buf+4)); VERBOSE("KeyFrameRate: %d\n", LE16(buf+8)); VERBOSE("PFrameRate: %d\n", LE16(buf+10)); VERBOSE("CompQuality: %d\n", LE16(buf+12)); VERBOSE("CompWindowSize: %d\n", LE16(buf+14)); VERBOSE("Delay: %d\n", LE16(buf+16)); VERBOSE("MaxVideoFrameSize: %d\n", LE32(buf+18)); VERBOSE("MaxPayloadTransferSize: %d\n", LE32(buf+22)); } void uvc::probe_commit_control(struct stcamcfg* cfg) { DBG_ASSERT(cfg); uint8_t param[34]; uint8_t temp[34]; int param_len = 34; DBG_ASSERT(cfg->bcdUVC >= 0x0100); if (cfg->bcdUVC == 0x0100) { // UVC ver. 1.0 param_len = 26; } UsbErr rc; rc = Control(GET_INFO, VS_PROBE_CONTROL, 1, param, 1); DBG_ASSERT(rc == USBERR_OK); DBG_BYTES("GET_INFO Probe ", param, 1); rc = Control(GET_DEF, VS_PROBE_CONTROL, 1, temp, param_len); DBG_ASSERT(rc == USBERR_OK); DBG_BYTES("GET_DEF Probe ", temp, param_len); dump_param(temp); rc = Control(GET_MIN, VS_PROBE_CONTROL, 1, temp, param_len); DBG_ASSERT(rc == USBERR_OK); DBG_BYTES("GET_MIN Probe ", temp, param_len); dump_param(temp); rc = Control(GET_MAX, VS_PROBE_CONTROL, 1, temp, param_len); DBG_ASSERT(rc == USBERR_OK); DBG_BYTES("GET_MAX Probe ", temp, param_len); dump_param(temp); rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, temp, param_len); DBG_ASSERT(rc == USBERR_OK); DBG_BYTES("GET_CUR Probe ", temp, param_len); dump_param(temp); memset(param, 0x00, param_len); param[2] = cfg->FormatIndex; param[3] = cfg->FrameIndex; // 160x120 LE32(cfg->dwFrameInterval, param+4); // Frame Interval DBG_BYTES("SET_CUR Probe ", param, param_len); rc = Control(SET_CUR, VS_PROBE_CONTROL, 1, param, param_len); DBG_ASSERT(rc == USBERR_OK); rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, temp, param_len); DBG_ASSERT(rc == USBERR_OK); DBG_BYTES("GET_CUR Probe ", temp, param_len); rc = Control(GET_INFO, VS_COMMIT_CONTROL, 1, temp, param_len); DBG_ASSERT(rc == USBERR_OK); DBG_BYTES("GET_INFO Commit", temp, 1); rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, temp, param_len); DBG_ASSERT(rc == USBERR_OK); DBG_BYTES("GET_CUR Commit", temp, param_len); dump_param(temp); DBG_BYTES("SET_CUR Commit", param, param_len); dump_param(param); rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, param, param_len); if (rc != USBERR_OK) { VERBOSE("Error SET_CUR VS_COMMIT_CONTROL\n"); } DBG_ASSERT(rc == USBERR_OK); rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, temp, param_len); DBG_ASSERT(rc == USBERR_OK); DBG_BYTES("GET_CUR Commit", temp, param_len); dump_param(temp); }