newtx/usb/usb_io.h

101 lines
3.1 KiB
C
Raw Normal View History

2023-12-01 09:17:09 +00:00
#pragma once
// Objects IO
//
// created on 2023-03-10
#include <base/utils.h>
#include <base/packet.h>
#include <base/data.h>
#include <functional>
#include <memory>
#include <vector>
#include <thread>
// callback proto
//
// parameters: usb_functionfs_event* - the function event ptr
//
// dyn_mem_ptr - the packet buffer, read-only
//
// uint32_t* - to return how many data in bytes the handler consumed
//
// normally, the value should be sizeof(PACK_BASE) + PACK_BASE::payload_len, i.e. the handler consume all data of an entire packet
//
// when invalid packet, suggest use the entire data
//
// packet_data_base_ptr* - return data_holder or data_source or nullptr
//
// data_holder: the packet/command need more data than dyn_mem_ptr provides to complete the business. such as 'write a large file'
//
// data_source: the reply content may be a large data (a large file content)
//
// return value of all routines is the reply packet, nullptr if the packet need not reply
//
#define FUNCTION_PROTO_UNHANDLED_EP0 dyn_mem_ptr(struct usb_functionfs_event*)
class usb_device;
class async_usb_gadget : public refer
{
volatile bool run_ = true;
usb_device *dev_ = nullptr;
safe_thread threads_;
size_t unit_in_ = 0x200;
size_t unit_out_ = 0x200;
uint16_t buf_coef_ = 1;
MUTEX buf_coef_lock_;
uint32_t enc_head_;
uint32_t enc_payload_;
uint8_t enc_data_;
2023-12-01 10:03:10 +00:00
int last_err_ = 0;
2023-12-01 09:17:09 +00:00
volatile EP0REPLYSTATUS status_;
safe_fifo<dyn_mem_ptr> cmd_que_;
safe_fifo<data_source_ptr> sent_que_;
enum
{
EP0_STATUS_IDLE = 0,
EP0_STATUS_READ_DATA, // ep0_statu::data is rest data len
EP0_STATUS_READ_INVAL_DATA, // ep0_statu::data is rest data len
EP0_STATUS_HANDLE_CMD,
};
std::function<FUNCTION_PROTO_COMMAND_HANDLE> handle_cmd_;
std::function<void(bool)> dev_connect_;
const char* ep0_status_desc(int ep0_status, char* unk_buf/*>= 40 bytes*/);
int wait_fd_event(int fd, int to_ms = -1);
uint16_t get_buf_coefficient(void);
void set_buf_coefficient(int coef);
dyn_mem_ptr handle_ctrl_message(dyn_mem_ptr data);
dyn_mem_ptr handle_ctrl_setup(dyn_mem_ptr data); // user command ...
int inner_write_bulk(int fd, data_source_ptr data, int* err = nullptr);
dyn_mem_ptr handle_bulk_command(dyn_mem_ptr data, uint32_t* used, packet_data_base_ptr* pkd);
void thread_read_ep0(void);
void thread_read_bulk(int fd);
void thread_write_bulk(int fd);
void thread_pump_task(void);
public:
async_usb_gadget(std::function<FUNCTION_PROTO_COMMAND_HANDLE> cmd_handler = std::function<FUNCTION_PROTO_COMMAND_HANDLE>()
, std::function<void(bool)> dev_conn = std::function<void(bool)>());
protected:
~async_usb_gadget();
public:
int stop(void);
int write_bulk(data_source_ptr data); // return sent-que length
2023-12-01 10:03:10 +00:00
int last_error(void);
2023-12-01 09:17:09 +00:00
};