📄 usbfndrv.cpp
字号:
BOOL CUsbFn::DeviceNotify(DWORD dwMsg, DWORD dwParam)
{
DEBUGMSG (ZONE_WRITE|ZONE_EVENTS,(TEXT("DeviceNotify (0x%x,0x%x)\r\n"),dwMsg, dwParam));
switch(dwMsg) {
case UFN_MSG_BUS_EVENTS: {
// Ensure device is in running state
DEBUGCHK(m_hDefaultPipe);
switch(dwParam) {
case UFN_DETACH:
CableDetached();
break;
case UFN_ATTACH:
break;
case UFN_RESET: {
CableDetached();
break;
}
}
break;
}
case UFN_MSG_BUS_SPEED:
m_CurrentSpeed = (UFN_BUS_SPEED) dwParam;
break;
case UFN_MSG_SETUP_PACKET:
case UFN_MSG_PREPROCESSED_SETUP_PACKET: {
HandleRequest(dwMsg,*(PUSB_DEVICE_REQUEST)dwParam);
break;
}
case UFN_MSG_CONFIGURED: {
if (dwParam == 0) {
CableDetached();
}
else {
CableAttached();
}
break;
}
}
return TRUE;
}
void CUsbFn::HandleRequest(
DWORD dwMsg,
USB_DEVICE_REQUEST udr
)
{
CONTROL_RESPONSE response;
if (dwMsg == UFN_MSG_PREPROCESSED_SETUP_PACKET) {
response = CR_SUCCESS; // Don't respond since it was already handled.
if ( udr.bmRequestType ==
(USB_REQUEST_HOST_TO_DEVICE | USB_REQUEST_STANDARD | USB_REQUEST_FOR_ENDPOINT) ) {
switch (udr.bRequest) {
case USB_REQUEST_CLEAR_FEATURE:
// This may be needed in the future to terminate a transfer
// in progress
HandleClearFeature(udr);
break;
}
}
}
else {
DEBUGCHK(dwMsg == UFN_MSG_SETUP_PACKET);
response = CR_STALL_DEFAULT_PIPE;
if (udr.bmRequestType & USB_REQUEST_CLASS) {
response = HandleClassRequest(udr);
}
}
if (response == CR_STALL_DEFAULT_PIPE) {
m_pUfnFuncs->lpStallPipe(m_hDevice, m_hDefaultPipe);
m_pUfnFuncs->lpSendControlStatusHandshake(m_hDevice);
}
else if (response == CR_SUCCESS_SEND_CONTROL_HANDSHAKE) {
m_pUfnFuncs->lpSendControlStatusHandshake(m_hDevice);
}
}
CONTROL_RESPONSE CUsbFn::HandleClassRequest(
USB_DEVICE_REQUEST udr
)
{
CONTROL_RESPONSE response = CR_STALL_DEFAULT_PIPE;
if (udr.bmRequestType ==
(USB_REQUEST_CLASS | USB_REQUEST_FOR_INTERFACE | USB_REQUEST_HOST_TO_DEVICE) ) {
if (udr.bRequest == SET_CONTROL_LINE_STATE) {
/* Host is notifying us of control line state.
* wValue contains bitmask
* 0 - DTR
* 1 - RTS
*/
DEBUGMSG( ZONE_FUNCTION, (TEXT("SET_CONTROL_LINE_STATE %X\r\n"),
udr.wValue));
DWORD dwModemStatus = 0;
if (udr.wValue & USB_COMM_DTR)
dwModemStatus |= (MS_DSR_ON|MS_RLSD_ON); // DTR active, set DSR/RLSD
if (udr.wValue & USB_COMM_RTS)
dwModemStatus |= MS_CTS_ON; // RTS active, set CTS
ModemSignal(dwModemStatus);
response = CR_SUCCESS_SEND_CONTROL_HANDSHAKE;
}
}
else {
RETAILMSG(1, (_T("Unrecognized Serial class bRequest -> 0x%x\r\n"), udr.bmRequestType));
ASSERT(FALSE);
}
ASSERT(response == CR_SUCCESS_SEND_CONTROL_HANDSHAKE);
return response;
}
void USBSerialFn::CableDetached()
{
// This is last time to call this structure.
CloseBulkIn();
CloseBulkOut();
CloseInterruptIn();
ModemSignal(0);
}
void USBSerialFn::CableAttached()
{
m_HardwareLock.Lock();
DWORD dwBulkSize = (m_CurrentSpeed == BS_HIGH_SPEED?
m_HighSpeedEndpoints[BULK_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize:
m_FullSpeedEndpoints[BULK_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize);
BYTE uEdptAddr = (m_CurrentSpeed == BS_HIGH_SPEED?
m_HighSpeedEndpoints[BULK_IN_DESCRIPTOR_INDEX].Descriptor.bEndpointAddress:
m_FullSpeedEndpoints[BULK_IN_DESCRIPTOR_INDEX].Descriptor.bEndpointAddress);
OpenBulkIn(m_hDevice, m_pUfnFuncs,uEdptAddr,FALSE, dwBulkSize, 0x1000, 2);
dwBulkSize = (m_CurrentSpeed == BS_HIGH_SPEED?
m_HighSpeedEndpoints[BULK_OUT_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize:
m_FullSpeedEndpoints[BULK_OUT_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize);
uEdptAddr = (m_CurrentSpeed == BS_HIGH_SPEED?
m_HighSpeedEndpoints[BULK_OUT_DESCRIPTOR_INDEX].Descriptor.bEndpointAddress:
m_FullSpeedEndpoints[BULK_OUT_DESCRIPTOR_INDEX].Descriptor.bEndpointAddress);
OpenBulkOut(m_hDevice, m_pUfnFuncs,uEdptAddr,TRUE,dwBulkSize,dwBulkSize, 4); // WCEUSBSH Bug. Only can usb MaxPacketSize
if (m_fInterrupt) {
DWORD dwInterruptSize = (m_CurrentSpeed == BS_HIGH_SPEED?
m_HighSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize:
m_FullSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize);
uEdptAddr = (m_CurrentSpeed == BS_HIGH_SPEED?
m_HighSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.bEndpointAddress:
m_FullSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.bEndpointAddress);
OpenInterruptIn(m_hDevice, m_pUfnFuncs,uEdptAddr,FALSE,dwInterruptSize,dwInterruptSize, 1);
}
m_HardwareLock.Unlock();
}
USBSerSerialFn::USBSerSerialFn(LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj )
: USBSerialFn(lpActivePath,pMdd,pHwObj )
{
// Setup Discriptor default value for USBSer driver.
m_FullSpeedDeviceDesc.bDeviceClass = m_HighSpeedDeviceDesc.bDeviceClass = 0x20;
m_FullSpeedDeviceDesc.bDeviceSubClass = m_HighSpeedDeviceDesc.bDeviceSubClass = 0;
m_FullSpeedDeviceDesc.bDeviceProtocol = m_HighSpeedDeviceDesc.bDeviceProtocol = 0;
m_FullSpeedDeviceDesc.idProduct = m_HighSpeedDeviceDesc.idProduct = 0x0079 ;
m_FullSpeedDeviceDesc.idVendor = m_HighSpeedDeviceDesc.idVendor = 0x045e ;
m_FullSpeedDeviceDesc.bcdDevice = m_HighSpeedDeviceDesc.bcdDevice = 0x90;
m_FullSpeedInterface1.Descriptor.bInterfaceClass = m_HighSpeedInterface1.Descriptor.bInterfaceClass = 0x02;
m_FullSpeedInterface1.Descriptor.bInterfaceSubClass = m_HighSpeedInterface1.Descriptor.bInterfaceSubClass = 0xff;
m_FullSpeedInterface1.Descriptor.bInterfaceProtocol = m_HighSpeedInterface1.Descriptor.bInterfaceProtocol = 0xff;
const USB_COMM_LINE_CODING CommLineCoding = {
9600, USB_COMM_STOPBITS_10, USB_COMM_PARITY_NONE,8
};
m_CommLineCoding = CommLineCoding;
m_hTransferHandle = NULL;
m_wModemSetState = USB_COMM_DCD ;
const USB_COMM_SERIAL_STATUS CommSerialStatus= {
0, USB_COMM_SERIAL_STATE, 0, 0, 0, USB_COMM_DCD
};
m_CommSerialStatus = CommSerialStatus;
// USBSER requires interrupt endpoint maxpacket size bigger than 8. So we try 64 to find anything available.
m_HighSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize = 0x40;
m_FullSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize = 0x40;
}
USBSerSerialFn::~USBSerSerialFn()
{
if (m_pUfnFuncs && m_hDevice && m_hDefaultPipe && m_hTransferHandle) {
DWORD dwRet = m_pUfnFuncs->lpAbortTransfer(m_hDevice,m_hTransferHandle);
DEBUGMSG (ZONE_EVENTS,(TEXT("USBSerSerialFn::~USBSerSerialFn(Handle=0x%x)\r\n"), m_pUfnFuncs));
}
}
DWORD USBSerSerialFn::StartUSBFunction()
{
DWORD dwRet = ERROR_GEN_FAILURE;
dwRet = m_pUfnFuncs->lpRegisterDevice(m_hDevice, &m_HighSpeedDeviceDesc, &m_HighSpeedConfig1,
&m_FullSpeedDeviceDesc, &m_FullSpeedConfig1, &m_rgStringSets, 1 );
if (m_HighSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize <=8 ||
m_FullSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize <=8) {
DEBUGMSG (ZONE_ERROR,(TEXT("USBSerSerialFn::StartUSBFunction: Interrupt Endpoint point MaxPacket (%d, %d) is too small \r\n"),
m_HighSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize,
m_FullSpeedEndpoints[INTERRUPT_IN_DESCRIPTOR_INDEX].Descriptor.wMaxPacketSize));
return ERROR_GEN_FAILURE;
}
if (dwRet == ERROR_SUCCESS ) { // Do I need Initial Pipe Here?
m_fInterrupt = TRUE;
dwRet = m_pUfnFuncs->lpStart(m_hDevice, DeviceNotifyStub, (CUsbFn *)this, &m_hDefaultPipe);
}
return dwRet;
}
BOOL USBSerSerialFn::IssueTransfer(PBYTE pBuffer, DWORD dwLength, BOOL fIn)
{
DWORD dwFlags = (fIn? USB_IN_TRANSFER: USB_OUT_TRANSFER);
BOOL bReturn = FALSE;
m_HardwareLock.Lock();
if (pBuffer && m_hTransferHandle == NULL) {
DWORD dwRet = m_pUfnFuncs->lpIssueTransfer(m_hDevice,m_hDefaultPipe,CompleteNotificationStub,this,dwFlags,
dwLength,pBuffer,NULL,NULL,&m_hTransferHandle);
if (dwRet != ERROR_SUCCESS)
m_hTransferHandle = NULL;
bReturn = (dwRet == ERROR_SUCCESS);
}
m_HardwareLock.Unlock();
ASSERT(bReturn == TRUE);
return bReturn;
}
DWORD WINAPI USBSerSerialFn::CompleteNotification()
{
DWORD dwRet = ERROR_GEN_FAILURE ;
m_HardwareLock.Lock();
if (m_hTransferHandle) {
m_pUfnFuncs->lpCloseTransfer(m_hDevice,m_hTransferHandle);
m_pUfnFuncs->lpSendControlStatusHandshake(m_hDevice);
m_hTransferHandle = NULL;
dwRet = ERROR_SUCCESS;
}
m_HardwareLock.Unlock();
ASSERT(dwRet == ERROR_SUCCESS) ;
return (dwRet);
}
CONTROL_RESPONSE USBSerSerialFn::HandleClassRequest(USB_DEVICE_REQUEST udr)
{
CONTROL_RESPONSE response = CR_STALL_DEFAULT_PIPE;
if (udr.bmRequestType == (USB_REQUEST_CLASS | USB_REQUEST_FOR_INTERFACE | USB_REQUEST_DEVICE_TO_HOST) ) {
switch (udr.bRequest) {
case USB_COMM_GET_LINE_CODING:
if (IssueTransfer((PBYTE)&m_CommLineCoding,min( sizeof(m_CommLineCoding), udr.wLength), TRUE )) {
response = CR_SUCCESS ;
}
break;
}
}
else if (udr.bmRequestType == (USB_REQUEST_CLASS | USB_REQUEST_FOR_INTERFACE | USB_REQUEST_HOST_TO_DEVICE) ) {
switch (udr.bRequest) {
case USB_COMM_SET_LINE_CODING:
if (IssueTransfer((PBYTE)&m_CommLineCoding, sizeof(m_CommLineCoding), FALSE )) {
response = CR_SUCCESS ;
}
break;
case USB_COMM_SET_CONTROL_LINE_STATE: {
DEBUGMSG( ZONE_FUNCTION, (TEXT("SET_CONTROL_LINE_STATE %X\r\n"), udr.wValue));
DWORD dwModemStatus = 0;
if (udr.wValue & USB_COMM_DTR)
dwModemStatus |= (MS_DSR_ON|MS_RLSD_ON); // DTR active, set DSR/RLSD
//if (udr.wValue & USB_COMM_RTS)
// dwModemStatus |= MS_CTS_ON; // RTS active, set CTS
// Desktop Driver has problem to set RTS. We always set it on.
dwModemStatus |= MS_CTS_ON ;
ModemSignal(dwModemStatus);
response = CR_SUCCESS_SEND_CONTROL_HANDSHAKE ;
break;
}
case USB_COMM_SEND_BREAK: {
EventCallback(EV_BREAK);
// Do I need Sleep Here? Sleep(udr.wValue)
response = CR_SUCCESS_SEND_CONTROL_HANDSHAKE ;
break;
}
default:
ASSERT(FALSE);
break;
}
}
return response;
}
void USBSerSerialFn::SetModemSignal(BOOL bSet, BYTE bBitSet)
{
m_HardwareLock.Lock();
if (bSet)
m_wModemSetState |= bBitSet;
else
m_wModemSetState &= ~bBitSet;
if (m_pInterruptIn && m_CommSerialStatus.SerialState != m_wModemSetState && m_pInterruptIn->IsAnySpaceAvailable()) {
DWORD dwLength = sizeof(m_CommSerialStatus);
m_CommSerialStatus.SerialState = m_wModemSetState;
m_pInterruptIn->WriteData((PBYTE)&m_CommSerialStatus,&dwLength);
}
m_HardwareLock.Unlock();
}
CSerialPDD * CreateSerialObject(LPTSTR lpActivePath, PVOID pMdd,PHWOBJ pHwObj, DWORD dwDeviceArrayIndex )
{
CSerialPDD * pSerialPDD = NULL;
switch (dwDeviceArrayIndex) {
case 0:
pSerialPDD = new USBSerialFn(lpActivePath,pMdd, pHwObj);
break;
case 1:
pSerialPDD = new USBSerSerialFn(lpActivePath,pMdd, pHwObj);
break;
default:
ASSERT(FALSE);
}
if (pSerialPDD && !pSerialPDD->Init()) {
delete pSerialPDD;
pSerialPDD = NULL;
}
return pSerialPDD;
}
void DeleteSerialObject(CSerialPDD * pSerialPDD)
{
if (pSerialPDD)
delete pSerialPDD;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -