summaryrefslogtreecommitdiff
path: root/tools/pkg/2/ps2_driver/src/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/pkg/2/ps2_driver/src/main.c')
-rw-r--r--tools/pkg/2/ps2_driver/src/main.c289
1 files changed, 278 insertions, 11 deletions
diff --git a/tools/pkg/2/ps2_driver/src/main.c b/tools/pkg/2/ps2_driver/src/main.c
index 78fadd7..6f7acdc 100644
--- a/tools/pkg/2/ps2_driver/src/main.c
+++ b/tools/pkg/2/ps2_driver/src/main.c
@@ -1,40 +1,307 @@
#include <orange/dev.h>
#include <orange/io.h>
+#include <orange/log.h>
#include <stdio.h>
-#include <unistd.h>
#include <fcntl.h>
+#include <poll.h>
+
+#include <stdlib.h>
#include <stdint.h>
#include <string.h>
+#include <unistd.h>
+
+#define STATUS 0x64
+#define COMMAND 0x64
+#define DATA 0x60
+#define RESEND 0xFE
+#define ACK 0xFA
+#define ECHO 0xEE
+
+static inline char ps2_isfull() {
+ return (inb(0x64) & 2) == 2;
+}
+
+static inline char ps2_wait() {
+ return (inb(0x64) & 1) == 0;
+}
+
+void ps2_writecmd(uint8_t cmd) {
+ while(ps2_isfull());
+ outb(0x64,cmd);
+}
+
+void ps2_writedata(uint8_t cmd) {
+ while(ps2_isfull());
+ outb(0x60,cmd);
+}
+
+void ps2_flush() {
+ int timeout = 1000;
+ while((inb(STATUS) & 1) && --timeout > 0) inb(DATA);
+}
+
+uint8_t ps2_read() {
+ while(ps2_wait());
+ return inb(0x60);
+}
+
+uint8_t ps2_readtimeout() {
+ int timeout = 100;
+ while(ps2_wait() && --timeout > 0) usleep(100);
+ if(timeout <= 0)
+ return 0;
+ return inb(0x60);
+}
+
+uint8_t ps2_readlongtimeout() {
+ int timeout = 100;
+ while(ps2_wait() && --timeout > 0) usleep(1000);
+ if(timeout <= 0)
+ return 0;
+ return inb(0x60);
+}
+
+
+
+void ps2_writeport(uint8_t port, uint8_t cmd) {
+ if(port == 2)
+ ps2_writecmd(0xD4);
+
+ ps2_writedata(cmd);
+}
+
+int dual_channel = 0;
+
+void ps2_disableport(uint8_t port) {
+ ps2_writeport(port,0xF5);
+ int retry = 0;
+ while(1) {
+ uint8_t response = ps2_readtimeout();
+ if(!response)
+ break;
+ else if(response == RESEND) {
+ if(++retry == 10)
+ break;
+ ps2_writeport(port,0xF5);
+ }
+ }
+ ps2_flush();
+}
+
+void ps2_enableport(uint8_t port) {
+ ps2_writeport(port,0xF4);
+ int retry = 0;
+ while(1) {
+ uint8_t response = ps2_readtimeout();
+ if(!response)
+ break;
+ else if(response == ACK)
+ break;
+ else if(response == RESEND) {
+ if(++retry == 10)
+ break;
+ ps2_writeport(port,0xF4);
+ }
+ }
+ ps2_flush();
+}
+
+char ps2_selftest(uint8_t port) {
+ ps2_disableport(port);
+ ps2_writeport(port,0xFF);
+ int retry = 0;
+ while(1) {
+ uint8_t response = ps2_readtimeout();
+ if(!response)
+ break;
+ else if(response == RESEND) {
+ if(++retry == 10)
+ break;
+ ps2_writeport(port,0xFF);
+ } else if(response == ACK)
+ break;
+ }
+
+ while(1) {
+ uint8_t response = ps2_readlongtimeout();
+ if(!response)
+ break;
+ else if(response == 0xAA)
+ break;
+ else if(response == 0xFC) {
+ log(LEVEL_MESSAGE_FAIL,"Failed to test PS/2 port %d\n",port);
+ return 0;
+ }
+ }
+
+ // used from astral src
+ while(1) {
+ if(!ps2_readtimeout())
+ break;
+ }
+
+ ps2_flush();
+ return 1;
+}
+
+#define MOUSE_LB (1 << 0)
+#define MOUSE_RB (1 << 1)
+#define MOUSE_MB (1 << 2)
+#define MOUSE_B4 (1 << 3)
+#define MOUSE_B5 (1 << 4)
+
+typedef struct {
+ unsigned char buttons;
+ unsigned char x;
+ unsigned char y;
+ unsigned char z;
+} __attribute__((packed)) mouse_packet_t;
+
int main() {
+
+ int pid = fork();
+
+ if(pid > 0)
+ exit(0);
+
int masterinput = open("/dev/masterps2keyboard",O_RDWR);
+ int mastermouse = open("/dev/mastermouse",O_RDWR);
+
+ if(mastermouse < 0) {
+ perror("Can't open /dev/mastermouse device");
+ exit(-1);
+ }
+
+ if(masterinput < 0) {
+ perror("Can't open /dev/masterkeyboard device");
+ exit(-1);
+ }
liborange_setup_iopl_3();
int pic = open("/dev/pic",O_RDWR);
+ if(pic < 0) {
+ perror("Can't open /dev/pic device");
+ exit(-1);
+ }
+
+ ps2_writecmd(0xAD);
+ ps2_writecmd(0xA7);
+
+ ps2_writecmd(0x20);
+ uint8_t config = ps2_read();
+ config |= (1 << 0) | (1 << 1) | (1 << 6);
+ ps2_writecmd(0x60);
+ ps2_writedata(config);
+
+ ps2_enableport(1);
+ ps2_enableport(2);
+
+ // dont need identify just know what port 1 is kbd port 2 is mouse
+
liborange_pic_create_t irq_create_request;
irq_create_request.flags = 0;
+
+ ps2_writecmd(0xAE);
+
irq_create_request.irq = 1;
+ write(pic,&irq_create_request,sizeof(liborange_pic_create_t));
+ ps2_writecmd(0xA8);
+
+ irq_create_request.irq = 12;
write(pic,&irq_create_request,sizeof(liborange_pic_create_t));
- close(pic);
+
+ ps2_flush();
+
+ int irq1 = open("/dev/irq1",O_RDWR);
+ int irq12 = open("/dev/irq12",O_RDWR);
+
+ struct pollfd irq_fds[2];
+
+ irq_fds[0].events = POLLIN;
+ irq_fds[0].fd = irq1;
+ irq_fds[1].events = POLLIN;
+ irq_fds[1].fd = irq12;
+
+ int mouse_seq = 0;
- int kbd_irq = open("/dev/irq1",O_RDWR);
- char val = 0;
- while(1) {
- int count = read(kbd_irq,&val,1);
- if(count && val == 1) {
- write(kbd_irq,&val,1); /* Ask kernel to unmask this irq */
- while((inb(0x64) & 1)) {
- uint8_t scancode = inb(0x60);
- write(masterinput,&scancode,1);
+ if(1) {
+
+ uint8_t mouse_buffer[4] = {0,0,0,0};
+
+ while(1) {
+ int num_events = poll(irq_fds,2,500);
+ if(num_events < 0) {
+ perror("Failed to poll irq fds");
+ exit(-1);
+ }
+
+ if(num_events == 0) {
+ mouse_seq = 0;
+ ps2_flush();
+ int val = 1;
+ write(irq1,&val,1);
+ write(irq12,&val,1);
}
+
+ if(irq_fds[1].revents & POLLIN) {
+ char val = 0;
+ int count = read(irq12,&val,1);
+ if(count && val == 1) {
+
+ mouse_buffer[mouse_seq++] = inb(DATA);
+
+ if(mouse_seq != 3) {
+ write(irq1,&val,1);
+ write(irq12,&val,1);
+ continue; }
+
+ mouse_packet_t packet = {0,0,0,0};
+
+ packet.x = mouse_buffer[1] - (mouse_buffer[0] & 0x10 ? 0x100 : 0);
+ packet.y = mouse_buffer[2] - (mouse_buffer[0] & 0x20 ? 0x100 : 0);
+ packet.z = (mouse_buffer[3] & 0x7) * (mouse_buffer[3] & 0x8 ? -1 : 1);
+
+ packet.buttons |= (mouse_buffer[0] & 1) ? MOUSE_LB : 0;
+ packet.buttons |= (mouse_buffer[0] & 2) ? MOUSE_RB : 0;
+ packet.buttons |= (mouse_buffer[0] & 4) ? MOUSE_MB : 0;
+
+ packet.buttons |= (mouse_buffer[0] & 0x10) ? MOUSE_B4 : 0;
+ packet.buttons |= (mouse_buffer[0] & 0x20) ? MOUSE_B5 : 0;
+
+ write(mastermouse,&packet,4);
+
+ mouse_seq = 0;
+
+ write(irq1,&val,1);
+ write(irq12,&val,1);
+
+ }
+ }
+
+ if(irq_fds[0].revents & POLLIN) {
+ char val = 0;
+ int count = read(irq1,&val,1);
+ if(count && val == 1) {
+ while((inb(0x64) & 1)) {
+ uint8_t scancode = inb(0x60);
+ write(masterinput,&scancode,1);
+ }
+ write(irq1,&val,1); /* Ask kernel to unmask this irq */
+ write(irq12,&val,1); /* irq 12 and irq 1 are connected */
+ }
+ }
+
}
}
+ exit(0);
+
} \ No newline at end of file