diff options
| author | 2022-09-26 13:17:04 -0400 | |
|---|---|---|
| committer | 2022-09-26 13:17:04 -0400 | |
| commit | a31884d44375d99c1ac47e27150b3b05d42871ef (patch) | |
| tree | 9a26a9aebc1ccf8a33085f34d5c3b00c7d4e4347 /linux/1394ethbridge.c | |
start unfinished code
Diffstat (limited to 'linux/1394ethbridge.c')
| -rw-r--r-- | linux/1394ethbridge.c | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/linux/1394ethbridge.c b/linux/1394ethbridge.c new file mode 100644 index 0000000..c7fffcf --- /dev/null +++ b/linux/1394ethbridge.c @@ -0,0 +1,266 @@ +#include <stdio.h> +#include <stdarg.h> +#include <errno.h> +#include <stdint.h> +#include <stdbool.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <unistd.h> +#include <poll.h> +#include <libraw1394/raw1394.h> + +enum { + SERVER_FD = 0, + IEEE_FD = 1, + CLIENT_FD = 2, + DESCRIPTORS = 3 +}; + +static struct msg_state client_state; +static raw1394handle_t ieee_handle; +static struct pollfd pollfds[DESCRIPTORS] = {{0}}; + +static void verr(char *fmt, va_list va) { + int n = 0; + if (fmt) + n = vfprintf(stderr, fmt, va); + + if (errno) + fprintf(stderr, "%s%s\n", n ? ": " : "", strerror(errno)); + else + fprintf(stderr, "\n"); + exit(1); +} + +static void err(char *fmt, ...) { + va_list va; + va_start(va, fmt); + verr(fmt, va); + va_end(va); +} + +static void server_accept(void) { + int fd = accept(pollfds[SERVER_FD], NULL, NULL); + if (pollfds[CLIENT_FD].fd >= 0) { + close(fd); + return; + } + + if (fd < 0) { + if (errno != ECONNABORTED) + err("accept"); + else + return; + } + + pollfds[CLIENT_FD].fd = fd; + client_state.state = PARSE_VERSION_MESSAGE; + client_state.type = MESSAGE_INVALID; + if (client_state.buf) { + sdsclear(client_state.buf); + } else { + client_state.buf = sdsempty(); + } +} + +static void iterate(void) { + if (raw1394_loop_iterate(ieee_handle) < 0) + err("raw1394_loop_iterate"); +} + +/* 0b111111 = 0x3F + * if tags[x] < 0, then tag is not allocated + */ +#define TAG_NUM 0x40 +static long tag_to_handle[TAG_NUM]; + +static void handle_send_async(union msg *msg) { + switch (msg->send_async.tcode) { + case TCODE_WRITE_QUADLET_REQUEST: + case TCODE_WRITE_BLOCK_REQUEST: + raw1394_start_write(ieee_handle, msg->send_async.node, + msg->send_async.addr, msg->send_async.len, + msg->send_async.buf, msg->send_async.tlabel); + break; + case TCODE_READ_QUADLET_REQUEST: + case TCODE_READ_BLOCK_REQUEST: + raw1394_start_read(ieee_handle, msg->send_async.node, + msg->send_async.addr, msg->send_async.len, + msg->send_async.buf, msg->send_async.tlabel); + break; + case TCODE_WRITE_RESONSE: case TCODE_READ_QUADLET_RESPONSE: + case TCODE_READ_BLOCK_RESPONSE: + if (msg->send_async.tlabel < TAG_NUM && + tags_to_handle[msg->send_async.tlabel] >= 0) { + raw1394_send_rw_response(ieee_handle, msg->send_async.tcode, + msg->send_async.buf, msg->send_async.len, + tags_to_handle[msg->send_async.tlabel]); + tags_to_handle[msg->send_async.tlabel] = 0; + } + break; + /* FIXME: implement lock request */ + } +} + +static void handle_send_iso(union msg *msg) { + /* do nothing */ +} + +static int arm_handler(raw1394handle_t handle, raw1394_arm_allocation_t *arm, + int tcode, unsigned long long offset, int source_node_id, + int card, unsigned kernel_handle, size_t length, void *data) +{ + (void)handle; + uint8_t tag; + + /* Allocate tags. + * Tags are temporarily allocated since the real tag is stored in the + * kernel in the kernel_handle. + * + * firewire-cdev: bus is only 1023? + */ + for (tag = 0; tag < MAX_TAG; tag++) { + if (tag_to_handle[tag] < 0) + break; + } + if (tag == MAX_TAG) + return -1; + + tag_to_handle[tag] = kernel_handle; + if (msg_send_async(pollfds[SERVER_FD].fd, 1023, source_node_id, offset, + tcode, tag, length, data) < 0) + tag_to_handle[tag] = -1; + /* TODO: return an error response */ + return 0; +} + +static void handle_allocation(union msg *msg) { + /* may fail due to overlap: ignore */ + raw1394_arm_register(ieee_handle, msg->allocate.start, msg->allocate.length, + ARM_READ | ARM_WRITE | ARM_LOCK, + ARM_READ | ARM_WRITE | ARM_LOCK, + 0 /* ignored */); +} + +static bool read_client(void) { + char buf[512]; + ssize_t len; + int msgtype; + + len = read(pollfds[CLIENT_FD].fd, buf, sizeof(buf)); + if (len <= 0) + return false; + + client_state.buf = sdscatlen(client_state.buf, buf, len); + while (!parse_packet(fdstate)); + + return true; +} + +static bool client_process(void) { + if (fd->revents & POLLERR) + return false; + + if (fd->revents & POLLIN) + if (!read_client(fd, fdstate)) + return false; + + if (!(fd->revents & POLLIN) && fd->revents & POLLHUP) + return false; + return true; +} + +static int open_server(const char *port) { + int r; + struct addrinfo *serv; + int sock; + + if ((r = getaddrinfo(NULL, port, &(struct addrinfo){ + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_PASSIVE + }, &serv) != 0) { + err("getaddrinfo: %s", gai_strerror(r)); + } + + for (struct addrinfo *p = serv; p; p = p->ai_next) { + sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol); + if (sock < 0) + continue; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR) < 0) + continue; + if (bind(sock, p->ai_addr, p->ai_addrlen) < 0) + continue; + break; + } + if (!p) + err("socket"); + + freeaddrinfo(serv); + + if (listen(p, 5) < 0) + err("listen"); + + return sock; +} + +static int setup_port(int port) { + int num; + int fd; + static struct raw1394_portinfo ports[PORTSNUM] = {0}; + + ieee_handle = raw1394_new_handle(); + if (!ieee_handle) + err("raw1394_new_handle"); + + num = raw1394_get_port_info(ieee_handle, ports, PORTSNUM); + + do { + for (int i = 0; i < num && i < PORTSNUM; i++) + fprintf(stderr, "[%d/%d]: %s w/ %d\n", i + 1, num, + ports[i].name, ports[i].nodes); + errno = 0; + raw1394_set_port(ieee_handle, port); + } while (errno != ESTALE); + + if (errno) + die("raw1394_set_port"); + + fd = raw1394_get_fd(ieee_handle); + if (fd < 0) + die("raw1394_get_fd"); + + return fd; +} + +int main(void) { + pollfds[IEEE_FD].fd = setup_port(0); + pollfds[IEEE_FD].events = POLLIN | POLLPRI; + pollfds[SERVER_FD].fd = open_server("1394"); + pollfds[SERVER_FD].events = POLLIN | POLLPRI; + pollfds[CLIENT_FD].fd = -1; + + for (int i = 0; i < TAG_NUM; i++) + tag_to_handle[i] = -1; + + client_state.on_read[PARSE_SEND_ASYNC] = ieee_process; + + while (1) { + if (poll(pollfds, DESCRIPTORS, -1) <= 0) + err("poll"); + + if (pollfds[SERVER_FD].revents & (POLLIN | POLLPRI)) { + server_accept(); + } else if (pollfds[IEEE_FD].revents & (POLLIN | POLLPRI)) { + ieee_process(); + } + if (!client_process()) { + close(pollfds[CLIENT_FD].fd); + pollfds[CLIENT_FD].fd = -1; + + // Reset Firewire + raw1394_destroy_handle(ieee_handle); + pollfds[IEEE_FD].fd = setup_port(0); + } + } +} |
