📄 usb.c
字号:
/*===============================================================================//
//== 文 件 名:USB.c
//== author :gnsusn
//== 说 明:对 USB 协议的处理
//== 修改日志:2008.8.20 创建文件
//==
//===============================================================================*/
#include <reg52.h>
#include "USB.h"
#include "PDIUSBD12.h"
#include "functions.h"
#include "hid_report.h"
//***************************************************************************************
//=======================================================================================
EPPFLAGS bEPPflags; //== 程序运行状态标志
CONTROL_DATA_BUFF Control_Data; //== setup 包
unsigned char usb_transmit_buf[8]; //== 用于给USB发送数据的缓冲区
unsigned char hid_idle; //== HID 设备的idle状态
unsigned char hid_protocol; //== HID 当前协议
//*********************************************************************************
//== 协议中用到的数据
code unsigned char LANGUAGE_ID[4] = {0x04,0x03,0x09,0x04}; //== 字符串描述符所用的语言种类
code unsigned char device_serial_number[] = //== 设备序列号
{
22,STRING_DESCRIPTOR,'2',0,'0',0,'0',0,
'8',0,'-',0,'0',0,'8',0,'-',0,'2',0,'3',0
};
code unsigned char ManufacturerString[28] = //== 厂商字符串
{
28,STRING_DESCRIPTOR,0x3F,0x80,0x11,0x68,0x7E,0x67,0x84,
0x76,'U',0x00,'S',0x00,'B',0x00,'-',0x00,'H',0x00,'I',
0x00,'D',0x00,0xBE,0x8B,0x07,0x59
};
code unsigned char ProducterString[30] = //== 产品字符串
{
30,STRING_DESCRIPTOR,0x3F,0x80,0x11,0x68,0x7E,0x67,0x84,
0x76,'U',0x00,'S',0x00,'B',0x00,'-',0x00,'-',0x00,'H',
0x00,'I',0x00,'D',0x00,0xBE,0x8B,0x07,0x59
};
code DEVICE_DESCRIPTOR_STRUCT device_descriptor = //== 设备描述符
{
sizeof(DEVICE_DESCRIPTOR_STRUCT), //== 设备描述符的字节数大小
DEVICE_DESCRIPTOR, //== 设备描述符类型编号
SWAP16(0x0110), //== USB版本号
0x03, //== USB分配的设备类代码
0x00, //== USB分配的子类代码
0x00, //== USB分配的设备协议代码
0x10, //== 端点0的最大包大小
SWAP16(0x0471), //== 厂商编号VID,这里只是作为测试用,请使用自己的VID
SWAP16(0x1234), //== 产品编号PID,这里只是作为测试用,请使用自己的PID
SWAP16(0x0001), //== 设备出厂编号
0x01, //== 设备厂商字符串的索引
0x02, //== 描述产品字符串的索引
0x03, //== 描述设备序列号字符串的索引
0x01 //== 可能的配置数量
};
//== 定义配置,接口,端点等描述符结构体,因为它们是随配置描述符一起返回的
typedef struct _CON_INT_ENDP_DESCRIPTOR_STRUCT
{
CONFIGURATION_DESCRIPTOR_STRUCT configuration_descriptor;
INTERFACE_DESCRIPTOR_STRUCT interface_descriptor;
HID_DESCRIPTOR_STRUCT hid_descriptor;
ENDPOINT_DESCRIPTOR_STRUCT endpoint_descriptor[ENDPOINT_NUMBER];
}CON_INT_ENDP_DESCRIPTOR_STRUCT;
code CON_INT_ENDP_DESCRIPTOR_STRUCT con_int_endp_descriptor =
{
//configuration_descriptor //配置描述符
{
sizeof(CONFIGURATION_DESCRIPTOR_STRUCT), //== 配置描述符的字节数大小
CONFIGURATION_DESCRIPTOR, //== 配置描述符类型编号
SWAP16(sizeof(CON_INT_ENDP_DESCRIPTOR_STRUCT)),
0x01, //== 只包含一个接口
0x01, //== 该配置的编号
0x00, //== iConfiguration字段
0x80, //== 采用总线供电
0xC8 //== 从总线获取最大电流400mA
},
//interface_descritor //== 接口描述符
{
sizeof(INTERFACE_DESCRIPTOR_STRUCT), //== 接口描述符的字节数大小
INTERFACE_DESCRIPTOR, //== 接口描述符类型编号
0x00, //== 接口编号为0
0x00, //== 该接口描述符的编号
ENDPOINT_NUMBER, //== 该接口使用的端点数量,非0端点数量为4,只使用端点主端点输入和输出
0x03, //== 人机接口设备(HID)类
0x00, //== 使用的子类:未定义
0x00, //== 使用的协议:未定义
0x00 //== 接口描述符字符串索引
},
//hid_descriptor
{
sizeof(HID_DESCRIPTOR_STRUCT), //== HID描述符的字节数大小
HID_DESCRIPTOR, //== HID描述符类型编号
0x1001, //== HID类协议版本号,为1.1
0x00, //== 固件的国家地区代号,0x21为美国
NUM_SUB_DESCRIPTORS, //== 下级描述符的数量
{
{
REPORT_DESCRIPTOR, //== 下级描述符为报告描述符
SWAP16(sizeof(DataReportDescriptor)) //== 下级描述符的长度
}
},
},
//endpoint_descriptor[]
{
{ //== 主端点输入描述
sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //== 端点描述符的字节数大小
ENDPOINT_DESCRIPTOR, //== 端点描述符类型编号
POINT_1_IN, //== 控制输入端点
ENDPOINT_TYPE_INTERRUPT, //== 使用的传输类型:中断传输
SWAP16(0x0010), //== 该端点支持的最大包尺寸,16字节
0x0A //== 中断扫描时间:设置为10ms
},
{ //== 主端点输出描述
sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //== 端点描述符的字节数大小
ENDPOINT_DESCRIPTOR, //== 端点描述符类型编号
POINT_1_OUT, //== 控制输出端点
ENDPOINT_TYPE_INTERRUPT, //== 使用的传输类型:中断传输
SWAP16(0x0010), //== 该端点支持的最大包尺寸,16字节
0x0A //== 中断扫描时间:设置为10ms
},
{ //== 主端点输出描述
sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //== 端点描述符的字节数大小
ENDPOINT_DESCRIPTOR, //== 端点描述符类型编号
MAIN_POINT_IN, //== 端点号,主输入端点
ENDPOINT_TYPE_INTERRUPT, //== 使用的传输类型:批量传输
SWAP16(0x0040), //== 该端点支持的最大包尺寸,64字节
0x0A //== 中断扫描时间:设置为10ms
},
{ //== 主端点输出描述
sizeof(ENDPOINT_DESCRIPTOR_STRUCT), //== 端点描述符的字节数大小
ENDPOINT_DESCRIPTOR, //== 端点描述符类型编号
MAIN_POINT_OUT, //== 端点号,主输出端点
ENDPOINT_TYPE_INTERRUPT, //== 使用的传输类型:中断传输
SWAP16(0x0040), //== 该端点支持的最大包尺寸,64字节
0x0A //== 中断扫描时间:设置为10ms
},
},
};
//*********************************************************************************
//===============================================================================//
//== 函 数 名:usb_bus_reset
//== 功 能:USB 总线复位处理
//== 说 明:
//== 时 间:2008.8.13 创建函数
//== 入口参数:无
//== 返 回 值:0
//===============================================================================//
unsigned char usb_bus_reset(void)
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg("Runing usb_bus_reset()!\r\n");
#endif
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg("USB总线复位................................\r\n");
#endif
bEPPflags.bits.bus_reset = 1;
return 0;
}
//===============================================================================//
//== 函 数 名:usb_bus_suspend
//== 功 能:USB 总线挂起处理
//== 说 明:
//== 时 间:2008.8.13 创建函数
//== 入口参数:无
//== 返 回 值:0
//===============================================================================//
unsigned char usb_bus_suspend(void)
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg("Runing usb_bus_suspend()!\r\n");
#endif
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg("USB总线挂起................................\r\n");
#endif
bEPPflags.bits.suspend = 1;
return 0;
}
//===============================================================================//
//== 函 数 名:set_usb_address
//== 功 能:设置D12的地址
//== 说 明:主机请求设置地址时被调用
//== 时 间:2008.8.22 创建函数
//== 入口参数:无
//== 返 回 值:0
//===============================================================================//
unsigned char set_usb_address(void)
{
set_usb_addr((unsigned char)(Control_Data.DeviceRequest.wValue & DEVICE_ADDRESS_MASK));
Control_Data.wLength = 0; //== 发送0字节长度数据到主机做回答
Control_Data.wCount = 0;
bEPPflags.bits.control_state = USB_TRANSMIT; //== 设置为发送状态,等待in端点中断
return 0;
}
//===============================================================================//
//== 函 数 名:stall_ep0
//== 功 能:停止端点0
//== 说 明:
//== 时 间:
//== 入口参数:
//== 返 回 值:0
//===============================================================================//
unsigned char stall_ep0(void)
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg("Runing stall_ep0()!\r\n");
#endif
set_endpoint_status(0, 1);
set_endpoint_status(1, 1);
return 0;
}
//===============================================================================//
//== 函 数 名:reserved
//== 功 能:备用函数
//== 说 明:
//== 时 间:
//== 入口参数:
//== 返 回 值:0
//===============================================================================//
unsigned char reserved(void)
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg("Runing reserved()!\r\n");
#endif
stall_ep0();
return 0;
}
//===============================================================================//
//== 函 数 名:control_handler
//== 功 能:得到状态
//== 说 明:
//== 时 间:2008.8.20 创建函数
//== 入口参数:receiver: 要得到状态的对象
//== 返 回 值:0
//===============================================================================//
unsigned char get_status(unsigned char receiver)
{
unsigned char status[2];
unsigned char endp, endp_state;
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg("Runing get_status()!\r\n");
#endif
switch (receiver)
{
case USB_RECIPIENT_DEVICE: //== 获取设备状态
{
if (bEPPflags.bits.remote_wakeup == 1) //== 自给供电+远程唤醒
{
status[0] = 0x03;
}
else //== 自给供电
{
status[0] = 0x01;
}
status[1] = 0x00;
} break;
case USB_RECIPIENT_INTERFACE: //== 获取接口状态
{
status[0] = 0x00;
status[1] = 0x00;
} break;
case USB_RECIPIENT_ENDPOINT: //== 获取端点状态
{
endp = (unsigned char)(Control_Data.DeviceRequest.wIndex & MAX_ENDPOINTS); //== 得到端点号
if (Control_Data.DeviceRequest.wIndex & (unsigned char)USB_ENDPOINT_DIRECTION_MASK)
endp_state = select_endpoint(endp*2 + 1); //== Control-in
else
endp_state = select_endpoint(endp*2); //== Control-out
if (endp_state & D12_STALL)
status[0] = 0x01;
else
status[0] = 0;
status[1] = 0;
} break;
default:stall_ep0(); break;
}
usb_transmit_buf[0] = status[0];
usb_transmit_buf[1] = status[1];
Control_Data.pData = usb_transmit_buf;
Control_Data.wLength = 2;
Control_Data.wCount = 0;
bEPPflags.bits.control_state = USB_TRANSMIT; //== 设置为发送状态,等待in端点中断
return 0;
}
//===============================================================================//
//== 函 数 名:get_descriptor
//== 功 能:得到描述符
//== 说 明:
//== 时 间:2008.8.20 创建函数
//== 入口参数:无
//== 返 回 值:0
//===============================================================================//
unsigned char get_descriptor(void)
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg("Runing get_descriptor()!\r\n");
#endif
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg("获取描述符................................\r\n");
#endif
switch(MSB(Control_Data.DeviceRequest.wValue))
{
case DEVICE_DESCRIPTOR:
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg(" 获取设备描述符................................\r\n");
#endif
Control_Data.wCount = sizeof(DEVICE_DESCRIPTOR_STRUCT);
Control_Data.pData = (unsigned char *)(&device_descriptor);
if (Control_Data.DeviceRequest.wLength == 0x40) //== 第一次获取描述符
{
bEPPflags.bits.first_get_descriptor = 1;
}
} break;
case CONFIGURATION_DESCRIPTOR:
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg(" 获取配置描述符................................\r\n");
#endif
Control_Data.wCount = SWAP16(con_int_endp_descriptor.configuration_descriptor.wTotalLength);
Control_Data.pData = (unsigned char *)(&con_int_endp_descriptor);
if (Control_Data.wLength<Control_Data.wCount) Control_Data.wCount = Control_Data.wLength;
} break;
case STRING_DESCRIPTOR:
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg(" 获取字符串描述符................................\r\n");
#endif
switch(LSB(Control_Data.DeviceRequest.wValue))
{
case 0x00:
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg(" 获取语言ID................................\r\n");
#endif
Control_Data.wCount = LANGUAGE_ID[0];
Control_Data.pData = LANGUAGE_ID;
} break;
case 0x01:
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg(" 获取厂商字符串................................\r\n");
#endif
Control_Data.wCount = ManufacturerString[0];
Control_Data.pData = ManufacturerString;
} break;
case 0x02:
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg(" 获取产品字符串................................\r\n");
#endif
Control_Data.wCount = ProducterString[0];
Control_Data.pData = ProducterString;
} break;
case 0x03:
{
#ifdef __DEBUG__ //== 打印调试信息
Print_Msg(" 获取设备序列号................................\r\n");
#endif
Control_Data.wCount = device_serial_number[0];
Control_Data.pData = device_serial_number;
} break;
default: break;
}
} break;
case INTERFACE_DESCRIPTOR: break;
case ENDPOINT_DESCRIPTOR: break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -