?? usb.c
字號:
usb_transmit.mdata = &dev_status.configure; //point at it
usb_transmit.cflag = 0x0;
usb_control_read(); //initiate transfer
}
/********************************************************************************/
/* function : usb_get_report() */
/* created : hw-chen */
/* descript : 獲取報告 */
/********************************************************************************/
void usb_get_report(void)
{ if((EP0DATA_0!=usb_i_class_interface))
{ usb_set_mode(stall_inout);
return;
}
usb_transmit.length= (dev_status.protocol == REPT_PROTOCOL ? 4 : 3);
usb_transmit.mdata = &mouse_status.button_byte;
usb_transmit.cflag = 0x0;
usb_control_read();
}
/********************************************************************************/
/* function : usb_get_protocol() */
/* created : hw-chen */
/* descript : 獲取協議 */
/********************************************************************************/
void usb_get_protocol(void)
{ if((EP0DATA_0!=usb_i_class_interface))
{ usb_set_mode(stall_inout);
return;
}
usb_transmit.length= 0x1; //* set length of protocol
usb_transmit.mdata = &dev_status.protocol; //* aim usb_transmit at it
usb_transmit.cflag = 0x0;
usb_control_read(); //* initiate transfer
}
/********************************************************************************/
/* function : usb_get_idle() */
/* created : hw-chen */
/* descript : 獲取狀態 */
/********************************************************************************/
void usb_get_idle(void)
{ if((EP0DATA_0!=usb_i_class_interface))
{ usb_set_mode(stall_inout);
return;
}
usb_transmit.length= 0x1; //idle is 1-byte long
usb_transmit.mdata = &mouse_xmit_state.idle_period; //point at it
usb_transmit.cflag = 0x0;
usb_control_read(); //initiate transfer
}
/********************************************************************************/
/* function : usb_set_configuration() */
/* created : hw-chen */
/* descript : 設置配置 */
/********************************************************************************/
void usb_set_configuration(void)
{ if((EP0DATA_0!=usb_o_type_device))
{ usb_set_mode(stall_inout);
return;
}
if((EP0DATA_2!=UNCONFIG)&&(EP0DATA_2!=CONFIGURED))
{ usb_set_mode(stall_inout);
return;
}
dev_status.configure = EP0DATA_2; //* set the configuration
dev_status.ept1_stall= 0x0; //* and clear EP1 stall
EP1CNT &= ~DATATOGGLE; //* clear EP1's data toggle
if((dev_status.configure==UNCONFIG)) //* not configured -- disable EP1 from responding
{ EP1MODE=MODE_DISABLE;
}
else //* configured -- NAK traffic on EP1
{ DATA_toggle_bit=0x0; //*
EP1MODE=MODE_NAK_IN;
}
usb_set_mode(MODE_STATUS_ONLY);
}
/********************************************************************************/
/* function : usb_set_address() */
/* created : hw-chen */
/* descript : 設置地址 */
/* the address change cannot actually take place until the ensuing */
/* status-in is received from the host */
/* so we just save the address and set a flag to indicate that a new */
/* address was just received. the code that handles ins will */
/* recognize this and set the address properly */
/********************************************************************************/
void usb_set_address(void)
{ if((EP0DATA_0!=usb_o_type_device))
{ usb_set_mode(stall_inout);
return;
}
dev_status.cur_addr=0x80|EP0DATA_2;
usb_set_mode(MODE_STATUS_ONLY);
}
/********************************************************************************/
/* function : usb_clr_feature() */
/* created : hw-chen */
/* descript : 清除標記 */
/* resume是由PC主機叫醒USB設備,而wake-up是由USB設備叫醒PC主機 */
/* 這個線程主要檢查兩個功能: */
/* 1.清除USB設備叫醒PC主機請求 */
/* 2.清除端點1的STALL請求 */
/********************************************************************************/
void usb_clr_feature(void)
{ if((EP0DATA_0==usb_o_type_device)&&(EP0DATA_2==DEV_REM_WAKEUP)&&(EP0DATA_3==0x0))
{ dev_status.rem_wakeup=DIS_REM_WAKEUP; /* disable remote wakeup */
usb_set_mode(MODE_STATUS_ONLY);
return;
}
if((EP0DATA_0==usb_o_type_endpoint)&&(dev_status.configure==CONFIGURED)&&(EP0DATA_2==EPT_STALL)&&(EP0DATA_3==0x0)&&(EP0DATA_4==0x81))
{ dev_status.ept1_stall=0x0; //* ep1 stall request not stalled
EP1CNT &= ~DATATOGGLE; //* clear data 0/1 bit
EP1MODE = MODE_NAK_IN_OUT; //* nak anything on endpoint 1 until ready
usb_set_mode(MODE_STATUS_ONLY);
return;
}
else
{ usb_set_mode(stall_inout);
return;
}
}
/********************************************************************************/
/* function : usb_set_feature() */
/* created : hw-chen */
/* descript : 設置標記 */
/********************************************************************************/
void usb_set_feature(void)
{ if((EP0DATA_0==usb_o_type_device)&&(EP0DATA_2==DEV_REM_WAKEUP)&&(EP0DATA_3==0x0))
{ dev_status.rem_wakeup=ENB_REM_WAKEUP; //* set remote wakeup
usb_set_mode(MODE_STATUS_ONLY);
return;
}
if((EP0DATA_0==usb_o_type_endpoint)&&(dev_status.configure==CONFIGURED)&&(EP0DATA_2==EPT_STALL)&&(EP0DATA_3==0x0)&&(EP0DATA_4==0x81))
{ dev_status.ept1_stall=0x1; //* mark endpoint as stalled
EP1MODE=stall_inout; //* stall traffic on endpoint 1
usb_set_mode(MODE_STATUS_ONLY);
return;
}
else
{ usb_set_mode(stall_inout);
return;
}
}
/********************************************************************************/
/* function : usb_set_idle() */
/* created : hw-chen */
/* descript : 設置空閑 */
/* this routine is entered whenever a set idle request is received. */
/* see the hid spec for the rules on setting idle periods. */
/********************************************************************************/
void usb_set_idle(void)
{ if((EP0DATA_0!=usb_o_class_interface)&&(EP0DATA_0!=usb_o_class_endpoint))
{ usb_set_mode(stall_inout);
return;
}
if((EP0DATA_4)||(EP0DATA_5))
{ usb_set_mode(stall_inout);
return;
}
if((mouse_xmit_state.idle_period==0x0))//current idle setting is off. set both the new period and the counter
{ mouse_xmit_state.idle_period = EP0DATA_3;
mouse_xmit_state.idle_counter= mouse_xmit_state.idle_period;
usb_set_mode(MODE_STATUS_ONLY);
return;
}
if((mouse_xmit_state.idle_counter<=0x2)) // counter for current idle period is nearly expiring. leave it alone, but set new idle period
{ mouse_xmit_state.idle_period = EP0DATA_3;
usb_set_mode(MODE_STATUS_ONLY);
return;
}
if(EP0DATA_3>mouse_xmit_state.idle_counter) //* new period is shorter than the old one. Force current idle period to expire soon,and set new idle period
{ mouse_xmit_state.idle_period = EP0DATA_3;
mouse_xmit_state.idle_counter = 1;
}
else //new period is longer than old one. set new idle period, and adjust current period to be equal to the new period, minus the counts that have already expired for the old one
{ mouse_xmit_state.idle_period = EP0DATA_3;
mouse_xmit_state.idle_counter = EP0DATA_3 - mouse_xmit_state.idle_period;
}
usb_set_mode(MODE_STATUS_ONLY);
return;
}
/********************************************************************************/
/* function : usb_set_protocol() */
/* created : hw-chen */
/* descript : 設置協議 */
/********************************************************************************/
void usb_set_protocol(void)
{ if(((EP0DATA_0!=usb_o_class_interface)&&(EP0DATA_0!=usb_o_class_endpoint))||(EP0DATA_4)||(EP0DATA_5)||(EP0DATA_2>REPT_PROTOCOL))
{ usb_set_mode(stall_inout);
}
else
{ dev_status.protocol = EP0DATA_2; //set the new protocol
usb_set_mode(MODE_STATUS_ONLY); //acknowledge
}
}
/********************************************************************************/
/* function : usb_stall_inout() */
/* created : hw-chen */
/* descript : 停止端點0 */
/********************************************************************************/
void usb_stall_inout(void)
{ usb_set_mode(stall_inout);
}
/********************************************************************************/
/* function : usb_pro_in_request() */
/* created : hw-chen */
/* descript : HOST通過ACK確認端點零的IN數據包 */
/* 對于端點零,只要SETUP或者OUT事務更新了,EP0CNT寄存器就不能寫,需要 */
/* 讀取它就解鎖 */
/********************************************************************************/
void usb_pro_in_request(void)
{ byte_count=EP0CNT;
byte_count=0x0;
if((usb_transmit.length)) //* if we've stuff to send, load it into fifo
{ byte_count=usb_load_ctrl_buffer();
}
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.
if((dev_status.cur_addr&0x80)) //* 如果地址在SETUP階段更新了,需要在IN包更新地址
{ USBCR=dev_status.cur_addr; //* enable the new address
dev_status.cur_addr&=0x7F; //* and clear the new address flag
}
}
/********************************************************************************/
/* function : usb_pro_stander_setup() */
/* created : hw-chen */
/* descript : 處理端點0的標準類型的SETUP包 */
/********************************************************************************/
void usb_pro_stander_setup(void)
{ switch(EP0DATA_1)
{
case GET_STATUS:
usb_get_status();
break;
case CLR_FEATURE:
usb_clr_feature();
break;
case SET_FEATURE:
usb_set_feature();
break;
case SET_ADDRESS:
usb_set_address();
break;
case GET_DESCRIPTOR:
usb_get_descriptor();
break;
case GET_CONFIGURATION:
usb_get_configuration();
break;
case SET_CONFIGURATION:
usb_set_configuration();
break;
case GET_INTERFACE:
usb_get_status();
break;
default:
usb_stall_inout();
break;
}
}
/********************************************************************************/
/* function : usb_pro_class_setup() */
/* created : hw-chen */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -