2 * Copyright 2020 Niklas Ekström
3 * Based on a314d daemon for A314.
8 #include <linux/spi/spidev.h>
9 #include <linux/types.h>
11 #include <netinet/in.h>
12 #include <netinet/tcp.h>
14 #include <sys/epoll.h>
15 #include <sys/ioctl.h>
16 #include <sys/socket.h>
18 #include <sys/types.h>
40 #define LOGGER_TRACE 1
41 #define LOGGER_DEBUG 2
44 #define LOGGER_ERROR 5
46 #define LOGGER_SHOW LOGGER_INFO
48 #define logger_trace(...) do { if (LOGGER_TRACE >= LOGGER_SHOW) fprintf(stdout, __VA_ARGS__); } while (0)
49 #define logger_debug(...) do { if (LOGGER_DEBUG >= LOGGER_SHOW) fprintf(stdout, __VA_ARGS__); } while (0)
50 #define logger_info(...) do { if (LOGGER_INFO >= LOGGER_SHOW) fprintf(stdout, __VA_ARGS__); } while (0)
51 #define logger_warn(...) do { if (LOGGER_WARN >= LOGGER_SHOW) fprintf(stdout, __VA_ARGS__); } while (0)
52 #define logger_error(...) do { if (LOGGER_ERROR >= LOGGER_SHOW) fprintf(stderr, __VA_ARGS__); } while (0)
54 // Events that are communicated via IRQ from Amiga to Raspberry.
55 #define R_EVENT_A2R_TAIL 1
56 #define R_EVENT_R2A_HEAD 2
57 #define R_EVENT_STARTED 4
59 // Events that are communicated from Raspberry to Amiga.
60 #define A_EVENT_R2A_TAIL 1
61 #define A_EVENT_A2R_HEAD 2
63 // Offset relative to communication area for queue pointers.
64 #define A2R_TAIL_OFFSET 0
65 #define R2A_HEAD_OFFSET 1
66 #define R2A_TAIL_OFFSET 2
67 #define A2R_HEAD_OFFSET 3
69 // Packets that are communicated across physical channels (A2R and R2A).
71 #define PKT_CONNECT_RESPONSE 5
76 // Valid responses for PKT_CONNECT_RESPONSE.
78 #define CONNECT_UNKNOWN_SERVICE 3
80 // Messages that are communicated between driver and client.
81 #define MSG_REGISTER_REQ 1
82 #define MSG_REGISTER_RES 2
83 #define MSG_DEREGISTER_REQ 3
84 #define MSG_DEREGISTER_RES 4
85 #define MSG_READ_MEM_REQ 5
86 #define MSG_READ_MEM_RES 6
87 #define MSG_WRITE_MEM_REQ 7
88 #define MSG_WRITE_MEM_RES 8
90 #define MSG_CONNECT_RESPONSE 10
98 static sigset_t original_sigset;
100 static pthread_t thread_id;
101 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
103 static int server_socket = -1;
105 static int epfd = -1;
106 static int irq_fds[2];
108 extern "C" unsigned char fast_ram_array[];
109 extern "C" void write16(unsigned int address, unsigned int value);
111 // Register bank in 0xE90000 memory.
117 uint8_t r_enable; // Unused.
124 uint8_t a2r_buffer[256];
125 uint8_t r2a_buffer[256];
130 static bool a314_device_started = false;
132 static uint8_t channel_status[4];
133 static uint8_t channel_status_updated = 0;
135 static uint8_t recv_buf[256];
136 static uint8_t send_buf[256];
138 struct LogicalChannel;
139 struct ClientConnection;
141 #pragma pack(push, 1)
147 }; //} __attribute__((packed));
153 std::vector<uint8_t> data;
156 struct RegisteredService
159 ClientConnection *cc;
165 std::vector<uint8_t> data;
168 struct ClientConnection
175 MessageHeader header;
176 std::vector<uint8_t> payload;
178 std::list<MessageBuffer> message_queue;
180 std::list<LogicalChannel*> associations;
183 struct LogicalChannel
187 ClientConnection *association;
190 bool got_eos_from_ami;
191 bool got_eos_from_client;
193 std::list<PacketBuffer> packet_queue;
196 static void remove_association(LogicalChannel *ch);
197 static void clear_packet_queue(LogicalChannel *ch);
198 static void create_and_enqueue_packet(LogicalChannel *ch, uint8_t type, uint8_t *data, uint8_t length);
200 static std::list<ClientConnection> connections;
201 static std::list<RegisteredService> services;
202 static std::list<LogicalChannel> channels;
203 static std::list<LogicalChannel*> send_queue;
207 std::string service_name;
209 std::vector<std::string> arguments;
212 std::vector<OnDemandStart> on_demand_services;
214 static void load_config_file(const char *filename)
216 FILE *f = fopen(filename, "rt");
221 std::vector<char *> parts;
223 while (fgets(line, 256, f) != nullptr)
226 strcpy(org_line, line);
228 bool in_quotes = false;
231 for (int i = 0; i < 256; i++)
236 parts.push_back(&line[start]);
239 else if (line[i] == '"')
243 parts.push_back(&line[start]);
244 in_quotes = !in_quotes;
247 else if (isspace(line[i]) && !in_quotes)
251 parts.push_back(&line[start]);
256 if (parts.size() >= 2)
258 on_demand_services.emplace_back();
259 auto &e = on_demand_services.back();
260 e.service_name = parts[0];
261 e.program = parts[1];
262 for (int i = 1; i < parts.size(); i++)
263 e.arguments.push_back(std::string(parts[i]));
265 else if (parts.size() != 0)
266 logger_warn("Invalid number of columns in configuration file line: %s\n", org_line);
273 if (on_demand_services.empty())
274 logger_warn("No registered services\n");
277 static int init_server_socket()
279 server_socket = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
280 if (server_socket == -1)
282 logger_error("Failed to create server socket\n");
286 struct sockaddr_in address;
287 address.sin_family = AF_INET;
288 address.sin_addr.s_addr = INADDR_ANY;
289 address.sin_port = htons(7110);
291 int res = bind(server_socket, (struct sockaddr *)&address, sizeof(address));
294 logger_error("Bind to localhost:7110 failed\n");
298 listen(server_socket, 16);
303 static void shutdown_server_socket()
305 if (server_socket != -1)
306 close(server_socket);
310 void create_and_send_msg(ClientConnection *cc, int type, int stream_id, uint8_t *data, int length)
314 mb.data.resize(sizeof(MessageHeader) + length);
316 MessageHeader *mh = (MessageHeader *)&mb.data[0];
318 mh->stream_id = stream_id;
321 memcpy(&mb.data[sizeof(MessageHeader)], data, length);
323 if (!cc->message_queue.empty())
325 cc->message_queue.push_back(std::move(mb));
331 int left = mb.data.size() - mb.pos;
332 uint8_t *src = &mb.data[mb.pos];
333 ssize_t r = write(cc->fd, src, left);
336 if (errno == EAGAIN || errno == EWOULDBLOCK)
338 cc->message_queue.push_back(std::move(mb));
341 else if (errno == ECONNRESET)
343 // Do not close connection here; it will get done at some other place.
348 logger_error("Write failed unexpectedly with errno = %d\n", errno);
361 static void handle_msg_register_req(ClientConnection *cc)
363 uint8_t result = MSG_FAIL;
365 std::string service_name((char *)&cc->payload[0], cc->payload.size());
367 auto it = services.begin();
368 for (; it != services.end(); it++)
369 if (it->name == service_name)
372 if (it == services.end())
374 services.emplace_back();
376 RegisteredService &srv = services.back();
378 srv.name = std::move(service_name);
380 result = MSG_SUCCESS;
383 create_and_send_msg(cc, MSG_REGISTER_RES, 0, &result, 1);
386 static void handle_msg_deregister_req(ClientConnection *cc)
388 uint8_t result = MSG_FAIL;
390 std::string service_name((char *)&cc->payload[0], cc->payload.size());
392 for (auto it = services.begin(); it != services.end(); it++)
394 if (it->name == service_name && it->cc == cc)
397 result = MSG_SUCCESS;
402 create_and_send_msg(cc, MSG_DEREGISTER_RES, 0, &result, 1);
405 static void handle_msg_read_mem_req(ClientConnection *cc)
407 uint32_t address = *(uint32_t *)&(cc->payload[0]);
408 uint32_t length = *(uint32_t *)&(cc->payload[4]);
410 create_and_send_msg(cc, MSG_READ_MEM_RES, 0, &fast_ram_array[address], length);
413 static void handle_msg_write_mem_req(ClientConnection *cc)
415 uint32_t address = *(uint32_t *)&(cc->payload[0]);
416 uint32_t length = cc->payload.size() - 4;
418 memcpy(&fast_ram_array[address], &(cc->payload[4]), length);
420 create_and_send_msg(cc, MSG_WRITE_MEM_RES, 0, nullptr, 0);
423 static LogicalChannel *get_associated_channel_by_stream_id(ClientConnection *cc, int stream_id)
425 for (auto ch : cc->associations)
427 if (ch->stream_id == stream_id)
433 static void handle_msg_connect(ClientConnection *cc)
435 // We currently don't handle that a client tries to connect to a service on the Amiga.
438 static void handle_msg_connect_response(ClientConnection *cc)
440 LogicalChannel *ch = get_associated_channel_by_stream_id(cc, cc->header.stream_id);
444 create_and_enqueue_packet(ch, PKT_CONNECT_RESPONSE, &cc->payload[0], cc->payload.size());
446 if (cc->payload[0] != CONNECT_OK)
447 remove_association(ch);
450 static void handle_msg_data(ClientConnection *cc)
452 LogicalChannel *ch = get_associated_channel_by_stream_id(cc, cc->header.stream_id);
456 create_and_enqueue_packet(ch, PKT_DATA, &cc->payload[0], cc->header.length);
459 static void handle_msg_eos(ClientConnection *cc)
461 LogicalChannel *ch = get_associated_channel_by_stream_id(cc, cc->header.stream_id);
462 if (!ch || ch->got_eos_from_client)
465 ch->got_eos_from_client = true;
467 create_and_enqueue_packet(ch, PKT_EOS, nullptr, 0);
469 if (ch->got_eos_from_ami)
470 remove_association(ch);
473 static void handle_msg_reset(ClientConnection *cc)
475 LogicalChannel *ch = get_associated_channel_by_stream_id(cc, cc->header.stream_id);
479 remove_association(ch);
481 clear_packet_queue(ch);
482 create_and_enqueue_packet(ch, PKT_RESET, nullptr, 0);
485 static void handle_received_message(ClientConnection *cc)
487 switch (cc->header.type)
489 case MSG_REGISTER_REQ:
490 handle_msg_register_req(cc);
492 case MSG_DEREGISTER_REQ:
493 handle_msg_deregister_req(cc);
495 case MSG_READ_MEM_REQ:
496 handle_msg_read_mem_req(cc);
498 case MSG_WRITE_MEM_REQ:
499 handle_msg_write_mem_req(cc);
502 handle_msg_connect(cc);
504 case MSG_CONNECT_RESPONSE:
505 handle_msg_connect_response(cc);
514 handle_msg_reset(cc);
517 // This is bad, probably should disconnect from client.
518 logger_warn("Received a message of unknown type from client\n");
523 static void close_and_remove_connection(ClientConnection *cc)
525 shutdown(cc->fd, SHUT_WR);
529 auto it = services.begin();
530 while (it != services.end())
533 it = services.erase(it);
540 auto it = cc->associations.begin();
541 while (it != cc->associations.end())
545 clear_packet_queue(ch);
546 create_and_enqueue_packet(ch, PKT_RESET, nullptr, 0);
548 ch->association = nullptr;
551 it = cc->associations.erase(it);
555 for (auto it = connections.begin(); it != connections.end(); it++)
559 connections.erase(it);
565 static void remove_association(LogicalChannel *ch)
567 auto &ass = ch->association->associations;
568 ass.erase(std::find(ass.begin(), ass.end(), ch));
570 ch->association = nullptr;
574 static void clear_packet_queue(LogicalChannel *ch)
576 if (!ch->packet_queue.empty())
578 ch->packet_queue.clear();
579 send_queue.erase(std::find(send_queue.begin(), send_queue.end(), ch));
583 static void create_and_enqueue_packet(LogicalChannel *ch, uint8_t type, uint8_t *data, uint8_t length)
585 if (ch->packet_queue.empty())
586 send_queue.push_back(ch);
588 ch->packet_queue.emplace_back();
590 PacketBuffer &pb = ch->packet_queue.back();
592 pb.data.resize(length);
594 memcpy(&pb.data[0], data, length);
597 static void handle_pkt_connect(int channel_id, uint8_t *data, int plen)
599 for (auto &ch : channels)
601 if (ch.channel_id == channel_id)
603 // We should handle this in some constructive way.
604 // This signals that should reset all logical channels.
605 logger_error("Received a CONNECT packet on a channel that was believed to be previously allocated\n");
610 channels.emplace_back();
612 auto &ch = channels.back();
614 ch.channel_id = channel_id;
615 ch.association = nullptr;
617 ch.got_eos_from_ami = false;
618 ch.got_eos_from_client = false;
620 std::string service_name((char *)data, plen);
622 for (auto &srv : services)
624 if (srv.name == service_name)
626 ClientConnection *cc = srv.cc;
629 ch.stream_id = cc->next_stream_id;
631 cc->next_stream_id += 2;
632 cc->associations.push_back(&ch);
634 create_and_send_msg(ch.association, MSG_CONNECT, ch.stream_id, data, plen);
639 for (auto &on_demand : on_demand_services)
641 if (on_demand.service_name == service_name)
644 int status = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
647 logger_error("Unexpectedly not able to create socket pair.\n");
651 pid_t child = fork();
654 logger_error("Unexpectedly was not able to fork.\n");
662 // FIXE: The user should be configurable.
665 putenv("HOME=/home/pi");
667 std::vector<std::string> args(on_demand.arguments);
668 args.push_back("-ondemand");
669 args.push_back(std::to_string(fd));
670 std::vector<const char *> args_arr;
671 for (auto &arg : args)
672 args_arr.push_back(arg.c_str());
673 args_arr.push_back(nullptr);
675 execvp(on_demand.program.c_str(), (char* const*) &args_arr[0]);
682 int status = fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
685 logger_error("Unexpectedly unable to set close-on-exec flag on client socket descriptor; errno = %d\n", errno);
689 status = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
692 logger_error("Unexpectedly unable to set client socket to non blocking; errno = %d\n", errno);
697 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
699 connections.emplace_back();
701 ClientConnection &cc = connections.back();
703 cc.next_stream_id = 1;
706 struct epoll_event ev;
707 ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
709 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) != 0)
711 logger_error("epoll_ctl() failed unexpectedly with errno = %d\n", errno);
715 services.emplace_back();
717 RegisteredService &srv = services.back();
719 srv.name = std::move(service_name);
721 ch.association = &cc;
722 ch.stream_id = cc.next_stream_id;
724 cc.next_stream_id += 2;
725 cc.associations.push_back(&ch);
727 create_and_send_msg(ch.association, MSG_CONNECT, ch.stream_id, data, plen);
733 uint8_t response = CONNECT_UNKNOWN_SERVICE;
734 create_and_enqueue_packet(&ch, PKT_CONNECT_RESPONSE, &response, 1);
737 static void handle_pkt_data(int channel_id, uint8_t *data, int plen)
739 for (auto &ch : channels)
741 if (ch.channel_id == channel_id)
743 if (ch.association != nullptr && !ch.got_eos_from_ami)
744 create_and_send_msg(ch.association, MSG_DATA, ch.stream_id, data, plen);
751 static void handle_pkt_eos(int channel_id)
753 for (auto &ch : channels)
755 if (ch.channel_id == channel_id)
757 if (ch.association != nullptr && !ch.got_eos_from_ami)
759 ch.got_eos_from_ami = true;
761 create_and_send_msg(ch.association, MSG_EOS, ch.stream_id, nullptr, 0);
763 if (ch.got_eos_from_client)
764 remove_association(&ch);
771 static void handle_pkt_reset(int channel_id)
773 for (auto &ch : channels)
775 if (ch.channel_id == channel_id)
777 clear_packet_queue(&ch);
779 if (ch.association != nullptr)
781 create_and_send_msg(ch.association, MSG_RESET, ch.stream_id, nullptr, 0);
782 remove_association(&ch);
790 static void remove_channel_if_not_associated_and_empty_pq(int channel_id)
792 for (auto it = channels.begin(); it != channels.end(); it++)
794 if (it->channel_id == channel_id)
796 if (it->association == nullptr && it->packet_queue.empty())
804 static void handle_received_pkt(int ptype, int channel_id, uint8_t *data, int plen)
806 if (ptype == PKT_CONNECT)
807 handle_pkt_connect(channel_id, data, plen);
808 else if (ptype == PKT_DATA)
809 handle_pkt_data(channel_id, data, plen);
810 else if (ptype == PKT_EOS)
811 handle_pkt_eos(channel_id);
812 else if (ptype == PKT_RESET)
813 handle_pkt_reset(channel_id);
815 remove_channel_if_not_associated_and_empty_pq(channel_id);
818 static bool receive_from_a2r()
820 int head = channel_status[A2R_HEAD_OFFSET];
821 int tail = channel_status[A2R_TAIL_OFFSET];
822 int len = (tail - head) & 255;
828 memcpy(recv_buf, &ca.a2r_buffer[head], len);
832 memcpy(recv_buf, &ca.a2r_buffer[head], 256 - head);
836 memcpy(&recv_buf[len - tail], &ca.a2r_buffer[0], tail);
840 uint8_t *p = recv_buf;
841 while (p < recv_buf + len)
844 uint8_t ptype = *p++;
845 uint8_t channel_id = *p++;
846 handle_received_pkt(ptype, channel_id, p, plen);
850 channel_status[A2R_HEAD_OFFSET] = channel_status[A2R_TAIL_OFFSET];
851 channel_status_updated |= A_EVENT_A2R_HEAD;
855 static bool flush_send_queue()
857 int tail = channel_status[R2A_TAIL_OFFSET];
858 int head = channel_status[R2A_HEAD_OFFSET];
859 int len = (tail - head) & 255;
860 int left = 255 - len;
864 while (!send_queue.empty())
866 LogicalChannel *ch = send_queue.front();
867 PacketBuffer &pb = ch->packet_queue.front();
870 int plen = 3 + pb.data.size();
875 send_buf[pos++] = pb.data.size();
876 send_buf[pos++] = ptype;
877 send_buf[pos++] = ch->channel_id;
878 memcpy(&send_buf[pos], &pb.data[0], pb.data.size());
879 pos += pb.data.size();
881 ch->packet_queue.pop_front();
883 send_queue.pop_front();
885 if (!ch->packet_queue.empty())
886 send_queue.push_back(ch);
888 remove_channel_if_not_associated_and_empty_pq(ch->channel_id);
897 uint8_t *p = send_buf;
898 int at_end = 256 - tail;
899 if (at_end < to_write)
901 memcpy(&ca.r2a_buffer[tail], p, at_end);
907 memcpy(&ca.r2a_buffer[tail], p, to_write);
908 tail = (tail + to_write) & 255;
910 channel_status[R2A_TAIL_OFFSET] = tail;
911 channel_status_updated |= A_EVENT_R2A_TAIL;
915 static void read_channel_status()
917 channel_status[A2R_TAIL_OFFSET] = ca.a2r_tail;
918 channel_status[R2A_HEAD_OFFSET] = ca.r2a_head;
919 channel_status[R2A_TAIL_OFFSET] = ca.r2a_tail;
920 channel_status[A2R_HEAD_OFFSET] = ca.a2r_head;
921 channel_status_updated = 0;
924 static void write_channel_status()
926 if (channel_status_updated != 0)
928 ca.r2a_tail = channel_status[R2A_TAIL_OFFSET];
929 ca.a2r_head = channel_status[A2R_HEAD_OFFSET];
931 pthread_mutex_lock(&mutex);
932 ca.a_events |= channel_status_updated;
933 pthread_mutex_unlock(&mutex);
935 channel_status_updated = 0;
939 static void close_all_logical_channels()
943 auto it = channels.begin();
944 while (it != channels.end())
946 LogicalChannel &ch = *it;
948 if (ch.association != nullptr)
950 create_and_send_msg(ch.association, MSG_RESET, ch.stream_id, nullptr, 0);
951 remove_association(&ch);
954 it = channels.erase(it);
958 static void handle_a314_irq(uint8_t events)
963 if (events & R_EVENT_STARTED)
965 if (!channels.empty())
966 logger_info("Received STARTED event while logical channels are open -- closing channels\n");
968 close_all_logical_channels();
969 a314_device_started = true;
972 if (!a314_device_started)
975 read_channel_status();
977 bool any_rcvd = receive_from_a2r();
978 bool any_sent = flush_send_queue();
980 if (any_rcvd || any_sent)
981 write_channel_status();
984 static void handle_client_connection_event(ClientConnection *cc, struct epoll_event *ev)
986 if (ev->events & EPOLLERR)
988 logger_warn("Received EPOLLERR for client connection\n");
989 close_and_remove_connection(cc);
993 if (ev->events & EPOLLIN)
1000 if (cc->payload.empty())
1002 left = sizeof(MessageHeader) - cc->bytes_read;
1003 dst = (uint8_t *)&(cc->header) + cc->bytes_read;
1007 left = cc->header.length - cc->bytes_read;
1008 dst = &cc->payload[cc->bytes_read];
1011 ssize_t r = read(cc->fd, dst, left);
1014 if (errno == EAGAIN || errno == EWOULDBLOCK)
1017 logger_error("Read failed unexpectedly with errno = %d\n", errno);
1023 logger_info("Received End-of-File on client connection\n");
1024 close_and_remove_connection(cc);
1029 cc->bytes_read += r;
1033 if (cc->payload.empty())
1035 if (cc->header.length == 0)
1037 logger_trace("header: length=%d, stream_id=%d, type=%d\n", cc->header.length, cc->header.stream_id, cc->header.type);
1038 handle_received_message(cc);
1042 cc->payload.resize(cc->header.length);
1047 logger_trace("header: length=%d, stream_id=%d, type=%d\n", cc->header.length, cc->header.stream_id, cc->header.type);
1048 handle_received_message(cc);
1049 cc->payload.clear();
1057 if (ev->events & EPOLLOUT)
1059 while (!cc->message_queue.empty())
1061 MessageBuffer &mb = cc->message_queue.front();
1063 int left = mb.data.size() - mb.pos;
1064 uint8_t *src = &mb.data[mb.pos];
1065 ssize_t r = write(cc->fd, src, left);
1068 if (errno == EAGAIN || errno == EWOULDBLOCK)
1070 else if (errno == ECONNRESET)
1072 close_and_remove_connection(cc);
1077 logger_error("Write failed unexpectedly with errno = %d\n", errno);
1084 cc->message_queue.pop_front();
1089 static void handle_server_socket_ready()
1091 struct sockaddr_in address;
1092 int alen = sizeof(struct sockaddr_in);
1094 int fd = accept(server_socket, (struct sockaddr *)&address, (socklen_t *)&alen);
1097 logger_error("Accept failed unexpectedly with errno = %d\n", errno);
1101 int status = fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
1104 logger_error("Unexpectedly unable to set close-on-exec flag on client socket descriptor; errno = %d\n", errno);
1108 status = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
1111 logger_error("Unexpectedly unable to set client socket to non blocking; errno = %d\n", errno);
1116 setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
1118 connections.emplace_back();
1120 ClientConnection &cc = connections.back();
1122 cc.next_stream_id = 1;
1125 struct epoll_event ev;
1126 ev.events = EPOLLIN | EPOLLOUT | EPOLLET;
1128 if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) != 0)
1130 logger_error("epoll_ctl() failed unexpectedly with errno = %d\n", errno);
1135 static void main_loop()
1137 bool shutting_down = false;
1142 struct epoll_event ev;
1143 int timeout = shutting_down ? 10000 : -1;
1144 int n = epoll_pwait(epfd, &ev, 1, timeout, &original_sigset);
1149 logger_info("Received SIGTERM\n");
1151 shutdown_server_socket();
1153 while (!connections.empty())
1154 close_and_remove_connection(&connections.front());
1156 if (flush_send_queue())
1157 write_channel_status();
1159 if (!channels.empty())
1160 shutting_down = true;
1166 logger_error("epoll_pwait failed with unexpected errno = %d\n", errno);
1176 logger_error("epoll_pwait returned 0 which is unexpected since no timeout was set\n");
1182 if (ev.data.fd == irq_fds[1])
1185 if (read(irq_fds[1], &events, 1) != 1)
1187 logger_error("Read from interrupt socket pair, and unexpectedly didn't return 1 byte\n");
1191 handle_a314_irq(events);
1193 else if (ev.data.fd == server_socket)
1195 logger_trace("Epoll event: server socket is ready, events = %d\n", ev.events);
1196 handle_server_socket_ready();
1200 logger_trace("Epoll event: client socket is ready, events = %d\n", ev.events);
1202 auto it = connections.begin();
1203 for (; it != connections.end(); it++)
1205 if (it->fd == ev.data.fd)
1209 if (it == connections.end())
1211 logger_error("Got notified about an event on a client connection that supposedly isn't currently open\n");
1215 ClientConnection *cc = &(*it);
1216 handle_client_connection_event(cc, &ev);
1218 if (flush_send_queue())
1219 write_channel_status();
1225 static void sigterm_handler(int signo)
1229 static void init_sigterm()
1234 sigaddset(&ss, SIGTERM);
1235 sigprocmask(SIG_BLOCK, &ss, &original_sigset);
1237 struct sigaction sa;
1238 sa.sa_handler = sigterm_handler;
1239 sigemptyset(&sa.sa_mask);
1241 sigaction(SIGTERM, &sa, NULL);
1245 static int init_driver()
1249 if (init_server_socket() != 0)
1252 int err = socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, irq_fds);
1255 logger_error("Unable to create socket pair, errno = %d\n", errno);
1259 epfd = epoll_create1(EPOLL_CLOEXEC);
1263 struct epoll_event ev;
1264 ev.events = EPOLLIN;
1265 ev.data.fd = irq_fds[1];
1266 if (epoll_ctl(epfd, EPOLL_CTL_ADD, irq_fds[1], &ev) != 0)
1269 ev.events = EPOLLIN;
1270 ev.data.fd = server_socket;
1271 if (epoll_ctl(epfd, EPOLL_CTL_ADD, server_socket, &ev) != 0)
1277 static void shutdown_driver()
1282 shutdown_server_socket();
1285 static void *thread_start(void *arg)
1292 static void write_r_events(uint8_t events)
1294 if (write(irq_fds[0], &events, 1) != 1)
1295 logger_error("Write to interrupt socket pair did not return 1\n");
1304 std::string conf_filename("/etc/opt/a314/a314d.conf");
1306 load_config_file(conf_filename.c_str());
1308 int err = init_driver();
1315 err = pthread_create(&thread_id, NULL, thread_start, NULL);
1318 logger_error("pthread_create failed with err = %d\n", err);
1325 void a314_process_events()
1327 if (ca.a_events & ca.a_enable)
1329 write16(0xdff09c, 0x8008);
1334 unsigned int a314_read_memory_8(unsigned int address)
1336 if (address >= sizeof(ca))
1340 if (address == offsetof(ComArea, a_events))
1342 pthread_mutex_lock(&mutex);
1345 pthread_mutex_unlock(&mutex);
1349 uint8_t *p = (uint8_t *)&ca;
1356 unsigned int a314_read_memory_16(unsigned int address)
1362 unsigned int a314_read_memory_32(unsigned int address)
1368 void a314_write_memory_8(unsigned int address, unsigned int value)
1370 if (address >= sizeof(ca))
1375 case offsetof(ComArea, a_events):
1376 // a_events is not writable.
1379 case offsetof(ComArea, r_events):
1381 write_r_events((uint8_t)value);
1386 uint8_t *p = (uint8_t *)&ca;
1387 p[address] = (uint8_t)value;
1393 void a314_write_memory_16(unsigned int address, unsigned int value)
1398 void a314_write_memory_32(unsigned int address, unsigned int value)