private unsafe bool UnsafeAbort() { int[] dwBytes = new int[1]; dwBytes[0] = 0; byte[] buffer = new byte[1]; buffer[0] = Address; fixed(byte *lpInBuffer = buffer) { fixed(int *lpBytesXfered = dwBytes) { return(PInvoke.DeviceIoControl(_hDevice, CyConst.IOCTL_ADAPT_ABORT_PIPE, (IntPtr)lpInBuffer, 1, (IntPtr)null, 0, (IntPtr)lpBytesXfered, (IntPtr)null)); } } }
public unsafe override bool BeginDataXfer(ref byte[] singleXfer, ref byte[] buffer, ref int len, ref byte[] ov) { if (_hDevice == CyConst.INVALID_HANDLE) { return(false); } int pktBlockSize = GetPktBlockSize(len); int cmdLen = singleXfer.Length; fixed(byte *buf = singleXfer) { SINGLE_TRANSFER *transfer = (SINGLE_TRANSFER *)buf; transfer->WaitForever = 0; transfer->ucEndpointAddress = Address; transfer->IsoPacketOffset = CyConst.SINGLE_XFER_LEN; transfer->IsoPacketLength = (uint)pktBlockSize; int[] Xferred = new int[1]; Xferred[0] = 0; uint IOCTL; if (XferMode == XMODE.BUFFERED) { transfer->BufferOffset = (uint)(CyConst.SINGLE_XFER_LEN + pktBlockSize); transfer->BufferLength = (uint)len; IOCTL = CyConst.IOCTL_ADAPT_SEND_NON_EP0_TRANSFER; for (int i = 0; i < len; i++) buf[CyConst.SINGLE_XFER_LEN + pktBlockSize + i] = buffer[i]; fixed(byte *lpInBuffer = singleXfer) { fixed(byte *lpOutBuffer = singleXfer) { fixed(byte *lpOv = ov) { fixed(int *lpBytesXfered = Xferred) { PInvoke.DeviceIoControl(_hDevice, IOCTL, (IntPtr)lpInBuffer, cmdLen, (IntPtr)lpOutBuffer, cmdLen, (IntPtr)lpBytesXfered, (IntPtr)lpOv); } } } } } else { transfer->BufferOffset = 0; transfer->BufferLength = 0; IOCTL = CyConst.IOCTL_ADAPT_SEND_NON_EP0_DIRECT; fixed(byte *lpInBuffer = singleXfer) { fixed(byte *lpOutBuffer = buffer) { fixed(byte *lpOv = ov) { fixed(int *lpBytesXfered = Xferred) { PInvoke.DeviceIoControl(_hDevice, IOCTL, (IntPtr)lpInBuffer, cmdLen, (IntPtr)lpOutBuffer, len, (IntPtr)lpBytesXfered, (IntPtr)lpOv); } } } } } if (Xferred[0] > 0) { len = Xferred[0]; } _usbdStatus = transfer->UsbdStatus; _ntStatus = transfer->NtStatus; } _lastError = (uint)Marshal.GetLastWin32Error(); return(true); }
// 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); }
private unsafe bool SendScsiCmd32(byte cmd, byte op, byte lun, byte dirIn, int bank, int lba, int bytes, byte[] data) { SCSI_PASS_THROUGH_WITH_BUFFERS32 sptB = new SCSI_PASS_THROUGH_WITH_BUFFERS32(); int len = Marshal.SizeOf(sptB) + bytes; // total size of buffer byte[] buffer = new byte[len]; fixed(byte *buf = buffer) { SCSI_PASS_THROUGH_WITH_BUFFERS32 *sptBuf = (SCSI_PASS_THROUGH_WITH_BUFFERS32 *)buf; SCSI_PASS_THROUGH32 *spt = (SCSI_PASS_THROUGH32 *)buf; CDB10 *cdb = (CDB10 *)&(spt->Cdb); bool bRetVal; sptBuf->totalSize = (uint)len; spt->Length = (ushort)Marshal.SizeOf(*spt); spt->Lun = lun; spt->CdbLength = 10; spt->SenseInfoLength = 18; spt->DataIn = dirIn; spt->DataTransferLength = (uint)bytes; spt->TimeOutValue = _TimeOut; spt->SenseInfoOffset = (uint)Marshal.SizeOf(*spt) + 4; spt->DataBufferOffset = (uint)Marshal.SizeOf(sptB); cdb->Cmd = cmd; cdb->OpCode = op; cdb->LBA = (uint)lba; cdb->Bank = (byte)bank; Util.ReverseBytes((byte *)&(cdb->LBA), 4); cdb->Blocks = (ushort)(bytes / _BlockSize); Util.ReverseBytes((byte *)&(cdb->Blocks), 2); if ((dirIn == 0) && (data != null)) { Marshal.Copy(data, 0, (IntPtr)(buf + Marshal.SizeOf(sptB)), bytes); } int[] BytesXfered = new int[1]; BytesXfered[0] = 0; fixed(byte *lpInBuffer = buffer) { fixed(byte *lpOutBuffer = buffer) { fixed(int *lpBytesXferred = BytesXfered) { bRetVal = PInvoke.DeviceIoControl(_hDevice, CyConst.IOCTL_SCSI_PASS_THROUGH, (IntPtr)lpInBuffer, len, (IntPtr)lpOutBuffer, len, (IntPtr)lpBytesXferred, (IntPtr)null); } } } int error = Marshal.GetLastWin32Error(); if (dirIn == 1) { Marshal.Copy((IntPtr)(buf + Marshal.SizeOf(sptB)), data, 0, bytes); } return(bRetVal); } }
// 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)); } }