cleanup, added uvc descriptor structures, work in progress.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40352 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* Copyright 2011, Haiku Inc. All Rights Reserved.
|
||||
* Copyright 2009, Ithamar Adema, <[email protected]>.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _USB_VIDEO_H
|
||||
#define _USB_VIDEO_H
|
||||
|
||||
|
||||
/* Class/Subclass/Protocol */
|
||||
#define CC_VIDEO 0xE
|
||||
#define SC_UNDEFINED 0x0
|
||||
@@ -89,4 +90,205 @@
|
||||
#define CT_ROLL_RELATIVE_CONTROL 0x10
|
||||
#define CT_PRIVACY_CONTROL 0x11
|
||||
|
||||
typedef struct usbvc_class_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
} _PACKED usbvc_class_descriptor;
|
||||
|
||||
struct usbvc_input_header_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 numFormats;
|
||||
uint16 totalLength;
|
||||
uint8 endpointAddress;
|
||||
uint8 info;
|
||||
uint8 terminalLink;
|
||||
uint8 stillCaptureMethod;
|
||||
uint8 triggerSupport;
|
||||
uint8 triggerUsage;
|
||||
uint8 controlSize;
|
||||
uint8 controls[0];
|
||||
} _PACKED;
|
||||
|
||||
struct usbvc_output_header_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 numFormats;
|
||||
uint16 totalLength;
|
||||
uint8 endpointAddress;
|
||||
uint8 terminalLink;
|
||||
uint8 controlSize;
|
||||
uint8 controls[0];
|
||||
} _PACKED;
|
||||
|
||||
typedef uint8 usbvc_guid[16];
|
||||
|
||||
struct usbvc_format_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 formatIndex;
|
||||
uint8 numFrameDescriptors;
|
||||
union {
|
||||
struct {
|
||||
usbvc_guid format;
|
||||
uint8 bytesPerPixel;
|
||||
uint8 defaultFrameIndex;
|
||||
uint8 aspectRatioX;
|
||||
uint8 aspectRatioY;
|
||||
uint8 interlaceFlags;
|
||||
uint8 copyProtect;
|
||||
} uncompressed;
|
||||
struct {
|
||||
uint8 flags;
|
||||
uint8 defaultFrameIndex;
|
||||
uint8 aspectRatioX;
|
||||
uint8 aspectRatioY;
|
||||
uint8 interlaceFlags;
|
||||
uint8 copyProtect;
|
||||
} mjpeg;
|
||||
};
|
||||
} _PACKED;
|
||||
|
||||
struct usbvc_frame_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 frameIndex;
|
||||
uint8 capabilities;
|
||||
uint16 width;
|
||||
uint16 height;
|
||||
uint32 minBitRate;
|
||||
uint32 maxBitRate;
|
||||
uint32 maxVideoFrameBufferSize;
|
||||
uint32 defaultFrameInterval;
|
||||
uint8 frameIntervalType;
|
||||
union {
|
||||
struct {
|
||||
uint32 minFrameInterval;
|
||||
uint32 maxFrameInterval;
|
||||
uint32 frameIntervalStep;
|
||||
} continuous;
|
||||
uint32 discreteFrameIntervals[0];
|
||||
};
|
||||
} _PACKED;
|
||||
|
||||
typedef struct {
|
||||
uint16 width;
|
||||
uint16 height;
|
||||
} _PACKED usbvc_image_size_pattern;
|
||||
|
||||
struct usbvc_still_image_frame_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 endpointAddress;
|
||||
uint8 numImageSizePatterns;
|
||||
usbvc_image_size_pattern imageSizePatterns[0];
|
||||
uint8 NumCompressionPatterns() const { return *(CompressionPatterns() - 1); }
|
||||
const uint8* CompressionPatterns() const {
|
||||
return (const uint8*)(imageSizePatterns + sizeof(usbvc_image_size_pattern)
|
||||
* numImageSizePatterns + sizeof(uint8));
|
||||
}
|
||||
} _PACKED;
|
||||
|
||||
struct usbvc_color_matching_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 colorPrimaries;
|
||||
uint8 transferCharacteristics;
|
||||
uint8 matrixCoefficients;
|
||||
} _PACKED;
|
||||
|
||||
|
||||
struct usbvc_interface_header_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint16 version;
|
||||
uint16 totalLength;
|
||||
uint32 clockFrequency;
|
||||
uint8 numInterfacesNumbers;
|
||||
uint8 interfaceNumbers[0];
|
||||
} _PACKED;
|
||||
|
||||
struct usbvc_input_terminal_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 terminalID;
|
||||
uint16 terminalType;
|
||||
uint8 associatedTerminal;
|
||||
uint8 terminal;
|
||||
} _PACKED;
|
||||
|
||||
struct usbvc_output_terminal_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 terminalID;
|
||||
uint16 terminalType;
|
||||
uint8 associatedTerminal;
|
||||
uint8 sourceID;
|
||||
uint8 terminal;
|
||||
} _PACKED;
|
||||
|
||||
struct usbvc_camera_terminal_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 terminalID;
|
||||
uint16 terminalType;
|
||||
uint8 associatedTerminal;
|
||||
uint8 terminal;
|
||||
uint16 objectiveFocalLengthMin;
|
||||
uint16 objectiveFocalLengthMax;
|
||||
uint16 ocularFocalLength;
|
||||
uint8 controlSize;
|
||||
uint8 controls[0];
|
||||
} _PACKED;
|
||||
|
||||
struct usbvc_selector_unit_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 unitID;
|
||||
uint8 numInputPins;
|
||||
uint8 sourceID[0];
|
||||
uint8 Selector() const { return sourceID[numInputPins]; }
|
||||
} _PACKED;
|
||||
|
||||
struct usbvc_processing_unit_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 unitID;
|
||||
uint8 sourceID;
|
||||
uint16 maxMultiplier;
|
||||
uint8 controlSize;
|
||||
uint8 controls[0];
|
||||
uint8 Processing() const { return controls[controlSize]; }
|
||||
uint8 VideoStandards() const { return controls[controlSize+1]; }
|
||||
} _PACKED;
|
||||
|
||||
struct usbvc_extension_unit_descriptor {
|
||||
uint8 length;
|
||||
uint8 descriptorType;
|
||||
uint8 descriptorSubtype;
|
||||
uint8 unitID;
|
||||
usbvc_guid guidExtensionCode;
|
||||
uint8 numControls;
|
||||
uint8 numInputPins;
|
||||
uint8 sourceID[0];
|
||||
uint8 ControlSize() const { return sourceID[numInputPins]; }
|
||||
const uint8* Controls() const { return &sourceID[numInputPins+1]; }
|
||||
uint8 Extension() const
|
||||
{ return sourceID[numInputPins + ControlSize() + 1]; }
|
||||
} _PACKED;
|
||||
|
||||
|
||||
#endif /* _USB_VIDEO_H */
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2011, Jérôme Duval, [email protected].
|
||||
* Copyright 2009, Ithamar Adema, <[email protected]>.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "UVCCamDevice.h"
|
||||
#include "USB_video.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -37,52 +37,66 @@ usb_webcam_support_descriptor kSupportedDevices[] = {
|
||||
};
|
||||
|
||||
/* Table 2-1 Compression Formats of USB Video Payload Uncompressed */
|
||||
uint8 yuy2_guid = {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
|
||||
0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
|
||||
uint8 nv12_guid = {0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00,
|
||||
0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
|
||||
usbvc_guid kYUY2Guid = {0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80,
|
||||
0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
|
||||
usbvc_guid kNV12Guid = {0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, 0x80,
|
||||
0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71};
|
||||
|
||||
static void
|
||||
print_guid(const uint8* buf)
|
||||
print_guid(const usbvc_guid guid)
|
||||
{
|
||||
printf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
|
||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
||||
printf("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:"
|
||||
"%02x:%02x:%02x", guid[0], guid[1], guid[2], guid[3], guid[4], guid[5],
|
||||
guid[6], guid[7], guid[8], guid[9], guid[10], guid[11], guid[12],
|
||||
guid[13], guid[14], guid[15]);
|
||||
}
|
||||
|
||||
|
||||
UVCCamDevice::UVCCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
|
||||
: CamDevice(_addon, _device)
|
||||
{
|
||||
const BUSBConfiguration* uc;
|
||||
const BUSBInterface* ui;
|
||||
usb_descriptor *generic;
|
||||
uint32 cfg, intf, di;
|
||||
const BUSBConfiguration* config;
|
||||
const BUSBInterface* interface;
|
||||
usb_descriptor* generic;
|
||||
uint8 buffer[1024];
|
||||
|
||||
generic = (usb_descriptor *)buffer;
|
||||
|
||||
for (cfg=0; cfg < _device->CountConfigurations(); cfg++) {
|
||||
uc = _device->ConfigurationAt(cfg);
|
||||
for (intf=0; intf < uc->CountInterfaces(); intf++) {
|
||||
ui = uc->InterfaceAt(intf);
|
||||
for (uint32 i = 0; i < _device->CountConfigurations(); i++) {
|
||||
config = _device->ConfigurationAt(i);
|
||||
for (uint32 j = 0; j < config->CountInterfaces(); j++) {
|
||||
interface = config->InterfaceAt(j);
|
||||
|
||||
if (ui->Class() == CC_VIDEO && ui->Subclass() == SC_VIDEOCONTROL) {
|
||||
printf("UVCCamDevice: (%lu,%lu): Found Video Control interface.\n", cfg, intf);
|
||||
if (interface->Class() == CC_VIDEO && interface->Subclass()
|
||||
== SC_VIDEOCONTROL) {
|
||||
printf("UVCCamDevice: (%lu,%lu): Found Video Control "
|
||||
"interface.\n", i, j);
|
||||
|
||||
// look for class specific interface descriptors and parse them
|
||||
for (di=0; ui->OtherDescriptorAt(di,generic,sizeof(buffer)) == B_OK; ++di)
|
||||
if (generic->generic.descriptor_type == (USB_REQTYPE_CLASS | USB_DESCRIPTOR_INTERFACE))
|
||||
ParseVideoControl(buffer, generic->generic.length);
|
||||
for (uint32 k = 0; interface->OtherDescriptorAt(k, generic,
|
||||
sizeof(buffer)) == B_OK; k++) {
|
||||
if (generic->generic.descriptor_type == (USB_REQTYPE_CLASS
|
||||
| USB_DESCRIPTOR_INTERFACE)) {
|
||||
ParseVideoControl((const usbvc_class_descriptor*)generic,
|
||||
generic->generic.length);
|
||||
}
|
||||
}
|
||||
|
||||
fInitStatus = B_OK;
|
||||
} else if (ui->Class() == CC_VIDEO && ui->Subclass() == SC_VIDEOSTREAMING) {
|
||||
printf("UVCCamDevice: (%lu,%lu): Found Video Control interface.\n", cfg, intf);
|
||||
} else if (interface->Class() == CC_VIDEO && interface->Subclass()
|
||||
== SC_VIDEOSTREAMING) {
|
||||
printf("UVCCamDevice: (%lu,%lu): Found Video Control interface.\n",
|
||||
i, j);
|
||||
|
||||
// look for class specific interface descriptors and parse them
|
||||
for (di=0; ui->OtherDescriptorAt(di,generic,sizeof(buffer)) == B_OK; ++di)
|
||||
if (generic->generic.descriptor_type == (USB_REQTYPE_CLASS | USB_DESCRIPTOR_INTERFACE))
|
||||
ParseVideoStreaming(buffer, generic->generic.length);
|
||||
for (uint32 k = 0; interface->OtherDescriptorAt(k, generic,
|
||||
sizeof(buffer)) == B_OK; k++) {
|
||||
if (generic->generic.descriptor_type == (USB_REQTYPE_CLASS
|
||||
| USB_DESCRIPTOR_INTERFACE)) {
|
||||
ParseVideoStreaming((const usbvc_class_descriptor*)generic,
|
||||
generic->generic.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -90,72 +104,112 @@ UVCCamDevice::UVCCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device)
|
||||
|
||||
|
||||
void
|
||||
UVCCamDevice::ParseVideoStreaming(const uint8* buffer, size_t len)
|
||||
UVCCamDevice::ParseVideoStreaming(const usbvc_class_descriptor* _descriptor,
|
||||
size_t len)
|
||||
{
|
||||
int c, i, sz;
|
||||
|
||||
switch(buffer[2]) {
|
||||
switch(_descriptor->descriptorSubtype) {
|
||||
case VS_INPUT_HEADER:
|
||||
c = buffer[3];
|
||||
printf("VS_INPUT_HEADER:\t#fmts=%d,ept=0x%x\n", c, buffer[6]);
|
||||
if (buffer[7] & 1) printf("\tDynamic Format Change supported\n");
|
||||
printf("\toutput terminal id=%d\n", buffer[8]);
|
||||
printf("\tstill capture method=%d\n", buffer[9]);
|
||||
if (buffer[10])
|
||||
printf("\ttrigger button fixed to still capture=%s\n", buffer[11] ? "no" : "yes");
|
||||
sz = buffer[12];
|
||||
for (i=0; i < c; i++) {
|
||||
{
|
||||
const usbvc_input_header_descriptor* descriptor =
|
||||
(const usbvc_input_header_descriptor*)_descriptor;
|
||||
printf("VS_INPUT_HEADER:\t#fmts=%d,ept=0x%x\n", descriptor->numFormats,
|
||||
descriptor->endpointAddress);
|
||||
if (descriptor->info & 1)
|
||||
printf("\tDynamic Format Change supported\n");
|
||||
printf("\toutput terminal id=%d\n", descriptor->terminalLink);
|
||||
printf("\tstill capture method=%d\n", descriptor->stillCaptureMethod);
|
||||
if (descriptor->triggerSupport) {
|
||||
printf("\ttrigger button fixed to still capture=%s\n",
|
||||
descriptor->triggerUsage ? "no" : "yes");
|
||||
}
|
||||
const uint8 *controls = descriptor->controls;
|
||||
for (uint8 i = 0; i < descriptor->numFormats; i++,
|
||||
controls += descriptor->controlSize) {
|
||||
printf("\tfmt%d: %s %s %s %s - %s %s\n", i,
|
||||
(buffer[13+(sz*i)] & 1) ? "wKeyFrameRate" : "",
|
||||
(buffer[13+(sz*i)] & 2) ? "wPFrameRate" : "",
|
||||
(buffer[13+(sz*i)] & 4) ? "wCompQuality" : "",
|
||||
(buffer[13+(sz*i)] & 8) ? "wCompWindowSize" : "",
|
||||
(buffer[13+(sz*i)] & 16) ? "<Generate Key Frame>" : "",
|
||||
(buffer[13+(sz*i)] & 32) ? "<Update Frame Segment>" : "");
|
||||
(*controls & 1) ? "wKeyFrameRate" : "",
|
||||
(*controls & 2) ? "wPFrameRate" : "",
|
||||
(*controls & 4) ? "wCompQuality" : "",
|
||||
(*controls & 8) ? "wCompWindowSize" : "",
|
||||
(*controls & 16) ? "<Generate Key Frame>" : "",
|
||||
(*controls & 32) ? "<Update Frame Segment>" : "");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VS_FORMAT_UNCOMPRESSED:
|
||||
c = buffer[4];
|
||||
printf("VS_FORMAT_UNCOMPRESSED:\tbFormatIdx=%d,#frmdesc=%d,guid=", buffer[3], c);
|
||||
print_guid(buffer+5);
|
||||
printf("\n\t#bpp=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n", buffer[21], buffer[22],
|
||||
buffer[23], buffer[24]);
|
||||
{
|
||||
const usbvc_format_descriptor* descriptor =
|
||||
(const usbvc_format_descriptor*)_descriptor;
|
||||
printf("VS_FORMAT_UNCOMPRESSED:\tbFormatIdx=%d,#frmdesc=%d,guid=",
|
||||
descriptor->formatIndex, descriptor->numFrameDescriptors);
|
||||
print_guid(descriptor->uncompressed.format);
|
||||
printf("\n\t#bpp=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n",
|
||||
descriptor->uncompressed.bytesPerPixel,
|
||||
descriptor->uncompressed.defaultFrameIndex,
|
||||
descriptor->uncompressed.aspectRatioX,
|
||||
descriptor->uncompressed.aspectRatioY);
|
||||
printf("\tbmInterlaceFlags:\n");
|
||||
if (buffer[25] & 1) printf("\tInterlaced stream or variable\n");
|
||||
printf("\t%d fields per frame\n", (buffer[25] & 2) ? 1 : 2);
|
||||
if (buffer[25] & 4) printf("\tField 1 first\n");
|
||||
if (descriptor->uncompressed.interlaceFlags & 1)
|
||||
printf("\tInterlaced stream or variable\n");
|
||||
printf("\t%d fields per frame\n",
|
||||
(descriptor->uncompressed.interlaceFlags & 2) ? 1 : 2);
|
||||
if (descriptor->uncompressed.interlaceFlags & 4)
|
||||
printf("\tField 1 first\n");
|
||||
printf("\tField Pattern: ");
|
||||
switch((buffer[25] & 0x30) >> 4) {
|
||||
switch((descriptor->uncompressed.interlaceFlags & 0x30) >> 4) {
|
||||
case 0: printf("Field 1 only\n"); break;
|
||||
case 1: printf("Field 2 only\n"); break;
|
||||
case 2: printf("Regular pattern of fields 1 and 2\n"); break;
|
||||
case 3: printf("Random pattern of fields 1 and 2\n"); break;
|
||||
}
|
||||
if (buffer[26]) printf("\tRestrict duplication\n"); break;
|
||||
if (descriptor->uncompressed.copyProtect)
|
||||
printf("\tRestrict duplication\n");
|
||||
break;
|
||||
}
|
||||
case VS_FRAME_MJPEG:
|
||||
printf("VS_FRAME_MJPEG:"); // fall through
|
||||
case VS_FRAME_UNCOMPRESSED:
|
||||
printf("VS_FRAME_UNCOMPRESSED:\tbFrameIdx=%d,stillsupported=%s,fixedfrmrate=%s\n",
|
||||
buffer[3], (buffer[4]&1)?"yes":"no", (buffer[4]&2)?"yes":"no");
|
||||
{
|
||||
if (_descriptor->descriptorSubtype == VS_FRAME_UNCOMPRESSED)
|
||||
printf("VS_FRAME_UNCOMPRESSED:");
|
||||
const usbvc_frame_descriptor* descriptor =
|
||||
(const usbvc_frame_descriptor*)_descriptor;
|
||||
printf("\tbFrameIdx=%d,stillsupported=%s,"
|
||||
"fixedframerate=%s\n", descriptor->frameIndex,
|
||||
(descriptor->capabilities & 1) ? "yes" : "no",
|
||||
(descriptor->capabilities & 2) ? "yes" : "no");
|
||||
printf("\twidth=%u,height=%u,min/max bitrate=%lu/%lu, maxbuf=%lu\n",
|
||||
*(uint16*)(buffer+5), *(uint16*)(buffer+7),
|
||||
*(uint32*)(buffer+9), *(uint32*)(buffer+13),
|
||||
*(uint32*)(buffer+17));
|
||||
printf("\tframe interval: %lu, #intervals(0=cont): %d\n", *(uint32*)(buffer+21), buffer[25]);
|
||||
//TODO print interval table
|
||||
descriptor->width, descriptor->height,
|
||||
descriptor->minBitRate, descriptor->maxBitRate,
|
||||
descriptor->maxVideoFrameBufferSize);
|
||||
printf("\tdefault frame interval: %lu, #intervals(0=cont): %d\n",
|
||||
descriptor->defaultFrameInterval, descriptor->frameIntervalType);
|
||||
if (descriptor->frameIntervalType == 0) {
|
||||
printf("min/max frame interval=%lu/%lu, step=%lu\n",
|
||||
descriptor->continuous.minFrameInterval,
|
||||
descriptor->continuous.maxFrameInterval,
|
||||
descriptor->continuous.frameIntervalStep);
|
||||
} else for (uint8 i = 0; i < descriptor->frameIntervalType; i++) {
|
||||
printf("discrete frame interval: %lu\n",
|
||||
descriptor->discreteFrameIntervals[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VS_COLORFORMAT:
|
||||
{
|
||||
const usbvc_color_matching_descriptor* descriptor =
|
||||
(const usbvc_color_matching_descriptor*)_descriptor;
|
||||
printf("VS_COLORFORMAT:\n\tbColorPrimaries: ");
|
||||
switch(buffer[3]) {
|
||||
switch(descriptor->colorPrimaries) {
|
||||
case 0: printf("Unspecified\n"); break;
|
||||
case 1: printf("BT.709,sRGB\n"); break;
|
||||
case 2: printf("BT.470-2(M)\n"); break;
|
||||
case 3: printf("BT.470-2(B,G)\n"); break;
|
||||
case 4: printf("SMPTE 170M\n"); break;
|
||||
case 5: printf("SMPTE 240M\n"); break;
|
||||
default: printf("Invalid (%d)\n", buffer[3]);
|
||||
default: printf("Invalid (%d)\n", descriptor->colorPrimaries);
|
||||
}
|
||||
printf("\tbTransferCharacteristics: ");
|
||||
switch(buffer[4]) {
|
||||
switch(descriptor->transferCharacteristics) {
|
||||
case 0: printf("Unspecified\n"); break;
|
||||
case 1: printf("BT.709\n"); break;
|
||||
case 2: printf("BT.470-2(M)\n"); break;
|
||||
@@ -164,32 +218,87 @@ UVCCamDevice::ParseVideoStreaming(const uint8* buffer, size_t len)
|
||||
case 5: printf("SMPTE 240M\n"); break;
|
||||
case 6: printf("Linear (V=Lc)\n"); break;
|
||||
case 7: printf("sRGB\n"); break;
|
||||
default: printf("Invalid (%d)\n", buffer[4]);
|
||||
default: printf("Invalid (%d)\n",
|
||||
descriptor->transferCharacteristics);
|
||||
}
|
||||
printf("\tbMatrixCoefficients: ");
|
||||
switch(buffer[5]) {
|
||||
switch(descriptor->matrixCoefficients) {
|
||||
case 0: printf("Unspecified\n"); break;
|
||||
case 1: printf("BT.709\n"); break;
|
||||
case 2: printf("FCC\n"); break;
|
||||
case 3: printf("BT.470-2(B,G)\n"); break;
|
||||
case 4: printf("SMPTE 170M (BT.601)\n"); break;
|
||||
case 5: printf("SMPTE 240M\n"); break;
|
||||
default: printf("Invalid (%d)\n", buffer[5]);
|
||||
default: printf("Invalid (%d)\n", descriptor->matrixCoefficients);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case VS_OUTPUT_HEADER:
|
||||
printf("VS_OUTPUT_HEADER:\t\n");
|
||||
{
|
||||
const usbvc_output_header_descriptor* descriptor =
|
||||
(const usbvc_output_header_descriptor*)_descriptor;
|
||||
printf("VS_OUTPUT_HEADER:\t#fmts=%d,ept=0x%x\n",
|
||||
descriptor->numFormats, descriptor->endpointAddress);
|
||||
printf("\toutput terminal id=%d\n", descriptor->terminalLink);
|
||||
const uint8 *controls = descriptor->controls;
|
||||
for (uint8 i = 0; i < descriptor->numFormats; i++,
|
||||
controls += descriptor->controlSize) {
|
||||
printf("\tfmt%d: %s %s %s %s\n", i,
|
||||
(*controls & 1) ? "wKeyFrameRate" : "",
|
||||
(*controls & 2) ? "wPFrameRate" : "",
|
||||
(*controls & 4) ? "wCompQuality" : "",
|
||||
(*controls & 8) ? "wCompWindowSize" : "");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VS_STILL_IMAGE_FRAME:
|
||||
printf("VS_STILL_IMAGE_FRAME:\t\n");
|
||||
{
|
||||
const usbvc_still_image_frame_descriptor* descriptor =
|
||||
(const usbvc_still_image_frame_descriptor*)_descriptor;
|
||||
printf("VS_STILL_IMAGE_FRAME:\t#imageSizes=%d,compressions=%d,"
|
||||
"ept=0x%x\n", descriptor->numImageSizePatterns,
|
||||
descriptor->NumCompressionPatterns(),
|
||||
descriptor->endpointAddress);
|
||||
for (uint8 i = 0; i < descriptor->numImageSizePatterns; i++) {
|
||||
printf("imageSize%d: %dx%d\n", i,
|
||||
descriptor->imageSizePatterns[i].width,
|
||||
descriptor->imageSizePatterns[i].height);
|
||||
}
|
||||
for (uint8 i = 0; i < descriptor->NumCompressionPatterns(); i++) {
|
||||
printf("compression%d: %d\n", i,
|
||||
descriptor->CompressionPatterns()[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VS_FORMAT_MJPEG:
|
||||
printf("VS_FORMAT_MJPEG:\t\n");
|
||||
break;
|
||||
case VS_FRAME_MJPEG:
|
||||
printf("VS_FRAME_MJPEG:\t\n");
|
||||
{
|
||||
const usbvc_format_descriptor* descriptor =
|
||||
(const usbvc_format_descriptor*)_descriptor;
|
||||
printf("VS_FORMAT_MJPEG:\tbFormatIdx=%d,#frmdesc=%d\n",
|
||||
descriptor->formatIndex, descriptor->numFrameDescriptors);
|
||||
printf("\t#flgs=%d,optfrmidx=%d,aspRX=%d,aspRY=%d\n",
|
||||
descriptor->mjpeg.flags,
|
||||
descriptor->mjpeg.defaultFrameIndex,
|
||||
descriptor->mjpeg.aspectRatioX,
|
||||
descriptor->mjpeg.aspectRatioY);
|
||||
printf("\tbmInterlaceFlags:\n");
|
||||
if (descriptor->mjpeg.interlaceFlags & 1)
|
||||
printf("\tInterlaced stream or variable\n");
|
||||
printf("\t%d fields per frame\n",
|
||||
(descriptor->mjpeg.interlaceFlags & 2) ? 1 : 2);
|
||||
if (descriptor->mjpeg.interlaceFlags & 4)
|
||||
printf("\tField 1 first\n");
|
||||
printf("\tField Pattern: ");
|
||||
switch((descriptor->mjpeg.interlaceFlags & 0x30) >> 4) {
|
||||
case 0: printf("Field 1 only\n"); break;
|
||||
case 1: printf("Field 2 only\n"); break;
|
||||
case 2: printf("Regular pattern of fields 1 and 2\n"); break;
|
||||
case 3: printf("Random pattern of fields 1 and 2\n"); break;
|
||||
}
|
||||
if (descriptor->mjpeg.copyProtect)
|
||||
printf("\tRestrict duplication\n");
|
||||
break;
|
||||
}
|
||||
case VS_FORMAT_MPEG2TS:
|
||||
printf("VS_FORMAT_MPEG2TS:\t\n");
|
||||
break;
|
||||
@@ -206,94 +315,148 @@ UVCCamDevice::ParseVideoStreaming(const uint8* buffer, size_t len)
|
||||
printf("VS_FORMAT_STREAM_BASED:\t\n");
|
||||
break;
|
||||
default:
|
||||
printf("INVALID STREAM UNIT TYPE=%d!\n", buffer[2]);
|
||||
printf("INVALID STREAM UNIT TYPE=%d!\n",
|
||||
_descriptor->descriptorSubtype);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UVCCamDevice::ParseVideoControl(const uint8* buffer, size_t len)
|
||||
UVCCamDevice::ParseVideoControl(const usbvc_class_descriptor* _descriptor,
|
||||
size_t len)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
switch(buffer[2]) {
|
||||
switch(_descriptor->descriptorSubtype) {
|
||||
case VC_HEADER:
|
||||
printf("VC_HEADER:\tUVC v%04x, clk %lu Hz\n", *(uint16*)(buffer+3), *(uint32*)(buffer+7));
|
||||
c = (len >= 12) ? buffer[11] : 0;
|
||||
for (i=0; i < c; i++)
|
||||
printf("\tStreaming Interface %d\n", buffer[12+i]);
|
||||
{
|
||||
const usbvc_interface_header_descriptor* descriptor =
|
||||
(const usbvc_interface_header_descriptor*)_descriptor;
|
||||
printf("VC_HEADER:\tUVC v%04x, clk %lu Hz\n", descriptor->version,
|
||||
descriptor->clockFrequency);
|
||||
for (uint8 i = 0; i < descriptor->numInterfacesNumbers; i++) {
|
||||
printf("\tStreaming Interface %d\n",
|
||||
descriptor->interfaceNumbers[i]);
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
case VC_INPUT_TERMINAL:
|
||||
printf("VC_INPUT_TERMINAL:\tid=%d,type=%04x,associated terminal=%d\n", buffer[3], *(uint16*)(buffer+4), buffer[6]);
|
||||
printf("\tDesc: %s\n", fDevice->DecodeStringDescriptor(buffer[7]));
|
||||
{
|
||||
const usbvc_input_terminal_descriptor* descriptor =
|
||||
(const usbvc_input_terminal_descriptor*)_descriptor;
|
||||
printf("VC_INPUT_TERMINAL:\tid=%d,type=%04x,associated terminal="
|
||||
"%d\n", descriptor->terminalID, descriptor->terminalType,
|
||||
descriptor->associatedTerminal);
|
||||
printf("\tDesc: %s\n",
|
||||
fDevice->DecodeStringDescriptor(descriptor->terminal));
|
||||
break;
|
||||
|
||||
}
|
||||
case VC_OUTPUT_TERMINAL:
|
||||
printf("VC_OUTPUT_TERMINAL:\tid=%d,type=%04x,associated terminal=%d, src id=%d\n", buffer[3], *(uint16*)(buffer+4), buffer[6], buffer[7]);
|
||||
printf("\tDesc: %s\n", fDevice->DecodeStringDescriptor(buffer[8]));
|
||||
{
|
||||
const usbvc_output_terminal_descriptor* descriptor =
|
||||
(const usbvc_output_terminal_descriptor*)_descriptor;
|
||||
printf("VC_OUTPUT_TERMINAL:\tid=%d,type=%04x,associated terminal="
|
||||
"%d, src id=%d\n", descriptor->terminalID,
|
||||
descriptor->terminalType, descriptor->associatedTerminal,
|
||||
descriptor->sourceID);
|
||||
printf("\tDesc: %s\n",
|
||||
fDevice->DecodeStringDescriptor(descriptor->terminal));
|
||||
break;
|
||||
|
||||
}
|
||||
case VC_SELECTOR_UNIT:
|
||||
printf("VC_SELECTOR_UNIT:\tid=%d,#pins=%d\n", buffer[3], buffer[4]);
|
||||
{
|
||||
const usbvc_selector_unit_descriptor* descriptor =
|
||||
(const usbvc_selector_unit_descriptor*)_descriptor;
|
||||
printf("VC_SELECTOR_UNIT:\tid=%d,#pins=%d\n",
|
||||
descriptor->unitID, descriptor->numInputPins);
|
||||
printf("\t");
|
||||
for (i=0; i < buffer[4]; i++)
|
||||
printf("%d ", buffer[5+i]);
|
||||
for (uint8 i = 0; i < descriptor->numInputPins; i++)
|
||||
printf("%d ", descriptor->sourceID[i]);
|
||||
printf("\n");
|
||||
printf("\tDesc: %s\n", fDevice->DecodeStringDescriptor(buffer[5+buffer[4]]));
|
||||
printf("\tDesc: %s\n",
|
||||
fDevice->DecodeStringDescriptor(descriptor->Selector()));
|
||||
break;
|
||||
|
||||
}
|
||||
case VC_PROCESSING_UNIT:
|
||||
printf("VC_PROCESSING_UNIT:\tid=%d,src id=%d, digmul=%d\n", buffer[3], buffer[4], *(uint16*)(buffer+5));
|
||||
c = buffer[7];
|
||||
printf("\tbControlSize=%d\n", c);
|
||||
if (c >= 1) {
|
||||
if (buffer[8] & 1) printf("\tBrightness\n");
|
||||
if (buffer[8] & 2) printf("\tContrast\n");
|
||||
if (buffer[8] & 4) printf("\tHue\n");
|
||||
if (buffer[8] & 8) printf("\tSaturation\n");
|
||||
if (buffer[8] & 16) printf("\tSharpness\n");
|
||||
if (buffer[8] & 32) printf("\tGamma\n");
|
||||
if (buffer[8] & 64) printf("\tWhite Balance Temperature\n");
|
||||
if (buffer[8] & 128) printf("\tWhite Balance Component\n");
|
||||
{
|
||||
const usbvc_processing_unit_descriptor* descriptor =
|
||||
(const usbvc_processing_unit_descriptor*)_descriptor;
|
||||
printf("VC_PROCESSING_UNIT:\tid=%d,src id=%d, digmul=%d\n",
|
||||
descriptor->unitID, descriptor->sourceID,
|
||||
descriptor->maxMultiplier);
|
||||
printf("\tbControlSize=%d\n", descriptor->controlSize);
|
||||
if (descriptor->controlSize >= 1) {
|
||||
if (descriptor->controls[0] & 1)
|
||||
printf("\tBrightness\n");
|
||||
if (descriptor->controls[0] & 2)
|
||||
printf("\tContrast\n");
|
||||
if (descriptor->controls[0] & 4)
|
||||
printf("\tHue\n");
|
||||
if (descriptor->controls[0] & 8)
|
||||
printf("\tSaturation\n");
|
||||
if (descriptor->controls[0] & 16)
|
||||
printf("\tSharpness\n");
|
||||
if (descriptor->controls[0] & 32)
|
||||
printf("\tGamma\n");
|
||||
if (descriptor->controls[0] & 64)
|
||||
printf("\tWhite Balance Temperature\n");
|
||||
if (descriptor->controls[0] & 128)
|
||||
printf("\tWhite Balance Component\n");
|
||||
}
|
||||
if (c >= 2) {
|
||||
if (buffer[9] & 1) printf("\tBacklight Compensation\n");
|
||||
if (buffer[9] & 2) printf("\tGain\n");
|
||||
if (buffer[9] & 4) printf("\tPower Line Frequency\n");
|
||||
if (buffer[9] & 8) printf("\t[AUTO] Hue\n");
|
||||
if (buffer[9] & 16) printf("\t[AUTO] White Balance Temperature\n");
|
||||
if (buffer[9] & 32) printf("\t[AUTO] White Balance Component\n");
|
||||
if (buffer[9] & 64) printf("\tDigital Multiplier\n");
|
||||
if (buffer[9] & 128) printf("\tDigital Multiplier Limit\n");
|
||||
if (descriptor->controlSize >= 2) {
|
||||
if (descriptor->controls[1] & 1)
|
||||
printf("\tBacklight Compensation\n");
|
||||
if (descriptor->controls[1] & 2)
|
||||
printf("\tGain\n");
|
||||
if (descriptor->controls[1] & 4)
|
||||
printf("\tPower Line Frequency\n");
|
||||
if (descriptor->controls[1] & 8)
|
||||
printf("\t[AUTO] Hue\n");
|
||||
if (descriptor->controls[1] & 16)
|
||||
printf("\t[AUTO] White Balance Temperature\n");
|
||||
if (descriptor->controls[1] & 32)
|
||||
printf("\t[AUTO] White Balance Component\n");
|
||||
if (descriptor->controls[1] & 64)
|
||||
printf("\tDigital Multiplier\n");
|
||||
if (descriptor->controls[1] & 128)
|
||||
printf("\tDigital Multiplier Limit\n");
|
||||
}
|
||||
if (c >= 3) {
|
||||
if (buffer[10] & 1) printf("\tAnalog Video Standard\n");
|
||||
if (buffer[10] & 2) printf("\tAnalog Video Lock Status\n");
|
||||
if (descriptor->controlSize >= 3) {
|
||||
if (descriptor->controls[2] & 1)
|
||||
printf("\tAnalog Video Standard\n");
|
||||
if (descriptor->controls[2] & 2)
|
||||
printf("\tAnalog Video Lock Status\n");
|
||||
}
|
||||
printf("\tDesc: %s\n", fDevice->DecodeStringDescriptor(buffer[8+c]));
|
||||
i=buffer[9+c];
|
||||
if (i & 2) printf("\tNTSC 525/60\n");
|
||||
if (i & 4) printf("\tPAL 625/50\n");
|
||||
if (i & 8) printf("\tSECAM 625/50\n");
|
||||
if (i & 16) printf("\tNTSC 625/50\n");
|
||||
if (i & 32) printf("\tPAL 525/60\n");
|
||||
printf("\tDesc: %s\n",
|
||||
fDevice->DecodeStringDescriptor(descriptor->Processing()));
|
||||
if (descriptor->VideoStandards() & 2)
|
||||
printf("\tNTSC 525/60\n");
|
||||
if (descriptor->VideoStandards() & 4)
|
||||
printf("\tPAL 625/50\n");
|
||||
if (descriptor->VideoStandards() & 8)
|
||||
printf("\tSECAM 625/50\n");
|
||||
if (descriptor->VideoStandards() & 16)
|
||||
printf("\tNTSC 625/50\n");
|
||||
if (descriptor->VideoStandards() & 32)
|
||||
printf("\tPAL 525/60\n");
|
||||
break;
|
||||
|
||||
}
|
||||
case VC_EXTENSION_UNIT:
|
||||
printf("VC_EXTENSION_UNIT:\tid=%d, guid=", buffer[3]);
|
||||
print_guid(buffer+4);
|
||||
printf("\n\t#ctrls=%d, #pins=%d\n", buffer[20], buffer[21]);
|
||||
c = buffer[21];
|
||||
{
|
||||
const usbvc_extension_unit_descriptor* descriptor =
|
||||
(const usbvc_extension_unit_descriptor*)_descriptor;
|
||||
printf("VC_EXTENSION_UNIT:\tid=%d, guid=", descriptor->unitID);
|
||||
print_guid(descriptor->guidExtensionCode);
|
||||
printf("\n\t#ctrls=%d, #pins=%d\n", descriptor->numControls,
|
||||
descriptor->numInputPins);
|
||||
printf("\t");
|
||||
for (i=0; i < c; i++)
|
||||
printf("%d ", buffer[22+i]);
|
||||
for (uint8 i = 0; i < descriptor->numInputPins; i++)
|
||||
printf("%d ", descriptor->sourceID[i]);
|
||||
printf("\n");
|
||||
printf("\tDesc: %s\n", fDevice->DecodeStringDescriptor(buffer[23+c+buffer[22+c]]));
|
||||
printf("\tDesc: %s\n",
|
||||
fDevice->DecodeStringDescriptor(descriptor->Extension()));
|
||||
break;
|
||||
|
||||
}
|
||||
default:
|
||||
printf("Unknown control %d\n", buffer[2]);
|
||||
printf("Unknown control %d\n", _descriptor->descriptorSubtype);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,33 +1,44 @@
|
||||
/*
|
||||
* Copyright 2011, Jérôme Duval, [email protected].
|
||||
* Copyright 2009, Ithamar Adema, <[email protected]>.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#ifndef _UVC_CAM_DEVICE_H
|
||||
#define _UVC_CAM_DEVICE_H
|
||||
|
||||
|
||||
#include "CamDevice.h"
|
||||
#include "USB_video.h"
|
||||
|
||||
|
||||
class UVCCamDevice : public CamDevice {
|
||||
public:
|
||||
UVCCamDevice(CamDeviceAddon &_addon, BUSBDevice* _device);
|
||||
~UVCCamDevice();
|
||||
UVCCamDevice(CamDeviceAddon &_addon,
|
||||
BUSBDevice* _device);
|
||||
virtual ~UVCCamDevice();
|
||||
|
||||
virtual bool SupportsIsochronous();
|
||||
virtual status_t StartTransfer();
|
||||
virtual status_t StopTransfer();
|
||||
virtual bool SupportsIsochronous();
|
||||
virtual status_t StartTransfer();
|
||||
virtual status_t StopTransfer();
|
||||
private:
|
||||
void ParseVideoControl(const uint8* buf, size_t len);
|
||||
void ParseVideoStreaming(const uint8* buf, size_t len);
|
||||
void ParseVideoControl(
|
||||
const usbvc_class_descriptor* descriptor,
|
||||
size_t len);
|
||||
void ParseVideoStreaming(
|
||||
const usbvc_class_descriptor* descriptor,
|
||||
size_t len);
|
||||
};
|
||||
|
||||
class UVCCamDeviceAddon : public CamDeviceAddon {
|
||||
public:
|
||||
UVCCamDeviceAddon(WebCamMediaAddOn* webcam);
|
||||
virtual ~UVCCamDeviceAddon();
|
||||
|
||||
virtual const char *BrandName();
|
||||
virtual UVCCamDevice *Instantiate(CamRoster &roster, BUSBDevice *from);
|
||||
class UVCCamDeviceAddon : public CamDeviceAddon {
|
||||
public:
|
||||
UVCCamDeviceAddon(WebCamMediaAddOn* webcam);
|
||||
virtual ~UVCCamDeviceAddon();
|
||||
|
||||
virtual const char* BrandName();
|
||||
virtual UVCCamDevice* Instantiate(CamRoster &roster,
|
||||
BUSBDevice *from);
|
||||
};
|
||||
|
||||
#endif /* _UVC_CAM_DEVICE_H */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user