mirror of
https://github.com/google/pebble.git
synced 2025-06-16 06:33:14 +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
159
src/fw/applib/plugin_service.c
Normal file
159
src/fw/applib/plugin_service.c
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* 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 "event_service_client.h"
|
||||
#include "applib/applib_malloc.auto.h"
|
||||
#include "plugin_service.h"
|
||||
#include "plugin_service_private.h"
|
||||
#include "syscall/syscall.h"
|
||||
|
||||
#include "process_state/app_state/app_state.h"
|
||||
#include "process_state/worker_state/worker_state.h"
|
||||
#include "system/logging.h"
|
||||
#include "system/passert.h"
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// Get our state variables
|
||||
static PluginServiceState* prv_get_state(PebbleTask task) {
|
||||
if (task == PebbleTask_Unknown) {
|
||||
task = pebble_task_get_current();
|
||||
}
|
||||
if (task == PebbleTask_App) {
|
||||
return app_state_get_plugin_service();
|
||||
} else {
|
||||
PBL_ASSERTN(task == PebbleTask_Worker);
|
||||
return worker_state_get_plugin_service();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// Lookup the plugin service index from the UUID. We store the index in the event structure instead of the UUID
|
||||
// so that we have payload room.
|
||||
static uint16_t prv_get_service_index(Uuid *uuid) {
|
||||
return sys_event_service_get_plugin_service_index(uuid);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// Used by list_find to locate the handler for a specfic service index.
|
||||
static bool prv_service_filter(ListNode *node, void *tp) {
|
||||
PluginServiceEntry *info = (PluginServiceEntry *)node;
|
||||
uint16_t service_idx = (uint16_t)(uintptr_t)tp;
|
||||
return (info->service_index == service_idx);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// Callback provided to the app_event_service. All events of type PEBBLE_PLUGIN_SERVICE_EVENT that get sent to
|
||||
// this task trigger this callback. From here, we look up which user-supplied callback corresponds to the
|
||||
// service index stored in the event structure and then pass control to that user-supplied callback.
|
||||
static void prv_handle_event_service_event(PebbleEvent *e, void *context) {
|
||||
PluginServiceState *state = prv_get_state(PebbleTask_Unknown);
|
||||
uint16_t service_index = e->plugin_service.service_index;
|
||||
|
||||
ListNode *found;
|
||||
ListNode *list = &state->subscribed_services;
|
||||
found = list_find(list, prv_service_filter, (void*)(uintptr_t)service_index);
|
||||
if (!found) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Call the handler provided by the client
|
||||
PluginServiceEntry *entry = (PluginServiceEntry *)found;
|
||||
entry->handler(e->plugin_service.type, &e->plugin_service.data);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// Subscribe to a specific plug-in service by uuid.
|
||||
bool plugin_service_subscribe(Uuid *uuid, PluginServiceHandler handler) {
|
||||
PluginServiceState *state = prv_get_state(PebbleTask_Unknown);
|
||||
uint16_t service_index = prv_get_service_index(uuid);
|
||||
|
||||
ListNode *list = &state->subscribed_services;
|
||||
if (list_find(list, prv_service_filter, (void*)(uintptr_t)service_index)) {
|
||||
PBL_LOG(LOG_LEVEL_DEBUG, "Plug service handler already subscribed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add to handlers list
|
||||
PluginServiceEntry *entry = applib_type_zalloc(PluginServiceEntry);
|
||||
if (!entry) {
|
||||
PBL_LOG(LOG_LEVEL_ERROR, "OOM in plugin_service_subscribe");
|
||||
return false;
|
||||
}
|
||||
entry->service_index = service_index;
|
||||
entry->handler = handler;
|
||||
list_append(list, &entry->list_node);
|
||||
|
||||
// Subscribe to the app event service if we haven't already
|
||||
if (!state->subscribed_to_app_event_service) {
|
||||
state->subscribed_to_app_event_service = true;
|
||||
event_service_client_subscribe(&state->event_service_info);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// Unsubscribe from a specific plug-in service by uuid.
|
||||
bool plugin_service_unsubscribe(Uuid *uuid) {
|
||||
PluginServiceState *state = prv_get_state(PebbleTask_Unknown);
|
||||
uint16_t service_index = prv_get_service_index(uuid);
|
||||
|
||||
ListNode *found;
|
||||
ListNode *list = &state->subscribed_services;
|
||||
found = list_find(list, prv_service_filter, (void*)(uintptr_t)service_index);
|
||||
if (!found) {
|
||||
PBL_LOG(LOG_LEVEL_DEBUG, "Plug service handler already unsubscribed");
|
||||
return true;
|
||||
}
|
||||
|
||||
list_remove(found, NULL, NULL);
|
||||
applib_free(found);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// Send an event to all registered subscribers of the given plugin service identified by UUID.
|
||||
void plugin_service_send_event(Uuid *uuid, uint8_t type, PluginEventData *data) {
|
||||
uint16_t service_index = prv_get_service_index(uuid);
|
||||
|
||||
PebbleEvent event = {
|
||||
.type = PEBBLE_PLUGIN_SERVICE_EVENT,
|
||||
.plugin_service = {
|
||||
.service_index = service_index,
|
||||
.type = type,
|
||||
.data = *data
|
||||
},
|
||||
};
|
||||
sys_send_pebble_event_to_kernel(&event);
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------------------------------------------
|
||||
// Init our state variables.
|
||||
void plugin_service_state_init(PluginServiceState *state) {
|
||||
*state = (PluginServiceState) {
|
||||
.event_service_info = {
|
||||
.type = PEBBLE_PLUGIN_SERVICE_EVENT,
|
||||
.handler = &prv_handle_event_service_event,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue