mirror of
https://github.com/google/pebble.git
synced 2025-05-22 11:24:52 +00:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
208
src/fw/kernel/system_message.c
Normal file
208
src/fw/kernel/system_message.c
Normal file
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright 2024 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "kernel/system_message.h"
|
||||
|
||||
#include "flash_region/filesystem_regions.h"
|
||||
#include "kernel/events.h"
|
||||
#include "kernel/util/sleep.h"
|
||||
#include "process_management/worker_manager.h"
|
||||
#include "services/common/comm_session/protocol.h"
|
||||
#include "services/common/comm_session/session.h"
|
||||
#include "services/common/firmware_update.h"
|
||||
#include "services/common/i18n/i18n.h"
|
||||
#include "services/common/put_bytes/put_bytes.h"
|
||||
#include "services/common/system_task.h"
|
||||
#include "services/runlevel.h"
|
||||
#include "system/bootbits.h"
|
||||
#include "system/logging.h"
|
||||
#include "system/passert.h"
|
||||
#include "system/reboot_reason.h"
|
||||
#include "system/reset.h"
|
||||
#include "system/version.h"
|
||||
#include "util/attributes.h"
|
||||
#include "util/net.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
static const uint16_t ENDPOINT_ID = 0x12;
|
||||
|
||||
void system_message_send(SystemMessageType type) {
|
||||
uint8_t buffer[2] = { 0x00, type };
|
||||
CommSession *system_session = comm_session_get_system_session();
|
||||
comm_session_send_data(system_session, ENDPOINT_ID, buffer, sizeof(buffer), COMM_SESSION_DEFAULT_TIMEOUT);
|
||||
PBL_LOG(LOG_LEVEL_DEBUG, "Sending sysmsg: %u", type);
|
||||
}
|
||||
|
||||
static void prv_reset_kernel_bg_cb(void *unused) {
|
||||
PBL_LOG(LOG_LEVEL_ALWAYS, "Rebooting to install firmware...");
|
||||
RebootReason reason = { RebootReasonCode_SoftwareUpdate, 0 };
|
||||
reboot_reason_set(&reason);
|
||||
system_reset();
|
||||
}
|
||||
|
||||
static void prv_ui_update_reset_delay_timer_callback(void *unused) {
|
||||
system_task_add_callback(prv_reset_kernel_bg_cb, NULL);
|
||||
}
|
||||
|
||||
static void prv_handle_firmware_complete_msg(void) {
|
||||
uint32_t timeout = 3000;
|
||||
|
||||
// Wait 3 seconds before rebooting so there is time to show the update complete screen
|
||||
PBL_LOG(LOG_LEVEL_ALWAYS, "Delaying reset by 3s so the UI can update...");
|
||||
TimerID timer = new_timer_create(); // Don't bother cleaning up this timer, we're going to reset
|
||||
PBL_ASSERTN(timer != TIMER_INVALID_ID);
|
||||
new_timer_start(timer, timeout, prv_ui_update_reset_delay_timer_callback, NULL, 0);
|
||||
}
|
||||
|
||||
//! Note: For now we just call into storage directly for the status of FW installs. Someday,
|
||||
//! it would be nice for this exchange to take place as part of PutBytes
|
||||
extern bool pb_storage_get_status(PutBytesObjectType obj_type, PbInstallStatus *status);
|
||||
static void prv_handle_firmware_status_request(CommSession *session) {
|
||||
struct PACKED {
|
||||
uint8_t deprecated;
|
||||
uint8_t type;
|
||||
uint8_t rsvd[2];
|
||||
uint32_t resource_bytes_written;
|
||||
uint32_t resource_crc;
|
||||
uint32_t firmware_bytes_written;
|
||||
uint32_t firmware_crc;
|
||||
} fw_status_resp = {
|
||||
.type = SysMsgFirmwareStatusResponse,
|
||||
};
|
||||
|
||||
PbInstallStatus status = { };
|
||||
if (pb_storage_get_status(ObjectFirmware, &status)) {
|
||||
fw_status_resp.firmware_bytes_written = status.num_bytes_written;
|
||||
fw_status_resp.firmware_crc = status.crc_of_bytes;
|
||||
}
|
||||
|
||||
if (pb_storage_get_status(ObjectSysResources, &status)) {
|
||||
fw_status_resp.resource_bytes_written = status.num_bytes_written;
|
||||
fw_status_resp.resource_crc = status.crc_of_bytes;
|
||||
}
|
||||
|
||||
PBL_LOG(LOG_LEVEL_INFO, "FW Status Resp: res %"PRIu32" : 0x%x fw %"PRIu32" : 0x%x",
|
||||
fw_status_resp.resource_bytes_written, (int)fw_status_resp.resource_crc,
|
||||
fw_status_resp.firmware_bytes_written, (int)fw_status_resp.firmware_crc);
|
||||
|
||||
comm_session_send_data(session, ENDPOINT_ID, (uint8_t *)&fw_status_resp, sizeof(fw_status_resp),
|
||||
COMM_SESSION_DEFAULT_TIMEOUT);
|
||||
}
|
||||
|
||||
void sys_msg_protocol_msg_callback(CommSession *session, const uint8_t* data, size_t length) {
|
||||
PBL_ASSERT_RUNNING_FROM_EXPECTED_TASK(PebbleTask_KernelBackground);
|
||||
|
||||
SystemMessageType t = data[1];
|
||||
|
||||
PBL_LOG(LOG_LEVEL_DEBUG, "Received sysmsg: %u", t);
|
||||
|
||||
switch (t) {
|
||||
case SysMsgFirmwareAvailable_Deprecated: {
|
||||
PBL_LOG(LOG_LEVEL_DEBUG, "Deprecated available message received.");
|
||||
break;
|
||||
}
|
||||
|
||||
case SysMsgFirmwareStart: {
|
||||
PBL_LOG_VERBOSE("About to receive new firmware!");
|
||||
|
||||
uint32_t bytes_transferred = 0;
|
||||
uint32_t total_size = 0;
|
||||
|
||||
bool smooth_progress_supported =
|
||||
comm_session_has_capability(session, CommSessionSmoothFwInstallProgressSupport) &&
|
||||
(length >= sizeof(SysMsgSmoothFirmwareStartPayload));
|
||||
|
||||
if (smooth_progress_supported) {
|
||||
SysMsgSmoothFirmwareStartPayload *payload = (SysMsgSmoothFirmwareStartPayload *)data;
|
||||
bytes_transferred = payload->bytes_already_transferred;
|
||||
total_size = bytes_transferred + payload->bytes_to_transfer;
|
||||
PBL_LOG(LOG_LEVEL_INFO, "Starting FW update, %"PRIu32" of %"PRIu32" bytes already "
|
||||
"transferred", bytes_transferred, total_size);
|
||||
}
|
||||
|
||||
PebbleEvent e = {
|
||||
.type = PEBBLE_SYSTEM_MESSAGE_EVENT,
|
||||
.firmware_update = {
|
||||
.type = smooth_progress_supported ?
|
||||
PebbleSystemMessageFirmwareUpdateStart : PebbleSystemMessageFirmwareUpdateStartLegacy,
|
||||
.bytes_transferred = bytes_transferred,
|
||||
.total_transfer_size = total_size,
|
||||
}
|
||||
};
|
||||
event_put(&e);
|
||||
break;
|
||||
}
|
||||
|
||||
case SysMsgFirmwareStatus:
|
||||
prv_handle_firmware_status_request(session);
|
||||
break;
|
||||
|
||||
case SysMsgFirmwareComplete: {
|
||||
PBL_LOG_VERBOSE("Firmware transfer succeeded, okay to restart!");
|
||||
PebbleEvent e = {
|
||||
.type = PEBBLE_SYSTEM_MESSAGE_EVENT,
|
||||
.firmware_update.type = PebbleSystemMessageFirmwareUpdateComplete,
|
||||
};
|
||||
event_put(&e);
|
||||
prv_handle_firmware_complete_msg();
|
||||
break;
|
||||
}
|
||||
|
||||
case SysMsgFirmwareFail: {
|
||||
PBL_LOG_VERBOSE("Firmware transfer failed, time to clean up!");
|
||||
PebbleEvent e = {
|
||||
.type = PEBBLE_SYSTEM_MESSAGE_EVENT,
|
||||
.firmware_update.type = PebbleSystemMessageFirmwareUpdateFailed,
|
||||
};
|
||||
event_put(&e);
|
||||
break;
|
||||
}
|
||||
|
||||
case SysMsgFirmwareUpToDate: {
|
||||
PBL_LOG_VERBOSE("Firmware is up to date!");
|
||||
PebbleEvent e = {
|
||||
.type = PEBBLE_SYSTEM_MESSAGE_EVENT,
|
||||
.firmware_update.type = PebbleSystemMessageFirmwareUpToDate,
|
||||
};
|
||||
event_put(&e);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
PBL_LOG(LOG_LEVEL_ERROR, "Invalid message received, type is %u", data[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void system_message_send_firmware_start_response(FirmwareUpdateStatus status) {
|
||||
struct PACKED {
|
||||
uint8_t zero;
|
||||
uint8_t type;
|
||||
uint8_t status;
|
||||
} msg = {
|
||||
.zero = 0x00,
|
||||
.type = SysMsgFirmwareStartResponse,
|
||||
.status = status
|
||||
};
|
||||
|
||||
CommSession *session = comm_session_get_system_session();
|
||||
comm_session_send_data(session, ENDPOINT_ID, (const uint8_t*) &msg, sizeof(msg), COMM_SESSION_DEFAULT_TIMEOUT);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue