bul_usbfn.cpp
来自「pxa27x library for windows ce 5.0」· C++ 代码 · 共 1,704 行 · 第 1/4 页
CPP
1,704 行
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Module Name:
bul_usbfn.cpp
Abstract:
Bulverde USB Function Driver.
--*/
#include <windows.h>
#include <ceddk.h>
#include <ddkreg.h>
#include <nkintr.h> // needed for SYSINTR_NOP
#include "bul_usbfn.h"
#include "bulverde_base_regs.h"
#include <pm.h>
BOOL BulEndpoint::Init (PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc,
BYTE bConfigurationValue, BYTE bInterfaceNumber, BYTE bAlternateSetting)
{
SETFNAME();
FUNCTION_ENTER_MSG();
BOOL bReturn = FALSE;
Lock();
m_bConfigurationValue= bConfigurationValue;
m_bInterfaceNumber = bInterfaceNumber;
m_bAlternateSetting =bAlternateSetting;
m_fZeroPacket = FALSE;
m_fStalled = FALSE;
if ( pEndpointDesc && m_pUsbDevice!=NULL && m_dwEndpointIndex < MAX_ENDPOINT_NUMBER) {
m_epDesc = *pEndpointDesc;
bReturn = ReInit();
}
Unlock();
FUNCTION_LEAVE_MSG();
return bReturn;
}
BOOL BulEndpoint::ReInit()
{
UDCCSR udccsr;
udccsr.ulValue = 0;
udccsr.epbit.PC = udccsr.epbit.TRN= udccsr.epbit.SST = udccsr.epbit.FEF =1;
WriteControlStatusRegister(udccsr.ulValue);
UDCCRAX udccrax;
udccrax.ulValue = 0;
udccrax.bit.CN = (m_bConfigurationValue & 3);
udccrax.bit.ISN = (m_bInterfaceNumber & 0x7);
udccrax.bit.AISN = m_bAlternateSetting & 0x7;
udccrax.bit.EN = m_epDesc.bEndpointAddress & 0xf;
udccrax.bit.ET = m_epDesc.bmAttributes & 0x3;
udccrax.bit.ED = ((m_epDesc.bEndpointAddress & 0x80)!=0?1:0);
udccrax.bit.MPS = m_epDesc.wMaxPacketSize & 0x3ff ;
udccrax.bit.DE = 0;
// Only In and Isochronouse transfer can use double buffer
if (((m_epDesc.bEndpointAddress & 0x80) != 0 || (m_epDesc.bmAttributes & 0x3) == 1 ) && m_fDoubleBuffer)
udccrax.bit.DE = 1 ;
udccrax.bit.EE = 1;
WriteConfigurationRegister(udccrax.ulValue);
return TRUE;
}
DWORD BulEndpoint::StallEndpoint()
{
UDCCSR udccsr, udccsrWrite;
SETFNAME();
FUNCTION_ENTER_MSG();
Lock();
udccsr.ulValue = ReadControlStatusRegister();
udccsrWrite.ulValue = 0;
udccsrWrite.epbit.DME = udccsr.epbit.DME;
udccsrWrite.epbit.FST = 1; // Force Stall.
udccsrWrite.epbit.SST = 1; // Clear Previous Stall Sent if there is any.
WriteControlStatusRegister(udccsrWrite.ulValue);
m_fStalled = TRUE;
Unlock();
FUNCTION_LEAVE_MSG();
return ERROR_SUCCESS;
}
DWORD BulEndpoint::ClearEndpointStall()
{
Lock();
m_fStalled = FALSE;
Unlock();
return ERROR_SUCCESS;
}
DWORD BulEndpoint::ResetEndpoint()
{
UDCCSR udccsr;
SETFNAME();
FUNCTION_ENTER_MSG();
DEBUGMSG(ZONE_WARNING, (_T("ResetEndpoint+ (%d) UDCCSR =0x%x UDCCRAX = 0x%x"),m_dwEndpointIndex, ReadControlStatusRegister(),ReadConfigurationRegister()));
Lock();
udccsr.ulValue = ReadControlStatusRegister();
udccsr.epbit.PC = udccsr.epbit.TRN= udccsr.epbit.SST = udccsr.epbit.FEF =1;
WriteControlStatusRegister(udccsr.ulValue);
Unlock();
DEBUGMSG(ZONE_WARNING, (_T("ResetEndpoint- (%d) UDCCSR =0x%x UDCCRAX = 0x%x"),m_dwEndpointIndex, ReadControlStatusRegister(),ReadConfigurationRegister()));
FUNCTION_LEAVE_MSG();
return ERROR_SUCCESS;
}
DWORD BulEndpoint::IsEndpointHalted(PBOOL pfHalted )
{
Lock();
if (pfHalted)
*pfHalted = m_fStalled;
Unlock();
return ERROR_SUCCESS;
}
void BulEndpoint::CompleteTransfer(DWORD dwError)
{
if (m_pCurTransfer) {
PSTransfer pCurTransfer = m_pCurTransfer;
m_pCurTransfer->dwUsbError= dwError;
m_pCurTransfer = NULL;
m_pUsbDevice->MddTransferComplete(pCurTransfer);
}
}
DWORD BulEndpoint::IssueTransfer(PSTransfer pTransfer )
{
DWORD dwReturn = ERROR_SUCCESS;
SETFNAME();
FUNCTION_ENTER_MSG();
Lock();
DEBUGMSG(ZONE_FUNCTION, (_T("ReadConfigurationRegister (%d) UDCCSR =0x%x"),m_dwEndpointIndex,ReadConfigurationRegister()));
if (pTransfer!=NULL && pTransfer->pvBuffer!=NULL && m_pCurTransfer == NULL) { // If it is valid.
if (((pTransfer->dwFlags & USB_IN_TRANSFER)!= 0 )== ((m_epDesc.bEndpointAddress & 0x80)!=0)) {
pTransfer ->pvPddData = (PVOID)m_dwEndpointIndex;
m_pCurTransfer = pTransfer;
m_pCurTransfer->cbTransferred = 0;
m_pCurTransfer->pvPddData = (PVOID) m_dwEndpointIndex;
m_fZeroPacket = (m_pCurTransfer->cbBuffer== 0 || m_pCurTransfer->pvBuffer== 0);
m_pUsbDevice->EnableEndpointInterrupt(m_dwEndpointIndex,TRUE);
// Trigger First IST.
IST(EPINT_PACKET_COMPLETE);
}
else
dwReturn = ERROR_INVALID_DATA;
}
else
dwReturn = ERROR_NOT_READY;
Unlock();
FUNCTION_LEAVE_MSG();
ASSERT(dwReturn == ERROR_SUCCESS);
return dwReturn ;
}
DWORD BulEndpoint::AbortTransfer(PSTransfer pTransfer )
{
DWORD dwReturn = ERROR_SUCCESS;
SETFNAME();
FUNCTION_ENTER_MSG();
Lock();
if (pTransfer == m_pCurTransfer && m_pCurTransfer!=NULL) {
ResetEndpoint();
CompleteTransfer(UFN_CANCELED_ERROR);
}
else
dwReturn = ERROR_INVALID_DATA;
Unlock();
FUNCTION_LEAVE_MSG();
return dwReturn;
}
DWORD BulEndpoint::XmitData(PBYTE pBuffer, DWORD dwLength)
{
SETFNAME();
DEBUGMSG(ZONE_FUNCTION, (_T("%s pBuffer=0x%x, dwLegnth= 0x%x\r\n"),pszFname,pBuffer,dwLength));
PREFAST_ASSERT(pBuffer!=NULL);
// Spec 12.4.2
union {
BYTE bData[4];
DWORD dwData;
} ;
if (dwLength > m_epDesc.wMaxPacketSize)
dwLength = m_epDesc.wMaxPacketSize;
for (DWORD dwIndex = 0; dwIndex< dwLength; ) {
for ( DWORD dwCount = 0; dwCount < sizeof(DWORD) && dwIndex< dwLength ; dwCount ++, dwIndex++) {
bData[dwCount] = *(pBuffer++);
}
if (dwCount >= sizeof(DWORD)) {
WriteDataRegister(dwData);
}
else {
for (DWORD dwCount2=0; dwCount2 < dwCount; dwCount2 ++)
WriteDataRegisterByte(bData[dwCount2]);
}
};
DEBUGMSG(ZONE_FUNCTION, (_T("%s Complete dwLength = 0x%x\r\n"),pszFname,dwLength));
return dwLength;
}
DWORD BulEndpoint::ReceiveData(PBYTE pBuffer, DWORD dwLength)
{
SETFNAME();
DEBUGMSG(ZONE_FUNCTION, (_T("%s pBuffer=0x%x, dwLegnth= 0x%x\r\n"),pszFname,pBuffer,dwLength));
PREFAST_ASSERT(pBuffer!=NULL);
// Spec 12.4.2
union {
BYTE bData[4];
DWORD dwData;
} ;
DWORD dwAvailableDataSize = ReadByteCountRegister();
DWORD dwDataRead;
DWORD dwIndex;
DWORD dwTotalRead = 0;
while (dwAvailableDataSize) {
dwData = ReadDataRegister();
if (dwAvailableDataSize>=sizeof(DWORD)) {
dwAvailableDataSize -= sizeof(DWORD);
dwDataRead = sizeof(DWORD);
}
else {
dwDataRead = dwAvailableDataSize;
dwAvailableDataSize = 0;
}
for (dwIndex = 0 ; dwIndex < dwDataRead && dwIndex < dwLength; dwIndex ++) {
*(pBuffer++) = bData[dwIndex];
dwTotalRead ++;
}
dwLength -= dwIndex;
}
DEBUGMSG(ZONE_FUNCTION, (_T("%s Complete dwTotalRead = 0x%x\r\n"),pszFname,dwTotalRead));
return dwTotalRead;
}
void BulEndpoint::SendFakeFeature(BYTE bRequest,WORD wFeatureSelector)
{
USB_DEVICE_REQUEST udr;
PREFAST_DEBUGCHK(m_pUsbDevice!=NULL);
udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
udr.bRequest = bRequest;
udr.wValue = wFeatureSelector ;
udr.wIndex = m_epDesc.bEndpointAddress ;
udr.wLength =0;
m_pUsbDevice->DeviceNotification( UFN_MSG_SETUP_PACKET,(DWORD) &udr);
}
BOOL BulEndpointZero:: Init( PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc,
BYTE bConfigurationValue, BYTE bInterfaceNumber, BYTE bAlternateSetting)
{
Lock();
BOOL bReturn = FALSE;
SETFNAME();
FUNCTION_ENTER_MSG();
m_bConfigurationValue= bConfigurationValue;
m_bInterfaceNumber = bInterfaceNumber;
m_bAlternateSetting =bAlternateSetting;
if ( pEndpointDesc && m_pUsbDevice!=NULL && m_dwEndpointIndex < MAX_ENDPOINT_NUMBER) {
m_epDesc = *pEndpointDesc;
if ((m_epDesc.wMaxPacketSize & 0x3ff) >= EP0_MAX_PACKET_SIZE) {
m_epDesc.wMaxPacketSize = pEndpointDesc->wMaxPacketSize = EP0_MAX_PACKET_SIZE;
bReturn = ReInit();
}
}
Unlock();
FUNCTION_LEAVE_MSG();
return bReturn;
}
BOOL BulEndpointZero::ReInit()
{
m_bNeedAck = FALSE;
m_bSetupDirIn = FALSE;
UDCCSR udccsr;
udccsr.ulValue = 0;
udccsr.ep0bit.SA = udccsr.ep0bit.SST = udccsr.ep0bit.FTF =udccsr.ep0bit.OPC=1;
WriteControlStatusRegister(udccsr.ulValue);
UDCCR udccr;
udccr.ulValue = 0;
udccr.bit.EMCE = 1;
m_pUsbDevice->WriteControlRegister(udccr.ulValue);
return TRUE;
}
DWORD BulEndpointZero::ResetEndpoint()
{
UDCCSR udccsr;
SETFNAME();
FUNCTION_ENTER_MSG();
Lock();
m_bNeedAck = FALSE;
udccsr.ulValue = 0;
udccsr.ep0bit.SA = udccsr.ep0bit.SST = udccsr.ep0bit.FTF =udccsr.ep0bit.OPC=1;
WriteControlStatusRegister(udccsr.ulValue);
Unlock();
FUNCTION_LEAVE_MSG();
return ERROR_SUCCESS;
}
DWORD BulEndpointZero::IssueTransfer(PSTransfer pTransfer )
{
Lock();
SETFNAME();
FUNCTION_ENTER_MSG();
DWORD dwReturn = ERROR_SUCCESS;
if (pTransfer!=NULL && pTransfer->pvBuffer!=NULL && m_pCurTransfer == NULL) { // If it is valid.
m_pCurTransfer = pTransfer;
m_pCurTransfer->cbTransferred = 0;
m_pCurTransfer->pvPddData = (PVOID) m_dwEndpointIndex;
UDCCSR udccsr;
udccsr.ulValue = ReadControlStatusRegister();
udccsr.ep0bit.FST = 0; //
m_pCurTransfer->cbTransferred = 0;
m_fZeroPacket = (m_pCurTransfer->cbBuffer== 0 || m_pCurTransfer->pvBuffer== 0);
if (dwReturn == ERROR_SUCCESS) {
m_pUsbDevice->EnableEndpointInterrupt(m_dwEndpointIndex,TRUE);
}
else {
// We no long handle this because of return error.
m_pCurTransfer = NULL;
}
}
else
dwReturn = ERROR_INVALID_DATA;
FUNCTION_LEAVE_MSG();
Unlock();
return dwReturn;
}
DWORD BulEndpointZero::SendControlStatusHandshake()
{
Lock();
SETFNAME();
DWORD dwReturn = ERROR_SUCCESS ;
if (m_pCurTransfer == NULL && m_bNeedAck) { // No Transfer.
m_pUsbDevice->EnableEndpointInterrupt(m_dwEndpointIndex,TRUE);
if (!m_bSetupDirIn) {
UDCCSR udccsr;
udccsr.ulValue = ReadControlStatusRegister();
udccsr.ep0bit.FST = 0; //
udccsr.ep0bit.IPR = 1; // Sent Zero Packet.
WriteControlStatusRegister(udccsr.ulValue);
}
m_bNeedAck = FALSE;
if (m_bSetupDirIn && !m_fInIST )
IST(EPINT_PACKET_COMPLETE);
DEBUGMSG(ZONE_TRANSFER, (_T("%s Complete\r\n"),pszFname));
}
else
DEBUGMSG(ZONE_TRANSFER, (_T("%s Skipped\r\n"),pszFname));
Unlock();
return ERROR_SUCCESS;
}
DWORD BulEndpointZero::IST(DWORD dwIRBit)
{
Lock();
BOOL bContinue = TRUE;
m_fInIST = TRUE;
SETFNAME();
FUNCTION_ENTER_MSG();
if ((dwIRBit & EPINT_FIFO_ERROR)!=0) { // FIFO Error. End
DWORD dwUdccsr;
dwUdccsr = ReadControlStatusRegister();
DEBUGMSG(ZONE_WARNING, (_T("FIFO Error on Endpoint Zero UDCCSR=0x%x"),dwUdccsr));
};
while (bContinue && (dwIRBit & EPINT_PACKET_COMPLETE)!=0) {
bContinue = FALSE;
m_fStalled = FALSE; // Endpoint Zero is auto clear stall condition.
UDCCSR udccsr;
udccsr.ulValue = ReadControlStatusRegister();
DEBUGMSG(ZONE_TRANSFER, (_T("Endpoint Zero ReadControlStatusRegister()=0x%x"),udccsr.ulValue));
udccsr.ep0bit.FST = 0;
if (udccsr.ep0bit.OPC) {
if ( udccsr.ep0bit.SA ) { // This is setup Packet.
if (m_pCurTransfer) { // Outstanding transfer.
//DebugBreak();
WriteControlStatusRegister( udccsr.ulValue);
CompleteTransfer( UFN_CANCELED_ERROR );
}
if (m_bNeedAck) { // Previous setup haven't ack yet. Disable Interrupt and wait for the Ack.
m_pUsbDevice->EnableEndpointInterrupt(m_dwEndpointIndex,FALSE);
DEBUGMSG(ZONE_TRANSFER, (_T("Endpoint Zero Disable Interrupt")));
continue;
}
ASSERT(ReadByteCountRegister() == sizeof (USB_DEVICE_REQUEST));
union {
USB_DEVICE_REQUEST udr;
DWORD dw8Byte[2];
};
dw8Byte[0] = ReadDataRegister();
dw8Byte[1] = ReadDataRegister();
m_bNeedAck = TRUE;
m_bSetupDirIn = ((udr.bmRequestType & USB_REQUEST_DEVICE_TO_HOST)!=0?TRUE:FALSE);
bContinue = TRUE ;
m_fZeroPacket = FALSE;
WriteControlStatusRegister( udccsr.ulValue);
m_pUsbDevice->DeviceNotification(UFN_MSG_SETUP_PACKET, (DWORD) &udr);
continue;
}
else if ( ReadByteCountRegister() == 0 ) { // ACK from Host.
bContinue = TRUE;
}
else if (m_pCurTransfer ) {
if((m_pCurTransfer->dwFlags & USB_IN_TRANSFER)==0) { // Out Data.
BOOL bComplete = (ReadByteCountRegister()<m_epDesc.wMaxPacketSize);
DWORD dwSize = (m_pCurTransfer->cbTransferred< m_pCurTransfer->cbBuffer? m_pCurTransfer->cbBuffer-m_pCurTransfer->cbTransferred: 0);
if (dwSize!=0) {
dwSize= ReceiveData((PBYTE)m_pCurTransfer->pvBuffer + m_pCurTransfer->cbTransferred , dwSize);
m_pCurTransfer->cbTransferred += dwSize;
}
bComplete = (bComplete || (m_pCurTransfer->cbTransferred>= m_pCurTransfer->cbBuffer));
// Check for the completeion.
if ( bComplete ) {
WriteControlStatusRegister( udccsr.ulValue);
CompleteTransfer(UFN_NO_ERROR);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?