Skip to content

Commit

Permalink
pbz reading, fw update messages, putbytes sendfwpart
Browse files Browse the repository at this point in the history
  • Loading branch information
crc-32 committed Apr 22, 2023
1 parent aa54ad6 commit b82e5e2
Show file tree
Hide file tree
Showing 9 changed files with 174 additions and 31 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
kotlin.code.style=official

group=io.rebble.libpebblecommon
version=0.1.8
version=0.1.9
org.gradle.jvmargs=-Xms128M -Xmx1G -XX:ReservedCodeCacheSize=200M
kotlin.native.binary.memoryModel=experimental
kotlin.mpp.androidSourceSetLayoutVersion=2
Original file line number Diff line number Diff line change
@@ -1,33 +1,64 @@
package io.rebble.libpebblecommon.metadata

enum class WatchHardwarePlatform(val protocolNumber: UByte, val watchType: WatchType) {
PEBBLE_ONE_EV_1(1u, WatchType.APLITE),
PEBBLE_ONE_EV_2(2u, WatchType.APLITE),
PEBBLE_ONE_EV_2_3(3u, WatchType.APLITE),
PEBBLE_ONE_EV_2_4(4u, WatchType.APLITE),
PEBBLE_ONE_POINT_FIVE(5u, WatchType.APLITE),
PEBBLE_ONE_POINT_ZERO(6u, WatchType.APLITE),
PEBBLE_SNOWY_EVT_2(7u, WatchType.BASALT),
PEBBLE_SNOWY_DVT(8u, WatchType.BASALT),
PEBBLE_BOBBY_SMILES(10u, WatchType.BASALT),
PEBBLE_ONE_BIGBOARD_2(254u, WatchType.APLITE),
PEBBLE_ONE_BIGBOARD(255u, WatchType.APLITE),
PEBBLE_SNOWY_BIGBOARD(253u, WatchType.BASALT),
PEBBLE_SNOWY_BIGBOARD_2(252u, WatchType.BASALT),
PEBBLE_SPALDING_EVT(9u, WatchType.CHALK),
PEBBLE_SPALDING_PVT(11u, WatchType.CHALK),
PEBBLE_SPALDING_BIGBOARD(251u, WatchType.CHALK),
PEBBLE_SILK_EVT(12u, WatchType.DIORITE),
PEBBLE_SILK(14u, WatchType.DIORITE),
PEBBLE_SILK_BIGBOARD(250u, WatchType.DIORITE),
PEBBLE_SILK_BIGBOARD_2_PLUS(248u, WatchType.DIORITE),
PEBBLE_ROBERT_EVT(13u, WatchType.EMERY),
PEBBLE_ROBERT_BIGBOARD(249u, WatchType.EMERY),
PEBBLE_ROBERT_BIGBOARD_2(247u, WatchType.EMERY);
import kotlinx.serialization.SerializationException
import kotlinx.serialization.Serializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlin.reflect.KClass

enum class WatchHardwarePlatform(val protocolNumber: UByte, val watchType: WatchType, val revision: String) {
PEBBLE_ONE_EV_1(1u, WatchType.APLITE, "ev1"),
PEBBLE_ONE_EV_2(2u, WatchType.APLITE, "ev2"),
PEBBLE_ONE_EV_2_3(3u, WatchType.APLITE, "ev2_3"),
PEBBLE_ONE_EV_2_4(4u, WatchType.APLITE, "ev2_4"),
PEBBLE_ONE_POINT_FIVE(5u, WatchType.APLITE, "v1_5"),
PEBBLE_ONE_POINT_ZERO(6u, WatchType.APLITE, "v1_0"),
PEBBLE_SNOWY_EVT_2(7u, WatchType.BASALT, "snowy_evt2"),
PEBBLE_SNOWY_DVT(8u, WatchType.BASALT, "snowy_dvt"),
PEBBLE_BOBBY_SMILES(10u, WatchType.BASALT, "snowy_s3"),
PEBBLE_ONE_BIGBOARD_2(254u, WatchType.APLITE, "unk"),
PEBBLE_ONE_BIGBOARD(255u, WatchType.APLITE, "unk"),
PEBBLE_SNOWY_BIGBOARD(253u, WatchType.BASALT, "unk"),
PEBBLE_SNOWY_BIGBOARD_2(252u, WatchType.BASALT, "unk"),
PEBBLE_SPALDING_EVT(9u, WatchType.CHALK, "spalding_evt"),
PEBBLE_SPALDING_PVT(11u, WatchType.CHALK, "spalding"),
PEBBLE_SPALDING_BIGBOARD(251u, WatchType.CHALK, "unk"),
PEBBLE_SILK_EVT(12u, WatchType.DIORITE, "silk_evt"),
PEBBLE_SILK(14u, WatchType.DIORITE, "silk"),
PEBBLE_SILK_BIGBOARD(250u, WatchType.DIORITE, "unk"),
PEBBLE_SILK_BIGBOARD_2_PLUS(248u, WatchType.DIORITE, "unk"),
PEBBLE_ROBERT_EVT(13u, WatchType.EMERY, "robert_evt"),
PEBBLE_ROBERT_BIGBOARD(249u, WatchType.EMERY, "unk"),
PEBBLE_ROBERT_BIGBOARD_2(247u, WatchType.EMERY, "unk");

companion object {
fun fromProtocolNumber(number: UByte): WatchHardwarePlatform? {
return values().firstOrNull { it.protocolNumber == number }
}

fun fromHWRevision(revision: String): WatchHardwarePlatform? {
if (revision == "unk") return null
return values().firstOrNull() { it.revision == revision }
}
}
}

@Serializer(WatchHardwarePlatform::class)
class WatchHardwarePlatformSerializer {
override val descriptor: SerialDescriptor
get() = PrimitiveSerialDescriptor("WatchHardwarePlatform", PrimitiveKind.STRING)

override fun deserialize(decoder: Decoder): WatchHardwarePlatform {
val revision = decoder.decodeString()
return WatchHardwarePlatform.fromHWRevision(revision) ?: throw SerializationException("Unknown hardware revision $revision")
}

override fun serialize(encoder: Encoder, value: WatchHardwarePlatform) {
val revision = value.revision
encoder.encodeString(revision)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.rebble.libpebblecommon.metadata.pbz.manifest

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class JsTooling(
@SerialName("bytecode_version")
val bytecodeVersion: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.rebble.libpebblecommon.metadata.pbz.manifest

import io.rebble.libpebblecommon.metadata.WatchHardwarePlatform
import io.rebble.libpebblecommon.metadata.WatchHardwarePlatformSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PbzFirmware(
val name: String,
val type: String,
val timestamp: Long,
val commit: String,
@Serializable(with = WatchHardwarePlatformSerializer::class)
@SerialName("hwrev")
val hwRev: WatchHardwarePlatform,
val size: Long,
val crc: Long,
val versionTag: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.rebble.libpebblecommon.metadata.pbz.manifest

import io.rebble.libpebblecommon.metadata.pbw.manifest.Debug
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class PbzManifest(
val manifestVersion: Int,
val generatedAt: Long,
val generatedBy: String,
val debug: Debug,
val firmware: PbzFirmware,
val resources: SystemResources,
@SerialName("js_tooling")
val jsTooling: JsTooling,
val type: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package io.rebble.libpebblecommon.metadata.pbz.manifest

import kotlinx.serialization.Serializable

@Serializable
data class SystemResources(
val name: String,
val timestamp: Long,
val size: Long,
val crc: Long
)
20 changes: 18 additions & 2 deletions src/commonMain/kotlin/io/rebble/libpebblecommon/packets/System.kt
Original file line number Diff line number Diff line change
Expand Up @@ -398,16 +398,27 @@ open class SystemMessage(message: Message) : SystemPacket(endpoint) {
}

val command = SUByte(m, message.value)
val messageType = SUByte(m)

init {
type = command.get()
TODO("Incomplete packet declaration")
}

companion object {
val endpoint = ProtocolEndpoint.SYSTEM_MESSAGE
}

class NewFirmwareAvailable: SystemMessage(Message.NewFirmwareAvailable)
class FirmwareUpdateStart: SystemMessage(Message.FirmwareUpdateStart)
class FirmwareUpdateComplete: SystemMessage(Message.FirmwareUpdateComplete)
class FirmwareUpdateFailed: SystemMessage(Message.FirmwareUpdateFailed)
class FirmwareUpToDate: SystemMessage(Message.FirmwareUpToDate)
class StopReconnecting: SystemMessage(Message.StopReconnecting)
class StartReconnecting: SystemMessage(Message.StartReconnecting)
class MAPDisabled: SystemMessage(Message.MAPDisabled)
class MAPEnabled: SystemMessage(Message.MAPEnabled)
class FirmwareUpdateStartResponse: SystemMessage(Message.FirmwareUpdateStartResponse) {
val response = SUByte(m)
}
}

class BLEControl(opcode: UByte = 0x4u, discoverable: Boolean, duration: UShort) : SystemPacket(
Expand Down Expand Up @@ -492,4 +503,9 @@ fun systemPacketsRegister() {

PacketRegistry.register(PingPong.endpoint, PingPong.Message.Ping.value) { PingPong.Ping() }
PacketRegistry.register(PingPong.endpoint, PingPong.Message.Pong.value) { PingPong.Pong() }

PacketRegistry.register(
SystemMessage.endpoint,
SystemMessage.Message.FirmwareUpdateStartResponse.value
) { SystemMessage.FirmwareUpdateStartResponse() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,35 @@ class PutBytesService(private val protocolHandler: ProtocolHandler) : ProtocolSe
logger.i { "Install complete" }
}

suspend fun sendFirmwarePart(
blob: ByteArray,
watchVersion: WatchVersion.WatchVersionResponse,
crc: Long,
size: UInt,
type: ObjectType,
fileName: String
) {
logger.i { "Send FW part $type ${type.value}" }
send(
PutBytesInit(size, type, 0u, fileName)
)

val cookie = awaitCookieAndPutByteArray(
blob,
crc,
watchVersion
)

logger.d { "Sending install" }

send(
PutBytesInstall(cookie)
)
awaitAck()

logger.i { "Install complete" }
}

suspend fun awaitCookieAndPutByteArray(
byteArray: ByteArray,
expectedCrc: Long?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ package io.rebble.libpebblecommon.services

import io.rebble.libpebblecommon.PacketPriority
import io.rebble.libpebblecommon.ProtocolHandler
import io.rebble.libpebblecommon.packets.PhoneAppVersion
import io.rebble.libpebblecommon.packets.SystemPacket
import io.rebble.libpebblecommon.packets.WatchFactoryData
import io.rebble.libpebblecommon.packets.WatchVersion
import io.rebble.libpebblecommon.packets.*
import io.rebble.libpebblecommon.protocolhelpers.PebblePacket
import io.rebble.libpebblecommon.protocolhelpers.ProtocolEndpoint
import io.rebble.libpebblecommon.structmapper.SInt
Expand All @@ -23,6 +20,7 @@ class SystemService(private val protocolHandler: ProtocolHandler) : ProtocolServ

private var watchVersionCallback: CompletableDeferred<WatchVersion.WatchVersionResponse>? = null
private var watchModelCallback: CompletableDeferred<UByteArray>? = null
private var firmwareUpdateStartResponseCallback: CompletableDeferred<SystemMessage.FirmwareUpdateStartResponse>? = null

init {
protocolHandler.registerReceiveCallback(ProtocolEndpoint.PHONE_VERSION, this::receive)
Expand Down Expand Up @@ -57,6 +55,16 @@ class SystemService(private val protocolHandler: ProtocolHandler) : ProtocolServ
return SInt(StructMapper()).also { it.fromBytes(DataBuffer(modelBytes)) }.get()
}

suspend fun firmwareUpdateStart(): UByte {
val callback = CompletableDeferred<SystemMessage.FirmwareUpdateStartResponse>()
firmwareUpdateStartResponseCallback = callback
send(SystemMessage.FirmwareUpdateStart())

val response = callback.await()

return response.response.get()
}

suspend fun receive(packet: PebblePacket) {
if (packet !is SystemPacket) {
throw IllegalStateException("Received invalid packet type: $packet")
Expand Down

0 comments on commit b82e5e2

Please sign in to comment.