pebble/tests/fw/services/test_smartstrap_comms.c
2025-01-27 11:38:16 -08:00

227 lines
7.9 KiB
C

/*
* 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 "clar.h"
#include "services/normal/accessory/smartstrap_comms.h"
#include "util/mbuf.h"
#include <string.h>
#include "stubs_freertos.h"
#include "stubs_logging.h"
#include "stubs_mutex.h"
#include "stubs_passert.h"
#include "stubs_serial.h"
#include "fake_accessory.h"
#include "fake_new_timer.h"
#include "fake_smartstrap_profiles.h"
#include "fake_smartstrap_state.h"
#include "fake_system_task.h"
// Fakes
static struct {
bool enabled;
int after_bytes;
} s_faked_bus_contention;
bool accessory_bus_contention_detected(void) {
return s_faked_bus_contention.enabled && (s_faked_bus_contention.after_bytes-- <= 0);
}
// Setup
void test_smartstrap_comms__initialize(void) {
smartstrap_comms_init();
s_faked_bus_contention.enabled = false;
}
void test_smartstrap_comms__cleanup(void) {
}
// Helper functions
static void prv_do_send(MBuf *write_mbuf, MBuf *read_mbuf, uint8_t *expect_data,
int expect_length) {
// send the data out the smartstrap port
smartstrap_fsm_state_reset();
smartstrap_state_lock();
SmartstrapResult result = smartstrap_send(SmartstrapProfileRawData, write_mbuf, read_mbuf, 1000);
smartstrap_state_unlock();
cl_assert(result == SmartstrapResultOk);
if (read_mbuf) {
cl_assert(smartstrap_fsm_state_get() == SmartstrapStateReadInProgress);
} else {
cl_assert(smartstrap_fsm_state_get() == SmartstrapStateReadReady);
}
// verify the data that was sent out the accessory port
uint8_t *buffer;
int length;
fake_accessory_get_buffer(&buffer, &length);
cl_assert(length == expect_length);
for (int i = 0; i < length; i++) {
cl_assert(buffer[i] == expect_data[i]);
}
}
static void prv_do_send_bus_contention(MBuf *write_mbuf, MBuf *read_mbuf, uint8_t *expect_data,
int expect_length) {
const int BUS_CONTENTION_AFTER = 5;
// setup faked bus contention
s_faked_bus_contention.enabled = true;
s_faked_bus_contention.after_bytes = BUS_CONTENTION_AFTER;
// send the data out the smartstrap port
smartstrap_fsm_state_reset();
smartstrap_state_lock();
SmartstrapResult result = smartstrap_send(SmartstrapProfileRawData, write_mbuf, read_mbuf, 1000);
smartstrap_state_unlock();
cl_assert(result == SmartstrapResultBusy);
cl_assert(smartstrap_fsm_state_get() == SmartstrapStateReadReady);
// verify the data that was sent out the accessory port
uint8_t *buffer;
int length;
fake_accessory_get_buffer(&buffer, &length);
cl_assert(length == BUS_CONTENTION_AFTER + 1);
for (int i = 0; i < length; i++) {
cl_assert(buffer[i] == expect_data[i]);
}
}
static void prv_do_read(uint8_t *data, int length, MBuf *read_mbuf, uint8_t *expect_data,
int expect_length) {
for (int i = 0; i < length; i++) {
smartstrap_handle_data_from_isr(data[i]);
}
fake_system_task_callbacks_invoke_pending();
fake_smartstrap_profiles_check_read_params(true, SmartstrapProfileRawData, expect_length);
uint8_t *read_data = mbuf_get_data(read_mbuf);
int read_length = mbuf_get_length(read_mbuf);
cl_assert(read_length == expect_length);
for (int i = 0; i < read_length; i++) {
cl_assert(read_data[i] == expect_data[i]);
}
}
static void prv_do_read_notify(uint8_t *data, int length) {
for (int i = 0; i < length; i++) {
smartstrap_handle_data_from_isr(data[i]);
}
fake_system_task_callbacks_invoke_pending();
cl_assert(smartstrap_fsm_state_get() == SmartstrapStateReadReady);
fake_smartstrap_profiles_check_notify_params(true, SmartstrapProfileRawData);
}
// Tests
void test_smartstrap_comms__send_receive_data(void) {
// write Mbuf
MBuf write_mbuf = MBUF_EMPTY;
uint8_t test_data[] = {0x00, 0x01};
mbuf_set_data(&write_mbuf, test_data, sizeof(test_data));
// read mbuf
MBuf read_mbuf = MBUF_EMPTY;
uint8_t read_data[sizeof(test_data)] = {0};
mbuf_set_data(&read_mbuf, read_data, sizeof(read_data));
// expected on-the-wire data for send
uint8_t expected[] = {0x7E, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0xEF, 0x7E};
// faked on-the-wire data for response
uint8_t response_raw[] = {0x7E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x43, 0x7E};
// send the rquest
prv_do_send(&write_mbuf, &read_mbuf, expected, sizeof(expected));
// process the fake response
prv_do_read(response_raw, sizeof(response_raw), &read_mbuf, test_data, sizeof(test_data));
}
void test_smartstrap_comms__send_receive_escaped_data(void) {
// write Mbuf
MBuf write_mbuf = MBUF_EMPTY;
uint8_t test_data[] = {0x7D, 0x7E, 0x00, 0x7E, 0x7D, 0x00};
mbuf_set_data(&write_mbuf, test_data, sizeof(test_data));
// read MBuf
MBuf read_mbuf = MBUF_EMPTY;
uint8_t read_data[sizeof(test_data)] = {0};
mbuf_set_data(&read_mbuf, read_data, sizeof(read_data));
// expected on-the-wire data from send
uint8_t send_raw[] = {0x7E, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x7D, 0x5D, 0x7D, 0x5E,
0x00, 0x7D, 0x5E, 0x7D, 0x5D, 0x00, 0x59, 0x7E};
// faked on-the-wire data for response
uint8_t response_raw[] = {0x7E, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x7D, 0x5D, 0x7D, 0x5E,
0x00, 0x7D, 0x5E, 0x7D, 0x5D, 0x00, 0xC5, 0x7E};
// send the request
prv_do_send(&write_mbuf, &read_mbuf, send_raw, sizeof(send_raw));
// process the fake response
prv_do_read(response_raw, sizeof(response_raw), &read_mbuf, test_data, sizeof(test_data));
}
void test_smartstrap_comms__send_data(void) {
// write Mbuf
MBuf write_mbuf = MBUF_EMPTY;
uint8_t test_data[] = {0x01, 0x11};
mbuf_set_data(&write_mbuf, test_data, sizeof(test_data));
// expected on-the-wire data from send
uint8_t send_raw[] = {0x7E, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x11, 0xCC, 0x7E};
// send the write
prv_do_send(&write_mbuf, NULL, send_raw, sizeof(send_raw));
}
void test_smartstrap_comms__send_data_bus_contention(void) {
// write Mbuf
MBuf write_mbuf = MBUF_EMPTY;
uint8_t test_data[] = {0x01, 0x11};
mbuf_set_data(&write_mbuf, test_data, sizeof(test_data));
// expected on-the-wire data from send
uint8_t send_raw[] = {0x7E, 0x01, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x11, 0xCC, 0x7E};
// send the write
prv_do_send_bus_contention(&write_mbuf, NULL, send_raw, sizeof(send_raw));
}
void test_smartstrap_comms__send_receive_data_bus_contention(void) {
// write Mbuf
MBuf write_mbuf = MBUF_EMPTY;
uint8_t test_data[] = {0x01, 0x11};
mbuf_set_data(&write_mbuf, test_data, sizeof(test_data));
// read MBuf
MBuf read_mbuf = MBUF_EMPTY;
uint8_t read_data[sizeof(test_data)] = {0};
mbuf_set_data(&read_mbuf, read_data, sizeof(read_data));
// expected on-the-wire data from send
uint8_t send_raw[] = {0x7E, 0x01, 0x03, 0x00, 0x00, 0x00, 0x02, 0x00, 0x01, 0x11, 0xA8, 0x7E};
// send the write
prv_do_send_bus_contention(&write_mbuf, &read_mbuf, send_raw, sizeof(send_raw));
}
void test_smartstrap_comms__notification(void) {
// faked on-the-wire data for the context frame
uint8_t notify_context_raw[] = {0x7E, 0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x00, 0x76, 0x7E};
// send a break character
smartstrap_fsm_state_reset();
smartstrap_handle_break_from_isr();
fake_system_task_callbacks_invoke_pending();
cl_assert(smartstrap_fsm_state_get() == SmartstrapStateNotifyInProgress);
// process the fake context frame
prv_do_read_notify(notify_context_raw, sizeof(notify_context_raw));
}