File upload. Yeah
This commit is contained in:
@@ -113,10 +113,58 @@ static void send_stream_error(buzz_transport_reply_fn reply_cb, uint16_t error_c
|
||||
buzz_proto_buf_free(&buf);
|
||||
}
|
||||
|
||||
uint16_t buzz_proto_get_free_rx_slabs(void)
|
||||
{
|
||||
uint32_t free_slabs = k_mem_slab_num_free_get(&buzz_proto_slabs);
|
||||
return (free_slabs > 4) ? (uint16_t)(free_slabs - 4) : 0;
|
||||
}
|
||||
|
||||
void buzz_proto_send_ack(buzz_transport_reply_fn reply_cb, uint16_t credits)
|
||||
{
|
||||
if (!reply_cb || credits == 0)
|
||||
return;
|
||||
uint8_t *buf;
|
||||
if (buzz_proto_buf_alloc(&buf) == 0)
|
||||
{
|
||||
struct buzz_proto_header *hdr = (struct buzz_proto_header *)buf;
|
||||
hdr->frame_type = BUZZ_FRAME_ACK;
|
||||
hdr->payload_length = sys_cpu_to_le16(sizeof(struct buzz_ack_payload));
|
||||
struct buzz_ack_payload *pl = (struct buzz_ack_payload *)(buf + sizeof(*hdr));
|
||||
pl->credits = sys_cpu_to_le16(credits);
|
||||
reply_cb(buf, sizeof(*hdr) + sizeof(*pl));
|
||||
buzz_proto_buf_free(&buf);
|
||||
}
|
||||
}
|
||||
|
||||
void buzz_proto_send_success_reusing_slab(buzz_transport_reply_fn reply_cb, uint8_t data_type, uint8_t *slab)
|
||||
{
|
||||
if (!reply_cb || !slab)
|
||||
return;
|
||||
struct buzz_proto_header *hdr = (struct buzz_proto_header *)slab;
|
||||
hdr->frame_type = BUZZ_FRAME_SUCCESS;
|
||||
hdr->payload_length = sys_cpu_to_le16(sizeof(struct buzz_resp_success));
|
||||
struct buzz_resp_success *succ = (struct buzz_resp_success *)(slab + sizeof(*hdr));
|
||||
succ->data_type = data_type;
|
||||
reply_cb(slab, sizeof(*hdr) + sizeof(*succ));
|
||||
buzz_proto_buf_free(&slab);
|
||||
}
|
||||
|
||||
void buzz_proto_send_error_reusing_slab(buzz_transport_reply_fn reply_cb, uint16_t error_code, uint8_t *slab)
|
||||
{
|
||||
if (!reply_cb || !slab)
|
||||
return;
|
||||
struct buzz_proto_header *hdr = (struct buzz_proto_header *)slab;
|
||||
hdr->frame_type = BUZZ_FRAME_ERROR;
|
||||
hdr->payload_length = sys_cpu_to_le16(sizeof(struct buzz_resp_error));
|
||||
struct buzz_resp_error *err = (struct buzz_resp_error *)(slab + sizeof(*hdr));
|
||||
err->error_code = sys_cpu_to_le16(error_code);
|
||||
reply_cb(slab, sizeof(*hdr) + sizeof(*err));
|
||||
buzz_proto_buf_free(&slab);
|
||||
}
|
||||
|
||||
static void handle_proto_version_request(struct buzz_frame_msg *msg)
|
||||
{
|
||||
struct buzz_proto_header *hdr = (struct buzz_proto_header *)msg->data_ptr;
|
||||
|
||||
hdr->frame_type = BUZZ_FRAME_RESPONSE;
|
||||
|
||||
struct buzz_resp_proto_version *resp_data = (struct buzz_resp_proto_version *)(msg->data_ptr + sizeof(*hdr));
|
||||
@@ -124,10 +172,18 @@ static void handle_proto_version_request(struct buzz_frame_msg *msg)
|
||||
resp_data->data_type = BUZZ_DATA_PROTO_INFO;
|
||||
resp_data->version = sys_cpu_to_le16(BUZZ_PROTO_VERSION);
|
||||
|
||||
resp_data->max_chunk_size = sys_cpu_to_le16(CONFIG_BUZZ_PROTO_SLAB_SIZE - sizeof(struct buzz_proto_header));
|
||||
/* Dynamische Chunk-Größe basierend auf der aktuellen Transport-MTU berechnen */
|
||||
uint16_t slab_payload = CONFIG_BUZZ_PROTO_SLAB_SIZE - sizeof(struct buzz_proto_header);
|
||||
uint16_t transport_payload = 0;
|
||||
|
||||
if (msg->max_payload > sizeof(struct buzz_proto_header)) {
|
||||
transport_payload = msg->max_payload - sizeof(struct buzz_proto_header);
|
||||
}
|
||||
|
||||
uint16_t safe_chunk = MIN(slab_payload, transport_payload);
|
||||
resp_data->max_chunk_size = sys_cpu_to_le16(safe_chunk);
|
||||
|
||||
hdr->payload_length = sys_cpu_to_le16(sizeof(struct buzz_resp_proto_version));
|
||||
|
||||
uint16_t total_len = sizeof(struct buzz_proto_header) + sizeof(struct buzz_resp_proto_version);
|
||||
|
||||
if (msg->reply_cb)
|
||||
@@ -228,7 +284,7 @@ static void handle_ls_request(struct buzz_frame_msg *msg)
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_file_get_request(struct buzz_frame_msg *msg)
|
||||
static void handle_file_get_request(struct buzz_frame_msg *msg, bool only_tags)
|
||||
{
|
||||
struct buzz_proto_header *hdr = (struct buzz_proto_header *)msg->data_ptr;
|
||||
uint16_t payload_len = sys_le16_to_cpu(hdr->payload_length);
|
||||
@@ -251,7 +307,6 @@ static void handle_file_get_request(struct buzz_frame_msg *msg)
|
||||
memcpy(src_path, msg->data_ptr + sizeof(*hdr) + 1, path_len);
|
||||
src_path[path_len] = '\0';
|
||||
|
||||
// 1. Datei-Größe ermitteln
|
||||
struct fs_dirent entry;
|
||||
if (fs_mgmt_pm_stat(src_path, &entry) != 0)
|
||||
{
|
||||
@@ -260,7 +315,6 @@ static void handle_file_get_request(struct buzz_frame_msg *msg)
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. Datei öffnen
|
||||
fs_file_t_init(&get_file_state.file);
|
||||
int rc = fs_mgmt_pm_open(&get_file_state.file, src_path, FS_O_READ);
|
||||
if (rc != 0)
|
||||
@@ -270,7 +324,31 @@ static void handle_file_get_request(struct buzz_frame_msg *msg)
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. State initialisieren
|
||||
uint32_t stream_size = entry.size;
|
||||
|
||||
if (only_tags)
|
||||
{
|
||||
ssize_t audio_len = fs_get_audio_data_len(&get_file_state.file);
|
||||
if (audio_len < 0)
|
||||
{
|
||||
LOG_ERR("Failed to get audio data len: %d", (int)audio_len);
|
||||
fs_mgmt_pm_close(&get_file_state.file);
|
||||
send_error_frame(msg, EIO);
|
||||
return;
|
||||
}
|
||||
|
||||
stream_size = entry.size - audio_len;
|
||||
|
||||
if (stream_size == 0)
|
||||
{
|
||||
fs_seek(&get_file_state.file, entry.size, FS_SEEK_SET);
|
||||
}
|
||||
else
|
||||
{
|
||||
fs_seek(&get_file_state.file, audio_len, FS_SEEK_SET);
|
||||
}
|
||||
}
|
||||
|
||||
current_stream = STREAM_FILE_GET;
|
||||
get_file_state.active = true;
|
||||
get_file_state.credits = 0;
|
||||
@@ -282,12 +360,11 @@ static void handle_file_get_request(struct buzz_frame_msg *msg)
|
||||
|
||||
LOG_INF("Started FILE_GET stream for '%s' (%u bytes)", src_path, entry.size);
|
||||
|
||||
// 4. FILE_START Frame senden
|
||||
hdr->frame_type = BUZZ_FRAME_FILE_START;
|
||||
hdr->payload_length = sys_cpu_to_le16(sizeof(struct buzz_file_start_payload));
|
||||
|
||||
struct buzz_file_start_payload *start_pl = (struct buzz_file_start_payload *)(msg->data_ptr + sizeof(*hdr));
|
||||
start_pl->total_size = sys_cpu_to_le32(entry.size);
|
||||
start_pl->total_size = sys_cpu_to_le32(stream_size);
|
||||
|
||||
if (msg->reply_cb)
|
||||
{
|
||||
@@ -332,7 +409,7 @@ static void process_file_get_stream(void)
|
||||
return;
|
||||
}
|
||||
|
||||
// Chunk Size berechnen
|
||||
// Chunk Size berechnen
|
||||
uint16_t max_chunk_size = MIN(
|
||||
get_file_state.max_payload - sizeof(*hdr),
|
||||
CONFIG_BUZZ_PROTO_SLAB_SIZE - sizeof(struct buzz_proto_header));
|
||||
@@ -434,18 +511,96 @@ static void handle_request(struct buzz_frame_msg *msg)
|
||||
LOG_DBG("Received Proto Version Request");
|
||||
handle_proto_version_request(msg);
|
||||
break;
|
||||
|
||||
case BUZZ_DATA_FS_INFO:
|
||||
LOG_DBG("Received FS Info Request");
|
||||
handle_fs_info_request(msg);
|
||||
break;
|
||||
|
||||
case BUZZ_DATA_LS:
|
||||
LOG_DBG("Received LS Request");
|
||||
handle_ls_request(msg);
|
||||
break;
|
||||
|
||||
case BUZZ_DATA_FILE_GET:
|
||||
LOG_DBG("Received FILE_GET Request");
|
||||
handle_file_get_request(msg);
|
||||
handle_file_get_request(msg, false);
|
||||
break;
|
||||
|
||||
case BUZZ_DATA_FILE_PUT:
|
||||
LOG_DBG("Received FILE_PUT Request");
|
||||
if (payload_len < sizeof(struct buzz_request_payload) + sizeof(uint32_t) + 1)
|
||||
{
|
||||
send_error_frame(msg, EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_stream != STREAM_IDLE)
|
||||
{
|
||||
LOG_WRN("Stream active, rejecting FILE_PUT request");
|
||||
send_error_frame(msg, EBUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
struct fs_write_msg write_req = {
|
||||
.op = FS_WRITE_OP_FILE_START,
|
||||
.slab_ptr = msg->data_ptr,
|
||||
.data_offset = sizeof(*hdr) + sizeof(struct buzz_request_payload) + sizeof(uint32_t),
|
||||
.data_len = payload_len - sizeof(struct buzz_request_payload) - sizeof(uint32_t),
|
||||
.metadata = sys_get_le32(msg->data_ptr + sizeof(*hdr) + sizeof(struct buzz_request_payload)),
|
||||
.reply_cb = msg->reply_cb};
|
||||
|
||||
if (fs_mgmt_submit_write(&write_req) == 0)
|
||||
{
|
||||
current_stream = STREAM_FILE_PUT; /* WICHTIG: Status blockieren */
|
||||
msg->data_ptr = NULL; /* Ownership an FS-Thread übertragen */
|
||||
}
|
||||
else
|
||||
{
|
||||
send_error_frame(msg, EBUSY);
|
||||
}
|
||||
break;
|
||||
|
||||
case BUZZ_DATA_TAGS_PUT:
|
||||
LOG_DBG("Received TAGS_PUT Request");
|
||||
if (payload_len < sizeof(struct buzz_request_payload) + sizeof(uint32_t) + 1)
|
||||
{
|
||||
send_error_frame(msg, EINVAL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (current_stream != STREAM_IDLE)
|
||||
{
|
||||
LOG_WRN("Stream active, rejecting TAGS_PUT request");
|
||||
send_error_frame(msg, EBUSY);
|
||||
return;
|
||||
}
|
||||
|
||||
struct fs_write_msg tags_req = {
|
||||
.op = FS_WRITE_OP_TAGS_START,
|
||||
.slab_ptr = msg->data_ptr,
|
||||
.data_offset = sizeof(*hdr) + sizeof(struct buzz_request_payload) + sizeof(uint32_t),
|
||||
.data_len = payload_len - sizeof(struct buzz_request_payload) - sizeof(uint32_t),
|
||||
.metadata = sys_get_le32(msg->data_ptr + sizeof(*hdr) + sizeof(struct buzz_request_payload)),
|
||||
.reply_cb = msg->reply_cb
|
||||
};
|
||||
|
||||
if (fs_mgmt_submit_write(&tags_req) == 0)
|
||||
{
|
||||
current_stream = STREAM_FILE_PUT; /* Blockiert den Stream für weitere Requests */
|
||||
msg->data_ptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
send_error_frame(msg, EBUSY);
|
||||
}
|
||||
break;
|
||||
|
||||
case BUZZ_DATA_TAGS_GET:
|
||||
LOG_DBG("Received TAGS_GET Request");
|
||||
handle_file_get_request(msg, true);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG_WRN("Unknown request data_type: 0x%02x", req_data->data_type);
|
||||
send_error_frame(msg, EINVAL);
|
||||
@@ -580,7 +735,64 @@ static void buzz_proto_thread_fn(void *p1, void *p2, void *p3)
|
||||
break;
|
||||
|
||||
case BUZZ_FRAME_FILE_CHUNK:
|
||||
send_error_frame(&msg, ENOSYS);
|
||||
if (current_stream != STREAM_FILE_PUT)
|
||||
{
|
||||
send_error_frame(&msg, EBADMSG);
|
||||
buzz_proto_buf_free(&msg.data_ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
struct fs_write_msg chunk_req = {
|
||||
.op = FS_WRITE_OP_FILE_CHUNK,
|
||||
.slab_ptr = msg.data_ptr,
|
||||
.data_offset = sizeof(*hdr),
|
||||
.data_len = sys_le16_to_cpu(hdr->payload_length),
|
||||
.reply_cb = msg.reply_cb};
|
||||
|
||||
if (fs_mgmt_submit_write(&chunk_req) == 0)
|
||||
{
|
||||
msg.data_ptr = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
send_error_frame(&msg, EBUSY);
|
||||
}
|
||||
buzz_proto_buf_free(&msg.data_ptr); /* Tut nichts, wenn msg.data_ptr == NULL */
|
||||
break;
|
||||
|
||||
case BUZZ_FRAME_FILE_END:
|
||||
if (current_stream != STREAM_FILE_PUT)
|
||||
{
|
||||
send_error_frame(&msg, EBADMSG);
|
||||
buzz_proto_buf_free(&msg.data_ptr);
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg.length >= sizeof(*hdr) + sizeof(struct buzz_file_end_payload))
|
||||
{
|
||||
struct buzz_file_end_payload *end_pl = (struct buzz_file_end_payload *)(msg.data_ptr + sizeof(*hdr));
|
||||
struct fs_write_msg end_req = {
|
||||
.op = FS_WRITE_OP_FILE_END,
|
||||
.slab_ptr = msg.data_ptr,
|
||||
.data_offset = 0,
|
||||
.data_len = 0,
|
||||
.metadata = sys_le32_to_cpu(end_pl->crc32),
|
||||
.reply_cb = msg.reply_cb};
|
||||
|
||||
if (fs_mgmt_submit_write(&end_req) == 0)
|
||||
{
|
||||
msg.data_ptr = NULL;
|
||||
current_stream = STREAM_IDLE; /* Stream wieder freigeben */
|
||||
}
|
||||
else
|
||||
{
|
||||
send_error_frame(&msg, EBUSY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
send_error_frame(&msg, EINVAL);
|
||||
}
|
||||
buzz_proto_buf_free(&msg.data_ptr);
|
||||
break;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user