UVC host library

Dependents:   LifeCam WebcamServer

Committer:
va009039
Date:
Wed Aug 15 13:52:53 2012 +0000
Revision:
3:3eb41d749f9a
Parent:
0:b0f04c137829
add USB_USE_MALLOC

Who changed what in which revision?

UserRevisionLine numberNew contents of line
va009039 0:b0f04c137829 1 #include "mbed.h"
va009039 0:b0f04c137829 2 #include "uvc.h"
va009039 0:b0f04c137829 3
va009039 0:b0f04c137829 4 //#define __DEBUG
va009039 0:b0f04c137829 5 //#define __DEBUG3
va009039 0:b0f04c137829 6 #include "mydbg.h"
va009039 0:b0f04c137829 7 #include "usb_itd.h"
va009039 0:b0f04c137829 8
va009039 0:b0f04c137829 9 uvc::uvc(int cam)
va009039 0:b0f04c137829 10 {
va009039 0:b0f04c137829 11 DBG("cam=%d\n", cam);
va009039 0:b0f04c137829 12 DBG_ASSERT(cam >= 0);
va009039 0:b0f04c137829 13 m_cam = cam;
va009039 0:b0f04c137829 14 m_init = false;
va009039 0:b0f04c137829 15 m_connect = false;
va009039 0:b0f04c137829 16 m_int_seq = 0;
va009039 0:b0f04c137829 17 m_iso_seq = 0;
va009039 0:b0f04c137829 18 m_width = 0;
va009039 0:b0f04c137829 19 m_height = 0;
va009039 0:b0f04c137829 20 m_payload = PAYLOAD_MJPEG;
va009039 0:b0f04c137829 21 m_FormatIndex = 0;
va009039 0:b0f04c137829 22 m_FrameIndex = 0;
va009039 0:b0f04c137829 23 m_FrameInterval = 0;
va009039 0:b0f04c137829 24 m_PacketSize = 0;
va009039 0:b0f04c137829 25 m_stream = NULL;
va009039 0:b0f04c137829 26 for(int i = 0; i <= 15; i++) {
va009039 0:b0f04c137829 27 ReportConditionCode[i] = 0;
va009039 0:b0f04c137829 28 }
va009039 0:b0f04c137829 29 clearOnResult();
va009039 0:b0f04c137829 30 }
va009039 0:b0f04c137829 31
va009039 0:b0f04c137829 32 uvc::~uvc()
va009039 0:b0f04c137829 33 {
va009039 0:b0f04c137829 34 clearOnResult();
va009039 0:b0f04c137829 35 }
va009039 0:b0f04c137829 36
va009039 0:b0f04c137829 37 int uvc::setup()
va009039 0:b0f04c137829 38 {
va009039 0:b0f04c137829 39 if (!m_init) {
va009039 0:b0f04c137829 40 return _init();
va009039 0:b0f04c137829 41 }
va009039 0:b0f04c137829 42 return 0;
va009039 0:b0f04c137829 43 }
va009039 0:b0f04c137829 44
va009039 0:b0f04c137829 45 int uvc::get_jpeg(const char* path)
va009039 0:b0f04c137829 46 {
va009039 0:b0f04c137829 47 const int size = 4800;
va009039 0:b0f04c137829 48 const int timeout = 5000;
va009039 0:b0f04c137829 49 uint8_t* buf = new uint8_t[size];
va009039 0:b0f04c137829 50 DBG_ASSERT(buf);
va009039 0:b0f04c137829 51 if (buf == NULL) {
va009039 0:b0f04c137829 52 return -1;
va009039 0:b0f04c137829 53 }
va009039 0:b0f04c137829 54 usb_mjpeg mjpeg(buf, size);
va009039 0:b0f04c137829 55 attach(&mjpeg);
va009039 0:b0f04c137829 56 Timer t;
va009039 0:b0f04c137829 57 t.reset();
va009039 0:b0f04c137829 58 t.start();
va009039 0:b0f04c137829 59 while(t.read_ms() < timeout) {
va009039 0:b0f04c137829 60 int stat = isochronous();
va009039 0:b0f04c137829 61 if (mjpeg.status() >= 0) {
va009039 0:b0f04c137829 62 break;
va009039 0:b0f04c137829 63 }
va009039 0:b0f04c137829 64 }
va009039 0:b0f04c137829 65 detach();
va009039 0:b0f04c137829 66 int len = mjpeg.status();
va009039 0:b0f04c137829 67 if (len >= 0) {
va009039 0:b0f04c137829 68 if (path != NULL) {
va009039 0:b0f04c137829 69 FILE *fp = fopen(path, "wb");
va009039 0:b0f04c137829 70 if (fp != NULL) {
va009039 0:b0f04c137829 71 for(int i = 0; i < len; i++) {
va009039 0:b0f04c137829 72 fputc(buf[i], fp);
va009039 0:b0f04c137829 73 }
va009039 0:b0f04c137829 74 fclose(fp);
va009039 0:b0f04c137829 75 }
va009039 0:b0f04c137829 76 }
va009039 0:b0f04c137829 77 }
va009039 0:b0f04c137829 78 delete[] buf;
va009039 0:b0f04c137829 79 return len;
va009039 0:b0f04c137829 80 }
va009039 0:b0f04c137829 81
va009039 0:b0f04c137829 82 int uvc::get_jpeg(uint8_t* buf, int size)
va009039 0:b0f04c137829 83 {
va009039 0:b0f04c137829 84 //DBG("buf=%p size=%d\n", buf, size);
va009039 0:b0f04c137829 85 const int timeout = 5000;
va009039 0:b0f04c137829 86 usb_mjpeg mjpeg(buf, size);
va009039 0:b0f04c137829 87 attach(&mjpeg);
va009039 0:b0f04c137829 88 Timer t;
va009039 0:b0f04c137829 89 t.reset();
va009039 0:b0f04c137829 90 t.start();
va009039 0:b0f04c137829 91 while(t.read_ms() < timeout) {
va009039 0:b0f04c137829 92 int stat = isochronous();
va009039 0:b0f04c137829 93 if (mjpeg.status() >= 0) {
va009039 0:b0f04c137829 94 break;
va009039 0:b0f04c137829 95 }
va009039 0:b0f04c137829 96 }
va009039 0:b0f04c137829 97 detach();
va009039 0:b0f04c137829 98 int len = mjpeg.status();
va009039 0:b0f04c137829 99 return len;
va009039 0:b0f04c137829 100 }
va009039 0:b0f04c137829 101
va009039 0:b0f04c137829 102 bool uvc::interrupt()
va009039 0:b0f04c137829 103 {
va009039 0:b0f04c137829 104 if (!m_init) {
va009039 0:b0f04c137829 105 _init();
va009039 0:b0f04c137829 106 }
va009039 0:b0f04c137829 107 if (m_int_seq == 0) {
va009039 0:b0f04c137829 108 int rc = m_pEpIntIn->transfer(m_int_buf, sizeof(m_int_buf));
va009039 0:b0f04c137829 109 if (rc != USBERR_PROCESSING) {
va009039 0:b0f04c137829 110 return false;
va009039 0:b0f04c137829 111 }
va009039 0:b0f04c137829 112 m_int_seq++;
va009039 0:b0f04c137829 113 }
va009039 0:b0f04c137829 114 int len = m_pEpIntIn->status();
va009039 0:b0f04c137829 115 if (len > 0) {
va009039 0:b0f04c137829 116 m_int_seq = 0;
va009039 0:b0f04c137829 117 DBG_BYTES("interrupt", m_int_buf, len);
va009039 0:b0f04c137829 118 return true;
va009039 0:b0f04c137829 119 }
va009039 0:b0f04c137829 120 return false;
va009039 0:b0f04c137829 121 }
va009039 0:b0f04c137829 122
va009039 0:b0f04c137829 123 #define CC_NOERROR 0x0
va009039 0:b0f04c137829 124 #define CC_DATAOVERRUN 0x8
va009039 0:b0f04c137829 125 #define CC_DATAUNDERRUN 0x9
va009039 0:b0f04c137829 126
va009039 0:b0f04c137829 127 inline void DI()
va009039 0:b0f04c137829 128 {
va009039 0:b0f04c137829 129 NVIC_DisableIRQ(USB_IRQn);
va009039 0:b0f04c137829 130 }
va009039 0:b0f04c137829 131
va009039 0:b0f04c137829 132 inline void EI()
va009039 0:b0f04c137829 133 {
va009039 0:b0f04c137829 134 NVIC_EnableIRQ(USB_IRQn);
va009039 0:b0f04c137829 135 }
va009039 0:b0f04c137829 136
va009039 0:b0f04c137829 137 int uvc::isochronous()
va009039 0:b0f04c137829 138 {
va009039 0:b0f04c137829 139 if (m_iso_seq == 0) {
va009039 0:b0f04c137829 140 uint16_t frame = LPC_USB->HcFmNumber;
va009039 0:b0f04c137829 141 m_iso_frame = frame + 10; // 10msec
va009039 0:b0f04c137829 142 DBG_ASSERT(m_pEpIsoIn->m_itdActive == 0);
va009039 0:b0f04c137829 143 m_iso_seq++;
va009039 0:b0f04c137829 144 }
va009039 0:b0f04c137829 145 if (m_iso_seq == 1) {
va009039 0:b0f04c137829 146 DBG_ASSERT(m_itdCount > 0 && m_itdCount <= 8);
va009039 0:b0f04c137829 147 while(m_pEpIsoIn->m_itdActive < m_itdCount) {
va009039 0:b0f04c137829 148 int len = m_PacketSize * m_FrameCount;
va009039 0:b0f04c137829 149 uint8_t* buf = (uint8_t*)usb_get_bp(len);
va009039 0:b0f04c137829 150 if (buf == NULL) {
va009039 0:b0f04c137829 151 DBG("len=%d\n", len);
va009039 0:b0f04c137829 152 DBG("m_itdCount=%d\n", m_itdCount);
va009039 0:b0f04c137829 153 }
va009039 0:b0f04c137829 154 DBG_ASSERT(buf);
va009039 0:b0f04c137829 155 int rc = m_pEpIsoIn->transfer(m_iso_frame, m_FrameCount, buf, len);
va009039 0:b0f04c137829 156 m_iso_frame += m_FrameCount;
va009039 0:b0f04c137829 157 DBG_ASSERT(rc == USBERR_PROCESSING);
va009039 0:b0f04c137829 158 }
va009039 0:b0f04c137829 159 m_iso_seq++;
va009039 0:b0f04c137829 160 }
va009039 0:b0f04c137829 161 if (m_iso_seq == 2) {
va009039 0:b0f04c137829 162 //DBG("frame:%04X\n", LPC_USB->HcFmNumber);
va009039 0:b0f04c137829 163 while(1) {
va009039 0:b0f04c137829 164 DI();
va009039 0:b0f04c137829 165 bool empty = m_pEpIsoIn->queue_done_itd.empty();
va009039 0:b0f04c137829 166 EI();
va009039 0:b0f04c137829 167
va009039 0:b0f04c137829 168 if (empty) {
va009039 0:b0f04c137829 169 break;
va009039 0:b0f04c137829 170 }
va009039 0:b0f04c137829 171
va009039 0:b0f04c137829 172 DI();
va009039 0:b0f04c137829 173 HCITD* itd = m_pEpIsoIn->queue_done_itd.front();
va009039 0:b0f04c137829 174 m_pEpIsoIn->queue_done_itd.pop();
va009039 0:b0f04c137829 175 EI();
va009039 0:b0f04c137829 176
va009039 0:b0f04c137829 177 m_pEpIsoIn->m_itdActive--;
va009039 0:b0f04c137829 178 usb_itd iso_td(itd);
va009039 0:b0f04c137829 179 //DBG("frame:%04X\n", LPC_USB->HcFmNumber);
va009039 0:b0f04c137829 180 //DBG("itd->Control=%08X\n", itd->Control);
va009039 0:b0f04c137829 181 int cc = iso_td.ConditionCode();
va009039 0:b0f04c137829 182 DBG_ASSERT(cc >= 0 && cc <= 15);
va009039 0:b0f04c137829 183 ReportConditionCode[cc]++;
va009039 0:b0f04c137829 184 if (cc != CC_NOERROR) {
va009039 0:b0f04c137829 185 DBG3("%04X ERR:%X\n", LPC_USB->HcFmNumber, cc);
va009039 0:b0f04c137829 186 iso_td.free();
va009039 0:b0f04c137829 187 m_iso_seq = 3;
va009039 0:b0f04c137829 188 return -1;
va009039 0:b0f04c137829 189 }
va009039 0:b0f04c137829 190 uint16_t frame = iso_td.StartingFrame();
va009039 0:b0f04c137829 191 int fc = iso_td.FrameCount();
va009039 0:b0f04c137829 192 for(int i = 0; i < fc; i++) {
va009039 0:b0f04c137829 193 int len = iso_td.Length(i);
va009039 0:b0f04c137829 194 if (len > 0) {
va009039 0:b0f04c137829 195 if (m_stream) {
va009039 0:b0f04c137829 196 m_stream->input(frame+i, iso_td.BufferPage(i, m_PacketSize), len);
va009039 0:b0f04c137829 197 }
va009039 0:b0f04c137829 198 onResult(frame+i, iso_td.BufferPage(i, m_PacketSize), len);
va009039 0:b0f04c137829 199 }
va009039 0:b0f04c137829 200 }
va009039 0:b0f04c137829 201 iso_td.free();
va009039 0:b0f04c137829 202 }
va009039 0:b0f04c137829 203 //DBG("frame:%04X\n", LPC_USB->HcFmNumber);
va009039 0:b0f04c137829 204 m_iso_seq = 1;
va009039 0:b0f04c137829 205 return m_pEpIsoIn->m_itdActive;
va009039 0:b0f04c137829 206 }
va009039 0:b0f04c137829 207 if (m_iso_seq == 3) { // cleanup
va009039 0:b0f04c137829 208 DBG("m_pEpIsoIn->queue_done_itd.size() :%d\n", m_pEpIsoIn->queue_done_itd.size());
va009039 0:b0f04c137829 209 while(1) {
va009039 0:b0f04c137829 210 DI();
va009039 0:b0f04c137829 211 bool empty = m_pEpIsoIn->queue_done_itd.empty();
va009039 0:b0f04c137829 212 EI();
va009039 0:b0f04c137829 213
va009039 0:b0f04c137829 214 if (empty) {
va009039 0:b0f04c137829 215 break;
va009039 0:b0f04c137829 216 }
va009039 0:b0f04c137829 217
va009039 0:b0f04c137829 218 DI();
va009039 0:b0f04c137829 219 HCITD* itd = m_pEpIsoIn->queue_done_itd.front();
va009039 0:b0f04c137829 220 m_pEpIsoIn->queue_done_itd.pop();
va009039 0:b0f04c137829 221 EI();
va009039 0:b0f04c137829 222
va009039 0:b0f04c137829 223 m_pEpIsoIn->m_itdActive--;
va009039 0:b0f04c137829 224 usb_itd iso_td(itd);
va009039 0:b0f04c137829 225 iso_td.free();
va009039 0:b0f04c137829 226 }
va009039 0:b0f04c137829 227 if (m_pEpIsoIn->m_itdActive == 0) {
va009039 0:b0f04c137829 228 m_iso_seq = 0;
va009039 0:b0f04c137829 229 }
va009039 0:b0f04c137829 230 }
va009039 0:b0f04c137829 231 return m_pEpIsoIn->m_itdActive;
va009039 0:b0f04c137829 232 }
va009039 0:b0f04c137829 233
va009039 0:b0f04c137829 234 void uvc::attach(usb_stream* stream)
va009039 0:b0f04c137829 235 {
va009039 0:b0f04c137829 236 m_stream = stream;
va009039 0:b0f04c137829 237 }
va009039 0:b0f04c137829 238
va009039 0:b0f04c137829 239 void uvc::detach()
va009039 0:b0f04c137829 240 {
va009039 0:b0f04c137829 241 m_stream = NULL;
va009039 0:b0f04c137829 242 }
va009039 0:b0f04c137829 243
va009039 0:b0f04c137829 244 void uvc::onResult(uint16_t frame, uint8_t* buf, int len)
va009039 0:b0f04c137829 245 {
va009039 0:b0f04c137829 246 if(m_pCbItem && m_pCbMeth)
va009039 0:b0f04c137829 247 (m_pCbItem->*m_pCbMeth)(frame, buf, len);
va009039 0:b0f04c137829 248 else if(m_pCb)
va009039 0:b0f04c137829 249 m_pCb(frame, buf, len);
va009039 0:b0f04c137829 250 }
va009039 0:b0f04c137829 251
va009039 0:b0f04c137829 252 void uvc::setOnResult( void (*pMethod)(uint16_t, uint8_t*, int) )
va009039 0:b0f04c137829 253 {
va009039 0:b0f04c137829 254 m_pCb = pMethod;
va009039 0:b0f04c137829 255 m_pCbItem = NULL;
va009039 0:b0f04c137829 256 m_pCbMeth = NULL;
va009039 0:b0f04c137829 257 }
va009039 0:b0f04c137829 258
va009039 0:b0f04c137829 259 void uvc::clearOnResult()
va009039 0:b0f04c137829 260 {
va009039 0:b0f04c137829 261 m_pCb = NULL;
va009039 0:b0f04c137829 262 m_pCbItem = NULL;
va009039 0:b0f04c137829 263 m_pCbMeth = NULL;
va009039 0:b0f04c137829 264 }