BaseJpegDeocde exampe program

Dependencies:   BaseJpegDecode Terminal BaseUsbHost mbed mbed-rtos

Fork of BaseJpegDecode by Norimasa Okamoto

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UvcCam.cpp Source File

UvcCam.cpp

00001 // UvcCam.cpp 2013/1/25
00002 #include "mbed.h"
00003 #include "rtos.h"
00004 #include "BaseUsbHost.h"
00005 //#define DEBUG
00006 #include "BaseUsbHostDebug.h"
00007 #define TEST
00008 #include "BaseUsbHostTest.h"
00009 #include "UvcCam.h"
00010 
00011 UvcCam::UvcCam(int formatIndex, int frameIndex, uint32_t interval, ControlEp* ctlEp)
00012 {
00013     uint8_t buf[34];
00014     int rc;
00015     int alt;
00016     int cfg2;
00017     
00018     if (ctlEp == NULL) { // root hub
00019         DBG_OHCI(LPC_USB->HcRhPortStatus1);
00020         TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200);
00021         ctlEp = new ControlEp();
00022         TEST_ASSERT_TRUE(ctlEp);
00023     }
00024     bool r = check(ctlEp);
00025     TEST_ASSERT(r);
00026     m_ctlEp = ctlEp;
00027     
00028     UvcCfg* cfg = new UvcCfg(formatIndex, frameIndex, ctlEp);
00029     TEST_ASSERT(cfg);
00030 
00031     int param_len = 34;
00032     TEST_ASSERT(cfg->bcdUVC >= 0x0100);
00033     if (cfg->bcdUVC == 0x0100) { // UVC ver. 1.0
00034         param_len = 26;
00035     }
00036     
00037     int addr = m_ctlEp->GetAddr();
00038     m_isoEp = new IsochronousEp(addr, cfg->bEndpointAddress, cfg->wMaxPacketSize);
00039     TEST_ASSERT_TRUE(m_isoEp);
00040 
00041 //#define USE_PROBE
00042 
00043 #ifdef USE_PROBE
00044     rc = Control(GET_INFO, VS_PROBE_CONTROL, 1, buf, 1);
00045     TEST_ASSERT(rc == USB_OK);
00046     DBG_BYTES("GET_INFO Prob", buf, 1);
00047 
00048     rc = Control(GET_DEF, VS_PROBE_CONTROL, 1, buf, param_len);
00049     TEST_ASSERT(rc == USB_OK);
00050     DBG_BYTES("GET_DEF Probe", buf, param_len);
00051 
00052     rc = Control(GET_MIN, VS_PROBE_CONTROL, 1, buf, param_len);
00053     TEST_ASSERT(rc == USB_OK);
00054     DBG_BYTES("GET_MIN Probe", buf, param_len);
00055 
00056     rc = Control(GET_MAX, VS_PROBE_CONTROL, 1, buf, param_len);
00057     TEST_ASSERT(rc == USB_OK);
00058     DBG_BYTES("GET_MAX Probe", buf, param_len);
00059 
00060     rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, buf, param_len);
00061     TEST_ASSERT(rc == USB_OK);
00062     DBG_BYTES("GET_CUR Probe", buf, param_len);
00063 #endif // USE_PROBE
00064 
00065     rc = Control(GET_INFO, VS_COMMIT_CONTROL, 1, buf, 1);
00066     TEST_ASSERT(rc == USB_OK);
00067     DBG_BYTES("GET_INFO Commit", buf, 1);
00068 
00069     memset(buf, 0, param_len);
00070     buf[2] = cfg->FormatIndex;
00071     buf[3] = cfg->FrameIndex;
00072     *reinterpret_cast<uint32_t*>(buf+4) = interval;
00073     
00074     DBG_BYTES("SET_CUR Commit", buf, param_len);
00075     rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len);
00076     TEST_ASSERT(rc == USB_OK);
00077 
00078     rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len);
00079     TEST_ASSERT(rc == USB_OK);
00080     TEST_ASSERT_EQUAL(buf[2], cfg->FormatIndex);
00081     TEST_ASSERT_EQUAL(buf[3], cfg->FrameIndex);
00082     TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval);
00083     DBG_BYTES("GET_CUR Commit", buf, param_len);
00084 
00085     rc = m_ctlEp->GetConfiguration(&cfg2);
00086     TEST_ASSERT_EQUAL(rc, USB_OK);
00087     DBG("config: %d\n", cfg2);
00088 
00089     rc = m_ctlEp->SetConfiguration(1);
00090     TEST_ASSERT_EQUAL(rc, USB_OK);
00091 
00092     rc = m_ctlEp->GetConfiguration(&cfg2);
00093     TEST_ASSERT_EQUAL(rc, USB_OK);
00094     DBG("config: %d\n", cfg2);
00095     TEST_ASSERT_EQUAL(cfg2, 1);
00096 
00097     rc = m_ctlEp->GetInterface(cfg->bInterface, &alt);
00098     TEST_ASSERT_EQUAL(rc, USB_OK);
00099     DBG("alt: %d\n", alt);
00100 
00101     rc = m_ctlEp->SetInterfaceAlternate(cfg->bInterface, cfg->bAlternate);
00102     TEST_ASSERT_EQUAL(rc, USB_OK);
00103 
00104     rc = m_ctlEp->GetInterface(cfg->bInterface, &alt);
00105     TEST_ASSERT_EQUAL(rc, USB_OK);
00106     DBG("alt: %d\n", alt);
00107     TEST_ASSERT_EQUAL(alt, cfg->bAlternate);
00108     delete cfg;
00109     
00110     for(int i = 0; i < 16; i++) {
00111         report_cc_count[i] = 0;
00112         report_ps_cc_count[i] = 0;
00113     }
00114   
00115     LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable
00116     LPC_USB->HcControl |= OR_CONTROL_IE;  // IsochronousEnable
00117 }
00118 
00119 bool UvcCam::check(ControlEp* ctlEp)
00120 {
00121     if (ctlEp == NULL) {
00122         return false;
00123     }
00124     uint8_t buf[18];
00125     int r = ctlEp->GetDescriptor(1, 0, buf, 8);
00126     if (r != USB_OK) {
00127         return false;
00128     }
00129     DBG_HEX(buf, 8);
00130     const uint8_t desc[] = {0x12,0x01,0x00,0x02,0xef,0x02,0x01};
00131     if (memcmp(buf, desc, sizeof(desc)) != 0) {
00132         return false;
00133     }
00134     r = ctlEp->GetDescriptor(1, 0, buf, 18);
00135     if (r != USB_OK) {
00136         return false;
00137     }
00138     DBG_HEX(buf, 18);
00139     return true;
00140 }
00141 
00142 #define  DESCRIPTOR_TYPE_DEVICE        1
00143 #define  DESCRIPTOR_TYPE_CONFIGURATION 2
00144 #define  DESCRIPTOR_TYPE_STRING        3
00145 #define  DESCRIPTOR_TYPE_INTERFACE     4
00146 #define  DESCRIPTOR_TYPE_ENDPOINT      5
00147 
00148 #define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b
00149 
00150 #define DESCRIPTOR_TYPE_HID          0x21
00151 #define DESCRIPTOR_TYPE_REPORT       0x22
00152 #define DESCRIPTOR_TYPE_PHYSICAL     0x23
00153 #define DESCRIPTOR_TYPE_CS_INTERFACE 0x24
00154 #define DESCRIPTOR_TYPE_CS_ENDPOINT  0x25
00155 #define DESCRIPTOR_TYPE_HUB          0x29
00156 
00157 #define CLASS_AUDIO 0x02
00158 #define CLASS_HUB   0x09
00159 
00160 #define IF_EQ_THEN_PRINTF(A,B) if (A == B) {VERBOSE("%s\n", #A);
00161 #define ENDIF }
00162 
00163 #define CC_AUDIO 0x01
00164 #define SC_AUDIOCONTROL   0x01
00165 #define SC_AUDIOSTREAMING 0x02
00166 
00167 #define AC_HEADER          0x01
00168 #define AC_INPUT_TERMINAL  0x02
00169 #define AC_OUTPUT_TERMINAL 0x03
00170 #define AC_FEATURE_UNIT    0x06
00171 
00172 // Input Terminal Types
00173 #define ITT_CAMERA 0x0201
00174 
00175 static int LE16(const uint8_t* d)
00176 {
00177     return d[0] | (d[1] << 8);
00178 }
00179 
00180 static int LE24(const uint8_t* d) {
00181     return d[0] | (d[1]<<8) | (d[2] << 16);
00182 }
00183 
00184 static int LE32(const uint8_t* d) {
00185     return d[0] |(d[1]<<8) | (d[2] << 16) |(d[3] << 24) ;
00186 }
00187 
00188 UvcCfg::UvcCfg(int formatIndex, int frameIndex, ControlEp* ctlEp):wMaxPacketSize(0)
00189 {
00190     TEST_ASSERT(ctlEp);
00191     switch(formatIndex) {
00192         case UVC_MJPEG: _payload = UVC_MJPEG; break;
00193         case UVC_YUY2:  _payload = UVC_YUY2; break;
00194         default:        _payload = UVC_MJPEG; break;
00195     }
00196 
00197     switch(frameIndex) {
00198         case UVC_160x120: _width = 160; _height = 120; break;
00199         case UVC_176x144: _width = 176; _height = 144; break;
00200         case UVC_320x176: _width = 320; _height = 176; break;
00201         case UVC_320x240: _width = 320; _height = 240; break;
00202         case UVC_352x288: _width = 352; _height = 288; break;
00203         case UVC_432x240: _width = 432; _height = 240; break;
00204         case UVC_640x480: _width = 640; _height = 480; break;
00205         case UVC_544x288: _width = 544; _height = 288; break;
00206         case UVC_640x360: _width = 640; _height = 360; break;
00207         case UVC_752x416: _width = 752; _height = 416; break;
00208         case UVC_800x448: _width = 800; _height = 448; break;
00209         case UVC_800x600: _width = 800; _height = 600; break;
00210         default:          _width = 160; _height = 120; break;
00211     }
00212     int index = 0;
00213     uint8_t temp[4];
00214     int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, temp, sizeof(temp));
00215     TEST_ASSERT(rc == USB_OK);
00216     DBG_BYTES("Config Descriptor 4bytes", temp, sizeof(temp));
00217     TEST_ASSERT(temp[0] == 9);
00218     TEST_ASSERT(temp[1] == 0x02);
00219     int TotalLength = LE16(temp+2);
00220     DBG("TotalLength: %d\n", TotalLength);
00221 
00222     uint8_t* buf = new uint8_t[TotalLength];
00223     TEST_ASSERT(buf);
00224     rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, TotalLength);
00225     TEST_ASSERT(rc == USB_OK);
00226     if (rc != USB_OK) {
00227         delete[] buf;
00228         return;
00229     }
00230     _parserConfigurationDescriptor(buf, TotalLength);
00231     delete[] buf;
00232 }
00233 
00234 void UvcCfg::_parserAudioControl(uint8_t* buf, int len) {
00235     int subtype = buf[2];
00236     IF_EQ_THEN_PRINTF(AC_HEADER, subtype)
00237     VERBOSE("ADC: %04x\n", LE16(buf+3));
00238     VERBOSE("TotalLength: %d\n", LE16(buf+5));
00239     VERBOSE("InCollection: %d\n", buf[7]);
00240     for (int n = 1; n <= buf[7]; n++) {
00241         VERBOSE("aInterfaceNr(%d): %d\n", n, buf[8+n-1]);
00242     }
00243     ENDIF
00244     IF_EQ_THEN_PRINTF(AC_INPUT_TERMINAL, subtype)
00245     VERBOSE("TerminalID: %d\n", buf[3]);
00246     VERBOSE("TerminalType: %04X\n", LE16(buf+4));
00247     VERBOSE("AssocTermianl: %d\n", buf[6]);
00248     VERBOSE("NrChannels: %d\n", buf[7]);
00249     ENDIF
00250     IF_EQ_THEN_PRINTF(AC_OUTPUT_TERMINAL, subtype)
00251     VERBOSE("TerminalID: %d\n", buf[3]);
00252     VERBOSE("TerminalType: %04X\n", LE16(buf+4));
00253     VERBOSE("AssocTermianl: %d\n", buf[6]);
00254     ENDIF
00255     IF_EQ_THEN_PRINTF(AC_FEATURE_UNIT, subtype)
00256     VERBOSE("UnitID: %d\n", buf[3]);
00257     VERBOSE("SourceID: %d\n", buf[4]);
00258     VERBOSE("ControlSize: %d\n", buf[5]);
00259     ENDIF
00260 }
00261 
00262 #define AS_GENERAL     0x01
00263 #define AS_FORMAT_TYPE 0x02
00264 
00265 void UvcCfg::_parserAudioStream(uint8_t* buf, int len) {
00266     int subtype = buf[2];
00267     IF_EQ_THEN_PRINTF(AS_GENERAL, subtype)
00268     VERBOSE("TerminalLink: %d\n", buf[3]);
00269     VERBOSE("Delay: %d\n", buf[4]);
00270     VERBOSE("FormatTag: %04x\n", LE16(buf+5));
00271     ENDIF
00272     IF_EQ_THEN_PRINTF(AS_FORMAT_TYPE, subtype)
00273     VERBOSE("FormatType: %d\n", buf[3]);
00274     VERBOSE("NrChannels: %d\n", buf[4]);
00275     VERBOSE("SubFrameSize: %d\n", buf[5]);
00276     VERBOSE("BitResolution: %d\n", buf[6]);
00277     VERBOSE("SamFreqType: %d\n", buf[7]);
00278     VERBOSE("SamFreq(1): %d\n", LE24(buf+8));
00279     ENDIF
00280 }
00281 
00282 #define CC_VIDEO 0x0e
00283 
00284 #define SC_VIDEOCONTROL   0x01
00285 #define SC_VIDEOSTREAMING 0x02
00286 
00287 #define VC_HEADER          0x01
00288 #define VC_INPUT_TERMINAL  0x02
00289 #define VC_OUTPUT_TERMINAL 0x03
00290 #define VC_SELECTOR_UNIT   0x04
00291 #define VC_PROCESSING_UNIT 0x05
00292 #define VC_EXTENSION_UNIT  0x06
00293 
00294 void UvcCfg::_parserVideoControl(uint8_t* buf, int len) {
00295     int subtype = buf[2];
00296     IF_EQ_THEN_PRINTF(VC_HEADER, subtype)
00297         bcdUVC = LE16(buf+3);
00298         VERBOSE("UVC: %04x\n", bcdUVC);
00299         VERBOSE("TotalLength: %d\n", LE16(buf+5));
00300         VERBOSE("ClockFrequency: %d\n", LE32(buf+7));
00301         VERBOSE("InCollection: %d\n", buf[11]);
00302         VERBOSE("aInterfaceNr(1): %d\n", buf[12]);
00303     ENDIF
00304     IF_EQ_THEN_PRINTF(VC_INPUT_TERMINAL, subtype)
00305         VERBOSE("TerminalID: %d\n", buf[3]);
00306         uint16_t tt = LE16(buf+4);
00307         VERBOSE("TerminalType: %04X\n", tt);
00308         VERBOSE("AssocTerminal: %d\n", buf[6]);
00309         VERBOSE("Terminal: %d\n", buf[7]);
00310         if (tt == ITT_CAMERA) { // camera
00311             int bControlSize = buf[14];
00312             VERBOSE("ControlSize: %d\n", bControlSize);
00313             for(int i = 0; i < bControlSize; i++) {
00314             uint8_t bControls = buf[15+i];
00315                 VERBOSE("Controls(%d): %02X\n", i, bControls); 
00316             }
00317         }
00318     ENDIF
00319     IF_EQ_THEN_PRINTF(VC_OUTPUT_TERMINAL, subtype)
00320         VERBOSE("TerminalID: %d\n", buf[3]);
00321         VERBOSE("TerminalType: %04X\n", LE16(buf+4));
00322         VERBOSE("AssocTerminal: %d\n", buf[6]);
00323         VERBOSE("SourceID: %d\n", buf[7]);
00324         VERBOSE("Terminal: %d\n", buf[8]);
00325     ENDIF
00326     IF_EQ_THEN_PRINTF(VC_SELECTOR_UNIT, subtype)
00327         VERBOSE("UnitID: %d\n", buf[3]);
00328     ENDIF
00329     IF_EQ_THEN_PRINTF(VC_PROCESSING_UNIT, subtype)
00330         VERBOSE("UnitID: %d\n", buf[3]);
00331         VERBOSE("SourceID: %d\n", buf[4]);
00332         VERBOSE("MaxMultiplier: %d\n", LE16(buf+5));
00333         VERBOSE("ControlSize: %d\n", buf[7]);
00334         int pos = 8;
00335         for (int n = 1; n <= buf[7]; n++) {
00336             VERBOSE("Controls(%d): %02X\n", n , buf[pos]);
00337             pos++;
00338         }
00339         VERBOSE("Processing: %d\n", buf[pos]);
00340         pos++;
00341         VERBOSE("VideoStanders: %02X\n", buf[pos]);
00342     ENDIF
00343     IF_EQ_THEN_PRINTF(VC_EXTENSION_UNIT, subtype)
00344         VERBOSE("UnitID: %d\n", buf[3]);
00345     ENDIF
00346 }
00347 
00348 #define VS_INPUT_HEADER 0x01
00349 #define VS_STILL_FRAME  0x03
00350 #define VS_FORMAT_UNCOMPRESSED 0x04
00351 #define VS_FRAME_UNCOMPRESSED 0x05
00352 #define VS_FORMAT_MJPEG 0x06
00353 #define VS_FRAME_MJPEG  0x07
00354 #define VS_COLOR_FORMAT 0x0d
00355 
00356 void UvcCfg::_parserVideoStream(uint8_t* buf, int len) {
00357     int subtype = buf[2];
00358     IF_EQ_THEN_PRINTF(VS_INPUT_HEADER, subtype)
00359         VERBOSE("NumFormats: %d\n", buf[3]);
00360         VERBOSE("TotalLength: %d\n", LE16(buf+4));
00361         VERBOSE("EndpointAddress: %02X\n", buf[6]);
00362         VERBOSE("Info: %02X\n", buf[7]);
00363         VERBOSE("TerminalLink: %d\n", buf[8]);
00364         VERBOSE("StillCaptureMethod: %d\n", buf[9]);
00365         VERBOSE("TriggerSupport: %d\n", buf[10]);
00366         VERBOSE("TriggerUsage: %d\n", buf[11]);
00367         VERBOSE("ControlSize: %d\n", buf[12]);
00368         int pos = 13;
00369         for (int n = 1; n <= buf[12]; n++) {
00370             VERBOSE("Controls(%d): %02X\n", n, buf[pos]);
00371             pos++;
00372         }
00373         bEndpointAddress = buf[6];
00374     ENDIF
00375     IF_EQ_THEN_PRINTF(VS_STILL_FRAME, subtype)
00376     VERBOSE("EndpointAdress: %02X\n", buf[3]);
00377     VERBOSE("NumImageSizePatterns: %d\n", buf[4]);
00378     int ptn = buf[4];
00379     int pos = 5;
00380     for (int n = 1; n <= ptn; n++) {
00381         VERBOSE("Width(%d): %d\n", n, LE16(buf+pos));
00382         VERBOSE("Height(%d): %d\n", n, LE16(buf+pos+2));
00383         pos += 4;
00384     }
00385     VERBOSE("NumCompressPtn: %d\n", buf[pos]);
00386     ptn = buf[pos++];
00387     for (int n = 1; n <= ptn; n++) {
00388         VERBOSE("Compress(%d): %d\n", n, buf[pos]);
00389         pos++;
00390     }
00391     ENDIF
00392     IF_EQ_THEN_PRINTF(VS_FORMAT_UNCOMPRESSED, subtype)
00393         VERBOSE("FormatIndex: %d\n", buf[3]);
00394         VERBOSE("NumFrameDescriptors: %d\n", buf[4]);
00395         uint32_t guid = LE32(buf+5);
00396         if (guid == 0x32595559) {
00397             VERBOSE("GUID: YUY2\n");
00398         } else if (guid == 0x3231564e) {
00399             VERBOSE("GUID: NV12\n");
00400         } else {
00401             VERBOSE("GUID: %08x\n", guid);
00402         }
00403         VERBOSE("DefaultFrameIndex: %d\n", buf[22]);
00404         if (_payload == UVC_YUY2) {
00405             FormatIndex = buf[3];
00406         }
00407     ENDIF
00408     IF_EQ_THEN_PRINTF(VS_FRAME_UNCOMPRESSED, subtype)
00409         VERBOSE("FrameIndex: %d\n", buf[3]);
00410         VERBOSE("Capabilites: %d\n", buf[4]);
00411         VERBOSE("Width: %d\n", LE16(buf+5));
00412         VERBOSE("Height: %d\n", LE16(buf+7));
00413         VERBOSE("MinBitRate: %d\n", LE32(buf+9));
00414         VERBOSE("MaxBitRate: %d\n", LE32(buf+13));
00415         VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17));
00416         VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21));
00417         VERBOSE("FrameIntervalType: %d\n", buf[25]);
00418         int it = buf[25];
00419         uint32_t max_fi = 333333; // 30.0fps
00420         if (it == 0) {
00421             VERBOSE("FrameMinInterval: %d\n", buf[26]);
00422             VERBOSE("FrameMaxInterval: %d\n", buf[30]);
00423             VERBOSE("FrameIntervalStep: %d\n", buf[34]);
00424         } else {
00425             int pos = 26;
00426             for (int n = 1; n <= it; n++) {
00427                 uint32_t fi = LE32(buf+pos);
00428                 if (fi >= max_fi) {
00429                     max_fi = fi;
00430                 }
00431                 float fps = 1e+7 / fi;
00432                 VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps);
00433                 pos += 4;
00434             }
00435         }
00436         if (_payload == UVC_YUY2) {
00437             if (_width == LE16(buf+5) && _height == LE16(buf+7)) {
00438                 FrameIndex = buf[3];
00439             }
00440             if (dwFrameInterval == 0) {
00441                 dwFrameInterval = max_fi;
00442             }
00443         }
00444     ENDIF
00445     IF_EQ_THEN_PRINTF(VS_FORMAT_MJPEG, subtype)
00446         VERBOSE("FormatIndex: %d\n", buf[3]);
00447         VERBOSE("NumFrameDescriptors: %d\n", buf[4]);
00448         VERBOSE("Flags: %d\n", buf[5]);
00449         VERBOSE("DefaultFrameIndex: %d\n", buf[6]);
00450         if (_payload == UVC_MJPEG) {
00451             FormatIndex = buf[3];
00452         }
00453     ENDIF
00454     IF_EQ_THEN_PRINTF(VS_FRAME_MJPEG, subtype)
00455         VERBOSE("FrameIndex: %d\n", buf[3]);
00456         VERBOSE("Capabilites: %d\n", buf[4]);
00457         VERBOSE("Width: %d\n", LE16(buf+5));
00458         VERBOSE("Height: %d\n", LE16(buf+7));
00459         VERBOSE("MinBitRate: %d\n", LE32(buf+9));
00460         VERBOSE("MaxBitRate: %d\n", LE32(buf+13));
00461         VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17));
00462         VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21));
00463         VERBOSE("FrameIntervalType: %d\n", buf[25]);
00464         int it = buf[25];
00465         uint32_t max_fi = 333333; // 30.0fps
00466         if (it == 0) {
00467             VERBOSE("FrameMinInterval: %d\n", buf[26]);
00468             VERBOSE("FrameMaxInterval: %d\n", buf[30]);
00469             VERBOSE("FrameIntervalStep: %d\n", buf[34]);
00470         } else {
00471             int pos = 26;
00472             for (int n = 1; n <= it; n++) {
00473                 uint32_t fi = LE32(buf+pos);
00474                 if (fi >= max_fi) {
00475                     max_fi = fi;
00476                 }
00477                 float fps = 1e+7 / fi;
00478                 VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps);
00479                 pos += 4;
00480             }
00481         }
00482         if (_payload == UVC_MJPEG) {
00483             if (_width == LE16(buf+5) && _height == LE16(buf+7)) {
00484                 FrameIndex = buf[3];
00485             }
00486             if (dwFrameInterval == 0) {
00487                 dwFrameInterval = max_fi;
00488             }
00489         }
00490     ENDIF
00491     IF_EQ_THEN_PRINTF(VS_COLOR_FORMAT, subtype)
00492     ENDIF
00493 }
00494 
00495 void UvcCfg::_parserConfigurationDescriptor(uint8_t* buf, int len) {
00496     int pos = 0;
00497     _IfClass = 0;
00498     _IfSubClass = 0;
00499     while (pos < len) {
00500         int type = buf[pos+1];
00501         //DBG_BYTES(TYPE_Str(type), buf+pos, buf[pos]);
00502         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CONFIGURATION, type)
00503             VERBOSE("NumInterfaces: %d\n", buf[pos+4]);
00504         ENDIF
00505         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, type)
00506             VERBOSE("FirstInterface: %d\n", buf[pos+2]);
00507             VERBOSE("InterfaceCount: %d\n", buf[pos+3]);
00508             VERBOSE("FunctionClass: %02X\n", buf[pos+4]);
00509             VERBOSE("FunctionSubClass: %02X\n", buf[pos+5]);
00510             VERBOSE("FunctionProtocol: %02X\n", buf[pos+6]);
00511             VERBOSE("Function: %d\n", buf[pos+7]);
00512         ENDIF
00513         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE,type)
00514             VERBOSE("InterfaceNumber: %d\n", buf[pos+2]);
00515             VERBOSE("AlternateSetting: %d\n", buf[pos+3]);
00516             VERBOSE("NumEndpoint: %d\n", buf[pos+4]);
00517             VERBOSE("InterfaceClass: %02X\n", buf[pos+5]);
00518             VERBOSE("InterfaceSubClass: %02X\n", buf[pos+6]);
00519             VERBOSE("InterfaceProtocol: %02X\n", buf[pos+7]);
00520             VERBOSE("Interface: %d\n", buf[pos+8]);
00521             _If         = buf[pos+2];
00522             _Ifalt      = buf[pos+3];
00523             _IfClass    = buf[pos+5];
00524             _IfSubClass = buf[pos+6];
00525         ENDIF
00526         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_ENDPOINT, type)
00527             VERBOSE("EndpointAddress: %02X\n", buf[pos+2]);
00528             VERBOSE("Attributes: %02X\n", buf[pos+3]);
00529             VERBOSE("MaxPacketSize: %d\n", LE16(buf+pos+4));
00530             VERBOSE("Interval: %d\n", buf[pos+6]);
00531             if (_IfClass == CC_VIDEO && _IfSubClass == SC_VIDEOSTREAMING) {
00532                 if (bEndpointAddress == buf[pos+2]) {
00533                     if (wMaxPacketSize == 0) {
00534                         wMaxPacketSize = LE16(buf+pos+4);
00535                     }    
00536                     if (wMaxPacketSize == LE16(buf+pos+4)) {
00537                         bInterface = _If;
00538                         bAlternate = _Ifalt;
00539                     }
00540                 }
00541             }
00542         ENDIF
00543         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CS_INTERFACE, type)
00544             IF_EQ_THEN_PRINTF(CC_VIDEO, _IfClass)
00545                 IF_EQ_THEN_PRINTF(SC_VIDEOCONTROL, _IfSubClass)
00546                     _parserVideoControl(buf+pos, buf[pos]);
00547                 ENDIF
00548                 IF_EQ_THEN_PRINTF(SC_VIDEOSTREAMING, _IfSubClass)
00549                     _parserVideoStream(buf+pos, buf[pos]);
00550                 ENDIF
00551             ENDIF
00552             IF_EQ_THEN_PRINTF(CC_AUDIO, _IfClass)
00553                 IF_EQ_THEN_PRINTF(SC_AUDIOCONTROL, _IfSubClass)
00554                     _parserAudioControl(buf+pos, buf[pos]);
00555                 ENDIF 
00556                 IF_EQ_THEN_PRINTF(SC_AUDIOSTREAMING, _IfSubClass)
00557                     _parserAudioStream(buf+pos, buf[pos]);
00558                 ENDIF
00559             ENDIF
00560         ENDIF
00561         IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_HUB, type)
00562         ENDIF
00563         pos += buf[pos];
00564     }
00565 }
00566