📄 usb.c
字号:
0x03, //* 人机接口设备(HID)类
0x01, //* 使用的子类:支持BIOS根启动Boot的子类
0x02, //* 使用的协议:鼠标
0x00, //* 接口描述符字符串索引
0x09, //* HID描述符的字节数大小
DESCRIPTOR_HID, //* HID描述符类型编号
0x10, //* HID类协议版本号,LO为10
0x01, //* HID类协议版本号,LO为1,所以为1.10
0x00, //* 固件的国家地区代号,0x21为美国
0x01, //* 下级描述符的数量,为1个
0x22, //* 下级描述符为报告描述符
0x3b, //* 下级描述符的长度的低字节
0x00, //* 下级描述符的长度的高字节
0x07, //* 端点描述符的字节数大小
DESCRIPTOR_ENDPOINT, //* 端点描述符类型编号
0x81, //* 端点号0x1,输入端点
0x03, //* 使用的传输类型:中断传输
0x05, //* 该端点支持的最大包尺寸,0x5字节
0x00,
0x0a //* 中断扫描时间:设置为10ms
};
volatile const char * g_cdata;
volatile signed char * g_mdata;
volatile unsigned char g_lenth;
/********************************************************************************/
/* function : load_rom_ctrl_buffer() */
/* created : hw-chen */
/* descript : copy data from a ROM source */
/********************************************************************************/
void load_rom_ctrl_buffer(void)
{ asm("PUSH A");
asm("PUSH X");
asm("MOV X,0");
asm("ROM_COPY:");
asm("PUSH X");
asm("MOV A,[_g_cdata]");
asm("MOV X,[_g_cdata+1]");
asm("INC [_g_cdata+1]");
asm("ADC [_g_cdata],0");
asm("ROMX ");
asm("POP X");
asm("MOV REG[X+0x50],A");
asm("INC X");
asm("MOV A,X");
asm("CMP A,[_g_lenth]");
asm("JC ROM_COPY");
asm("POP X");
asm("POP A");
}
/********************************************************************************/
/* function : load_ram_ctrl_buffer() */
/* created : hw-chen */
/* descript : copy data from a RAM source */
/********************************************************************************/
void load_ram_ctrl_buffer(void)
{ asm("PUSH A");
asm("PUSH X");
asm("MOV X,0");
asm("RAM_COPY:");
asm("MVI A,[_g_cdata+1]");
asm("MOV REG[X+0x50],A");
asm("INC X");
asm("MOV A,X");
asm("CMP A,[_g_lenth]");
asm("JC RAM_COPY");
asm("POP X");
asm("POP A");
}
/********************************************************************************/
/* function : usb_error_clear() */
/* created : hw-chen */
/* descript : 如果端点出现错误,需要清除 */
/********************************************************************************/
void usb_error_clear(void)
{ EP0CNT = 0x0;
EP0MODE= MODE_ACK_IN_STATUS_OUT;
}
/********************************************************************************/
/* function : usb_set_mode() */
/* created : hw-chen */
/* descript : 设置控制端点模式 */
/********************************************************************************/
void usb_set_mode(unsigned char mode)
{ EP0CNT = 0x0;
EP0MODE= mode;
}
/********************************************************************************/
/* function : usb_load_ctrl_buffer() */
/* created : hw-chen */
/* descript : 向端点0的控制缓冲区写入数据 */
/********************************************************************************/
char usb_load_ctrl_buffer(void)
{ if((usb_transmit.length>=0x8))
{ usb_transmit.length-=0x8;
g_lenth=0x8;
}
else
{ g_lenth=usb_transmit.length;
usb_transmit.length=0x0;
}
if((usb_transmit.cflag))
{ g_cdata=usb_transmit.cdata;
usb_transmit.cdata+=g_lenth;
load_rom_ctrl_buffer();
return g_lenth;
}
else
{ g_mdata=usb_transmit.mdata;
load_rom_ctrl_buffer();
usb_transmit.mdata+=g_lenth;
return g_lenth;
}
}
/********************************************************************************/
/* function : usb_control_read() */
/* created : hw-chen */
/* descript : 控制读取 */
/* this routine is called after a setup has been received that is */
/* requesting a data response from the mouse. upon entry, */
/* usb_transmit has been initialized to point to the data buffer */
/* that needs to be tranmsitted. usb_control_read adjusts the */
/* length of the data to be returned if the host requested less data */
/* than the actual length of the buffer. it then loads the fifo */
/* with the first chunck of data and prepares the SIE to ack with */
/* the data. */
/********************************************************************************/
void usb_control_read(void)
{ if((!EP0DATA_7)&&(EP0DATA_6<usb_transmit.length))
{ usb_transmit.length = EP0DATA_6;
}
byte_count=0x0;
if((usb_transmit.length))
{ byte_count=usb_load_ctrl_buffer(); //data to send. Load FIFO with first chunck
}
if((ctrl_toggle_bit==0x1))
{ byte_count|=DATATOGGLE; //* 设置TOGGLE
ctrl_toggle_bit=0x0;
}
else
{ ctrl_toggle_bit=0x1;
}
EP0CNT = byte_count; //* 设置长度
EP0MODE= MODE_ACK_IN_STATUS_OUT; //* and set the ep mode to ack the next IN with the data.
}
/********************************************************************************/
/* function : usb_get_status() */
/* created : hw-chen */
/* descript : 获取状态 */
/* This routine checks for either a request to get the device */
/* status, the interface status, or the endpoint status, */
/* sets up usb_transmit to point to the appropriate status, and */
/* calls usb_control_read to initiate the transfer. */
/********************************************************************************/
void usb_get_status(void)
{ switch(EP0DATA_0)
{
case (DEV_2_HST|STANDARD|DEVICE):
usb_transmit.length= 0x2; //* send 2 bytes
usb_transmit.mdata = &dev_status.rem_wakeup; //* point at remote wakeup status
usb_transmit.cflag = 0x0;
break;
case (DEV_2_HST|STANDARD|INTERFACE):
usb_transmit.length= 0x2;
usb_transmit.cdata = get_interface_status_table;
usb_transmit.cflag = 0x1;
break;
case (DEV_2_HST|STANDARD|ENDPOINT):
usb_transmit.length= 0x2; //* send two bytes
usb_transmit.mdata = &dev_status.ept1_stall; //* point at endpoint stall status
usb_transmit.cflag = 0x0;
break;
default:
usb_set_mode(stall_inout); //* bogus request, complain
return;
}
usb_control_read(); //* initiate transfer
}
/********************************************************************************/
/* function : usb_get_string() */
/* created : hw-chen */
/* descript : 处理字符串描述符 */
/********************************************************************************/
int usb_get_string(void)
{ switch(EP0DATA_2)
{
case 0x0:
usb_transmit.length= sizeof(string_language_table);
usb_transmit.cdata = string_language_table;
usb_transmit.cflag = 0x1;
break;
case 0x1:
usb_transmit.length= sizeof(string_description_one);
usb_transmit.cdata = string_description_one;
usb_transmit.cflag = 0x1;
break;
case 0x2:
usb_transmit.length= sizeof(string_description_two);
usb_transmit.cdata = string_description_two;
break;
case 0x3:
usb_transmit.length= sizeof(string_description_thr);
usb_transmit.cdata = string_description_thr;
usb_transmit.cflag = 0x1;
break;
case 0x4:
usb_transmit.length= sizeof(string_description_for);
usb_transmit.cdata = string_description_for;
usb_transmit.cflag = 0x1;
break;
case 0x5:
usb_transmit.length= sizeof(string_description_fiv);
usb_transmit.cdata = string_description_fiv;
usb_transmit.cflag = 0x1;
break;
default:
usb_set_mode(stall_inout);
return 0x0;
}
return 0x1;
}
/********************************************************************************/
/* function : usb_get_descriptor() */
/* created : hw-chen */
/* descript : 获取描述符 */
/********************************************************************************/
void usb_get_descriptor(void)
{ unsigned char rdata=EP0DATA_0;
if((rdata!=usb_i_type_device)&&(rdata!=usb_i_type_endpoint)&&(rdata!=usb_i_type_interface))
{ usb_set_mode(stall_inout);
return;
}
switch(EP0DATA_3)
{
case DESCRIPTOR_DEVICE :
usb_transmit.length= sizeof(st_descript_device);
usb_transmit.cdata = descriptor_device;
usb_transmit.cflag = 0x1;
break;
case DESCRIPTOR_CONFIGURATION :
usb_transmit.length= sizeof(st_all_confiure);
usb_transmit.cdata = &all_confiure[0x0];
usb_transmit.cflag = 0x1;
break;
case DESCRIPTOR_STRING :
if(usb_get_string()==0x0)
{ return;
}
break;
case DESCRIPTOR_HID :
usb_transmit.length= sizeof(st_descript_hid);
usb_transmit.cdata = &all_confiure[sizeof(st_descript_configure)+sizeof(st_descript_interface)];
usb_transmit.cflag = 0x1;
break;
case DESCRIPTOR_REPORT :
usb_transmit.length= sizeof(HID_report_table);
usb_transmit.cdata = HID_report_table;
usb_transmit.cflag = 0x1;
break;
default :
usb_set_mode(stall_inout);
return;
}
ctrl_toggle_bit=0x1;
usb_control_read();
}
/********************************************************************************/
/* function : usb_get_configuration() */
/* created : hw-chen */
/* descript : 获取配置 */
/********************************************************************************/
void usb_get_configuration(void)
{ if((EP0DATA_0!=usb_i_type_device))
{ usb_set_mode(stall_inout);
return;
}
usb_transmit.length= 0x1; //configuration is 1-byte long
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -