-
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.
- Loading branch information
Showing
7 changed files
with
334 additions
and
1 deletion.
There are no files selected for viewing
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() } | ||
} |
137 changes: 137 additions & 0 deletions
137
src/commonMain/kotlin/io/rebble/libpebblecommon/packets/PutBytes.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,137 @@ | ||
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.SBytes | ||
import io.rebble.libpebblecommon.structmapper.SNullTerminatedString | ||
import io.rebble.libpebblecommon.structmapper.SUByte | ||
import io.rebble.libpebblecommon.structmapper.SUInt | ||
|
||
sealed class PutBytesOutgoingPacket(command: PutBytesCommand) : | ||
PebblePacket(ProtocolEndpoint.PUT_BYTES) { | ||
/** | ||
* Request command. See [PutBytesCommand]. | ||
*/ | ||
val command = SUByte(m, command.value) | ||
|
||
} | ||
|
||
class PutBytesResponse : PebblePacket(ProtocolEndpoint.PUT_BYTES) { | ||
|
||
/** | ||
* See [PutBytesResult] | ||
*/ | ||
val result = SUByte(m) | ||
|
||
/** | ||
* Cookie to send to all other put bytes requests | ||
*/ | ||
val cookie = SUInt(m) | ||
} | ||
|
||
/** | ||
* Send to init non-app related file transfer | ||
*/ | ||
class PutBytesInit( | ||
objectSize: UInt, | ||
objectType: ObjectType, | ||
bank: UByte, | ||
filename: String | ||
) : PutBytesOutgoingPacket(PutBytesCommand.INIT) { | ||
val objectSize = SUInt(m, objectSize) | ||
val objectType = SUByte(m, objectType.value) | ||
val bank = SUByte(m, bank) | ||
val filename = SNullTerminatedString(m, filename) | ||
} | ||
|
||
/** | ||
* Send to init app-specific file transfer. | ||
*/ | ||
class PutBytesAppInit( | ||
objectSize: UInt, | ||
objectType: ObjectType, | ||
appId: UInt | ||
) : PutBytesOutgoingPacket(PutBytesCommand.INIT) { | ||
val objectSize = SUInt(m, objectSize) | ||
|
||
// Object type in app init packet must have 8th bit set (?) | ||
val objectType = SUByte(m, objectType.value or (1u shl 7).toUByte()) | ||
val appId = SUInt(m, appId) | ||
} | ||
|
||
/** | ||
* Send file data to the watch. After every put you have to wait for response from the watch. | ||
*/ | ||
class PutBytesPut( | ||
cookie: UInt, | ||
payload: UByteArray | ||
) : PutBytesOutgoingPacket(PutBytesCommand.PUT) { | ||
val cookie = SUInt(m, cookie) | ||
val payloadSize = SUInt(m, payload.size.toUInt()) | ||
val payload = SBytes(m, payload.size, payload) | ||
} | ||
|
||
/** | ||
* Sent when current file transfer is complete. [objectCrc] is the CRC32 hash of the sent payload. | ||
*/ | ||
class PutBytesCommit( | ||
cookie: UInt, | ||
objectCrc: UInt | ||
) : PutBytesOutgoingPacket(PutBytesCommand.COMMIT) { | ||
val cookie = SUInt(m, cookie) | ||
val objectCrc = SUInt(m, objectCrc) | ||
} | ||
|
||
/** | ||
* Send when there was an error during transfer and transfer cannot complete. | ||
*/ | ||
class PutBytesAbort( | ||
cookie: UInt | ||
) : PutBytesOutgoingPacket(PutBytesCommand.ABORT) { | ||
val cookie = SUInt(m, cookie) | ||
} | ||
|
||
/** | ||
* Send after app-related file was commited to complete install sequence | ||
*/ | ||
class PutBytesInstall( | ||
cookie: UInt | ||
) : PutBytesOutgoingPacket(PutBytesCommand.INSTALL) { | ||
val cookie = SUInt(m, cookie) | ||
} | ||
|
||
enum class PutBytesCommand(val value: UByte) { | ||
INIT(0x01u), | ||
PUT(0x02u), | ||
COMMIT(0x03u), | ||
ABORT(0x04u), | ||
INSTALL(0x05u) | ||
} | ||
|
||
enum class PutBytesResult(val value: UByte) { | ||
ACK(0x01u), | ||
NACK(0x02u) | ||
} | ||
|
||
enum class ObjectType(val value: UByte) { | ||
FIRMWARE(0x01u), | ||
RECOVERY(0x02u), | ||
SYSTEM_RESOURCE(0x03u), | ||
APP_RESOURCE(0x04u), | ||
APP_EXECUTABLE(0x05u), | ||
FILE(0x06u), | ||
WORKER(0x07u) | ||
} | ||
|
||
fun putBytesIncomingPacketsRegister() { | ||
PacketRegistry.register( | ||
ProtocolEndpoint.PUT_BYTES, | ||
PutBytesResult.ACK.value, | ||
) { PutBytesResponse() } | ||
|
||
PacketRegistry.register( | ||
ProtocolEndpoint.PUT_BYTES, | ||
PutBytesResult.NACK.value, | ||
) { PutBytesResponse() } | ||
} |
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
29 changes: 29 additions & 0 deletions
29
src/commonMain/kotlin/io/rebble/libpebblecommon/services/AppFetchService.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,29 @@ | ||
package io.rebble.libpebblecommon.services | ||
|
||
import io.rebble.libpebblecommon.ProtocolHandler | ||
import io.rebble.libpebblecommon.packets.AppFetchIncomingPacket | ||
import io.rebble.libpebblecommon.packets.AppFetchOutgoingPacket | ||
import io.rebble.libpebblecommon.protocolhelpers.PebblePacket | ||
import io.rebble.libpebblecommon.protocolhelpers.ProtocolEndpoint | ||
import kotlinx.coroutines.channels.Channel | ||
|
||
class AppFetchService(private val protocolHandler: ProtocolHandler) : ProtocolService { | ||
val receivedMessages = Channel<AppFetchIncomingPacket>(Channel.BUFFERED) | ||
|
||
init { | ||
protocolHandler.registerReceiveCallback(ProtocolEndpoint.APP_FETCH, this::receive) | ||
} | ||
|
||
suspend fun send(packet: AppFetchOutgoingPacket) { | ||
protocolHandler.send(packet) | ||
} | ||
|
||
fun receive(packet: PebblePacket) { | ||
if (packet !is AppFetchIncomingPacket) { | ||
throw IllegalStateException("Received invalid packet type: $packet") | ||
} | ||
|
||
receivedMessages.offer(packet) | ||
} | ||
|
||
} |
29 changes: 29 additions & 0 deletions
29
src/commonMain/kotlin/io/rebble/libpebblecommon/services/PutBytesService.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,29 @@ | ||
package io.rebble.libpebblecommon.services | ||
|
||
import io.rebble.libpebblecommon.ProtocolHandler | ||
import io.rebble.libpebblecommon.packets.PutBytesOutgoingPacket | ||
import io.rebble.libpebblecommon.packets.PutBytesResponse | ||
import io.rebble.libpebblecommon.protocolhelpers.PebblePacket | ||
import io.rebble.libpebblecommon.protocolhelpers.ProtocolEndpoint | ||
import kotlinx.coroutines.channels.Channel | ||
|
||
class PutBytesService(private val protocolHandler: ProtocolHandler) : ProtocolService { | ||
val receivedMessages = Channel<PutBytesResponse>(Channel.BUFFERED) | ||
|
||
init { | ||
protocolHandler.registerReceiveCallback(ProtocolEndpoint.PUT_BYTES, this::receive) | ||
} | ||
|
||
suspend fun send(packet: PutBytesOutgoingPacket) { | ||
protocolHandler.send(packet) | ||
} | ||
|
||
fun receive(packet: PebblePacket) { | ||
if (packet !is PutBytesResponse) { | ||
throw IllegalStateException("Received invalid packet type: $packet") | ||
} | ||
|
||
receivedMessages.offer(packet) | ||
} | ||
|
||
} |
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
29 changes: 29 additions & 0 deletions
29
src/commonMain/kotlin/io/rebble/libpebblecommon/util/PacketSize.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,29 @@ | ||
package io.rebble.libpebblecommon.util | ||
|
||
import io.rebble.libpebblecommon.packets.ProtocolCapsFlag | ||
import io.rebble.libpebblecommon.packets.WatchVersion | ||
import io.rebble.libpebblecommon.protocolhelpers.ProtocolEndpoint | ||
|
||
fun getMaxPebblePacketPayloadSize( | ||
endpoint: ProtocolEndpoint, | ||
watchVersion: WatchVersion.WatchVersionResponse? | ||
): Int { | ||
if (endpoint != ProtocolEndpoint.APP_MESSAGE) { | ||
return STANDARD_MAX_PEBBLE_PACKET_SIZE | ||
} | ||
|
||
val capabilities = watchVersion?.capabilities?.let { ProtocolCapsFlag.fromFlags(it.get()) } | ||
|
||
return if (capabilities?.contains(ProtocolCapsFlag.Supports8kAppMessage) == true) { | ||
8222 | ||
} else { | ||
STANDARD_MAX_PEBBLE_PACKET_SIZE | ||
} | ||
} | ||
|
||
fun getPutBytesMaximumDataSize(watchVersion: WatchVersion.WatchVersionResponse?): Int { | ||
// 4 bytes get used for the cookie | ||
return getMaxPebblePacketPayloadSize(ProtocolEndpoint.PUT_BYTES, watchVersion) - 4 | ||
} | ||
|
||
val STANDARD_MAX_PEBBLE_PACKET_SIZE = 2048 |