====== CubeMx USB-audio 结构体详解 ====== --- usbd_audio.h typedef enum { AUDIO_CMD_START = 1, AUDIO_CMD_PLAY, AUDIO_CMD_STOP, }AUDIO_CMD_TypeDef; typedef enum { AUDIO_OFFSET_NONE = 0, AUDIO_OFFSET_HALF, AUDIO_OFFSET_FULL, AUDIO_OFFSET_UNKNOWN, } AUDIO_OffsetTypeDef; /** * @} */ /** @defgroup USBD_CORE_Exported_TypesDefinitions * @{ */ typedef struct { uint8_t cmd; uint8_t data[USB_MAX_EP0_SIZE]; uint8_t len; uint8_t unit; } USBD_AUDIO_ControlTypeDef; typedef struct { __IO uint32_t alt_setting; uint8_t buffer[AUDIO_TOTAL_BUF_SIZE]; AUDIO_OffsetTypeDef offset; uint8_t rd_enable; uint16_t rd_ptr; uint16_t wr_ptr; USBD_AUDIO_ControlTypeDef control; } USBD_AUDIO_HandleTypeDef; typedef struct { int8_t (*Init) (uint32_t AudioFreq, uint32_t Volume, uint32_t options); int8_t (*DeInit) (uint32_t options); int8_t (*AudioCmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); int8_t (*VolumeCtl) (uint8_t vol); int8_t (*MuteCtl) (uint8_t cmd); int8_t (*PeriodicTC) (uint8_t cmd); int8_t (*GetState) (void); }USBD_AUDIO_ItfTypeDef; ===== audio hardware interface driver ===== USBD_AUDIO_ItfTypeDef USBD_AUDIO_fops_FS; **结构体定义** // usbd_audio.h typedef struct { int8_t (*Init) (uint32_t AudioFreq, uint32_t Volume, uint32_t options); int8_t (*DeInit) (uint32_t options); int8_t (*AudioCmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); int8_t (*VolumeCtl) (uint8_t vol); int8_t (*MuteCtl) (uint8_t cmd); int8_t (*PeriodicTC) (uint8_t cmd); int8_t (*GetState) (void); }USBD_AUDIO_ItfTypeDef; * Init * Deinit * AudioCmd * VolumeCtrl * MuteCtl * PeriodicTC * GetState **变量定义** //usbd_audio_if.c USBD_AUDIO_ItfTypeDef USBD_AUDIO_fops_FS = { AUDIO_Init_FS, AUDIO_DeInit_FS, AUDIO_AudioCmd_FS, AUDIO_VolumeCtl_FS, AUDIO_MuteCtl_FS, AUDIO_PeriodicTC_FS, AUDIO_GetState_FS }; **注册** 由文件usb_device.c 中 MX_USB_DEVICE_Init() 调用 USBD_AUDIO_RegisterInterface() 注册。 // usb_device.c void MX_USB_DEVICE_Init(void) { /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */ /* USER CODE END USB_DEVICE_Init_PreTreatment */ /* Init Device Library, add supported class and start the library. */ if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) { Error_Handler(); } if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_AUDIO) != USBD_OK) { Error_Handler(); } if (USBD_AUDIO_RegisterInterface(&hUsbDeviceFS, &USBD_AUDIO_fops_FS) != USBD_OK) { Error_Handler(); } if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { Error_Handler(); } /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */ /* USER CODE END USB_DEVICE_Init_PostTreatment */ } // usbd_audio.c uint8_t USBD_AUDIO_RegisterInterface (USBD_HandleTypeDef *pdev, USBD_AUDIO_ItfTypeDef *fops) { if(fops != NULL) { pdev->pUserData= fops; } return 0; } ===== Audio 控制句柄 ===== ** 结构体定义 ** // usb_audio.h typedef struct { __IO uint32_t alt_setting; uint8_t buffer[AUDIO_TOTAL_BUF_SIZE]; AUDIO_OffsetTypeDef offset; uint8_t rd_enable; uint16_t rd_ptr; uint16_t wr_ptr; USBD_AUDIO_ControlTypeDef control; } USBD_AUDIO_HandleTypeDef; * alt_setting; * buffer[AUDIO_TOTAL_BUF_SIZE]; * offset; * rd_enable; * rd_ptr; * wr_ptr; * USBD_AUDIO_ControlTypeDef control; **注册并初始化** //usb_audio.c static uint8_t USBD_AUDIO_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx) { USBD_AUDIO_HandleTypeDef *haudio; DBG_FN_MARK(); /* Open EP OUT */ USBD_LL_OpenEP(pdev, AUDIO_OUT_EP, USBD_EP_TYPE_ISOC, AUDIO_OUT_PACKET); /* Allocate Audio structure */ pdev->pClassData = USBD_malloc(sizeof (USBD_AUDIO_HandleTypeDef)); if(pdev->pClassData == NULL) { return USBD_FAIL; } else { haudio = (USBD_AUDIO_HandleTypeDef*) pdev->pClassData; haudio->alt_setting = 0; haudio->offset = AUDIO_OFFSET_UNKNOWN; haudio->wr_ptr = 0; haudio->rd_ptr = 0; haudio->rd_enable = 0; /* Initialize the Audio output Hardware layer */ if (((USBD_AUDIO_ItfTypeDef *)pdev->pUserData)->Init(USBD_AUDIO_FREQ, AUDIO_DEFAULT_VOLUME, 0) != USBD_OK) { return USBD_FAIL; } /* Prepare Out endpoint to receive 1st packet */ USBD_LL_PrepareReceive(pdev, AUDIO_OUT_EP, haudio->buffer, AUDIO_OUT_PACKET); } return USBD_OK; } ===== 模块接口 ===== ---- 驱动中的各个模块接口,通过各自模块提供的注册函数注册到设备handle (变量: hUsbDeviceFS,类型: USBD_HandleTypeDef),注册函数在设备初始化过程 MX_USB_DEVICE_Init() 被调用。 * pClass : 设备类(class)接口入口 * pUserData : 设备Interface接口入口 设备handle结构体定义 // usbd_def.h /* USB Device handle structure */ typedef struct _USBD_HandleTypeDef { uint8_t id; uint32_t dev_config; uint32_t dev_default_config; uint32_t dev_config_status; USBD_SpeedTypeDef dev_speed; USBD_EndpointTypeDef ep_in[15]; USBD_EndpointTypeDef ep_out[15]; uint32_t ep0_state; uint32_t ep0_data_len; uint8_t dev_state; uint8_t dev_old_state; uint8_t dev_address; uint8_t dev_connection_status; uint8_t dev_test_mode; uint32_t dev_remote_wakeup; USBD_SetupReqTypedef request; USBD_DescriptorsTypeDef *pDesc; USBD_ClassTypeDef *pClass; void *pClassData; void *pUserData; void *pData; } USBD_HandleTypeDef; **模块的注册** void MX_USB_DEVICE_Init(void) { /* Init Device Library, add supported class and start the library. */ if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) { Error_Handler(); } if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_AUDIO) != USBD_OK) { Error_Handler(); } if (USBD_AUDIO_RegisterInterface(&hUsbDeviceFS, &USBD_AUDIO_fops_FS) != USBD_OK) { Error_Handler(); } if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { Error_Handler(); } } ==== Audio Interface 接口 - USBD_AUDIO_ItfTypeDef ==== ---- * AUDIO Interface 的接口,定义在结构体变量 USBD_AUDIO_fops_FS 中,类型为 USBD_AUDIO_ItfTypeDef * 注册函数 USBD_AUDIO_RegisterInterface() 将接口注册到USB设备handel变量中(hUsbDeviceFS.pUserData) * 注册函数(设备初始化时)由设备初始化函数 MX_USB_DEVICE_Init() 调用 接口结构体定义 //usbd_audio.h typedef struct { int8_t (*Init) (uint32_t AudioFreq, uint32_t Volume, uint32_t options); int8_t (*DeInit) (uint32_t options); int8_t (*AudioCmd) (uint8_t* pbuf, uint32_t size, uint8_t cmd); int8_t (*VolumeCtl) (uint8_t vol); int8_t (*MuteCtl) (uint8_t cmd); int8_t (*PeriodicTC) (uint8_t cmd); int8_t (*GetState) (void); }USBD_AUDIO_ItfTypeDef; 接口定义及初始化 // usbd_audio_if.c USBD_AUDIO_ItfTypeDef USBD_AUDIO_fops_FS = { AUDIO_Init_FS, AUDIO_DeInit_FS, AUDIO_AudioCmd_FS, AUDIO_VolumeCtl_FS, AUDIO_MuteCtl_FS, AUDIO_PeriodicTC_FS, AUDIO_GetState_FS }; 接口注册函数 // usbd_audio.c uint8_t USBD_AUDIO_RegisterInterface (USBD_HandleTypeDef *pdev, USBD_AUDIO_ItfTypeDef *fops) { if(fops != NULL) { pdev->pUserData= fops; } return 0; } 注册函数在 MX_USB_DEVICE_Init() (usb_device.c)中调用。 ==== Audio Class 接口 - USBD_ClassTypeDef ==== ---- * USBD_ClassTypeDef的接口,在结构体变量 USBD_AUDIO 中定义,类型为 USBD_ClassTypeDef * 注册函数 USBD_RegisterClass() 将接口注册到USB设备handel变量中(hUsbDeviceFS.pClass) * 注册函数(设备初始化时)由设备初始化函数 MX_USB_DEVICE_Init() 调用 接口结构体定义 // usbd_def.h typedef struct _Device_cb { uint8_t (*Init) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx); uint8_t (*DeInit) (struct _USBD_HandleTypeDef *pdev , uint8_t cfgidx); /* Control Endpoints*/ uint8_t (*Setup) (struct _USBD_HandleTypeDef *pdev , USBD_SetupReqTypedef *req); uint8_t (*EP0_TxSent) (struct _USBD_HandleTypeDef *pdev ); uint8_t (*EP0_RxReady) (struct _USBD_HandleTypeDef *pdev ); /* Class Specific Endpoints*/ uint8_t (*DataIn) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); uint8_t (*DataOut) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); uint8_t (*SOF) (struct _USBD_HandleTypeDef *pdev); uint8_t (*IsoINIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); uint8_t (*IsoOUTIncomplete) (struct _USBD_HandleTypeDef *pdev , uint8_t epnum); uint8_t *(*GetHSConfigDescriptor)(uint16_t *length); uint8_t *(*GetFSConfigDescriptor)(uint16_t *length); uint8_t *(*GetOtherSpeedConfigDescriptor)(uint16_t *length); uint8_t *(*GetDeviceQualifierDescriptor)(uint16_t *length); #if (USBD_SUPPORT_USER_STRING == 1) uint8_t *(*GetUsrStrDescriptor)(struct _USBD_HandleTypeDef *pdev ,uint8_t index, uint16_t *length); #endif } USBD_ClassTypeDef; 接口定义及初始化 //usbd_audio.c USBD_ClassTypeDef USBD_AUDIO = { USBD_AUDIO_Init, USBD_AUDIO_DeInit, USBD_AUDIO_Setup, USBD_AUDIO_EP0_TxReady, USBD_AUDIO_EP0_RxReady, USBD_AUDIO_DataIn, USBD_AUDIO_DataOut, USBD_AUDIO_SOF, USBD_AUDIO_IsoINIncomplete, USBD_AUDIO_IsoOutIncomplete, USBD_AUDIO_GetCfgDesc, USBD_AUDIO_GetCfgDesc, USBD_AUDIO_GetCfgDesc, USBD_AUDIO_GetDeviceQualifierDesc, }; 接口注册函数 // usbd_core.c USBD_StatusTypeDef USBD_RegisterClass(USBD_HandleTypeDef *pdev, USBD_ClassTypeDef *pclass) { USBD_StatusTypeDef status = USBD_OK; if(pclass != 0) { /* link the class to the USB Device handle */ pdev->pClass = pclass; status = USBD_OK; } else { status = USBD_FAIL; } return status; }