📄 send.c
字号:
* If the attempt to send the packet to the driver fails,
* return ownership of the packet to the protocol and
* try another packet (until one succeeds).
*
*
*****************************************************************************/
NTSTATUS
UsbIoCompleteWrite(
IN PDEVICE_OBJECT pUsbDevObj,
IN PIRP pIrp,
IN PVOID Context
)
{
PUSB_DEVICE device;
PVOID pThisContextPacket;
NTSTATUS status;
BOOLEAN found = FALSE;
PUSB_CONTEXT thisContext = ( PUSB_CONTEXT ) Context;
PUSB_CONTEXT pPrev, pCur, pNext;
int len;
CONTEXT_TYPE ContextType;
PIRP ContextIrp;
PURB ContextUrb;
ULONG BufLen;
//
// The context given to IoSetCompletionRoutine is an USB_CONTEXT struct
//
ASSERT( NULL != thisContext ); // we better have a non NULL buffer
device = thisContext->DeviceObject;
ASSERT( NULL != device );
ContextType = thisContext->Type;
ContextIrp = thisContext->Irp;
ContextUrb = thisContext->Urb;
BufLen = thisContext->BufLen;
pThisContextPacket = thisContext->Packet; //save ptr to packet to access after context freed
//
// Perform various IRP, URB, and buffer 'sanity checks'
//
ASSERT( ContextIrp == pIrp ); // check we're not a bogus IRP
status = pIrp->IoStatus.Status;
//we should have failed, succeeded, or cancelled, but NOT be pending
ASSERT( STATUS_PENDING != status );
//
// IoCallDriver has been called on this Irp;
// Set the length based on the TransferBufferLength
// value in the URB
//
pIrp->IoStatus.Information =
ContextUrb->UrbBulkOrInterruptTransfer.TransferBufferLength;
len = (int)pIrp->IoStatus.Information; // save for below need-termination test
if (status == STATUS_SUCCESS)
{
InterlockedIncrement( (PLONG) &device->packetsSent );
}
else
{
InterlockedIncrement( (PLONG) &device->NumDataErrors);
InterlockedIncrement( (PLONG) &device->packetsSentDropped);
}
//
// Free the IRP because we alloced it ourselves,
//
IoFreeIrp( pIrp );
//
// See if this was the last packet before we need to change
// speed.
//
/*if ( pThisContextPacket == device->LastPacketAtOldSpeed){
InterlockedExchangePointer( &device->LastPacketAtOldSpeed, NULL);
InterlockedExchange( (PLONG) &device->fSetSpeedAfterCurrentSendPacket, TRUE);
}*/
InterlockedExchange( (PLONG) &thisContext->fInUse, FALSE );
UsbDecIoCount( device ); // we will track count of pending irps
/*if ( device->fSetSpeedAfterCurrentSendPacket) {
InterlockedExchange( (PLONG) &device->fSetSpeedAfterCurrentSendPacket, FALSE);
ASSERT( NULL == device->LastPacketAtOldSpeed );
// Signal SetspeedCallback it's OK to set speed now
KeSetEvent(&device->EventSetSpeedNow, 0, FALSE );
}*/
/* if ( CONTEXT_SETSPEED == ContextType ) {
if ( STATUS_SUCCESS == status ) {
InterlockedExchange( (PLONG) &device->currentSpeed,
device->linkSpeedInfo->bitsPerSec);
}
NdisMSetInformationComplete( (NDIS_HANDLE) device->hNdisAdapter, (NDIS_STATUS) status );
device->LastSetTime.QuadPart = 0;
device->fSetpending = FALSE;
} else */
if ( CONTEXT_NDIS_PACKET == ContextType )
{
//
//
// Indicate to the protocol the status of the sent packet and return
// ownership of the packet.
//
NdisMSendComplete(
device->hNdisAdapter,
pThisContextPacket,
status );
}
if (( STATUS_SUCCESS != status ) && ( STATUS_CANCELLED != status ))
{
InterlockedExchange( (PLONG) &device->fPendingWriteClearStall, TRUE );
ScheduleWorkItem( device,
ResetPipeCallback, device->BulkOutPipeHandle, 0);
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
BOOLEAN
NdisToUsbPacket(
PUSB_DEVICE Device,
PVOID pPack,
UCHAR *usbPacketBuf,
UINT usbPacketBufLen
)
{
UINT i;
UINT ndisPacketBytes;
UINT totalBytes;
UINT ndisPacketLen;
UINT bufLen;
UCHAR *bufData;
UCHAR nextChar;
PNDIS_BUFFER ndisBuf;
PNDIS_PACKET pPacket = (PNDIS_PACKET) pPack;
DEBUGMSG(DBG_FUNC, ("+NdisToUsbPacket input packet:\n"));
//
// Initialize locals.
//
//Beginning of Frame
// Device->OutBoundHeader = 0; // this translates to 'no change ' of either link speed or BOFS
ndisPacketBytes = 0;
totalBytes = 0;
//
// Get the packet's entire length and its first NDIS buffer.
//
NdisQueryPacket(pPacket, NULL, NULL, &ndisBuf, &ndisPacketLen);
// A zero-legth packet is OK; we may just get the one-byte inbound header
// to report media busy!
if ( ndisPacketLen > 0 )
{
//
// But if the packet is not 0-len, it must have at least Addr and Control fields
// Make sure that the packet is big enough to be legal.
// It consists of an A, C, and variable-length I field.
//
if (ndisPacketLen < 20 )//IP head length
{
DEBUGMSG(DBG_ERR, ("Packet too short in NdisToUsbPacket (%d bytes)\n",
ndisPacketLen));
return FALSE;
}
}
//
// Make sure that we won't overwrite our contiguous buffer.
// Make sure that the passed-in buffer can accomodate this packet's data
//
if (ndisPacketLen > MAX_PACKET_SIZE)
{
//
// The packet is too large
// Tell the caller to retry with a packet size large
// enough to get past this stage next time.
//
DEBUGMSG(DBG_ERR, ("Packet too large in NdisToUsbPacket (%d=%xh bytes), \n"
"usbPacketBufLen=%d.",
ndisPacketLen, ndisPacketLen, usbPacketBufLen));
return FALSE;
}
if (!ndisBuf)
{
DEBUGMSG(DBG_ERR, ("No NDIS_BUFFER in NdisToUsbPacket\n"));
return FALSE;
}
NdisQueryBuffer(ndisBuf, (PVOID *)&bufData, &bufLen);
//
// Now begin building the USB frame.
//
// This is the final format:
//
// FIRST BYTE low byte ethernet packet length (1)
// SECOND BYTE
// NdisMedium packet (what we get from NDIS):
// Ethernet packet
//
usbPacketBuf[0] =(UCHAR) ((ndisPacketLen) & 0x000000FF);
// DEBUGMSG(DBG_ERR, ("usbPacketBuf[0]="d% bytes), \n",usbPacketBuf[0]);
usbPacketBuf[1] =(UCHAR) (((ndisPacketLen) & 0x0000FF00)/0x100);
//DEBUGMSG(DBG_ERR, ("usbPacketBuf[1]="d% bytes), \n",usbPacketBuf[1]);
totalBytes = USB_PACKET_LENGTH; // USB_HEADER_SIZE is just two byte
for (i=0; i<ndisPacketLen; i++)
{
ASSERT(bufData);
nextChar = *bufData++;
usbPacketBuf[totalBytes++] = nextChar;
if (--bufLen==0)
{
NdisGetNextBuffer(ndisBuf, &ndisBuf);
if (ndisBuf)
{
NdisQueryBuffer(ndisBuf, (PVOID *)&bufData, &bufLen);
}
else
{
bufData = NULL;
}
}
}
if ((bufData!=NULL) && ndisPacketLen )
{
/*
* Packet was corrupt -- it misreported its size.
*/
DEBUGMSG(DBG_ERR, ("Packet corrupt in NdisToUsbPacket (buffer lengths don't add up to packet length)."));
return FALSE;
}
DEBUGMSG(DBG_FUNC, ("-NdisToUsbPacket converted %d-byte ndis pkt to %d-byte irda pkt to send\n", ndisPacketLen, totalBytes));
DEBUGMSG(DBG_BUF, ("SENDING:"));
USB_DUMP( DBG_BUF, (usbPacketBuf, totalBytes ) );
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -