mirror of
https://github.com/google/pebble
synced 2026-10-18 01:04:12 +02:00
Import of the watch repository from Pebble
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "applib/app_inbox.h"
|
||||
#include "util/attributes.h"
|
||||
|
||||
// Design goals of this module:
|
||||
//
|
||||
// - Provide a generic mechanism to pass variable-length data from a kernel service to app.
|
||||
// - Have the data be written directly into an app-provided buffer (in app space).
|
||||
// - Data is chunked up in "messages".
|
||||
// - Data must be contiguously stored for easy parsing (no circular buffer wrap-arounds).
|
||||
// - Support writing a message, while having pending, unconsumed message(s) in the buffer.
|
||||
// - Support starting to write a partial message, write some more and finally decide to cancel it.
|
||||
// The partial message should not get delivered.
|
||||
// - No race conditions can exist that could cause reading of an incomplete message.
|
||||
// - Support for notifying the app when data has been dropped (not enough buffer space) and
|
||||
// report the number of dropped messages.
|
||||
//
|
||||
// Non-goals:
|
||||
// - Sharing the same buffer between multiple kernel services (1:1 service to buffer relation is OK)
|
||||
// - Concurrently writing to the inbox from multiple tasks (failing the write up front when another
|
||||
// task is currently in the process of writing a message is OK)
|
||||
// - Preserve the ordering of when the dropped messages happened vs the received messages (it's OK
|
||||
// to only report the number of dropped messages)
|
||||
|
||||
typedef enum {
|
||||
AppInboxServiceTagInvalid = -1,
|
||||
AppInboxServiceTagAppMessageReceiver,
|
||||
#ifdef UNITTEST
|
||||
AppInboxServiceTagUnitTest,
|
||||
AppInboxServiceTagUnitTestAlt,
|
||||
#endif
|
||||
NumAppInboxServiceTag,
|
||||
} AppInboxServiceTag;
|
||||
|
||||
typedef struct PACKED {
|
||||
// Length of `data` payload (excluding the size of this header)
|
||||
size_t length;
|
||||
//! To give us some room for future changes. This structure ends up in a buffer that is sized by
|
||||
//! the app, so we can't easily increase the size of this once shipped.
|
||||
uint8_t padding[4];
|
||||
uint8_t data[];
|
||||
} AppInboxMessageHeader;
|
||||
|
||||
#ifndef UNITTEST
|
||||
_Static_assert(sizeof(AppInboxMessageHeader) == 8,
|
||||
"The size of AppInboxMessageHeader cannot grow beyond 8 bytes!");
|
||||
#endif
|
||||
|
||||
//! To be called once at boot.
|
||||
void app_inbox_service_init(void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Owner / Receiver (App) API
|
||||
|
||||
//! @param storage_size The size of the buffer (in app space). Note that a header will be appended
|
||||
//! to the data of sizeof(AppInboxMessageHeader) bytes.
|
||||
//! @note The event handler will be executed on the task that called this function.
|
||||
//! @see app_inbox_create_and_register() for the applib invocation.
|
||||
bool app_inbox_service_register(uint8_t *storage, size_t storage_size,
|
||||
AppInboxMessageHandler message_handler,
|
||||
AppInboxDroppedHandler dropped_handler, AppInboxServiceTag tag);
|
||||
|
||||
//! @return The number of messages that were dropped, plus the ones that were still waiting
|
||||
//! to be consumed.
|
||||
//! @see app_inbox_destroy_and_deregister() for the applib invocation.
|
||||
uint32_t app_inbox_service_unregister_by_storage(uint8_t *storage);
|
||||
|
||||
void app_inbox_service_unregister_all(void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Sender (Kernel) API
|
||||
|
||||
//! @param required_free_length The length in bytes of the data that needs to be written. Note that
|
||||
//! this should not include the size of the AppInboxMessageHeader. However, there must be at least
|
||||
//! (required_free_length + sizeof(AppInboxMessageHeader)) bytes free in the buffer in order to
|
||||
//! be able to write the message.
|
||||
//! @param writer Reference to the writer, just for debugging.
|
||||
//! @return True if the buffer is claimed successfully, false if not. If this function returns
|
||||
//! true, you MUST call app_inbox_service_end() at some point. Inversely, if this functions returns
|
||||
//! false, you MUST NOT call app_inbox_service_write() nor app_inbox_service_end() nor
|
||||
//! app_inbox_service_cancel().
|
||||
bool app_inbox_service_begin(AppInboxServiceTag tag, size_t required_free_length, void *writer);
|
||||
|
||||
//! @return True if the write was successful, false if not. If one write failed, successive writes
|
||||
//! will also fail and `app_inbox_service_end` will not actually dispatch the (broken) message,
|
||||
//! but instead just dispatch an event that data got dropped.
|
||||
bool app_inbox_service_write(AppInboxServiceTag tag, const uint8_t *data, size_t length);
|
||||
|
||||
//! @return True is the entire message was written successfully, false if not. If a partial write
|
||||
//! failed, the "dropped handler" will be invoked.
|
||||
bool app_inbox_service_end(AppInboxServiceTag tag);
|
||||
|
||||
void app_inbox_service_cancel(AppInboxServiceTag tag);
|
||||
Reference in New Issue
Block a user