📄 bul_usbfn.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
/*++
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;
#ifndef BULVERDE_MULTI_INTEFACE_FIXED
m_bInterfaceNumber = 0;
m_bAlternateSetting =0;
#endif
m_fZeroPacket = FALSE;
m_fStalled = FALSE;
// Change address according
if ( pEndpointDesc && m_pUsbDevice!=NULL && m_dwEndpointIndex < MAX_ENDPOINT_NUMBER) {
pEndpointDesc->bEndpointAddress = (UCHAR)((pEndpointDesc->bEndpointAddress & 0x80) | m_dwEndpointIndex);
m_epDesc = *pEndpointDesc;
bReturn = ReInit();
}
Unlock();
FUNCTION_LEAVE_MSG();
return bReturn;
}
BOOL BulEndpoint::ReInit()
{
SETFNAME();
FUNCTION_ENTER_MSG();
UDCCSR udccsr;
udccsr.ulValue = 0;
udccsr.epbit.PC = udccsr.epbit.TRN= udccsr.epbit.SST = udccsr.epbit.FEF =1;
WriteControlStatusRegister(udccsr.ulValue);
DEBUGMSG(ZONE_INIT, (_T("%s (%d)udccsr.ulValue= 0x%x\r\n"),pszFname,m_dwEndpointIndex,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);
DEBUGMSG(ZONE_INIT, (_T("%s(%d) udccrax.ulValue= 0x%x\r\n"),pszFname,m_dwEndpointIndex,udccrax.ulValue));
FUNCTION_LEAVE_MSG();
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 (m_fStalled)
IST(0);
if (pfHalted)
*pfHalted = m_fStalled;
Unlock();
return ERROR_SUCCESS;
}
PSTransfer BulEndpoint::CompleteTransfer(DWORD dwError)
{
if (m_pCurTransfer) {
PSTransfer pCurTransfer = m_pCurTransfer;
m_pCurTransfer->dwUsbError= dwError;
m_pCurTransfer = NULL;
return pCurTransfer ;
}
return NULL;
}
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 && m_pCurTransfer == NULL && (pTransfer->cbBuffer==0 || pTransfer->pvBuffer!=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();
PSTransfer pNotifyTransfer = NULL;
if (pTransfer == m_pCurTransfer && m_pCurTransfer!=NULL) {
ResetEndpoint();
pNotifyTransfer = CompleteTransfer(UFN_CANCELED_ERROR);
}
else
dwReturn = ERROR_INVALID_DATA;
Unlock();
if (pNotifyTransfer)
m_pUsbDevice->MddTransferComplete(pNotifyTransfer);
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));
if (pBuffer==NULL || dwLength==0 )
return 0;
// 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();
m_fBackedudr = FALSE;
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.SA = 0 ;
udccsr.ep0bit.FST = 0; //
udccsr.ep0bit.SST = 0;
udccsr.ep0bit.IPR = 1; // Sent Zero Packet.
udccsr.ep0bit.OPC = 0;
WriteControlStatusRegister(udccsr.ulValue);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -