Webcam Server.

Dependencies:   uvchost FatFileSystem mbed HTTPServer NetServicesMin

Committer:
va009039
Date:
Wed Jun 06 11:47:06 2012 +0000
Revision:
0:2b4ea8a138e5

        

Who changed what in which revision?

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