From e37ac7bc77e5bae0076136033d3fbd345ba300e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=A4rkl?= Date: Thu, 4 Jul 2019 23:46:26 +0200 Subject: [PATCH] Feedback History working! --- gui/src/streamsession.cpp | 22 ++++++ lib/include/chiaki/controller.h | 25 +++++-- lib/include/chiaki/feedback.h | 40 ++++++++++- lib/include/chiaki/feedbacksender.h | 3 + lib/include/chiaki/takion.h | 4 ++ lib/src/feedback.c | 107 ++++++++++++++++++++++++++++ lib/src/feedbacksender.c | 85 ++++++++++++++++++++-- lib/src/mirai.c | 2 +- lib/src/takion.c | 74 ++++++++++++------- 9 files changed, 326 insertions(+), 36 deletions(-) diff --git a/gui/src/streamsession.cpp b/gui/src/streamsession.cpp index 3e5f0c3..89eb72a 100644 --- a/gui/src/streamsession.cpp +++ b/gui/src/streamsession.cpp @@ -117,6 +117,17 @@ void StreamSession::UpdateGamepads() connect(gamepad, &QGamepad::buttonBChanged, this, &StreamSession::SendFeedbackState); connect(gamepad, &QGamepad::buttonXChanged, this, &StreamSession::SendFeedbackState); connect(gamepad, &QGamepad::buttonYChanged, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonLeftChanged, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonRightChanged, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonUpChanged, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonDownChanged, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonL1Changed, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonR1Changed, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonL3Changed, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonR3Changed, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonStartChanged, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonSelectChanged, this, &StreamSession::SendFeedbackState); + connect(gamepad, &QGamepad::buttonGuideChanged, this, &StreamSession::SendFeedbackState); connect(gamepad, &QGamepad::axisLeftXChanged, this, &StreamSession::SendFeedbackState); connect(gamepad, &QGamepad::axisLeftYChanged, this, &StreamSession::SendFeedbackState); connect(gamepad, &QGamepad::axisRightXChanged, this, &StreamSession::SendFeedbackState); @@ -137,6 +148,17 @@ void StreamSession::SendFeedbackState() state.buttons |= gamepad->buttonB() ? CHIAKI_CONTROLLER_BUTTON_MOON : 0; state.buttons |= gamepad->buttonX() ? CHIAKI_CONTROLLER_BUTTON_BOX : 0; state.buttons |= gamepad->buttonY() ? CHIAKI_CONTROLLER_BUTTON_PYRAMID : 0; + state.buttons |= gamepad->buttonLeft() ? CHIAKI_CONTROLLER_BUTTON_DPAD_LEFT : 0; + state.buttons |= gamepad->buttonRight() ? CHIAKI_CONTROLLER_BUTTON_DPAD_RIGHT : 0; + state.buttons |= gamepad->buttonUp() ? CHIAKI_CONTROLLER_BUTTON_DPAD_UP : 0; + state.buttons |= gamepad->buttonDown() ? CHIAKI_CONTROLLER_BUTTON_DPAD_DOWN : 0; + state.buttons |= gamepad->buttonL1() ? CHIAKI_CONTROLLER_BUTTON_L1 : 0; + state.buttons |= gamepad->buttonR1() ? CHIAKI_CONTROLLER_BUTTON_R1 : 0; + state.buttons |= gamepad->buttonL3() ? CHIAKI_CONTROLLER_BUTTON_L3 : 0; + state.buttons |= gamepad->buttonR3() ? CHIAKI_CONTROLLER_BUTTON_R3 : 0; + state.buttons |= gamepad->buttonStart() ? CHIAKI_CONTROLLER_BUTTON_OPTIONS : 0; + state.buttons |= gamepad->buttonSelect() ? CHIAKI_CONTROLLER_BUTTON_SHARE : 0; + state.buttons |= gamepad->buttonGuide() ? CHIAKI_CONTROLLER_BUTTON_PS : 0; state.left_x = static_cast(gamepad->axisLeftX() * 0x7fff); state.left_y = static_cast(gamepad->axisLeftY() * 0x7fff); state.right_x = static_cast(gamepad->axisRightX() * 0x7fff); diff --git a/lib/include/chiaki/controller.h b/lib/include/chiaki/controller.h index e98307a..edb3e4b 100644 --- a/lib/include/chiaki/controller.h +++ b/lib/include/chiaki/controller.h @@ -29,12 +29,26 @@ extern "C" { typedef enum chiaki_controller_button_t { - CHIAKI_CONTROLLER_BUTTON_CROSS = (1 << 0), - CHIAKI_CONTROLLER_BUTTON_MOON = (1 << 1), - CHIAKI_CONTROLLER_BUTTON_BOX = (1 << 2), - CHIAKI_CONTROLLER_BUTTON_PYRAMID = (1 << 3) + CHIAKI_CONTROLLER_BUTTON_CROSS = (1 << 0), + CHIAKI_CONTROLLER_BUTTON_MOON = (1 << 1), + CHIAKI_CONTROLLER_BUTTON_BOX = (1 << 2), + CHIAKI_CONTROLLER_BUTTON_PYRAMID = (1 << 3), + CHIAKI_CONTROLLER_BUTTON_DPAD_LEFT = (1 << 4), + CHIAKI_CONTROLLER_BUTTON_DPAD_RIGHT = (1 << 5), + CHIAKI_CONTROLLER_BUTTON_DPAD_UP = (1 << 6), + CHIAKI_CONTROLLER_BUTTON_DPAD_DOWN = (1 << 7), + CHIAKI_CONTROLLER_BUTTON_L1 = (1 << 8), + CHIAKI_CONTROLLER_BUTTON_R1 = (1 << 9), + CHIAKI_CONTROLLER_BUTTON_L3 = (1 << 10), + CHIAKI_CONTROLLER_BUTTON_R3 = (1 << 11), + CHIAKI_CONTROLLER_BUTTON_OPTIONS = (1 << 12), + CHIAKI_CONTROLLER_BUTTON_SHARE = (1 << 13), + CHIAKI_CONTROLLER_BUTTON_TOUCHPAD = (1 << 14), + CHIAKI_CONTROLLER_BUTTON_PS = (1 << 15) } ChiakiControllerButton; +#define CHIAKI_CONTROLLER_BUTTONS_COUNT 16 + typedef struct chiaki_controller_state_t { /** @@ -42,6 +56,9 @@ typedef struct chiaki_controller_state_t */ uint32_t buttons; + uint8_t l2_state; + uint8_t r2_state; + int16_t left_x; int16_t left_y; int16_t right_x; diff --git a/lib/include/chiaki/feedback.h b/lib/include/chiaki/feedback.h index f35695f..91009db 100644 --- a/lib/include/chiaki/feedback.h +++ b/lib/include/chiaki/feedback.h @@ -20,6 +20,7 @@ #include "common.h" #include "log.h" +#include "controller.h" #include @@ -29,7 +30,6 @@ extern "C" { typedef struct chiaki_feedback_state_t { - uint32_t buttons; int16_t left_x; int16_t left_y; int16_t right_x; @@ -43,6 +43,44 @@ typedef struct chiaki_feedback_state_t */ CHIAKI_EXPORT void chiaki_feedback_state_format(uint8_t *buf, ChiakiFeedbackState *state); + +#define CHIAKI_HISTORY_EVENT_SIZE_MAX 0x3 // TODO: will be bigger later for touchpad at least + +typedef struct chiaki_feedback_history_event_t +{ + uint8_t buf[CHIAKI_HISTORY_EVENT_SIZE_MAX]; + size_t len; +} ChiakiFeedbackHistoryEvent; + +/** + * @param state 0x0 for not pressed, 0xff for pressed, intermediate values for analog triggers + */ +CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_button(ChiakiFeedbackHistoryEvent *event, ChiakiControllerButton button, uint8_t state); + +/** + * Ring buffer of ChiakiFeedbackHistoryEvent + */ +typedef struct chiaki_feedback_history_buffer_t +{ + ChiakiFeedbackHistoryEvent *events; + size_t size; + size_t begin; + size_t len; +} ChiakiFeedbackHistoryBuffer; + +CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_buffer_init(ChiakiFeedbackHistoryBuffer *feedback_history_buffer, size_t size); +CHIAKI_EXPORT void chiaki_feedback_history_buffer_fini(ChiakiFeedbackHistoryBuffer *feedback_history_buffer); + +/** + * @param buf_size Pointer to the allocated size of buf, will contain the written size after a successful formatting. + */ +CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_buffer_format(ChiakiFeedbackHistoryBuffer *feedback_history_buffer, uint8_t *buf, size_t *buf_size); + +/** + * Push an event to the front of the buffer + */ +CHIAKI_EXPORT void chiaki_feedback_history_buffer_push(ChiakiFeedbackHistoryBuffer *feedback_history_buffer, ChiakiFeedbackHistoryEvent *event); + #ifdef __cplusplus } #endif diff --git a/lib/include/chiaki/feedbacksender.h b/lib/include/chiaki/feedbacksender.h index 94d32e4..1e6e6c7 100644 --- a/lib/include/chiaki/feedbacksender.h +++ b/lib/include/chiaki/feedbacksender.h @@ -35,6 +35,9 @@ typedef struct chiaki_feedback_sender_t ChiakiSeqNum16 state_seq_num; + ChiakiSeqNum16 history_seq_num; + ChiakiFeedbackHistoryBuffer history_buf; + bool should_stop; ChiakiControllerState controller_state_prev; ChiakiControllerState controller_state; diff --git a/lib/include/chiaki/takion.h b/lib/include/chiaki/takion.h index b788ad1..56f74fa 100644 --- a/lib/include/chiaki/takion.h +++ b/lib/include/chiaki/takion.h @@ -205,6 +205,10 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_congestion(ChiakiTakion *takion */ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_feedback_state(ChiakiTakion *takion, ChiakiSeqNum16 seq_num, ChiakiFeedbackState *feedback_state); +/** + * Thread-safe while Takion is running. + */ +CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_feedback_history(ChiakiTakion *takion, ChiakiSeqNum16 seq_num, uint8_t *payload, size_t payload_size); CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_av_packet_parse(ChiakiTakionAVPacket *packet, uint8_t base_type, uint8_t *buf, size_t buf_size); diff --git a/lib/src/feedback.c b/lib/src/feedback.c index 605c825..243ad4d 100644 --- a/lib/src/feedback.c +++ b/lib/src/feedback.c @@ -19,6 +19,7 @@ #include #include +#include CHIAKI_EXPORT void chiaki_feedback_state_format(uint8_t *buf, ChiakiFeedbackState *state) { @@ -44,3 +45,109 @@ CHIAKI_EXPORT void chiaki_feedback_state_format(uint8_t *buf, ChiakiFeedbackStat *((uint16_t *)(buf + 0x15)) = htons((uint16_t)state->right_x); *((uint16_t *)(buf + 0x17)) = htons((uint16_t)state->right_y); } + +CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_event_set_button(ChiakiFeedbackHistoryEvent *event, ChiakiControllerButton button, uint8_t state) +{ + // some buttons use a third byte for the state, some don't + event->buf[0] = 0x80; + event->len = 2; + switch(button) + { + case CHIAKI_CONTROLLER_BUTTON_CROSS: + event->buf[1] = 0x88; + break; + case CHIAKI_CONTROLLER_BUTTON_MOON: + event->buf[1] = 0x89; + break; + case CHIAKI_CONTROLLER_BUTTON_BOX: + event->buf[1] = 0x8a; + break; + case CHIAKI_CONTROLLER_BUTTON_PYRAMID: + event->buf[1] = 0x8b; + break; + case CHIAKI_CONTROLLER_BUTTON_DPAD_LEFT: + event->buf[1] = 0x82; + break; + case CHIAKI_CONTROLLER_BUTTON_DPAD_RIGHT: + event->buf[1] = 0x83; + break; + case CHIAKI_CONTROLLER_BUTTON_DPAD_UP: + event->buf[1] = 0x80; + break; + case CHIAKI_CONTROLLER_BUTTON_DPAD_DOWN: + event->buf[1] = 0x81; + break; + case CHIAKI_CONTROLLER_BUTTON_L1: + event->buf[1] = 0x84; + break; + case CHIAKI_CONTROLLER_BUTTON_R1: + event->buf[1] = 0x85; + break; + case CHIAKI_CONTROLLER_BUTTON_L3: + event->buf[1] = state ? 0xaf : 0x8f; + return CHIAKI_ERR_SUCCESS; + case CHIAKI_CONTROLLER_BUTTON_R3: + event->buf[1] = state ? 0xb0 : 0x90; + return CHIAKI_ERR_SUCCESS; + case CHIAKI_CONTROLLER_BUTTON_OPTIONS: + event->buf[1] = state ? 0xac : 0x8c; + return CHIAKI_ERR_SUCCESS; + case CHIAKI_CONTROLLER_BUTTON_SHARE: + event->buf[1] = state ? 0xad : 0x8d; + return CHIAKI_ERR_SUCCESS; + case CHIAKI_CONTROLLER_BUTTON_TOUCHPAD: + event->buf[1] = state ? 0xb1 : 0x91; + return CHIAKI_ERR_SUCCESS; + case CHIAKI_CONTROLLER_BUTTON_PS: + event->buf[1] = state ? 0xae : 0x8e; + return CHIAKI_ERR_SUCCESS; + default: + return CHIAKI_ERR_INVALID_DATA; + } + event->buf[2] = state; + event->len = 3; + return CHIAKI_ERR_SUCCESS; +} + +CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_buffer_init(ChiakiFeedbackHistoryBuffer *feedback_history_buffer, size_t size) +{ + feedback_history_buffer->events = calloc(size, sizeof(ChiakiFeedbackHistoryEvent)); + if(!feedback_history_buffer->events) + return CHIAKI_ERR_MEMORY; + feedback_history_buffer->size = size; + feedback_history_buffer->begin = 0; + feedback_history_buffer->len = 0; + return CHIAKI_ERR_SUCCESS; +} + +CHIAKI_EXPORT void chiaki_feedback_history_buffer_fini(ChiakiFeedbackHistoryBuffer *feedback_history_buffer) +{ + free(feedback_history_buffer->events); +} + +CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_history_buffer_format(ChiakiFeedbackHistoryBuffer *feedback_history_buffer, uint8_t *buf, size_t *buf_size) +{ + size_t size_max = *buf_size; + size_t written = 0; + + for(size_t i=0; ilen; i++) + { + ChiakiFeedbackHistoryEvent *event = &feedback_history_buffer->events[(feedback_history_buffer->begin + i) % feedback_history_buffer->size]; + if(written + event->len > size_max) + return CHIAKI_ERR_BUF_TOO_SMALL; + memcpy(buf + written, event->buf, event->len); + written += event->len; + } + + *buf_size = written; + return CHIAKI_ERR_SUCCESS; +} + +CHIAKI_EXPORT void chiaki_feedback_history_buffer_push(ChiakiFeedbackHistoryBuffer *feedback_history_buffer, ChiakiFeedbackHistoryEvent *event) +{ + feedback_history_buffer->begin = (feedback_history_buffer->begin + feedback_history_buffer->size - 1) % feedback_history_buffer->size; + feedback_history_buffer->len++; + if(feedback_history_buffer->len >= feedback_history_buffer->size) + feedback_history_buffer->len = feedback_history_buffer->size; + feedback_history_buffer->events[feedback_history_buffer->begin] = *event; +} \ No newline at end of file diff --git a/lib/src/feedbacksender.c b/lib/src/feedbacksender.c index 8b9e0ff..6a50243 100644 --- a/lib/src/feedbacksender.c +++ b/lib/src/feedbacksender.c @@ -20,6 +20,8 @@ #define FEEDBACK_STATE_TIMEOUT_MIN_MS 8 // minimum time to wait between sending 2 packets #define FEEDBACK_STATE_TIMEOUT_MAX_MS 200 // maximum time to wait between sending 2 packets +#define FEEDBACK_HISTORY_BUFFER_SIZE 0x10 + static void *feedback_sender_thread_func(void *user); CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_sender_init(ChiakiFeedbackSender *feedback_sender, ChiakiTakion *takion) @@ -32,10 +34,15 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_sender_init(ChiakiFeedbackSender * feedback_sender->state_seq_num = 0; - ChiakiErrorCode err = chiaki_mutex_init(&feedback_sender->state_mutex, false); + feedback_sender->history_seq_num = 0; + ChiakiErrorCode err = chiaki_feedback_history_buffer_init(&feedback_sender->history_buf, FEEDBACK_HISTORY_BUFFER_SIZE); if(err != CHIAKI_ERR_SUCCESS) return err; + err = chiaki_mutex_init(&feedback_sender->state_mutex, false); + if(err != CHIAKI_ERR_SUCCESS) + goto error_history_buffer; + err = chiaki_cond_init(&feedback_sender->state_cond); if(err != CHIAKI_ERR_SUCCESS) goto error_mutex; @@ -49,6 +56,8 @@ error_cond: chiaki_cond_fini(&feedback_sender->state_cond); error_mutex: chiaki_mutex_fini(&feedback_sender->state_mutex); +error_history_buffer: + chiaki_feedback_history_buffer_fini(&feedback_sender->history_buf); return err; } @@ -61,6 +70,7 @@ CHIAKI_EXPORT void chiaki_feedback_sender_fini(ChiakiFeedbackSender *feedback_se chiaki_thread_join(&feedback_sender->thread, NULL); chiaki_cond_fini(&feedback_sender->state_cond); chiaki_mutex_fini(&feedback_sender->state_mutex); + chiaki_feedback_history_buffer_fini(&feedback_sender->history_buf); } CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_sender_set_controller_state(ChiakiFeedbackSender *feedback_sender, ChiakiControllerState *state) @@ -84,10 +94,17 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_feedback_sender_set_controller_state(Chiaki return CHIAKI_ERR_SUCCESS; } +static bool controller_state_equals_for_feedback_state(ChiakiControllerState *a, ChiakiControllerState *b) +{ + return a->left_x == b->left_x + && a->left_y == b->left_y + && a->right_x == b->right_x + && a->right_y == b->right_y; +} + static void feedback_sender_send_state(ChiakiFeedbackSender *feedback_sender) { ChiakiFeedbackState state; - state.buttons = feedback_sender->controller_state.buttons; state.left_x = feedback_sender->controller_state.left_x; state.left_y = feedback_sender->controller_state.left_y; state.right_x = feedback_sender->controller_state.right_x; @@ -97,6 +114,53 @@ static void feedback_sender_send_state(ChiakiFeedbackSender *feedback_sender) CHIAKI_LOGE(feedback_sender->log, "FeedbackSender failed to send Feedback State\n"); } +static bool controller_state_equals_for_feedback_history(ChiakiControllerState *a, ChiakiControllerState *b) +{ + return a->buttons == b->buttons; +} + +static void feedback_sender_send_history(ChiakiFeedbackSender *feedback_sender) +{ + // TODO: Is it legal to have more than one new event per packet? + size_t new_events_count = 0; + uint64_t buttons_prev = feedback_sender->controller_state_prev.buttons; + uint64_t buttons_now = feedback_sender->controller_state.buttons; + for(uint8_t i=0; ilog, "Feedback Sender failed to format button history event for button id %llu\n", (unsigned long long)button_id); + continue; + } + chiaki_feedback_history_buffer_push(&feedback_sender->history_buf, &event); + new_events_count++; + } + } + + if(!new_events_count) // TODO: also send on timeout sometimes? + return; + + uint8_t buf[0x300]; + size_t buf_size = sizeof(buf); + ChiakiErrorCode err = chiaki_feedback_history_buffer_format(&feedback_sender->history_buf, buf, &buf_size); + if(err != CHIAKI_ERR_SUCCESS) + { + CHIAKI_LOGE(feedback_sender->log, "Feedback Sender failed to format history buffer\n"); + return; + } + + CHIAKI_LOGD(feedback_sender->log, "Feedback History:\n"); + chiaki_log_hexdump(feedback_sender->log, CHIAKI_LOG_DEBUG, buf, buf_size); + chiaki_takion_send_feedback_history(feedback_sender->takion, feedback_sender->history_seq_num++, buf, buf_size); +} + static bool state_cond_check(void *user) { ChiakiFeedbackSender *feedback_sender = user; @@ -121,13 +185,26 @@ static void *feedback_sender_thread_func(void *user) if(feedback_sender->should_stop) break; + bool send_feedback_state = true; + bool send_feedback_history = false; + if(feedback_sender->controller_state_changed) { // TODO: FEEDBACK_STATE_TIMEOUT_MIN_MS feedback_sender->controller_state_changed = false; - } - feedback_sender_send_state(feedback_sender); + // don't need to send feedback state if nothing relevant changed + if(controller_state_equals_for_feedback_state(&feedback_sender->controller_state, &feedback_sender->controller_state_prev)) + send_feedback_state = false; + + send_feedback_history = !controller_state_equals_for_feedback_history(&feedback_sender->controller_state, &feedback_sender->controller_state_prev); + } // else: timeout + + if(send_feedback_state) + feedback_sender_send_state(feedback_sender); + + if(send_feedback_history) + feedback_sender_send_history(feedback_sender); feedback_sender->controller_state_prev = feedback_sender->controller_state; } diff --git a/lib/src/mirai.c b/lib/src/mirai.c index 4245bf9..548243c 100644 --- a/lib/src/mirai.c +++ b/lib/src/mirai.c @@ -21,7 +21,7 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_mirai_init(ChiakiMirai *mirai) { mirai->request = -1; mirai->response = -1; - ChiakiErrorCode err = chiaki_mutex_init(&mirai->mutex); + ChiakiErrorCode err = chiaki_mutex_init(&mirai->mutex, false); if(err != CHIAKI_ERR_SUCCESS) return err; err = chiaki_cond_init(&mirai->cond); diff --git a/lib/src/takion.c b/lib/src/takion.c index ee27c82..7b4fdab 100644 --- a/lib/src/takion.c +++ b/lib/src/takion.c @@ -408,6 +408,38 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_congestion(ChiakiTakion *takion return chiaki_takion_send_raw(takion, buf, sizeof(buf)); } +static ChiakiErrorCode takion_send_feedback_packet(ChiakiTakion *takion, uint8_t *buf, size_t buf_size) +{ + assert(buf_size >= 0xc); + + size_t payload_size = buf_size - 0xc; + + ChiakiErrorCode err = chiaki_mutex_lock(&takion->gkcrypt_local_mutex); + if(err != CHIAKI_ERR_SUCCESS) + return err; + + size_t key_pos; + err = chiaki_takion_crypt_advance_key_pos(takion, payload_size + CHIAKI_GKCRYPT_BLOCK_SIZE, &key_pos); + if(err != CHIAKI_ERR_SUCCESS) + goto beach; + + err = chiaki_gkcrypt_encrypt(takion->gkcrypt_local, key_pos + CHIAKI_GKCRYPT_BLOCK_SIZE, buf + 0xc, payload_size); + if(err != CHIAKI_ERR_SUCCESS) + goto beach; + + *((uint32_t *)(buf + 4)) = htonl((uint32_t)key_pos); + + err = chiaki_gkcrypt_gmac(takion->gkcrypt_local, key_pos, buf, buf_size, buf + 8); + if(err != CHIAKI_ERR_SUCCESS) + goto beach; + + chiaki_takion_send_raw(takion, buf, buf_size); + +beach: + chiaki_mutex_unlock(&takion->gkcrypt_local_mutex); + return err; +} + CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_feedback_state(ChiakiTakion *takion, ChiakiSeqNum16 seq_num, ChiakiFeedbackState *feedback_state) { uint8_t buf[0xc + CHIAKI_FEEDBACK_STATE_BUF_SIZE]; @@ -417,33 +449,23 @@ CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_feedback_state(ChiakiTakion *ta *((uint32_t *)(buf + 4)) = 0; // key pos *((uint32_t *)(buf + 8)) = 0; // gmac chiaki_feedback_state_format(buf + 0xc, feedback_state); + return takion_send_feedback_packet(takion, buf, sizeof(buf)); +} - //CHIAKI_LOGD(takion->log, "Takion sending Feedback State:\n"); - //chiaki_log_hexdump(takion->log, CHIAKI_LOG_DEBUG, buf, sizeof(buf)); - - ChiakiErrorCode err = chiaki_mutex_lock(&takion->gkcrypt_local_mutex); - if(err != CHIAKI_ERR_SUCCESS) - return err; - - size_t key_pos; - err = chiaki_takion_crypt_advance_key_pos(takion, CHIAKI_FEEDBACK_STATE_BUF_SIZE + CHIAKI_GKCRYPT_BLOCK_SIZE, &key_pos); - if(err != CHIAKI_ERR_SUCCESS) - goto beach; - - err = chiaki_gkcrypt_encrypt(takion->gkcrypt_local, key_pos + CHIAKI_GKCRYPT_BLOCK_SIZE, buf + 0xc, CHIAKI_FEEDBACK_STATE_BUF_SIZE); - if(err != CHIAKI_ERR_SUCCESS) - goto beach; - - *((uint32_t *)(buf + 4)) = htonl((uint32_t)key_pos); - - err = chiaki_gkcrypt_gmac(takion->gkcrypt_local, key_pos, buf, sizeof(buf), buf + 8); - if(err != CHIAKI_ERR_SUCCESS) - goto beach; - - chiaki_takion_send_raw(takion, buf, sizeof(buf)); - -beach: - chiaki_mutex_unlock(&takion->gkcrypt_local_mutex); +CHIAKI_EXPORT ChiakiErrorCode chiaki_takion_send_feedback_history(ChiakiTakion *takion, ChiakiSeqNum16 seq_num, uint8_t *payload, size_t payload_size) +{ + size_t buf_size = 0xc + payload_size; + uint8_t *buf = malloc(buf_size); + if(!buf) + return CHIAKI_ERR_MEMORY; + buf[0] = TAKION_PACKET_TYPE_FEEDBACK_HISTORY; + *((uint16_t *)(buf + 1)) = htons(seq_num); + buf[3] = 0; // TODO + *((uint32_t *)(buf + 4)) = 0; // key pos + *((uint32_t *)(buf + 8)) = 0; // gmac + memcpy(buf + 0xc, payload, payload_size); + ChiakiErrorCode err = takion_send_feedback_packet(takion, buf, buf_size); + free(buf); return err; }