Skip to content

Commit

Permalink
Merge pull request #15 from crc-32/emulator
Browse files Browse the repository at this point in the history
Emulator packet support
  • Loading branch information
crc-32 authored Feb 16, 2021
2 parents a8316f7 + 6dd0699 commit 0e9eb76
Show file tree
Hide file tree
Showing 11 changed files with 80 additions and 15 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
kotlin.code.style=official

group=io.rebble.libpebblecommon
version=0.0.19
version=0.0.20
org.gradle.jvmargs=-Xms1G
4 changes: 4 additions & 0 deletions src/androidMain/kotlin/util/DataBuffer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,8 @@ actual class DataBuffer {
actualBuf.putLong(ulong.toLong())
}
actual fun getULong(): ULong = actualBuf.long.toULong()

actual fun rewind() {
actualBuf.rewind()
}
}
40 changes: 30 additions & 10 deletions src/commonMain/kotlin/io/rebble/libpebblecommon/packets/Emulator.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.rebble.libpebblecommon.packets

import io.rebble.libpebblecommon.exceptions.PacketDecodeException
import io.rebble.libpebblecommon.protocolhelpers.PebblePacket
import io.rebble.libpebblecommon.structmapper.SBytes
import io.rebble.libpebblecommon.structmapper.SUShort
import io.rebble.libpebblecommon.structmapper.StructMapper
Expand All @@ -10,35 +8,57 @@ import io.rebble.libpebblecommon.util.DataBuffer
const val HEADER_SIGNATURE = 0xFEEDU
const val FOOTER_SIGNATURE = 0xBEEFU

open class QemuInboundPacket {
open class QemuPacket(protocol: Protocol) {
val m = StructMapper()
val signature = SUShort(m, HEADER_SIGNATURE.toUShort())
val protocol = SUShort(m)
val protocol = SUShort(m, protocol.value)
val length = SUShort(m)

class QemuSPP: QemuInboundPacket() {
val payload = SBytes(m)
enum class Protocol(val value: UShort) {
SPP(1U),
Tap(2U),
BluetoothConnection(3U),
Compass(4U),
Battery(5U),
Accel(6U),
Vibration(7U),
Button(8U),
TimeFormat(9U),
TimelinePeek(10U),
ContentSize(11U),
RebbleTest(100U),
Invalid(UShort.MAX_VALUE)
}

class QemuSPP(data: UByteArray? = null): QemuPacket(Protocol.SPP) {
val payload = SBytes(m, data?.size?:-1, data?: ubyteArrayOf())
val footer = SUShort(m, FOOTER_SIGNATURE.toUShort())

init {
payload.linkWithSize(length)
if (data == null) payload.linkWithSize(length)
}
}

companion object {
fun deserialize(packet: UByteArray): QemuInboundPacket {
fun deserialize(packet: UByteArray): QemuPacket {
val buf = DataBuffer(packet)
val meta = StructMapper()
val header = SUShort(meta)
val protocol = SUShort(meta)
meta.fromBytes(buf)
buf.rewind()
return when (protocol.get()) {
1u.toUShort() -> QemuSPP().also { it.m.fromBytes(buf) }
Protocol.SPP.value -> QemuSPP().also { it.m.fromBytes(buf) }
else -> {
println("Warning: QEMU packet left generic")
QemuInboundPacket().also { it.m.fromBytes(buf) }
QemuPacket(Protocol.Invalid).also { it.m.fromBytes(buf) }
}
}
}
}

fun serialize(): UByteArray {
length.set((m.size-(4*UShort.SIZE_BYTES)).toUShort()) //total size - header+footer = payload length
return m.toBytes()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ class TimelineItem(
override fun toBytes(): UByteArray = m.toBytes()

override fun fromBytes(bytes: DataBuffer) = m.fromBytes(bytes)

override val size: Int
get() = m.size
}

class Attribute() : StructMappable() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,6 @@ abstract class StructMappable : Mappable {
override fun fromBytes(bytes: DataBuffer) {
m.fromBytes(bytes)
}

override val size get() = m.size
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.rebble.libpebblecommon.structmapper

import io.rebble.libpebblecommon.exceptions.PacketDecodeException
import io.rebble.libpebblecommon.util.DataBuffer

/**
Expand Down Expand Up @@ -34,8 +35,16 @@ class StructMapper: Mappable {
}

override fun fromBytes(bytes: DataBuffer) {
getStruct().forEach {
it.fromBytes(bytes)
getStruct().forEachIndexed { i: Int, mappable: Mappable ->
try {
mappable.fromBytes(bytes)
}catch (e: Exception) {
throw PacketDecodeException("Unable to deserialize mappable ${mappable::class.simpleName} at index $i (${mappable})", e)
}

}
}

override val size: Int
get() = getStruct().fold(0, {t,el -> t+el.size})
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ interface Mappable {
* @param bytes the data to read, seek position is incremented
*/
fun fromBytes(bytes: DataBuffer)

/**
* The projected size in bytes of the raw data returned by [toBytes]
*/
val size: Int
}

interface NumberStructElement {
Expand All @@ -41,15 +46,14 @@ open class StructElement<T>(
default: T,
endianness: Char = '|'
) : Mappable { //TODO: Element-level endianness on deserialization
var size = size
override var size = size
get() {
return linkedSize?.valueNumber?.toInt() ?: field
}
set(value) {
field = value
linkedSize = null
}

private var linkedSize: NumberStructElement? = null
private set

Expand Down Expand Up @@ -353,6 +357,9 @@ class SFixedList<T : Mappable>(
}
}

override val size: Int
get() = list.fold(0, {t,el -> t+el.size})

/**
* Link the count of this element to the value of another struct element. Count will
* automatically match value of the target element.
Expand Down Expand Up @@ -402,6 +409,9 @@ class SOptional<T>(
}
}

override val size: Int
get() = if (present) value.size else 0

fun get(): T? {
return if (present) value.get() else null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ expect class DataBuffer {

fun setEndian(endian: Char)

fun rewind()

/**
* Total length of the buffer
*/
Expand Down
7 changes: 7 additions & 0 deletions src/commonTest/kotlin/Tests.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import io.rebble.libpebblecommon.packets.PingPong
import io.rebble.libpebblecommon.packets.QemuPacket
import io.rebble.libpebblecommon.protocolhelpers.PebblePacket
import kotlin.test.Test
import kotlin.test.assertEquals
Expand Down Expand Up @@ -33,4 +34,10 @@ class Tests {

assertEquals(bytesToHex(expect), bytesToHex(packet.serialize()))
}

@Test
fun serializeQemuPacket() {
val packet = QemuPacket.QemuSPP(ubyteArrayOf(0xCAu,0xFEu,0x10u))
assertUByteArrayEquals(ubyteArrayOf(0xFEu, 0xEDu, 0x00u, 0x01u, 0x00u, 0x03u, 0xCAu, 0xFEu, 0x10u, 0xBEu, 0xEFu), packet.serialize())
}
}
4 changes: 4 additions & 0 deletions src/iosMain/kotlin/util/DataBuffer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,8 @@ actual class DataBuffer {
return pULong.value
}
}

actual fun rewind() {
TODO("iOS rewind buffer")
}
}
4 changes: 4 additions & 0 deletions src/jvmMain/kotlin/util/DataBuffer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,8 @@ actual class DataBuffer {
actualBuf.putLong(ulong.toLong())
}
actual fun getULong(): ULong = actualBuf.long.toULong()

actual fun rewind() {
actualBuf.rewind()
}
}

0 comments on commit 0e9eb76

Please sign in to comment.