[feat] add usb audio and video driver
This commit is contained in:
parent
5cca7f0193
commit
4115724dc7
@ -6,6 +6,7 @@ list(APPEND ADD_INCLUDE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/class/hid"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/class/msc"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/class/video"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/class/audio"
|
||||
#"${CMAKE_CURRENT_SOURCE_DIR}/class/vendor"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/class/winusb"
|
||||
)
|
||||
|
@ -1,7 +1,96 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_audio.h"
|
||||
|
||||
|
||||
struct usbd_audio_control_info audio_control_info = {0xdb00,0x0000,0x0100,0xf600,0};
|
||||
|
||||
int audio_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USBD_LOG_DBG("Class request:"
|
||||
"bRequest 0x%02x, bmRequestType 0x%02x len %d",
|
||||
setup->bRequest, setup->bmRequestType, *len);
|
||||
|
||||
switch (setup->bRequest)
|
||||
{
|
||||
case AUDIO_REQUEST_SET_CUR:
|
||||
|
||||
if(setup->wValueL == 0x01)
|
||||
{
|
||||
if(setup->wValueH == AUDIO_FU_CONTROL_MUTE)
|
||||
{
|
||||
memcpy(&audio_control_info.mute,*data,*len);
|
||||
}
|
||||
else if(setup->wValueH == AUDIO_FU_CONTROL_VOLUME)
|
||||
{
|
||||
memcpy(&audio_control_info.vol_current,*data,*len);
|
||||
USBD_LOG_DBG("vol:0x%x\r\n",audio_control_info.vol_current);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_CUR:
|
||||
if(setup->wValueH == AUDIO_FU_CONTROL_MUTE)
|
||||
{
|
||||
*data = (uint8_t*)&audio_control_info.mute;
|
||||
*len = 1;
|
||||
}
|
||||
else if(setup->wValueH == AUDIO_FU_CONTROL_VOLUME)
|
||||
{
|
||||
*data = (uint8_t*)&audio_control_info.vol_current;
|
||||
*len = 2;
|
||||
}
|
||||
|
||||
break;
|
||||
case AUDIO_REQUEST_SET_RES:
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_MIN:
|
||||
*data = (uint8_t*)&audio_control_info.vol_min;
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_MAX:
|
||||
*data = (uint8_t*)&audio_control_info.vol_max;
|
||||
*len = 2;
|
||||
break;
|
||||
case AUDIO_REQUEST_GET_RES:
|
||||
*data = (uint8_t*)&audio_control_info.vol_res;
|
||||
*len = 2;
|
||||
break;
|
||||
default:
|
||||
USBD_LOG_ERR("Unhandled request 0x%02x", setup->bRequest);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audio_notify_handler(uint8_t event, void* arg)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case USB_EVENT_RESET:
|
||||
|
||||
break;
|
||||
case USB_EVENT_SOF:
|
||||
break;
|
||||
case USB_EVENT_SET_INTERFACE:
|
||||
usbd_audio_set_interface_callback(((uint8_t*)arg)[3]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_audio_add_interface(usbd_class_t *class, usbd_interface_t *intf)
|
||||
{
|
||||
static usbd_class_t *last_class = NULL;
|
||||
|
||||
if(last_class != class)
|
||||
{
|
||||
last_class = class;
|
||||
usbd_class_register(class);
|
||||
}
|
||||
|
||||
intf->class_handler = audio_class_request_handler;
|
||||
intf->custom_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = audio_notify_handler;
|
||||
usbd_class_add_interface(class,intf);
|
||||
}
|
@ -20,72 +20,116 @@ extern "C" {
|
||||
/** Audio Interface Subclass Codes
|
||||
* Refer to Table A-2 from audio10.pdf
|
||||
*/
|
||||
enum usb_audio_int_subclass_codes {
|
||||
USB_AUDIO_SUBCLASS_UNDEFINED = 0x00,
|
||||
USB_AUDIO_AUDIOCONTROL = 0x01,
|
||||
USB_AUDIO_AUDIOSTREAMING = 0x02,
|
||||
USB_AUDIO_MIDISTREAMING = 0x03
|
||||
};
|
||||
#define AUDIO_SUBCLASS_UNDEFINED 0x00
|
||||
#define AUDIO_SUBCLASS_AUDIOCONTROL 0x01
|
||||
#define AUDIO_SUBCLASS_AUDIOSTREAMING 0x02
|
||||
#define AUDIO_SUBCLASS_MIDISTREAMING 0x03
|
||||
|
||||
/** Audio Class-Specific AC Interface Descriptor Subtypes
|
||||
#define AUDIO_PROTOCOL_UNDEFINED 0x00U
|
||||
|
||||
#define AUDIO_ENDPOINT_GENERAL 0x01U
|
||||
|
||||
/** Audio Class-Specific Control Interface Descriptor Subtypes
|
||||
* Refer to Table A-5 from audio10.pdf
|
||||
*/
|
||||
enum usb_audio_cs_ac_int_desc_subtypes {
|
||||
USB_AUDIO_AC_DESCRIPTOR_UNDEFINED = 0x00,
|
||||
USB_AUDIO_HEADER = 0x01,
|
||||
USB_AUDIO_INPUT_TERMINAL = 0x02,
|
||||
USB_AUDIO_OUTPUT_TERMINAL = 0x03,
|
||||
USB_AUDIO_MIXER_UNIT = 0x04,
|
||||
USB_AUDIO_SELECTOR_UNIT = 0x05,
|
||||
USB_AUDIO_FEATURE_UNIT = 0x06,
|
||||
USB_AUDIO_PROCESSING_UNIT = 0x07,
|
||||
USB_AUDIO_EXTENSION_UNIT = 0x08
|
||||
};
|
||||
#define AUDIO_CONTROL_UNDEFINED 0x01U
|
||||
#define AUDIO_CONTROL_HEADER 0x01U
|
||||
#define AUDIO_CONTROL_INPUT_TERMINAL 0x02U
|
||||
#define AUDIO_CONTROL_OUTPUT_TERMINAL 0x03U
|
||||
#define AUDIO_CONTROL_MIXER_UNIT 0x04U
|
||||
#define AUDIO_CONTROL_SELECTOR_UNIT 0x05U
|
||||
#define AUDIO_CONTROL_FEATURE_UNIT 0x06U
|
||||
#define AUDIO_CONTROL_PROCESSING_UNIT 0x07U
|
||||
#define AUDIO_CONTROL_EXTENSION_UNIT 0x08U
|
||||
|
||||
/** Audio Class-Specific AS Interface Descriptor Subtypes
|
||||
* Refer to Table A-6 from audio10.pdf
|
||||
*/
|
||||
enum usb_audio_cs_as_int_desc_subtypes {
|
||||
USB_AUDIO_AS_DESCRIPTOR_UNDEFINED = 0x00,
|
||||
USB_AUDIO_AS_GENERAL = 0x01,
|
||||
USB_AUDIO_FORMAT_TYPE = 0x02,
|
||||
USB_AUDIO_FORMAT_SPECIFIC = 0x03
|
||||
};
|
||||
#define AUDIO_STREAMING_UNDEFINED 0x00U
|
||||
#define AUDIO_STREAMING_GENERAL 0x01U
|
||||
#define AUDIO_STREAMING_FORMAT_TYPE 0x02U
|
||||
#define AUDIO_STREAMING_FORMAT_SPECIFIC 0x03U
|
||||
|
||||
/** Audio Class-Specific Request Codes
|
||||
* Refer to Table A-9 from audio10.pdf
|
||||
*/
|
||||
enum usb_audio_cs_req_codes {
|
||||
USB_AUDIO_REQUEST_CODE_UNDEFINED = 0x00,
|
||||
USB_AUDIO_SET_CUR = 0x01,
|
||||
USB_AUDIO_GET_CUR = 0x81,
|
||||
USB_AUDIO_SET_MIN = 0x02,
|
||||
USB_AUDIO_GET_MIN = 0x82,
|
||||
USB_AUDIO_SET_MAX = 0x03,
|
||||
USB_AUDIO_GET_MAX = 0x83,
|
||||
USB_AUDIO_SET_RES = 0x04,
|
||||
USB_AUDIO_GET_RES = 0x84,
|
||||
USB_AUDIO_SET_MEM = 0x05,
|
||||
USB_AUDIO_GET_MEM = 0x85,
|
||||
USB_AUDIO_GET_STAT = 0xFF
|
||||
};
|
||||
#define AUDIO_REQUEST_UNDEFINED 0x00
|
||||
#define AUDIO_REQUEST_SET_CUR 0x01
|
||||
#define AUDIO_REQUEST_GET_CUR 0x81
|
||||
#define AUDIO_REQUEST_SET_MIN 0x02
|
||||
#define AUDIO_REQUEST_GET_MIN 0x82
|
||||
#define AUDIO_REQUEST_SET_MAX 0x03
|
||||
#define AUDIO_REQUEST_GET_MAX 0x83
|
||||
#define AUDIO_REQUEST_SET_RES 0x04
|
||||
#define AUDIO_REQUEST_GET_RES 0x84
|
||||
#define AUDIO_REQUEST_SET_MEM 0x05
|
||||
#define AUDIO_REQUEST_GET_MEM 0x85
|
||||
#define AUDIO_REQUEST_GET_STAT 0xFF
|
||||
|
||||
/* Feature Unit Control Bits */
|
||||
#define AUDIO_CONTROL_MUTE 0x0001
|
||||
#define AUDIO_CONTROL_VOLUME 0x0002
|
||||
#define AUDIO_CONTROL_BASS 0x0004
|
||||
#define AUDIO_CONTROL_MID 0x0008
|
||||
#define AUDIO_CONTROL_TREBLE 0x0010
|
||||
#define AUDIO_CONTROL_GRAPHIC_EQUALIZER 0x0020
|
||||
#define AUDIO_CONTROL_AUTOMATIC_GAIN 0x0040
|
||||
#define AUDIO_CONTROL_DEALY 0x0080
|
||||
#define AUDIO_CONTROL_BASS_BOOST 0x0100
|
||||
#define AUDIO_CONTROL_LOUDNESS 0x0200
|
||||
|
||||
|
||||
/** Feature Unit Control Selectors
|
||||
* Refer to Table A-11 from audio10.pdf
|
||||
*/
|
||||
enum usb_audio_fucs {
|
||||
USB_AUDIO_FU_CONTROL_UNDEFINED = 0x00,
|
||||
USB_AUDIO_FU_MUTE_CONTROL = 0x01,
|
||||
USB_AUDIO_FU_VOLUME_CONTROL = 0x02,
|
||||
USB_AUDIO_FU_BASS_CONTROL = 0x03,
|
||||
USB_AUDIO_FU_MID_CONTROL = 0x04,
|
||||
USB_AUDIO_FU_TREBLE_CONTROL = 0x05,
|
||||
USB_AUDIO_FU_GRAPHIC_EQUALIZER_CONTROL = 0x06,
|
||||
USB_AUDIO_FU_AUTOMATIC_GAIN_CONTROL = 0x07,
|
||||
USB_AUDIO_FU_DELAY_CONTROL = 0x08,
|
||||
USB_AUDIO_FU_BASS_BOOST_CONTROL = 0x09,
|
||||
USB_AUDIO_FU_LOUDNESS_CONTROL = 0x0A
|
||||
};
|
||||
#define AUDIO_FU_CONTROL_MUTE 0x01
|
||||
#define AUDIO_FU_CONTROL_VOLUME 0x02
|
||||
#define AUDIO_FU_CONTROL_BASS 0x03
|
||||
#define AUDIO_FU_CONTROL_MID 0x04
|
||||
#define AUDIO_FU_CONTROL_TREBLE 0x05
|
||||
#define AUDIO_FU_CONTROL_GRAPHIC_EQUALIZER 0x06
|
||||
#define AUDIO_FU_CONTROL_AUTOMATIC_GAIN 0x07
|
||||
#define AUDIO_FU_CONTROL_DELAY 0x08
|
||||
#define AUDIO_FU_CONTROL_BASS_BOOST 0x09
|
||||
#define AUDIO_FU_CONTROL_LOUDNESS 0x0A
|
||||
|
||||
|
||||
/* Audio Descriptor Types */
|
||||
#define AUDIO_UNDEFINED_DESCRIPTOR_TYPE 0x20
|
||||
#define AUDIO_DEVICE_DESCRIPTOR_TYPE 0x21
|
||||
#define AUDIO_CONFIGURATION_DESCRIPTOR_TYPE 0x22
|
||||
#define AUDIO_STRING_DESCRIPTOR_TYPE 0x23
|
||||
#define AUDIO_INTERFACE_DESCRIPTOR_TYPE 0x24
|
||||
#define AUDIO_ENDPOINT_DESCRIPTOR_TYPE 0x25
|
||||
|
||||
|
||||
/* Audio Data Format Type I Codes */
|
||||
#define AUDIO_FORMAT_TYPE_I_UNDEFINED 0x0000
|
||||
#define AUDIO_FORMAT_PCM 0x0001
|
||||
#define AUDIO_FORMAT_PCM8 0x0002
|
||||
#define AUDIO_FORMAT_IEEE_FLOAT 0x0003
|
||||
#define AUDIO_FORMAT_ALAW 0x0004
|
||||
#define AUDIO_FORMAT_MULAW 0x0005
|
||||
|
||||
/* Predefined Audio Channel Configuration Bits */
|
||||
#define AUDIO_CHANNEL_M 0x0000 /* Mono */
|
||||
#define AUDIO_CHANNEL_L 0x0001 /* Left Front */
|
||||
#define AUDIO_CHANNEL_R 0x0002 /* Right Front */
|
||||
#define AUDIO_CHANNEL_C 0x0004 /* Center Front */
|
||||
#define AUDIO_CHANNEL_LFE 0x0008 /* Low Freq. Enhance. */
|
||||
#define AUDIO_CHANNEL_LS 0x0010 /* Left Surround */
|
||||
#define AUDIO_CHANNEL_RS 0x0020 /* Right Surround */
|
||||
#define AUDIO_CHANNEL_LC 0x0040 /* Left of Center */
|
||||
#define AUDIO_CHANNEL_RC 0x0080 /* Right of Center */
|
||||
#define AUDIO_CHANNEL_S 0x0100 /* Surround */
|
||||
#define AUDIO_CHANNEL_SL 0x0200 /* Side Left */
|
||||
#define AUDIO_CHANNEL_SR 0x0400 /* Side Right */
|
||||
#define AUDIO_CHANNEL_T 0x0800 /* Top */
|
||||
|
||||
#define AUDIO_FORMAT_TYPE_I 0x01
|
||||
#define AUDIO_FORMAT_TYPE_II 0x02
|
||||
#define AUDIO_FORMAT_TYPE_III 0x03
|
||||
|
||||
|
||||
/** USB Terminal Types
|
||||
* Refer to Table 2-1 - Table 2-4 from termt10.pdf
|
||||
@ -124,21 +168,6 @@ enum usb_audio_terminal_types {
|
||||
USB_AUDIO_IO_SPEAKERPHONE_ECHO_CAN = 0x0405,
|
||||
};
|
||||
|
||||
enum usb_audio_direction {
|
||||
USB_AUDIO_IN = 0x00,
|
||||
USB_AUDIO_OUT = 0x01
|
||||
};
|
||||
|
||||
/**
|
||||
* Addressable logical object inside an audio function.
|
||||
* Entity is one of: Terminal or Unit.
|
||||
* Refer to 1.4 Terms and Abbreviations from audio10.pdf
|
||||
*/
|
||||
struct usb_audio_entity {
|
||||
enum usb_audio_cs_ac_int_desc_subtypes subtype;
|
||||
uint8_t id;
|
||||
};
|
||||
|
||||
/**
|
||||
* @warning Size of baInterface is 2 just to make it useable
|
||||
* for all kind of devices: headphones, microphone and headset.
|
||||
@ -233,8 +262,20 @@ struct cs_as_ad_ep_descriptor {
|
||||
uint8_t bLockDelayUnits;
|
||||
uint16_t wLockDelay;
|
||||
} __packed;
|
||||
|
||||
struct usbd_audio_control_info
|
||||
{
|
||||
uint16_t vol_min;
|
||||
uint16_t vol_max;
|
||||
uint16_t vol_res;
|
||||
uint16_t vol_current;
|
||||
uint8_t mute;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbd_audio_add_interface(usbd_class_t *class, usbd_interface_t *intf);
|
||||
void usbd_audio_set_interface_callback(uint8_t value);
|
||||
#endif /* _USB_AUDIO_H_ */
|
||||
|
@ -23,8 +23,8 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_cdc.h"
|
||||
|
||||
static const char *stop_name[] = {"1", "1.5", "2"};
|
||||
static const char *parity_name[] = {"N","O","E","M","S"};
|
||||
const char *stop_name[] = {"1", "1.5", "2"};
|
||||
const char *parity_name[] = {"N","O","E","M","S"};
|
||||
|
||||
/* Device data structure */
|
||||
struct cdc_acm_cfg_private {
|
||||
@ -40,9 +40,11 @@ struct cdc_acm_cfg_private {
|
||||
bool configured;
|
||||
/* CDC ACM suspended flag */
|
||||
bool suspended;
|
||||
uint32_t uart_first_init_flag;
|
||||
|
||||
} usbd_cdc_acm_cfg;
|
||||
|
||||
|
||||
static void usbd_cdc_acm_reset(void)
|
||||
{
|
||||
usbd_cdc_acm_cfg.line_coding.dwDTERate = 2000000;
|
||||
@ -50,6 +52,7 @@ static void usbd_cdc_acm_reset(void)
|
||||
usbd_cdc_acm_cfg.line_coding.bParityType = 0;
|
||||
usbd_cdc_acm_cfg.line_coding.bCharFormat = 0;
|
||||
usbd_cdc_acm_cfg.configured = false;
|
||||
usbd_cdc_acm_cfg.uart_first_init_flag = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,8 +86,14 @@ static int cdc_acm_class_request_handler(struct usb_setup_packet *pSetup,uint8_t
|
||||
/* 4 - Space */
|
||||
/* 6 | bDataBits | 1 | Number Data bits (5, 6, 7, 8 or 16). */
|
||||
/*******************************************************************************/
|
||||
if(usbd_cdc_acm_cfg.uart_first_init_flag == 0)
|
||||
{
|
||||
usbd_cdc_acm_cfg.uart_first_init_flag = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(&usbd_cdc_acm_cfg.line_coding,*data, sizeof(usbd_cdc_acm_cfg.line_coding));
|
||||
USBD_LOG("CDC_SET_LINE_CODING <%d %d %s %s>\r\n",
|
||||
USBD_LOG_DBG("CDC_SET_LINE_CODING <%d %d %s %s>\r\n",
|
||||
usbd_cdc_acm_cfg.line_coding.dwDTERate,
|
||||
usbd_cdc_acm_cfg.line_coding.bDataBits,
|
||||
parity_name[usbd_cdc_acm_cfg.line_coding.bParityType],
|
||||
@ -98,7 +107,7 @@ static int cdc_acm_class_request_handler(struct usb_setup_packet *pSetup,uint8_t
|
||||
usbd_cdc_acm_cfg.line_state = (uint8_t)pSetup->wValue;
|
||||
bool dtr = (pSetup->wValue & 0x01);
|
||||
bool rts = (pSetup->wValue & 0x02);
|
||||
USBD_LOG("DTR 0x%x,RTS 0x%x\r\n",
|
||||
USBD_LOG_DBG("DTR 0x%x,RTS 0x%x\r\n",
|
||||
dtr,rts);
|
||||
usbd_cdc_acm_set_dtr(dtr);
|
||||
usbd_cdc_acm_set_rts(rts);
|
||||
|
@ -23,11 +23,31 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_hid.h"
|
||||
|
||||
#define HID_STATE_IDLE 0
|
||||
#define HID_STATE_BUSY 1
|
||||
|
||||
struct usbd_hid_cfg_private
|
||||
{
|
||||
const uint8_t* hid_descriptor;
|
||||
const uint8_t* hid_report_descriptor;
|
||||
uint32_t hid_report_descriptor_len;
|
||||
uint32_t protocol;
|
||||
uint32_t idle_state;
|
||||
uint8_t hid_state;
|
||||
} usbd_hid_cfg;
|
||||
|
||||
static void usbd_hid_reset(void)
|
||||
{
|
||||
usbd_hid_cfg.idle_state = 0;
|
||||
usbd_hid_cfg.protocol = 2;
|
||||
usbd_hid_cfg.hid_state = HID_STATE_IDLE;
|
||||
}
|
||||
|
||||
int hid_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USBD_LOG_DBG("Standard request:"
|
||||
"bRequest 0x%02x, bmRequestType 0x%02x, len %d",
|
||||
setup->bRequest, setup->bmRequestType, *len);
|
||||
"bmRequestType 0x%02x, bRequest 0x%02x, len %d\r\n",
|
||||
setup->bmRequestType, setup->bRequest, *len);
|
||||
|
||||
if (REQTYPE_GET_DIR(setup->bmRequestType) == USB_REQUEST_DEVICE_TO_HOST &&
|
||||
setup->bRequest == USB_REQUEST_GET_DESCRIPTOR)
|
||||
@ -37,17 +57,18 @@ int hid_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case USB_DESCRIPTOR_TYPE_HID:
|
||||
|
||||
USBD_LOG_DBG("Return HID Descriptor");
|
||||
|
||||
case HID_DESCRIPTOR_TYPE_HID:
|
||||
USBD_LOG("get HID Descriptor\r\n");
|
||||
*data = (uint8_t*)usbd_hid_cfg.hid_descriptor;
|
||||
*len = usbd_hid_cfg.hid_descriptor[0];
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_HID_REPORT:
|
||||
USBD_LOG_DBG("Return Report Descriptor");
|
||||
|
||||
case HID_DESCRIPTOR_TYPE_HID_REPORT:
|
||||
USBD_LOG("get Report Descriptor\r\n");
|
||||
*data = (uint8_t*)usbd_hid_cfg.hid_report_descriptor;
|
||||
*len = usbd_hid_cfg.hid_report_descriptor_len;
|
||||
break;
|
||||
case USB_DESCRIPTOR_TYPE_HID_PHYSICAL:
|
||||
USBD_LOG_DBG("Return PHYSICAL Descriptor");
|
||||
case HID_DESCRIPTOR_TYPE_HID_PHYSICAL:
|
||||
USBD_LOG_DBG("get PHYSICAL Descriptor\r\n");
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -59,36 +80,87 @@ int hid_custom_request_handler(struct usb_setup_packet *setup, uint8_t **data, u
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hid_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
USBD_LOG_DBG("Class request:"
|
||||
"bRequest 0x%02x, bmRequestType 0x%02x len %d",
|
||||
setup->bRequest, setup->bmRequestType, *len);
|
||||
USBD_LOG("Class request:"
|
||||
"bmRequestType 0x%02x bRequest 0x%02x, len %d\r\n",
|
||||
setup->bmRequestType,setup->bRequest, *len);
|
||||
|
||||
switch (setup->bRequest)
|
||||
{
|
||||
case HID_REQUEST_GET_IDLE:
|
||||
|
||||
break;
|
||||
case HID_REQUEST_GET_REPORT:
|
||||
|
||||
*data = (uint8_t*)&usbd_hid_cfg.idle_state;
|
||||
*len = 1;
|
||||
break;
|
||||
case HID_REQUEST_GET_PROTOCOL:
|
||||
|
||||
*data = (uint8_t*)&usbd_hid_cfg.protocol;
|
||||
*len = 1;
|
||||
break;
|
||||
case HID_REQUEST_SET_IDLE:
|
||||
|
||||
break;
|
||||
case HID_REQUEST_SET_REPORT:
|
||||
|
||||
usbd_hid_cfg.idle_state = setup->wValueH;
|
||||
break;
|
||||
case HID_REQUEST_SET_PROTOCOL:
|
||||
|
||||
usbd_hid_cfg.protocol = setup->wValueL;
|
||||
break;
|
||||
default:
|
||||
USBD_LOG_ERR("Unhandled request 0x%02x", setup->bRequest);
|
||||
USBD_LOG_ERR("Unhandled request 0x%02x\r\n", setup->bRequest);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hid_notify_handler(uint8_t event, void* arg)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case USB_EVENT_RESET:
|
||||
usbd_hid_reset();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_hid_reset_state(void)
|
||||
{
|
||||
usbd_hid_cfg.hid_state = HID_STATE_IDLE;
|
||||
}
|
||||
|
||||
void usbd_hid_send_report(uint8_t ep, uint8_t* data, uint8_t len)
|
||||
{
|
||||
if(usbd_hid_cfg.hid_state == HID_STATE_IDLE)
|
||||
{
|
||||
usbd_hid_cfg.hid_state = HID_STATE_BUSY;
|
||||
usbd_ep_write(ep,data,len,NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_hid_descriptor_register(const uint8_t* desc)
|
||||
{
|
||||
usbd_hid_cfg.hid_descriptor = desc;
|
||||
}
|
||||
|
||||
void usbd_hid_report_descriptor_register(const uint8_t* desc, uint32_t desc_len)
|
||||
{
|
||||
usbd_hid_cfg.hid_report_descriptor = desc;
|
||||
usbd_hid_cfg.hid_report_descriptor_len = desc_len;
|
||||
}
|
||||
|
||||
void usbd_hid_add_interface(usbd_class_t *class, usbd_interface_t *intf)
|
||||
{
|
||||
static usbd_class_t *last_class = NULL;
|
||||
|
||||
if(last_class != class)
|
||||
{
|
||||
last_class = class;
|
||||
usbd_class_register(class);
|
||||
}
|
||||
|
||||
intf->class_handler = hid_class_request_handler;
|
||||
intf->custom_handler = hid_custom_request_handler;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = hid_notify_handler;
|
||||
usbd_class_add_interface(class,intf);
|
||||
}
|
||||
|
@ -13,9 +13,9 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
/* HID Class Descriptor Types */
|
||||
#define USB_DESCRIPTOR_TYPE_HID 0x21
|
||||
#define USB_DESCRIPTOR_TYPE_HID_REPORT 0x22
|
||||
#define USB_DESCRIPTOR_TYPE_HID_PHYSICAL 0x23
|
||||
#define HID_DESCRIPTOR_TYPE_HID 0x21
|
||||
#define HID_DESCRIPTOR_TYPE_HID_REPORT 0x22
|
||||
#define HID_DESCRIPTOR_TYPE_HID_PHYSICAL 0x23
|
||||
|
||||
/* HID Class Specific Requests */
|
||||
#define HID_REQUEST_GET_REPORT 0x01
|
||||
@ -393,4 +393,9 @@ enum hid_kbd_led {
|
||||
}
|
||||
#endif
|
||||
|
||||
void usbd_hid_descriptor_register(const uint8_t* desc);
|
||||
void usbd_hid_report_descriptor_register(const uint8_t* desc, uint32_t desc_len);
|
||||
void usbd_hid_add_interface(usbd_class_t *class, usbd_interface_t *intf);
|
||||
void usbd_hid_reset_state(void);
|
||||
void usbd_hid_send_report(uint8_t ep, uint8_t* data, uint8_t len);
|
||||
#endif /* _USB_HID_H_ */
|
||||
|
@ -22,56 +22,8 @@
|
||||
#include "usbd_core.h"
|
||||
#include "usbd_video.h"
|
||||
|
||||
#define WIDTH (unsigned int)320
|
||||
#define HEIGHT (unsigned int)240
|
||||
#define VIDEO_PACKET_SIZE (unsigned int)(768+2)
|
||||
|
||||
#define CAM_FPS 20
|
||||
#define INTERVAL (unsigned long)(10000000/CAM_FPS)
|
||||
#define MIN_BIT_RATE (unsigned long)(WIDTH*HEIGHT*16*CAM_FPS)//16 bit
|
||||
#define MAX_BIT_RATE (unsigned long)(WIDTH*HEIGHT*16*CAM_FPS)
|
||||
#define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT *2)
|
||||
|
||||
struct video_probe_and_commit_controls probe =
|
||||
{
|
||||
.hintUnion.bmHint = 0,
|
||||
.hintUnion1.bmHint = 0,
|
||||
.bFormatIndex = 1,
|
||||
.bFrameIndex = 1,
|
||||
.dwFrameInterval = INTERVAL,
|
||||
.wKeyFrameRate = 0,
|
||||
.wPFrameRate = 0,
|
||||
.wCompQuality = 0,
|
||||
.wCompWindowSize = 0,
|
||||
.wDelay = 0,
|
||||
.dwMaxVideoFrameSize = MAX_FRAME_SIZE,
|
||||
.dwMaxPayloadTransferSize = 0,
|
||||
.dwClockFrequency = 0,
|
||||
.bmFramingInfo = 0,
|
||||
.bPreferedVersion = 0,
|
||||
.bMinVersion = 0,
|
||||
.bMaxVersion = 0,
|
||||
};
|
||||
struct video_probe_and_commit_controls commit =
|
||||
{
|
||||
.hintUnion.bmHint = 0,
|
||||
.hintUnion1.bmHint = 0,
|
||||
.bFormatIndex = 1,
|
||||
.bFrameIndex = 1,
|
||||
.dwFrameInterval = INTERVAL,
|
||||
.wKeyFrameRate = 0,
|
||||
.wPFrameRate = 0,
|
||||
.wCompQuality = 0,
|
||||
.wCompWindowSize = 0,
|
||||
.wDelay = 0,
|
||||
.dwMaxVideoFrameSize = MAX_FRAME_SIZE,
|
||||
.dwMaxPayloadTransferSize = 0,
|
||||
.dwClockFrequency = 0,
|
||||
.bmFramingInfo = 0,
|
||||
.bPreferedVersion = 0,
|
||||
.bMinVersion = 0,
|
||||
.bMaxVersion = 0,
|
||||
};
|
||||
extern struct video_probe_and_commit_controls probe;
|
||||
extern struct video_probe_and_commit_controls commit;
|
||||
|
||||
int video_class_request_handler(struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
@ -126,65 +78,38 @@ int video_class_request_handler(struct usb_setup_packet *setup, uint8_t **data,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
uint8_t play_status = 0;
|
||||
|
||||
void video_notify_handler(uint8_t event, void* arg)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case USB_EVENT_RESET:
|
||||
//usbd_cdc_acm_reset();
|
||||
|
||||
break;
|
||||
case USB_EVENT_SOF:
|
||||
usbd_video_sof_callback();
|
||||
break;
|
||||
case USB_EVENT_SET_INTERFACE:
|
||||
if(((uint8_t*)arg)[3])
|
||||
{
|
||||
play_status =1;
|
||||
MSG("Y\r\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
play_status=0;
|
||||
MSG("N\r\n");
|
||||
}
|
||||
usbd_video_set_interface_callback(((uint8_t*)arg)[3]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
__weak void usbd_video_isoch_out(uint8_t ep)
|
||||
void usbd_video_add_interface(usbd_class_t *class, usbd_interface_t *intf)
|
||||
{
|
||||
static usbd_class_t *last_class = NULL;
|
||||
|
||||
}
|
||||
__weak void usbd_video_isoch_in(uint8_t ep)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static usbd_class_t video_class;
|
||||
|
||||
usbd_interface_t video_stream_intf =
|
||||
{
|
||||
.class_handler = video_class_request_handler,
|
||||
.vendor_handler = NULL,
|
||||
.notify_handler = video_notify_handler,
|
||||
};
|
||||
|
||||
static usbd_endpoint_t video_in_ep =
|
||||
{
|
||||
.ep_cb = usbd_video_isoch_in,
|
||||
.ep_addr = 0x81
|
||||
};
|
||||
|
||||
void usbd_video_class_init(const char *name,uint8_t in_ep)
|
||||
{
|
||||
video_class.name = name;
|
||||
|
||||
usbd_class_register(&video_class);
|
||||
usbd_class_add_interface(&video_class,&video_stream_intf);
|
||||
video_stream_intf.intf_num = 1;
|
||||
video_in_ep.ep_addr = in_ep;
|
||||
usbd_interface_add_endpoint(&video_stream_intf,&video_in_ep);
|
||||
if(last_class != class)
|
||||
{
|
||||
last_class = class;
|
||||
usbd_class_register(class);
|
||||
}
|
||||
|
||||
intf->class_handler = video_class_request_handler;
|
||||
intf->custom_handler = NULL;
|
||||
intf->vendor_handler = NULL;
|
||||
intf->notify_handler = video_notify_handler;
|
||||
usbd_class_add_interface(class,intf);
|
||||
}
|
@ -816,8 +816,9 @@ struct video_still_probe_and_commit_controls
|
||||
receive in a single payload transfer.*/
|
||||
} __packed;
|
||||
|
||||
void usbd_video_isoch_in(uint8_t ep);
|
||||
void usbd_video_class_init(const char *name,uint8_t in_ep);
|
||||
void usbd_video_sof_callback(void);
|
||||
void usbd_video_set_interface_callback(uint8_t value);
|
||||
void usbd_video_add_interface(usbd_class_t *class, usbd_interface_t *intf);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -70,7 +70,7 @@
|
||||
|
||||
#define BCD(x) ((((x) / 10) << 4) | ((x) % 10))
|
||||
|
||||
#define BIT(n) (1UL << (n))
|
||||
#define BIT(x) (1<<(x))
|
||||
|
||||
#define ARRAY_SIZE(array) \
|
||||
((int)((sizeof(array) / sizeof((array)[0]))))
|
||||
|
@ -78,7 +78,7 @@ static struct usbd_core_cfg_priv
|
||||
static usb_slist_t usbd_class_head= USB_SLIST_OBJECT_INIT(usbd_class_head);
|
||||
static struct usb_msosv1_descriptor *msosv1_desc;
|
||||
static struct usb_bos_descriptor *bos_desc;
|
||||
static volatile uint32_t sof_tick = 0;
|
||||
|
||||
/**
|
||||
* @brief print the contents of a setup packet
|
||||
*
|
||||
@ -962,7 +962,7 @@ static void usbd_send_to_host(uint16_t len)
|
||||
if ((!usbd_core_cfg.ep0_data_buf_residue) && !(usbd_core_cfg.ep0_data_buf_len % USB_CTRL_EP_MPS))
|
||||
{
|
||||
/* Transfers a zero-length packet */
|
||||
// LOG_DBG("ZLP, requested %u , length %u ",
|
||||
// USBD_LOG("ZLP, requested %u , length %u ",
|
||||
// len, usb_dev.ep0_data_buf_len);
|
||||
usbd_core_cfg.zlp_flag = true;
|
||||
}
|
||||
@ -1010,7 +1010,7 @@ static void usbd_ep0_setup_handler(void)
|
||||
if (setup->wLength &&
|
||||
setup->bmRequestType_b.Dir == USB_REQUEST_HOST_TO_DEVICE)
|
||||
{
|
||||
USBD_LOG_DBG("D\r\n");
|
||||
USBD_LOG_DBG("prepare to out data\r\n");
|
||||
/*set ep ack to recv next data*/
|
||||
usbd_ep_read(USB_CONTROL_OUT_EP0,NULL,0,NULL);
|
||||
return;
|
||||
@ -1036,23 +1036,23 @@ static void usbd_ep0_out_handler(void)
|
||||
uint32_t chunk = 0U;
|
||||
struct usb_setup_packet *setup = &usbd_core_cfg.setup;
|
||||
|
||||
/* OUT transfer, data or status packets */
|
||||
if (usbd_core_cfg.ep0_data_buf_residue <= 0)
|
||||
/* OUT transfer, status packets */
|
||||
if (usbd_core_cfg.ep0_data_buf_residue == 0)
|
||||
{
|
||||
/* absorb zero-length status message */
|
||||
USBD_LOG_DBG("Z\r\n");
|
||||
USBD_LOG_DBG("recv status\r\n");
|
||||
if (usbd_ep_read(USB_CONTROL_OUT_EP0,
|
||||
usbd_core_cfg.ep0_data_buf,
|
||||
0, &chunk) < 0)
|
||||
NULL,
|
||||
0, NULL) < 0)
|
||||
{
|
||||
USBD_LOG_ERR("Read DATA Packet failed\r\n");
|
||||
usbd_ep_set_stall(USB_CONTROL_IN_EP0);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
usbd_core_cfg.ep0_data_buf = usbd_core_cfg.req_data;
|
||||
/* OUT transfer, data or status packets */
|
||||
|
||||
/* OUT transfer, data packets */
|
||||
if (usbd_ep_read(USB_CONTROL_OUT_EP0,
|
||||
usbd_core_cfg.ep0_data_buf,
|
||||
usbd_core_cfg.ep0_data_buf_residue, &chunk) < 0)
|
||||
@ -1064,7 +1064,7 @@ static void usbd_ep0_out_handler(void)
|
||||
|
||||
usbd_core_cfg.ep0_data_buf += chunk;
|
||||
usbd_core_cfg.ep0_data_buf_residue -= chunk;
|
||||
|
||||
|
||||
if (usbd_core_cfg.ep0_data_buf_residue == 0)
|
||||
{
|
||||
/* Received all, send data to handler */
|
||||
@ -1166,16 +1166,13 @@ void usbd_event_notify_handler(uint8_t event, void* arg)
|
||||
{
|
||||
switch (event)
|
||||
{
|
||||
case USB_EVENT_SOF:
|
||||
sof_tick++;
|
||||
USBD_LOG_DBG("tick: %d\r\n", sof_tick);
|
||||
break;
|
||||
case USB_EVENT_RESET:
|
||||
usbd_set_address(0);
|
||||
#if USBD_EP_CALLBACK_SEARCH_METHOD == 1
|
||||
usbd_ep_callback_register();
|
||||
#endif
|
||||
case USB_EVENT_ERROR:
|
||||
case USB_EVENT_SOF:
|
||||
case USB_EVENT_CONNECTED:
|
||||
case USB_EVENT_CONFIGURED:
|
||||
case USB_EVENT_SUSPEND:
|
||||
@ -1243,8 +1240,3 @@ bool usb_device_is_configured(void)
|
||||
{
|
||||
return usbd_core_cfg.configured;
|
||||
}
|
||||
|
||||
uint32_t usbd_get_sof_tick(void)
|
||||
{
|
||||
return sof_tick;
|
||||
}
|
@ -131,10 +131,6 @@ void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
|
||||
void usbd_class_add_interface(usbd_class_t *class,usbd_interface_t *intf);
|
||||
void usbd_interface_add_endpoint(usbd_interface_t *intf,usbd_endpoint_t *ep);
|
||||
bool usb_device_is_configured(void);
|
||||
uint32_t usbd_get_sof_tick(void);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Reference in New Issue
Block a user