?? usbtransfer.c
字號:
/*****************************Copyright(c)****************************************************************
** Guangzhou ZHIYUAN electronics Co.,LTD.
**
** http://www.embedtools.com
**
**------File Info-----------------------------------------------------------------------------------------
** File Name: USBTransfer.c
** Latest modified Date: 2007-11-14
** Latest Version: V1.0
** Description: USB主機軟件包的傳輸函數
**
**--------------------------------------------------------------------------------------------------------
** Created By: 吳隆穗 Longsui Wu
** Created date: 2007-11-14
** Version: V1.0
** Descriptions: 初始版本
**
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
**--------------------------------------------------------------------------------------------------------
** Modified by:
** Modified date:
** Version:
** Description:
**
*********************************************************************************************************/
#include "USBHostConfig.h"
USB_INT8U __usbCtrlTranPhase_Setup (PUSB_DEV_REQ pusbDevReq);
USB_INT8U __usbCtrlTranPhase_In (USB_INT16U usLength, USB_INT8U *pucBuf);
USB_INT8U __usbCtrlTranPhase_Out (void);
#ifdef __cplusplus
extern "C" {
#endif
/*********************************************************************************************************
** Function name: usbStandardReqTransfer
** Descriptions: 發送標準請求, 并取得返回值
** input parameters: pusbDevReq 標準請求
** output parameters: pucBuf 設備返回的數據
** puiSts 狀態,如錯誤號等
** Returned value: 錯誤碼
*********************************************************************************************************/
USB_INT8U usbStandardReqTransfer (PUSB_DEV_REQ pusbDevReq, USB_INT8U *pucBuf)
{
USB_INT8U ucErr, ucRet;
if (GusbHostFlags.ucAttached == 0) { /* 設備未插入 */
return USB_ERR_DEVICE_NOT_ATTACHED;
}
OS_ENTER_CRITICAL();
if (GusbHostFlags.bExitStdOperaReq) { /* 應用程序要求退出操作 */
OS_EXIT_CRITICAL();
return USB_ERR_EXIT_REQ;
}
__GusbHostEvtCnt.ucStdTranCnt++; /* 控制傳輸計數器自加1 */
OS_EXIT_CRITICAL();
OSSemPend(__GevtUsbCtrlSem, 0, &ucErr);
do { /* 避免 goto 而使用 do...while */
/*
* 第一步: SETUP 階段
*/
ucRet = __usbCtrlTranPhase_Setup(pusbDevReq);
if (ucRet != USB_ERR_SUCESS) {
break;
}
/*
* 第二步: IN 階段
*/
ucRet = __usbCtrlTranPhase_In (pusbDevReq->wLength, pucBuf);
if (ucRet != USB_ERR_SUCESS) {
break;
}
/*
* 第三步: OUT 階段, 只有 IN 階段有數據傳輸時才需要此 OUT 階段
*/
if (pusbDevReq->wLength) {
__usbCtrlTranPhase_Out();
}
} while (0);
OSSemPost(__GevtUsbCtrlSem);
OS_ENTER_CRITICAL();
__GusbHostEvtCnt.ucStdTranCnt--; /* 控制傳輸計數器自減1 */
OS_EXIT_CRITICAL();
return ucRet;
}
/*********************************************************************************************************
** Function name: usbDataTransfer
** Descriptions: 發送或接收 Bulk, Intrrupt 傳輸的數據
** input parameters: pucData 要發送或接收的數據緩沖區
** uiLength 要發送或接收數據的長度
** uiTranType 傳輸類型: __HC_ED_TYPE_BULK 或 __HC_ED_TYPE_INTR
** ucMaxTryCount 當出現錯誤時,最大的重試次數
** Returned value: 錯誤碼
*********************************************************************************************************/
USB_INT8U usbDataTransfer (USB_INT8U *pucData, /* 數據緩沖區 */
USB_INT32U uiLength, /* 要傳輸的數據長度 */
USB_INT8U ucTranType, /* 傳輸類型 */
USB_INT8U ucMaxTryCount) /* 發生錯誤時最大嘗試次數 */
{
USB_INT8U ucErr;
USB_INT8U ucTryCount;
USB_INT32U uiCode;
USB_INT16U usMaxLenPerPkt;
USB_INT16U usCurTran;
USB_INT32U uiTotalTran;
USB_INT32U uiBufLen;
USB_INT8U *pucBufTmp;
USB_INT8U *pucFristBuf;
__HC_GEN_TD_PARAM tdParam;
__PHC_GEN_TRANSFER_DESCRIPTOR ptdAddTd;
__ED_INFO edInfo;
if (!usbIsDeviceReady()) {
return USB_ERR_DEVICE_NOT_READY;
}
OS_ENTER_CRITICAL();
if (GusbHostFlags.bExitDataOperaReq) { /* 應用程序要求退出操作 */
OS_EXIT_CRITICAL();
return USB_ERR_EXIT_REQ;
}
__GusbHostEvtCnt.ucDataTranCnt++;
OS_EXIT_CRITICAL();
usbPipeOpen(ucTranType);
__hcdGetEdInfo(ucTranType, &edInfo);
usMaxLenPerPkt = edInfo.usMaxPktSize;
OSSemPend(__GevtUsbDataTranSem, 0, &ucErr);
ucTryCount = 0;
do {
pucBufTmp = pucData;
/*
* 設置 TD 的參數
*/
tdParam.ucBufferRound = 1;
tdParam.ucDelayIntr = 0;
tdParam.ucDataToggle = 0;
if (ucTranType & 0x80) {
tdParam.ucDirect_PID = __OHCI_TD_TYPE_IN;
} else {
tdParam.ucDirect_PID = __OHCI_TD_TYPE_OUT;
}
/*
* 為傳輸添加傳輸描述符 TD 并啟動傳輸
* 當數據量比較大時可能會出現TD 不夠,或緩沖區不夠,此時傳輸要分割為多次,
* 分割點為無法申請到空閑 TD 或申請不到緩沖區時
*/
uiTotalTran = 0; /* 清零總傳輸量計數器 */
do{
uiBufLen = 0;
do {
ptdAddTd = __hcdAllocTd(&edInfo); /* 申請 TD */
if (ptdAddTd == NULL) {
break;
}
if (uiLength - uiTotalTran <= usMaxLenPerPkt) {
usCurTran = (USB_INT16U)(uiLength - uiTotalTran);
} else {
usCurTran = usMaxLenPerPkt;
}
tdParam.pucCBP = __usbAllocGenBuffer(usCurTran);
if (tdParam.pucCBP == NULL) { /* 如果現在無緩沖區可用,則, */
/* ...跳出本循環 */
__hcdFreeTd(&edInfo, ptdAddTd);
break;
}
if (!(ucTranType & 0x80)) { /* OUT 傳輸 */
usbMemCopy(tdParam.pucCBP, pucBufTmp, usCurTran);
pucBufTmp = pucBufTmp + usCurTran;
} else { /* IN 傳輸 */
if (uiBufLen == 0) {
pucFristBuf = tdParam.pucCBP; /* 保存第一次的緩沖區位置, */
} /* ...usbMemCopy時要用 */
}
tdParam.usBufLen = usCurTran;
__hcdAddTd(&tdParam, ptdAddTd, &edInfo); /* 將申請到的TD加入到ED中 */
uiTotalTran = (USB_INT32U)(uiTotalTran + usCurTran);
uiBufLen = (USB_INT32U)(uiBufLen + usCurTran);
} while (uiTotalTran < uiLength);
__usbEdClearSkip(ucTranType); /* 清除 sKip 位 */
__hcStartSchedule(ucTranType);
uiCode = (USB_INT32U)OSMboxPend(__GevtUsbDataTranMbox, USB_TIMEOUT_TICK, &ucErr);
/* 等待調度任務處理完畢 */
if (ucErr != OS_NO_ERR) { /* 等待超時 */
uiCode = (USB_INT32U)(USB_ERR_TIMEOUT << 24); /* 超時錯誤碼 */
ucTryCount = (USB_INT8U)(ucMaxTryCount + 1); /* 使當前重試次數大于最大重試 */
/* 次數,使程序退出do while循環 */
__hcDisEnSchedAndWaitNextFrame(ucTranType);
__hcdEdLetHeadEquTail(&edInfo); /* 強制 使HeadP = TailP */
__hcdFreeAllTd(&edInfo); /* 釋放所有 TD 資源 */
__hcEnableSchedule(ucTranType);
break;
}
if (uiCode == __USB_TRANDEAL_OK) {
if ((ucTranType & 0x80)) { /* IN 傳輸 */
usbMemCopy(pucBufTmp, pucFristBuf, uiBufLen); /* 將USB RAM里的數據拷貝至 */
/* ...用戶緩沖區 */
pucBufTmp = pucBufTmp + uiBufLen;
}
__usbFreeGenBuffer(uiBufLen); /* 釋放所占USB RAM緩沖區 */
} else if (__USBLSB(uiCode, 0) == __USB_TRANDEAL_ERR_TRY) { /* 需要重試 */
if (__USBLSB(uiCode, 3) == USB_ERR_STALL) { /* 端點被禁止, 需要解禁 */
usbClearFeature_EP(usbGetEp(0, ucTranType));
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -