示例#1
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();
            }
        }
示例#2
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();
            }
        }