forked from logzhan/UPBot-Pioneer
377 lines
14 KiB
C
377 lines
14 KiB
C
|
/*********************************************************************
|
||
|
* Software License Agreement (BSD License)
|
||
|
*
|
||
|
* Copyright (C) 2010-2012 Ken Tossell
|
||
|
* All rights reserved.
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions
|
||
|
* are met:
|
||
|
*
|
||
|
* * Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
* * Redistributions in binary form must reproduce the above
|
||
|
* copyright notice, this list of conditions and the following
|
||
|
* disclaimer in the documentation and/or other materials provided
|
||
|
* with the distribution.
|
||
|
* * Neither the name of the author nor other contributors may be
|
||
|
* used to endorse or promote products derived from this software
|
||
|
* without specific prior written permission.
|
||
|
*
|
||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||
|
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||
|
*********************************************************************/
|
||
|
/**
|
||
|
* @defgroup diag Diagnostics
|
||
|
* @brief Interpretation of devices, error codes and negotiated stream parameters
|
||
|
*/
|
||
|
|
||
|
#include "libuvc/libuvc.h"
|
||
|
#include "libuvc/libuvc_internal.h"
|
||
|
|
||
|
/** @internal */
|
||
|
typedef struct _uvc_error_msg {
|
||
|
uvc_error_t err;
|
||
|
const char *msg;
|
||
|
} _uvc_error_msg_t;
|
||
|
|
||
|
static const _uvc_error_msg_t uvc_error_msgs[] = {
|
||
|
{UVC_SUCCESS, "Success"},
|
||
|
{UVC_ERROR_IO, "I/O error"},
|
||
|
{UVC_ERROR_INVALID_PARAM, "Invalid parameter"},
|
||
|
{UVC_ERROR_ACCESS, "Access denied"},
|
||
|
{UVC_ERROR_NO_DEVICE, "No such device"},
|
||
|
{UVC_ERROR_NOT_FOUND, "Not found"},
|
||
|
{UVC_ERROR_BUSY, "Busy"},
|
||
|
{UVC_ERROR_TIMEOUT, "Timeout"},
|
||
|
{UVC_ERROR_OVERFLOW, "Overflow"},
|
||
|
{UVC_ERROR_PIPE, "Pipe"},
|
||
|
{UVC_ERROR_INTERRUPTED, "Interrupted"},
|
||
|
{UVC_ERROR_NO_MEM, "Out of memory"},
|
||
|
{UVC_ERROR_NOT_SUPPORTED, "Not supported"},
|
||
|
{UVC_ERROR_INVALID_DEVICE, "Invalid device"},
|
||
|
{UVC_ERROR_INVALID_MODE, "Invalid mode"},
|
||
|
{UVC_ERROR_CALLBACK_EXISTS, "Callback exists"}
|
||
|
};
|
||
|
|
||
|
/** @brief Print a message explaining an error in the UVC driver
|
||
|
* @ingroup diag
|
||
|
*
|
||
|
* @param err UVC error code
|
||
|
* @param msg Optional custom message, prepended to output
|
||
|
*/
|
||
|
void uvc_perror(uvc_error_t err, const char *msg) {
|
||
|
if (msg && *msg) {
|
||
|
fputs(msg, stderr);
|
||
|
fputs(": ", stderr);
|
||
|
}
|
||
|
|
||
|
fprintf(stderr, "%s (%d)\n", uvc_strerror(err), err);
|
||
|
}
|
||
|
|
||
|
/** @brief Return a string explaining an error in the UVC driver
|
||
|
* @ingroup diag
|
||
|
*
|
||
|
* @param err UVC error code
|
||
|
* @return error message
|
||
|
*/
|
||
|
const char* uvc_strerror(uvc_error_t err) {
|
||
|
size_t idx;
|
||
|
|
||
|
for (idx = 0; idx < sizeof(uvc_error_msgs) / sizeof(*uvc_error_msgs); ++idx) {
|
||
|
if (uvc_error_msgs[idx].err == err) {
|
||
|
return uvc_error_msgs[idx].msg;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return "Unknown error";
|
||
|
}
|
||
|
|
||
|
/** @brief Print the values in a stream control block
|
||
|
* @ingroup diag
|
||
|
*
|
||
|
* @param devh UVC device
|
||
|
* @param stream Output stream (stderr if NULL)
|
||
|
*/
|
||
|
void uvc_print_stream_ctrl(uvc_stream_ctrl_t *ctrl, FILE *stream) {
|
||
|
if (stream == NULL)
|
||
|
stream = stderr;
|
||
|
|
||
|
fprintf(stream, "bmHint: %04x\n", ctrl->bmHint);
|
||
|
fprintf(stream, "bFormatIndex: %d\n", ctrl->bFormatIndex);
|
||
|
fprintf(stream, "bFrameIndex: %d\n", ctrl->bFrameIndex);
|
||
|
fprintf(stream, "dwFrameInterval: %u\n", ctrl->dwFrameInterval);
|
||
|
fprintf(stream, "wKeyFrameRate: %d\n", ctrl->wKeyFrameRate);
|
||
|
fprintf(stream, "wPFrameRate: %d\n", ctrl->wPFrameRate);
|
||
|
fprintf(stream, "wCompQuality: %d\n", ctrl->wCompQuality);
|
||
|
fprintf(stream, "wCompWindowSize: %d\n", ctrl->wCompWindowSize);
|
||
|
fprintf(stream, "wDelay: %d\n", ctrl->wDelay);
|
||
|
fprintf(stream, "dwMaxVideoFrameSize: %u\n", ctrl->dwMaxVideoFrameSize);
|
||
|
fprintf(stream, "dwMaxPayloadTransferSize: %u\n", ctrl->dwMaxPayloadTransferSize);
|
||
|
fprintf(stream, "bInterfaceNumber: %d\n", ctrl->bInterfaceNumber);
|
||
|
}
|
||
|
|
||
|
static const char *_uvc_name_for_format_subtype(uint8_t subtype) {
|
||
|
switch (subtype) {
|
||
|
case UVC_VS_FORMAT_UNCOMPRESSED:
|
||
|
return "UncompressedFormat";
|
||
|
case UVC_VS_FORMAT_MJPEG:
|
||
|
return "MJPEGFormat";
|
||
|
case UVC_VS_FORMAT_FRAME_BASED:
|
||
|
return "FrameFormat";
|
||
|
default:
|
||
|
return "Unknown";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** @brief Print camera capabilities and configuration.
|
||
|
* @ingroup diag
|
||
|
*
|
||
|
* @param devh UVC device
|
||
|
* @param stream Output stream (stderr if NULL)
|
||
|
*/
|
||
|
void uvc_print_diag(uvc_device_handle_t *devh, FILE *stream) {
|
||
|
if (stream == NULL)
|
||
|
stream = stderr;
|
||
|
|
||
|
if (devh->info->ctrl_if.bcdUVC) {
|
||
|
uvc_streaming_interface_t *stream_if;
|
||
|
int stream_idx = 0;
|
||
|
|
||
|
uvc_device_descriptor_t *desc;
|
||
|
uvc_get_device_descriptor(devh->dev, &desc);
|
||
|
|
||
|
fprintf(stream, "DEVICE CONFIGURATION (%04x:%04x/%s) ---\n",
|
||
|
desc->idVendor, desc->idProduct,
|
||
|
desc->serialNumber ? desc->serialNumber : "[none]");
|
||
|
|
||
|
uvc_free_device_descriptor(desc);
|
||
|
|
||
|
fprintf(stream, "Status: %s\n", devh->streams ? "streaming" : "idle");
|
||
|
|
||
|
fprintf(stream, "VideoControl:\n"
|
||
|
"\tbcdUVC: 0x%04x\n",
|
||
|
devh->info->ctrl_if.bcdUVC);
|
||
|
|
||
|
DL_FOREACH(devh->info->stream_ifs, stream_if) {
|
||
|
uvc_format_desc_t *fmt_desc;
|
||
|
|
||
|
++stream_idx;
|
||
|
|
||
|
fprintf(stream, "VideoStreaming(%d):\n"
|
||
|
"\tbEndpointAddress: %d\n\tFormats:\n",
|
||
|
stream_idx, stream_if->bEndpointAddress);
|
||
|
|
||
|
DL_FOREACH(stream_if->format_descs, fmt_desc) {
|
||
|
uvc_frame_desc_t *frame_desc;
|
||
|
int i;
|
||
|
|
||
|
switch (fmt_desc->bDescriptorSubtype) {
|
||
|
case UVC_VS_FORMAT_UNCOMPRESSED:
|
||
|
case UVC_VS_FORMAT_MJPEG:
|
||
|
case UVC_VS_FORMAT_FRAME_BASED:
|
||
|
fprintf(stream,
|
||
|
"\t\%s(%d)\n"
|
||
|
"\t\t bits per pixel: %d\n"
|
||
|
"\t\t GUID: ",
|
||
|
_uvc_name_for_format_subtype(fmt_desc->bDescriptorSubtype),
|
||
|
fmt_desc->bFormatIndex,
|
||
|
fmt_desc->bBitsPerPixel);
|
||
|
|
||
|
for (i = 0; i < 16; ++i)
|
||
|
fprintf(stream, "%02x", fmt_desc->guidFormat[i]);
|
||
|
|
||
|
fprintf(stream, " (%4s)\n", fmt_desc->fourccFormat );
|
||
|
|
||
|
fprintf(stream,
|
||
|
"\t\t default frame: %d\n"
|
||
|
"\t\t aspect ratio: %dx%d\n"
|
||
|
"\t\t interlace flags: %02x\n"
|
||
|
"\t\t copy protect: %02x\n",
|
||
|
fmt_desc->bDefaultFrameIndex,
|
||
|
fmt_desc->bAspectRatioX,
|
||
|
fmt_desc->bAspectRatioY,
|
||
|
fmt_desc->bmInterlaceFlags,
|
||
|
fmt_desc->bCopyProtect);
|
||
|
|
||
|
DL_FOREACH(fmt_desc->frame_descs, frame_desc) {
|
||
|
uint32_t *interval_ptr;
|
||
|
|
||
|
fprintf(stream,
|
||
|
"\t\t\tFrameDescriptor(%d)\n"
|
||
|
"\t\t\t capabilities: %02x\n"
|
||
|
"\t\t\t size: %dx%d\n"
|
||
|
"\t\t\t bit rate: %d-%d\n"
|
||
|
"\t\t\t max frame size: %d\n"
|
||
|
"\t\t\t default interval: 1/%d\n",
|
||
|
frame_desc->bFrameIndex,
|
||
|
frame_desc->bmCapabilities,
|
||
|
frame_desc->wWidth,
|
||
|
frame_desc->wHeight,
|
||
|
frame_desc->dwMinBitRate,
|
||
|
frame_desc->dwMaxBitRate,
|
||
|
frame_desc->dwMaxVideoFrameBufferSize,
|
||
|
10000000 / frame_desc->dwDefaultFrameInterval);
|
||
|
if (frame_desc->intervals) {
|
||
|
for (interval_ptr = frame_desc->intervals;
|
||
|
*interval_ptr;
|
||
|
++interval_ptr) {
|
||
|
fprintf(stream,
|
||
|
"\t\t\t interval[%d]: 1/%d\n",
|
||
|
(int) (interval_ptr - frame_desc->intervals),
|
||
|
10000000 / *interval_ptr);
|
||
|
}
|
||
|
} else {
|
||
|
fprintf(stream,
|
||
|
"\t\t\t min interval[%d] = 1/%d\n"
|
||
|
"\t\t\t max interval[%d] = 1/%d\n",
|
||
|
frame_desc->dwMinFrameInterval,
|
||
|
10000000 / frame_desc->dwMinFrameInterval,
|
||
|
frame_desc->dwMaxFrameInterval,
|
||
|
10000000 / frame_desc->dwMaxFrameInterval);
|
||
|
if (frame_desc->dwFrameIntervalStep)
|
||
|
fprintf(stream,
|
||
|
"\t\t\t interval step[%d] = 1/%d\n",
|
||
|
frame_desc->dwFrameIntervalStep,
|
||
|
10000000 / frame_desc->dwFrameIntervalStep);
|
||
|
}
|
||
|
}
|
||
|
if(fmt_desc->still_frame_desc)
|
||
|
{
|
||
|
uvc_still_frame_desc_t* still_frame_desc;
|
||
|
DL_FOREACH(fmt_desc->still_frame_desc, still_frame_desc)
|
||
|
{
|
||
|
fprintf(stream,
|
||
|
"\t\t\tStillFrameDescriptor\n"
|
||
|
"\t\t\t bEndPointAddress: %02x\n",
|
||
|
still_frame_desc->bEndPointAddress);
|
||
|
uvc_still_frame_res_t* imageSizePattern;
|
||
|
DL_FOREACH(still_frame_desc->imageSizePatterns, imageSizePattern) {
|
||
|
fprintf(stream,
|
||
|
"\t\t\t wWidth(%d) = %d\n"
|
||
|
"\t\t\t wHeight(%d) = %d\n",
|
||
|
imageSizePattern->bResolutionIndex,
|
||
|
imageSizePattern->wWidth,
|
||
|
imageSizePattern->bResolutionIndex,
|
||
|
imageSizePattern->wHeight);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
fprintf(stream, "\t-UnknownFormat (%d)\n",
|
||
|
fmt_desc->bDescriptorSubtype );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fprintf(stream, "END DEVICE CONFIGURATION\n");
|
||
|
} else {
|
||
|
fprintf(stream, "uvc_print_diag: Device not configured!\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** @brief Print all possible frame configuration.
|
||
|
* @ingroup diag
|
||
|
*
|
||
|
* @param devh UVC device
|
||
|
* @param stream Output stream (stderr if NULL)
|
||
|
*/
|
||
|
void uvc_print_frameformats(uvc_device_handle_t *devh) {
|
||
|
|
||
|
if (devh->info->ctrl_if.bcdUVC) {
|
||
|
uvc_streaming_interface_t *stream_if;
|
||
|
int stream_idx = 0;
|
||
|
DL_FOREACH(devh->info->stream_ifs, stream_if) {
|
||
|
uvc_format_desc_t *fmt_desc;
|
||
|
++stream_idx;
|
||
|
|
||
|
DL_FOREACH(stream_if->format_descs, fmt_desc) {
|
||
|
uvc_frame_desc_t *frame_desc;
|
||
|
int i;
|
||
|
|
||
|
switch (fmt_desc->bDescriptorSubtype) {
|
||
|
case UVC_VS_FORMAT_UNCOMPRESSED:
|
||
|
case UVC_VS_FORMAT_MJPEG:
|
||
|
case UVC_VS_FORMAT_FRAME_BASED:
|
||
|
printf(" \%s(%d)\n"
|
||
|
" bits per pixel: %d\n"
|
||
|
" GUID: ",
|
||
|
_uvc_name_for_format_subtype(fmt_desc->bDescriptorSubtype),
|
||
|
fmt_desc->bFormatIndex,
|
||
|
fmt_desc->bBitsPerPixel);
|
||
|
|
||
|
for (i = 0; i < 16; ++i)
|
||
|
printf("%02x", fmt_desc->guidFormat[i]);
|
||
|
|
||
|
printf(" (%4s)\n", fmt_desc->fourccFormat );
|
||
|
|
||
|
printf(" default frame: %d\n"
|
||
|
" aspect ratio: %dx%d\n"
|
||
|
" interlace flags: %02x\n"
|
||
|
" copy protect: %02x\n",
|
||
|
fmt_desc->bDefaultFrameIndex,
|
||
|
fmt_desc->bAspectRatioX,
|
||
|
fmt_desc->bAspectRatioY,
|
||
|
fmt_desc->bmInterlaceFlags,
|
||
|
fmt_desc->bCopyProtect);
|
||
|
|
||
|
DL_FOREACH(fmt_desc->frame_descs, frame_desc) {
|
||
|
uint32_t *interval_ptr;
|
||
|
|
||
|
printf(" FrameDescriptor(%d)\n"
|
||
|
" capabilities: %02x\n"
|
||
|
" size: %dx%d\n"
|
||
|
" bit rate: %d-%d\n"
|
||
|
" max frame size: %d\n"
|
||
|
" default interval: 1/%d\n",
|
||
|
frame_desc->bFrameIndex,
|
||
|
frame_desc->bmCapabilities,
|
||
|
frame_desc->wWidth,
|
||
|
frame_desc->wHeight,
|
||
|
frame_desc->dwMinBitRate,
|
||
|
frame_desc->dwMaxBitRate,
|
||
|
frame_desc->dwMaxVideoFrameBufferSize,
|
||
|
10000000 / frame_desc->dwDefaultFrameInterval);
|
||
|
if (frame_desc->intervals) {
|
||
|
for (interval_ptr = frame_desc->intervals;
|
||
|
*interval_ptr;
|
||
|
++interval_ptr) {
|
||
|
printf(" interval[%d]: 1/%d\n",
|
||
|
(int) (interval_ptr - frame_desc->intervals),
|
||
|
10000000 / *interval_ptr);
|
||
|
}
|
||
|
} else {
|
||
|
printf(" min interval[%d] = 1/%d\n"
|
||
|
" max interval[%d] = 1/%d\n",
|
||
|
frame_desc->dwMinFrameInterval,
|
||
|
10000000 / frame_desc->dwMinFrameInterval,
|
||
|
frame_desc->dwMaxFrameInterval,
|
||
|
10000000 / frame_desc->dwMaxFrameInterval);
|
||
|
if (frame_desc->dwFrameIntervalStep)
|
||
|
printf(" interval step[%d] = 1/%d\n",
|
||
|
frame_desc->dwFrameIntervalStep,
|
||
|
10000000 / frame_desc->dwFrameIntervalStep);
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
printf("\t-UnknownFormat (%d)\n",fmt_desc->bDescriptorSubtype );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
printf("uvc_print_frameformats: Device not configured!\n");
|
||
|
}
|
||
|
}
|