1163 lines
50 KiB
C
1163 lines
50 KiB
C
/*
|
|
* Copyright (c) 2015 - 2016, Freescale Semiconductor, Inc.
|
|
* Copyright 2016 - 2017, 2019 NXP
|
|
* All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
/*${standard_header_anchor}*/
|
|
#include "usb_device_config.h"
|
|
#include "usb.h"
|
|
#include "usb_device.h"
|
|
|
|
#include "usb_device_video.h"
|
|
|
|
#include "usb_device_ch9.h"
|
|
#include "usb_device_descriptor.h"
|
|
|
|
#include "virtual_camera.h"
|
|
|
|
#include "video_data.h"
|
|
|
|
#include "fsl_device_registers.h"
|
|
#include "fsl_debug_console.h"
|
|
#include "pin_mux.h"
|
|
#include "clock_config.h"
|
|
#include "board.h"
|
|
|
|
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
|
|
#include "fsl_sysmpu.h"
|
|
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
|
|
|
|
#if ((defined FSL_FEATURE_SOC_USBPHY_COUNT) && (FSL_FEATURE_SOC_USBPHY_COUNT > 0U))
|
|
#include "usb_phy.h"
|
|
#endif
|
|
|
|
/*******************************************************************************
|
|
* Definitions
|
|
******************************************************************************/
|
|
|
|
/*******************************************************************************
|
|
* Prototypes
|
|
******************************************************************************/
|
|
void BOARD_InitHardware(void);
|
|
void USB_DeviceClockInit(void);
|
|
void USB_DeviceIsrEnable(void);
|
|
#if USB_DEVICE_CONFIG_USE_TASK
|
|
void USB_DeviceTaskFn(void *deviceHandle);
|
|
#endif
|
|
|
|
static void USB_DeviceVideoPrepareVideoData(void);
|
|
static usb_status_t USB_DeviceVideoIsoIn(usb_device_handle deviceHandle,
|
|
usb_device_endpoint_callback_message_struct_t *event,
|
|
void *arg);
|
|
static void USB_DeviceVideoApplicationSetDefault(void);
|
|
static usb_status_t USB_DeviceVideoProcessClassVsProbeRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceVideoProcessClassVsCommitRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceVideoProcessClassVsStillProbeRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceVideoProcessClassVsStillCommitRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceVideoProcessClassVsStillImageTriggerRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceVideoProcessClassVsRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceProcessClassVcInterfaceRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceProcessClassVcCameraTerminalRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceProcessClassVcInputTerminalRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceProcessClassVcOutputTerminalRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceProcessClassVcProcessingUintRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static usb_status_t USB_DeviceProcessClassVcRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer);
|
|
static void USB_DeviceApplicationInit(void);
|
|
/*******************************************************************************
|
|
* Variables
|
|
******************************************************************************/
|
|
|
|
extern const unsigned char g_UsbDeviceVideoMjpegData[];
|
|
extern const uint32_t g_UsbDeviceVideoMjpegLength;
|
|
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
|
|
static usb_device_video_probe_and_commit_controls_struct_t s_ProbeStruct;
|
|
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
|
|
static usb_device_video_probe_and_commit_controls_struct_t s_CommitStruct;
|
|
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
|
|
static usb_device_video_still_probe_and_commit_controls_struct_t s_StillProbeStruct;
|
|
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
|
|
static usb_device_video_still_probe_and_commit_controls_struct_t s_StillCommitStruct;
|
|
/* this buffer is used to do transfer */
|
|
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE) uint8_t s_ImageBuffer[HS_STREAM_IN_PACKET_SIZE];
|
|
usb_video_virtual_camera_struct_t g_UsbDeviceVideoVirtualCamera;
|
|
|
|
extern uint8_t g_UsbDeviceCurrentConfigure;
|
|
extern uint8_t g_UsbDeviceInterface[USB_VIDEO_VIRTUAL_CAMERA_INTERFACE_COUNT];
|
|
USB_DMA_NONINIT_DATA_ALIGN(USB_DATA_ALIGN_SIZE)
|
|
static uint32_t s_SetupOutBuffer[(sizeof(usb_device_video_probe_and_commit_controls_struct_t) >> 2U) + 1U];
|
|
|
|
/*******************************************************************************
|
|
* Code
|
|
******************************************************************************/
|
|
|
|
void USB_OTG1_IRQHandler(void)
|
|
{
|
|
USB_DeviceEhciIsrFunction(g_UsbDeviceVideoVirtualCamera.deviceHandle);
|
|
}
|
|
|
|
void USB_DeviceClockInit(void)
|
|
{
|
|
usb_phy_config_struct_t phyConfig = {
|
|
BOARD_USB_PHY_D_CAL,
|
|
BOARD_USB_PHY_TXCAL45DP,
|
|
BOARD_USB_PHY_TXCAL45DM,
|
|
};
|
|
|
|
CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
|
|
CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
|
|
USB_EhciPhyInit(CONTROLLER_ID, BOARD_XTAL0_CLK_HZ, &phyConfig);
|
|
}
|
|
void USB_DeviceIsrEnable(void)
|
|
{
|
|
uint8_t irqNumber;
|
|
|
|
uint8_t usbDeviceEhciIrq[] = USBHS_IRQS;
|
|
irqNumber = usbDeviceEhciIrq[CONTROLLER_ID - kUSB_ControllerEhci0];
|
|
|
|
/* Install isr, set priority, and enable IRQ. */
|
|
NVIC_SetPriority((IRQn_Type)irqNumber, USB_DEVICE_INTERRUPT_PRIORITY);
|
|
EnableIRQ((IRQn_Type)irqNumber);
|
|
}
|
|
#if USB_DEVICE_CONFIG_USE_TASK
|
|
void USB_DeviceTaskFn(void *deviceHandle)
|
|
{
|
|
USB_DeviceEhciTaskFunction(deviceHandle);
|
|
}
|
|
#endif
|
|
|
|
/* Prepare next transfer payload */
|
|
static void USB_DeviceVideoPrepareVideoData(void)
|
|
{
|
|
usb_device_video_mjpeg_payload_header_struct_t *payloadHeader;
|
|
uint32_t maxPacketSize;
|
|
uint32_t temp32dwFrameInterval;
|
|
/* update the current time counter, add 1 ms in this case */
|
|
g_UsbDeviceVideoVirtualCamera.currentTime += 10000U;
|
|
/* get payload header buffer from imageBuffer */
|
|
payloadHeader = (usb_device_video_mjpeg_payload_header_struct_t *)&g_UsbDeviceVideoVirtualCamera.imageBuffer[0];
|
|
/* set payload header length */
|
|
payloadHeader->bHeaderLength = sizeof(usb_device_video_mjpeg_payload_header_struct_t);
|
|
payloadHeader->headerInfoUnion.bmheaderInfo = 0U;
|
|
/* set frame id */
|
|
payloadHeader->headerInfoUnion.headerInfoBits.frameIdentifier = g_UsbDeviceVideoVirtualCamera.currentFrameId;
|
|
g_UsbDeviceVideoVirtualCamera.imageBufferLength = sizeof(usb_device_video_mjpeg_payload_header_struct_t);
|
|
|
|
/* the current frame need to be still image */
|
|
if (g_UsbDeviceVideoVirtualCamera.stillImageTransmission)
|
|
{
|
|
payloadHeader->headerInfoUnion.headerInfoBits.stillImage = 1U;
|
|
maxPacketSize =
|
|
USB_LONG_FROM_LITTLE_ENDIAN_DATA(g_UsbDeviceVideoVirtualCamera.stillCommitStruct->dwMaxPayloadTransferSize);
|
|
}
|
|
else
|
|
{
|
|
maxPacketSize =
|
|
USB_LONG_FROM_LITTLE_ENDIAN_DATA(g_UsbDeviceVideoVirtualCamera.commitStruct->dwMaxPayloadTransferSize);
|
|
}
|
|
|
|
/* wait for the next frame interval */
|
|
if (g_UsbDeviceVideoVirtualCamera.waitForNewInterval)
|
|
{
|
|
temp32dwFrameInterval =
|
|
USB_LONG_FROM_LITTLE_ENDIAN_DATA(g_UsbDeviceVideoVirtualCamera.commitStruct->dwFrameInterval);
|
|
/* the current time is still in transferred frame, return to continue waiting */
|
|
if (g_UsbDeviceVideoVirtualCamera.currentTime < temp32dwFrameInterval)
|
|
{
|
|
return;
|
|
}
|
|
else /* next frame time */
|
|
{
|
|
/* before the new frame starts transfer, set endOfFrame of the current frame is 1, this frame may not have payload */
|
|
payloadHeader->headerInfoUnion.headerInfoBits.endOfFrame = 1U;
|
|
/* prepare to transfer new frame, reset the current time */
|
|
g_UsbDeviceVideoVirtualCamera.currentTime = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.waitForNewInterval = 0U;
|
|
/* clear the still image transmission flag */
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTransmission = 0U;
|
|
/* toggle frame id for the next frame */
|
|
g_UsbDeviceVideoVirtualCamera.currentFrameId ^= 1U;
|
|
/* next frame is still image */
|
|
if (USB_DEVICE_VIDEO_STILL_IMAGE_TRIGGER_TRANSMIT_STILL_IMAGE ==
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTriggerControl)
|
|
{
|
|
/* reset the image trigger control as normal operation */
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTriggerControl =
|
|
USB_DEVICE_VIDEO_STILL_IMAGE_TRIGGER_NORMAL_OPERATION;
|
|
/* still image starts transfer */
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTransmission = 1U;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* copy paypoad to image buffer, copy size is maxPacketSize every time */
|
|
for (; g_UsbDeviceVideoVirtualCamera.imageBufferLength < maxPacketSize;
|
|
g_UsbDeviceVideoVirtualCamera.imageBufferLength++)
|
|
{
|
|
g_UsbDeviceVideoVirtualCamera.imageBuffer[g_UsbDeviceVideoVirtualCamera.imageBufferLength] =
|
|
g_UsbDeviceVideoMjpegData[g_UsbDeviceVideoVirtualCamera.imageIndex];
|
|
g_UsbDeviceVideoVirtualCamera.imageIndex++;
|
|
|
|
/* the end of one frame */
|
|
if ((0xFFU == g_UsbDeviceVideoMjpegData[g_UsbDeviceVideoVirtualCamera.imageIndex - 2]) &&
|
|
(0xD9U == g_UsbDeviceVideoMjpegData[g_UsbDeviceVideoVirtualCamera.imageIndex - 1U]))
|
|
{
|
|
/* get the negotiated frame interval */
|
|
temp32dwFrameInterval =
|
|
USB_LONG_FROM_LITTLE_ENDIAN_DATA(g_UsbDeviceVideoVirtualCamera.commitStruct->dwFrameInterval);
|
|
/* back to the start of stream mjpeg data if reach to the end of the video data buffer */
|
|
if (g_UsbDeviceVideoVirtualCamera.imageIndex >= g_UsbDeviceVideoMjpegLength)
|
|
{
|
|
g_UsbDeviceVideoVirtualCamera.imageIndex = 0U;
|
|
}
|
|
/* finish to transfer this frame, if there is still time left, start transfer in next frame interval */
|
|
if (g_UsbDeviceVideoVirtualCamera.currentTime < temp32dwFrameInterval)
|
|
{
|
|
g_UsbDeviceVideoVirtualCamera.waitForNewInterval = 1U;
|
|
}
|
|
else /* the current fame is finished, next frame can start */
|
|
{
|
|
/* before the new frame starts transfer, set endOfFrame of the current frame is 1, this frame may not have payload */
|
|
payloadHeader->headerInfoUnion.headerInfoBits.endOfFrame = 1U;
|
|
/* prepare to transfer new frame, reset the current time */
|
|
g_UsbDeviceVideoVirtualCamera.currentTime = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTransmission = 0U;
|
|
/* toggle frame id for the next frame */
|
|
g_UsbDeviceVideoVirtualCamera.currentFrameId ^= 1U;
|
|
if (USB_DEVICE_VIDEO_STILL_IMAGE_TRIGGER_TRANSMIT_STILL_IMAGE ==
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTriggerControl)
|
|
{
|
|
/* reset the image trigger control as normal operation */
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTriggerControl =
|
|
USB_DEVICE_VIDEO_STILL_IMAGE_TRIGGER_NORMAL_OPERATION;
|
|
/* still image starts transfer */
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTransmission = 1U;
|
|
}
|
|
}
|
|
g_UsbDeviceVideoVirtualCamera.imageBufferLength++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* USB device video ISO IN endpoint callback */
|
|
static usb_status_t USB_DeviceVideoIsoIn(usb_device_handle deviceHandle,
|
|
usb_device_endpoint_callback_message_struct_t *event,
|
|
void *arg)
|
|
{
|
|
if (g_UsbDeviceVideoVirtualCamera.attach)
|
|
{
|
|
USB_DeviceVideoPrepareVideoData();
|
|
return USB_DeviceSendRequest(deviceHandle, USB_VIDEO_VIRTUAL_CAMERA_STREAM_ENDPOINT_IN,
|
|
g_UsbDeviceVideoVirtualCamera.imageBuffer,
|
|
g_UsbDeviceVideoVirtualCamera.imageBufferLength);
|
|
}
|
|
|
|
return kStatus_USB_Error;
|
|
}
|
|
|
|
/* Set to default state */
|
|
static void USB_DeviceVideoApplicationSetDefault(void)
|
|
{
|
|
g_UsbDeviceVideoVirtualCamera.speed = USB_SPEED_FULL;
|
|
g_UsbDeviceVideoVirtualCamera.attach = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize = HS_STREAM_IN_PACKET_SIZE;
|
|
g_UsbDeviceVideoVirtualCamera.imageBuffer = s_ImageBuffer;
|
|
g_UsbDeviceVideoVirtualCamera.probeStruct = &s_ProbeStruct;
|
|
g_UsbDeviceVideoVirtualCamera.commitStruct = &s_CommitStruct;
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeStruct = &s_StillProbeStruct;
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitStruct = &s_StillCommitStruct;
|
|
|
|
g_UsbDeviceVideoVirtualCamera.probeStruct->bFormatIndex = USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FORMAT_INDEX;
|
|
g_UsbDeviceVideoVirtualCamera.probeStruct->bFrameIndex = USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_INDEX;
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_DEFAULT_INTERVAL,
|
|
g_UsbDeviceVideoVirtualCamera.probeStruct->dwFrameInterval);
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize,
|
|
g_UsbDeviceVideoVirtualCamera.probeStruct->dwMaxPayloadTransferSize);
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_MAX_FRAME_SIZE,
|
|
g_UsbDeviceVideoVirtualCamera.probeStruct->dwMaxVideoFrameSize);
|
|
|
|
g_UsbDeviceVideoVirtualCamera.commitStruct->bFormatIndex = USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FORMAT_INDEX;
|
|
g_UsbDeviceVideoVirtualCamera.commitStruct->bFrameIndex = USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_INDEX;
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_DEFAULT_INTERVAL,
|
|
g_UsbDeviceVideoVirtualCamera.commitStruct->dwFrameInterval);
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize,
|
|
g_UsbDeviceVideoVirtualCamera.commitStruct->dwMaxPayloadTransferSize);
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_MAX_FRAME_SIZE,
|
|
g_UsbDeviceVideoVirtualCamera.commitStruct->dwMaxVideoFrameSize);
|
|
|
|
g_UsbDeviceVideoVirtualCamera.probeInfo = 0x03U;
|
|
g_UsbDeviceVideoVirtualCamera.probeLength = 26U;
|
|
g_UsbDeviceVideoVirtualCamera.commitInfo = 0x03U;
|
|
g_UsbDeviceVideoVirtualCamera.commitLength = 26U;
|
|
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeStruct->bFormatIndex = USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FORMAT_INDEX;
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeStruct->bFrameIndex = USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_INDEX;
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeStruct->bCompressionIndex = 0x01U;
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize,
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeStruct->dwMaxPayloadTransferSize);
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_MAX_FRAME_SIZE,
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeStruct->dwMaxVideoFrameSize);
|
|
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitStruct->bFormatIndex = USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FORMAT_INDEX;
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitStruct->bFrameIndex = USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_INDEX;
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitStruct->bCompressionIndex = 0x01U;
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize,
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitStruct->dwMaxPayloadTransferSize);
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_MAX_FRAME_SIZE,
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitStruct->dwMaxVideoFrameSize);
|
|
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeInfo = 0x03U;
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeLength = sizeof(s_StillProbeStruct);
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitInfo = 0x03U;
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitLength = sizeof(s_StillCommitStruct);
|
|
|
|
g_UsbDeviceVideoVirtualCamera.currentTime = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.currentFrameId = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.currentStreamInterfaceAlternateSetting = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.imageBufferLength = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.imageIndex = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.waitForNewInterval = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTransmission = 0U;
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTriggerControl = USB_DEVICE_VIDEO_STILL_IMAGE_TRIGGER_NORMAL_OPERATION;
|
|
}
|
|
|
|
/* Device callback */
|
|
usb_status_t USB_DeviceCallback(usb_device_handle handle, uint32_t event, void *param)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint8_t *temp8 = (uint8_t *)param;
|
|
|
|
switch (event)
|
|
{
|
|
case kUSB_DeviceEventBusReset:
|
|
{
|
|
USB_DeviceControlPipeInit(g_UsbDeviceVideoVirtualCamera.deviceHandle);
|
|
USB_DeviceVideoApplicationSetDefault();
|
|
error = kStatus_USB_Success;
|
|
#if (defined(USB_DEVICE_CONFIG_EHCI) && (USB_DEVICE_CONFIG_EHCI > 0U)) || \
|
|
(defined(USB_DEVICE_CONFIG_LPCIP3511HS) && (USB_DEVICE_CONFIG_LPCIP3511HS > 0U))
|
|
/* Get USB speed to configure the device, including max packet size and interval of the endpoints. */
|
|
if (kStatus_USB_Success == USB_DeviceGetStatus(g_UsbDeviceVideoVirtualCamera.deviceHandle,
|
|
kUSB_DeviceStatusSpeed,
|
|
&g_UsbDeviceVideoVirtualCamera.speed))
|
|
{
|
|
USB_DeviceSetSpeed(g_UsbDeviceVideoVirtualCamera.speed);
|
|
}
|
|
|
|
if (USB_SPEED_HIGH == g_UsbDeviceVideoVirtualCamera.speed)
|
|
{
|
|
g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize = HS_STREAM_IN_PACKET_SIZE;
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventSetConfiguration:
|
|
if (USB_VIDEO_VIRTUAL_CAMERA_CONFIGURE_INDEX == (*temp8))
|
|
{
|
|
g_UsbDeviceVideoVirtualCamera.attach = 1U;
|
|
error = kStatus_USB_Success;
|
|
}
|
|
break;
|
|
case kUSB_DeviceEventSetInterface:
|
|
if ((g_UsbDeviceVideoVirtualCamera.attach) && param)
|
|
{
|
|
uint8_t interface = (*temp8) & 0xFFU;
|
|
uint8_t alternateSetting = g_UsbDeviceInterface[interface];
|
|
error = kStatus_USB_Success;
|
|
if (g_UsbDeviceVideoVirtualCamera.currentStreamInterfaceAlternateSetting != alternateSetting)
|
|
{
|
|
if (g_UsbDeviceVideoVirtualCamera.currentStreamInterfaceAlternateSetting)
|
|
{
|
|
USB_DeviceDeinitEndpoint(g_UsbDeviceVideoVirtualCamera.deviceHandle,
|
|
USB_VIDEO_VIRTUAL_CAMERA_STREAM_ENDPOINT_IN |
|
|
(USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT));
|
|
}
|
|
else
|
|
{
|
|
usb_device_endpoint_init_struct_t epInitStruct;
|
|
usb_device_endpoint_callback_struct_t epCallback;
|
|
|
|
epCallback.callbackFn = USB_DeviceVideoIsoIn;
|
|
epCallback.callbackParam = handle;
|
|
|
|
epInitStruct.zlt = 0U;
|
|
epInitStruct.transferType = USB_ENDPOINT_ISOCHRONOUS;
|
|
epInitStruct.endpointAddress = USB_VIDEO_VIRTUAL_CAMERA_STREAM_ENDPOINT_IN |
|
|
(USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT);
|
|
if (USB_SPEED_HIGH == g_UsbDeviceVideoVirtualCamera.speed)
|
|
{
|
|
epInitStruct.maxPacketSize = HS_STREAM_IN_PACKET_SIZE;
|
|
epInitStruct.interval = HS_STREAM_IN_INTERVAL;
|
|
}
|
|
else
|
|
{
|
|
epInitStruct.maxPacketSize = FS_STREAM_IN_PACKET_SIZE;
|
|
epInitStruct.interval = FS_STREAM_IN_INTERVAL;
|
|
}
|
|
|
|
USB_DeviceInitEndpoint(g_UsbDeviceVideoVirtualCamera.deviceHandle, &epInitStruct, &epCallback);
|
|
USB_DeviceVideoPrepareVideoData();
|
|
error = USB_DeviceSendRequest(
|
|
g_UsbDeviceVideoVirtualCamera.deviceHandle, USB_VIDEO_VIRTUAL_CAMERA_STREAM_ENDPOINT_IN,
|
|
g_UsbDeviceVideoVirtualCamera.imageBuffer, g_UsbDeviceVideoVirtualCamera.imageBufferLength);
|
|
}
|
|
g_UsbDeviceVideoVirtualCamera.currentStreamInterfaceAlternateSetting = alternateSetting;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/* Get the setup buffer */
|
|
usb_status_t USB_DeviceGetSetupBuffer(usb_device_handle handle, usb_setup_struct_t **setupBuffer)
|
|
{
|
|
static uint32_t setup[2];
|
|
if (NULL == setupBuffer)
|
|
{
|
|
return kStatus_USB_InvalidParameter;
|
|
}
|
|
*setupBuffer = (usb_setup_struct_t *)&setup;
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
/* Configure remote wakeup(Enable or disbale) */
|
|
usb_status_t USB_DeviceConfigureRemoteWakeup(usb_device_handle handle, uint8_t enable)
|
|
{
|
|
return kStatus_USB_Success;
|
|
}
|
|
/* Configure endpoint status(Idle or stall) */
|
|
usb_status_t USB_DeviceConfigureEndpointStatus(usb_device_handle handle, uint8_t ep, uint8_t status)
|
|
{
|
|
if (status)
|
|
{
|
|
if ((USB_VIDEO_VIRTUAL_CAMERA_STREAM_ENDPOINT_IN == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
|
|
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
|
|
{
|
|
return USB_DeviceStallEndpoint(handle, ep);
|
|
}
|
|
else if ((USB_VIDEO_VIRTUAL_CAMERA_CONTROL_ENDPOINT == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
|
|
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
|
|
{
|
|
return USB_DeviceStallEndpoint(handle, ep);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((USB_VIDEO_VIRTUAL_CAMERA_STREAM_ENDPOINT_IN == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
|
|
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
|
|
{
|
|
return USB_DeviceUnstallEndpoint(handle, ep);
|
|
}
|
|
else if ((USB_VIDEO_VIRTUAL_CAMERA_CONTROL_ENDPOINT == (ep & USB_ENDPOINT_NUMBER_MASK)) &&
|
|
(ep & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK))
|
|
{
|
|
return USB_DeviceUnstallEndpoint(handle, ep);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
return kStatus_USB_InvalidRequest;
|
|
}
|
|
|
|
/* Get class-specific request buffer */
|
|
usb_status_t USB_DeviceGetClassReceiveBuffer(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
if ((NULL == buffer) || ((*length) > sizeof(s_SetupOutBuffer)))
|
|
{
|
|
return kStatus_USB_InvalidRequest;
|
|
}
|
|
*buffer = (uint8_t *)&s_SetupOutBuffer[0];
|
|
return kStatus_USB_Success;
|
|
}
|
|
|
|
/* Precess class-specific VS probe request */
|
|
static usb_status_t USB_DeviceVideoProcessClassVsProbeRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_device_video_probe_and_commit_controls_struct_t *probe;
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint32_t temp32;
|
|
|
|
if ((NULL == buffer) || (NULL == length))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
probe = (usb_device_video_probe_and_commit_controls_struct_t *)(*buffer);
|
|
|
|
switch (setup->bRequest)
|
|
{
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
|
|
if ((*buffer == NULL) || (*length == 0U))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
temp32 = USB_LONG_FROM_LITTLE_ENDIAN_DATA(probe->dwFrameInterval);
|
|
if ((temp32 >= USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_MIN_INTERVAL) &&
|
|
(temp32 <= USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_MAX_INTERVAL))
|
|
{
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(temp32, g_UsbDeviceVideoVirtualCamera.probeStruct->dwFrameInterval);
|
|
}
|
|
|
|
temp32 = USB_LONG_FROM_LITTLE_ENDIAN_DATA(probe->dwMaxPayloadTransferSize);
|
|
if ((temp32) && (temp32 < g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize))
|
|
{
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(temp32,
|
|
g_UsbDeviceVideoVirtualCamera.probeStruct->dwMaxPayloadTransferSize);
|
|
}
|
|
|
|
g_UsbDeviceVideoVirtualCamera.probeStruct->bFormatIndex = probe->bFormatIndex;
|
|
g_UsbDeviceVideoVirtualCamera.probeStruct->bFrameIndex = probe->bFrameIndex;
|
|
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
|
|
*buffer = (uint8_t *)g_UsbDeviceVideoVirtualCamera.probeStruct;
|
|
*length = g_UsbDeviceVideoVirtualCamera.probeLength;
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MIN:
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MAX:
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_RES:
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
|
|
*buffer = &g_UsbDeviceVideoVirtualCamera.probeLength;
|
|
*length = sizeof(g_UsbDeviceVideoVirtualCamera.probeLength);
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
|
|
*buffer = &g_UsbDeviceVideoVirtualCamera.probeInfo;
|
|
*length = sizeof(g_UsbDeviceVideoVirtualCamera.probeInfo);
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_DEF:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VS commit request */
|
|
static usb_status_t USB_DeviceVideoProcessClassVsCommitRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_device_video_probe_and_commit_controls_struct_t *commit;
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint32_t temp32;
|
|
|
|
if ((NULL == buffer) || (NULL == length))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
commit = (usb_device_video_probe_and_commit_controls_struct_t *)(*buffer);
|
|
switch (setup->bRequest)
|
|
{
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
|
|
if ((*buffer == NULL) || (*length == 0U))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
temp32 = USB_LONG_FROM_LITTLE_ENDIAN_DATA(commit->dwFrameInterval);
|
|
if ((temp32 >= USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_MIN_INTERVAL) &&
|
|
(temp32 <= USB_VIDEO_VIRTUAL_CAMERA_MJPEG_FRAME_MAX_INTERVAL))
|
|
{
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(temp32, g_UsbDeviceVideoVirtualCamera.commitStruct->dwFrameInterval);
|
|
}
|
|
|
|
temp32 = USB_LONG_FROM_LITTLE_ENDIAN_DATA(commit->dwMaxPayloadTransferSize);
|
|
if ((temp32) && (temp32 < g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize))
|
|
{
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(temp32,
|
|
g_UsbDeviceVideoVirtualCamera.commitStruct->dwMaxPayloadTransferSize);
|
|
}
|
|
|
|
g_UsbDeviceVideoVirtualCamera.commitStruct->bFormatIndex = commit->bFormatIndex;
|
|
g_UsbDeviceVideoVirtualCamera.commitStruct->bFrameIndex = commit->bFrameIndex;
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
|
|
*buffer = (uint8_t *)g_UsbDeviceVideoVirtualCamera.commitStruct;
|
|
*length = g_UsbDeviceVideoVirtualCamera.commitLength;
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
|
|
*buffer = &g_UsbDeviceVideoVirtualCamera.commitLength;
|
|
*length = sizeof(g_UsbDeviceVideoVirtualCamera.commitLength);
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
|
|
*buffer = &g_UsbDeviceVideoVirtualCamera.commitInfo;
|
|
*length = sizeof(g_UsbDeviceVideoVirtualCamera.commitInfo);
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VS STILL probe request */
|
|
static usb_status_t USB_DeviceVideoProcessClassVsStillProbeRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_device_video_still_probe_and_commit_controls_struct_t *still_probe;
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint32_t temp32;
|
|
|
|
if ((NULL == buffer) || (NULL == length))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
still_probe = (usb_device_video_still_probe_and_commit_controls_struct_t *)(*buffer);
|
|
|
|
switch (setup->bRequest)
|
|
{
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
|
|
if ((*buffer == NULL) || (*length == 0U))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
temp32 = USB_LONG_FROM_LITTLE_ENDIAN_DATA(still_probe->dwMaxPayloadTransferSize);
|
|
if ((temp32) && (temp32 < g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize))
|
|
{
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(
|
|
temp32, g_UsbDeviceVideoVirtualCamera.stillProbeStruct->dwMaxPayloadTransferSize);
|
|
}
|
|
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeStruct->bFormatIndex = still_probe->bFormatIndex;
|
|
g_UsbDeviceVideoVirtualCamera.stillProbeStruct->bFrameIndex = still_probe->bFrameIndex;
|
|
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
|
|
*buffer = (uint8_t *)g_UsbDeviceVideoVirtualCamera.stillProbeStruct;
|
|
*length = g_UsbDeviceVideoVirtualCamera.stillProbeLength;
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MIN:
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MAX:
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_RES:
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
|
|
*buffer = &g_UsbDeviceVideoVirtualCamera.stillProbeLength;
|
|
*length = sizeof(g_UsbDeviceVideoVirtualCamera.stillProbeLength);
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
|
|
*buffer = &g_UsbDeviceVideoVirtualCamera.stillProbeInfo;
|
|
*length = sizeof(g_UsbDeviceVideoVirtualCamera.stillProbeInfo);
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_DEF:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VS STILL commit request */
|
|
static usb_status_t USB_DeviceVideoProcessClassVsStillCommitRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_device_video_still_probe_and_commit_controls_struct_t *still_commit;
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint32_t temp32;
|
|
|
|
if ((NULL == buffer) || (NULL == length))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
still_commit = (usb_device_video_still_probe_and_commit_controls_struct_t *)(*buffer);
|
|
|
|
switch (setup->bRequest)
|
|
{
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
|
|
if ((*buffer == NULL) || (*length == 0U))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
temp32 = USB_LONG_FROM_LITTLE_ENDIAN_DATA(still_commit->dwMaxPayloadTransferSize);
|
|
if ((temp32) && (temp32 < g_UsbDeviceVideoVirtualCamera.currentMaxPacketSize))
|
|
{
|
|
USB_LONG_TO_LITTLE_ENDIAN_DATA(
|
|
temp32, g_UsbDeviceVideoVirtualCamera.stillCommitStruct->dwMaxPayloadTransferSize);
|
|
}
|
|
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitStruct->bFormatIndex = still_commit->bFormatIndex;
|
|
g_UsbDeviceVideoVirtualCamera.stillCommitStruct->bFrameIndex = still_commit->bFrameIndex;
|
|
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
|
|
*buffer = (uint8_t *)g_UsbDeviceVideoVirtualCamera.stillCommitStruct;
|
|
*length = g_UsbDeviceVideoVirtualCamera.stillCommitLength;
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
|
|
*buffer = &g_UsbDeviceVideoVirtualCamera.stillCommitLength;
|
|
*length = sizeof(g_UsbDeviceVideoVirtualCamera.stillCommitLength);
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
|
|
*buffer = &g_UsbDeviceVideoVirtualCamera.stillCommitInfo;
|
|
*length = sizeof(g_UsbDeviceVideoVirtualCamera.stillCommitInfo);
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VS STILL image trigger request */
|
|
static usb_status_t USB_DeviceVideoProcessClassVsStillImageTriggerRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
|
|
if ((NULL == buffer) || (NULL == length))
|
|
{
|
|
return error;
|
|
}
|
|
|
|
switch (setup->bRequest)
|
|
{
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
|
|
if ((*buffer == NULL) || (*length == 0U))
|
|
{
|
|
return error;
|
|
}
|
|
g_UsbDeviceVideoVirtualCamera.stillImageTriggerControl = *(*buffer);
|
|
error = kStatus_USB_Success;
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
|
|
break;
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VS request */
|
|
static usb_status_t USB_DeviceVideoProcessClassVsRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint8_t cs = (setup->wValue >> 0x08U) & 0xFFU;
|
|
|
|
switch (cs)
|
|
{
|
|
case USB_DEVICE_VIDEO_VS_PROBE_CONTROL:
|
|
error = USB_DeviceVideoProcessClassVsProbeRequest(handle, setup, length, buffer);
|
|
break;
|
|
case USB_DEVICE_VIDEO_VS_COMMIT_CONTROL:
|
|
error = USB_DeviceVideoProcessClassVsCommitRequest(handle, setup, length, buffer);
|
|
break;
|
|
case USB_DEVICE_VIDEO_VS_STILL_PROBE_CONTROL:
|
|
error = USB_DeviceVideoProcessClassVsStillProbeRequest(handle, setup, length, buffer);
|
|
break;
|
|
case USB_DEVICE_VIDEO_VS_STILL_COMMIT_CONTROL:
|
|
error = USB_DeviceVideoProcessClassVsStillCommitRequest(handle, setup, length, buffer);
|
|
break;
|
|
case USB_DEVICE_VIDEO_VS_STILL_IMAGE_TRIGGER_CONTROL:
|
|
error = USB_DeviceVideoProcessClassVsStillImageTriggerRequest(handle, setup, length, buffer);
|
|
break;
|
|
case USB_DEVICE_VIDEO_VS_STREAM_ERROR_CODE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_VS_GENERATE_KEY_FRAME_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_VS_UPDATE_FRAME_SEGMENT_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_VS_SYNCH_DELAY_CONTROL:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VC interface request */
|
|
static usb_status_t USB_DeviceProcessClassVcInterfaceRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint8_t cs = (setup->wValue >> 0x08U) & 0xFFU;
|
|
|
|
if (USB_DEVICE_VIDEO_VC_VIDEO_POWER_MODE_CONTROL == cs)
|
|
{
|
|
}
|
|
else if (USB_DEVICE_VIDEO_VC_REQUEST_ERROR_CODE_CONTROL == cs)
|
|
{
|
|
}
|
|
else
|
|
{
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VC camera terminal request */
|
|
static usb_status_t USB_DeviceProcessClassVcCameraTerminalRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint8_t cs = (setup->wValue >> 0x08U) & 0xFFU;
|
|
|
|
switch (cs)
|
|
{
|
|
case USB_DEVICE_VIDEO_CT_SCANNING_MODE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_AE_MODE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_AE_PRIORITY_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_EXPOSURE_TIME_RELATIVE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_FOCUS_ABSOLUTE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_FOCUS_RELATIVE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_FOCUS_AUTO_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_IRIS_ABSOLUTE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_IRIS_RELATIVE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_ZOOM_ABSOLUTE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_ZOOM_RELATIVE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_PANTILT_ABSOLUTE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_PANTILT_RELATIVE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_ROLL_ABSOLUTE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_ROLL_RELATIVE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_PRIVACY_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_FOCUS_SIMPLE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_WINDOW_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_CT_REGION_OF_INTEREST_CONTROL:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VC input terminal request */
|
|
static usb_status_t USB_DeviceProcessClassVcInputTerminalRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
|
|
if (USB_DEVICE_VIDEO_ITT_CAMERA == USB_VIDEO_VIRTUAL_CAMERA_VC_INPUT_TERMINAL_TYPE)
|
|
{
|
|
error = USB_DeviceProcessClassVcCameraTerminalRequest(handle, setup, length, buffer);
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VC onput terminal request */
|
|
static usb_status_t USB_DeviceProcessClassVcOutputTerminalRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VC processing unit request */
|
|
static usb_status_t USB_DeviceProcessClassVcProcessingUintRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint8_t cs = (setup->wValue >> 0x08U) & 0xFFU;
|
|
|
|
switch (cs)
|
|
{
|
|
case USB_DEVICE_VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_BRIGHTNESS_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_CONTRAST_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_GAIN_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_POWER_LINE_FREQUENCY_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_HUE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_SATURATION_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_SHARPNESS_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_GAMMA_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_WHITE_BALANCE_COMPONENT_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_DIGITAL_MULTIPLIER_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_HUE_AUTO_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_ANALOG_VIDEO_STANDARD_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_ANALOG_LOCK_STATUS_CONTROL:
|
|
break;
|
|
case USB_DEVICE_VIDEO_PU_CONTRAST_AUTO_CONTROL:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific VC request */
|
|
static usb_status_t USB_DeviceProcessClassVcRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint8_t entityId = (uint8_t)(setup->wIndex >> 0x08U);
|
|
if (0U == entityId)
|
|
{
|
|
error = USB_DeviceProcessClassVcInterfaceRequest(handle, setup, length, buffer);
|
|
}
|
|
else if (USB_VIDEO_VIRTUAL_CAMERA_VC_INPUT_TERMINAL_ID == entityId)
|
|
{
|
|
error = USB_DeviceProcessClassVcInputTerminalRequest(handle, setup, length, buffer);
|
|
}
|
|
else if (USB_VIDEO_VIRTUAL_CAMERA_VC_OUTPUT_TERMINAL_ID == entityId)
|
|
{
|
|
error = USB_DeviceProcessClassVcOutputTerminalRequest(handle, setup, length, buffer);
|
|
}
|
|
else if (USB_VIDEO_VIRTUAL_CAMERA_VC_PROCESSING_UNIT_ID == entityId)
|
|
{
|
|
error = USB_DeviceProcessClassVcProcessingUintRequest(handle, setup, length, buffer);
|
|
}
|
|
else
|
|
{
|
|
}
|
|
return error;
|
|
}
|
|
|
|
/* Precess class-specific request */
|
|
usb_status_t USB_DeviceProcessClassRequest(usb_device_handle handle,
|
|
usb_setup_struct_t *setup,
|
|
uint32_t *length,
|
|
uint8_t **buffer)
|
|
{
|
|
usb_status_t error = kStatus_USB_InvalidRequest;
|
|
uint8_t interface_index = (uint8_t)setup->wIndex;
|
|
|
|
if ((USB_VIDEO_VIRTUAL_CAMERA_CONTROL_INTERFACE_INDEX != interface_index) &&
|
|
(USB_VIDEO_VIRTUAL_CAMERA_STREAM_INTERFACE_INDEX != interface_index))
|
|
{
|
|
return kStatus_USB_InvalidRequest;
|
|
}
|
|
|
|
switch (setup->bRequest)
|
|
{
|
|
/* Set */
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_SET_CUR_ALL:
|
|
if (setup->bmRequestType == USB_DEVICE_VIDEO_SET_REQUEST_INTERFACE)
|
|
{
|
|
error = kStatus_USB_Success;
|
|
}
|
|
break;
|
|
/* Get */
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MIN:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MAX:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_RES:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_LEN:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_INFO:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_DEF:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_CUR_ALL:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MIN_ALL:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_MAX_ALL:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_RES_ALL:
|
|
case USB_DEVICE_VIDEO_REQUEST_CODE_GET_DEF_ALL:
|
|
if (setup->bmRequestType == USB_DEVICE_VIDEO_GET_REQUEST_INTERFACE)
|
|
{
|
|
error = kStatus_USB_Success;
|
|
}
|
|
break;
|
|
default:
|
|
/* no action */
|
|
break;
|
|
}
|
|
if (kStatus_USB_Success == error)
|
|
{
|
|
error = kStatus_USB_InvalidRequest;
|
|
if (USB_VIDEO_VIRTUAL_CAMERA_CONTROL_INTERFACE_INDEX == interface_index)
|
|
{
|
|
error = USB_DeviceProcessClassVcRequest(handle, setup, length, buffer);
|
|
}
|
|
else if (USB_VIDEO_VIRTUAL_CAMERA_STREAM_INTERFACE_INDEX == interface_index)
|
|
{
|
|
error = USB_DeviceVideoProcessClassVsRequest(handle, setup, length, buffer);
|
|
}
|
|
else
|
|
{
|
|
/*no action*/
|
|
}
|
|
}
|
|
|
|
return error;
|
|
}
|
|
|
|
static void USB_DeviceApplicationInit(void)
|
|
{
|
|
USB_DeviceClockInit();
|
|
#if (defined(FSL_FEATURE_SOC_SYSMPU_COUNT) && (FSL_FEATURE_SOC_SYSMPU_COUNT > 0U))
|
|
SYSMPU_Enable(SYSMPU, 0);
|
|
#endif /* FSL_FEATURE_SOC_SYSMPU_COUNT */
|
|
|
|
USB_DeviceVideoApplicationSetDefault();
|
|
|
|
if (kStatus_USB_Success !=
|
|
USB_DeviceInit(CONTROLLER_ID, USB_DeviceCallback, &g_UsbDeviceVideoVirtualCamera.deviceHandle))
|
|
{
|
|
usb_echo("USB device video virtual camera failed\r\n");
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
usb_echo("USB device video virtual camera demo\r\n");
|
|
}
|
|
|
|
USB_DeviceIsrEnable();
|
|
|
|
/*Add one delay here to make the DP pull down long enough to allow host to detect the previous disconnection.*/
|
|
SDK_DelayAtLeastUs(5000, SDK_DEVICE_MAXIMUM_CPU_CLOCK_FREQUENCY);
|
|
USB_DeviceRun(g_UsbDeviceVideoVirtualCamera.deviceHandle);
|
|
}
|
|
|
|
#if defined(__CC_ARM) || (defined(__ARMCC_VERSION)) || defined(__GNUC__)
|
|
int main(void)
|
|
#else
|
|
void main(void)
|
|
#endif
|
|
{
|
|
BOARD_ConfigMPU();
|
|
BOARD_InitBootPins();
|
|
BOARD_InitBootClocks();
|
|
BOARD_InitDebugConsole();
|
|
|
|
USB_DeviceApplicationInit();
|
|
|
|
while (1U)
|
|
{
|
|
#if USB_DEVICE_CONFIG_USE_TASK
|
|
USB_DeviceTaskFn(g_UsbDeviceVideoVirtualCamera.deviceHandle);
|
|
#endif
|
|
}
|
|
}
|