UVC host library
Dependents: LifeCam WebcamServer
uvc/uvccfg.cpp@3:3eb41d749f9a, 2012-08-15 (annotated)
- 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?
User | Revision | Line number | New contents of line |
---|---|---|---|
va009039 | 0:b0f04c137829 | 1 | #include "mbed.h" |
va009039 | 0:b0f04c137829 | 2 | #include "uvc.h" |
va009039 | 0:b0f04c137829 | 3 | #define __DEBUG |
va009039 | 0:b0f04c137829 | 4 | #include "mydbg.h" |
va009039 | 0:b0f04c137829 | 5 | #include "stcamcfg.h" |
va009039 | 0:b0f04c137829 | 6 | #include "Utils.h" |
va009039 | 0:b0f04c137829 | 7 | |
va009039 | 0:b0f04c137829 | 8 | #define DESCRIPTOR_TYPE_DEVICE 1 |
va009039 | 0:b0f04c137829 | 9 | #define DESCRIPTOR_TYPE_CONFIGURATION 2 |
va009039 | 0:b0f04c137829 | 10 | #define DESCRIPTOR_TYPE_STRING 3 |
va009039 | 0:b0f04c137829 | 11 | #define DESCRIPTOR_TYPE_INTERFACE 4 |
va009039 | 0:b0f04c137829 | 12 | #define DESCRIPTOR_TYPE_ENDPOINT 5 |
va009039 | 0:b0f04c137829 | 13 | |
va009039 | 0:b0f04c137829 | 14 | #define DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b |
va009039 | 0:b0f04c137829 | 15 | |
va009039 | 0:b0f04c137829 | 16 | #define DESCRIPTOR_TYPE_HID 0x21 |
va009039 | 0:b0f04c137829 | 17 | #define DESCRIPTOR_TYPE_REPORT 0x22 |
va009039 | 0:b0f04c137829 | 18 | #define DESCRIPTOR_TYPE_PHYSICAL 0x23 |
va009039 | 0:b0f04c137829 | 19 | #define DESCRIPTOR_TYPE_CS_INTERFACE 0x24 |
va009039 | 0:b0f04c137829 | 20 | #define DESCRIPTOR_TYPE_CS_ENDPOINT 0x25 |
va009039 | 0:b0f04c137829 | 21 | #define DESCRIPTOR_TYPE_HUB 0x29 |
va009039 | 0:b0f04c137829 | 22 | |
va009039 | 0:b0f04c137829 | 23 | #define CLASS_AUDIO 0x02 |
va009039 | 0:b0f04c137829 | 24 | #define CLASS_HUB 0x09 |
va009039 | 0:b0f04c137829 | 25 | |
va009039 | 0:b0f04c137829 | 26 | #define IF_EQ_THEN_PRINTF(A,B) if (A == B) {VERBOSE("%s\n", #A); |
va009039 | 0:b0f04c137829 | 27 | #define ENDIF } |
va009039 | 0:b0f04c137829 | 28 | |
va009039 | 0:b0f04c137829 | 29 | #define CC_AUDIO 0x01 |
va009039 | 0:b0f04c137829 | 30 | #define SC_AUDIOCONTROL 0x01 |
va009039 | 0:b0f04c137829 | 31 | #define SC_AUDIOSTREAMING 0x02 |
va009039 | 0:b0f04c137829 | 32 | |
va009039 | 0:b0f04c137829 | 33 | #define AC_HEADER 0x01 |
va009039 | 0:b0f04c137829 | 34 | #define AC_INPUT_TERMINAL 0x02 |
va009039 | 0:b0f04c137829 | 35 | #define AC_OUTPUT_TERMINAL 0x03 |
va009039 | 0:b0f04c137829 | 36 | #define AC_FEATURE_UNIT 0x06 |
va009039 | 0:b0f04c137829 | 37 | |
va009039 | 0:b0f04c137829 | 38 | // Input Terminal Types |
va009039 | 0:b0f04c137829 | 39 | #define ITT_CAMERA 0x0201 |
va009039 | 0:b0f04c137829 | 40 | |
va009039 | 0:b0f04c137829 | 41 | |
va009039 | 0:b0f04c137829 | 42 | void _parserAudioControl(uint8_t* buf, int len) { |
va009039 | 0:b0f04c137829 | 43 | int subtype = buf[2]; |
va009039 | 0:b0f04c137829 | 44 | IF_EQ_THEN_PRINTF(AC_HEADER, subtype) |
va009039 | 0:b0f04c137829 | 45 | VERBOSE("ADC: %04x\n", LE16(buf+3)); |
va009039 | 0:b0f04c137829 | 46 | VERBOSE("TotalLength: %d\n", LE16(buf+5)); |
va009039 | 0:b0f04c137829 | 47 | VERBOSE("InCollection: %d\n", buf[7]); |
va009039 | 0:b0f04c137829 | 48 | for (int n = 1; n <= buf[7]; n++) { |
va009039 | 0:b0f04c137829 | 49 | VERBOSE("aInterfaceNr(%d): %d\n", n, buf[8+n-1]); |
va009039 | 0:b0f04c137829 | 50 | } |
va009039 | 0:b0f04c137829 | 51 | ENDIF |
va009039 | 0:b0f04c137829 | 52 | IF_EQ_THEN_PRINTF(AC_INPUT_TERMINAL, subtype) |
va009039 | 0:b0f04c137829 | 53 | VERBOSE("TerminalID: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 54 | VERBOSE("TerminalType: %04X\n", LE16(buf+4)); |
va009039 | 0:b0f04c137829 | 55 | VERBOSE("AssocTermianl: %d\n", buf[6]); |
va009039 | 0:b0f04c137829 | 56 | VERBOSE("NrChannels: %d\n", buf[7]); |
va009039 | 0:b0f04c137829 | 57 | ENDIF |
va009039 | 0:b0f04c137829 | 58 | IF_EQ_THEN_PRINTF(AC_OUTPUT_TERMINAL, subtype) |
va009039 | 0:b0f04c137829 | 59 | VERBOSE("TerminalID: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 60 | VERBOSE("TerminalType: %04X\n", LE16(buf+4)); |
va009039 | 0:b0f04c137829 | 61 | VERBOSE("AssocTermianl: %d\n", buf[6]); |
va009039 | 0:b0f04c137829 | 62 | ENDIF |
va009039 | 0:b0f04c137829 | 63 | IF_EQ_THEN_PRINTF(AC_FEATURE_UNIT, subtype) |
va009039 | 0:b0f04c137829 | 64 | VERBOSE("UnitID: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 65 | VERBOSE("SourceID: %d\n", buf[4]); |
va009039 | 0:b0f04c137829 | 66 | VERBOSE("ControlSize: %d\n", buf[5]); |
va009039 | 0:b0f04c137829 | 67 | ENDIF |
va009039 | 0:b0f04c137829 | 68 | } |
va009039 | 0:b0f04c137829 | 69 | |
va009039 | 0:b0f04c137829 | 70 | #define AS_GENERAL 0x01 |
va009039 | 0:b0f04c137829 | 71 | #define AS_FORMAT_TYPE 0x02 |
va009039 | 0:b0f04c137829 | 72 | |
va009039 | 0:b0f04c137829 | 73 | void _parserAudioStream(uint8_t* buf, int len) { |
va009039 | 0:b0f04c137829 | 74 | int subtype = buf[2]; |
va009039 | 0:b0f04c137829 | 75 | IF_EQ_THEN_PRINTF(AS_GENERAL, subtype) |
va009039 | 0:b0f04c137829 | 76 | VERBOSE("TerminalLink: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 77 | VERBOSE("Delay: %d\n", buf[4]); |
va009039 | 0:b0f04c137829 | 78 | VERBOSE("FormatTag: %04x\n", LE16(buf+5)); |
va009039 | 0:b0f04c137829 | 79 | ENDIF |
va009039 | 0:b0f04c137829 | 80 | IF_EQ_THEN_PRINTF(AS_FORMAT_TYPE, subtype) |
va009039 | 0:b0f04c137829 | 81 | VERBOSE("FormatType: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 82 | VERBOSE("NrChannels: %d\n", buf[4]); |
va009039 | 0:b0f04c137829 | 83 | VERBOSE("SubFrameSize: %d\n", buf[5]); |
va009039 | 0:b0f04c137829 | 84 | VERBOSE("BitResolution: %d\n", buf[6]); |
va009039 | 0:b0f04c137829 | 85 | VERBOSE("SamFreqType: %d\n", buf[7]); |
va009039 | 0:b0f04c137829 | 86 | VERBOSE("SamFreq(1): %d\n", LE24(buf+8)); |
va009039 | 0:b0f04c137829 | 87 | ENDIF |
va009039 | 0:b0f04c137829 | 88 | } |
va009039 | 0:b0f04c137829 | 89 | |
va009039 | 0:b0f04c137829 | 90 | #define CC_VIDEO 0x0e |
va009039 | 0:b0f04c137829 | 91 | |
va009039 | 0:b0f04c137829 | 92 | #define SC_VIDEOCONTROL 0x01 |
va009039 | 0:b0f04c137829 | 93 | #define SC_VIDEOSTREAMING 0x02 |
va009039 | 0:b0f04c137829 | 94 | |
va009039 | 0:b0f04c137829 | 95 | #define VC_HEADER 0x01 |
va009039 | 0:b0f04c137829 | 96 | #define VC_INPUT_TERMINAL 0x02 |
va009039 | 0:b0f04c137829 | 97 | #define VC_OUTPUT_TERMINAL 0x03 |
va009039 | 0:b0f04c137829 | 98 | #define VC_SELECTOR_UNIT 0x04 |
va009039 | 0:b0f04c137829 | 99 | #define VC_PROCESSING_UNIT 0x05 |
va009039 | 0:b0f04c137829 | 100 | #define VC_EXTENSION_UNIT 0x06 |
va009039 | 0:b0f04c137829 | 101 | |
va009039 | 0:b0f04c137829 | 102 | void _parserVideoControl(struct stcamcfg* cfg, uint8_t* buf, int len) { |
va009039 | 0:b0f04c137829 | 103 | int subtype = buf[2]; |
va009039 | 0:b0f04c137829 | 104 | IF_EQ_THEN_PRINTF(VC_HEADER, subtype) |
va009039 | 0:b0f04c137829 | 105 | cfg->bcdUVC = LE16(buf+3); |
va009039 | 0:b0f04c137829 | 106 | VERBOSE("UVC: %04x\n", cfg->bcdUVC); |
va009039 | 0:b0f04c137829 | 107 | VERBOSE("TotalLength: %d\n", LE16(buf+5)); |
va009039 | 0:b0f04c137829 | 108 | VERBOSE("ClockFrequency: %d\n", LE32(buf+7)); |
va009039 | 0:b0f04c137829 | 109 | VERBOSE("InCollection: %d\n", buf[11]); |
va009039 | 0:b0f04c137829 | 110 | VERBOSE("aInterfaceNr(1): %d\n", buf[12]); |
va009039 | 0:b0f04c137829 | 111 | ENDIF |
va009039 | 0:b0f04c137829 | 112 | IF_EQ_THEN_PRINTF(VC_INPUT_TERMINAL, subtype) |
va009039 | 0:b0f04c137829 | 113 | VERBOSE("TerminalID: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 114 | uint16_t tt = LE16(buf+4); |
va009039 | 0:b0f04c137829 | 115 | VERBOSE("TerminalType: %04X\n", tt); |
va009039 | 0:b0f04c137829 | 116 | VERBOSE("AssocTerminal: %d\n", buf[6]); |
va009039 | 0:b0f04c137829 | 117 | VERBOSE("Terminal: %d\n", buf[7]); |
va009039 | 0:b0f04c137829 | 118 | if (tt == ITT_CAMERA) { // camera |
va009039 | 0:b0f04c137829 | 119 | int bControlSize = buf[14]; |
va009039 | 0:b0f04c137829 | 120 | VERBOSE("ControlSize: %d\n", bControlSize); |
va009039 | 0:b0f04c137829 | 121 | for(int i = 0; i < bControlSize; i++) { |
va009039 | 0:b0f04c137829 | 122 | uint8_t bControls = buf[15+i]; |
va009039 | 0:b0f04c137829 | 123 | VERBOSE("Controls(%d): %02X\n", i, bControls); |
va009039 | 0:b0f04c137829 | 124 | } |
va009039 | 0:b0f04c137829 | 125 | } |
va009039 | 0:b0f04c137829 | 126 | ENDIF |
va009039 | 0:b0f04c137829 | 127 | IF_EQ_THEN_PRINTF(VC_OUTPUT_TERMINAL, subtype) |
va009039 | 0:b0f04c137829 | 128 | VERBOSE("TerminalID: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 129 | VERBOSE("TerminalType: %04X\n", LE16(buf+4)); |
va009039 | 0:b0f04c137829 | 130 | VERBOSE("AssocTerminal: %d\n", buf[6]); |
va009039 | 0:b0f04c137829 | 131 | VERBOSE("SourceID: %d\n", buf[7]); |
va009039 | 0:b0f04c137829 | 132 | VERBOSE("Terminal: %d\n", buf[8]); |
va009039 | 0:b0f04c137829 | 133 | ENDIF |
va009039 | 0:b0f04c137829 | 134 | IF_EQ_THEN_PRINTF(VC_SELECTOR_UNIT, subtype) |
va009039 | 0:b0f04c137829 | 135 | VERBOSE("UnitID: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 136 | ENDIF |
va009039 | 0:b0f04c137829 | 137 | IF_EQ_THEN_PRINTF(VC_PROCESSING_UNIT, subtype) |
va009039 | 0:b0f04c137829 | 138 | VERBOSE("UnitID: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 139 | VERBOSE("SourceID: %d\n", buf[4]); |
va009039 | 0:b0f04c137829 | 140 | VERBOSE("MaxMultiplier: %d\n", LE16(buf+5)); |
va009039 | 0:b0f04c137829 | 141 | VERBOSE("ControlSize: %d\n", buf[7]); |
va009039 | 0:b0f04c137829 | 142 | int pos = 8; |
va009039 | 0:b0f04c137829 | 143 | for (int n = 1; n <= buf[7]; n++) { |
va009039 | 0:b0f04c137829 | 144 | VERBOSE("Controls(%d): %02X\n", n , buf[pos]); |
va009039 | 0:b0f04c137829 | 145 | pos++; |
va009039 | 0:b0f04c137829 | 146 | } |
va009039 | 0:b0f04c137829 | 147 | VERBOSE("Processing: %d\n", buf[pos]); |
va009039 | 0:b0f04c137829 | 148 | pos++; |
va009039 | 0:b0f04c137829 | 149 | VERBOSE("VideoStanders: %02X\n", buf[pos]); |
va009039 | 0:b0f04c137829 | 150 | ENDIF |
va009039 | 0:b0f04c137829 | 151 | IF_EQ_THEN_PRINTF(VC_EXTENSION_UNIT, subtype) |
va009039 | 0:b0f04c137829 | 152 | VERBOSE("UnitID: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 153 | ENDIF |
va009039 | 0:b0f04c137829 | 154 | } |
va009039 | 0:b0f04c137829 | 155 | |
va009039 | 0:b0f04c137829 | 156 | #define VS_INPUT_HEADER 0x01 |
va009039 | 0:b0f04c137829 | 157 | #define VS_STILL_FRAME 0x03 |
va009039 | 0:b0f04c137829 | 158 | #define VS_FORMAT_UNCOMPRESSED 0x04 |
va009039 | 0:b0f04c137829 | 159 | #define VS_FRAME_UNCOMPRESSED 0x05 |
va009039 | 0:b0f04c137829 | 160 | #define VS_FORMAT_MJPEG 0x06 |
va009039 | 0:b0f04c137829 | 161 | #define VS_FRAME_MJPEG 0x07 |
va009039 | 0:b0f04c137829 | 162 | #define VS_COLOR_FORMAT 0x0d |
va009039 | 0:b0f04c137829 | 163 | |
va009039 | 0:b0f04c137829 | 164 | void _parserVideoStream(struct stcamcfg* cfg, uint8_t* buf, int len) { |
va009039 | 0:b0f04c137829 | 165 | int subtype = buf[2]; |
va009039 | 0:b0f04c137829 | 166 | IF_EQ_THEN_PRINTF(VS_INPUT_HEADER, subtype) |
va009039 | 0:b0f04c137829 | 167 | VERBOSE("NumFormats: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 168 | VERBOSE("TotalLength: %d\n", LE16(buf+4)); |
va009039 | 0:b0f04c137829 | 169 | VERBOSE("EndpointAddress: %02X\n", buf[6]); |
va009039 | 0:b0f04c137829 | 170 | VERBOSE("Info: %02X\n", buf[7]); |
va009039 | 0:b0f04c137829 | 171 | VERBOSE("TerminalLink: %d\n", buf[8]); |
va009039 | 0:b0f04c137829 | 172 | VERBOSE("StillCaptureMethod: %d\n", buf[9]); |
va009039 | 0:b0f04c137829 | 173 | VERBOSE("TriggerSupport: %d\n", buf[10]); |
va009039 | 0:b0f04c137829 | 174 | VERBOSE("TriggerUsage: %d\n", buf[11]); |
va009039 | 0:b0f04c137829 | 175 | VERBOSE("ControlSize: %d\n", buf[12]); |
va009039 | 0:b0f04c137829 | 176 | int pos = 13; |
va009039 | 0:b0f04c137829 | 177 | for (int n = 1; n <= buf[12]; n++) { |
va009039 | 0:b0f04c137829 | 178 | VERBOSE("Controls(%d): %02X\n", n, buf[pos]); |
va009039 | 0:b0f04c137829 | 179 | pos++; |
va009039 | 0:b0f04c137829 | 180 | } |
va009039 | 0:b0f04c137829 | 181 | cfg->bEndpointAddress = buf[6]; |
va009039 | 0:b0f04c137829 | 182 | ENDIF |
va009039 | 0:b0f04c137829 | 183 | IF_EQ_THEN_PRINTF(VS_STILL_FRAME, subtype) |
va009039 | 0:b0f04c137829 | 184 | VERBOSE("EndpointAdress: %02X\n", buf[3]); |
va009039 | 0:b0f04c137829 | 185 | VERBOSE("NumImageSizePatterns: %d\n", buf[4]); |
va009039 | 0:b0f04c137829 | 186 | int ptn = buf[4]; |
va009039 | 0:b0f04c137829 | 187 | int pos = 5; |
va009039 | 0:b0f04c137829 | 188 | for (int n = 1; n <= ptn; n++) { |
va009039 | 0:b0f04c137829 | 189 | VERBOSE("Width(%d): %d\n", n, LE16(buf+pos)); |
va009039 | 0:b0f04c137829 | 190 | VERBOSE("Height(%d): %d\n", n, LE16(buf+pos+2)); |
va009039 | 0:b0f04c137829 | 191 | pos += 4; |
va009039 | 0:b0f04c137829 | 192 | } |
va009039 | 0:b0f04c137829 | 193 | VERBOSE("NumCompressPtn: %d\n", buf[pos]); |
va009039 | 0:b0f04c137829 | 194 | ptn = buf[pos++]; |
va009039 | 0:b0f04c137829 | 195 | for (int n = 1; n <= ptn; n++) { |
va009039 | 0:b0f04c137829 | 196 | VERBOSE("Compress(%d): %d\n", n, buf[pos]); |
va009039 | 0:b0f04c137829 | 197 | pos++; |
va009039 | 0:b0f04c137829 | 198 | } |
va009039 | 0:b0f04c137829 | 199 | ENDIF |
va009039 | 0:b0f04c137829 | 200 | IF_EQ_THEN_PRINTF(VS_FORMAT_UNCOMPRESSED, subtype) |
va009039 | 0:b0f04c137829 | 201 | VERBOSE("FormatIndex: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 202 | VERBOSE("NumFrameDescriptors: %d\n", buf[4]); |
va009039 | 0:b0f04c137829 | 203 | uint32_t guid = LE32(buf+5); |
va009039 | 0:b0f04c137829 | 204 | if (guid == 0x32595559) { |
va009039 | 0:b0f04c137829 | 205 | VERBOSE("GUID: YUY2\n"); |
va009039 | 0:b0f04c137829 | 206 | } else if (guid == 0x3231564e) { |
va009039 | 0:b0f04c137829 | 207 | VERBOSE("GUID: NV12\n"); |
va009039 | 0:b0f04c137829 | 208 | } else { |
va009039 | 0:b0f04c137829 | 209 | VERBOSE("GUID: %08x\n", guid); |
va009039 | 0:b0f04c137829 | 210 | } |
va009039 | 0:b0f04c137829 | 211 | VERBOSE("DefaultFrameIndex: %d\n", buf[22]); |
va009039 | 0:b0f04c137829 | 212 | if (cfg->payload == PAYLOAD_YUY2) { |
va009039 | 0:b0f04c137829 | 213 | cfg->FormatIndex = buf[3]; |
va009039 | 0:b0f04c137829 | 214 | } |
va009039 | 0:b0f04c137829 | 215 | ENDIF |
va009039 | 0:b0f04c137829 | 216 | IF_EQ_THEN_PRINTF(VS_FRAME_UNCOMPRESSED, subtype) |
va009039 | 0:b0f04c137829 | 217 | VERBOSE("FrameIndex: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 218 | VERBOSE("Capabilites: %d\n", buf[4]); |
va009039 | 0:b0f04c137829 | 219 | VERBOSE("Width: %d\n", LE16(buf+5)); |
va009039 | 0:b0f04c137829 | 220 | VERBOSE("Height: %d\n", LE16(buf+7)); |
va009039 | 0:b0f04c137829 | 221 | VERBOSE("MinBitRate: %d\n", LE32(buf+9)); |
va009039 | 0:b0f04c137829 | 222 | VERBOSE("MaxBitRate: %d\n", LE32(buf+13)); |
va009039 | 0:b0f04c137829 | 223 | VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17)); |
va009039 | 0:b0f04c137829 | 224 | VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21)); |
va009039 | 0:b0f04c137829 | 225 | VERBOSE("FrameIntervalType: %d\n", buf[25]); |
va009039 | 0:b0f04c137829 | 226 | int it = buf[25]; |
va009039 | 0:b0f04c137829 | 227 | uint32_t max_fi = 333333; // 30.0fps |
va009039 | 0:b0f04c137829 | 228 | if (it == 0) { |
va009039 | 0:b0f04c137829 | 229 | VERBOSE("FrameMinInterval: %d\n", buf[26]); |
va009039 | 0:b0f04c137829 | 230 | VERBOSE("FrameMaxInterval: %d\n", buf[30]); |
va009039 | 0:b0f04c137829 | 231 | VERBOSE("FrameIntervalStep: %d\n", buf[34]); |
va009039 | 0:b0f04c137829 | 232 | } else { |
va009039 | 0:b0f04c137829 | 233 | int pos = 26; |
va009039 | 0:b0f04c137829 | 234 | for (int n = 1; n <= it; n++) { |
va009039 | 0:b0f04c137829 | 235 | uint32_t fi = LE32(buf+pos); |
va009039 | 0:b0f04c137829 | 236 | if (fi >= max_fi) { |
va009039 | 0:b0f04c137829 | 237 | max_fi = fi; |
va009039 | 0:b0f04c137829 | 238 | } |
va009039 | 0:b0f04c137829 | 239 | float fps = 1e+7 / fi; |
va009039 | 0:b0f04c137829 | 240 | VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps); |
va009039 | 0:b0f04c137829 | 241 | pos += 4; |
va009039 | 0:b0f04c137829 | 242 | } |
va009039 | 0:b0f04c137829 | 243 | } |
va009039 | 0:b0f04c137829 | 244 | if (cfg->payload == PAYLOAD_YUY2) { |
va009039 | 0:b0f04c137829 | 245 | if (cfg->width == LE16(buf+5) && cfg->height == LE16(buf+7)) { |
va009039 | 0:b0f04c137829 | 246 | cfg->FrameIndex = buf[3]; |
va009039 | 0:b0f04c137829 | 247 | } |
va009039 | 0:b0f04c137829 | 248 | if (cfg->dwFrameInterval == 0) { |
va009039 | 0:b0f04c137829 | 249 | cfg->dwFrameInterval = max_fi; |
va009039 | 0:b0f04c137829 | 250 | } |
va009039 | 0:b0f04c137829 | 251 | } |
va009039 | 0:b0f04c137829 | 252 | ENDIF |
va009039 | 0:b0f04c137829 | 253 | IF_EQ_THEN_PRINTF(VS_FORMAT_MJPEG, subtype) |
va009039 | 0:b0f04c137829 | 254 | VERBOSE("FormatIndex: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 255 | VERBOSE("NumFrameDescriptors: %d\n", buf[4]); |
va009039 | 0:b0f04c137829 | 256 | VERBOSE("Flags: %d\n", buf[5]); |
va009039 | 0:b0f04c137829 | 257 | VERBOSE("DefaultFrameIndex: %d\n", buf[6]); |
va009039 | 0:b0f04c137829 | 258 | if (cfg->payload == PAYLOAD_MJPEG) { |
va009039 | 0:b0f04c137829 | 259 | cfg->FormatIndex = buf[3]; |
va009039 | 0:b0f04c137829 | 260 | } |
va009039 | 0:b0f04c137829 | 261 | ENDIF |
va009039 | 0:b0f04c137829 | 262 | IF_EQ_THEN_PRINTF(VS_FRAME_MJPEG, subtype) |
va009039 | 0:b0f04c137829 | 263 | VERBOSE("FrameIndex: %d\n", buf[3]); |
va009039 | 0:b0f04c137829 | 264 | VERBOSE("Capabilites: %d\n", buf[4]); |
va009039 | 0:b0f04c137829 | 265 | VERBOSE("Width: %d\n", LE16(buf+5)); |
va009039 | 0:b0f04c137829 | 266 | VERBOSE("Height: %d\n", LE16(buf+7)); |
va009039 | 0:b0f04c137829 | 267 | VERBOSE("MinBitRate: %d\n", LE32(buf+9)); |
va009039 | 0:b0f04c137829 | 268 | VERBOSE("MaxBitRate: %d\n", LE32(buf+13)); |
va009039 | 0:b0f04c137829 | 269 | VERBOSE("MaxVideoFrameBufferSize: %d\n", LE32(buf+17)); |
va009039 | 0:b0f04c137829 | 270 | VERBOSE("DefaultFrameInterval: %d\n", LE32(buf+21)); |
va009039 | 0:b0f04c137829 | 271 | VERBOSE("FrameIntervalType: %d\n", buf[25]); |
va009039 | 0:b0f04c137829 | 272 | int it = buf[25]; |
va009039 | 0:b0f04c137829 | 273 | uint32_t max_fi = 333333; // 30.0fps |
va009039 | 0:b0f04c137829 | 274 | if (it == 0) { |
va009039 | 0:b0f04c137829 | 275 | VERBOSE("FrameMinInterval: %d\n", buf[26]); |
va009039 | 0:b0f04c137829 | 276 | VERBOSE("FrameMaxInterval: %d\n", buf[30]); |
va009039 | 0:b0f04c137829 | 277 | VERBOSE("FrameIntervalStep: %d\n", buf[34]); |
va009039 | 0:b0f04c137829 | 278 | } else { |
va009039 | 0:b0f04c137829 | 279 | int pos = 26; |
va009039 | 0:b0f04c137829 | 280 | for (int n = 1; n <= it; n++) { |
va009039 | 0:b0f04c137829 | 281 | uint32_t fi = LE32(buf+pos); |
va009039 | 0:b0f04c137829 | 282 | if (fi >= max_fi) { |
va009039 | 0:b0f04c137829 | 283 | max_fi = fi; |
va009039 | 0:b0f04c137829 | 284 | } |
va009039 | 0:b0f04c137829 | 285 | float fps = 1e+7 / fi; |
va009039 | 0:b0f04c137829 | 286 | VERBOSE("FrameInterval(%u): %d (%.1f fps)\n", n, fi, fps); |
va009039 | 0:b0f04c137829 | 287 | pos += 4; |
va009039 | 0:b0f04c137829 | 288 | } |
va009039 | 0:b0f04c137829 | 289 | } |
va009039 | 0:b0f04c137829 | 290 | if (cfg->payload == PAYLOAD_MJPEG) { |
va009039 | 0:b0f04c137829 | 291 | if (cfg->width == LE16(buf+5) && cfg->height == LE16(buf+7)) { |
va009039 | 0:b0f04c137829 | 292 | cfg->FrameIndex = buf[3]; |
va009039 | 0:b0f04c137829 | 293 | } |
va009039 | 0:b0f04c137829 | 294 | if (cfg->dwFrameInterval == 0) { |
va009039 | 0:b0f04c137829 | 295 | cfg->dwFrameInterval = max_fi; |
va009039 | 0:b0f04c137829 | 296 | } |
va009039 | 0:b0f04c137829 | 297 | } |
va009039 | 0:b0f04c137829 | 298 | ENDIF |
va009039 | 0:b0f04c137829 | 299 | IF_EQ_THEN_PRINTF(VS_COLOR_FORMAT, subtype) |
va009039 | 0:b0f04c137829 | 300 | ENDIF |
va009039 | 0:b0f04c137829 | 301 | } |
va009039 | 0:b0f04c137829 | 302 | |
va009039 | 0:b0f04c137829 | 303 | void _parserConfigurationDescriptor(struct stcamcfg* cfg, uint8_t* buf, int len) { |
va009039 | 0:b0f04c137829 | 304 | //DBG("buf=%p len=%d\n", buf, len); |
va009039 | 0:b0f04c137829 | 305 | //DBG_HEX(buf, len); |
va009039 | 0:b0f04c137829 | 306 | int pos = 0; |
va009039 | 0:b0f04c137829 | 307 | cfg->_IfClass = 0; |
va009039 | 0:b0f04c137829 | 308 | cfg->_IfSubClass = 0; |
va009039 | 0:b0f04c137829 | 309 | while (pos < len) { |
va009039 | 0:b0f04c137829 | 310 | int type = buf[pos+1]; |
va009039 | 0:b0f04c137829 | 311 | //DBG_BYTES(TYPE_Str(type), buf+pos, buf[pos]); |
va009039 | 0:b0f04c137829 | 312 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CONFIGURATION, type) |
va009039 | 0:b0f04c137829 | 313 | VERBOSE("NumInterfaces: %d\n", buf[pos+4]); |
va009039 | 0:b0f04c137829 | 314 | ENDIF |
va009039 | 0:b0f04c137829 | 315 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION, type) |
va009039 | 0:b0f04c137829 | 316 | VERBOSE("FirstInterface: %d\n", buf[pos+2]); |
va009039 | 0:b0f04c137829 | 317 | VERBOSE("InterfaceCount: %d\n", buf[pos+3]); |
va009039 | 0:b0f04c137829 | 318 | VERBOSE("FunctionClass: %02X\n", buf[pos+4]); |
va009039 | 0:b0f04c137829 | 319 | VERBOSE("FunctionSubClass: %02X\n", buf[pos+5]); |
va009039 | 0:b0f04c137829 | 320 | VERBOSE("FunctionProtocol: %02X\n", buf[pos+6]); |
va009039 | 0:b0f04c137829 | 321 | VERBOSE("Function: %d\n", buf[pos+7]); |
va009039 | 0:b0f04c137829 | 322 | ENDIF |
va009039 | 0:b0f04c137829 | 323 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_INTERFACE,type) |
va009039 | 0:b0f04c137829 | 324 | VERBOSE("InterfaceNumber: %d\n", buf[pos+2]); |
va009039 | 0:b0f04c137829 | 325 | VERBOSE("AlternateSetting: %d\n", buf[pos+3]); |
va009039 | 0:b0f04c137829 | 326 | VERBOSE("NumEndpoint: %d\n", buf[pos+4]); |
va009039 | 0:b0f04c137829 | 327 | VERBOSE("InterfaceClass: %02X\n", buf[pos+5]); |
va009039 | 0:b0f04c137829 | 328 | VERBOSE("InterfaceSubClass: %02X\n", buf[pos+6]); |
va009039 | 0:b0f04c137829 | 329 | VERBOSE("InterfaceProtocol: %02X\n", buf[pos+7]); |
va009039 | 0:b0f04c137829 | 330 | VERBOSE("Interface: %d\n", buf[pos+8]); |
va009039 | 0:b0f04c137829 | 331 | cfg->_If = buf[pos+2]; |
va009039 | 0:b0f04c137829 | 332 | cfg->_Ifalt = buf[pos+3]; |
va009039 | 0:b0f04c137829 | 333 | cfg->_IfClass = buf[pos+5]; |
va009039 | 0:b0f04c137829 | 334 | cfg->_IfSubClass = buf[pos+6]; |
va009039 | 0:b0f04c137829 | 335 | ENDIF |
va009039 | 0:b0f04c137829 | 336 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_ENDPOINT, type) |
va009039 | 0:b0f04c137829 | 337 | VERBOSE("EndpointAddress: %02X\n", buf[pos+2]); |
va009039 | 0:b0f04c137829 | 338 | VERBOSE("Attributes: %02X\n", buf[pos+3]); |
va009039 | 0:b0f04c137829 | 339 | VERBOSE("MaxPacketSize: %d\n", LE16(buf+pos+4)); |
va009039 | 0:b0f04c137829 | 340 | VERBOSE("Interval: %d\n", buf[pos+6]); |
va009039 | 0:b0f04c137829 | 341 | if (cfg->_IfClass == CC_VIDEO && cfg->_IfSubClass == SC_VIDEOSTREAMING) { |
va009039 | 0:b0f04c137829 | 342 | if (cfg->bEndpointAddress == buf[pos+2]) { |
va009039 | 0:b0f04c137829 | 343 | if (cfg->wMaxPacketSize == 0) { |
va009039 | 0:b0f04c137829 | 344 | cfg->wMaxPacketSize = LE16(buf+pos+4); |
va009039 | 0:b0f04c137829 | 345 | } |
va009039 | 0:b0f04c137829 | 346 | if (cfg->wMaxPacketSize == LE16(buf+pos+4)) { |
va009039 | 0:b0f04c137829 | 347 | cfg->bInterface = cfg->_If; |
va009039 | 0:b0f04c137829 | 348 | cfg->bAlternate = cfg->_Ifalt; |
va009039 | 0:b0f04c137829 | 349 | } |
va009039 | 0:b0f04c137829 | 350 | } |
va009039 | 0:b0f04c137829 | 351 | } |
va009039 | 0:b0f04c137829 | 352 | ENDIF |
va009039 | 0:b0f04c137829 | 353 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_CS_INTERFACE, type) |
va009039 | 0:b0f04c137829 | 354 | IF_EQ_THEN_PRINTF(CC_VIDEO, cfg->_IfClass) |
va009039 | 0:b0f04c137829 | 355 | IF_EQ_THEN_PRINTF(SC_VIDEOCONTROL, cfg->_IfSubClass) |
va009039 | 0:b0f04c137829 | 356 | _parserVideoControl(cfg, buf+pos, buf[pos]); |
va009039 | 0:b0f04c137829 | 357 | ENDIF |
va009039 | 0:b0f04c137829 | 358 | IF_EQ_THEN_PRINTF(SC_VIDEOSTREAMING, cfg->_IfSubClass) |
va009039 | 0:b0f04c137829 | 359 | _parserVideoStream(cfg, buf+pos, buf[pos]); |
va009039 | 0:b0f04c137829 | 360 | ENDIF |
va009039 | 0:b0f04c137829 | 361 | ENDIF |
va009039 | 0:b0f04c137829 | 362 | IF_EQ_THEN_PRINTF(CC_AUDIO, cfg->_IfClass) |
va009039 | 0:b0f04c137829 | 363 | IF_EQ_THEN_PRINTF(SC_AUDIOCONTROL, cfg->_IfSubClass) |
va009039 | 0:b0f04c137829 | 364 | _parserAudioControl(buf+pos, buf[pos]); |
va009039 | 0:b0f04c137829 | 365 | ENDIF |
va009039 | 0:b0f04c137829 | 366 | IF_EQ_THEN_PRINTF(SC_AUDIOSTREAMING, cfg->_IfSubClass) |
va009039 | 0:b0f04c137829 | 367 | _parserAudioStream(buf+pos, buf[pos]); |
va009039 | 0:b0f04c137829 | 368 | ENDIF |
va009039 | 0:b0f04c137829 | 369 | ENDIF |
va009039 | 0:b0f04c137829 | 370 | ENDIF |
va009039 | 0:b0f04c137829 | 371 | IF_EQ_THEN_PRINTF(DESCRIPTOR_TYPE_HUB, type) |
va009039 | 0:b0f04c137829 | 372 | ENDIF |
va009039 | 0:b0f04c137829 | 373 | pos += buf[pos]; |
va009039 | 0:b0f04c137829 | 374 | } |
va009039 | 0:b0f04c137829 | 375 | } |
va009039 | 0:b0f04c137829 | 376 | |
va009039 | 0:b0f04c137829 | 377 | void uvc::_config(struct stcamcfg* cfg) |
va009039 | 0:b0f04c137829 | 378 | { |
va009039 | 0:b0f04c137829 | 379 | DBG_ASSERT(cfg); |
va009039 | 0:b0f04c137829 | 380 | int index = 0; |
va009039 | 0:b0f04c137829 | 381 | uint8_t temp[4]; |
va009039 | 0:b0f04c137829 | 382 | int rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, temp, sizeof(temp)); |
va009039 | 0:b0f04c137829 | 383 | DBG_ASSERT(rc == USBERR_OK); |
va009039 | 0:b0f04c137829 | 384 | DBG_BYTES("Config Descriptor 4bytes", temp, sizeof(temp)); |
va009039 | 0:b0f04c137829 | 385 | DBG_ASSERT(temp[0] == 9); |
va009039 | 0:b0f04c137829 | 386 | DBG_ASSERT(temp[1] == 0x02); |
va009039 | 0:b0f04c137829 | 387 | int TotalLength = LE16(temp+2); |
va009039 | 0:b0f04c137829 | 388 | DBG("TotalLength: %d\n", TotalLength); |
va009039 | 0:b0f04c137829 | 389 | |
va009039 | 0:b0f04c137829 | 390 | uint8_t* buf = new uint8_t[TotalLength]; |
va009039 | 0:b0f04c137829 | 391 | DBG_ASSERT(buf); |
va009039 | 0:b0f04c137829 | 392 | rc = m_pDev->GetDescriptor(USB_DESCRIPTOR_TYPE_CONFIGURATION, index, |
va009039 | 0:b0f04c137829 | 393 | buf, TotalLength); |
va009039 | 0:b0f04c137829 | 394 | DBG_ASSERT(rc == USBERR_OK); |
va009039 | 0:b0f04c137829 | 395 | |
va009039 | 0:b0f04c137829 | 396 | _parserConfigurationDescriptor(cfg, buf, TotalLength); |
va009039 | 0:b0f04c137829 | 397 | |
va009039 | 0:b0f04c137829 | 398 | DBG("cfg->FormatIndex=%d\n", cfg->FormatIndex); |
va009039 | 0:b0f04c137829 | 399 | DBG("cfg->FrameIndex=%d\n", cfg->FrameIndex); |
va009039 | 0:b0f04c137829 | 400 | DBG("cfg->dwFrameInterval=%u\n", cfg->dwFrameInterval); |
va009039 | 0:b0f04c137829 | 401 | |
va009039 | 0:b0f04c137829 | 402 | //DBG_ASSERT(cfg->FormatIndex >= 1); |
va009039 | 0:b0f04c137829 | 403 | //DBG_ASSERT(cfg->FormatIndex <= 2); |
va009039 | 0:b0f04c137829 | 404 | //DBG_ASSERT(cfg->FrameIndex >= 1); |
va009039 | 0:b0f04c137829 | 405 | //DBG_ASSERT(cfg->FrameIndex <= 6); |
va009039 | 0:b0f04c137829 | 406 | |
va009039 | 0:b0f04c137829 | 407 | delete[] buf; |
va009039 | 0:b0f04c137829 | 408 | } |