📄 port_ctl.c
字号:
/****************************************************************************/
/* includes */
/****************************************************************************/
#include "HostStack.h"
/****************************************************************************/
/* constants */
/****************************************************************************/
#define ENUM_RETRY 3
#define ENUM_RETRY_INTERVAL 1000L
#define RESET_SECOVERY_TIME 100L // In the standard, it is 10mS. But some devices need more time to start enum.
// See section 7.1.7.3 in USB2.0 spec.
/****************************************************************************/
/* global vars */
/****************************************************************************/
device_instance *device_at_root_hub[ NUMBER_OF_ROOT_HUB_PORT ] = {
NULL,
NULL
};
hub_instance g_root_hub_instance = {
NULL, // Pointer to device instance
{ 0x09, 0x29, 0x02, 0x09, 0x00, 0x32, 0x00, 0x00, 0x00 }, // Dummy hub descriptor
2, // Number of downstream ports
{ NULL, NULL, NULL, NULL, NULL, NULL, NULL }, // Pointer to device attached on downstream ports
NULL, // Pointer to ransfer instance
0 // Hub and Port Statua Change Bitmap
};
hub_event_flag g_root_hub_event = {
0,
0x00
};
/****************************************************************************/
/* function definitions */
/****************************************************************************/
void isr_flag_handler( void );
void root_hub_event( void );
void hub_event_handler( hub_event_flag *h_ev_ptr );
unsigned long read_hub_port_status( unsigned char address, unsigned char port );
void clear_status_change_bits( unsigned char address, unsigned char port, unsigned long status_bits );
device_instance *connect_a_device( unsigned char address, unsigned char port, unsigned char topology_layer );
void disconnect_a_device( device_instance **dvi_ptr_ptr );
unsigned char port_reset( unsigned char address, unsigned char port );
device_instance *start_a_device( unsigned char speed, unsigned char topology_layer );
void message_of_enum_done( device_instance *dvi_ptr );
/*********************************************************
**
** Hub event handling.
**
**********************************************************/
//**********************************************************************
// 函数名称:hub_handler
// 输入参数:无
// 输出参数:无
// 功能描述:根集线器和集线器设备事件处理
//**********************************************************************
void hub_handler( void )
{
if(g_event_marker&ROOT_HUB_EVENT) // 根集线器事件
{
g_event_marker &= ~ROOT_HUB_EVENT; // 清事件标记位
root_hub_event(); // 处理根集线器事件
hub_event_handler( &g_root_hub_event );
}
#ifdef HUB_CLASS_DRIVE
if(g_event_marker & DEVICE_HUB_EVENT ) // 集线器设备事件
{
g_event_marker &= ~DEVICE_HUB_EVENT; // 清事件标记位
hub_event_handler(&g_hub_device_event);
}
#endif
}
unsigned short HcRhPortStatusComm[2] = {
Com32_HcRhPortStatus1,
Com32_HcRhPortStatus2
};
//**************************************************************
// 函数名称: root_hub_event
// 输入参数: 无
// 输出参数: 无
// 功能描述: 根集线器事件处理
//**************************************************************
void root_hub_event( void )
{
unsigned long rh_status;
unsigned char i;
if ( g_isr_flag & RHSC ) // 发生根集线器中断
g_isr_flag &= ~RHSC; // 清除根集线器中断侠
else return; // 非根集线器中断退出
g_root_hub_event.port_status_change_bit_map = 0x0;
for ( i = 0; i < 2; i++ )
{ rh_status = read_register32( HcRhPortStatusComm[ i ] ) ;
if ( rh_status & 0x00010000 ) // 端口连接状态改变
{ g_root_hub_event.hub_address = 1; // 根集线器地址
g_root_hub_event.port_status_change_bit_map|= (0x1 << (i + 1)); // 端口状态改变位
g_root_hub_event.topology_layer = 0; // 根集线器为拓朴的第0层
}
}
}
//**********************************************************************
// 函数名称: hub_event_handler
// 输入参数: h_ev_ptr
// 输出参数: 无
// 功描述符: 集线器事件处理
//**********************************************************************
void hub_event_handler( hub_event_flag *h_ev_ptr )
{
device_instance *dvi_ptr;
hub_instance *hi_ptr;
unsigned long h_status;
unsigned char port_num;
unsigned char topology_layer;
unsigned char i;
if ( h_ev_ptr->hub_address == 0 )
return;
if ( NULL == (dvi_ptr = find_device( h_ev_ptr->hub_address )) )
return;
// 设置目标集线器
if ( h_ev_ptr->hub_address == ROOT_HUB_ADDRESS ) //
{
hi_ptr = &g_root_hub_instance; // If the target is a root HUB
topology_layer = 0 ; // 根集线器下的设备为0层
}
else
{
hi_ptr = hub_instance_ptr( dvi_ptr ); // If the target is a device HUB
topology_layer = hi_ptr->device_ptr->topology_layer;
}
// Port processing for target HUB
// 目标集线器端口处理
for ( i = 0; i < hi_ptr->number_of_ports; i++ )
{
port_num = i + 1;
if ( !(h_ev_ptr->port_status_change_bit_map & (0x1 << port_num)) )
continue;
h_status = read_hub_port_status( h_ev_ptr->hub_address, port_num );// 读集线器端口状态
if ( h_status & 0x001F0000 )
clear_status_change_bits( h_ev_ptr->hub_address, port_num, h_status & 0x001F0000 );// 清除改变位
if ( h_status & 0x00010000) // 端口设备连接状态发生改变
{
dispose_device( &(hi_ptr->device_on_port[ i ]) ); // 设备断开连接处理
if ( h_status & 0x00000001 ) // Device connected!
hi_ptr->device_on_port[ i ] = connect_a_device( h_ev_ptr->hub_address, i + 1, topology_layer + 1 );
}
}
h_ev_ptr->hub_address = 0;
h_ev_ptr->port_status_change_bit_map = 0 ;
}
//******************************************************************************************
// 函数名称:read_hub_port_status
// 输入参数:address,集线器地址,根集线器为1
// port,集线器下行端口
// 输出参数:端口状态值
// 功能描述:读集线器下行端口状态
//******************************************************************************************
unsigned long read_hub_port_status( unsigned char address, unsigned char port )
{
if ( address == ROOT_HUB_ADDRESS )
return ( read_register32( HcRhPortStatusComm[ port - 1 ] ) );
else
{
#ifdef HUB_CLASS_DRIVE
return ( read_hub_device_port_status( find_device( address ), port ) );
#else
return NULL;
#endif
}
}
//*************************************************************
// 函数名称: clear_status_change_bits
// 输入参数: address,集线器地址,根集线器为1
// port,集线器下行端口
// status_bits,清除状态位
// 输出参数:无
// 功能描述:清除集线器端口状态改变位
//*************************************************************
void clear_status_change_bits( unsigned char address, unsigned char port, unsigned long status_bits )
{
if ( address == ROOT_HUB_ADDRESS )
write_register32( HcRhPortStatusComm[ port - 1 ], status_bits );
#ifdef HUB_CLASS_DRIVE
else
{
unsigned char i;
for ( i = 16; i <=20; i++ )
{
if ( status_bits & (0x1L << i) )
clear_status_change_bits_in_hub( find_device( address ), port, i );
}
}
#endif
}
/*********************************************************
**
** Port event handling.
**
**********************************************************/
//**************************************************************************
// 函数名称: connect_a_device
// 输入参数: address,设备地址;
// port,设备端口;
// topology_layer,拓扑层,根集线器下的设备为0(层)
// 输出参数: dvi_ptr,设备描述信息结构指针.
// 功能描述: 连接上一个USB设备处理.
//**************************************************************************
device_instance *connect_a_device( unsigned char address, unsigned char port, unsigned char topology_layer )
{
device_instance *dvi_ptr;
unsigned char speed;
unsigned char i;
dvi_ptr = NULL;
for ( i = 0; i < ENUM_RETRY; i++ ) // 如果建立设备不成功重试
{
speed = port_reset( address, port ); //复位集线器一个端口,根集线器地址为1
dvi_ptr = create_device( speed, topology_layer ); // 建立设备(枚举)
if ( dvi_ptr != NULL ) // 设备建立成功,退出循环
break;
wait_ms( ENUM_RETRY_INTERVAL ); // 延时片刻,准备从试
}
return ( dvi_ptr ); // 返回成功建立设备的描述信息结构指针,出错返回NULL
}
//**************************************************************************
// 函数名称: connect_a_device
// 输入参数: address,设备地址;
// port,设备端口;
// topology_layer,
// 输出参数: dvi_ptr,设备描述信息结构指针.
// 功能描述: 断开USB设备连接处理.
//**************************************************************************
void disconnect_a_device( device_instance **dvi_ptr_ptr )
{
if ( *dvi_ptr_ptr == NULL )
return;
dispose_device( dvi_ptr_ptr );
}
//***********************************************************************
// 函数名称:port_reset
// 输入参数:address,设备地址
// port,端口号
// 输出参数:h_status,返回集线器状态
// 功能描述:端口复位,并返口设备类型,全速或低速。
//***********************************************************************
unsigned char port_reset( unsigned char address, unsigned char port )
{
unsigned long h_status;
wait_ms( 100L ); // Need to wait before reset to handle bounce
if ( address == ROOT_HUB_ADDRESS )
{ // 根集线器
write_register32( HcRhPortStatusComm[ port - 1 ], 0x00000010 ); // Set port reset
while ( read_register32( HcRhPortStatusComm[ port - 1 ] ) & 0x00000010 ) // Polling port reset status (waiting for finishing port reset)
wait_ms( 5L );
h_status = read_register32( HcRhPortStatusComm[ port - 1 ] );
wait_ms( RESET_SECOVERY_TIME ); // Wait reset recovery time
}
#ifdef HUB_CLASS_DRIVE
else
{ // 集线器设备端口
reset_hub_device_port( find_device( address ), port );// 复位集线器端
h_status = read_hub_device_port_status( find_device( address ), port );
wait_ms( RESET_SECOVERY_TIME ); // Wait reset recovery time
}
#endif
return ( (h_status >> 9) & 0x1 );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -