📄 ncufnpdd.c
字号:
PVOID pvPddContext,
UFN_BUS_SPEED Speed,
PUFN_CONFIGURATION pConfiguration
)
{ // Not implemented for now
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
UfnPdd_IsEndpointSupportable(
PVOID pvPddContext,
DWORD dwEndpoint,
UFN_BUS_SPEED Speed,
PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc,
BYTE bConfigurationValue,
BYTE bInterfaceNumber,
BYTE bAlternateSetting
)
{
// With Virtual Endpoints, this function can't be correct in every case
// For instance if the MDD requested a configuration that listed endpoints
// in this order:
// BULK, BULK, BULK, ISO
// ISO endpoints and Virtual Endpoints don't mix. Any ISO endpoints
// must always be assigned to a physical endpoint, otherwise a lot of data
// will be lost
// In this case we need a function called UfnPdd_IsConfigurationSupportable
// that supplies the whole USB Configuration for evaluation.
PCEUFNPDD_CONTEXT pContext = (PCEUFNPDD_CONTEXT) pvPddContext;
PNC_DEVICE_OBJECT pNcDeviceObject = pContext->pNcDeviceObject;
if (dwEndpoint == 0)
{ // We only support a MaxPacketSize of 64 on EP0
if (pEndpointDesc->wMaxPacketSizeLo != 64)
{
ASSERT(FALSE);
pEndpointDesc->wMaxPacketSizeLo = 64;
}
}
else
{
BYTE EndpointType = pEndpointDesc->bmAttributes & 0x3;
PWORD pwMaxPacketSize = (PWORD)&pEndpointDesc->wMaxPacketSizeLo;
if (Speed == BS_HIGH_SPEED)
{
switch(EndpointType)
{
case BULK:
if(*pwMaxPacketSize != 0x200)
{
ASSERT(FALSE);
*pwMaxPacketSize = 0x200;
}
break;
case ISOC:
if(*pwMaxPacketSize > 0x400)
{
ASSERT(FALSE);
}
break;
case INTR:
if(*pwMaxPacketSize > 0x400)
{
ASSERT(FALSE);
}
break;
default:
ASSERT(FALSE);
break;
}
}
else
{
switch(EndpointType)
{
case BULK:
if(*pwMaxPacketSize != 0x08 && *pwMaxPacketSize != 0x10 &&
*pwMaxPacketSize != 0x20 && *pwMaxPacketSize != 0x40)
{
ASSERT(FALSE);
*pwMaxPacketSize = 0x40;
}
break;
case ISOC:
if(*pwMaxPacketSize > 0x3ff)
{
ASSERT(FALSE);
}
break;
case INTR:
if(*pwMaxPacketSize > 0x40)
{
ASSERT(FALSE);
}
break;
default:
ASSERT(FALSE);
break;
}
}
}
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
UfnPdd_InitEndpoint(
PVOID pvPddContext,
DWORD dwEndpoint,
UFN_BUS_SPEED Speed,
PUSB_ENDPOINT_DESCRIPTOR pEndpointDesc,
PVOID pvReserved,
BYTE bConfigurationValue,
BYTE bInterfaceNumber,
BYTE bAlternateSetting
)
{
PCEUFNPDD_CONTEXT pContext = (PCEUFNPDD_CONTEXT) pvPddContext;
PNC_DEVICE_OBJECT pNcDeviceObject = pContext->pNcDeviceObject;
PNC_ENDPOINT_OBJECT pNcEndpointObject;
HISTO(DEFAULT_HISTORY, "UpIe", dwEndpoint, Speed, pEndpointDesc);
if (dwEndpoint != 0)
{
ASSERT(UfnPdd_IsEndpointSupportable(
pvPddContext,
dwEndpoint,
Speed,
pEndpointDesc)
== ERROR_SUCCESS);
pNcEndpointObject = pContext->pEndpointObjects[dwEndpoint] = NcApi_EpCreate(dwEndpoint, NC_DEFAULT_ENDPOINT_MAPPING);
pNcEndpointObject->ClientContext1 = pContext;
InitializeCriticalSection(&pContext->NcUfnEp[dwEndpoint].cs);
}
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
UfnPdd_RegisterDevice(
PVOID pvPddContext,
PCUSB_DEVICE_DESCRIPTOR pHighSpeedDeviceDesc,
PCUFN_CONFIGURATION pHighSpeedConfig,
PCUSB_CONFIGURATION_DESCRIPTOR pHighSpeedConfigDesc,
PCUSB_DEVICE_DESCRIPTOR pFullSpeedDeviceDesc,
PCUFN_CONFIGURATION pFullSpeedConfig,
PCUSB_CONFIGURATION_DESCRIPTOR pFullSpeedConfigDesc,
PCUFN_STRING_SET pStringSets,
DWORD cStringSets
)
{
PCEUFNPDD_CONTEXT pContext = (PCEUFNPDD_CONTEXT) pvPddContext;
PNC_DEVICE_OBJECT pNcDeviceObject = pContext->pNcDeviceObject;
HISTO(DEFAULT_HISTORY, "UpRD", 0, 0, 0);
pNcDeviceObject->DeviceDescriptor = (PUSB_DEVICE_DESCRIPTOR)pHighSpeedDeviceDesc;
// The FirmwareApi doesn't really require the DeviceQualifier, but we derive it anyways
pNcDeviceObject->DeviceQualifierDescriptor =
(PUSB_DEVICE_QUALIFIER_DESCRIPTOR) LocalAlloc(LPTR, sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR));
pNcDeviceObject->DeviceQualifierDescriptor->bLength = sizeof(USB_DEVICE_QUALIFIER_DESCRIPTOR);
pNcDeviceObject->DeviceQualifierDescriptor->bDescriptorType = DEVICE_QUALIFIER_DESC;
pNcDeviceObject->DeviceQualifierDescriptor->bcdUSBLo = pNcDeviceObject->DeviceDescriptor->bcdUSBLo;
pNcDeviceObject->DeviceQualifierDescriptor->bcdUSBHi = pNcDeviceObject->DeviceDescriptor->bcdUSBHi;
pNcDeviceObject->DeviceQualifierDescriptor->bDeviceClass = pNcDeviceObject->DeviceDescriptor->bcdUSBHi;
pNcDeviceObject->DeviceQualifierDescriptor->bDeviceSubClass = pNcDeviceObject->DeviceDescriptor->bcdUSBHi;
pNcDeviceObject->DeviceQualifierDescriptor->bDeviceProtocol = pNcDeviceObject->DeviceDescriptor->bcdUSBHi;
pNcDeviceObject->DeviceQualifierDescriptor->bMaxPacketSize0 = pNcDeviceObject->DeviceDescriptor->bcdUSBHi;
pNcDeviceObject->DeviceQualifierDescriptor->bNumConfigurations = pNcDeviceObject->DeviceDescriptor->bcdUSBHi;
pNcDeviceObject->DeviceQualifierDescriptor->bReserved = 0;
pNcDeviceObject->HS_Configuration = (PUSB_CONFIGURATION_DESCRIPTOR)pHighSpeedConfigDesc;
pNcDeviceObject->FS_Configuration = (PUSB_CONFIGURATION_DESCRIPTOR)pFullSpeedConfigDesc;
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
UfnPdd_DeregisterDevice(
PVOID pvPddContext
)
{
// Not implemented
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
UfnPdd_Start(
PVOID pvPddContext
)
{
PCEUFNPDD_CONTEXT pContext = (PCEUFNPDD_CONTEXT) pvPddContext;
PNC_DEVICE_OBJECT pNcDeviceObject = pContext->pNcDeviceObject;
HISTO(DEFAULT_HISTORY, "UpSt", 0, 0, 0);
InitializeCriticalSection(&pContext->NcUfnEp[0].cs);
// Initialize the Chip
NcApi_OneTimeInit(pNcDeviceObject);
// NcApi_OneTimeInit initilizes the handlers to default values, so these
// must be set after the call to NcApi_OneTimeInit.
pNcDeviceObject->DeviceEventHandler = NcUfnPdd_DeviceEventHandler;
// Finish EP0 Initialization
pNcDeviceObject->EndpointZero->ClientContext1 = pContext;
pContext->pEndpointObjects[0] = pNcDeviceObject->EndpointZero;
// Enable the USB
NcApi_UsbEnable(pNcDeviceObject);
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
UfnPdd_Stop(
PVOID pvPddContext
)
{
PCEUFNPDD_CONTEXT pContext = (PCEUFNPDD_CONTEXT) pvPddContext;
PNC_DEVICE_OBJECT pNcDeviceObject = pContext->pNcDeviceObject;
HISTO(DEFAULT_HISTORY, "UpSo", 0, 0, 0);
NcApi_UsbDisable(pNcDeviceObject);
NcApi_CleanUp(pNcDeviceObject);
return ERROR_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
void
TransferCompletionHandler(
PNC_ENDPOINT_OBJECT pEndpointObject
)
{ // The FirmwareApi calls this function when a transfer has completed on any
// endpoint. Consequently, UfnMdd_TransferComplete is called to notify
// the MDD.
PCEUFNPDD_CONTEXT pContext = (PCEUFNPDD_CONTEXT)pEndpointObject->ClientContext1;
DWORD dwEndpoint = pEndpointObject->LogicalEp;
PSTransfer UfnpTransfer = pContext->pUfnPSTransfers[dwEndpoint];
EnterCriticalSection(&pContext->NcUfnEp[dwEndpoint].cs);
// Fill out PSTransfer fields: status, length, etc.
if (pEndpointObject->CompletionStatus == NCSTATUS_CLIENT_CANCEL)
{
UfnpTransfer->dwUsbError = UFN_CANCELED_ERROR;
}
else
{
UfnpTransfer->dwUsbError = UFN_NO_ERROR;
}
UfnpTransfer->cbTransferred = pEndpointObject->BytesTransferred;
HISTO(DEFAULT_HISTORY, "TrCH", dwEndpoint, UfnpTransfer->cbTransferred, 0);
pContext->pfnNotify(
pContext->pvMddContext,
UFN_MSG_TRANSFER_COMPLETE,
(DWORD)UfnpTransfer
);
LeaveCriticalSection(&pContext->NcUfnEp[dwEndpoint].cs);
}
///////////////////////////////////////////////////////////////////////////////
DWORD
WINAPI
UfnPdd_IssueTransfer(
PVOID pvPddContext,
DWORD dwEndpoint,
PSTransfer pTransfer
)
{ // The MDD calls this function to initiate a transfer on any endpoint.
NCSTATUS NcStatus;
PCEUFNPDD_CONTEXT pContext = (PCEUFNPDD_CONTEXT) pvPddContext;
PNC_ENDPOINT_OBJECT pEndpointObject = pContext->pEndpointObjects[dwEndpoint];
PNC_TRANSFER_OBJECT pNcTransfer = pEndpointObject->Transfer;
HISTO(DEFAULT_HISTORY, "TrIT", dwEndpoint, pTransfer->pvBuffer, pTransfer->cbBuffer);
EnterCriticalSection(&pContext->NcUfnEp[dwEndpoint].cs);
// Copy transfer parameters from PSTransfer (Microsoft) to NC_TRANSFER_OBJECT
pNcTransfer->TransferBuffer = pTransfer->pvBuffer;
pNcTransfer->TransferSize = pTransfer->cbBuffer;
// The MDD never expects a ZLP(zero length packet) to be validated on
// maxpacket multiple IN transfers, nor does it expect to receive a ZLP on
// maxpacket multiple OUT transfers.
pNcTransfer->TransferFlags = 0;
pNcTransfer->ClientCompletionHandler = TransferCompletionHandler;
pNcTransfer->PartialTransferHandler = NULL;
pContext->pUfnPSTransfers[dwEndpoint] = pTransfer;
EnterCriticalSection(&pContext->csInterrupt);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -