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