public static InitializationPacket ReadFrom(ArraySegment <byte> segment) { if (segment.Count < NoDataSize) { throw new InvalidPacketSizeException(segment, $"Data is too small, expected {NoDataSize} bytes but provided only {segment.Count}"); } var result = new InitializationPacket(); using (var stream = new MemoryStream(segment.Array, segment.Offset, segment.Count)) { var reader = new EndianReader(stream, Endianness.BigEndian); result.ChannelIdentifier = reader.ReadUInt32(); result.CommandIdentifier = reader.ReadByte(); CheckCommand(segment, result.CommandIdentifier); var payloadLengthHi = reader.ReadByte(); var payloadLengthLo = reader.ReadByte(); result.PayloadLength = (ushort)(payloadLengthHi << 8 | payloadLengthLo); } var remainingBytes = Math.Min(segment.Count - NoDataSize, result.PayloadLength); result.Data = new ArraySegment <byte>(segment.Array, segment.Offset + NoDataSize, remainingBytes); return(result); }
public static InitializationPacket ReadFrom(ArraySegment<byte> segment) { if (segment.Count < NoDataSize) { throw new InvalidPacketSizeException(segment, $"Data is too small, expected {NoDataSize} bytes but provided only {segment.Count}"); } var result = new InitializationPacket(); using (var stream = new MemoryStream(segment.Array, segment.Offset, segment.Count)) { var reader = new EndianReader(stream, Endianness.BigEndian); result.ChannelIdentifier = reader.ReadUInt32(); result.CommandIdentifier = reader.ReadByte(); CheckCommand(segment, result.CommandIdentifier); var payloadLengthHi = reader.ReadByte(); var payloadLengthLo = reader.ReadByte(); result.PayloadLength = (ushort)(payloadLengthHi << 8 | payloadLengthLo); } var remainingBytes = Math.Min(segment.Count - NoDataSize, result.PayloadLength); result.Data = new ArraySegment<byte>(segment.Array, segment.Offset + NoDataSize, remainingBytes); return result; }
static FidoU2FHidMessage BuildMessage(InitializationPacket init, List<ContinuationPacket> continuations) { ArraySegment<byte> data; if (continuations.Count > 0) { // We must allocate memory to reconstruct the message var stream = new MemoryStream(init.PayloadLength); stream.Write(init.Data.Array, init.Data.Offset, init.Data.Count); foreach (var continuation in continuations) { stream.Write(continuation.Data.Array, continuation.Data.Offset, continuation.Data.Count); } data = stream.ToArray().Segment(); } else { // No need to reconstruct the message data = init.Data; } return new FidoU2FHidMessage(init.ChannelIdentifier, (U2FHidCommand)init.CommandIdentifier, data); }
static Tuple<InitializationPacket, List<ContinuationPacket>> MakeOutputPackets( int paketLength, FidoU2FHidMessage message) { var availableInInit = paketLength - InitializationPacket.NoDataSize; var availableInContinuation = paketLength - ContinuationPacket.NoDataSize; var data = message.Data; var init = new InitializationPacket { ChannelIdentifier = message.Channel, CommandIdentifier = (byte)message.Command, PayloadLength = (ushort)data.Count, Data = new ArraySegment<byte>(data.Array, data.Offset, Math.Min(data.Count, availableInInit)) }; var sizeHandled = init.Data.Count; var continuations = new List<ContinuationPacket>(); byte sequence = 0; while (sizeHandled < data.Count) { var continuation = new ContinuationPacket { ChannelIdentifier = message.Channel, PaketSequence = sequence, Data = new ArraySegment<byte>(data.Array, data.Offset + sizeHandled, Math.Min(data.Count - sizeHandled, availableInContinuation)) }; continuations.Add(continuation); sizeHandled += continuation.Data.Count; sequence += 1; } return Tuple.Create(init, continuations); }
static unsafe void Test(Win32HidDevice device) { var init = new InitializationPacket(); init.CommandIdentifier = (byte)U2FHidCommand.Init; init.ChannelIdentifier = U2FHID_BROADCAST_CID; init.PayloadLength = 8; var caps = device.Information.Capabilities; var buffer = new byte[caps.InputReportByteLength]; fixed (byte* pBuffer = buffer) { Marshal.StructureToPtr(init, new IntPtr(pBuffer + 1), false); buffer[0] = 0x00; buffer[8] = 0xCA; buffer[9] = 0xFE; buffer[10] = 0xBA; buffer[11] = 0xBE; buffer[12] = 0xDE; buffer[13] = 0xAD; buffer[14] = 0xBA; buffer[15] = 0xBE; WriteBuffer(buffer); var task = Kernel32Dll.WriteFileAsync(device.Handle, new IntPtr(pBuffer), buffer.Length); var writen = task.Result; Console.WriteLine("Writen {0} bytes", writen); } var bufferOut = new byte[caps.OutputReportByteLength]; fixed (byte* pBuffer = bufferOut) { var intPtr = new IntPtr(pBuffer); var task = Kernel32Dll.ReadFileAsync(device.Handle, intPtr, bufferOut.Length); var read = task.Result; Console.WriteLine("Read {0} bytes", read); } WriteBuffer(bufferOut); Wink(device, bufferOut[16], bufferOut[17], bufferOut[18], bufferOut[19]); }