ref: bd6f0231604a570b72d9468fcf7e65a2ebd284db
dir: /src/backends/m8_plan9.c/
#include "m8.h"
#include <SDL3/SDL.h>
#include <thread.h>
#include "../command.h"
#include "queue.h"
#include "slip.h"
#define SERIAL_READ_SIZE 1024 // maximum amount of bytes to read from the serial in one pass
static uint8_t serial_buffer[SERIAL_READ_SIZE] = {0};
static uint8_t slip_buffer[SERIAL_READ_SIZE] = {0};
static slip_handler_s slip;
message_queue_s queue;
static int epfd = -1;
static int send_message_to_queue(uint8_t *data, const uint32_t size) {
push_message(&queue, data, size);
return 1;
}
int m8_list_devices(void) {
if (access("/dev/m8", AEXIST) == 0)
return 1;
return 0;
}
static void
reader(void *arg)
{
int m, fd;
long n;
uchar buf[1024], *p, *e;
fd = (int)(intptr)arg;
for(;;){
if((n = read(fd, buf, sizeof buf)) < 0)
break;
if(n == 0)
continue;
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Received %ld bytes from M8", n);
for(p=buf, e=p+n; p<e; p++){
if((m = slip_read_byte(&slip, *p)) != SLIP_NO_ERROR){
if(m == SLIP_ERROR_INVALID_PACKET)
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Invalid SLIP packet!\n");
else
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SLIP error %d\n", m);
}
}
}
if(n < 0)
fprint(2, "reader: %r\n");
}
int blocking_write(void *buf, int count, unsigned int timeout_ms) {
long n;
if (epfd < 0) {
return -1;
}
USED(timeout_ms);
if((n = write(epfd, buf, count)) != count)
SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "write error: %r");
return n;
}
int m8_process_data(const config_params_s *) {
// Process any queued messages
if (queue_size(&queue) > 0) {
unsigned char *command;
size_t length = 0;
while ((command = pop_message(&queue, &length)) != NULL) {
if (length > 0) {
process_command(command, length);
}
SDL_free(command);
}
}
return DEVICE_PROCESSING;
}
int check_serial_port() {
// Reading will fail anyway when the device is not present anymore
return 1;
}
int
init_interface(void)
{
if(epfd < 0){
SDL_Log("Device not initialised!");
return 0;
}
init_queue(&queue);
if(proccreate(reader, (void *)epfd, 4096) < 0)
sysfatal("proccreate: %r");
return 1;
}
int
m8_initialize(int, const char *)
{
/* assuming nusb/audio running on the endpoint */
if(epfd != -1)
return 1;
else if((epfd = open("/dev/m8", ORDWR)) < 0){
SDL_Log("could not open device: %r");
return 0;
}
static const slip_descriptor_s slip_descriptor = {
.buf = slip_buffer,
.buf_size = sizeof(slip_buffer),
.recv_message = send_message_to_queue,
};
slip_init(&slip, &slip_descriptor);
SDL_Log("USB device init success");
return init_interface();
}
int
m8_reset_display(void)
{
int result;
SDL_Log("Reset display\n");
char buf[1] = {'R'};
result = blocking_write(buf, 1, 5);
if (result != 1) {
SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d", result);
return 0;
}
return 1;
}
int m8_enable_display(const unsigned char) {
if (epfd < 0) {
return 0;
}
int result;
SDL_Log("Enabling and resetting M8 display\n");
char buf[1] = {'E'};
result = blocking_write(buf, 1, 5);
if (result != 1) {
SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error enabling M8 display, code %d", result);
return 0;
}
SDL_Delay(5);
result = m8_reset_display();
return result;
}
int m8_close(void) {
char buf[1] = {'D'};
int result;
SDL_Log("Disconnecting M8\n");
result = blocking_write(buf, 1, 5);
if (result != 1) {
SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending disconnect, code %d", result);
return -1;
}
if (epfd >= 0) {
close(epfd);
epfd = -1;
}
destroy_queue(&queue);
return 1;
}
int m8_send_msg_controller(uint8_t input) {
char buf[2] = {'C', input};
int nbytes = 2;
int result;
result = blocking_write(buf, nbytes, 5);
if (result != nbytes) {
SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending input, code %d", result);
return -1;
}
return 1;
}
int m8_send_msg_keyjazz(uint8_t note, uint8_t velocity) {
if (velocity > 0x7F)
velocity = 0x7F;
char buf[3] = {'K', note, velocity};
int nbytes = 3;
int result;
result = blocking_write(buf, nbytes, 5);
if (result != nbytes) {
SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending keyjazz, code %d", result);
return -1;
}
return 1;
}
// These shouldn't be needed with serial
int m8_pause_processing(void) { return 1; }
int m8_resume_processing(void) { return 1; }