// Call this one if you want the PacketInfo data passed-back public unsafe bool XferData(ref byte[] buf, ref int len, ref ISO_PKT_INFO[] pktInfos) { byte[] ovLap = new byte[OverlapSignalAllocSize]; fixed(byte *tmp0 = ovLap) { OVERLAPPED *ovLapStatus = (OVERLAPPED *)tmp0; ovLapStatus->hEvent = PInvoke.CreateEvent(0, 0, 0, 0); // This SINGLE_TRANSFER buffer must be allocated at this level. int bufSz = CyConst.SINGLE_XFER_LEN + GetPktBlockSize(len) + ((XferMode == XMODE.DIRECT) ? 0 : len); byte[] cmdBuf = new byte[bufSz]; fixed(byte *tmp1 = cmdBuf, tmp2 = buf) { bool bResult = BeginDataXfer(ref cmdBuf, ref buf, ref len, ref ovLap); bool wResult = WaitForIO(ovLapStatus->hEvent); bool fResult = FinishDataXfer(ref cmdBuf, ref buf, ref len, ref ovLap, ref pktInfos); PInvoke.CloseHandle(ovLapStatus->hEvent); return(wResult && fResult); } } }
// These used by both BULK and INTERRUPT endpoints public unsafe virtual bool XferData(ref byte[] buf, ref int len) { byte[] ovLap = new byte[OverlapSignalAllocSize]; fixed(byte *fixedOvLap = ovLap) { OVERLAPPED *ovLapStatus = (OVERLAPPED *)fixedOvLap; ovLapStatus->hEvent = PInvoke.CreateEvent(0, 0, 0, 0); // This SINGLE_TRANSFER buffer must be allocated at this level. int bufSz = CyConst.SINGLE_XFER_LEN + ((XferMode == XMODE.DIRECT) ? 0 : len); byte[] cmdBuf = new byte[bufSz]; // These nested fixed blocks ensure that the buffers don't move in memory // While we're doing the asynchronous IO - Begin/Wait/Finish fixed(byte *tmp1 = cmdBuf, tmp2 = buf) { bool bResult = BeginDataXfer(ref cmdBuf, ref buf, ref len, ref ovLap); // // This waits for driver to call IoRequestComplete on the IRP // we just sent. // bool wResult = WaitForIO(ovLapStatus->hEvent); bool fResult = FinishDataXfer(ref cmdBuf, ref buf, ref len, ref ovLap); PInvoke.CloseHandle(ovLapStatus->hEvent); return(wResult && fResult); } } }
// Control endpoint uses the BUFFERED xfer method. So that it // doesn't collide with the base class' XferData, we declare it 'new' public new unsafe bool XferData(ref byte[] buf, ref int len) { byte[] ovLap = new byte[sizeof(OVERLAPPED)]; fixed(byte *tmp0 = ovLap) { OVERLAPPED *ovLapStatus = (OVERLAPPED *)tmp0; ovLapStatus->hEvent = PInvoke.CreateEvent(0, 0, 0, 0); bool bResult, wResult, fResult; // Create a temporary buffer that will contain a SINGLE_TRANSFER structure // followed by the actual data. byte[] tmpBuf = new byte[CyConst.SINGLE_XFER_LEN + len]; for (int i = 0; i < len; i++) { tmpBuf[CyConst.SINGLE_XFER_LEN + i] = buf[i]; } GCHandle bufSingleTransfer = GCHandle.Alloc(tmpBuf, GCHandleType.Pinned); GCHandle bufDataAllocation = GCHandle.Alloc(buf, GCHandleType.Pinned); fixed(int *lenTemp = &len) { bResult = BeginDataXfer(ref tmpBuf, ref *lenTemp, ref ovLap); wResult = WaitForIO(ovLapStatus->hEvent); fResult = FinishDataXfer(ref buf, ref tmpBuf, ref *lenTemp, ref ovLap); } PInvoke.CloseHandle(ovLapStatus->hEvent); bufSingleTransfer.Free(); bufDataAllocation.Free(); return(wResult && fResult); } }
// Control endpoint uses the BUFFERED xfer method. So that it // doesn't collide with the base class' XferData, we declare it 'new' public new unsafe bool XferData(ref byte[] buf, ref int len) { byte[] ovLap = new byte[sizeof(OVERLAPPED)]; fixed(byte *tmp0 = ovLap) { OVERLAPPED *ovLapStatus = (OVERLAPPED *)tmp0; ovLapStatus->hEvent = PInvoke.CreateEvent(0, 0, 0, 0); bool bResult, wResult, fResult; // Create a temporary buffer that will contain a SINGLE_TRANSFER structure // followed by the actual data. byte[] tmpBuf = new byte[CyConst.SINGLE_XFER_LEN + len]; for (int i = 0; i < len; i++) { tmpBuf[CyConst.SINGLE_XFER_LEN + i] = buf[i]; fixed(byte *tmp1 = tmpBuf) { bResult = BeginDataXfer(ref tmpBuf, ref len, ref ovLap); wResult = WaitForIO(ovLapStatus->hEvent); fResult = FinishDataXfer(ref buf, ref tmpBuf, ref len, ref ovLap); } PInvoke.CloseHandle(ovLapStatus->hEvent); return(wResult && fResult); } } // Control Endpoints don't support the Begin/Wait/Finish advanced technique from the // app level. So, these methods are declared private. unsafe bool BeginDataXfer(ref byte[] buffer, ref Int32 len, ref byte[] ov) { bool bRetVal = false; if (_hDevice == CyConst.INVALID_HANDLE) { return(false); } uint tmo = ((TimeOut > 0) && (TimeOut < 1000)) ? 1 : TimeOut / 1000; _bIn = (Direction == CyConst.DIR_FROM_DEVICE); int bufSz = len + CyConst.SINGLE_XFER_LEN; fixed(byte *buf = buffer) { SINGLE_TRANSFER *transfer = (SINGLE_TRANSFER *)buf; transfer->SetupPacket.bmRequest = (byte)(Target | ReqType | Direction); transfer->SetupPacket.bRequest = ReqCode; transfer->SetupPacket.wValue = Value; transfer->SetupPacket.wLength = (ushort)len; transfer->SetupPacket.wIndex = Index; transfer->SetupPacket.dwTimeOut = tmo; transfer->WaitForever = 0; transfer->ucEndpointAddress = 0x00; // control pipe transfer->IsoPacketLength = 0; transfer->BufferOffset = CyConst.SINGLE_XFER_LEN; // size of the SINGLE_TRANSFER part transfer->BufferLength = (uint)len; int[] Xferred = new int[1]; Xferred[0] = 0; fixed(byte *lpInBuffer = buffer) { fixed(byte *lpOutBuffer = buffer) { fixed(byte *lpOv = ov) { fixed(int *lpBytesXfered = Xferred) { bRetVal = PInvoke.DeviceIoControl(_hDevice, CyConst.IOCTL_ADAPT_SEND_EP0_CONTROL_TRANSFER, (IntPtr)lpInBuffer, bufSz, (IntPtr)lpOutBuffer, bufSz, (IntPtr)lpBytesXfered, (IntPtr)lpOv); } } } } len = Xferred[0]; _usbdStatus = transfer->UsbdStatus; _ntStatus = transfer->NtStatus; } _lastError = (uint)Marshal.GetLastWin32Error(); return(bRetVal); } // This is a BUFFERED xfer method - specific version of FinishDataXfer. So that it // doesn't collide with the base class' FinishDataXfer, we declare it 'new' new unsafe bool FinishDataXfer(ref byte[] userBuf, ref byte[] xferBuf, ref int len, ref byte[] ov) { uint bytes = 0; bool rResult = PInvoke.GetOverlappedResult(_hDevice, ov, ref bytes, 0); uint dataOffset; fixed(byte *buf = xferBuf) { SINGLE_TRANSFER *transfer = (SINGLE_TRANSFER *)buf; len = (bytes > CyConst.SINGLE_XFER_LEN) ? (int)bytes - (int)transfer->BufferOffset : 0; _bytesWritten = (uint)len; dataOffset = transfer->BufferOffset; _usbdStatus = transfer->UsbdStatus; _ntStatus = transfer->NtStatus; } // Extract the acquired data and move from xferBuf to userBuf if (bIn) { for (int i = 0; i < len; i++) userBuf[i] = xferBuf[dataOffset + i]; } } return(rResult && (_usbdStatus == 0) && (_ntStatus == 0)); } }