460 lines
14 KiB
C
460 lines
14 KiB
C
/*
|
||
ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
|
||
Copyright (C) 2015..2019 Diego Ismirlian, (dismirlian(at)google's mail)
|
||
|
||
Licensed under the Apache License, Version 2.0 (the "License");
|
||
you may not use this file except in compliance with the License.
|
||
You may obtain a copy of the License at
|
||
|
||
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
||
Unless required by applicable law or agreed to in writing, software
|
||
distributed under the License is distributed on an "AS IS" BASIS,
|
||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
See the License for the specific language governing permissions and
|
||
limitations under the License.
|
||
*/
|
||
|
||
#ifndef USBH_INCLUDE_USBH_UVC_H_
|
||
#define USBH_INCLUDE_USBH_UVC_H_
|
||
|
||
#include "hal_usbh.h"
|
||
|
||
#if HAL_USE_USBH && HAL_USBH_USE_UVC
|
||
|
||
#include "usbh/desciter.h"
|
||
|
||
/*===========================================================================*/
|
||
/* Driver pre-compile time settings. */
|
||
/*===========================================================================*/
|
||
|
||
|
||
/*===========================================================================*/
|
||
/* Derived constants and error checks. */
|
||
/*===========================================================================*/
|
||
#define USBHUVC_MAX_STATUS_PACKET_SZ 16
|
||
|
||
|
||
/*===========================================================================*/
|
||
/* Driver data structures and types. */
|
||
/*===========================================================================*/
|
||
|
||
|
||
typedef enum {
|
||
UVC_CS_INTERFACE = 0x24,
|
||
UVC_CS_ENDPOINT = 0x25
|
||
} usbh_uvc_cstype_t;
|
||
|
||
typedef enum {
|
||
UVC_CC_VIDEO = 0x0e
|
||
} usbh_uvc_cctype_t;
|
||
|
||
typedef enum {
|
||
UVC_SC_UNKNOWN = 0x00,
|
||
UVC_SC_VIDEOCONTROL,
|
||
UVC_SC_VIDEOSTREAMING,
|
||
UVC_SC_VIDEO_INTERFACE_COLLECTION
|
||
} usbh_uvc_sctype_t;
|
||
|
||
typedef enum {
|
||
UVC_VC_UNDEF = 0x00,
|
||
UVC_VC_HEADER,
|
||
UVC_VC_INPUT_TERMINAL,
|
||
UVC_VC_OUTPUT_TERMINAL,
|
||
UVC_VC_SELECTOR_UNIT,
|
||
UVC_VC_PROCESSING_UNIT,
|
||
UVC_VC_EXTENSION_UNIT
|
||
} usbh_uvc_vctype_t;
|
||
|
||
typedef enum {
|
||
UVC_VS_UNDEF = 0x00,
|
||
UVC_VS_INPUT_HEADER,
|
||
UVC_VS_OUTPUT_HEADER,
|
||
UVC_VS_STILL_IMAGE_FRAME,
|
||
UVC_VS_FORMAT_UNCOMPRESSED,
|
||
UVC_VS_FRAME_UNCOMPRESSED,
|
||
UVC_VS_FORMAT_MJPEG,
|
||
UVC_VS_FRAME_MJPEG,
|
||
UVC_VS_RESERVED_0,
|
||
UVC_VS_RESERVED_1,
|
||
UVC_VS_FORMAT_MPEG2TS,
|
||
UVC_VS_RESERVED_2,
|
||
UVC_VS_FORMAT_DV,
|
||
UVC_VS_COLOR_FORMAT,
|
||
UVC_VS_RESERVED_3,
|
||
UVC_VS_RESERVED_4,
|
||
UVC_VS_FORMAT_FRAME_BASED,
|
||
UVC_VS_FRAME_FRAME_BASED,
|
||
UVC_VS_FORMAT_STREAM_BASED
|
||
} usbh_uvc_vstype_t;
|
||
|
||
typedef enum {
|
||
UVC_TT_VENDOR_SPECIFIC = 0x0100,
|
||
UVC_TT_STREAMING = 0x0101,
|
||
UVC_ITT_VENDOR_SPECIFIC = 0x0200,
|
||
UVC_ITT_CAMERA = 0x0201,
|
||
UVC_ITT_MEDIA_TRANSPORT_INPUT = 0x0202,
|
||
UVC_OTT_VENDOR_SPECIFIC = 0x0300,
|
||
UVC_OTT_DISPLAY = 0x0301,
|
||
UVC_OTT_MEDIA_TRANSPORT = 0x0302
|
||
} usbh_uvc_tttype_t;
|
||
|
||
typedef enum {
|
||
UVC_SET_CUR = 0x01,
|
||
UVC_GET_CUR = 0x81,
|
||
UVC_GET_MIN = 0x82,
|
||
UVC_GET_MAX = 0x83,
|
||
UVC_GET_RES = 0x84,
|
||
UVC_GET_LEN = 0x85,
|
||
UVC_GET_INFO = 0x86,
|
||
UVC_GET_DEF = 0x87
|
||
} usbh_uvc_ctrlops_t;
|
||
|
||
typedef enum {
|
||
UVC_CTRL_VC_CONTROL_UNDEFINED = 0x00,
|
||
UVC_CTRL_VC_VIDEO_POWER_MODE_CONTROL = 0x01,
|
||
UVC_CTRL_VC_REQUEST_ERROR_CODE_CONTROL = 0x02,
|
||
} usbh_uvc_ctrl_vc_interface_controls_t;
|
||
|
||
typedef enum {
|
||
UVC_CTRL_SU_CONTROL_UNDEFINED = 0x00,
|
||
UVC_CTRL_SU_INPUT_SELECT_CONTROL = 0x01,
|
||
} usbh_uvc_ctrl_vc_selectorunit_controls_t;
|
||
|
||
typedef enum {
|
||
UVC_CTRL_CT_CONTROL_UNDEFINED = 0x00,
|
||
UVC_CTRL_CT_SCANNING_MODE_CONTROL = 0x01,
|
||
UVC_CTRL_CT_AE_MODE_CONTROL = 0x02,
|
||
UVC_CTRL_CT_AE_PRIORITY_CONTROL = 0x03,
|
||
UVC_CTRL_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL = 0x04,
|
||
UVC_CTRL_CT_EXPOSURE_TIME_RELATIVE_CONTROL = 0x05,
|
||
UVC_CTRL_CT_FOCUS_ABSOLUTE_CONTROL = 0x06,
|
||
UVC_CTRL_CT_FOCUS_RELATIVE_CONTROL = 0x07,
|
||
UVC_CTRL_CT_FOCUS_AUTO_CONTROL = 0x08,
|
||
UVC_CTRL_CT_IRIS_ABSOLUTE_CONTROL = 0x09,
|
||
UVC_CTRL_CT_IRIS_RELATIVE_CONTROL = 0x0A,
|
||
UVC_CTRL_CT_ZOOM_ABSOLUTE_CONTROL = 0x0B,
|
||
UVC_CTRL_CT_ZOOM_RELATIVE_CONTROL = 0x0C,
|
||
UVC_CTRL_CT_PANTILT_ABSOLUTE_CONTROL = 0x0D,
|
||
UVC_CTRL_CT_PANTILT_RELATIVE_CONTROL = 0x0E,
|
||
UVC_CTRL_CT_ROLL_ABSOLUTE_CONTROL = 0x0F,
|
||
UVC_CTRL_CT_ROLL_RELATIVE_CONTROL = 0x10,
|
||
UVC_CTRL_CT_PRIVACY_CONTROL = 0x11
|
||
} usbh_uvc_ctrl_vc_cameraterminal_controls_t;
|
||
|
||
typedef enum {
|
||
UVC_CTRL_PU_CONTROL_UNDEFINED = 0x00,
|
||
UVC_CTRL_PU_BACKLIGHT_COMPENSATION_CONTROL = 0x01,
|
||
UVC_CTRL_PU_BRIGHTNESS_CONTROL = 0x02,
|
||
UVC_CTRL_PU_CONTRAST_CONTROL = 0x03,
|
||
UVC_CTRL_PU_GAIN_CONTROL = 0x04,
|
||
UVC_CTRL_PU_POWER_LINE_FREQUENCY_CONTROL = 0x05,
|
||
UVC_CTRL_PU_HUE_CONTROL = 0x06,
|
||
UVC_CTRL_PU_SATURATION_CONTROL = 0x07,
|
||
UVC_CTRL_PU_SHARPNESS_CONTROL = 0x08,
|
||
UVC_CTRL_PU_GAMMA_CONTROL = 0x09,
|
||
UVC_CTRL_PU_WHITE_BALANCE_TEMPERATURE_CONTROL = 0x0A,
|
||
UVC_CTRL_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL = 0x0B,
|
||
UVC_CTRL_PU_WHITE_BALANCE_COMPONENT_CONTROL = 0x0C,
|
||
UVC_CTRL_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL = 0x0D,
|
||
UVC_CTRL_PU_DIGITAL_MULTIPLIER_CONTROL = 0x0E,
|
||
UVC_CTRL_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL = 0x0F,
|
||
UVC_CTRL_PU_HUE_AUTO_CONTROL = 0x10,
|
||
UVC_CTRL_PU_ANALOG_VIDEO_STANDARD_CONTROL = 0x11,
|
||
UVC_CTRL_PU_ANALOG_LOCK_STATUS_CONTROL = 0x12,
|
||
} usbh_uvc_ctrl_vc_processingunit_controls_t;
|
||
|
||
typedef enum {
|
||
UVC_CTRL_VS_CONTROL_UNDEFINED = 0x00,
|
||
UVC_CTRL_VS_PROBE_CONTROL = 0x01,
|
||
UVC_CTRL_VS_COMMIT_CONTROL = 0x02,
|
||
UVC_CTRL_VS_STILL_PROBE_CONTROL = 0x03,
|
||
UVC_CTRL_VS_STILL_COMMIT_CONTROL = 0x04,
|
||
UVC_CTRL_VS_STILL_IMAGE_TRIGGER_CONTROL = 0x05,
|
||
UVC_CTRL_VS_STREAM_ERROR_CODE_CONTROL = 0x06,
|
||
UVC_CTRL_VS_GENERATE_KEY_FRAME_CONTROL = 0x07,
|
||
UVC_CTRL_VS_UPDATE_FRAME_SEGMENT_CONTROL = 0x08,
|
||
UVC_CTRL_VS_SYNCH_DELAY_CONTROL = 0x09
|
||
} usbh_uvc_ctrl_vs_interface_controls_t;
|
||
|
||
|
||
typedef PACKED_STRUCT {
|
||
uint8_t bLength;
|
||
uint8_t bDescriptorType;
|
||
uint8_t bDescriptorSubType;
|
||
uint8_t bFormatIndex;
|
||
uint8_t bNumFrameDescriptors;
|
||
uint8_t bmFlags;
|
||
uint8_t bDefaultFrameIndex;
|
||
uint8_t bAspectRatioX;
|
||
uint8_t bAspectRatioY;
|
||
uint8_t bmInterfaceFlags;
|
||
uint8_t bCopyProtect;
|
||
} usbh_uvc_format_mjpeg_t;
|
||
|
||
typedef PACKED_STRUCT {
|
||
uint8_t bLength;
|
||
uint8_t bDescriptorType;
|
||
uint8_t bDescriptorSubType;
|
||
uint8_t bFrameIndex;
|
||
uint8_t bmCapabilities;
|
||
uint16_t wWidth;
|
||
uint16_t wHeight;
|
||
uint32_t dwMinBitRate;
|
||
uint32_t dwMaxBitRate;
|
||
uint32_t dwMaxVideoFrameBufferSize;
|
||
uint32_t dwDefaultFrameInterval;
|
||
uint8_t bFrameIntervalType;
|
||
uint32_t dwFrameInterval[0];
|
||
} usbh_uvc_frame_mjpeg_t;
|
||
|
||
|
||
typedef PACKED_STRUCT {
|
||
uint8_t bLength;
|
||
uint8_t bDescriptorType;
|
||
uint8_t bDescriptorSubType;
|
||
uint8_t bFrameIndex;
|
||
uint8_t bmCapabilities;
|
||
uint16_t wWidth;
|
||
uint16_t wHeight;
|
||
uint32_t dwMinBitRate;
|
||
uint32_t dwMaxBitRate;
|
||
uint32_t dwMaxVideoFrameBufferSize;
|
||
uint32_t dwDefaultFrameInterval;
|
||
uint8_t bFrameIntervalType;
|
||
uint32_t dwFrameInterval[0];
|
||
} usbh_uvc_frame_uncompressed_t;
|
||
|
||
typedef PACKED_STRUCT {
|
||
uint8_t bLength;
|
||
uint8_t bDescriptorType;
|
||
uint8_t bDescriptorSubType;
|
||
uint8_t bFormatIndex;
|
||
uint8_t bNumFrameDescriptors;
|
||
uint8_t guidFormat[16];
|
||
uint8_t bBitsPerPixel;
|
||
uint8_t bDefaultFrameIndex;
|
||
uint8_t bAspectRatioX;
|
||
uint8_t bAspectRatioY;
|
||
uint8_t bmInterfaceFlags;
|
||
uint8_t bCopyProtect;
|
||
} usbh_uvc_format_uncompressed;
|
||
|
||
typedef PACKED_STRUCT {
|
||
uint16_t bmHint;
|
||
uint8_t bFormatIndex;
|
||
uint8_t bFrameIndex;
|
||
uint32_t dwFrameInterval;
|
||
uint16_t wKeyFrameRate;
|
||
uint16_t wPFrameRate;
|
||
uint16_t wCompQuality;
|
||
uint16_t wCompWindowSize;
|
||
uint16_t wDelay;
|
||
uint32_t dwMaxVideoFrameSize;
|
||
uint32_t dwMaxPayloadTransferSize;
|
||
// uint32_t dwClockFrequency;
|
||
// uint8_t bmFramingInfo;
|
||
// uint8_t bPreferedVersion;
|
||
// uint8_t bMinVersion;
|
||
// uint8_t bMaxVersion;
|
||
} usbh_uvc_ctrl_vs_probecommit_data_t;
|
||
|
||
|
||
|
||
/* D0: Frame ID.
|
||
* For frame-based formats, this bit toggles between 0 and 1 every time a new video frame begins.
|
||
* For stream-based formats, this bit toggles between 0 and 1 at the start of each new codec-specific
|
||
* segment. This behavior is required for frame-based payload formats (e.g., DV) and is optional
|
||
* for stream-based payload formats (e.g., MPEG-2 TS). For stream-based formats, support for this
|
||
* bit must be indicated via the bmFramingInfofield of the Video Probe and Commitcontrols
|
||
* (see section 4.3.1.1, <20>Video Probe and Commit Controls<6C>).
|
||
*
|
||
* D1: End of Frame.
|
||
* This bit is set if the following payload data marks the end of the current video or still image
|
||
* frame (for framebased formats), or to indicate the end of a codec-specific segment
|
||
* (for stream-based formats). This behavior is optional for all payload formats.
|
||
* For stream-based formats, support for this bit must be indicated via the bmFramingInfofield
|
||
* of the Video Probe and CommitControls (see section 4.3.1.1, <20>Video Probe and Commit Controls<6C>).
|
||
*
|
||
* D2: Presentation Time.
|
||
* This bit is set if the dwPresentationTimefield is being sent as part of the header.
|
||
*
|
||
* D3: Source Clock Reference
|
||
* This bit is set if the dwSourceClockfield is being sent as part of the header.
|
||
*
|
||
* D4: Reserved
|
||
*
|
||
* D5: Still Image
|
||
* This bit is set ifthe following data is part of a still image frame, and is only used for
|
||
* methods 2 and 3 of still image capture.
|
||
*
|
||
* D6: Error
|
||
* This bit is set ifthere was an error in the video or still image transmission
|
||
* for this payload. The StreamError Code control would reflect the cause of the error.
|
||
*
|
||
* D7: End of header
|
||
* This bit is set if this is the last header group in the packet, where the
|
||
* header group refers to this field and any optional fields identified by the bits in this
|
||
* field (Defined for future extension)
|
||
*/
|
||
|
||
#define UVC_HDR_EOH (1 << 7) /* End of header */
|
||
#define UVC_HDR_ERR (1 << 6) /* Error */
|
||
#define UVC_HDR_STILL (1 << 5) /* Still Image */
|
||
#define UVC_HDR_SCR (1 << 3) /* Source Clock Reference */
|
||
#define UVC_HDR_PT (1 << 2) /* Presentation Time */
|
||
#define UVC_HDR_EOF (1 << 1) /* End of Frame */
|
||
#define UVC_HDR_FID (1 << 0) /* Frame ID */
|
||
|
||
|
||
|
||
typedef struct USBHUVCDriver USBHUVCDriver;
|
||
|
||
#define USBHUVC_MESSAGETYPE_STATUS 1
|
||
#define USBHUVC_MESSAGETYPE_DATA 2
|
||
|
||
|
||
#define _usbhuvc_message_base_data \
|
||
uint16_t type; \
|
||
uint16_t length; \
|
||
systime_t timestamp;
|
||
|
||
typedef struct {
|
||
_usbhuvc_message_base_data
|
||
} usbhuvc_message_base_t;
|
||
|
||
typedef struct {
|
||
_usbhuvc_message_base_data
|
||
USBH_DECLARE_STRUCT_MEMBER(uint8_t data[0]);
|
||
} usbhuvc_message_data_t;
|
||
|
||
typedef struct {
|
||
_usbhuvc_message_base_data
|
||
USBH_DECLARE_STRUCT_MEMBER(uint8_t data[USBHUVC_MAX_STATUS_PACKET_SZ]);
|
||
} usbhuvc_message_status_t;
|
||
|
||
|
||
typedef enum {
|
||
USBHUVC_STATE_UNINITIALIZED = 0, //must call usbhuvcObjectInit
|
||
USBHUVC_STATE_STOP = 1, //the device is disconnected
|
||
USBHUVC_STATE_ACTIVE = 2, //the device is connected
|
||
USBHUVC_STATE_READY = 3, //the device has negotiated the parameters
|
||
USBHUVC_STATE_STREAMING = 4, //the device is streaming data
|
||
USBHUVC_STATE_BUSY = 5 //the driver is busy performing some action
|
||
} usbhuvc_state_t;
|
||
|
||
|
||
struct USBHUVCDriver {
|
||
/* inherited from abstract class driver */
|
||
_usbh_base_classdriver_data
|
||
|
||
usbhuvc_state_t state;
|
||
|
||
usbh_ep_t ep_int;
|
||
usbh_ep_t ep_iso;
|
||
|
||
usbh_urb_t urb_iso;
|
||
usbh_urb_t urb_int;
|
||
|
||
if_iterator_t ivc;
|
||
if_iterator_t ivs;
|
||
|
||
USBH_DECLARE_STRUCT_MEMBER(usbh_uvc_ctrl_vs_probecommit_data_t pc);
|
||
USBH_DECLARE_STRUCT_MEMBER(usbh_uvc_ctrl_vs_probecommit_data_t pc_min);
|
||
USBH_DECLARE_STRUCT_MEMBER(usbh_uvc_ctrl_vs_probecommit_data_t pc_max);
|
||
|
||
mailbox_t mb;
|
||
msg_t mb_buff[HAL_USBHUVC_MAX_MAILBOX_SZ];
|
||
|
||
memory_pool_t mp_data;
|
||
void *mp_data_buffer;
|
||
|
||
memory_pool_t mp_status;
|
||
usbhuvc_message_status_t mp_status_buffer[HAL_USBHUVC_STATUS_PACKETS_COUNT];
|
||
|
||
mutex_t mtx;
|
||
};
|
||
|
||
|
||
/*===========================================================================*/
|
||
/* Driver macros. */
|
||
/*===========================================================================*/
|
||
|
||
|
||
/*===========================================================================*/
|
||
/* External declarations. */
|
||
/*===========================================================================*/
|
||
|
||
extern USBHUVCDriver USBHUVCD[HAL_USBHUVC_MAX_INSTANCES];
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
static inline usbhuvc_state_t usbhuvcGetState(USBHUVCDriver *uvcd) {
|
||
return uvcd->state;
|
||
}
|
||
|
||
bool usbhuvcVCRequest(USBHUVCDriver *uvcdp,
|
||
uint8_t bRequest, uint8_t entity, uint8_t control,
|
||
uint16_t wLength, uint8_t *data);
|
||
bool usbhuvcVSRequest(USBHUVCDriver *uvcdp,
|
||
uint8_t bRequest, uint8_t control,
|
||
uint16_t wLength, uint8_t *data);
|
||
bool usbhuvcFindVSDescriptor(USBHUVCDriver *uvcdp,
|
||
generic_iterator_t *ics,
|
||
uint8_t bDescriptorSubtype,
|
||
bool start);
|
||
uint32_t usbhuvcEstimateRequiredEPSize(USBHUVCDriver *uvcdp, const uint8_t *formatdesc,
|
||
const uint8_t *framedesc, uint32_t dwFrameInterval);
|
||
|
||
#if USBH_DEBUG_ENABLE && USBHUVC_DEBUG_ENABLE_INFO
|
||
void usbhuvcPrintProbeCommit(USBHUVCDriver *uvcdp, const usbh_uvc_ctrl_vs_probecommit_data_t *pc);
|
||
#else
|
||
# define usbhuvcPrintProbeCommit(uvcdp, pc) do {} while(0)
|
||
#endif
|
||
bool usbhuvcProbe(USBHUVCDriver *uvcdp);
|
||
bool usbhuvcCommit(USBHUVCDriver *uvcdp);
|
||
void usbhuvcResetPC(USBHUVCDriver *uvcdp);
|
||
static inline const usbh_uvc_ctrl_vs_probecommit_data_t *usbhuvcGetPCMin(USBHUVCDriver *uvcdp) {
|
||
return &uvcdp->pc_min;
|
||
}
|
||
static inline const usbh_uvc_ctrl_vs_probecommit_data_t *usbhuvcGetPCMax(USBHUVCDriver *uvcdp) {
|
||
return &uvcdp->pc_min;
|
||
}
|
||
static inline usbh_uvc_ctrl_vs_probecommit_data_t *usbhuvcGetPC(USBHUVCDriver *uvcdp) {
|
||
return &uvcdp->pc;
|
||
}
|
||
|
||
bool usbhuvcStreamStart(USBHUVCDriver *uvcdp, uint16_t min_ep_sz);
|
||
bool usbhuvcStreamStop(USBHUVCDriver *uvcdp);
|
||
|
||
static inline msg_t usbhuvcLockAndFetchS(USBHUVCDriver *uvcdp, msg_t *msg, systime_t timeout) {
|
||
chMtxLockS(&uvcdp->mtx);
|
||
msg_t ret = chMBFetchTimeoutS(&uvcdp->mb, msg, timeout);
|
||
if (ret != MSG_OK)
|
||
chMtxUnlockS(&uvcdp->mtx);
|
||
return ret;
|
||
}
|
||
static inline msg_t usbhuvcLockAndFetch(USBHUVCDriver *uvcdp, msg_t *msg, systime_t timeout) {
|
||
osalSysLock();
|
||
msg_t ret = usbhuvcLockAndFetchS(uvcdp, msg, timeout);
|
||
osalSysUnlock();
|
||
return ret;
|
||
}
|
||
static inline void usbhuvcUnlock(USBHUVCDriver *uvcdp) {
|
||
chMtxUnlock(&uvcdp->mtx);
|
||
}
|
||
static inline void usbhuvcFreeDataMessage(USBHUVCDriver *uvcdp, usbhuvc_message_data_t *msg) {
|
||
chPoolFree(&uvcdp->mp_data, msg);
|
||
}
|
||
static inline void usbhuvcFreeStatusMessage(USBHUVCDriver *uvcdp, usbhuvc_message_status_t *msg) {
|
||
chPoolFree(&uvcdp->mp_status, msg);
|
||
}
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif
|
||
|
||
#endif /* USBH_INCLUDE_USBH_UVC_H_ */
|