public unsafe void LockNLoad(byte[][] cBufs, byte[][] xBufs, byte[][] oLaps, ISO_PKT_INFO[][] pktsInfo) { int j = 0; int nLocalCount = j; GCHandle[] bufSingleTransfer = new GCHandle[QueueSz]; GCHandle[] bufDataAllocation = new GCHandle[QueueSz]; GCHandle[] bufPktsInfo = new GCHandle[QueueSz]; GCHandle[] handleOverlap = new GCHandle[QueueSz]; while (j < QueueSz) { // Allocate one set of buffers for the queue, Buffered IO method require user to allocate a buffer as a part of command buffer, // the BeginDataXfer does not allocated it. BeginDataXfer will copy the data from the main buffer to the allocated while initializing the commands. cBufs[j] = new byte[CyConst.SINGLE_XFER_LEN]; xBufs[j] = new byte[BufSz]; //initialize the buffer with initial value 0xA5 for (int iIndex = 0; iIndex < BufSz; iIndex++) { xBufs[j][iIndex] = 0; } int sz = Math.Max(CyConst.OverlapSignalAllocSize, sizeof(OVERLAPPED)); oLaps[j] = new byte[sz]; pktsInfo[j] = new ISO_PKT_INFO[PPX]; /*///////////////////////////////////////////////////////////////////////////// * * fixed keyword is getting thrown own by the compiler because the temporary variables * tL0, tc0 and tb0 aren't used. And for jagged C# array there is no way, we can use this * temporary variable. * * Solution for Variable Pinning: * Its expected that application pin memory before passing the variable address to the * library and subsequently to the windows driver. * * Cypress Windows Driver is using this very same memory location for data reception or * data delivery to the device. * And, hence .Net Garbage collector isn't expected to move the memory location. And, * Pinning the memory location is essential. And, not through FIXED keyword, because of * non-usability of temporary variable. * * /////////////////////////////////////////////////////////////////////////////*/ //fixed (byte* tL0 = oLaps[j], tc0 = cBufs[j], tb0 = xBufs[j]) // Pin the buffers in memory ////////////////////////////////////////////////////////////////////////////////////////////// bufSingleTransfer[j] = GCHandle.Alloc(cBufs[j], GCHandleType.Pinned); bufDataAllocation[j] = GCHandle.Alloc(xBufs[j], GCHandleType.Pinned); bufPktsInfo[j] = GCHandle.Alloc(pktsInfo[j], GCHandleType.Pinned); handleOverlap[j] = GCHandle.Alloc(oLaps[j], GCHandleType.Pinned); // oLaps "fixed" keyword variable is in use. So, we are good. ///////////////////////////////////////////////////////////////////////////////////////////// unsafe { //fixed (byte* tL0 = oLaps[j]) { CyUSB.OVERLAPPED ovLapStatus = new CyUSB.OVERLAPPED(); ovLapStatus = (CyUSB.OVERLAPPED)Marshal.PtrToStructure(handleOverlap[j].AddrOfPinnedObject(), typeof(CyUSB.OVERLAPPED)); ovLapStatus.hEvent = (IntPtr)PInvoke.CreateEvent(0, 0, 0, 0); Marshal.StructureToPtr(ovLapStatus, handleOverlap[j].AddrOfPinnedObject(), true); // Pre-load the queue with a request int len = BufSz; if (BulkInEndPoint.BeginDataXfer(ref cBufs[j], ref xBufs[j], ref len, ref oLaps[j]) == false) { Failures++; } } j++; } } XferData(cBufs, xBufs, oLaps, pktsInfo, handleOverlap); // All loaded. Let's go! unsafe { for (nLocalCount = 0; nLocalCount < QueueSz; nLocalCount++) { CyUSB.OVERLAPPED ovLapStatus = new CyUSB.OVERLAPPED(); ovLapStatus = (CyUSB.OVERLAPPED)Marshal.PtrToStructure(handleOverlap[nLocalCount].AddrOfPinnedObject(), typeof(CyUSB.OVERLAPPED)); PInvoke.CloseHandle(ovLapStatus.hEvent); /*//////////////////////////////////////////////////////////////////////////////////////////// * * Release the pinned allocation handles. * * ////////////////////////////////////////////////////////////////////////////////////////////*/ bufSingleTransfer[nLocalCount].Free(); bufDataAllocation[nLocalCount].Free(); bufPktsInfo[nLocalCount].Free(); handleOverlap[nLocalCount].Free(); cBufs[nLocalCount] = null; xBufs[nLocalCount] = null; oLaps[nLocalCount] = null; } } GC.Collect(); }
public unsafe void XferData(byte[][] cBufs, byte[][] xBufs, byte[][] oLaps, ISO_PKT_INFO[][] pktsInfo, GCHandle[] handleOverlap) { int k = 0; int len = 0; Successes = 0; Failures = 0; XferBytes = 0; t1 = DateTime.Now; long nIteration = 0; CyUSB.OVERLAPPED ovData = new CyUSB.OVERLAPPED(); DisplayPacketInfo dp = new DisplayPacketInfo((int x, int y, double z) => UpdatePackageInfo(x, y, z)); for (; bRunning;) { nIteration++; // WaitForXfer unsafe { //fixed (byte* tmpOvlap = oLaps[k]) { ovData = (CyUSB.OVERLAPPED)Marshal.PtrToStructure(handleOverlap[k].AddrOfPinnedObject(), typeof(CyUSB.OVERLAPPED)); if (!BulkInEndPoint.WaitForXfer(ovData.hEvent, 500)) { BulkInEndPoint.Abort(); PInvoke.WaitForSingleObject(ovData.hEvent, 500); } } } // FinishDataXfer int FirstPackage; int LastPackage = 0; int PkgLength; if (BulkInEndPoint.FinishDataXfer(ref cBufs[k], ref xBufs[k], ref len, ref oLaps[k])) { XferBytes += len; //if(xBufs[k] != null) if (len != 0) { byte[] DataToFile = new byte[len]; Array.Copy(xBufs[k], DataToFile, len); //AcqDataBuffer.SetData(DataToFile); ThreadData.Add(DataToFile); FirstPackage = DataToFile[0] + (DataToFile[1] << 8) + (DataToFile[2] << 16) + (DataToFile[3] << 24); PkgLength = DataToFile.Length; LastPackage = DataToFile[PkgLength - 4] + (DataToFile[PkgLength - 3] << 8) + (DataToFile[PkgLength - 2] << 16) + (DataToFile[PkgLength - 1] << 24); } Successes++; } else { Failures++; } // Re-submit this buffer into the queue len = BufSz; if (BulkInEndPoint.BeginDataXfer(ref cBufs[k], ref xBufs[k], ref len, ref oLaps[k]) == false) { Failures++; } Thread.Sleep(10); k++; if (k == QueueSz) // Only update displayed stats once each time through the queue { k = 0; t2 = DateTime.Now; elapsed = t2 - t1; xferRate = XferBytes / elapsed.TotalMilliseconds; xferRate = xferRate / (1000.0); Dispatcher.Invoke(dp, (int)Successes, (int)Failures, (double)xferRate); // Call StatusUpdate() in the main thread //if (bRunning == true) this.Invoke(updateUI); // For small QueueSz or PPX, the loop is too tight for UI thread to ever get service. // Without this, app hangs in those scenarios. Thread.Sleep(0); } Thread.Sleep(0); } // End infinite loop // Let's recall all the queued buffer and abort the end point. BulkInEndPoint.Abort(); //AcqDataBuffer.SetDataDone(); ThreadData.CompleteAdding(); }
/*Summary * Called at the end of recursive method, LockNLoad(). * XferData() implements the infinite transfer loop */ public unsafe void XferData(byte[][] cBufs, byte[][] xBufs, byte[][] oLaps, ISO_PKT_INFO[][] pktsInfo, GCHandle[] handleOverlap) { int k = 0; int len = 0; Successes = 0; Failures = 0; XferBytes = 0; t1 = DateTime.Now; long nIteration = 0; CyUSB.OVERLAPPED ovData = new CyUSB.OVERLAPPED(); for (; bRunning;) { nIteration++; // WaitForXfer unsafe { //fixed (byte* tmpOvlap = oLaps[k]) { ovData = (CyUSB.OVERLAPPED)Marshal.PtrToStructure(handleOverlap[k].AddrOfPinnedObject(), typeof(CyUSB.OVERLAPPED)); if (!EndPoint.WaitForXfer(ovData.hEvent, 500)) { EndPoint.Abort(); PInvoke.WaitForSingleObject(ovData.hEvent, 500); } } } if (EndPoint.Attributes == 1) { CyIsocEndPoint isoc = EndPoint as CyIsocEndPoint; // FinishDataXfer if (isoc.FinishDataXfer(ref cBufs[k], ref xBufs[k], ref len, ref oLaps[k], ref pktsInfo[k])) { //XferBytes += len; //Successes++; ISO_PKT_INFO[] pkts = pktsInfo[k]; for (int j = 0; j < PPX; j++) { if (pkts[j].Status == 0) { XferBytes += pkts[j].Length; Successes++; } else { Failures++; } pkts[j].Length = 0; } } else { Failures++; } } else { // FinishDataXfer if (EndPoint.FinishDataXfer(ref cBufs[k], ref xBufs[k], ref len, ref oLaps[k])) { XferBytes += len; Successes++; } else { Failures++; } } // Re-submit this buffer into the queue len = BufSz; if (EndPoint.BeginDataXfer(ref cBufs[k], ref xBufs[k], ref len, ref oLaps[k]) == false) { Failures++; } k++; if (k == QueueSz) // Only update displayed stats once each time through the queue { k = 0; t2 = DateTime.Now; elapsed = t2 - t1; xferRate = (long)(XferBytes / elapsed.TotalMilliseconds); xferRate = xferRate / (int)100 * (int)100; // Call StatusUpdate() in the main thread if (bRunning == true) { this.Invoke(updateUI); } // For small QueueSz or PPX, the loop is too tight for UI thread to ever get service. // Without this, app hangs in those scenarios. Thread.Sleep(0); } Thread.Sleep(0); } // End infinite loop // Let's recall all the queued buffer and abort the end point. EndPoint.Abort(); }