-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from matejdro/apps
App install
- Loading branch information
Showing
15 changed files
with
716 additions
and
3 deletions.
There are no files selected for viewing
140 changes: 140 additions & 0 deletions
140
src/commonMain/kotlin/io/rebble/libpebblecommon/disk/PbwBinHeader.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
package io.rebble.libpebblecommon.disk | ||
|
||
import io.rebble.libpebblecommon.packets.blobdb.AppMetadata | ||
import io.rebble.libpebblecommon.structmapper.* | ||
import io.rebble.libpebblecommon.util.DataBuffer | ||
|
||
/** | ||
* Header of the | ||
*/ | ||
class PbwBinHeader() : StructMappable() { | ||
/** | ||
* Major header version. | ||
*/ | ||
val headerVersionMajor: SUByte = SUByte(m) | ||
|
||
/** | ||
* Minor header version. | ||
*/ | ||
val headerVersionMinor: SUByte = SUByte(m) | ||
|
||
/** | ||
* Major sdk version. | ||
*/ | ||
val sdkVersionMajor: SUByte = SUByte(m) | ||
|
||
/** | ||
* Minor sdk version. | ||
*/ | ||
val sdkVersionMinor: SUByte = SUByte(m) | ||
|
||
/** | ||
* Major app version. | ||
*/ | ||
val appVersionMajor: SUByte = SUByte(m) | ||
|
||
/** | ||
* Minor app version. | ||
*/ | ||
val appVersionMinor: SUByte = SUByte(m) | ||
|
||
/** | ||
* Size of the app payload in bytes | ||
*/ | ||
val appSize: SUShort = SUShort(m) | ||
|
||
/** | ||
* ??? (Presumably offset where app payload starts?) | ||
*/ | ||
val appOffset: SUInt = SUInt(m) | ||
|
||
/** | ||
* CRC checksum of the app payload | ||
*/ | ||
val crc: SUInt = SUInt(m) | ||
|
||
/** | ||
* Name of the app | ||
*/ | ||
val appName: SFixedString = SFixedString(m, 32) | ||
|
||
/** | ||
* Name of the company that made the app | ||
*/ | ||
val companyName: SFixedString = SFixedString(m, 32) | ||
|
||
/** | ||
* Resource ID of the primary icon. | ||
*/ | ||
val icon: SUInt = SUInt(m) | ||
|
||
/** | ||
* ??? | ||
*/ | ||
val symbolTableAddress: SUInt = SUInt(m) | ||
|
||
/** | ||
* List of app install flags. Should be forwarded to the watch when inserting into BlobDB. | ||
*/ | ||
val flags: SUInt = SUInt(m) | ||
|
||
/** | ||
* ??? | ||
*/ | ||
val numRelocationListEntries: SUInt = SUInt(m) | ||
|
||
/** | ||
* UUID of the app | ||
*/ | ||
val uuid: SUUID = SUUID(m) | ||
|
||
fun toBlobDbApp(): AppMetadata { | ||
return AppMetadata().also { | ||
it.uuid.set(uuid.get()) | ||
it.flags.set(flags.get()) | ||
it.icon.set(icon.get()) | ||
it.appVersionMajor.set(appVersionMajor.get()) | ||
it.appVersionMinor.set(appVersionMinor.get()) | ||
it.sdkVersionMajor.set(sdkVersionMajor.get()) | ||
it.sdkVersionMinor.set(sdkVersionMinor.get()) | ||
it.appName.set(appName.get()) | ||
} | ||
} | ||
|
||
companion object { | ||
const val SIZE: Int = 8 + 2 + 2 + 2 + 2 + 4 + 4 + 32 + 32 + 4 + 4 + 4 + 4 + 16 | ||
|
||
/** | ||
* Parse existing Pbw binary payload header. You should read [SIZE] bytes from the binary | ||
* payload and pass it into this method. | ||
* | ||
* @throws IllegalArgumentException if header is not valid pebble app header | ||
*/ | ||
fun parseFileHeader(data: UByteArray): PbwBinHeader { | ||
if (data.size != SIZE) { | ||
throw IllegalArgumentException( | ||
"Read data from the file should be exactly $SIZE bytes" | ||
) | ||
} | ||
|
||
val buffer = DataBuffer(data) | ||
|
||
val sentinel = buffer.getBytes(8) | ||
if (!sentinel.contentEquals(EXPECTED_SENTINEL)) { | ||
throw IllegalArgumentException("Sentinel does not match") | ||
} | ||
|
||
return PbwBinHeader().also { | ||
it.fromBytes(buffer) | ||
} | ||
} | ||
|
||
/** | ||
* First 8 bytes of the header, spelling the word "PBLAPP" in ASCII, | ||
* followed by two zeros. | ||
*/ | ||
private val EXPECTED_SENTINEL = ubyteArrayOf( | ||
0x50u, 0x42u, 0x4Cu, 0x41u, 0x50u, 0x50u, 0x00u, 0x00u | ||
) | ||
} | ||
} |
33 changes: 33 additions & 0 deletions
33
src/commonMain/kotlin/io/rebble/libpebblecommon/metadata/WatchHardwarePlatform.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
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); | ||
|
||
companion object { | ||
fun fromProtocolNumber(number: UByte): WatchHardwarePlatform? { | ||
return values().firstOrNull { it.protocolNumber == number } | ||
} | ||
} | ||
} |
9 changes: 9 additions & 0 deletions
9
src/commonMain/kotlin/io/rebble/libpebblecommon/metadata/WatchType.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package io.rebble.libpebblecommon.metadata | ||
|
||
enum class WatchType(val codename: String) { | ||
APLITE("aplite"), | ||
BASALT("basalt"), | ||
CHALK("chalk"), | ||
DIORITE("diorite"), | ||
EMERY("emery") | ||
} |
89 changes: 89 additions & 0 deletions
89
src/commonMain/kotlin/io/rebble/libpebblecommon/packets/AppFetch.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package io.rebble.libpebblecommon.packets | ||
|
||
import io.rebble.libpebblecommon.protocolhelpers.PacketRegistry | ||
import io.rebble.libpebblecommon.protocolhelpers.PebblePacket | ||
import io.rebble.libpebblecommon.protocolhelpers.ProtocolEndpoint | ||
import io.rebble.libpebblecommon.structmapper.SUByte | ||
import io.rebble.libpebblecommon.structmapper.SUInt | ||
import io.rebble.libpebblecommon.structmapper.SUUID | ||
|
||
sealed class AppFetchIncomingPacket() : PebblePacket(ProtocolEndpoint.APP_FETCH) { | ||
/** | ||
* Request command. See [AppFetchRequestCommand]. | ||
*/ | ||
val command = SUByte(m) | ||
|
||
} | ||
|
||
sealed class AppFetchOutgoingPacket(command: AppFetchRequestCommand) : | ||
PebblePacket(ProtocolEndpoint.APP_FETCH) { | ||
/** | ||
* Request command. See [AppFetchRequestCommand]. | ||
*/ | ||
val command = SUByte(m, command.value) | ||
|
||
} | ||
|
||
|
||
/** | ||
* Packet sent from the watch when user opens an app that is not in the watch storage. | ||
*/ | ||
class AppFetchRequest : AppFetchIncomingPacket() { | ||
|
||
/** | ||
* UUID of the app to request | ||
*/ | ||
val uuid = SUUID(m) | ||
|
||
/** | ||
* ID of the app bank. Use in the [PutBytesAppInit] packet to identify this app install. | ||
*/ | ||
val appId = SUInt(m, endianness = '<') | ||
} | ||
|
||
/** | ||
* Packet sent from the watch when user opens an app that is not in the watch storage. | ||
*/ | ||
class AppFetchResponse( | ||
status: AppFetchResponseStatus | ||
) : AppFetchOutgoingPacket(AppFetchRequestCommand.FETCH_APP) { | ||
/** | ||
* Response status | ||
*/ | ||
val status = SUByte(m, status.value) | ||
|
||
} | ||
|
||
enum class AppFetchRequestCommand(val value: UByte) { | ||
FETCH_APP(0x01u) | ||
} | ||
|
||
enum class AppFetchResponseStatus(val value: UByte) { | ||
/** | ||
* Sent right before starting to send PutBytes data | ||
*/ | ||
START(0x01u), | ||
|
||
/** | ||
* Sent when phone PutBytes is already busy sending something else | ||
*/ | ||
BUSY(0x02u), | ||
|
||
/** | ||
* Sent when UUID that watch sent is not in the locker | ||
*/ | ||
INVALID_UUID(0x03u), | ||
|
||
/** | ||
* Sent when there is generic data sending error (such as failure to read the local pbw file) | ||
*/ | ||
NO_DATA(0x01u), | ||
} | ||
|
||
|
||
fun appFetchIncomingPacketsRegister() { | ||
PacketRegistry.register( | ||
ProtocolEndpoint.APP_FETCH, | ||
AppFetchRequestCommand.FETCH_APP.value | ||
) { AppFetchRequest() } | ||
} |
Oops, something went wrong.