#include "custom_core.h"
#define USBD_VID 0xABCDU
#define USBD_PID 0x1234U
/* USER */
extern rt_sem_t Sem_usb_rc;
extern rt_sem_t Sem_usb_se;
uint8_t custom_rc_buff[512];
uint8_t custom_se_buff[512];
extern usb_core_driver usbd_custom;
/* USB standard device descriptor USB标准设备描述符 */
__ALIGN_BEGIN const usb_desc_dev custom_dev_desc __ALIGN_END =
{
.header =
{
.bLength = USB_DEV_DESC_LEN, //0x12 此描述表的字节数 18个
.bDescriptorType = USB_DESCTYPE_DEV, //描述符的类型 0x01 设备描述符
},
.bcdUSB = 0x0200U, //USB版本 USB2.0 则0x200 USB2.13 则0x213
.bDeviceClass = 0xFFU, // 设备为自定义设备类型 0xff
.bDeviceSubClass = 0x00U, //子类掩码 保留
.bDeviceProtocol = 0x00U, //0x00
.bMaxPacketSize0 = USB_FS_EP0_MAX_LEN, //端点0的最大包大小64
.idVendor = USBD_VID, // 0xABCDU 厂商标志
.idProduct = USBD_PID, //0x1234U 产品标志
.bcdDevice = 0x0100U, //0x0100U 设备发行号
.iManufacturer = STR_IDX_MFC, //(uint8_t *)&manufacturer_string 描述厂商信息的字符串描述符的索引值
.iProduct = STR_IDX_PRODUCT, //(uint8_t *)&product_string 描述产品信息的字串描述符的索引值
.iSerialNumber = STR_IDX_SERIAL, //(uint8_t *)&serial_string 描述设备序列号信息的字串描述符的索引值
.bNumberConfigurations = USBD_CFG_MAX_NUM, //配置描述符数目 1
};
/* USB device configuration descriptor USB本设备的配置 */
__ALIGN_BEGIN const usb_custom_desc_config_set custom_config_desc __ALIGN_END =
{
.config =
{
.header =
{
.bLength = sizeof(usb_desc_config),
.bDescriptorType = USB_DESCTYPE_CONFIG //0x02 配置描述符
},
.wTotalLength = USB_DEV_CONFIG_DESC_LEN, //此配置信息的总长(包括配置,接口,端点,设备类,厂商定义的描述符)
.bNumInterfaces = 0x01U, //此配置的接口数量
.bConfigurationValue = 0x01U, //SetConfiguration()请求中用作参数选定此配置
.iConfiguration = 0x00U, //此配置的字串描述表索引
.bmAttributes = 0xD0U, // 自给电源 1101
.bMaxPower = 0x32U //耗电 (2*bMaxPower)mA
},
.custom_itf =
{
.header =
{
.bLength = sizeof(usb_desc_itf),
.bDescriptorType = USB_DESCTYPE_ITF //0x04 接口描述符
},
.bInterfaceNumber = 0x00U, //接口号 此接口配置索引值
.bAlternateSetting = 0x00U, //可选设置的索引值
.bNumEndpoints = 0x02U, //此接点用了几个端点 2个
.bInterfaceClass = 0x00U, //此接口类型 0x00 保留 0xff 厂商说明
.bInterfaceSubClass = 0x00U, //子类码 bInterfaceClass为0 则此必为0
.bInterfaceProtocol = 0x00U, //协议码
.iInterface = 0x00U //描述此接口的字串描述表的索引值
},
.custom_epin =
{
.header =
{
.bLength = sizeof(usb_desc_ep),
.bDescriptorType = USB_DESCTYPE_EP //0x05 端点描述符
},
.bEndpointAddress = DEV_IN_EP, //端点地址与方向 0x81 地址为1的输入设备端点(设备到主机)
.bmAttributes = USB_EP_ATTR_BULK, //USB_EP_ATTR_BULK 待验证 此端点的通道类型 0x2 批传送(块传送)
.wMaxPacketSize = 512, //DEV_IN_PACKET 传送的块大小 512个字节
.bInterval = 0x00U //块传输,此位无意义
},
.custom_epout =
{
.header =
{
.bLength = sizeof(usb_desc_ep),
.bDescriptorType = USB_DESCTYPE_EP //0x05 端点描述符
},
.bEndpointAddress = DEV_OUT_EP, //端点地址与方向 0x01 地址为1的输出设备端点(主机到设备) //地址是否可以重复使用待证实,端点单向,应该是不行,此地址需要更改
.bmAttributes = USB_EP_ATTR_BULK, //USB_EP_ATTR_BULK 块传送
.wMaxPacketSize = 512, //DEV_OUT_PACKET 传送的块大小 512个字节
.bInterval = 0x00U //块传输,此位无意义
},
};
/* USB language ID Descriptor USB语言ID描述符 */
static __ALIGN_BEGIN const usb_desc_LANGID usbd_language_id_desc __ALIGN_END =
{
.header =
{
.bLength = sizeof(usb_desc_LANGID),
.bDescriptorType = USB_DESCTYPE_STR, // 0x03 字符串描述符
},
.wLANGID = ENG_LANGID //(uint8_t *)&usbd_language_id_desc 语言标识使用那一套编码 0x0409U english 0x0804U chinese
};
/* USB manufacture string USB字符串描述符 */
static __ALIGN_BEGIN const usb_desc_str manufacturer_string __ALIGN_END =
{
.header =
{
.bLength = USB_STRING_LEN(10U),
.bDescriptorType = USB_DESCTYPE_STR,
},
.unicode_string = {'G', 'i', 'g', 'a', 'D', 'e', 'v', 'i', 'c', 'e'}
};
/* USB product string USB字符串 */
static __ALIGN_BEGIN const usb_desc_str product_string __ALIGN_END =
{
.header =
{
.bLength = USB_STRING_LEN(20U),
.bDescriptorType = USB_DESCTYPE_STR,
},
.unicode_string = {'M', 'Y', ' ', 'U', 'S', 'B', ' ', 'B', 'u', 'l', 'k', ' ', 'T', 'r', 'a', 'n' , 's' , 'f' , 'e' ,'r'}
};
/* USBD serial string USB串行字符串 */
static __ALIGN_BEGIN usb_desc_str serial_string __ALIGN_END =
{
.header =
{
.bLength = USB_STRING_LEN(12U),
.bDescriptorType = USB_DESCTYPE_STR,
}
};
/* USB string descriptor USB字符串描述符 */
static void *const usbd_msc_strings[] =
{
[STR_IDX_LANGID] = (uint8_t *)&usbd_language_id_desc,
[STR_IDX_MFC] = (uint8_t *)&manufacturer_string,
[STR_IDX_PRODUCT] = (uint8_t *)&product_string,
[STR_IDX_SERIAL] = (uint8_t *)&serial_string
};
usb_desc custom_desc = {
.dev_desc = (uint8_t *)&custom_dev_desc,
.config_desc = (uint8_t *)&custom_config_desc,
.strings = usbd_msc_strings
};
/* local function prototypes ('static') 本地函数原型 静态*/
static uint8_t custom_init (usb_dev *udev, uint8_t config_index);
static uint8_t custom_deinit (usb_dev *udev, uint8_t config_index);
static uint8_t custom_req (usb_dev *udev, usb_req *req);
static uint8_t custom_in (usb_dev *udev, uint8_t ep_num);
static uint8_t custom_out (usb_dev *udev, uint8_t ep_num);
usb_class_core usbd_custom_cb = {
.init = custom_init,
.deinit = custom_deinit,
.req_proc = custom_req,
.data_in = custom_in,
.data_out = custom_out
};
/*!
\brief initialize the custom device 初始化自定义设备
\param[in] udev: pointer to USB device instance 指向USB设备实例的指针
\param[in] config_index: configuration index 配置索引
\param[out] none 无
\retval USB device operation status 返回USB操作状态
*/
static uint8_t custom_init (usb_dev *udev, uint8_t config_index)
{
/* initialize the data TX endpoint */
usbd_ep_setup (udev, &(custom_config_desc.custom_epin));
/* initialize the data RX endpoint */
usbd_ep_setup (udev, &(custom_config_desc.custom_epout));
/* prepare to receive data */
usbd_ep_recev(udev, DEV_OUT_EP, custom_rc_buff, 512);
return USBD_OK;
}
/*!
\brief deinitialize the custom device 消除初始化自定义设备
\param[in] udev: pointer to USB device instance
\param[in] config_index: configuration index
\param[out] none
\retval USB device operation status
*/
static uint8_t custom_deinit (usb_dev *udev, uint8_t config_index)
{
/* deinitialize the data TX/RX endpoint */
usbd_ep_clear (udev, DEV_IN_EP);
usbd_ep_clear (udev, DEV_OUT_EP);
return USBD_OK;
}
/*!
\brief handle the custom class-specific requests 处理自定义类特定的请求
\param[in] udev: pointer to USB device instance
\param[in] req: device class-specific request
\param[out] none
\retval USB device operation status
*/
static uint8_t custom_req(usb_dev *udev, usb_req *req)
{
return USBD_OK;
}
/*!
\brief handle custom data 处理自定义设备数据 GD发送数据
\param[in] udev: pointer to USB device instance
\param[in] ep_num: endpoint number
\param[out] none
\retval USB device operation status
*/
static uint8_t custom_in (usb_dev *udev, uint8_t ep_num)
{
rt_sem_release(Sem_usb_se);
return USBD_OK;
}
/*!
\brief handle printer data 处理自定义设备数据 GD接收数据 以中断方式接收 这里是回调函数
\param[in] udev: pointer to USB device instance
\param[in] ep_num: endpoint number
\param[out] none
\retval USB device operation status
*/
static uint8_t custom_out (usb_dev *udev, uint8_t ep_num) /* OUT端回调函数,接收到数据之后会进入此函数 */
{
rt_sem_release(Sem_usb_rc);
return USBD_OK;
}
void usb_start_next_receive(void)
{
/* prepare to receive data */
usbd_ep_recev(&usbd_custom, DEV_OUT_EP, custom_rc_buff, 512);
}
rt_err_t usb_start_send(uint8_t *pbuf, uint32_t len)
{
rt_err_t err = RT_EOK;
usbd_ep_send (&usbd_custom, DEV_IN_EP, pbuf, len);
err = rt_sem_take(Sem_usb_se, 20);
return err;
}
最新发布