STM32 USB组合设备HID+MIDI
目的:完成一个HID + MIDI的组合设备
准备工作:
·用CUBE生成HID工程;
·复制一份工程修改为MIDI工程;(参考之前博客已完成这两个工程)
·新建USB_User文件夹,将USB相关配置文件放到这里,并新建usbd_composite.c,usbd_composite.h文件;
·修改:
·分配端点号
#define HID_EPIN_ADDR 0x81
#define HID_EPIN_SIZE 0x40
#define HID_EPOUT_ADDR 0x01
#define HID_EPOUT_SIZE 0x40
#define MIDI_EPIN_ADDR 0x82
#define MIDI_EPOUT_ADDR 0x02
#define MIDI_EPIN_SIZE 0x40
#define MIDI_EPOUT_SIZE 0x40
·添加usbd_composite.c,usbd_composite.h文件内容:
<<usbd_composite.c>>
#include "usbd_composite.h"
#include "usbd_hid_if.h"
#include "usbd_midi_if.h"
static USBD_HID_HandleTypeDef *pHIDData;
static USBD_MIDI_HandleTypeDef *pMIDIData;
static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev, uint8_t cfgidx);
static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req);
static uint8_t USBD_Composite_EP0_RxReady(USBD_HandleTypeDef *pdev);
static uint8_t USBD_Composite_DataIn (USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t USBD_Composite_DataOut (USBD_HandleTypeDef *pdev, uint8_t epnum);
static uint8_t *USBD_Composite_GetFSCfgDesc (uint16_t *length);
static uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length);
USBD_ClassTypeDef USBD_COMPOSITE =
{
USBD_Composite_Init,
USBD_Composite_DeInit,
USBD_Composite_Setup,
NULL, /*EP0_TxSent*/
USBD_Composite_EP0_RxReady, /*EP0_RxReady*/
USBD_Composite_DataIn,
USBD_Composite_DataOut,
NULL,
NULL,
NULL,
USBD_Composite_GetFSCfgDesc,
USBD_Composite_GetFSCfgDesc,
USBD_Composite_GetFSCfgDesc,
USBD_Composite_GetDeviceQualifierDescriptor,
};
/* USB composite device Configuration Descriptor */
/* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */
__ALIGN_BEGIN uint8_t USBD_Composite_CfgFSDesc[USBD_COMPOSITE_DESC_SIZE] __ALIGN_END =
{
/*Configuration Descriptor*/
0x09, /* bLength: Configuration Descriptor size */
USB_DESC_TYPE_CONFIGURATION, /* bDescriptorType: Configuration */
USBD_COMPOSITE_DESC_SIZE,
0x00,
USBD_MAX_NUM_INTERFACES, /* bNumInterfaces: 2 interface */
0x01, /* bConfigurationValue: Configuration value */
0x00, /* iConfiguration: Index of string descriptor describing the configuration */
0xC0, /* bmAttributes: self powered */
0x00, /* MaxPower 0 mA */
/*--HID 1-------------------------------------------------------------------------*/
/* 9 */
/*******************接口描述符*********************/
//bLength字段。接口描述符的长度为9字节。
0x09,
//bDescriptorType字段。接口描述符的编号为0x04。
0x04,
//bInterfaceNumber字段。该接口的编号,第一个接口,编号为0。
USB_INTERFACE_HID_INDEX,
//bAlternateSetting字段。该接口的备用编号,为0。
0x00,
//bNumEndpoints字段。非0端点的数目。本实例需要二个
//中断端点(一个输入一个输出),因此该值为2。
0x02,
//bInterfaceClass字段。该接口所使用的类。本实例是HID类,
//HID类的编码为0x03。
0x03,
//bInterfaceSubClass字段。该接口所使用的子类。在HID1.1协议中,
//只规定了一种子类:支持BIOS引导启动的子类。
//USB键盘、鼠标属于该子类,子类代码为0x01。
//但这里我们是自定义的HID设备,所以不使用子类。
0x00,
//bInterfaceProtocol字段。如果子类为支持引导启动的子类,
//则协议可选择鼠标和键盘。键盘代码为0x01,鼠标代码为0x02。
//自定义的HID设备,也不使用协议。
0x00,
//iConfiguration字段。该接口的字符串索引值。这里没有,为0。
0x00,
/* 18 */
/******************HID描述符************************/
//bLength字段。本HID描述符下只有一个下级描述符。所以长度为9字节。
0x09,
//bDescriptorType字段。HID描述符的编号为0x21。
0x21,
//bcdHID字段。本协议使用的HID1.1协议。注意低字节在先。
0x10,
0x01,
//bCountyCode字段。设备适用的国家代码,这里选择为美国,代码0x21。
0x21,
//bNumDescriptors字段。下级描述符的数目。我们只有一个报告描述符。
0x01,
//bDescritporType字段。下级描述符的类型,为报告描述符,编号为0x22。
0x22,
//bDescriptorLength字段。下级描述符的长度。下级描述符为报告描述符。
USBD_HID_REPORT_DESC_SIZE,
0,
/* 27 */
/**********************输入端点描述符***********************/
//bLength字段。端点描述符长度为7字节。
0x07,
//bDescriptorType字段。端点描述符编号为0x05。
0x05,
//bEndpointAddress字段。端点的地址。我们使用D12的输入端点1。
//D7位表示数据方向,输入端点D7为1。所以输入端点1的地址为0x81。
HID_EPIN_ADDR,//IN 1
//bmAttributes字段。D1~D0为端点传输类型选择。
//该端点为中断端点。中断端点的编号为3。其它位保留为0。
0x03,
//wMaxPacketSize字段。该端点的最大包长。端点1的最大包长为16字节。
//注意低字节在先。
HID_EPIN_SIZE,
0x00,
//bInterval字段。端点查询的时间,我们设置为10个帧时间,即1ms。
0x01,
/* 34 */
/**********************输出端点描述符***********************/
//bLength字段。端点描述符长度为7字节。
0x07,
//bDescriptorType字段。端点描述符编号为0x05。
0x05,
//bEndpointAddress字段。端点的地址。我们使用D12的输出端点1。
//D7位表示数据方向,输出端点D7为0。所以输出端点1的地址为0x01。
HID_EPOUT_ADDR,
//bmAttributes字段。D1~D0为端点传输类型选择。
//该端点为中断端点。中断端点的编号为3。其它位保留为0。
0x03,
//wMaxPacketSize字段。该端点的最大包长。端点1的最大包长为16字节。
//注意低字节在先。
HID_EPOUT_SIZE,
0x00,
//bInterval字段。端点查询的时间,我们设置为10个帧时间,即1ms。
0x01,
/* 41 */
#if 1
/*--MIDI-------------------------------------------------------------------------*/
/******************* Standard AC Interface Descriptor *********************/
/* 00 */
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE, /*bDescriptorType: Interface descriptor type*/
USB_INTERFACE_MIDI_CONTRL_INDEX, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x00, /*bNumEndpoints*/
0x01, /*bInterfaceClass: Audio*/
0x01, /*bInterfaceSubClass : Audio Control*/
0, /*nInterfaceProtocol*/
0, /*iInterface: Index of string descriptor*/
/**************** Class-specific AC Interface Descriptor ******************/
/* 9 */
0x09, /*bLength: Interface Descriptor size*/
0x24, /*bDescriptorType: Class-specific interface descriptor type*/
0x01, /*bDescriptorSubType: Header*/
0x00, /*bcdADC: Revision of class specification - 1.0*/
0x01,
0x09, /*wTotalLength: Total size of class specific discriptor*/
0x00,
0x01, /*bInCollection: Number of streaming interfaces*/
USB_INTERFACE_MIDI_INDEX, /*baInterfaceNr : MIDIStreaming interface 1 belongs to
this AudioControl interface*/
/******************* Standard MS Interface Descriptor *********************/
/* 18 */
0x09, /*bLength: Interface Descriptor size*/
USB_DESC_TYPE_INTERFACE, /*bDescriptorType: Interface descriptor type*/
USB_INTERFACE_MIDI_INDEX, /*bInterfaceNumber: Number of Interface*/
0x00, /*bAlternateSetting: Alternate setting*/
0x02, /*bNumEndpoints*/
0x01, /*bInterfaceClass: Audio*/
0x03, /*bInterfaceSubClass : MIDI Streaming*/
0, /*nInterfaceProtocol*/
0, /*iInterface: Index of string descriptor*/
/**************** Class-specific MS Interface Descriptor ******************/
/* 27 */
0x07, /*bLength: Interface Descriptor size*/
0x24, /*bDescriptorType: Class-specific interface descriptor type*/
0x01, /*bDescriptorSubType: MS Header*/
0x00, /*bcdADC: Revision of class specification*/
0x01,
0x41, /*wTotalLength: Total size of class specific discriptor*/
0x00,
/******************* MIDI IN Jack Descriptor (Embedded) *******************/
/* 34 */
0x06, /*bLength: Size of this descriptor*/
0x24, /*bDescriptorType: Class-specific interface descriptor type*/
0x02, /*bDescriptorSubType: MIDI IN Jack*/
0x01, /*bJackType: Embedded*/
0x01, /*bJackID: ID of this Jack*/
0x00, /*iJack*/
/******************* MIDI IN Jack Descriptor (External) *******************/
/* 40 */
0x06, /*bLength: Size of this descriptor*/
0x24, /*bDescriptorType: Class-specific interface descriptor type*/
0x02, /*bDescriptorSubType: MIDI IN Jack*/
0x02, /*bJackType: External*/
0x02, /*bJackID: ID of this Jack*/
0x00, /*iJack*/
/******************* MIDI OUT Jack Descriptor (Embedded) ******************/
/* 46 */
0x09, /*bLength: Size of this descriptor*/
0x24, /*bDescriptorType: Class-specific interface descriptor type*/
0x03, /*bDescriptorSubType: MIDI OUT Jack*/
0x01, /*bJackType: Embedded*/
0x03, /*bJackID: ID of this Jack*/
0x01, /*bNrInputPins: Number of Input Pins of this Jack*/
0x02, /*BaSourceID: ID of the Entry to which this Pin is connected*/
0x01, /*BaSourceID: Output Pin number of the Entry to
which this Input Pin is connected*/
0x00, /*iJack*/
/******************* MIDI OUT Jack Descriptor (External) ******************/
/* 55 */
0x09, /*bLength: Size of this descriptor*/
0x24, /*bDescriptorType: Class-specific interface descriptor type*/
0x03, /*bDescriptorSubType: MIDI OUT Jack*/
0x02, /*bJackType: External*/
0x04, /*bJackID: ID of this Jack*/
0x01, /*bNrInputPins: Number of Input Pins of this Jack*/
0x02, /*BaSourceID: ID of the Entry to which this Pin is connected*/
0x01, /*BaSourceID: Output Pin number of the Entry to
which this Input Pin is connected*/
0x00, /*iJack*/
/****************** Standard Bulk OUT Endpoint Descriptor *****************/
/* 64 */
0x09, /*bLength: Size of this descriptor*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType: Endpoint descriptor type*/
MIDI_EPOUT_ADDR, /*bEndpointAddress: OUT Endpoint 1*/
0x02, /*bmAttributes: Bulk, not shared.*/
0x40, /*wMaxPacketSize 64*/
0x00,
0x00, /*bInterval*/
0x00, /*bRefresh*/
0x00, /*bSynchAddress*/
/************* Class-specific MS Bulk OUT Endpoint Descriptor *************/
/* 73 */
0x05, /*bLength: Size of this descriptor*/
0x25, /*bDescriptorType: Class-specific endpoint descriptor type*/
0x01, /*bDescriptorSubType: MS General*/
0x01, /*bNumEmbMIDIJack: Number of embedded MIDI IN Jack*/
0x01, /*BaAssocJackID: ID of the Embedded MIDI IN Jack*/
/****************** Standard Bulk IN Endpoint Descriptor *****************/
/* 78 */
0x09, /*bLength: Size of this descriptor*/
USB_DESC_TYPE_ENDPOINT, /*bDescriptorType: Endpoint descriptor type*/
MIDI_EPIN_ADDR, /*bEndpointAddress: IN Endpoint 1*/
0x02, /*bmAttributes: Bulk, not shared.*/
0x40, /*wMaxPacketSize 64*/
0x00,
0x00, /*bInterval*/
0x00, /*bRefresh*/
0x00, /*bSynchAddress*/
/************* Class-specific MS Bulk OUT Endpoint Descriptor *************/
/* 87 */
0x05, /*bLength: Size of this descriptor*/
0x25, /*bDescriptorType: Class-specific endpoint descriptor type*/
0x01, /*bDescriptorSubType: MS General*/
0x01, /*bNumEmbMIDIJack: Number of embedded MIDI OUT Jack*/
0x03, /*BaAssocJackID: ID of the Embedded MIDI OUT Jack*/
/* 92 */
#endif
};
/* USB Standard Device Descriptor */
__ALIGN_BEGIN uint8_t USBD_Composite_DeviceQualifierDesc[USB_LEN_DEV_QUALIFIER_DESC] __ALIGN_END =
{
USB_LEN_DEV_QUALIFIER_DESC,
USB_DESC_TYPE_DEVICE_QUALIFIER,
0x00,
0x02,
0x00,
0x00,
0x00,
0x40,
0x01,
0x00,
};
/**
* @brief USBD_Composite_Init
* Initialize the Composite interface
* @param pdev: device instance
* @param cfgidx: Configuration index
* @retval status
*/
static uint8_t USBD_Composite_Init (USBD_HandleTypeDef *pdev, uint8_t cfgidx)
{
uint8_t res = 0;
pdev->pUserData = &USBD_HID_fops_FS;
res += USBD_HID.Init(pdev,cfgidx);
pHIDData = pdev->pClassData;
pdev->pUserData = &USBD_MIDI_fops_FS;
res += USBD_MIDI.Init(pdev,cfgidx);
pMIDIData = pdev->pClassData;
return res;
}
/**
* @brief USBD_Composite_DeInit
* DeInitilaize the Composite configuration
* @param pdev: device instance
* @param cfgidx: configuration index
* @retval status
*/
static uint8_t USBD_Composite_DeInit (USBD_HandleTypeDef *pdev,
uint8_t cfgidx)
{
uint8_t res = 0;
pdev->pUserData = &USBD_HID_fops_FS;
pdev->pClassData = pHIDData;
res += USBD_HID.DeInit(pdev,cfgidx);
pdev->pUserData = &USBD_MIDI_fops_FS;
pdev->pClassData = pMIDIData;
res += USBD_MIDI.DeInit(pdev,cfgidx);
return res;
}
/**
* @brief USBD_Composite_Setup
* Handle the Composite requests
* @param pdev: device instance
* @param req: USB request
* @retval status
*/
static uint8_t USBD_Composite_Setup (USBD_HandleTypeDef *pdev, USBD_SetupReqTypedef *req)
{
switch (req->bmRequest & USB_REQ_RECIPIENT_MASK)
{
case USB_REQ_RECIPIENT_INTERFACE:
switch(req->wIndex)
{
case USB_INTERFACE_HID_INDEX:
pdev->pUserData = &USBD_HID_fops_FS;
pdev->pClassData = pHIDData;
return(USBD_HID.Setup(pdev, req));
case USB_INTERFACE_MIDI_INDEX:
pdev->pUserData = &USBD_MIDI_fops_FS;
pdev->pClassData = pMIDIData;
return(USBD_MIDI.Setup(pdev, req));
default:
break;
}
break;
case USB_REQ_RECIPIENT_ENDPOINT:
switch(req->wIndex)
{
case HID_EPIN_ADDR:
case HID_EPOUT_ADDR:
pdev->pClassData = pHIDData;
pdev->pUserData = &USBD_HID_fops_FS;
return(USBD_HID.Setup(pdev, req));
case MIDI_EPIN_ADDR:
case MIDI_EPOUT_ADDR:
pdev->pClassData = pMIDIData;
pdev->pUserData = &USBD_MIDI_fops_FS;
return(USBD_MIDI.Setup(pdev, req));
default:
break;
}
break;
}
return USBD_OK;
}
/**
* @brief USBD_HID_EP0_RxReady
* Handles control request data.
* @param pdev: device instance
* @retval status
*/
uint8_t USBD_Composite_EP0_RxReady(USBD_HandleTypeDef *pdev)
{
return USBD_HID.EP0_RxReady(pdev);
}
/**
* @brief USBD_Composite_DataIn
* handle data IN Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_Composite_DataIn(USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
switch(epnum)
{
case HID_INDATA_NUM:
pdev->pUserData = &USBD_HID_fops_FS;
pdev->pClassData = pHIDData;
return(USBD_HID.DataIn(pdev,epnum));
case MIDI_INDATA_NUM:
pdev->pUserData = &USBD_MIDI_fops_FS;
pdev->pClassData = pMIDIData;
return(USBD_MIDI.DataIn(pdev,epnum));
default:
break;
}
return USBD_FAIL;
}
/**
* @brief USBD_Composite_DataOut
* handle data OUT Stage
* @param pdev: device instance
* @param epnum: endpoint index
* @retval status
*/
uint8_t USBD_Composite_DataOut(USBD_HandleTypeDef *pdev,
uint8_t epnum)
{
switch(epnum)
{
case HID_OUTDATA_NUM:
pdev->pUserData = &USBD_HID_fops_FS;
pdev->pClassData = pHIDData;
return(USBD_HID.DataOut(pdev,epnum));
case MIDI_OUTDATA_NUM:
pdev->pUserData = &USBD_MIDI_fops_FS;
pdev->pClassData = pMIDIData;
return(USBD_MIDI.DataOut(pdev,epnum));
default:
break;
}
return USBD_FAIL;
}
/**
* @brief USBD_Composite_GetHSCfgDesc
* return configuration descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_Composite_GetFSCfgDesc (uint16_t *length)
{
*length = sizeof (USBD_Composite_CfgFSDesc);
return USBD_Composite_CfgFSDesc;
}
/**
* @brief DeviceQualifierDescriptor
* return Device Qualifier descriptor
* @param length : pointer data length
* @retval pointer to descriptor buffer
*/
uint8_t *USBD_Composite_GetDeviceQualifierDescriptor (uint16_t *length)
{
*length = sizeof (USBD_Composite_DeviceQualifierDesc);
return USBD_Composite_DeviceQualifierDesc;
}
<<usbd_composite.h>>
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_COMPOSITE_H
#define __USBD_COMPOSITE_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "usbd_hid.h"
#include "usbd_midi.h"
#include "usbd_desc.h"
#include "usbd_ctlreq.h"
#define WBVAL(x) (x & 0xFF),((x >> 8) & 0xFF)
#define DBVAL(x) (x & 0xFF),((x >> 8) & 0xFF),((x >> 16) & 0xFF),((x >> 24) & 0xFF)
#define USBD_COMPOSITE_DESC_SIZE (41+92)
#define USB_INTERFACE_HID_INDEX 0
#define USB_INTERFACE_MIDI_CONTRL_INDEX 1
#define USB_INTERFACE_MIDI_INDEX 2
#define HID_INDATA_NUM (HID_EPIN_ADDR & 0x0F)
#define HID_OUTDATA_NUM (HID_EPOUT_ADDR & 0x0F)
#define MIDI_INDATA_NUM (MIDI_EPIN_ADDR & 0x0F)
#define MIDI_OUTDATA_NUM (MIDI_EPOUT_ADDR & 0x0F)
extern USBD_ClassTypeDef USBD_COMPOSITE;
#ifdef __cplusplus
}
#endif
#endif
·修改usbd_device.c
void MX_USB_DEVICE_Init(void)
{
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUsbDeviceFS, &USBD_COMPOSITE);
// USBD_HID_RegisterInterface(&hUsbDeviceFS, &USBD_HID_fops_FS);
USBD_Start(&hUsbDeviceFS);
}
·修改usbd_config.c
USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev)
{
/* Init USB Ip. */
/* Link the driver to the stack. */
hpcd_USB_FS.pData = pdev;
pdev->pData = &hpcd_USB_FS;
hpcd_USB_FS.Instance = USB;
hpcd_USB_FS.Init.dev_endpoints = 8;
hpcd_USB_FS.Init.speed = PCD_SPEED_FULL;
hpcd_USB_FS.Init.ep0_mps = DEP0CTL_MPS_8;
hpcd_USB_FS.Init.low_power_enable = DISABLE;
hpcd_USB_FS.Init.lpm_enable = DISABLE;
hpcd_USB_FS.Init.battery_charging_enable = DISABLE;
if (HAL_PCD_Init(&hpcd_USB_FS) != HAL_OK)
{
Error_Handler( );
}
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x00 , PCD_SNG_BUF, 0x18);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , 0x80 , PCD_SNG_BUF, 0x58);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPIN_ADDR , PCD_SNG_BUF, 0x98);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , HID_EPOUT_ADDR , PCD_SNG_BUF, 0xD8);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , MIDI_EPIN_ADDR , PCD_SNG_BUF, 0x118);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , MIDI_EPOUT_ADDR , PCD_SNG_BUF, 0x158);
return USBD_OK;
}
·修改usbd_config.h
#define USBD_MAX_NUM_INTERFACES 3
·修改usbd_desc.c
#define USBD_PRODUCT_STRING_FS "STM32_HID+MIDI"
·修改main.c文件,
·烧录测试
识别到HID设备和MIDI设备了
MIDI数据收发OK
HID数据收发OK
参考资料:
使用STM32CubeMX编写USB复合设备 https://www.taterli.com/2355/
STM32 USB复合设备编写 https://www.cnblogs.com/WeyneChen/p/6007049.html
STM32 USB组合设备HID+MIDI相关推荐
- STM32配置组合设备(HID+CDC)
STM32组合设备 STM32配置组合设备(HID+CDC) 1. CDC基础工程,HID基础工程生成 2.USB工程熟悉 2.1 USB初始化 2.2USB中断 2.3 相关结构体 2.3.1 ` ...
- STM32CubeMX | 基于STM32使用HAL库实现USB组合设备之多路CDC
STM32CubeMX | 基于STM32使用HAL库实现USB组合设备之多路CDC 本博客完整代码下载地址:https://download.csdn.net/download/qq15347150 ...
- STM32 USB VCOM和HID的区别,配置及Echo功能实现(HAL)
STM32 USB VCOM和HID的区别,配置及Echo功能实现(HAL ) STM32的USB功能模块可以配置为虚拟串口(VCOM: Visual Port Com)或人机交互设备(HID: Hu ...
- USB Compound Device,USB复合设备 ; USB Composite Device,USB组合设备【转】
本文转载自:https://blog.csdn.net/autumn20080101/article/details/52776863 科普下USB复合设备和USB组合设备的区别. 关键字 Commu ...
- USB组合设备——带鼠标功能的键盘
文章目录 带鼠标功能的键盘 一个接口实现 报告描述符示例 键盘的报告 鼠标的报告 两个接口实现 配置描述符集合结构 配置描述符集合的实现 接口 1 字符串描述符(索引为 4) 接口 2 字符串描述符( ...
- linux usb组合设备,USB组合设备(5)
最近做一个组合设备,说白了就是在一个usb 设备上面,实现2个或者更多功能,但是说实话中文的资料还是比较少,没找到多少比较靠谱的,就去外文网站翻翻了 还是不少的,下面我将自己的理解理清改一下,希望也可 ...
- 【STM32学习】 基于STM32 USB存储设备的w25qxx自动判断容量检测
简介 使用STM32USB功能配置成Mass Storage Class 存储介质使用w25qxx做U盘时,发现一个比较好玩的事情. 当换不同容量的存储介质时需要改下程序,显示不同的大小. 更改usb ...
- linux usb组合设备,USB复合设备的实现
USB复合设备一般用Interface Association Descriptor(IAD)实现,就是在要合并的接口前加上IAD描述符. IAD描述符: typedef struct _USBInt ...
- 首创STM32 USB主机驱动4G rndis设备
1.4G模块使用技术现状与难题 4G模块支持的对外通信接口有串口和USB接口,串口一般使用AT指令的方式,这个在MCU类产品上面使用的很多,USB接口主用于在连接APU应用处理器上面,由LINUX操作 ...
最新文章
- VS.net2008正式版发布了
- Android Activity的launchMode四种启动模式备忘
- Spring Boot-Profile
- make的自动变量和预定义变量
- 今天来谈谈Python中的各种排序总结,含实现代码
- JAVA可阻塞队列-ArrayBlockingQueue
- 【基础数论】欧拉函数
- 视达配色教程2 好的配色的第一条件是什么
- zabbix mysql trapper_分分钟一键部署Zabbix Server
- fms +fme 视频直播
- 相见恨晚的 18 个 Linux 趣味命令,最后一个千万要尝试~
- 2019年广东当代优质民办学校获奖名单公布
- 如何关闭计算机自动关机设置方法,Win7电脑怎么取消自动关机?
- win7计算机图标缩在,win7桌面图标怎么变小?win7桌面图标变小解决方法
- 蜗牛星际改内存_二、FreeNAS篇:使用U盘在蜗牛星际上安装FreeNAS
- 第八章 性能优化 之 内存优化(一)
- 北斗校时系统(GPS授时设备)几种时间同步方法
- C# 矩阵库 功能特别强大!!
- Java设计模式之外观模式
- 求二叉树的叶子节点数目