/**
 * USB Device Audio class interface definitions.
 */

#ifndef _UDI_AUDIO_H_
#define _UDI_AUDIO_H_

#include "conf_usb.h"
#include "usb_protocol.h"
#include "usb_protocol_audio.h"
#include "udd.h"
#include "udc_desc.h"
#include "udi.h"
#include "udi_audio_conf.h"

#ifdef __cplusplus
extern "C" {
#endif
typedef void (*udi_callback) (void);

#define UAC1_SAMP_RATE(rate)		{ (((uint32_t)rate) & 0x0000FFUL), \
									  (((uint32_t)rate) & 0x00FF00UL) >> 8, \
									  (((uint32_t)rate) & 0xFF0000UL) >> 16 }

//! Structures for USB Audio descriptors

#define UDI_AUDIO_IAD_DESC	{ \
	.bLength			= sizeof(usb_iad_desc_t), \
	.bDescriptorType	= USB_DT_IAD, \
	.bFirstInterface	= USB_AUDIO_CONTROL_IFACE_NUMBER, \
	.bInterfaceCount	= 2, \
	.bFunctionClass		= AUDIO_CLASS_DEVICE, \
	.bFunctionSubClass	= AUDIO_SUBCLASS_CONTROL, \
	.bFunctionProtocol	= 0, \
	.iFunction			= 2, \
}

COMPILER_PACK_SET(1)
typedef struct {
	usb_iface_desc_t udi_audio_ac_iface;
	usb_audio_ac_interface_hdr_desc_t udi_audio_iface_hdr;
	usb_audio_input_terminal_desc_t udi_audio_it;
	usb_audio_output_terminal_desc_t udi_audio_ot;
} udi_audio_control_desc_t;
COMPILER_PACK_RESET()

#if USB_AUDIO_NB_CHANNELS == 1
#define USB_AUDIO_CHANNEL_CONFIG		(0x0000U)
#else
#define USB_AUDIO_CHANNEL_CONFIG		(0x0003U)
#endif

#define UDI_AUDIO_CONTROL_DESC	{ \
	 .udi_audio_ac_iface.bLength = sizeof(usb_iface_desc_t), \
	 .udi_audio_ac_iface.bDescriptorType = USB_DT_INTERFACE, \
	 .udi_audio_ac_iface.bInterfaceNumber = USB_AUDIO_CONTROL_IFACE_NUMBER, \
	 .udi_audio_ac_iface.bAlternateSetting = 0, \
	 .udi_audio_ac_iface.bNumEndpoints = 0, \
	 .udi_audio_ac_iface.bInterfaceClass = AUDIO_CLASS_DEVICE, \
	 .udi_audio_ac_iface.bInterfaceSubClass = AUDIO_SUBCLASS_CONTROL, \
	 .udi_audio_ac_iface.bInterfaceProtocol = 0, \
	 .udi_audio_ac_iface.iInterface = 2, \
	 .udi_audio_iface_hdr.bLength = sizeof(usb_audio_ac_interface_hdr_desc_t), \
	 .udi_audio_iface_hdr.bDescriptorType = AUDIO_CS_INTERFACE, \
	 .udi_audio_iface_hdr.bDescriptorSubtype = AUDIO_AC_HEADER, \
	 .udi_audio_iface_hdr.bcdADC = 0x0100,  \
	 .udi_audio_iface_hdr.wTotalLength = sizeof(usb_audio_ac_interface_hdr_desc_t) + \
	 sizeof(usb_audio_input_terminal_desc_t) + sizeof(usb_audio_output_terminal_desc_t), \
	 .udi_audio_iface_hdr.bInCollection = USB_AUDIO_NR_IFACE, \
	 .udi_audio_iface_hdr.baInterfaceNr[0] = 1, \
	 .udi_audio_it.bLength = sizeof(usb_audio_input_terminal_desc_t), \
	 .udi_audio_it.bDescriptorType = AUDIO_CS_INTERFACE, \
	 .udi_audio_it.bDescriptorSubtype = AUDIO_AC_INPUT_TERMINAL, \
	 .udi_audio_it.bTerminalId = 1, \
	 .udi_audio_it.wTerminalType = 0x0201, \
	 .udi_audio_it.bAssocTerminal = 0, \
	 .udi_audio_it.bNrChannels = USB_AUDIO_NB_CHANNELS, \
	 .udi_audio_it.wChannelConfig = USB_AUDIO_CHANNEL_CONFIG, \
	 .udi_audio_it.wChannelConfig = 0x0003, \
	 .udi_audio_it.iChannelNames = 0, \
	 .udi_audio_it.iTerminal = 0, \
	 .udi_audio_ot.bLength = sizeof(usb_audio_output_terminal_desc_t), \
	 .udi_audio_ot.bDescriptorType = AUDIO_CS_INTERFACE, \
	 .udi_audio_ot.bDescriptorSubtype = AUDIO_AC_OUTPUT_TERMINAL, \
	 .udi_audio_ot.bTerminalId = 2, \
	 .udi_audio_ot.wTerminalType = 0x0101, \
	 .udi_audio_ot.bAssocTerminal = 0, \
	 .udi_audio_ot.bSourceID = 1, \
	 .udi_audio_ot.iTerminal = 0, \
}

COMPILER_PACK_SET(1)
typedef struct {
	usb_iface_desc_t udi_audio_streaming_zero_iface;
	usb_iface_desc_t udi_audio_streaming_iface;
	usb_audio_cs_iface_desc_t udi_audio_cs_iface;
	usb_audio_format_type_i_desc_t udi_audio_mic_format;
	usb_ep_ext_desc_t udi_audio_mic_ep;
	usb_audio_cs_endpoint_desc_t udi_audio_mic_cs_ep;	
} udi_audio_streaming_desc_t;
COMPILER_PACK_RESET()

#define UDI_AUDIO_STREAMING_DESC	{ \
	.udi_audio_streaming_zero_iface.bLength = sizeof(usb_iface_desc_t), \
	.udi_audio_streaming_zero_iface.bDescriptorType = USB_DT_INTERFACE, \
	.udi_audio_streaming_zero_iface.bInterfaceNumber = USB_AUDIO_STREAMING_IFACE_NUMBER, \
	.udi_audio_streaming_zero_iface.bAlternateSetting = 0, \
	.udi_audio_streaming_zero_iface.bNumEndpoints = 0, \
	.udi_audio_streaming_zero_iface.bInterfaceClass = AUDIO_CLASS_DEVICE, \
	.udi_audio_streaming_zero_iface.bInterfaceSubClass = AUDIO_SUBCLASS_STREAMING, \
	.udi_audio_streaming_zero_iface.bInterfaceProtocol = 0, \
	.udi_audio_streaming_zero_iface.iInterface = 2,  \
	.udi_audio_streaming_iface.bLength = sizeof(usb_iface_desc_t), \
	.udi_audio_streaming_iface.bDescriptorType = USB_DT_INTERFACE, \
	.udi_audio_streaming_iface.bInterfaceNumber = USB_AUDIO_STREAMING_IFACE_NUMBER, \
	.udi_audio_streaming_iface.bAlternateSetting = 1, \
	.udi_audio_streaming_iface.bNumEndpoints = 1, \
	.udi_audio_streaming_iface.bInterfaceClass = AUDIO_CLASS_DEVICE, \
	.udi_audio_streaming_iface.bInterfaceSubClass = AUDIO_SUBCLASS_STREAMING, \
	.udi_audio_streaming_iface.bInterfaceProtocol = 0, \
	.udi_audio_streaming_iface.iInterface = 2, \
	.udi_audio_cs_iface.bLength = sizeof(usb_audio_cs_iface_desc_t), \
	.udi_audio_cs_iface.bDescriptorType = AUDIO_CS_INTERFACE, \
	.udi_audio_cs_iface.bDescriptorSubtype = AUDIO_AS_GENERAL, \
	.udi_audio_cs_iface.bTerminalLink = 2,  \
	.udi_audio_cs_iface.bDelay = 1,  \
	.udi_audio_cs_iface.wFormatTag = 0x0001,  \
	.udi_audio_mic_format.bLength = sizeof(usb_audio_format_type_i_desc_t), \
	.udi_audio_mic_format.bDescriptorType = AUDIO_CS_INTERFACE, \
	.udi_audio_mic_format.bDescriptorSubtype = AUDIO_AS_FORMAT_TYPE, \
	.udi_audio_mic_format.bFormatType = 1,  \
	.udi_audio_mic_format.bNrChannels = USB_AUDIO_NB_CHANNELS, \
	.udi_audio_mic_format.bSubframeSize = 2,  \
	.udi_audio_mic_format.bBitResolution = 16, \
	.udi_audio_mic_format.bSamFreqType = USB_AUDIO_NR_SAM_FREQ, \
	.udi_audio_mic_format.tSamFreq[0] = UAC1_SAMP_RATE(UDI_AUDIO_FREQ), \
	.udi_audio_mic_ep.bLength = sizeof(usb_ep_ext_desc_t), \
	.udi_audio_mic_ep.bDescriptorType = USB_DT_ENDPOINT, \
	.udi_audio_mic_ep.bEndpointAddress = UDI_AUDIO_DATA_EP_IN_0, \
	.udi_audio_mic_ep.bmAttributes = USB_EP_TYPE_ISOCHRONOUS | 0x04, \
	.udi_audio_mic_ep.wMaxPacketSize = 256, \
	.udi_audio_mic_ep.bInterval = 1, \
	.udi_audio_mic_ep.bRefresh = 0, \
	.udi_audio_mic_ep.bSynchAddress = 0, \
	.udi_audio_mic_cs_ep.bLength = sizeof(usb_audio_cs_endpoint_desc_t), \
	.udi_audio_mic_cs_ep.bDescriptorType = AUDIO_CS_ENDPOINT, \
	.udi_audio_mic_cs_ep.bDescriptorSubtype = AUDIO_AS_GENERAL, \
	.udi_audio_mic_cs_ep.bmAttributes = 0, \
	.udi_audio_mic_cs_ep.bLockDelayUnits = 0, \
	.udi_audio_mic_cs_ep.wLockDelay = 0 \
	}

// Global structure which contains standard UDI API for UDC
extern UDC_DESC_STORAGE udi_api_t udi_api_audio_control;
extern UDC_DESC_STORAGE udi_api_t udi_api_audio_streaming;

typedef enum {
	STATE_AUDIO_IDLE,
	STATE_AUDIO_STREAMING
} UDI_Audio_State_t;

void udi_audio_fill_buffer(uint16_t tone_freq);
void udi_audio_send(uint8_t* buf, uint32_t buflen);
//void udi_audio_fill_buffer(uint16_t* bufin, size_t size);
void udi_audio_register_callback(udi_callback cbk);

#ifdef __cplusplus
}
#endif
#endif // _UDI_AUDIO_H_
