Example #1
0
        unsafe void WriteCharacteristic(BleCharacteristic characteristic, byte[] value, int offset, int count, NativeMethods.BLUETOOTH_GATT_FLAGS flags)
        {
            Throw.If.Null(characteristic, "characteristic").Null(value, "value").OutOfRange(value, offset, count);

            HandleAcquireIfOpenOrFail();
            try
            {
                lock (_writeSync)
                {
                    int error;
                    var wc = (WinBleCharacteristic)characteristic;

                    var cb = stackalloc byte[NativeMethods.BTH_LE_GATT_CHARACTERISTIC_VALUE.Size + count];
                    var cv = (NativeMethods.BTH_LE_GATT_CHARACTERISTIC_VALUE *)cb;
                    cv->DataSize = (uint)count; Marshal.Copy(value, offset, (IntPtr)(void *)&cv->Data[0], count);

                    error = NativeMethods.BluetoothGATTSetCharacteristicValue(_handle, ref wc.NativeData, cv, 0, flags);
                    if (error != 0)
                    {
                        var message = string.Format("Failed to write {0} bytes to characteristic {1}.", count, characteristic);
                        throw DeviceException.CreateIOException(Device, message, error);
                    }
                }
            }
            finally
            {
                HandleRelease();
            }
        }
Example #2
0
        internal void Init(string devicePath)
        {
            IntPtr handle = NativeMethods.CreateFileFromDevice(devicePath,
                                                               NativeMethods.EFileAccess.Read | NativeMethods.EFileAccess.Write,
                                                               NativeMethods.EFileShare.None);

            if (handle == (IntPtr)(-1))
            {
                int hr = Marshal.GetHRForLastWin32Error();
                throw DeviceException.CreateIOException(Device, "Unable to open serial device (" + devicePath + ").", hr);
            }

            var timeouts = new NativeMethods.COMMTIMEOUTS();

            timeouts.ReadIntervalTimeout        = uint.MaxValue;
            timeouts.ReadTotalTimeoutConstant   = uint.MaxValue - 1; // CP210x fails if this is set to uint.MaxValue.
            timeouts.ReadTotalTimeoutMultiplier = uint.MaxValue;
            if (!NativeMethods.SetCommTimeouts(handle, out timeouts))
            {
                int hr = Marshal.GetHRForLastWin32Error();
                NativeMethods.CloseHandle(handle);
                throw DeviceException.CreateIOException(Device, "Unable to set serial timeouts.", hr);
            }

            _handle = handle;
            HandleInitAndOpen();
        }
Example #3
0
        /*
         * public override bool GetConnectionState()
         * {
         *  uint devInst;
         *  if (0 == NativeMethods.CM_Locate_DevNode(out devInst, _id))
         *  {
         *      uint dnStatus, dnProblemNumber;
         *      if (0 == NativeMethods.CM_Get_DevNode_Status(out dnStatus, out dnProblemNumber, devInst))
         *      {
         *          if (0 == (dnStatus & NativeMethods.DN_DEVICE_DISCONNECTED)) { return true; }
         *      }
         *  }
         *
         *  return false;
         * }
         */

        void RequiresServices()
        {
            lock (_syncObject)
            {
                if (!TryOpenToGetInfo(handle =>
                {
                    var nativeServices = NativeMethods.BluetoothGATTGetServices(handle);
                    if (nativeServices == null)
                    {
                        return(false);
                    }

                    var services = new List <WinBleService>();
                    foreach (var nativeService in nativeServices)
                    {
                        var service = new WinBleService(this, nativeService);
                        services.Add(service);
                    }

                    _services = services.ToArray();
                    return(true);
                }))
                {
                    throw DeviceException.CreateIOException(this, "BLE service list could not be retrieved.");
                }
            }
        }
Example #4
0
 public override string GetManufacturer()
 {
     if (_manufacturer == null)
     {
         throw DeviceException.CreateIOException(this, "Unnamed manufacturer.");
     }
     return(_manufacturer);
 }
Example #5
0
 public override string GetProductName()
 {
     if (_productName == null)
     {
         throw DeviceException.CreateIOException(this, "Unnamed product.");
     }
     return(_productName);
 }
Example #6
0
 public override string GetSerialNumber()
 {
     if (_serialNumber == null)
     {
         throw DeviceException.CreateIOException(this, "No serial number.");
     }
     return(_serialNumber);
 }
        public DeviceExceptionDTO(DeviceException exception)
        {
            RowKey       = DateTime.UtcNow.ToInverseTicksRowKey();
            PartitionKey = exception.DeviceUniqueId;

            DeviceId           = exception.DeviceId;
            DeviceUniqueId     = exception.DeviceUniqueId;
            DeviceRepositoryId = exception.DeviceRepositoryId;
            Timestamp          = exception.Timestamp;
            ErrorCode          = exception.ErrorCode;
            Details            = exception.Details;
        }
Example #8
0
        public void ExceptionTest()
        {
            // Arrange.
            const string expectedMessage = "Exception of type 'Sensit.TestSDK.Exceptions.DeviceException' was thrown.";

            // Act
            var exception = new DeviceException();

            // Assert
            Assert.IsNull(exception.InnerException);
            Assert.AreEqual(expectedMessage, exception.Message);
        }
Example #9
0
        public void MessageTest()
        {
            // Arrange.
            const string expectedMessage = "message";

            // Act.
            var exception = new DeviceException(expectedMessage);

            // Assert.
            Assert.IsNull(exception.InnerException);
            Assert.AreEqual(expectedMessage, exception.Message);
        }
Example #10
0
        public override unsafe byte[] ReadCharacteristic(BleCharacteristic characteristic, BleRequestFlags requestFlags)
        {
            Throw.If.Null(characteristic, "characteristic");
            HidSharpDiagnostics.PerformStrictCheck(characteristic.IsReadable, "Characteristic doesn't support Read.");

            var flags = GetGattFlags(requestFlags);

            HandleAcquireIfOpenOrFail();
            try
            {
                lock (_readSync)
                {
                    int error;
                    var wc = (WinBleCharacteristic)characteristic;

                    ushort valueSize;
                    error = NativeMethods.BluetoothGATTGetCharacteristicValue(_handle,
                                                                              ref wc.NativeData,
                                                                              0, null,
                                                                              out valueSize,
                                                                              flags | ((requestFlags & BleRequestFlags.Cacheable) == 0 ? NativeMethods.BLUETOOTH_GATT_FLAGS.FORCE_READ_FROM_DEVICE : 0));
                    if (error != NativeMethods.ERROR_MORE_DATA || valueSize < NativeMethods.BTH_LE_GATT_CHARACTERISTIC_VALUE.Size)
                    {
                        var message = string.Format("Failed to read characteristic {0}.", characteristic);
                        throw DeviceException.CreateIOException(Device, message, error);
                    }

                    var cb = stackalloc byte[valueSize];
                    var cv = (NativeMethods.BTH_LE_GATT_CHARACTERISTIC_VALUE *)cb;

                    ushort valueSize2;
                    error = NativeMethods.BluetoothGATTGetCharacteristicValue(_handle,
                                                                              ref wc.NativeData,
                                                                              valueSize,
                                                                              cv,
                                                                              out valueSize2,
                                                                              flags);
                    if (error != 0 || valueSize != valueSize2 || cv->DataSize > valueSize - NativeMethods.BTH_LE_GATT_CHARACTERISTIC_VALUE.Size)
                    {
                        var message = string.Format("Failed to read characteristic {0}.", characteristic);
                        throw DeviceException.CreateIOException(Device, message, error);
                    }

                    var bytes = new byte[cv->DataSize];
                    Marshal.Copy((IntPtr)(void *)&cv->Data[0], bytes, 0, checked ((int)cv->DataSize));
                    return(bytes);
                }
            }
            finally
            {
                HandleRelease();
            }
        }
Example #11
0
        internal MacSerialStream(MacSerialDevice device)
            : base(device)
        {
            string fileSystemName = device.GetFileSystemName();

            int ret;
            int handle = NativeMethods.retry(() => NativeMethods.open(fileSystemName, NativeMethods.oflag.RDWR | NativeMethods.oflag.NOCTTY | NativeMethods.oflag.NONBLOCK));

            if (handle < 0)
            {
                var error = (NativeMethods.error)Marshal.GetLastWin32Error();
                if (error == NativeMethods.error.EACCES)
                {
                    throw DeviceException.CreateUnauthorizedAccessException(device, "Not permitted to open serial device at " + fileSystemName + ".");
                }
                else
                {
                    throw DeviceException.CreateIOException(device, "Unable to open serial device (" + error.ToString() + ").");
                }
            }

            ret = NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCEXCL));
            if (ret < 0)
            {
                NativeMethods.retry(() => NativeMethods.close(handle));
                throw new IOException("Unable to open serial device exclusively.");
            }

            /*
             * ret = NativeMethods.retry(() => NativeMethods.fcntl(handle, NativeMethods.F_SETFL, 0));
             * if (ret < 0)
             * {
             *  NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCNXCL));
             *  NativeMethods.retry(() => NativeMethods.close(handle));
             *  throw new IOException("Unable to remove blocking from port.");
             * }
             */

            ret = NativeMethods.retry(() => NativeMethods.tcgetattr(handle, out _oldSettings));
            if (ret < 0)
            {
                NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCNXCL));
                NativeMethods.retry(() => NativeMethods.close(handle));
                throw new IOException("Unable to get serial port settings.");
            }

            _newSettings = _oldSettings;
            NativeMethods.cfmakeraw(ref _newSettings);
            _handle = handle;
            InitSettings();
            UpdateSettings();
        }
Example #12
0
        internal void Init(NativeMethods.io_string_t path)
        {
            IntPtr handle; int retryCount = 0, maxRetries = 10;

            while (true)
            {
                var newPath = path.Clone();
                using (var service = NativeMethods.IORegistryEntryFromPath(0, ref newPath).ToIOObject())
                {
                    string error;

                    if (service.IsSet)
                    {
                        handle = NativeMethods.IOHIDDeviceCreate(IntPtr.Zero, service);
                        if (handle != IntPtr.Zero)
                        {
                            var ret = NativeMethods.IOHIDDeviceOpen(handle);
                            if (ret == NativeMethods.IOReturn.Success)
                            {
                                break;
                            }

                            NativeMethods.CFRelease(handle);

                            // TODO: Only count up if IOReturn is ExclusiveAccess or Offline.
                            error = string.Format("Unable to open HID class device (error {1}): {0}", newPath.ToString(), ret);
                        }
                        else
                        {
                            error = string.Format("HID class device not found: {0}", newPath.ToString());
                        }
                    }
                    else
                    {
                        error = string.Format("HID class device path not found: {0}", newPath.ToString());
                    }

                    if (++retryCount == maxRetries)
                    {
                        throw DeviceException.CreateIOException(Device, error);
                    }

                    Debug.WriteLine(string.Format("Retrying ({0})", error));
                    Thread.Sleep(100);
                }
            }
            _handle = handle;
            HandleInitAndOpen();

            _readThread.Start();
            _writeThread.Start();
        }
Example #13
0
        public void InnerExceptionTest()
        {
            // Arrange.
            const string expectedMessage = "message";
            var          innerException  = new Exception("foo");

            // Act.
            var exception = new DeviceException(expectedMessage, innerException);

            // Assert.
            Assert.AreEqual(innerException, exception.InnerException);
            Assert.AreEqual(expectedMessage, exception.Message);
        }
Example #14
0
        internal unsafe void Init(string path)
        {
            IntPtr handle = NativeMethods.CreateFileFromDevice(path, NativeMethods.EFileAccess.Read | NativeMethods.EFileAccess.Write, 0);

            if (handle == (IntPtr)(-1))
            {
                throw DeviceException.CreateIOException(Device, "Unable to open BLE service (" + path + ").");
            }

            _handle = handle;
            HandleInitAndOpen();

            // Let's register to watch all possible characteristics.
            var watchedCharacteristics = new List <WinBleCharacteristic>();

            foreach (var characteristic in Service.GetCharacteristics())
            {
                if (characteristic.IsNotifiable || characteristic.IsIndicatable)
                {
                    watchedCharacteristics.Add((WinBleCharacteristic)characteristic);
                }
            }

            if (watchedCharacteristics.Count > 0)
            {
                var eb = stackalloc byte[checked (NativeMethods.BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION.Size +
                                                  NativeMethods.BTH_LE_GATT_CHARACTERISTIC.Size * watchedCharacteristics.Count)];

                var er = (NativeMethods.BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION *)eb;
                er->NumCharacteristics = (ushort)watchedCharacteristics.Count;
                eb += NativeMethods.BLUETOOTH_GATT_VALUE_CHANGED_EVENT_REGISTRATION.Size;

                for (int i = 0; i < watchedCharacteristics.Count; i++)
                {
                    var wc = watchedCharacteristics[i];
                    Marshal.StructureToPtr(wc.NativeData, (IntPtr)eb, false);
                    eb += NativeMethods.BTH_LE_GATT_CHARACTERISTIC.Size;

                    _watchMap[wc.NativeData.AttributeHandle] = wc;
                }

                _watchCallback = new NativeMethods.BLUETOOTH_GATT_EVENT_CALLBACK(EventCallback);
                int error = NativeMethods.BluetoothGATTRegisterEvent(handle, NativeMethods.BTH_LE_GATT_EVENT_TYPE.CharacteristicValueChangedEvent,
                                                                     er, _watchCallback, IntPtr.Zero, out _watchRegisterEventHandle);
                if (error != 0)
                {
                    Debug.Assert(error == 0); _watchRegisterEventHandle = IntPtr.Zero;
                }
            }
        }
Example #15
0
        public override BleCharacteristic[] GetCharacteristics()
        {
            lock (_syncObject)
            {
                if (_characteristics == null)
                {
                    if (!_device.TryOpenToGetInfo(handle =>
                    {
                        var nativeCharacteristics = NativeMethods.BluetoothGATTGetCharacteristics(handle, ref NativeData);
                        if (nativeCharacteristics == null)
                        {
                            return(false);
                        }

                        var characteristics = new List <WinBleCharacteristic>();
                        foreach (var nativeCharacteristic in nativeCharacteristics)
                        {
                            var characteristic = new WinBleCharacteristic(nativeCharacteristic);
                            characteristics.Add(characteristic);

                            var nativeDescriptors = NativeMethods.BluetoothGATTGetDescriptors(handle, ref characteristic.NativeData);
                            if (nativeDescriptors == null)
                            {
                                return(false);
                            }

                            var descriptors = new List <WinBleDescriptor>();
                            foreach (var nativeDescriptor in nativeDescriptors)
                            {
                                var descriptor = new WinBleDescriptor(nativeDescriptor);
                                descriptors.Add(descriptor);
                            }

                            characteristic._characteristicDescriptors = descriptors.ToArray();
                        }

                        _characteristics = characteristics.ToArray();
                        return(true);
                    }))
                    {
                        throw DeviceException.CreateIOException(_device, "BLE service information could not be retrieved.");
                    }
                }
            }

            return((BleCharacteristic[])_characteristics.Clone());
        }
        internal static int DeviceHandleFromPath(string path, HidDevice hidDevice, NativeMethods.oflag oflag)
        {
            IntPtr udev = NativeMethodsLibudev.Instance.udev_new();

            if (IntPtr.Zero != udev)
            {
                try
                {
                    IntPtr device = NativeMethodsLibudev.Instance.udev_device_new_from_syspath(udev, path);
                    if (IntPtr.Zero != device)
                    {
                        try
                        {
                            string devnode = NativeMethodsLibudev.Instance.udev_device_get_devnode(device);
                            if (devnode != null)
                            {
                                int handle = NativeMethods.retry(() => NativeMethods.open(devnode, oflag));
                                if (handle < 0)
                                {
                                    var error = (NativeMethods.error)Marshal.GetLastWin32Error();
                                    if (error == NativeMethods.error.EACCES)
                                    {
                                        throw DeviceException.CreateUnauthorizedAccessException(hidDevice, "Not permitted to open HID class device at " + devnode + ".");
                                    }
                                    else
                                    {
                                        throw DeviceException.CreateIOException(hidDevice, "Unable to open HID class device (" + error.ToString() + ").");
                                    }
                                }
                                return(handle);
                            }
                        }
                        finally
                        {
                            NativeMethodsLibudev.Instance.udev_device_unref(device);
                        }
                    }
                }
                finally
                {
                    NativeMethodsLibudev.Instance.udev_unref(udev);
                }
            }

            throw new FileNotFoundException("HID class device not found.");
        }
Example #17
0
        public override string GetIndexedString(int stringIndex)
        {
            string indexedString = null;

            if (!TryOpenToGetInfo(handle =>
            {
                char[] buffer = new char[128];
                if (!NativeMethods.HidD_GetIndexedString(handle, stringIndex, buffer, Marshal.SystemDefaultCharSize * buffer.Length))
                {
                    return(Marshal.GetLastWin32Error() == NativeMethods.ERROR_GEN_FAILURE);
                }
                indexedString = NativeMethods.NTString(buffer);
                return(true);
            }))
            {
                throw DeviceException.CreateIOException(this, "Failed to get info.");
            }
            return(indexedString);
        }
Example #18
0
        void UpdateSettings()
        {
            lock (_lock)
            {
                // This assumes the handle is acquired.
                if (!_settingsChanged)
                {
                    return;
                }
                _settingsChanged = false;

                var dcb = new NativeMethods.DCB();
                dcb.DCBlength = Marshal.SizeOf(typeof(NativeMethods.DCB));
                if (!NativeMethods.GetCommState(_handle, ref dcb))
                {
                    int hr = Marshal.GetHRForLastWin32Error();
                    throw DeviceException.CreateIOException(Device, "Failed to get serial state.", hr);
                }

                int baudRate = _ser.BaudRate;
                int dataBits = _ser.DataBits;
                var parity   = _ser.Parity;
                int stopBits = _ser.StopBits;

                SetDcbDefaults(ref dcb);
                dcb.BaudRate = checked ((uint)baudRate);
                dcb.ByteSize = checked ((byte)_ser.DataBits);
                dcb.Parity   = parity == SerialParity.Even ? NativeMethods.EVENPARITY : parity == SerialParity.Odd ? NativeMethods.ODDPARITY : NativeMethods.NOPARITY;
                dcb.StopBits = stopBits == 2 ? NativeMethods.TWOSTOPBITS : NativeMethods.ONESTOPBIT;
                if (!NativeMethods.SetCommState(_handle, ref dcb))
                {
                    int hr = Marshal.GetHRForLastWin32Error();
                    throw DeviceException.CreateIOException(Device, "Failed to set serial state.", hr);
                }

                var purgeFlags = NativeMethods.PURGE_RXABORT | NativeMethods.PURGE_RXCLEAR | NativeMethods.PURGE_TXABORT | NativeMethods.PURGE_TXCLEAR;
                if (!NativeMethods.PurgeComm(_handle, purgeFlags))
                {
                    int hr = Marshal.GetHRForLastWin32Error();
                    throw DeviceException.CreateIOException(Device, "Failed to purge serial port.", hr);
                }
            }
        }
Example #19
0
        internal void Init(string path)
        {
            IntPtr handle = NativeMethods.CreateFileFromDevice(path, NativeMethods.EFileAccess.Read | NativeMethods.EFileAccess.Write, NativeMethods.EFileShare.Read | NativeMethods.EFileShare.Write);

            if (handle == (IntPtr)(-1))
            {
                throw DeviceException.CreateIOException(Device, "Unable to open HID class device (" + path + ").");
            }

            int maxInputBuffers = Environment.OSVersion.Version >= new Version(5, 1) ? 512 : 200; // Windows 2000 supports 200. Windows XP supports 512.

            if (!NativeMethods.HidD_SetNumInputBuffers(handle, maxInputBuffers))
            {
                NativeMethods.CloseHandle(handle);
                throw new IOException("Failed to set input buffers.", new Win32Exception());
            }

            _handle = handle;
            HandleInitAndOpen();
        }
Example #20
0
        bool TryParseReportDescriptor(out Reports.ReportDescriptor parser, out byte[] reportDescriptor)
        {
            parser = null; reportDescriptor = null;

            int handle;

            try { handle = LinuxHidStream.DeviceHandleFromPath(_path, this, NativeMethods.oflag.NONBLOCK); }
            catch (FileNotFoundException) { throw DeviceException.CreateIOException(this, "Failed to read report descriptor."); }

            try
            {
                uint descsize;
                if (NativeMethods.ioctl(handle, NativeMethods.HIDIOCGRDESCSIZE, out descsize) < 0)
                {
                    return(false);
                }
                if (descsize > NativeMethods.HID_MAX_DESCRIPTOR_SIZE)
                {
                    return(false);
                }

                var desc = new NativeMethods.hidraw_report_descriptor()
                {
                    size = descsize
                };
                if (NativeMethods.ioctl(handle, NativeMethods.HIDIOCGRDESC, ref desc) < 0)
                {
                    return(false);
                }

                Array.Resize(ref desc.value, (int)descsize);
                parser           = new Reports.ReportDescriptor(desc.value);
                reportDescriptor = desc.value; return(true);
            }
            finally
            {
                NativeMethods.retry(() => NativeMethods.close(handle));
            }
        }
Example #21
0
        void RequiresGetInfo()
        {
            lock (_getInfoLock)
            {
                if (_reportDescriptor != null)
                {
                    return;
                }

                Reports.ReportDescriptor parser; byte[] reportDescriptor;
                if (!TryParseReportDescriptor(out parser, out reportDescriptor))
                {
                    throw DeviceException.CreateIOException(this, "Failed to read report descriptor.");
                }

                _maxInput         = parser.MaxInputReportLength;
                _maxOutput        = parser.MaxOutputReportLength;
                _maxFeature       = parser.MaxFeatureReportLength;
                _reportsUseID     = parser.ReportsUseID;
                _reportDescriptor = reportDescriptor;
            }
        }
        public async Task <InvokeResult> ClearDeviceExcptionAsync([FromBody] DeviceException deviceExcpetion)
        {
            await ValidateRequest(HttpContext.Request);

            return(await _ticketCreator.ClearDeviceExceptionAsync(deviceExcpetion, OrgEntityHeader, UserEntityHeader));
        }
Example #23
0
        public override unsafe byte[] ReadDescriptor(BleDescriptor descriptor, BleRequestFlags requestFlags)
        {
            Throw.If.Null(descriptor, "descriptor");
            var flags = GetGattFlags(requestFlags);

            HandleAcquireIfOpenOrFail();
            try
            {
                lock (_readSync)
                {
                    int error;
                    var wd = (WinBleDescriptor)descriptor;

                    ushort valueSize;
                    error = NativeMethods.BluetoothGATTGetDescriptorValue(_handle,
                                                                          ref wd.NativeData,
                                                                          0, null,
                                                                          out valueSize,
                                                                          flags | ((requestFlags & BleRequestFlags.Cacheable) == 0 ? NativeMethods.BLUETOOTH_GATT_FLAGS.FORCE_READ_FROM_DEVICE : 0));
                    if (error != NativeMethods.ERROR_MORE_DATA || valueSize < NativeMethods.BTH_LE_GATT_DESCRIPTOR_VALUE.Size)
                    {
                        var message = string.Format("Failed to read descriptor {0}.", descriptor);
                        throw DeviceException.CreateIOException(Device, message, error);
                    }

                    var cb = stackalloc byte[valueSize];
                    var cv = (NativeMethods.BTH_LE_GATT_DESCRIPTOR_VALUE *)cb;

                    ushort valueSize2;
                    error = NativeMethods.BluetoothGATTGetDescriptorValue(_handle,
                                                                          ref wd.NativeData,
                                                                          valueSize,
                                                                          cv,
                                                                          out valueSize2,
                                                                          flags);
                    if (error != 0 || valueSize != valueSize2 || cv->Value.DataSize > valueSize - NativeMethods.BTH_LE_GATT_DESCRIPTOR_VALUE.Size)
                    {
                        var message = string.Format("Failed to read descriptor {0}.", descriptor);
                        throw DeviceException.CreateIOException(Device, message, error);
                    }

                    byte[] data;
                    switch (cv->DescriptorType)
                    {
                    case NativeMethods.BTH_LE_GATT_DESCRIPTOR_TYPE.CharacteristicExtendedProperties:
                        data = new byte[2];
                        if (0 != cv->Params.ExtendedProperties.IsReliableWriteEnabled)
                        {
                            data[0] |= 1;
                        }
                        if (0 != cv->Params.ExtendedProperties.IsAuxiliariesWritable)
                        {
                            data[0] |= 2;
                        }
                        break;

                    case NativeMethods.BTH_LE_GATT_DESCRIPTOR_TYPE.ClientCharacteristicConfiguration:
                        data = new byte[2];
                        if (0 != cv->Params.Cccd.IsSubscribeToNotification)
                        {
                            data[0] |= 1;
                        }
                        if (0 != cv->Params.Cccd.IsSubscribeToIndication)
                        {
                            data[0] |= 2;
                        }
                        break;

                    case NativeMethods.BTH_LE_GATT_DESCRIPTOR_TYPE.ServerCharacteristicConfiguration:
                        data = new byte[2];
                        if (0 != cv->Params.Sccd.IsBroadcast)
                        {
                            data[0] |= 1;
                        }
                        break;

                    case NativeMethods.BTH_LE_GATT_DESCRIPTOR_TYPE.CharacteristicFormat:
                        throw new NotImplementedException();

                    default:
                        //Console.WriteLine(string.Format("{0} {1} {2}", valueSize, cv->DescriptorType, cv->Value.DataSize));
                        data = new byte[cv->Value.DataSize];
                        Marshal.Copy((IntPtr)(void *)&cv->Value.Data[0], data, 0, data.Length);
                        break;
                    }

                    return(data);
                }
            }
            finally
            {
                HandleRelease();
            }
        }
        public async Task <InvokeResult> ClearDeviceExceptionAsync(DeviceException exception, EntityHeader org, EntityHeader user)
        {
            if (exception == null)
            {
                throw new ArgumentNullException(nameof(exception));
            }
            if (org == null)
            {
                throw new ArgumentNullException(nameof(org));
            }
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            var repo = await _repoManager.GetDeviceRepositoryWithSecretsAsync(exception.DeviceRepositoryId, org, user);

            var device = await _deviceManager.GetDeviceByIdAsync(repo, exception.DeviceUniqueId, org, user);

            var deviceConfig = await _deviceConfigManager.GetDeviceConfigurationAsync(device.DeviceConfiguration.Id, org, user);

            var deviceErrorCode = deviceConfig.ErrorCodes.FirstOrDefault(err => err.Key == exception.ErrorCode);

            if (deviceErrorCode == null)
            {
                return(InvokeResult.FromError($"Could not find error code [{exception.ErrorCode}] on device configuration [{deviceConfig.Name}] for device [{device.Name}]"));
            }

            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.WriteLine("Clear Device Exception.");

            if (!EntityHeader.IsNullOrEmpty(deviceErrorCode.ServiceTicketTemplate))
            {
                var tickets = await _repo.GetOpenTicketOnDeviceAsync(device.Id, deviceErrorCode.ServiceTicketTemplate.Id, org.Id);

                foreach (var ticket in tickets)
                {
                    ticket.IsClosed = true;
                    ticket.ClosedBy = user;

                    await _repo.UpdateServiceTicketAsync(ticket);
                }
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("No service ticket, skipping.");
            }

            if (!EntityHeader.IsNullOrEmpty(deviceErrorCode.DistroList))
            {
                var distroList = await _distroManager.GetListAsync(deviceErrorCode.DistroList.Id, org, user);

                var subject = "[CLEARED] -" + (String.IsNullOrEmpty(deviceErrorCode.EmailSubject) ? deviceErrorCode.Name : deviceErrorCode.EmailSubject.Replace("[DEVICEID]", device.DeviceId).Replace("[DEVICENAME]", device.Name));

                foreach (var notificationUser in distroList.AppUsers)
                {
                    var appUser = await _userManager.FindByIdAsync(notificationUser.Id);

                    if (deviceErrorCode.SendEmail)
                    {
                        var body = $"The error code [{deviceErrorCode.Key}] was cleared on the device {device.Name}<br>{deviceErrorCode.Description}<br>{exception.Details}";
                        await _emailSender.SendAsync(appUser.Email, subject, body);
                    }

                    if (deviceErrorCode.SendSMS)
                    {
                        var body = $"Device {device.Name} cleared error code [${deviceErrorCode.Key}] {deviceErrorCode.Description} {exception.Details}";
                        await _smsSender.SendAsync(appUser.PhoneNumber, body);
                    }
                }
            }
            else
            {
                Console.WriteLine("No distro, skipping.");
            }

            Console.ResetColor();


            return(InvokeResult.Success);
        }
        public async Task <InvokeResult> HandleDeviceExceptionAsync(DeviceException exception, EntityHeader org, EntityHeader user)
        {
            if (exception == null)
            {
                throw new ArgumentNullException(nameof(exception));
            }
            if (org == null)
            {
                throw new ArgumentNullException(nameof(org));
            }
            if (user == null)
            {
                throw new ArgumentNullException(nameof(user));
            }

            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.WriteLine("Handling Device Exception.");

            var repo = await _repoManager.GetDeviceRepositoryWithSecretsAsync(exception.DeviceRepositoryId, org, user);

            var device = await _deviceManager.GetDeviceByDeviceIdAsync(repo, exception.DeviceUniqueId, org, user);

            var deviceConfig = await _deviceConfigManager.GetDeviceConfigurationAsync(device.DeviceConfiguration.Id, org, user);

            var deviceErrorCode = deviceConfig.ErrorCodes.FirstOrDefault(err => err.Key == exception.ErrorCode);

            if (deviceErrorCode == null)
            {
                return(InvokeResult.FromError($"Could not find error code [{exception.ErrorCode}] on device configuration [{deviceConfig.Name}] for device [{device.Name}]"));
            }

            if (!EntityHeader.IsNullOrEmpty(deviceErrorCode.ServiceTicketTemplate))
            {
                Console.WriteLine("Generating service ticket (every occurence.");
                var request = new CreateServiceTicketRequest()
                {
                    TemplateId = deviceErrorCode.ServiceTicketTemplate.Id,
                    DeviceId   = device.DeviceId,
                    Details    = exception.Details,
                    DontCreateIfOpenForDevice = !deviceErrorCode.TriggerOnEachOccurrence,
                    RepoId = repo.Id
                };

                var result = await CreateServiceTicketAsync(request, org, user);

                if (!result.Successful)
                {
                    return(result.ToInvokeResult());
                }
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("No service ticket, skipping.");
            }

            var deviceError = device.Errors.Where(err => err.DeviceErrorCode == exception.ErrorCode).FirstOrDefault();

            if (deviceError == null)
            {
                deviceError = new DeviceError()
                {
                    Count           = 1,
                    DeviceErrorCode = exception.ErrorCode,
                    FirstSeen       = DateTime.UtcNow.ToJSONString(),
                    LastDetails     = exception.Details,
                    Timestamp       = DateTime.UtcNow.ToJSONString(),
                    Expires         = deviceErrorCode.AutoexpireTimespan.Value.AddTimeSpan(deviceErrorCode.AutoexpireTimespanQuantity.Value)
                };

                device.Errors.Add(deviceError);
            }

            if (!EntityHeader.IsNullOrEmpty(deviceErrorCode.DistroList))
            {
                if (deviceError == null || String.IsNullOrEmpty(deviceError.NextNotification) || (deviceError.NextNotification.ToDateTime().ToUniversalTime() < DateTime.UtcNow))
                {
                    var result = await _distroManager.GetListAsync(deviceErrorCode.DistroList.Id, org, user);

                    var subject = String.IsNullOrEmpty(deviceErrorCode.EmailSubject) ? deviceErrorCode.Name : deviceErrorCode.EmailSubject.Replace("[DEVICEID]", device.DeviceId).Replace("[DEVICENAME]", device.Name);

                    foreach (var notificationUser in result.AppUsers)
                    {
                        var appUser = await _userManager.FindByIdAsync(notificationUser.Id);

                        if (deviceErrorCode.SendEmail)
                        {
                            var body = $"The error code [{deviceErrorCode.Key}] was detected on the device {device.Name}<br>{deviceErrorCode.Description}<br>{exception.Details}";
                            if (exception.AdditionalDetails.Any())
                            {
                                body += "<br>";
                                body += "<b>Additional Details:<br /><b>";
                                body += "<ul>";
                                foreach (var detail in exception.AdditionalDetails)
                                {
                                    body += $"<li>{detail}</li>";
                                }

                                body += "</ul>";
                            }
                            await _emailSender.SendAsync(appUser.Email, subject, body);
                        }

                        if (deviceErrorCode.SendSMS)
                        {
                            var body = $"Device {device.Name} generated error code [${deviceErrorCode.Key}] {deviceErrorCode.Description} {exception.Details}";
                            await _smsSender.SendAsync(appUser.PhoneNumber, body);
                        }
                    }

                    if (EntityHeader.IsNullOrEmpty(deviceErrorCode.NotificationIntervalTimeSpan))
                    {
                        deviceError.NextNotification = null;
                    }
                    else if (deviceErrorCode.NotificationIntervalQuantity.HasValue && deviceErrorCode.NotificationIntervalTimeSpan.Value != TimeSpanIntervals.NotApplicable)
                    {
                        deviceError.NextNotification = deviceErrorCode.NotificationIntervalTimeSpan.Value.AddTimeSpan(deviceErrorCode.NotificationIntervalQuantity.Value);
                    }
                    else
                    {
                        deviceError.NextNotification = null;
                        Logger.AddCustomEvent(Core.PlatformSupport.LogLevel.Error, "ServiceTicketManager__HandleDeviceExceptionAsync", "Invalid quantity on NotificationIntervalQuantity", device.DeviceId.ToKVP("deviceId"), exception.ErrorCode.ToKVP("errorCode"));
                    }
                }
                else
                {
                    if (String.IsNullOrEmpty(deviceError.NextNotification))
                    {
                        Console.WriteLine("NExt Notification is null....");
                    }
                    else
                    {
                        Console.WriteLine("When to send next notification: " + deviceError.NextNotification);
                    }
                }
            }
            else
            {
                Console.WriteLine("No distro, skipping.");
            }

            Console.ResetColor();

            await _deviceManager.UpdateDeviceAsync(repo, device, org, user);

            return(InvokeResult.Success);
        }
Example #26
0
        private async Task <InvokeResult> HandleSystemMessageAsync(string path, string payload)
        {
            Metrics.MessagesProcessed++;

            PEMBus.InstanceLogger.AddCustomEvent(LagoVista.Core.PlatformSupport.LogLevel.Message, "ListenerMOdule_HandleSystemMessageAsync", "Received System Message", path.ToKVP("topic"), payload.ToKVP("body"));

            var parts = path.Split('/');

            if (parts.Length < 5)
            {
                var errMsg = $"NuvIoT service messages must be at least 5 segments {path} is {parts.Length} segments";
                PEMBus.InstanceLogger.AddError("ListenerModule__HandleSystemMessage", errMsg);
                return(InvokeResult.FromError(errMsg));
            }

            var deviceId = parts[3];

            var device = await PEMBus.DeviceStorage.GetDeviceByDeviceIdAsync(deviceId);

            if (device == null)
            {
                var errMsg = $"Could not find device with device id {deviceId}.";
                PEMBus.InstanceLogger.AddError("ListenerModule__HandleSystemMessage", errMsg);
                return(InvokeResult.FromError(errMsg));
            }

            device.LastContact = DateTime.UtcNow.ToJSONString();

            if (parts[4] == "state")
            {
                device.DeviceTwinDetails.Insert(0, new DeviceManagement.Models.DeviceTwinDetails()
                {
                    Timestamp = DateTime.UtcNow.ToJSONString(),
                    Details   = payload
                });

                var payloadSegements = payload.Split(',');
                foreach (var segement in payloadSegements)
                {
                    var fieldParts = segement.Split('=');
                    if (fieldParts.Length == 2)
                    {
                        var nameParts = fieldParts[0].Split('-');
                        if (nameParts.Length == 2)
                        {
                            var typeName = nameParts[0];
                            var key      = nameParts[1];
                            var value    = fieldParts[1];
                            if (typeName != "readonly")
                            {
                                var prop = device.Properties.FirstOrDefault(prp => prp.Key == key);
                                if (prop != null)
                                {
                                    if (prop.Value != value)
                                    {
                                        prop.Value         = value;
                                        prop.LastUpdated   = DateTime.UtcNow.ToJSONString();
                                        prop.LastUpdatedBy = "Device Twin";
                                    }
                                }
                            }
                            else
                            {
                                if (key == "firmwareSku")
                                {
                                    device.ActualFirmware     = value;
                                    device.ActualFirmwareDate = DateTime.Now.ToJSONString();
                                }
                                if (key == "firmwareVersion")
                                {
                                    device.ActualFirmwareRevision = value;
                                    device.ActualFirmwareDate     = DateTime.Now.ToJSONString();
                                }
                            }
                        }
                    }
                }
            }
            else if (parts[4] == "err")
            {
                var err       = parts[5];
                var action    = parts[6];
                var exception = new DeviceException()
                {
                    ErrorCode          = err,
                    DeviceId           = device.DeviceId,
                    DeviceUniqueId     = device.Id,
                    DeviceRepositoryId = device.DeviceRepository.Id,
                    Timestamp          = DateTime.UtcNow.ToString(),
                };

                exception.AdditionalDetails.Add(payload);

                if (action == "raise")
                {
                    await PEMBus.InstanceConnector.HandleDeviceExceptionAsync(exception);
                }
                else if (action == "clear")
                {
                    await PEMBus.InstanceConnector.ClearDeviceExceptionAsync(exception);
                }
            }
            else if (parts[4] == "iovalues")
            {
                var values = payload.Split(',');
                if (values.Length != 16)
                {
                    throw new InvalidDataException($"IO Configuration from device should consist of 16 comma delimited values, message consists of ${values.Length} items.");
                }

                for (int idx = 0; idx < 8; ++idx)
                {
                    if (!String.IsNullOrEmpty(values[idx + 8]))
                    {
                        var sensor = device.SensorCollection.Where(sns => sns.Technology != null && sns.Technology.Value == DeviceManagement.Models.SensorTechnology.ADC && sns.PortIndex == idx).FirstOrDefault();
                        if (sensor != null)
                        {
                            sensor.Value       = values[idx + 8];
                            sensor.LastUpdated = DateTime.UtcNow.ToJSONString();
                        }
                    }
                }

                for (int idx = 0; idx < 8; ++idx)
                {
                    if (!String.IsNullOrEmpty(values[idx]))
                    {
                        var sensor = device.SensorCollection.Where(sns => sns.Technology != null && sns.Technology.Value == DeviceManagement.Models.SensorTechnology.IO && sns.PortIndex == idx).FirstOrDefault();
                        if (sensor != null)
                        {
                            sensor.Value       = values[idx];
                            sensor.LastUpdated = DateTime.UtcNow.ToJSONString();
                        }
                    }
                }

                await PEMBus.SensorEvaluator.EvaluateAsync(device);
            }
            else if (parts[4] == "geo")
            {
                var values = payload.Split(',');
                if (values.Length < 2)
                {
                    throw new InvalidDataException($"Geo Location Data type must contain a minimum of 2 fields for latitude and longitude, message consists of ${values.Length} items.");
                }

                if (!double.TryParse(values[0], out double lat))
                {
                    throw new InvalidDataException($"Invalid Latitude value [{values[0]}].");
                }

                if (lat > 90 || lat < -90)
                {
                    throw new InvalidDataException($"Invalid Latitude value [{values[0]}], must be between -90 and 90.");
                }

                if (!double.TryParse(values[1], out double lon))
                {
                    throw new InvalidDataException($"Invalid Longitude value [{values[1]}].");
                }

                if (lon > 180 || lon < -180)
                {
                    throw new InvalidDataException($"Invalid Latitude value [{values[1]}], must be between -180 and 180.");
                }

                device.GeoLocation = new LagoVista.Core.Models.Geo.GeoLocation()
                {
                    LastUpdated = DateTime.UtcNow.ToJSONString(),
                    Latitude    = lat,
                    Longitude   = lon,
                };
            }
            else if (parts[4] == "online")
            {
                device.ConnectionTimeStamp = DateTime.UtcNow.ToJSONString();
                var rssi      = -1.0;
                var reconnect = false;

                var payloadSegements = payload.Split(',');
                foreach (var segement in payloadSegements)
                {
                    var fieldParts = segement.Split('=');
                    if (fieldParts.Length == 2)
                    {
                        var nameParts = fieldParts[0].Split('-');
                        if (nameParts.Length == 2)
                        {
                            var typeName = nameParts[0];
                            var key      = nameParts[1];
                            var value    = fieldParts[1];
                            if (typeName != "readonly")
                            {
                                var prop = device.Properties.FirstOrDefault(prp => prp.Key == key);
                                if (prop != null)
                                {
                                    if (prop.Value != value)
                                    {
                                        if (prop.AttributeType.Value == DeviceAdmin.Models.ParameterTypes.TrueFalse)
                                        {
                                            if (value == "1")
                                            {
                                                value = "true";
                                            }
                                            else if (value == "0")
                                            {
                                                value = "false";
                                            }
                                            else
                                            {
                                                value = value.ToLower();
                                            }
                                        }
                                        prop.Value         = value;
                                        prop.LastUpdated   = DateTime.UtcNow.ToJSONString();
                                        prop.LastUpdatedBy = "Device Twin";
                                    }
                                }
                            }
                            else
                            {
                                if (key == "firmwareSku")
                                {
                                    device.ActualFirmware     = value;
                                    device.ActualFirmwareDate = DateTime.Now.ToJSONString();
                                }
                                if (key == "firmwareVersion")
                                {
                                    device.ActualFirmwareRevision = value;
                                    device.ActualFirmwareDate     = DateTime.Now.ToJSONString();
                                }
                                if (key == "rssi")
                                {
                                    double.TryParse(value, out rssi);
                                }
                                if (key == "reconnect")
                                {
                                    reconnect = value != "0";
                                }
                            }
                        }
                    }
                }

                var connectionEvent = new DeviceConnectionEvent()
                {
                    DeviceId         = device.Id,
                    FirmwareRevision = device.ActualFirmwareRevision,
                    FirmwareSKU      = device.ActualFirmware,
                    TimeStamp        = DateTime.UtcNow.ToJSONString(),
                    RSSI             = rssi,
                    Reconnect        = reconnect
                };

                await PEMBus.DeviceConnectionEvent.AddDeviceEventConnectionEvent(connectionEvent);
            }

            await PEMBus.DeviceStorage.UpdateDeviceAsync(device);

            var json         = JsonConvert.SerializeObject(Models.DeviceForNotification.FromDevice(device), _camelCaseSettings);
            var notification = new Notification()
            {
                Payload     = json,
                Channel     = EntityHeader <Channels> .Create(Channels.Device),
                ChannelId   = device.Id,
                PayloadType = "Device",
                DateStamp   = DateTime.UtcNow.ToJSONString(),
                MessageId   = Guid.NewGuid().ToId(),
                Text        = "Device Updated",
                Title       = "Device Updated"
            };

            await PEMBus.NotificationPublisher.PublishAsync(Targets.WebSocket, notification);

            notification = new Notification()
            {
                Payload     = json,
                Channel     = EntityHeader <Channels> .Create(Channels.DeviceRepository),
                ChannelId   = device.DeviceRepository.Id,
                PayloadType = "Device",
                DateStamp   = DateTime.UtcNow.ToJSONString(),
                MessageId   = Guid.NewGuid().ToId(),
                Text        = "Device Updated",
                Title       = "Device Updated"
            };

            await PEMBus.NotificationPublisher.PublishAsync(Targets.WebSocket, notification);

            foreach (var group in device.DeviceGroups)
            {
                notification = new Notification()
                {
                    Payload     = json,
                    Channel     = EntityHeader <Channels> .Create(Channels.DeviceGroup),
                    ChannelId   = group.Id,
                    PayloadType = "Device",
                    DateStamp   = DateTime.UtcNow.ToJSONString(),
                    MessageId   = Guid.NewGuid().ToId(),
                    Text        = "Device Updated",
                    Title       = "Device Updated"
                };

                await PEMBus.NotificationPublisher.PublishAsync(Targets.WebSocket, notification);
            }

            return(InvokeResult.Success);
        }
Example #27
0
        public override unsafe void WriteDescriptor(BleDescriptor descriptor, byte[] value, int offset, int count, BleRequestFlags requestFlags)
        {
            Throw.If.Null(descriptor, "descriptor").Null(value, "value").OutOfRange(value, offset, count);
            var flags = GetGattFlags(requestFlags);

            HandleAcquireIfOpenOrFail();
            try
            {
                lock (_writeSync)
                {
                    int error;
                    var wd = (WinBleDescriptor)descriptor;

                    var dvp = new NativeMethods.BTH_LE_GATT_DESCRIPTOR_VALUE_PARAMS(); byte[] data = null; int dataOffset = 0, dataCount = 0;

                    switch (wd.NativeData.DescriptorType)
                    {
                    case NativeMethods.BTH_LE_GATT_DESCRIPTOR_TYPE.CharacteristicExtendedProperties:
                        dvp.ExtendedProperties.IsReliableWriteEnabled = (byte)(value.Length >= 1 && 0 != (value[offset] & 1) ? 1 : 0);
                        dvp.ExtendedProperties.IsAuxiliariesWritable  = (byte)(value.Length >= 1 && 0 != (value[offset] & 2) ? 1 : 0);
                        data = new byte[0]; break;

                    case NativeMethods.BTH_LE_GATT_DESCRIPTOR_TYPE.ClientCharacteristicConfiguration:
                        dvp.Cccd.IsSubscribeToNotification = (byte)(value.Length >= 1 && 0 != (value[offset] & 1) ? 1 : 0);
                        dvp.Cccd.IsSubscribeToIndication   = (byte)(value.Length >= 1 && 0 != (value[offset] & 2) ? 1 : 0);
                        data = new byte[0]; break;

                    case NativeMethods.BTH_LE_GATT_DESCRIPTOR_TYPE.ServerCharacteristicConfiguration:
                        dvp.Sccd.IsBroadcast = (byte)(value.Length >= 1 && 0 != (value[offset] & 1) ? 1 : 0);
                        data = new byte[0]; break;

                    case NativeMethods.BTH_LE_GATT_DESCRIPTOR_TYPE.CharacteristicFormat:
                        throw new NotImplementedException();

                    default:
                        data = value; dataOffset = offset; dataCount = count; break;
                    }

                    var db = stackalloc byte[NativeMethods.BTH_LE_GATT_DESCRIPTOR_VALUE.Size + dataCount];
                    var dv = (NativeMethods.BTH_LE_GATT_DESCRIPTOR_VALUE *)db;
                    dv->DescriptorType = wd.NativeData.DescriptorType;
                    dv->DescriptorUuid = wd.NativeData.DescriptorUuid;
                    dv->Params         = dvp;
                    dv->Value.DataSize = (uint)dataCount;
                    if (data != null)
                    {
                        Marshal.Copy(data, dataOffset, (IntPtr)(void *)&dv->Value.Data[0], dataCount);
                    }

                    error = NativeMethods.BluetoothGATTSetDescriptorValue(_handle, ref wd.NativeData, dv, flags);
                    if (error != 0)
                    {
                        var message = string.Format("Failed to write {0} bytes to descriptor {1}.", count, descriptor);
                        throw DeviceException.CreateIOException(Device, message, error);
                    }
                }
            }
            finally
            {
                HandleRelease();
            }
        }
        public async Task <InvokeResult> AddDeviceExceptionAsync(DeviceRepository deviceRepo, DeviceException deviceException)
        {
            await _deviceExceptionRepo.AddDeviceExceptionAsync(deviceRepo, deviceException);

            return(InvokeResult.Success);
        }
Example #29
0
        void RequiresGetInfo(GetInfoFlags flags)
        {
            lock (_getInfoLock)
            {
                flags &= ~_getInfoFlags; // Remove flags we already have.
                if (flags == 0)
                {
                    return;
                }

                if (!TryOpenToGetInfo(handle =>
                {
                    if ((flags & GetInfoFlags.Manufacturer) != 0)
                    {
                        if (!TryGetDeviceString(handle, NativeMethods.HidD_GetManufacturerString, out _manufacturer))
                        {
                            return(false);
                        }
                    }

                    if ((flags & GetInfoFlags.ProductName) != 0)
                    {
                        if (!TryGetDeviceString(handle, NativeMethods.HidD_GetProductString, out _productName))
                        {
                            return(false);
                        }
                    }

                    if ((flags & GetInfoFlags.SerialNumber) != 0)
                    {
                        if (!TryGetDeviceString(handle, NativeMethods.HidD_GetSerialNumberString, out _serialNumber))
                        {
                            return(false);
                        }
                    }

                    if ((flags & GetInfoFlags.ReportInfo) != 0)
                    {
                        IntPtr preparsed;
                        if (!NativeMethods.HidD_GetPreparsedData(handle, out preparsed))
                        {
                            return(false);
                        }

                        try
                        {
                            NativeMethods.HIDP_CAPS caps;
                            int statusCaps = NativeMethods.HidP_GetCaps(preparsed, out caps);
                            if (statusCaps != NativeMethods.HIDP_STATUS_SUCCESS)
                            {
                                return(false);
                            }

                            _maxInput = caps.InputReportByteLength;
                            _maxOutput = caps.OutputReportByteLength;
                            _maxFeature = caps.FeatureReportByteLength;

                            try { _reportDescriptor = new ReportDescriptorReconstructor().Run(preparsed, caps); }
                            catch (NotImplementedException) { _reportDescriptor = null; }
                            catch { return(false); }
                        }
                        finally
                        {
                            NativeMethods.HidD_FreePreparsedData(preparsed);
                        }
                    }

                    return(true);
                }))
                {
                    throw DeviceException.CreateIOException(this, "Failed to get info.");
                }

                _getInfoFlags |= flags;
            }
        }
Example #30
0
        protected override string GetStreamPath(OpenConfiguration openConfig)
        {
            var service = GetService(openConfig);

            if (service == null)
            {
                throw DeviceException.CreateIOException(this, "BLE service not specified.");
            }
            if (service.Device != this)
            {
                throw DeviceException.CreateIOException(this, "BLE service is on a different device.");
            }

            uint devInst;

            if (0 == NativeMethods.CM_Locate_DevNode(out devInst, _id))
            {
                if (0 == NativeMethods.CM_Get_Child(out devInst, devInst))
                {
                    do
                    {
                        string serviceDeviceID;
                        if (0 == NativeMethods.CM_Get_Device_ID(devInst, out serviceDeviceID))
                        {
                            NativeMethods.HDEVINFO devInfo = NativeMethods.SetupDiGetClassDevs(
                                service.Uuid, serviceDeviceID, IntPtr.Zero,
                                NativeMethods.DIGCF.DeviceInterface | NativeMethods.DIGCF.Present
                                );

                            if (devInfo.IsValid)
                            {
                                try
                                {
                                    NativeMethods.SP_DEVINFO_DATA dvi = new NativeMethods.SP_DEVINFO_DATA();
                                    dvi.Size = Marshal.SizeOf(dvi);

                                    for (int j = 0; NativeMethods.SetupDiEnumDeviceInfo(devInfo, j, ref dvi); j++)
                                    {
                                        NativeMethods.SP_DEVICE_INTERFACE_DATA did = new NativeMethods.SP_DEVICE_INTERFACE_DATA();
                                        did.Size = Marshal.SizeOf(did);

                                        for (int k = 0; NativeMethods.SetupDiEnumDeviceInterfaces(devInfo, ref dvi, service.Uuid, k, ref did); k++)
                                        {
                                            string devicePath;
                                            if (NativeMethods.SetupDiGetDeviceInterfaceDevicePath(devInfo, ref did, out devicePath))
                                            {
                                                // FIXME: Take the attribute handle into account as well.
                                                //        Right now, if there are multiple services with the same GUID, we do not distinguish between them.
                                                return(devicePath);
                                            }
                                        }
                                    }
                                }
                                finally
                                {
                                    NativeMethods.SetupDiDestroyDeviceInfoList(devInfo);
                                }
                            }
                        }
                    }while (0 == NativeMethods.CM_Get_Sibling(out devInst, devInst));
                }
            }

            throw DeviceException.CreateIOException(this, string.Format("BLE service {0} not found.", service.Uuid));
        }