shithub: m8c

ref: bd6f0231604a570b72d9468fcf7e65a2ebd284db
dir: /src/backends/m8_plan9.c/

View raw version
#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; }