?? 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 + -