// 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)); }
public unsafe virtual bool FinishDataXfer(ref byte[] singleXfer, ref byte[] buffer, ref int len, ref byte[] ov) { bool rResult; uint[] bytes = new uint[1]; // DWY fix single variable during call by converting it into an 'array of 1' // and fixing it to a pointer. fixed(uint *buf0 = bytes) { fixed(byte *buf = singleXfer) { SINGLE_TRANSFER *transfer = (SINGLE_TRANSFER *)buf; rResult = PInvoke.GetOverlappedResult(_hDevice, ov, ref bytes[0], 0); if (rResult == false) { transfer->NtStatus = PInvoke.GetLastError(); } } } len = (int)bytes[0]; fixed(byte *buf = singleXfer) { SINGLE_TRANSFER *transfer = (SINGLE_TRANSFER *)buf; _usbdStatus = transfer->UsbdStatus; _ntStatus = transfer->NtStatus; if ((XferMode == XMODE.BUFFERED) && (len > 0)) { //len -= (int)transfer->BufferOffset; This is not required becuse we pass the actual data buffer length for (int i = 0; i < len; i++) { buffer[i] = buf[transfer->BufferOffset + i]; } } } _bytesWritten = (uint)len; return(rResult && (_usbdStatus == 0) && (_ntStatus == 0)); }
// 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)); } }