Esempio n. 1
0
        internal void CommonWrite(byte[] buffer, int offset, int count,
                                  Queue <CommonOutputReport> queue,
                                  bool feature, int maxOutputReportLength)
        {
            Throw.If.OutOfRange(buffer, offset, count);
            count = Math.Min(count, maxOutputReportLength);
            if (count == 0)
            {
                return;
            }

            int writeTimeout = WriteTimeout;
            int startTime    = Environment.TickCount;
            int timeout;

            HandleAcquireIfOpenOrFail();
            try {
                lock (queue) {
                    while (true)
                    {
                        if (queue.Count == 0)
                        {
                            byte[] packet = new byte[count];
                            Array.Copy(buffer, offset, packet, 0, count);
                            var outputReport = new CommonOutputReport {
                                Bytes = packet, Feature = feature
                            };
                            queue.Enqueue(outputReport);
                            Monitor.PulseAll(queue);

                            while (true)
                            {
                                if (outputReport.Done)
                                {
                                    if (!outputReport.DoneOK)
                                    {
                                        throw new IOException();
                                    }
                                    return;
                                }

                                timeout = GetTimeout(startTime, writeTimeout);
                                if (!Monitor.Wait(queue, timeout))
                                {
                                    throw new TimeoutException();
                                }
                            }
                        }

                        timeout = GetTimeout(startTime, writeTimeout);
                        if (!Monitor.Wait(queue, timeout))
                        {
                            throw new TimeoutException();
                        }
                    }
                }
            } finally {
                HandleRelease();
            }
        }
        unsafe void WriteThread()
        {
            if (!HandleAcquire())
            {
                return;
            }

            try {
                lock (_outputQueue) {
                    while (true)
                    {
                        while (!_shutdown && _outputQueue.Count == 0)
                        {
                            Monitor.Wait(_outputQueue);
                        }
                        if (_shutdown)
                        {
                            break;
                        }

                        NativeMethods.IOReturn ret;
                        CommonOutputReport     outputReport = _outputQueue.Peek();
                        try
                        {
                            fixed(byte *outputReportBytes = outputReport.Bytes)
                            {
                                Monitor.Exit(_outputQueue);

                                try {
                                    ret = NativeMethods.IOHIDDeviceSetReport(_handle,
                                                                             outputReport.Feature ? NativeMethods.IOHIDReportType.Feature : NativeMethods.IOHIDReportType.Output,
                                                                             (IntPtr)outputReport.Bytes[0],
                                                                             (IntPtr)outputReportBytes,
                                                                             (IntPtr)outputReport.Bytes.Length);
                                    if (ret == NativeMethods.IOReturn.Success)
                                    {
                                        outputReport.DoneOK = true;
                                    }
                                } finally {
                                    Monitor.Enter(_outputQueue);
                                }
                            }
                        } finally {
                            _outputQueue.Dequeue();
                            outputReport.Done = true;
                            Monitor.PulseAll(_outputQueue);
                        }
                    }
                }
            } finally {
                HandleRelease();
            }
        }
        unsafe void WriteThread()
        {
            if (!HandleAcquire())
            {
                return;
            }

            try
            {
                lock (_outputQueue)
                {
                    while (true)
                    {
                        while (!_shutdown && _outputQueue.Count == 0)
                        {
                            Monitor.Wait(_outputQueue);
                        }
                        if (_shutdown)
                        {
                            break;
                        }

                        CommonOutputReport outputReport = _outputQueue.Peek();

                        byte[] outputBytesRaw = outputReport.Bytes;
                        // Linux doesn't expect a Report ID if the device doesn't use one.
                        //if (!((LinuxHidDevice)Device).ReportsUseID && outputBytesRaw.Length > 0) { outputBytesRaw = outputBytesRaw.Skip(1).ToArray(); }
                        // BUGFIX: Yes, it does. But only on write(). (HIDSharp 2.0.2)

                        try
                        {
                            fixed(byte *outputBytes = outputBytesRaw)
                            {
                                // hidraw is apparently blocking for output, even when O_NONBLOCK is used.
                                // See for yourself at drivers/hid/hidraw.c...
                                IntPtr length;

                                Monitor.Exit(_outputQueue);
                                try
                                {
                                    var outputBytesPtr = (IntPtr)outputBytes;
                                    length = NativeMethods.retry(() => NativeMethods.write
                                                                     (_handle, outputBytesPtr, (UIntPtr)outputBytesRaw.Length));
                                    if ((long)length == outputBytesRaw.Length)
                                    {
                                        outputReport.DoneOK = true;
                                    }
                                }
                                finally
                                {
                                    Monitor.Enter(_outputQueue);
                                }
                            }
                        }
                        finally
                        {
                            _outputQueue.Dequeue();
                            outputReport.Done = true;
                            Monitor.PulseAll(_outputQueue);
                        }
                    }
                }
            }
            finally
            {
                HandleRelease();
            }
        }
Esempio n. 4
0
        unsafe void WriteThread()
        {
            if (!HandleAcquire())
            {
                return;
            }

            try
            {
                lock (_outputQueue)
                {
                    while (true)
                    {
                        while (!_shutdown && _outputQueue.Count == 0)
                        {
                            Monitor.Wait(_outputQueue);
                        }
                        if (_shutdown)
                        {
                            break;
                        }

                        NativeMethods.IOReturn ret;
                        CommonOutputReport     outputReport = _outputQueue.Peek();
                        try
                        {
                            fixed(byte *outputReportBytes = outputReport.Bytes)
                            {
                                Monitor.Exit(_outputQueue);

                                try
                                {
                                    int reportID = outputReport.Bytes[0];
                                    var hasReportID = ((MacHidDevice)Device).ReportsUseID; int reportOffset = hasReportID ? 0 : 1;
                                    var reportPtr    = (IntPtr)(outputReportBytes + reportOffset);
                                    int reportLength = outputReport.Bytes.Length - reportOffset;
                                    if (reportLength > 0)
                                    {
                                        ret = NativeMethods.IOHIDDeviceSetReport(_handle,
                                                                                 outputReport.Feature ? NativeMethods.IOHIDReportType.Feature : NativeMethods.IOHIDReportType.Output,
                                                                                 (IntPtr)reportID, reportPtr, (IntPtr)reportLength);
                                        if (ret == NativeMethods.IOReturn.Success)
                                        {
                                            outputReport.DoneOK = true;
                                        }
                                    }
                                }
                                finally
                                {
                                    Monitor.Enter(_outputQueue);
                                }
                            }
                        }
                        finally
                        {
                            _outputQueue.Dequeue();
                            outputReport.Done = true;
                            Monitor.PulseAll(_outputQueue);
                        }
                    }
                }
            }
            finally
            {
                HandleRelease();
            }
        }
Esempio n. 5
0
        internal void CommonWrite(byte[] buffer, int offset, int count,
		                          Queue<CommonOutputReport> queue,
		                          bool feature, int maxOutputReportLength)
        {
            Throw.If.OutOfRange(buffer, offset, count);
            count = Math.Min(count, maxOutputReportLength);
            if (count == 0) { return; }

            int writeTimeout = WriteTimeout;
            int startTime = Environment.TickCount;
            int timeout;
			
			HandleAcquireIfOpenOrFail();
			try
			{
	            lock (queue)
	            {
	                while (true)
	                {
	                    if (queue.Count == 0)
	                    {
	                        byte[] packet = new byte[count];
	                        Array.Copy(buffer, offset, packet, 0, count);
	                        var outputReport = new CommonOutputReport() { Bytes = packet, Feature = feature };
	                        queue.Enqueue(outputReport);
	                        Monitor.PulseAll(queue);
	
	                        while (true)
	                        {
	                            if (outputReport.Done)
	                            {
	                                if (!outputReport.DoneOK) { throw new IOException(); }
	                                return;
	                            }
	
	                            timeout = GetTimeout(startTime, writeTimeout);
	                            if (!Monitor.Wait(queue, timeout)) { throw new TimeoutException(); }
	                        }
	                    }
	
	                    timeout = GetTimeout(startTime, writeTimeout);
	                    if (!Monitor.Wait(queue, timeout)) { throw new TimeoutException(); }
	                }
	            }
			}
			finally
			{
				HandleRelease();
			}
        }