#include "printer_protocol.h" #include "printer_protocol_internal.h" #include #include #include "ble_printer_client.h" esp_err_t printer_protocol_gap_move(uint32_t timeout_ms, char *err, size_t err_len) { if (!ble_printer_client_is_connected()) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "printer not connected"); } return ESP_ERR_INVALID_STATE; } if (!printer_protocol_acquire_control_lane(1000, err, err_len)) { return ESP_ERR_INVALID_STATE; } uint8_t payload = 0x01; esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_GAP_MOVE, &payload, 1, true, timeout_ms, true, NULL, 0, NULL, err, err_len); printer_protocol_release_control_lane(); return rc; } esp_err_t printer_protocol_get_label_offset(uint8_t *out_offset, uint32_t timeout_ms, char *err, size_t err_len) { if (out_offset == NULL) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "invalid args"); } return ESP_ERR_INVALID_ARG; } if (!ble_printer_client_is_connected()) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "printer not connected"); } return ESP_ERR_INVALID_STATE; } if (!printer_protocol_acquire_control_lane(1000, err, err_len)) { return ESP_ERR_INVALID_STATE; } uint8_t req = 0x01; uint8_t rsp[16]; uint16_t rsp_len = 0; esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_GET_OFFSET, &req, 1, true, timeout_ms, false, rsp, sizeof(rsp), &rsp_len, err, err_len); printer_protocol_release_control_lane(); if (rc != ESP_OK) { return rc; } if (rsp_len < 1) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "invalid offset response"); } return ESP_FAIL; } if (rsp[0] == 0xFF) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "offset unavailable"); } return ESP_FAIL; } *out_offset = rsp[0]; return ESP_OK; } esp_err_t printer_protocol_set_label_offset(uint8_t offset, uint32_t timeout_ms, char *err, size_t err_len) { if (!ble_printer_client_is_connected()) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "printer not connected"); } return ESP_ERR_INVALID_STATE; } if (!printer_protocol_acquire_control_lane(1000, err, err_len)) { return ESP_ERR_INVALID_STATE; } esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_SET_OFFSET, &offset, 1, true, timeout_ms, true, NULL, 0, NULL, err, err_len); printer_protocol_release_control_lane(); return rc; } esp_err_t printer_protocol_ota_jump_boot(uint32_t timeout_ms, char *err, size_t err_len) { if (!ble_printer_client_is_connected()) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "printer not connected"); } return ESP_ERR_INVALID_STATE; } if (!printer_protocol_acquire_control_lane(1000, err, err_len)) { return ESP_ERR_INVALID_STATE; } esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_JUMP_BOOT, NULL, 0, true, timeout_ms, true, NULL, 0, NULL, err, err_len); printer_protocol_release_control_lane(); return rc; } esp_err_t printer_protocol_ota_jump_app(uint32_t timeout_ms, char *err, size_t err_len) { if (!ble_printer_client_is_connected()) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "printer not connected"); } return ESP_ERR_INVALID_STATE; } if (!printer_protocol_acquire_control_lane(1000, err, err_len)) { return ESP_ERR_INVALID_STATE; } esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_JUMP_APP, NULL, 0, true, timeout_ms, true, NULL, 0, NULL, err, err_len); printer_protocol_release_control_lane(); return rc; } esp_err_t printer_protocol_ota_erase_page(uint16_t page_num, uint32_t timeout_ms, char *err, size_t err_len) { if (!ble_printer_client_is_connected()) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "printer not connected"); } return ESP_ERR_INVALID_STATE; } if (!printer_protocol_acquire_control_lane(1000, err, err_len)) { return ESP_ERR_INVALID_STATE; } uint8_t payload[2] = { (uint8_t)((page_num >> 8) & 0xFF), (uint8_t)(page_num & 0xFF), }; esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_ERASE_PAGE, payload, sizeof(payload), true, timeout_ms, true, NULL, 0, NULL, err, err_len); printer_protocol_release_control_lane(); return rc; } esp_err_t printer_protocol_ota_write_frame(uint16_t packet_num, bool is_last_frame, const uint8_t *data, size_t data_len, uint32_t timeout_ms, char *err, size_t err_len) { if ((data_len > 0 && data == NULL) || data_len > OTA_MAX_DATA_PER_FRAME) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "invalid frame length"); } return ESP_ERR_INVALID_ARG; } if (!ble_printer_client_is_connected()) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "printer not connected"); } return ESP_ERR_INVALID_STATE; } if (!printer_protocol_acquire_control_lane(1000, err, err_len)) { return ESP_ERR_INVALID_STATE; } uint8_t payload[3 + OTA_MAX_DATA_PER_FRAME]; payload[0] = (uint8_t)((packet_num >> 8) & 0xFF); payload[1] = (uint8_t)(packet_num & 0xFF); payload[2] = is_last_frame ? 0x01 : 0x00; if (data_len > 0) { memcpy(&payload[3], data, data_len); } esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_WRITE_DATA, payload, (uint16_t)(3 + data_len), true, timeout_ms, true, NULL, 0, NULL, err, err_len); printer_protocol_release_control_lane(); return rc; } esp_err_t printer_protocol_ota_get_version(printer_ota_version_t *out_version, uint32_t timeout_ms, char *err, size_t err_len) { if (out_version == NULL) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "invalid args"); } return ESP_ERR_INVALID_ARG; } if (!ble_printer_client_is_connected()) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "printer not connected"); } return ESP_ERR_INVALID_STATE; } if (!printer_protocol_acquire_control_lane(1000, err, err_len)) { return ESP_ERR_INVALID_STATE; } uint8_t rsp[16]; uint16_t rsp_len = 0; esp_err_t rc = printer_protocol_send_cmd_wait_response(CMD_BOOT_GET_VERSION, NULL, 0, true, timeout_ms, false, rsp, sizeof(rsp), &rsp_len, err, err_len); printer_protocol_release_control_lane(); if (rc != ESP_OK) { return rc; } if (rsp_len < 3) { if (err != NULL && err_len > 0) { snprintf(err, err_len, "invalid version response"); } return ESP_FAIL; } out_version->major = rsp[0]; out_version->minor = rsp[1]; out_version->patch = rsp[2]; return ESP_OK; } const char *printer_protocol_job_state_str(print_job_state_t state) { switch (state) { case PRINT_JOB_STATE_NONE: return "none"; case PRINT_JOB_STATE_QUEUED: return "queued"; case PRINT_JOB_STATE_RUNNING: return "running"; case PRINT_JOB_STATE_SUCCESS: return "success"; case PRINT_JOB_STATE_FAILED: return "failed"; case PRINT_JOB_STATE_CANCELED: return "canceled"; default: return "unknown"; } }