mirror of
https://github.com/google/pebble.git
synced 2025-06-03 16:53:11 +00:00
147 lines
4.3 KiB
C
147 lines
4.3 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 <stdint.h>
|
|
#include <string.h>
|
|
|
|
#include "console/pulse_llc.h"
|
|
#include "console/pulse_protocol_impl.h"
|
|
|
|
#include "console/pulse_internal.h"
|
|
#include "util/attributes.h"
|
|
#include "util/math.h"
|
|
|
|
#define LLC_INMSG_LINK_ESTABLISHMENT_REQUEST (1)
|
|
#define LLC_INMSG_LINK_CLOSE_REQUEST (3)
|
|
#define LLC_INMSG_ECHO_REQUEST (5)
|
|
#define LLC_INMSG_CHANGE_BAUD (7)
|
|
|
|
#define LLC_OUTMSG_LINK_OPENED (2)
|
|
#define LLC_OUTMSG_LINK_CLOSED (4)
|
|
#define LLC_OUTMSG_ECHO_REPLY (6)
|
|
#define LLC_OUTMSG_INVALID_LLC_MESSAGE (128)
|
|
#define LLC_OUTMSG_UNKNOWN_PROTOCOL_NUMBER (129)
|
|
|
|
|
|
static void prv_bad_packet_response(uint8_t type, uint8_t bad_id, void *body,
|
|
size_t body_length);
|
|
static void prv_handle_change_baud(void *body, size_t body_length);
|
|
|
|
|
|
void pulse_llc_handler(void *packet, size_t length) {
|
|
if (!length) {
|
|
// Message too small; doesn't contain a type field.
|
|
uint8_t *message = pulse_best_effort_send_begin(PULSE_PROTOCOL_LLC);
|
|
*message = LLC_OUTMSG_INVALID_LLC_MESSAGE;
|
|
pulse_best_effort_send(message, sizeof(uint8_t));
|
|
return;
|
|
}
|
|
|
|
uint8_t type = *(uint8_t*)packet;
|
|
switch (type) {
|
|
case LLC_INMSG_LINK_ESTABLISHMENT_REQUEST:
|
|
pulse_llc_send_link_opened_msg();
|
|
return;
|
|
case LLC_INMSG_LINK_CLOSE_REQUEST:
|
|
pulse_end();
|
|
return;
|
|
case LLC_INMSG_ECHO_REQUEST:
|
|
*(uint8_t*)packet = LLC_OUTMSG_ECHO_REPLY;
|
|
|
|
uint8_t *message = pulse_best_effort_send_begin(PULSE_PROTOCOL_LLC);
|
|
memcpy(message, packet, length);
|
|
|
|
pulse_best_effort_send(message, length);
|
|
return;
|
|
case LLC_INMSG_CHANGE_BAUD:
|
|
prv_handle_change_baud((char*)packet + 1, length - 1);
|
|
return;
|
|
default:
|
|
prv_bad_packet_response(LLC_OUTMSG_INVALID_LLC_MESSAGE, type,
|
|
(char*)packet + 1, length - 1);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void pulse_llc_link_state_handler(PulseLinkState link_state) {
|
|
}
|
|
|
|
void pulse_llc_send_link_opened_msg(void) {
|
|
typedef struct PACKED Response {
|
|
uint8_t type;
|
|
uint8_t pulse_version;
|
|
uint16_t mtu;
|
|
uint16_t mru;
|
|
uint8_t timeout;
|
|
} Response;
|
|
|
|
Response *response = pulse_best_effort_send_begin(PULSE_PROTOCOL_LLC);
|
|
*response = (Response) {
|
|
.type = LLC_OUTMSG_LINK_OPENED,
|
|
.pulse_version = 1,
|
|
.mtu = PULSE_MAX_SEND_SIZE + PULSE_MIN_FRAME_LENGTH,
|
|
.mru = PULSE_MAX_RECEIVE_UNIT,
|
|
.timeout = PULSE_KEEPALIVE_TIMEOUT_DECISECONDS
|
|
};
|
|
|
|
pulse_best_effort_send(response, sizeof(Response));
|
|
}
|
|
|
|
void pulse_llc_send_link_closed_msg(void) {
|
|
uint8_t *link_close_response = pulse_best_effort_send_begin(
|
|
PULSE_PROTOCOL_LLC);
|
|
*link_close_response = LLC_OUTMSG_LINK_CLOSED;
|
|
|
|
pulse_best_effort_send(link_close_response, sizeof(uint8_t));
|
|
}
|
|
|
|
static void prv_bad_packet_response(uint8_t type, uint8_t bad_id, void *body,
|
|
size_t body_length) {
|
|
typedef struct PACKED Response {
|
|
uint8_t type;
|
|
uint8_t bad_identifier;
|
|
char body[8];
|
|
} Response;
|
|
|
|
Response *response = pulse_best_effort_send_begin(PULSE_PROTOCOL_LLC);
|
|
*response = (Response) {
|
|
.type = type,
|
|
.bad_identifier = bad_id
|
|
};
|
|
|
|
body_length = MIN(sizeof(response->body), body_length);
|
|
if (body_length) {
|
|
memcpy(response->body, body, body_length);
|
|
}
|
|
|
|
pulse_best_effort_send(response, 2 + body_length);
|
|
}
|
|
|
|
void pulse_llc_unknown_protocol_handler(uint8_t protocol, void *packet,
|
|
size_t length) {
|
|
prv_bad_packet_response(LLC_OUTMSG_UNKNOWN_PROTOCOL_NUMBER, protocol, packet,
|
|
length);
|
|
}
|
|
|
|
void prv_handle_change_baud(void *body, size_t body_length) {
|
|
if (body_length != sizeof(uint32_t)) {
|
|
// Don't send a response; the client will have already changed its receiver
|
|
// baud rate.
|
|
return;
|
|
}
|
|
uint32_t *new_baud = body;
|
|
pulse_change_baud_rate(*new_baud);
|
|
}
|