/**
******************************************************************************
@file usb_prop.c
@author MCD Application Team
@version V4.0.0
@date 21-January-2013
@brief All processing related to Virtual Com Port Demo
******************************************************************************
@attention
© COPYRIGHT 2013 STMicroelectronics
Licensed under MCD-ST Liberty SW License Agreement V2, (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.st.com/software_license_agreement_liberty_v2
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.
******************************************************************************
*/
// Includes
#include "usb_lib.h"
#include "usb_conf.h"
#include "usb_prop.h"
#include "usb_desc.h"
#include "usb_pwr.h"
#include "hw_config.h"
// Private variables
uint8_t MIC_MUTE = 0;
int16_t MIC_VOLUME = 0;
int16_t MIC_VOLUME_MIN = 0x8001;
int16_t MIC_VOLUME_MAX = 0x7FFF;
int16_t MIC_VOLUME_RES = 0x0001;
// Structures initializations
DEVICE Device_Table = {
EP_NUM,
1
};
DEVICE_PROP Device_Property = {
USBdev_Init,
USBdev_Reset,
USBdev_Status_In,
USBdev_Status_Out,
USBdev_Data_Setup,
USBdev_NoData_Setup,
USBdev_Get_Interface_Setting,
USBdev_GetDeviceDescriptor,
USBdev_GetConfigDescriptor,
USBdev_GetStringDescriptor,
0,
0x40 // bMaxPacketSize from USB_DeviceDescriptor
};
USER_STANDARD_REQUESTS User_Standard_Requests = {
USBdev_GetConfiguration,
USBdev_SetConfiguration,
USBdev_GetInterface,
USBdev_SetInterface,
USBdev_GetStatus,
USBdev_ClearFeature,
USBdev_SetEndPointFeature,
USBdev_SetDeviceFeature,
USBdev_SetDeviceAddress
};
ONE_DESCRIPTOR Device_Descriptor = {
(uint8_t *)USB_DeviceDescriptor,
USB_DESC_SIZE_DEVICE
};
ONE_DESCRIPTOR Config_Descriptor = {
(uint8_t *)Mic_ConfigDescriptor,
MIC_DESC_SIZE_CONFIG
};
ONE_DESCRIPTOR String_Descriptor[4] = {
{(uint8_t *)USB_StringLangID, USB_STRING_SIZE_LANGID},
{(uint8_t *)USB_StringVendor, USB_STRING_SIZE_VENDOR},
{(uint8_t *)USB_StringProduct, USB_STRING_SIZE_PRODUCT},
{(uint8_t *)USB_StringSerial, USB_STRING_SIZE_SERIAL},
};
// Public variables
extern uint8_t packet_send;
// Private functions
/*******************************************************************************
Function Name : USBdev_Init.
Description : Mic init routine.
Input : None.
Output : None.
Return : None.
*******************************************************************************/
void USBdev_Init() {
// Update the serial number string descriptor with the data from the unique ID
Get_SerialNum();
// Initialize the current configuration
pInformation->Current_Configuration = 0;
// Connect the device
PowerOn();
// Perform basic device initialization operations
USB_SIL_Init();
bDeviceState = UNCONNECTED;
}
/*******************************************************************************
Function Name : USBdev_Reset.
Description : Mic reset routine.
Input : None.
Output : None.
Return : None.
*******************************************************************************/
void USBdev_Reset() {
// Set Mic device as not configured state
pInformation->Current_Configuration = 0;
// Current Feature initialization
pInformation->Current_Feature = Mic_ConfigDescriptor[7];
// *BTABLE = BTABLE_ADDRESS & 0xFFF8;
*BTABLE = BTABLE_ADDRESS; // BTABLE_ADDRESS = 0
// Initialize Endpoint 0
SetEPType(ENDP0,EP_CONTROL);
SetEPTxStatus(ENDP0,EP_TX_NAK);
SetEPRxAddr(ENDP0,ENDP0_RXADDR);
SetEPRxCount(ENDP0,Device_Property.MaxPacketSize);
SetEPTxAddr(ENDP0,ENDP0_TXADDR);
Clear_Status_Out(ENDP0);
SetEPRxValid(ENDP0);
// Initialize Endpoint 1 (as double buffer)
SetEPType(ENDP1,EP_ISOCHRONOUS);
SetEPDoubleBuff(ENDP1);
SetEPDblBuffAddr(ENDP1,ENDP1_BUF0Addr,ENDP1_BUF1Addr);
SetEPDblBuffCount(ENDP1,EP_DBUF_IN,Device_Property.MaxPacketSize);
ClearDTOG_TX(ENDP1);
ClearDTOG_RX(ENDP1);
ToggleDTOG_RX(ENDP1);
SetEPRxStatus(ENDP1,EP_RX_DIS);
SetEPTxStatus(ENDP1,EP_TX_VALID);
SetEPRxValid(ENDP0);
// Set this device to response on default address
SetDeviceAddress(0);
bDeviceState = ATTACHED;
packet_send = 1;
}
/*******************************************************************************
Function Name : USBdev_SetConfiguration.
Description : Update the device state to configured.
Input : None.
Output : None.
Return : None.
*******************************************************************************/
void USBdev_SetConfiguration(void) {
if (Device_Info.Current_Configuration) bDeviceState = CONFIGURED;
}
/*******************************************************************************
Function Name : USBdev_SetConfiguration.
Description : Update the device state to addressed.
Input : None.
Output : None.
Return : None.
*******************************************************************************/
void USBdev_SetDeviceAddress(void) {
bDeviceState = ADDRESSED;
}
/*******************************************************************************
Function Name : USBdev_Status_In.
Description : Mic Status In routine.
Input : None.
Output : None.
Return : None.
*******************************************************************************/
void USBdev_Status_In(void) {
}
/*******************************************************************************
Function Name : USBdev_Status_Out.
Description : Mic Status Out routine.
Input : None.
Output : None.
Return : None.
*******************************************************************************/
void USBdev_Status_Out(void) {
}
/*******************************************************************************
Function Name : USBdev_Data_Setup
Description : Handle the data class specific requests.
Input : None.
Output : None.
Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
RESULT USBdev_Data_Setup(uint8_t RequestNo) {
uint8_t *(*CopyRoutine)(uint16_t) = NULL;
switch (pInformation->USBbmRequestType) {
case 0xA1:
UART_SendStr(USART2," -> GET FU\n");
CopyRoutine = Mic_FU_Get;
break;
case 0x21:
UART_SendStr(USART2," -> SET FU\n");
CopyRoutine = Mic_FU_Set;
break;
case 0xA2:
UART_SendStr(USART2," -> GET EP\n");
CopyRoutine = Mic_EP_Get;
break;
case 0x22:
UART_SendStr(USART2," -> SET EP\n");
CopyRoutine = Mic_EP_Set;
break;
default:
return USB_UNSUPPORT;
break;
}
pInformation->Ctrl_Info.CopyData = CopyRoutine;
pInformation->Ctrl_Info.Usb_wOffset = 0;
(*CopyRoutine)(0);
return USB_SUCCESS;
}
/*******************************************************************************
Function Name : USBdev_NoData_Setup
Description : Handle the no data class specific requests.
Input : None.
Output : None.
Return : USB_UNSUPPORT or USB_SUCCESS.
*******************************************************************************/
RESULT USBdev_NoData_Setup(uint8_t RequestNo) {
return USB_UNSUPPORT;
}
/*******************************************************************************
Function Name : USBdev_GetDeviceDescriptor.
Description : Get the device descriptor.
Input : Length : uint16_t.
Output : None.
Return : The address of the device descriptor.
*******************************************************************************/
uint8_t *USBdev_GetDeviceDescriptor(uint16_t Length) {
return Standard_GetDescriptorData(Length,&Device_Descriptor);
}
/*******************************************************************************
Function Name : USBdev_GetConfigDescriptor.
Description : Get the configuration descriptor.
Input : Length : uint16_t.
Output : None.
Return : The address of the configuration descriptor.
*******************************************************************************/
uint8_t *USBdev_GetConfigDescriptor(uint16_t Length) {
return Standard_GetDescriptorData(Length,&Config_Descriptor);
}
/*******************************************************************************
Function Name : USBdev_GetStringDescriptor.
Description : Get the string descriptors according to the needed index.
Input : Length : uint16_t.
Output : None.
Return : The address of the string descriptors.
*******************************************************************************/
uint8_t *USBdev_GetStringDescriptor(uint16_t Length) {
uint8_t wValue0 = pInformation->USBwValue0;
if (wValue0 > 4) {
return NULL;
} else {
return Standard_GetDescriptorData(Length,&String_Descriptor[wValue0]);
}
}
/*******************************************************************************
Function Name : USBdev_Get_Interface_Setting.
Description : test the interface and the alternate setting according to the
supported one.
Input1 : uint8_t: Interface : interface number.
Input2 : uint8_t: AlternateSetting : Alternate Setting number.
Output : None.
Return : The address of the string descriptors.
*******************************************************************************/
RESULT USBdev_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting) {
if (AlternateSetting > 1) {
return USB_UNSUPPORT;
} else if (Interface > 1) {
return USB_UNSUPPORT;
}
return USB_SUCCESS;
}
// Handle feature unit GET control request
uint8_t *Mic_FU_Get(uint16_t Length) {
if (Length) {
switch (Length) {
case 0x0001:
// Mute control supports only CUR
UART_SendStr(USART2," -> MUTE CUR\n");
return &MIC_MUTE;
break;
case 0x0002:
// Volume control
UART_SendStr(USART2," -> VOLUME ");
switch (pInformation->USBbRequest) {
case GET_CUR:
UART_SendStr(USART2,"CUR\n");
return (uint8_t *)&MIC_VOLUME;
break;
case GET_MAX:
UART_SendStr(USART2,"MAX\n");
return (uint8_t *)&MIC_VOLUME_MAX;
break;
case GET_MIN:
UART_SendStr(USART2,"MIN\n");
return (uint8_t *)&MIC_VOLUME_MIN;
break;
case GET_RES:
UART_SendStr(USART2,"RES\n");
return (uint8_t *)&MIC_VOLUME_RES;
break;
default:
break;
}
break;
default:
// Don't know how to handle this
break;
}
return NULL;
} else {
switch (Length) {
case 0x0001:
// Mute control
pInformation->Ctrl_Info.Usb_wLength = 1;
break;
case 0x0002:
// Volume control
pInformation->Ctrl_Info.Usb_wLength = 2;
break;
default:
pInformation->Ctrl_Info.Usb_wLength = pInformation->USBwLengths.w;
break;
}
return NULL;
}
}
// Handle feature unit SET control request
uint8_t *Mic_FU_Set(uint16_t Length) {
if (Length) {
return (uint8_t *)(&MIC_MUTE);
} else {
pInformation->Ctrl_Info.Usb_wLength = pInformation->USBwLengths.w;
return NULL;
}
}
// Handle endpoint GET control request
uint8_t *Mic_EP_Get(uint16_t Length) {
if (Length) {
return (uint8_t *)(&MIC_MUTE);
} else {
pInformation->Ctrl_Info.Usb_wLength = pInformation->USBwLengths.w;
return NULL;
}
}
// Handle endpoint SET control request
uint8_t *Mic_EP_Set(uint16_t Length) {
if (Length) {
UART_SendStr(USART2,"EP: ");
UART_SendHex8(USART2,pInformation->USBwIndexs.bw.bb0);
UART_SendChar(USART2,'\n');
if (pInformation->USBwIndexs.bw.bb0 != 0x81) {
// Don't know to handle this EP
UART_SendStr(USART2,"DOH!\n");
return NULL;
}
UART_SendStr(USART2," -> SAMPLE RATE\n");
if (Length != 3) {
// Don't know how to handle this
return NULL;
}
// Set sampling rate request
UART_SendStr(USART2,"bRequest: ");
UART_SendHex16(USART2,pInformation->USBbRequest);
UART_SendChar(USART2,'\n');
/*
UART_SendStr(USART2,"wValue: ");
UART_SendHex16(USART2,pInformation->USBwValues.w);
UART_SendChar(USART2,'\n');
UART_SendStr(USART2,"Length: ");
UART_SendHex16(USART2,Length);
UART_SendChar(USART2,'\n');
UART_SendStr(USART2,"bRequest: ");
UART_SendHex16(USART2,pInformation->USBbRequest);
UART_SendChar(USART2,'\n');
*/
return (uint8_t *)(&MIC_MUTE);
} else {
pInformation->Ctrl_Info.Usb_wLength = pInformation->USBwLengths.w;
return NULL;
}
}