Skip to content

Commit

Permalink
✨ Add code to update touchscreen on SD+ devices.
Browse files Browse the repository at this point in the history
Not tested yet, but at least it is not forgotten.
  • Loading branch information
hexawyz committed Jan 14, 2025
1 parent 7654e93 commit fc14c56
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 4 deletions.
10 changes: 10 additions & 0 deletions Docs/Stream Decl XL.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ Firmware 1.01.000 end is 115272 bytes.
02 09 08 <IsFinalPacket:B8> <PacketIndex:U16> <PacketLength:U16> <Data:U8[]>
```

#### Command `0C` - Stream Deck + - Write image region

```
02 0C <Left:U16> <Top:U16> <Width:U16> <Height:U16> <IsFinalPacket:B8> <PacketIndex:U16> <PacketLength:U16> <Zero:U8> <Data:U8[]>
```

Stream Deck + devices would also include a touch screen, that can be updated entirely or partially using this command.

### Feature report `03` - Write - Device configuration

#### Command `02` - Reset
Expand Down Expand Up @@ -143,6 +151,8 @@ Example:
08 04 08 6000 6000 0004 5802 02 00 01 04 04 00 0000 0000 0000000000000000000000
```

NB: This likely includes touch screen width and height for SD+ devices.

### Feature report `09` - Read - Device total uptime

```
Expand Down
53 changes: 49 additions & 4 deletions src/Exo/Devices/Exo.Devices.Elgato.StreamDeck/StreamDeckDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -298,8 +298,8 @@ static ReadOnlyMemory<byte> UpdateRequest(Span<byte> buffer, ushort maxSliceLeng
ushort sliceLength = isLastSlice ? (ushort)remaining.Length : maxSliceLength;

buffer[3] = isLastSlice ? (byte)0x01 : (byte)0x00;
Unsafe.WriteUnaligned(ref buffer[4], BitConverter.IsLittleEndian ? sliceLength : BinaryPrimitives.ReverseEndianness(sliceLength));
Unsafe.WriteUnaligned(ref buffer[6], BitConverter.IsLittleEndian ? index : BinaryPrimitives.ReverseEndianness(index));
LittleEndian.Write(ref buffer[4], sliceLength);
LittleEndian.Write(ref buffer[6], index);
remaining.Span[..sliceLength].CopyTo(buffer[8..]);

return remaining[sliceLength..];
Expand All @@ -317,6 +317,51 @@ static ReadOnlyMemory<byte> UpdateRequest(Span<byte> buffer, ushort maxSliceLeng
}
}

public async Task SetTouchScreenRegionAsync(ushort x, ushort y, ushort width, ushort height, ReadOnlyMemory<byte> data, CancellationToken cancellationToken)
{
var buffer = WriteBuffer;

ushort maxSliceLength = checked((ushort)(buffer.Length - 16));

static ReadOnlyMemory<byte> PrepareRequest(Span<byte> buffer, ushort x, ushort y, ushort width, ushort height, ushort maxSliceLength, ReadOnlyMemory<byte> remaining)
{
buffer[0] = 0x02;
buffer[1] = 0x0C;
LittleEndian.Write(ref buffer[2], x);
LittleEndian.Write(ref buffer[4], y);
LittleEndian.Write(ref buffer[6], width);
LittleEndian.Write(ref buffer[8], height);
LittleEndian.Write(ref buffer[15], 0);

return UpdateRequest(buffer, maxSliceLength, remaining, 0);
}

static ReadOnlyMemory<byte> UpdateRequest(Span<byte> buffer, ushort maxSliceLength, ReadOnlyMemory<byte> remaining, ushort index)
{
bool isLastSlice = remaining.Length <= maxSliceLength;
ushort sliceLength = isLastSlice ? (ushort)remaining.Length : maxSliceLength;

// NB: For some reason, the slice index & length are inversed compared to the call to set the key image 🤷
buffer[10] = isLastSlice ? (byte)0x01 : (byte)0x00;
LittleEndian.Write(ref buffer[11], index);
LittleEndian.Write(ref buffer[13], sliceLength);
remaining.Span[..sliceLength].CopyTo(buffer[16..]);

return remaining[sliceLength..];
}

var remaining = data;

remaining = PrepareRequest(buffer.Span, x, y, width, height, maxSliceLength, remaining);
ushort index = 0;
while (true)
{
await _stream.WriteAsync(buffer, cancellationToken).ConfigureAwait(false);
if (remaining.Length == 0) break;
remaining = UpdateRequest(buffer.Span, maxSliceLength, remaining, ++index);
}
}

public async Task SetScreenSaverImageDataAsync(ReadOnlyMemory<byte> data, CancellationToken cancellationToken)
{
var buffer = WriteBuffer;
Expand All @@ -339,8 +384,8 @@ static ReadOnlyMemory<byte> UpdateRequest(Span<byte> buffer, ushort maxSliceLeng

// NB: For some reason, the slice index & length are inversed compared to the call to set the key image 🤷
buffer[3] = isLastSlice ? (byte)0x01 : (byte)0x00;
Unsafe.WriteUnaligned(ref buffer[4], BitConverter.IsLittleEndian ? index : BinaryPrimitives.ReverseEndianness(index));
Unsafe.WriteUnaligned(ref buffer[6], BitConverter.IsLittleEndian ? sliceLength : BinaryPrimitives.ReverseEndianness(sliceLength));
LittleEndian.Write(ref buffer[4], index);
LittleEndian.Write(ref buffer[6], sliceLength);
remaining.Span[..sliceLength].CopyTo(buffer[8..]);

return remaining[sliceLength..];
Expand Down

0 comments on commit fc14c56

Please sign in to comment.