private unsafe IAsyncResult BeginReadCore(byte[] array, int offset, int count, AsyncCallback userCallback, Object stateObject)
        {
            Debug.Assert(userCallback == null);
            Debug.Assert(stateObject == null);

            CheckParametersForBegin(array, offset, count);

            AsyncFileStream_AsyncResult asyncResult = new AsyncFileStream_AsyncResult(userCallback, stateObject, false);

            if (count == 0)
            {
                asyncResult.SignalCompleted( );
            }
            else
            {
                // Keep the array in one location in memory until the OS writes the
                // relevant data into the array.  Free GCHandle later.
                asyncResult.PinBuffer(array);

                int totalRead           = 0;
                int availableToTransfer = 0;
                fixed(byte *dst = array)
                {
                    // if we already have available data, then we need to use it
                    lock ( syncRW )
                    {
                        System.Diagnostics.Debug.Assert(count == m_bytesAvailable);

                        if (m_bytesAvailable > 0)
                        {
                            // truncate
                            availableToTransfer = Math.Min(count, ( int )m_bytesAvailable);

                            // copy over to the application buffer
                            Marshal.Copy(m_buffer, 0, new IntPtr(dst + offset), availableToTransfer);

                            // update the available bytes count
                            m_bytesAvailable -= ( uint )availableToTransfer;
                            totalRead        += availableToTransfer;

                            // adjust the buffering if there is a left over
                            // this will never happen if application call AvailableBytes and the reads them
                            if (m_bytesAvailable > 0)
                            {
                                fixed(byte *copy = m_buffer)
                                {
                                    Marshal.Copy(new IntPtr(copy), m_buffer, ( int )availableToTransfer, ( int )m_bytesAvailable);
                                }
                            }
                        }
                    }

                    // if we need to read more, then we should go to the stream directly
                    int remainder = count - availableToTransfer;

                    if (remainder > 0)
                    {
                        byte[] byteArray = new byte[remainder];

                        Array.Clear(byteArray, 0, byteArray.Length);

                        fixed(byte *p = byteArray)
                        {
                            uint numBytesRead = 0;

                            var res = m_winUsbDevice.ReadPipe(Convert.ToByte(m_winUsbDevice.DeviceInfo.bulkInPipe)
                                                              , byteArray
                                                              , ( uint )remainder
                                                              , ref numBytesRead
                                                              , IntPtr.Zero
                                                              );

                            if (!res)
                            {
                                if (HandleErrorSituation("BeginRead", false))
                                {
                                    asyncResult.SignalCompleted( );
                                }
                                else
                                {
                                    m_outstandingRequests.Add(asyncResult);
                                }
                            }
                            else
                            {
                                Marshal.Copy(byteArray, 0, new IntPtr(dst + totalRead + offset), ( int )numBytesRead);
                                totalRead += ( int )numBytesRead;
                            }
                        }
                    }

                    if (totalRead > 0)
                    {
                        asyncResult.m_numBytes = totalRead;
                        asyncResult.SignalCompleted( );
                    }
                }
            }

            return(asyncResult);
        }