![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
BaseUsbHost example program
Dependencies: BaseUsbHost FATFileSystem mbed mbed-rtos
UvcCam/UvcCam.cpp@2:c10029b87439, 2012-12-11 (annotated)
- Committer:
- va009039
- Date:
- Tue Dec 11 15:28:00 2012 +0000
- Revision:
- 2:c10029b87439
- Child:
- 5:495f7536897b
add example
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 2:c10029b87439 | 1 | // UvcCam.cpp 2012/12/9 |
va009039 | 2:c10029b87439 | 2 | #include "mbed.h" |
va009039 | 2:c10029b87439 | 3 | #include "rtos.h" |
va009039 | 2:c10029b87439 | 4 | #include "BaseUsbHost.h" |
va009039 | 2:c10029b87439 | 5 | #define DEBUG |
va009039 | 2:c10029b87439 | 6 | #include "BaseUsbHostDebug.h" |
va009039 | 2:c10029b87439 | 7 | #define TEST |
va009039 | 2:c10029b87439 | 8 | #include "BaseUsbHostTest.h" |
va009039 | 2:c10029b87439 | 9 | #include "UvcCam.h" |
va009039 | 2:c10029b87439 | 10 | |
va009039 | 2:c10029b87439 | 11 | UvcCam::UvcCam(int formatIndex, int frameIndex, uint32_t interval, ControlEp* ctlEp) |
va009039 | 2:c10029b87439 | 12 | { |
va009039 | 2:c10029b87439 | 13 | uint8_t buf[34]; |
va009039 | 2:c10029b87439 | 14 | int rc; |
va009039 | 2:c10029b87439 | 15 | int alt; |
va009039 | 2:c10029b87439 | 16 | int cfg2; |
va009039 | 2:c10029b87439 | 17 | |
va009039 | 2:c10029b87439 | 18 | if (ctlEp == NULL) { // root hub |
va009039 | 2:c10029b87439 | 19 | DBG_OHCI(LPC_USB->HcRhPortStatus1); |
va009039 | 2:c10029b87439 | 20 | TEST_ASSERT_FALSE(LPC_USB->HcRhPortStatus1 & 0x200); |
va009039 | 2:c10029b87439 | 21 | ctlEp = new ControlEp(); |
va009039 | 2:c10029b87439 | 22 | TEST_ASSERT_TRUE(ctlEp); |
va009039 | 2:c10029b87439 | 23 | } |
va009039 | 2:c10029b87439 | 24 | bool r = check(ctlEp); |
va009039 | 2:c10029b87439 | 25 | TEST_ASSERT(r); |
va009039 | 2:c10029b87439 | 26 | m_ctlEp = ctlEp; |
va009039 | 2:c10029b87439 | 27 | |
va009039 | 2:c10029b87439 | 28 | UvcCfg* cfg = new UvcCfg(formatIndex, frameIndex, ctlEp); |
va009039 | 2:c10029b87439 | 29 | TEST_ASSERT(cfg); |
va009039 | 2:c10029b87439 | 30 | |
va009039 | 2:c10029b87439 | 31 | int param_len = 34; |
va009039 | 2:c10029b87439 | 32 | TEST_ASSERT(cfg->bcdUVC >= 0x0100); |
va009039 | 2:c10029b87439 | 33 | if (cfg->bcdUVC == 0x0100) { // UVC ver. 1.0 |
va009039 | 2:c10029b87439 | 34 | param_len = 26; |
va009039 | 2:c10029b87439 | 35 | } |
va009039 | 2:c10029b87439 | 36 | |
va009039 | 2:c10029b87439 | 37 | int addr = m_ctlEp->GetAddr(); |
va009039 | 2:c10029b87439 | 38 | m_isoEp = new IsochronousEp(addr, cfg->bEndpointAddress, cfg->wMaxPacketSize); |
va009039 | 2:c10029b87439 | 39 | TEST_ASSERT_TRUE(m_isoEp); |
va009039 | 2:c10029b87439 | 40 | |
va009039 | 2:c10029b87439 | 41 | //#define USE_PROBE |
va009039 | 2:c10029b87439 | 42 | |
va009039 | 2:c10029b87439 | 43 | #ifdef USE_PROBE |
va009039 | 2:c10029b87439 | 44 | rc = Control(GET_INFO, VS_PROBE_CONTROL, 1, buf, 1); |
va009039 | 2:c10029b87439 | 45 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 46 | DBG_BYTES("GET_INFO Prob", buf, 1); |
va009039 | 2:c10029b87439 | 47 | |
va009039 | 2:c10029b87439 | 48 | rc = Control(GET_DEF, VS_PROBE_CONTROL, 1, buf, param_len); |
va009039 | 2:c10029b87439 | 49 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 50 | DBG_BYTES("GET_DEF Probe", buf, param_len); |
va009039 | 2:c10029b87439 | 51 | |
va009039 | 2:c10029b87439 | 52 | rc = Control(GET_MIN, VS_PROBE_CONTROL, 1, buf, param_len); |
va009039 | 2:c10029b87439 | 53 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 54 | DBG_BYTES("GET_MIN Probe", buf, param_len); |
va009039 | 2:c10029b87439 | 55 | |
va009039 | 2:c10029b87439 | 56 | rc = Control(GET_MAX, VS_PROBE_CONTROL, 1, buf, param_len); |
va009039 | 2:c10029b87439 | 57 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 58 | DBG_BYTES("GET_MAX Probe", buf, param_len); |
va009039 | 2:c10029b87439 | 59 | |
va009039 | 2:c10029b87439 | 60 | rc = Control(GET_CUR, VS_PROBE_CONTROL, 1, buf, param_len); |
va009039 | 2:c10029b87439 | 61 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 62 | DBG_BYTES("GET_CUR Probe", buf, param_len); |
va009039 | 2:c10029b87439 | 63 | #endif // USE_PROBE |
va009039 | 2:c10029b87439 | 64 | |
va009039 | 2:c10029b87439 | 65 | rc = Control(GET_INFO, VS_COMMIT_CONTROL, 1, buf, 1); |
va009039 | 2:c10029b87439 | 66 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 67 | DBG_BYTES("GET_INFO Commit", buf, 1); |
va009039 | 2:c10029b87439 | 68 | |
va009039 | 2:c10029b87439 | 69 | memset(buf, 0, param_len); |
va009039 | 2:c10029b87439 | 70 | buf[2] = cfg->FormatIndex; |
va009039 | 2:c10029b87439 | 71 | buf[3] = cfg->FrameIndex; |
va009039 | 2:c10029b87439 | 72 | *reinterpret_cast<uint32_t*>(buf+4) = interval; |
va009039 | 2:c10029b87439 | 73 | |
va009039 | 2:c10029b87439 | 74 | DBG_BYTES("SET_CUR Commit", buf, param_len); |
va009039 | 2:c10029b87439 | 75 | rc = Control(SET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len); |
va009039 | 2:c10029b87439 | 76 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 77 | |
va009039 | 2:c10029b87439 | 78 | rc = Control(GET_CUR, VS_COMMIT_CONTROL, 1, buf, param_len); |
va009039 | 2:c10029b87439 | 79 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 80 | TEST_ASSERT_EQUAL(buf[2], cfg->FormatIndex); |
va009039 | 2:c10029b87439 | 81 | TEST_ASSERT_EQUAL(buf[3], cfg->FrameIndex); |
va009039 | 2:c10029b87439 | 82 | TEST_ASSERT_EQUAL(*reinterpret_cast<uint32_t*>(buf+4), interval); |
va009039 | 2:c10029b87439 | 83 | DBG_BYTES("GET_CUR Commit", buf, param_len); |
va009039 | 2:c10029b87439 | 84 | |
va009039 | 2:c10029b87439 | 85 | rc = m_ctlEp->GetConfiguration(&cfg2); |
va009039 | 2:c10029b87439 | 86 | TEST_ASSERT_EQUAL(rc, USB_OK); |
va009039 | 2:c10029b87439 | 87 | DBG("config: %d\n", cfg2); |
va009039 | 2:c10029b87439 | 88 | |
va009039 | 2:c10029b87439 | 89 | rc = m_ctlEp->SetConfiguration(1); |
va009039 | 2:c10029b87439 | 90 | TEST_ASSERT_EQUAL(rc, USB_OK); |
va009039 | 2:c10029b87439 | 91 | |
va009039 | 2:c10029b87439 | 92 | rc = m_ctlEp->GetConfiguration(&cfg2); |
va009039 | 2:c10029b87439 | 93 | TEST_ASSERT_EQUAL(rc, USB_OK); |
va009039 | 2:c10029b87439 | 94 | DBG("config: %d\n", cfg2); |
va009039 | 2:c10029b87439 | 95 | TEST_ASSERT_EQUAL(cfg2, 1); |
va009039 | 2:c10029b87439 | 96 | |
va009039 | 2:c10029b87439 | 97 | rc = m_ctlEp->GetInterface(cfg->bInterface, &alt); |
va009039 | 2:c10029b87439 | 98 | TEST_ASSERT_EQUAL(rc, USB_OK); |
va009039 | 2:c10029b87439 | 99 | DBG("alt: %d\n", alt); |
va009039 | 2:c10029b87439 | 100 | |
va009039 | 2:c10029b87439 | 101 | rc = m_ctlEp->SetInterfaceAlternate(cfg->bInterface, cfg->bAlternate); |
va009039 | 2:c10029b87439 | 102 | TEST_ASSERT_EQUAL(rc, USB_OK); |
va009039 | 2:c10029b87439 | 103 | |
va009039 | 2:c10029b87439 | 104 | rc = m_ctlEp->GetInterface(cfg->bInterface, &alt); |
va009039 | 2:c10029b87439 | 105 | TEST_ASSERT_EQUAL(rc, USB_OK); |
va009039 | 2:c10029b87439 | 106 | DBG("alt: %d\n", alt); |
va009039 | 2:c10029b87439 | 107 | TEST_ASSERT_EQUAL(alt, cfg->bAlternate); |
va009039 | 2:c10029b87439 | 108 | delete cfg; |
va009039 | 2:c10029b87439 | 109 | |
va009039 | 2:c10029b87439 | 110 | for(int i = 0; i < 16; i++) { |
va009039 | 2:c10029b87439 | 111 | report_cc_count[i] = 0; |
va009039 | 2:c10029b87439 | 112 | report_ps_cc_count[i] = 0; |
va009039 | 2:c10029b87439 | 113 | } |
va009039 | 2:c10029b87439 | 114 | |
va009039 | 2:c10029b87439 | 115 | LPC_USB->HcControl |= OR_CONTROL_PLE; // PeriodicListEnable |
va009039 | 2:c10029b87439 | 116 | LPC_USB->HcControl |= OR_CONTROL_IE; // IsochronousEnable |
va009039 | 2:c10029b87439 | 117 | } |
va009039 | 2:c10029b87439 | 118 | |
va009039 | 2:c10029b87439 | 119 | bool UvcCam::check(ControlEp* ctlEp) |
va009039 | 2:c10029b87439 | 120 | { |
va009039 | 2:c10029b87439 | 121 | if (ctlEp == NULL) { |
va009039 | 2:c10029b87439 | 122 | return false; |
va009039 | 2:c10029b87439 | 123 | } |
va009039 | 2:c10029b87439 | 124 | uint8_t buf[18]; |
va009039 | 2:c10029b87439 | 125 | int r = ctlEp->GetDescriptor(1, 0, buf, 8); |
va009039 | 2:c10029b87439 | 126 | if (r != USB_OK) { |
va009039 | 2:c10029b87439 | 127 | return false; |
va009039 | 2:c10029b87439 | 128 | } |
va009039 | 2:c10029b87439 | 129 | DBG_HEX(buf, 8); |
va009039 | 2:c10029b87439 | 130 | const uint8_t desc[] = {0x12,0x01,0x00,0x02,0xef,0x02,0x01}; |
va009039 | 2:c10029b87439 | 131 | if (memcmp(buf, desc, sizeof(desc)) != 0) { |
va009039 | 2:c10029b87439 | 132 | return false; |
va009039 | 2:c10029b87439 | 133 | } |
va009039 | 2:c10029b87439 | 134 | r = ctlEp->GetDescriptor(1, 0, buf, 18); |
va009039 | 2:c10029b87439 | 135 | if (r != USB_OK) { |
va009039 | 2:c10029b87439 | 136 | return false; |
va009039 | 2:c10029b87439 | 137 | } |
va009039 | 2:c10029b87439 | 138 | DBG_HEX(buf, 18); |
va009039 | 2:c10029b87439 | 139 | return true; |
va009039 | 2:c10029b87439 | 140 | } |
va009039 | 2:c10029b87439 | 141 | |
va009039 | 2:c10029b87439 | 142 | #define DESCRIPTOR_TYPE_DEVICE 1 |
va009039 | 2:c10029b87439 | 143 | #define DESCRIPTOR_TYPE_CONFIGURATION 2 |
va009039 | 2:c10029b87439 | 144 | #define DESCRIPTOR_TYPE_STRING 3 |
va009039 | 2:c10029b87439 | 145 | #define DESCRIPTOR_TYPE_INTERFACE 4 |
va009039 | 2:c10029b87439 | 146 | #define DESCRIPTOR_TYPE_ENDPOINT 5 |
va009039 | 2:c10029b87439 | 147 | |
va009039 | 2:c10029b87439 | 148 | #define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b |
va009039 | 2:c10029b87439 | 149 | |
va009039 | 2:c10029b87439 | 150 | #define DESCRIPTOR_TYPE_HID 0x21 |
va009039 | 2:c10029b87439 | 151 | #define DESCRIPTOR_TYPE_REPORT 0x22 |
va009039 | 2:c10029b87439 | 152 | #define DESCRIPTOR_TYPE_PHYSICAL 0x23 |
va009039 | 2:c10029b87439 | 153 | #define DESCRIPTOR_TYPE_CS_INTERFACE 0x24 |
va009039 | 2:c10029b87439 | 154 | #define DESCRIPTOR_TYPE_CS_ENDPOINT 0x25 |
va009039 | 2:c10029b87439 | 155 | #define DESCRIPTOR_TYPE_HUB 0x29 |
va009039 | 2:c10029b87439 | 156 | |
va009039 | 2:c10029b87439 | 157 | #define CLASS_AUDIO 0x02 |
va009039 | 2:c10029b87439 | 158 | #define CLASS_HUB 0x09 |
va009039 | 2:c10029b87439 | 159 | |
va009039 | 2:c10029b87439 | 160 | #define IF_EQ_THEN_PRINTF(A,B) if (A == B) {VERBOSE("%s\n", #A); |
va009039 | 2:c10029b87439 | 161 | #define ENDIF } |
va009039 | 2:c10029b87439 | 162 | |
va009039 | 2:c10029b87439 | 163 | #define CC_AUDIO 0x01 |
va009039 | 2:c10029b87439 | 164 | #define SC_AUDIOCONTROL 0x01 |
va009039 | 2:c10029b87439 | 165 | #define SC_AUDIOSTREAMING 0x02 |
va009039 | 2:c10029b87439 | 166 | |
va009039 | 2:c10029b87439 | 167 | #define AC_HEADER 0x01 |
va009039 | 2:c10029b87439 | 168 | #define AC_INPUT_TERMINAL 0x02 |
va009039 | 2:c10029b87439 | 169 | #define AC_OUTPUT_TERMINAL 0x03 |
va009039 | 2:c10029b87439 | 170 | #define AC_FEATURE_UNIT 0x06 |
va009039 | 2:c10029b87439 | 171 | |
va009039 | 2:c10029b87439 | 172 | // Input Terminal Types |
va009039 | 2:c10029b87439 | 173 | #define ITT_CAMERA 0x0201 |
va009039 | 2:c10029b87439 | 174 | |
va009039 | 2:c10029b87439 | 175 | static int LE16(const uint8_t* d) |
va009039 | 2:c10029b87439 | 176 | { |
va009039 | 2:c10029b87439 | 177 | return d[0] | (d[1] << 8); |
va009039 | 2:c10029b87439 | 178 | } |
va009039 | 2:c10029b87439 | 179 | |
va009039 | 2:c10029b87439 | 180 | static int LE24(const uint8_t* d) { |
va009039 | 2:c10029b87439 | 181 | return d[0] | (d[1]<<8) | (d[2] << 16); |
va009039 | 2:c10029b87439 | 182 | } |
va009039 | 2:c10029b87439 | 183 | |
va009039 | 2:c10029b87439 | 184 | static int LE32(const uint8_t* d) { |
va009039 | 2:c10029b87439 | 185 | return d[0] |(d[1]<<8) | (d[2] << 16) |(d[3] << 24) ; |
va009039 | 2:c10029b87439 | 186 | } |
va009039 | 2:c10029b87439 | 187 | |
va009039 | 2:c10029b87439 | 188 | UvcCfg::UvcCfg(int formatIndex, int frameIndex, ControlEp* ctlEp):wMaxPacketSize(0) |
va009039 | 2:c10029b87439 | 189 | { |
va009039 | 2:c10029b87439 | 190 | TEST_ASSERT(ctlEp); |
va009039 | 2:c10029b87439 | 191 | switch(formatIndex) { |
va009039 | 2:c10029b87439 | 192 | case UVC_MJPEG: _payload = UVC_MJPEG; break; |
va009039 | 2:c10029b87439 | 193 | case UVC_YUY2: _payload = UVC_YUY2; break; |
va009039 | 2:c10029b87439 | 194 | default: _payload = UVC_MJPEG; break; |
va009039 | 2:c10029b87439 | 195 | } |
va009039 | 2:c10029b87439 | 196 | |
va009039 | 2:c10029b87439 | 197 | switch(frameIndex) { |
va009039 | 2:c10029b87439 | 198 | case UVC_160x120: _width = 160; _height = 120; break; |
va009039 | 2:c10029b87439 | 199 | case UVC_176x144: _width = 176; _height = 144; break; |
va009039 | 2:c10029b87439 | 200 | case UVC_320x176: _width = 320; _height = 176; break; |
va009039 | 2:c10029b87439 | 201 | case UVC_320x240: _width = 320; _height = 240; break; |
va009039 | 2:c10029b87439 | 202 | case UVC_352x288: _width = 352; _height = 288; break; |
va009039 | 2:c10029b87439 | 203 | case UVC_432x240: _width = 432; _height = 240; break; |
va009039 | 2:c10029b87439 | 204 | case UVC_640x480: _width = 640; _height = 480; break; |
va009039 | 2:c10029b87439 | 205 | case UVC_544x288: _width = 544; _height = 288; break; |
va009039 | 2:c10029b87439 | 206 | case UVC_640x360: _width = 640; _height = 360; break; |
va009039 | 2:c10029b87439 | 207 | case UVC_752x416: _width = 752; _height = 416; break; |
va009039 | 2:c10029b87439 | 208 | case UVC_800x448: _width = 800; _height = 448; break; |
va009039 | 2:c10029b87439 | 209 | case UVC_800x600: _width = 800; _height = 600; break; |
va009039 | 2:c10029b87439 | 210 | default: _width = 160; _height = 120; break; |
va009039 | 2:c10029b87439 | 211 | } |
va009039 | 2:c10029b87439 | 212 | int index = 0; |
va009039 | 2:c10029b87439 | 213 | uint8_t temp[4]; |
va009039 | 2:c10029b87439 | 214 | int rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, temp, sizeof(temp)); |
va009039 | 2:c10029b87439 | 215 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 216 | DBG_BYTES("Config Descriptor 4bytes", temp, sizeof(temp)); |
va009039 | 2:c10029b87439 | 217 | TEST_ASSERT(temp[0] == 9); |
va009039 | 2:c10029b87439 | 218 | TEST_ASSERT(temp[1] == 0x02); |
va009039 | 2:c10029b87439 | 219 | int TotalLength = LE16(temp+2); |
va009039 | 2:c10029b87439 | 220 | DBG("TotalLength: %d\n", TotalLength); |
va009039 | 2:c10029b87439 | 221 | |
va009039 | 2:c10029b87439 | 222 | uint8_t* buf = new uint8_t[TotalLength]; |
va009039 | 2:c10029b87439 | 223 | TEST_ASSERT(buf); |
va009039 | 2:c10029b87439 | 224 | rc = ctlEp->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, buf, TotalLength); |
va009039 | 2:c10029b87439 | 225 | TEST_ASSERT(rc == USB_OK); |
va009039 | 2:c10029b87439 | 226 | if (rc != USB_OK) { |
va009039 | 2:c10029b87439 | 227 | delete[] buf; |
va009039 | 2:c10029b87439 | 228 | return; |
va009039 | 2:c10029b87439 | 229 | } |
va009039 | 2:c10029b87439 | 230 | _parserConfigurationDescriptor(buf, TotalLength); |
va009039 | 2:c10029b87439 | 231 | delete[] buf; |
va009039 | 2:c10029b87439 | 232 | } |
va009039 | 2:c10029b87439 | 233 | |
va009039 | 2:c10029b87439 | 234 | void UvcCfg::_parserAudioControl(uint8_t* buf, int len) { |
va009039 | 2:c10029b87439 | 235 | int subtype = buf[2]; |
va009039 | 2:c10029b87439 | 236 | IF_EQ_THEN_PRINTF(AC_HEADER, subtype) |
va009039 | 2:c10029b87439 | 237 | VERBOSE("ADC: %04x\n", LE16(buf+3)); |
va009039 | 2:c10029b87439 | 238 | VERBOSE("TotalLength: %d\n", LE16(buf+5)); |
va009039 | 2:c10029b87439 | 239 | VERBOSE("InCollection: %d\n", buf[7]); |
va009039 | 2:c10029b87439 | 240 | for (int n = 1; n <= buf[7]; n++) { |
va009039 | 2:c10029b87439 | 241 | VERBOSE("aInterfaceNr(%d): %d\n", n, buf[8+n-1]); |
va009039 | 2:c10029b87439 | 242 | } |
va009039 | 2:c10029b87439 | 243 | ENDIF |
va009039 | 2:c10029b87439 | 244 | IF_EQ_THEN_PRINTF(AC_INPUT_TERMINAL, subtype) |
va009039 | 2:c10029b87439 | 245 | VERBOSE("TerminalID: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 246 | VERBOSE("TerminalType: %04X\n", LE16(buf+4)); |
va009039 | 2:c10029b87439 | 247 | VERBOSE("AssocTermianl: %d\n", buf[6]); |
va009039 | 2:c10029b87439 | 248 | VERBOSE("NrChannels: %d\n", buf[7]); |
va009039 | 2:c10029b87439 | 249 | ENDIF |
va009039 | 2:c10029b87439 | 250 | IF_EQ_THEN_PRINTF(AC_OUTPUT_TERMINAL, subtype) |
va009039 | 2:c10029b87439 | 251 | VERBOSE("TerminalID: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 252 | VERBOSE("TerminalType: %04X\n", LE16(buf+4)); |
va009039 | 2:c10029b87439 | 253 | VERBOSE("AssocTermianl: %d\n", buf[6]); |
va009039 | 2:c10029b87439 | 254 | ENDIF |
va009039 | 2:c10029b87439 | 255 | IF_EQ_THEN_PRINTF(AC_FEATURE_UNIT, subtype) |
va009039 | 2:c10029b87439 | 256 | VERBOSE("UnitID: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 257 | VERBOSE("SourceID: %d\n", buf[4]); |
va009039 | 2:c10029b87439 | 258 | VERBOSE("ControlSize: %d\n", buf[5]); |
va009039 | 2:c10029b87439 | 259 | ENDIF |
va009039 | 2:c10029b87439 | 260 | } |
va009039 | 2:c10029b87439 | 261 | |
va009039 | 2:c10029b87439 | 262 | #define AS_GENERAL 0x01 |
va009039 | 2:c10029b87439 | 263 | #define AS_FORMAT_TYPE 0x02 |
va009039 | 2:c10029b87439 | 264 | |
va009039 | 2:c10029b87439 | 265 | void UvcCfg::_parserAudioStream(uint8_t* buf, int len) { |
va009039 | 2:c10029b87439 | 266 | int subtype = buf[2]; |
va009039 | 2:c10029b87439 | 267 | IF_EQ_THEN_PRINTF(AS_GENERAL, subtype) |
va009039 | 2:c10029b87439 | 268 | VERBOSE("TerminalLink: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 269 | VERBOSE("Delay: %d\n", buf[4]); |
va009039 | 2:c10029b87439 | 270 | VERBOSE("FormatTag: %04x\n", LE16(buf+5)); |
va009039 | 2:c10029b87439 | 271 | ENDIF |
va009039 | 2:c10029b87439 | 272 | IF_EQ_THEN_PRINTF(AS_FORMAT_TYPE, subtype) |
va009039 | 2:c10029b87439 | 273 | VERBOSE("FormatType: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 274 | VERBOSE("NrChannels: %d\n", buf[4]); |
va009039 | 2:c10029b87439 | 275 | VERBOSE("SubFrameSize: %d\n", buf[5]); |
va009039 | 2:c10029b87439 | 276 | VERBOSE("BitResolution: %d\n", buf[6]); |
va009039 | 2:c10029b87439 | 277 | VERBOSE("SamFreqType: %d\n", buf[7]); |
va009039 | 2:c10029b87439 | 278 | VERBOSE("SamFreq(1): %d\n", LE24(buf+8)); |
va009039 | 2:c10029b87439 | 279 | ENDIF |
va009039 | 2:c10029b87439 | 280 | } |
va009039 | 2:c10029b87439 | 281 | |
va009039 | 2:c10029b87439 | 282 | #define CC_VIDEO 0x0e |
va009039 | 2:c10029b87439 | 283 | |
va009039 | 2:c10029b87439 | 284 | #define SC_VIDEOCONTROL 0x01 |
va009039 | 2:c10029b87439 | 285 | #define SC_VIDEOSTREAMING 0x02 |
va009039 | 2:c10029b87439 | 286 | |
va009039 | 2:c10029b87439 | 287 | #define VC_HEADER 0x01 |
va009039 | 2:c10029b87439 | 288 | #define VC_INPUT_TERMINAL 0x02 |
va009039 | 2:c10029b87439 | 289 | #define VC_OUTPUT_TERMINAL 0x03 |
va009039 | 2:c10029b87439 | 290 | #define VC_SELECTOR_UNIT 0x04 |
va009039 | 2:c10029b87439 | 291 | #define VC_PROCESSING_UNIT 0x05 |
va009039 | 2:c10029b87439 | 292 | #define VC_EXTENSION_UNIT 0x06 |
va009039 | 2:c10029b87439 | 293 | |
va009039 | 2:c10029b87439 | 294 | void UvcCfg::_parserVideoControl(uint8_t* buf, int len) { |
va009039 | 2:c10029b87439 | 295 | int subtype = buf[2]; |
va009039 | 2:c10029b87439 | 296 | IF_EQ_THEN_PRINTF(VC_HEADER, subtype) |
va009039 | 2:c10029b87439 | 297 | bcdUVC = LE16(buf+3); |
va009039 | 2:c10029b87439 | 298 | VERBOSE("UVC: %04x\n", bcdUVC); |
va009039 | 2:c10029b87439 | 299 | VERBOSE("TotalLength: %d\n", LE16(buf+5)); |
va009039 | 2:c10029b87439 | 300 | VERBOSE("ClockFrequency: %d\n", LE32(buf+7)); |
va009039 | 2:c10029b87439 | 301 | VERBOSE("InCollection: %d\n", buf[11]); |
va009039 | 2:c10029b87439 | 302 | VERBOSE("aInterfaceNr(1): %d\n", buf[12]); |
va009039 | 2:c10029b87439 | 303 | ENDIF |
va009039 | 2:c10029b87439 | 304 | IF_EQ_THEN_PRINTF(VC_INPUT_TERMINAL, subtype) |
va009039 | 2:c10029b87439 | 305 | VERBOSE("TerminalID: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 306 | uint16_t tt = LE16(buf+4); |
va009039 | 2:c10029b87439 | 307 | VERBOSE("TerminalType: %04X\n", tt); |
va009039 | 2:c10029b87439 | 308 | VERBOSE("AssocTerminal: %d\n", buf[6]); |
va009039 | 2:c10029b87439 | 309 | VERBOSE("Terminal: %d\n", buf[7]); |
va009039 | 2:c10029b87439 | 310 | if (tt == ITT_CAMERA) { // camera |
va009039 | 2:c10029b87439 | 311 | int bControlSize = buf[14]; |
va009039 | 2:c10029b87439 | 312 | VERBOSE("ControlSize: %d\n", bControlSize); |
va009039 | 2:c10029b87439 | 313 | for(int i = 0; i < bControlSize; i++) { |
va009039 | 2:c10029b87439 | 314 | uint8_t bControls = buf[15+i]; |
va009039 | 2:c10029b87439 | 315 | VERBOSE("Controls(%d): %02X\n", i, bControls); |
va009039 | 2:c10029b87439 | 316 | } |
va009039 | 2:c10029b87439 | 317 | } |
va009039 | 2:c10029b87439 | 318 | ENDIF |
va009039 | 2:c10029b87439 | 319 | IF_EQ_THEN_PRINTF(VC_OUTPUT_TERMINAL, subtype) |
va009039 | 2:c10029b87439 | 320 | VERBOSE("TerminalID: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 321 | VERBOSE("TerminalType: %04X\n", LE16(buf+4)); |
va009039 | 2:c10029b87439 | 322 | VERBOSE("AssocTerminal: %d\n", buf[6]); |
va009039 | 2:c10029b87439 | 323 | VERBOSE("SourceID: %d\n", buf[7]); |
va009039 | 2:c10029b87439 | 324 | VERBOSE("Terminal: %d\n", buf[8]); |
va009039 | 2:c10029b87439 | 325 | ENDIF |
va009039 | 2:c10029b87439 | 326 | IF_EQ_THEN_PRINTF(VC_SELECTOR_UNIT, subtype) |
va009039 | 2:c10029b87439 | 327 | VERBOSE("UnitID: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 328 | ENDIF |
va009039 | 2:c10029b87439 | 329 | IF_EQ_THEN_PRINTF(VC_PROCESSING_UNIT, subtype) |
va009039 | 2:c10029b87439 | 330 | VERBOSE("UnitID: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 331 | VERBOSE("SourceID: %d\n", buf[4]); |
va009039 | 2:c10029b87439 | 332 | VERBOSE("MaxMultiplier: %d\n", LE16(buf+5)); |
va009039 | 2:c10029b87439 | 333 | VERBOSE("ControlSize: %d\n", buf[7]); |
va009039 | 2:c10029b87439 | 334 | int pos = 8; |
va009039 | 2:c10029b87439 | 335 | for (int n = 1; n <= buf[7]; n++) { |
va009039 | 2:c10029b87439 | 336 | VERBOSE("Controls(%d): %02X\n", n , buf[pos]); |
va009039 | 2:c10029b87439 | 337 | pos++; |
va009039 | 2:c10029b87439 | 338 | } |
va009039 | 2:c10029b87439 | 339 | VERBOSE("Processing: %d\n", buf[pos]); |
va009039 | 2:c10029b87439 | 340 | pos++; |
va009039 | 2:c10029b87439 | 341 | VERBOSE("VideoStanders: %02X\n", buf[pos]); |
va009039 | 2:c10029b87439 | 342 | ENDIF |
va009039 | 2:c10029b87439 | 343 | IF_EQ_THEN_PRINTF(VC_EXTENSION_UNIT, subtype) |
va009039 | 2:c10029b87439 | 344 | VERBOSE("UnitID: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 345 | ENDIF |
va009039 | 2:c10029b87439 | 346 | } |
va009039 | 2:c10029b87439 | 347 | |
va009039 | 2:c10029b87439 | 348 | #define VS_INPUT_HEADER 0x01 |
va009039 | 2:c10029b87439 | 349 | #define VS_STILL_FRAME 0x03 |
va009039 | 2:c10029b87439 | 350 | #define VS_FORMAT_UNCOMPRESSED 0x04 |
va009039 | 2:c10029b87439 | 351 | #define VS_FRAME_UNCOMPRESSED 0x05 |
va009039 | 2:c10029b87439 | 352 | #define VS_FORMAT_MJPEG 0x06 |
va009039 | 2:c10029b87439 | 353 | #define VS_FRAME_MJPEG 0x07 |
va009039 | 2:c10029b87439 | 354 | #define VS_COLOR_FORMAT 0x0d |
va009039 | 2:c10029b87439 | 355 | |
va009039 | 2:c10029b87439 | 356 | void UvcCfg::_parserVideoStream(uint8_t* buf, int len) { |
va009039 | 2:c10029b87439 | 357 | int subtype = buf[2]; |
va009039 | 2:c10029b87439 | 358 | IF_EQ_THEN_PRINTF(VS_INPUT_HEADER, subtype) |
va009039 | 2:c10029b87439 | 359 | VERBOSE("NumFormats: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 360 | VERBOSE("TotalLength: %d\n", LE16(buf+4)); |
va009039 | 2:c10029b87439 | 361 | VERBOSE("EndpointAddress: %02X\n", buf[6]); |
va009039 | 2:c10029b87439 | 362 | VERBOSE("Info: %02X\n", buf[7]); |
va009039 | 2:c10029b87439 | 363 | VERBOSE("TerminalLink: %d\n", buf[8]); |
va009039 | 2:c10029b87439 | 364 | VERBOSE("StillCaptureMethod: %d\n", buf[9]); |
va009039 | 2:c10029b87439 | 365 | VERBOSE("TriggerSupport: %d\n", buf[10]); |
va009039 | 2:c10029b87439 | 366 | VERBOSE("TriggerUsage: %d\n", buf[11]); |
va009039 | 2:c10029b87439 | 367 | VERBOSE("ControlSize: %d\n", buf[12]); |
va009039 | 2:c10029b87439 | 368 | int pos = 13; |
va009039 | 2:c10029b87439 | 369 | for (int n = 1; n <= buf[12]; n++) { |
va009039 | 2:c10029b87439 | 370 | VERBOSE("Controls(%d): %02X\n", n, buf[pos]); |
va009039 | 2:c10029b87439 | 371 | pos++; |
va009039 | 2:c10029b87439 | 372 | } |
va009039 | 2:c10029b87439 | 373 | bEndpointAddress = buf[6]; |
va009039 | 2:c10029b87439 | 374 | ENDIF |
va009039 | 2:c10029b87439 | 375 | IF_EQ_THEN_PRINTF(VS_STILL_FRAME, subtype) |
va009039 | 2:c10029b87439 | 376 | VERBOSE("EndpointAdress: %02X\n", buf[3]); |
va009039 | 2:c10029b87439 | 377 | VERBOSE("NumImageSizePatterns: %d\n", buf[4]); |
va009039 | 2:c10029b87439 | 378 | int ptn = buf[4]; |
va009039 | 2:c10029b87439 | 379 | int pos = 5; |
va009039 | 2:c10029b87439 | 380 | for (int n = 1; n <= ptn; n++) { |
va009039 | 2:c10029b87439 | 381 | VERBOSE("Width(%d): %d\n", n, LE16(buf+pos)); |
va009039 | 2:c10029b87439 | 382 | VERBOSE("Height(%d): %d\n", n, LE16(buf+pos+2)); |
va009039 | 2:c10029b87439 | 383 | pos += 4; |
va009039 | 2:c10029b87439 | 384 | } |
va009039 | 2:c10029b87439 | 385 | VERBOSE("NumCompressPtn: %d\n", buf[pos]); |
va009039 | 2:c10029b87439 | 386 | ptn = buf[pos++]; |
va009039 | 2:c10029b87439 | 387 | for (int n = 1; n <= ptn; n++) { |
va009039 | 2:c10029b87439 | 388 | VERBOSE("Compress(%d): %d\n", n, buf[pos]); |
va009039 | 2:c10029b87439 | 389 | pos++; |
va009039 | 2:c10029b87439 | 390 | } |
va009039 | 2:c10029b87439 | 391 | ENDIF |
va009039 | 2:c10029b87439 | 392 | IF_EQ_THEN_PRINTF(VS_FORMAT_UNCOMPRESSED, subtype) |
va009039 | 2:c10029b87439 | 393 | VERBOSE("FormatIndex: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 394 | VERBOSE("NumFrameDescriptors: %d\n", buf[4]); |
va009039 | 2:c10029b87439 | 395 | uint32_t guid = LE32(buf+5); |
va009039 | 2:c10029b87439 | 396 | if (guid == 0x32595559) { |
va009039 | 2:c10029b87439 | 397 | VERBOSE("GUID: YUY2\n"); |
va009039 | 2:c10029b87439 | 398 | } else if (guid == 0x3231564e) { |
va009039 | 2:c10029b87439 | 399 | VERBOSE("GUID: NV12\n"); |
va009039 | 2:c10029b87439 | 400 | } else { |
va009039 | 2:c10029b87439 | 401 | VERBOSE("GUID: %08x\n", guid); |
va009039 | 2:c10029b87439 | 402 | } |
va009039 | 2:c10029b87439 | 403 | VERBOSE("DefaultFrameIndex: %d\n", buf[22]); |
va009039 | 2:c10029b87439 | 404 | if (_payload == UVC_YUY2) { |
va009039 | 2:c10029b87439 | 405 | FormatIndex = buf[3]; |
va009039 | 2:c10029b87439 | 406 | } |
va009039 | 2:c10029b87439 | 407 | ENDIF |
va009039 | 2:c10029b87439 | 408 | IF_EQ_THEN_PRINTF(VS_FRAME_UNCOMPRESSED, subtype) |
va009039 | 2:c10029b87439 | 409 | VERBOSE("FrameIndex: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 410 | VERBOSE("Capabilites: %d\n", buf[4]); |
va009039 | 2:c10029b87439 | 411 | VERBOSE("Width: %d\n", LE16(buf+5)); |
va009039 | 2:c10029b87439 | 412 | VERBOSE("Height: %d\n", LE16(buf+7)); |
va009039 | 2:c10029b87439 | 413 | VERBOSE("MinBitRate: %d\n", LE32(buf+9)); |
va009039 | 2:c10029b87439 | 414 | VERBOSE("MaxBitRate: %d\n", LE32(buf+13)); |
va009039 | 2:c10029b87439 | 415 | VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17)); |
va009039 | 2:c10029b87439 | 416 | VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21)); |
va009039 | 2:c10029b87439 | 417 | VERBOSE("FrameIntervalType: %d\n", buf[25]); |
va009039 | 2:c10029b87439 | 418 | int it = buf[25]; |
va009039 | 2:c10029b87439 | 419 | uint32_t max_fi = 333333; // 30.0fps |
va009039 | 2:c10029b87439 | 420 | if (it == 0) { |
va009039 | 2:c10029b87439 | 421 | VERBOSE("FrameMinInterval: %d\n", buf[26]); |
va009039 | 2:c10029b87439 | 422 | VERBOSE("FrameMaxInterval: %d\n", buf[30]); |
va009039 | 2:c10029b87439 | 423 | VERBOSE("FrameIntervalStep: %d\n", buf[34]); |
va009039 | 2:c10029b87439 | 424 | } else { |
va009039 | 2:c10029b87439 | 425 | int pos = 26; |
va009039 | 2:c10029b87439 | 426 | for (int n = 1; n <= it; n++) { |
va009039 | 2:c10029b87439 | 427 | uint32_t fi = LE32(buf+pos); |
va009039 | 2:c10029b87439 | 428 | if (fi >= max_fi) { |
va009039 | 2:c10029b87439 | 429 | max_fi = fi; |
va009039 | 2:c10029b87439 | 430 | } |
va009039 | 2:c10029b87439 | 431 | float fps = 1e+7 / fi; |
va009039 | 2:c10029b87439 | 432 | VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps); |
va009039 | 2:c10029b87439 | 433 | pos += 4; |
va009039 | 2:c10029b87439 | 434 | } |
va009039 | 2:c10029b87439 | 435 | } |
va009039 | 2:c10029b87439 | 436 | if (_payload == UVC_YUY2) { |
va009039 | 2:c10029b87439 | 437 | if (_width == LE16(buf+5) && _height == LE16(buf+7)) { |
va009039 | 2:c10029b87439 | 438 | FrameIndex = buf[3]; |
va009039 | 2:c10029b87439 | 439 | } |
va009039 | 2:c10029b87439 | 440 | if (dwFrameInterval == 0) { |
va009039 | 2:c10029b87439 | 441 | dwFrameInterval = max_fi; |
va009039 | 2:c10029b87439 | 442 | } |
va009039 | 2:c10029b87439 | 443 | } |
va009039 | 2:c10029b87439 | 444 | ENDIF |
va009039 | 2:c10029b87439 | 445 | IF_EQ_THEN_PRINTF(VS_FORMAT_MJPEG, subtype) |
va009039 | 2:c10029b87439 | 446 | VERBOSE("FormatIndex: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 447 | VERBOSE("NumFrameDescriptors: %d\n", buf[4]); |
va009039 | 2:c10029b87439 | 448 | VERBOSE("Flags: %d\n", buf[5]); |
va009039 | 2:c10029b87439 | 449 | VERBOSE("DefaultFrameIndex: %d\n", buf[6]); |
va009039 | 2:c10029b87439 | 450 | if (_payload == UVC_MJPEG) { |
va009039 | 2:c10029b87439 | 451 | FormatIndex = buf[3]; |
va009039 | 2:c10029b87439 | 452 | } |
va009039 | 2:c10029b87439 | 453 | ENDIF |
va009039 | 2:c10029b87439 | 454 | IF_EQ_THEN_PRINTF(VS_FRAME_MJPEG, subtype) |
va009039 | 2:c10029b87439 | 455 | VERBOSE("FrameIndex: %d\n", buf[3]); |
va009039 | 2:c10029b87439 | 456 | VERBOSE("Capabilites: %d\n", buf[4]); |
va009039 | 2:c10029b87439 | 457 | VERBOSE("Width: %d\n", LE16(buf+5)); |
va009039 | 2:c10029b87439 | 458 | VERBOSE("Height: %d\n", LE16(buf+7)); |
va009039 | 2:c10029b87439 | 459 | VERBOSE("MinBitRate: %d\n", LE32(buf+9)); |
va009039 | 2:c10029b87439 | 460 | VERBOSE("MaxBitRate: %d\n", LE32(buf+13)); |
va009039 | 2:c10029b87439 | 461 | VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17)); |
va009039 | 2:c10029b87439 | 462 | VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21)); |
va009039 | 2:c10029b87439 | 463 | VERBOSE("FrameIntervalType: %d\n", buf[25]); |
va009039 | 2:c10029b87439 | 464 | int it = buf[25]; |
va009039 | 2:c10029b87439 | 465 | uint32_t max_fi = 333333; // 30.0fps |
va009039 | 2:c10029b87439 | 466 | if (it == 0) { |
va009039 | 2:c10029b87439 | 467 | VERBOSE("FrameMinInterval: %d\n", buf[26]); |
va009039 | 2:c10029b87439 | 468 | VERBOSE("FrameMaxInterval: %d\n", buf[30]); |
va009039 | 2:c10029b87439 | 469 | VERBOSE("FrameIntervalStep: %d\n", buf[34]); |
va009039 | 2:c10029b87439 | 470 | } else { |
va009039 | 2:c10029b87439 | 471 | int pos = 26; |
va009039 | 2:c10029b87439 | 472 | for (int n = 1; n <= it; n++) { |
va009039 | 2:c10029b87439 | 473 | uint32_t fi = LE32(buf+pos); |
va009039 | 2:c10029b87439 | 474 | if (fi >= max_fi) { |
va009039 | 2:c10029b87439 | 475 | max_fi = fi; |
va009039 | 2:c10029b87439 | 476 | } |
va009039 | 2:c10029b87439 | 477 | float fps = 1e+7 / fi; |
va009039 | 2:c10029b87439 | 478 | VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps); |
va009039 | 2:c10029b87439 | 479 | pos += 4; |
va009039 | 2:c10029b87439 | 480 | } |
va009039 | 2:c10029b87439 | 481 | } |
va009039 | 2:c10029b87439 | 482 | if (_payload == UVC_MJPEG) { |
va009039 | 2:c10029b87439 | 483 | if (_width == LE16(buf+5) && _height == LE16(buf+7)) { |
va009039 | 2:c10029b87439 | 484 | FrameIndex = buf[3]; |
va009039 | 2:c10029b87439 | 485 | } |
va009039 | 2:c10029b87439 | 486 | if (dwFrameInterval == 0) { |
va009039 | 2:c10029b87439 | 487 | dwFrameInterval = max_fi; |
va009039 | 2:c10029b87439 | 488 | } |
va009039 | 2:c10029b87439 | 489 | } |
va009039 | 2:c10029b87439 | 490 | ENDIF |
va009039 | 2:c10029b87439 | 491 | IF_EQ_THEN_PRINTF(VS_COLOR_FORMAT, subtype) |
va009039 | 2:c10029b87439 | 492 | ENDIF |
va009039 | 2:c10029b87439 | 493 | } |
va009039 | 2:c10029b87439 | 494 | |
va009039 | 2:c10029b87439 | 495 | void UvcCfg::_parserConfigurationDescriptor(uint8_t* buf, int len) { |
va009039 | 2:c10029b87439 | 496 | int pos = 0; |
va009039 | 2:c10029b87439 | 497 | _IfClass = 0; |
va009039 | 2:c10029b87439 | 498 | _IfSubClass = 0; |
va009039 | 2:c10029b87439 | 499 | while (pos < len) { |
va009039 | 2:c10029b87439 | 500 | int type = buf[pos+1]; |
va009039 | 2:c10029b87439 | 501 | //DBG_BYTES(TYPE_Str(type), buf+pos, buf[pos]); |
va009039 | 2:c10029b87439 | 502 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CONFIGURATION, type) |
va009039 | 2:c10029b87439 | 503 | VERBOSE("NumInterfaces: %d\n", buf[pos+4]); |
va009039 | 2:c10029b87439 | 504 | ENDIF |
va009039 | 2:c10029b87439 | 505 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, type) |
va009039 | 2:c10029b87439 | 506 | VERBOSE("FirstInterface: %d\n", buf[pos+2]); |
va009039 | 2:c10029b87439 | 507 | VERBOSE("InterfaceCount: %d\n", buf[pos+3]); |
va009039 | 2:c10029b87439 | 508 | VERBOSE("FunctionClass: %02X\n", buf[pos+4]); |
va009039 | 2:c10029b87439 | 509 | VERBOSE("FunctionSubClass: %02X\n", buf[pos+5]); |
va009039 | 2:c10029b87439 | 510 | VERBOSE("FunctionProtocol: %02X\n", buf[pos+6]); |
va009039 | 2:c10029b87439 | 511 | VERBOSE("Function: %d\n", buf[pos+7]); |
va009039 | 2:c10029b87439 | 512 | ENDIF |
va009039 | 2:c10029b87439 | 513 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE,type) |
va009039 | 2:c10029b87439 | 514 | VERBOSE("InterfaceNumber: %d\n", buf[pos+2]); |
va009039 | 2:c10029b87439 | 515 | VERBOSE("AlternateSetting: %d\n", buf[pos+3]); |
va009039 | 2:c10029b87439 | 516 | VERBOSE("NumEndpoint: %d\n", buf[pos+4]); |
va009039 | 2:c10029b87439 | 517 | VERBOSE("InterfaceClass: %02X\n", buf[pos+5]); |
va009039 | 2:c10029b87439 | 518 | VERBOSE("InterfaceSubClass: %02X\n", buf[pos+6]); |
va009039 | 2:c10029b87439 | 519 | VERBOSE("InterfaceProtocol: %02X\n", buf[pos+7]); |
va009039 | 2:c10029b87439 | 520 | VERBOSE("Interface: %d\n", buf[pos+8]); |
va009039 | 2:c10029b87439 | 521 | _If = buf[pos+2]; |
va009039 | 2:c10029b87439 | 522 | _Ifalt = buf[pos+3]; |
va009039 | 2:c10029b87439 | 523 | _IfClass = buf[pos+5]; |
va009039 | 2:c10029b87439 | 524 | _IfSubClass = buf[pos+6]; |
va009039 | 2:c10029b87439 | 525 | ENDIF |
va009039 | 2:c10029b87439 | 526 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_ENDPOINT, type) |
va009039 | 2:c10029b87439 | 527 | VERBOSE("EndpointAddress: %02X\n", buf[pos+2]); |
va009039 | 2:c10029b87439 | 528 | VERBOSE("Attributes: %02X\n", buf[pos+3]); |
va009039 | 2:c10029b87439 | 529 | VERBOSE("MaxPacketSize: %d\n", LE16(buf+pos+4)); |
va009039 | 2:c10029b87439 | 530 | VERBOSE("Interval: %d\n", buf[pos+6]); |
va009039 | 2:c10029b87439 | 531 | if (_IfClass == CC_VIDEO && _IfSubClass == SC_VIDEOSTREAMING) { |
va009039 | 2:c10029b87439 | 532 | if (bEndpointAddress == buf[pos+2]) { |
va009039 | 2:c10029b87439 | 533 | if (wMaxPacketSize == 0) { |
va009039 | 2:c10029b87439 | 534 | wMaxPacketSize = LE16(buf+pos+4); |
va009039 | 2:c10029b87439 | 535 | } |
va009039 | 2:c10029b87439 | 536 | if (wMaxPacketSize == LE16(buf+pos+4)) { |
va009039 | 2:c10029b87439 | 537 | bInterface = _If; |
va009039 | 2:c10029b87439 | 538 | bAlternate = _Ifalt; |
va009039 | 2:c10029b87439 | 539 | } |
va009039 | 2:c10029b87439 | 540 | } |
va009039 | 2:c10029b87439 | 541 | } |
va009039 | 2:c10029b87439 | 542 | ENDIF |
va009039 | 2:c10029b87439 | 543 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CS_INTERFACE, type) |
va009039 | 2:c10029b87439 | 544 | IF_EQ_THEN_PRINTF(CC_VIDEO, _IfClass) |
va009039 | 2:c10029b87439 | 545 | IF_EQ_THEN_PRINTF(SC_VIDEOCONTROL, _IfSubClass) |
va009039 | 2:c10029b87439 | 546 | _parserVideoControl(buf+pos, buf[pos]); |
va009039 | 2:c10029b87439 | 547 | ENDIF |
va009039 | 2:c10029b87439 | 548 | IF_EQ_THEN_PRINTF(SC_VIDEOSTREAMING, _IfSubClass) |
va009039 | 2:c10029b87439 | 549 | _parserVideoStream(buf+pos, buf[pos]); |
va009039 | 2:c10029b87439 | 550 | ENDIF |
va009039 | 2:c10029b87439 | 551 | ENDIF |
va009039 | 2:c10029b87439 | 552 | IF_EQ_THEN_PRINTF(CC_AUDIO, _IfClass) |
va009039 | 2:c10029b87439 | 553 | IF_EQ_THEN_PRINTF(SC_AUDIOCONTROL, _IfSubClass) |
va009039 | 2:c10029b87439 | 554 | _parserAudioControl(buf+pos, buf[pos]); |
va009039 | 2:c10029b87439 | 555 | ENDIF |
va009039 | 2:c10029b87439 | 556 | IF_EQ_THEN_PRINTF(SC_AUDIOSTREAMING, _IfSubClass) |
va009039 | 2:c10029b87439 | 557 | _parserAudioStream(buf+pos, buf[pos]); |
va009039 | 2:c10029b87439 | 558 | ENDIF |
va009039 | 2:c10029b87439 | 559 | ENDIF |
va009039 | 2:c10029b87439 | 560 | ENDIF |
va009039 | 2:c10029b87439 | 561 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_HUB, type) |
va009039 | 2:c10029b87439 | 562 | ENDIF |
va009039 | 2:c10029b87439 | 563 | pos += buf[pos]; |
va009039 | 2:c10029b87439 | 564 | } |
va009039 | 2:c10029b87439 | 565 | } |
va009039 | 2:c10029b87439 | 566 |