mirror of
https://github.com/google/pebble.git
synced 2025-06-09 03:33:11 +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
172
src/bluetooth-fw/qemu/qemu_transport.c
Normal file
172
src/bluetooth-fw/qemu/qemu_transport.c
Normal file
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* 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/event_loop.h"
|
||||
#include "kernel/events.h"
|
||||
#include "kernel/pbl_malloc.h"
|
||||
|
||||
#include "services/common/comm_session/session_transport.h"
|
||||
|
||||
#include "system/passert.h"
|
||||
#include "system/logging.h"
|
||||
|
||||
#include "comm/bt_lock.h"
|
||||
|
||||
#include "drivers/qemu/qemu_serial.h"
|
||||
#include "drivers/qemu/qemu_serial_private.h"
|
||||
|
||||
#include "util/math.h"
|
||||
|
||||
#include <bluetooth/qemu_transport.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef struct {
|
||||
CommSession *session;
|
||||
} QemuTransport;
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// Static Variables (protected by bt_lock)
|
||||
|
||||
//! The CommSession that the QEMU transport is managing.
|
||||
//! Currently there's only one for the System session.
|
||||
static QemuTransport s_transport;
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// bt_lock() is held by caller
|
||||
static void prv_send_next(Transport *transport) {
|
||||
CommSession *session = s_transport.session;
|
||||
PBL_ASSERTN(session);
|
||||
size_t bytes_remaining = comm_session_send_queue_get_length(session);
|
||||
if (bytes_remaining == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t temp_buffer_size = MIN(bytes_remaining, QEMU_MAX_DATA_LEN);
|
||||
uint8_t *temp_buffer = kernel_malloc_check(temp_buffer_size);
|
||||
while (bytes_remaining) {
|
||||
const size_t bytes_to_copy = MIN(bytes_remaining, temp_buffer_size);
|
||||
comm_session_send_queue_copy(session, 0 /* start_offset */, bytes_to_copy, temp_buffer);
|
||||
qemu_serial_send(QemuProtocol_SPP, temp_buffer, bytes_to_copy);
|
||||
comm_session_send_queue_consume(session, bytes_to_copy);
|
||||
bytes_remaining -= bytes_to_copy;
|
||||
}
|
||||
kernel_free(temp_buffer);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// bt_lock() is held by caller
|
||||
static void prv_reset(Transport *transport) {
|
||||
PBL_LOG(LOG_LEVEL_INFO, "Unimplemented");
|
||||
}
|
||||
|
||||
static void prv_granted_kernel_main_cb(void *ctx) {
|
||||
ResponsivenessGrantedHandler granted_handler = ctx;
|
||||
granted_handler();
|
||||
}
|
||||
|
||||
static void prv_set_connection_responsiveness(
|
||||
Transport *transport, BtConsumer consumer, ResponseTimeState state, uint16_t max_period_secs,
|
||||
ResponsivenessGrantedHandler granted_handler) {
|
||||
PBL_LOG(LOG_LEVEL_INFO, "Consumer %d: requesting change to %d for %" PRIu16 "seconds",
|
||||
consumer, state, max_period_secs);
|
||||
|
||||
// it's qemu, our request to bump the speed is always granted!
|
||||
if (granted_handler) {
|
||||
launcher_task_add_callback(prv_granted_kernel_main_cb, granted_handler);
|
||||
}
|
||||
}
|
||||
|
||||
static CommSessionTransportType prv_get_type(struct Transport *transport) {
|
||||
return CommSessionTransportType_QEMU;
|
||||
}
|
||||
|
||||
//! Defined in session.c
|
||||
extern void comm_session_set_capabilities(
|
||||
CommSession *session, CommSessionCapability capability_flags);
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
void qemu_transport_set_connected(bool is_connected) {
|
||||
bt_lock();
|
||||
|
||||
const bool transport_is_connected = (s_transport.session);
|
||||
if (transport_is_connected == is_connected) {
|
||||
bt_unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
static const TransportImplementation s_qemu_transport_implementation = {
|
||||
.send_next = prv_send_next,
|
||||
.reset = prv_reset,
|
||||
.set_connection_responsiveness = prv_set_connection_responsiveness,
|
||||
.get_type = prv_get_type,
|
||||
};
|
||||
|
||||
bool send_event = true;
|
||||
|
||||
if (is_connected) {
|
||||
s_transport.session = comm_session_open((Transport *) &s_transport,
|
||||
&s_qemu_transport_implementation,
|
||||
TransportDestinationHybrid);
|
||||
if (!s_transport.session) {
|
||||
PBL_LOG(LOG_LEVEL_ERROR, "CommSession couldn't be opened");
|
||||
send_event = false;
|
||||
}
|
||||
|
||||
// Give it the appropriate capabilities
|
||||
const CommSessionCapability capabilities = CommSessionRunState |
|
||||
CommSessionInfiniteLogDumping |
|
||||
CommSessionVoiceApiSupport |
|
||||
CommSessionAppMessage8kSupport;
|
||||
comm_session_set_capabilities(s_transport.session, capabilities);
|
||||
} else {
|
||||
comm_session_close(s_transport.session, CommSessionCloseReason_UnderlyingDisconnection);
|
||||
s_transport.session = NULL;
|
||||
}
|
||||
|
||||
if (send_event) {
|
||||
PebbleEvent e = {
|
||||
.type = PEBBLE_BT_CONNECTION_EVENT,
|
||||
.bluetooth = {
|
||||
.connection = {
|
||||
.state = (s_transport.session) ? PebbleBluetoothConnectionEventStateConnected
|
||||
: PebbleBluetoothConnectionEventStateDisconnected
|
||||
}
|
||||
}
|
||||
};
|
||||
event_put(&e);
|
||||
}
|
||||
|
||||
bt_unlock();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
bool qemu_transport_is_connected(void) {
|
||||
return (s_transport.session != NULL);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// Handle incoming Qemu-SPP packet data
|
||||
void qemu_transport_handle_received_data(const uint8_t *data, uint32_t length) {
|
||||
bt_lock();
|
||||
if (!s_transport.session) {
|
||||
PBL_LOG(LOG_LEVEL_ERROR, "Received QEMU serial data, but session not connected!");
|
||||
goto unlock;
|
||||
}
|
||||
comm_session_receive_router_write(s_transport.session, data, length);
|
||||
unlock:
|
||||
bt_unlock();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue