summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames <git@panaceas.org>2014-05-05 17:50:20 +0100
committerJames <git@panaceas.org>2014-05-05 17:50:20 +0100
commit470457e22a1b5537013603d5e367c51e47bb61bf (patch)
tree6b72d32bfd9eaec31c8c520d18782ccaebc01759
downloadkmd_usb-470457e22a1b5537013603d5e367c51e47bb61bf.tar.gz
kmd_usb-470457e22a1b5537013603d5e367c51e47bb61bf.tar.bz2
kmd_usb-470457e22a1b5537013603d5e367c51e47bb61bf.zip
fish
-rw-r--r--Makefile40
-rw-r--r--dispatch.c233
-rw-r--r--input.c130
-rw-r--r--kmd.c89
-rw-r--r--layout.c156
-rw-r--r--lcd.c328
-rw-r--r--libdpf/Makefile12
-rw-r--r--libdpf/bootload.c379
-rw-r--r--libdpf/dpf.h189
-rw-r--r--libdpf/dpflib.c436
-rw-r--r--libdpf/flash.h19
-rw-r--r--libdpf/fwload.c121
-rw-r--r--libdpf/rawusb.c195
-rw-r--r--libdpf/scsi.c412
-rw-r--r--libdpf/sglib.h19
-rw-r--r--libdpf/spiflash.h30
-rw-r--r--libdpf/usbuser.h29
-rw-r--r--lirc.h168
-rw-r--r--map.c167
-rw-r--r--output.c441
-rw-r--r--output_map.h871
-rw-r--r--project.h57
-rw-r--r--prototypes.h52
-rw-r--r--status.c141
-rw-r--r--video_switch.c365
25 files changed, 5079 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..76953c5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,40 @@
+CSRCS=kmd.c status.c lcd.c input.c dispatch.c output.c map.c layout.c video_switch.c
+
+
+WHERE=$(shell hostname | sed -e 's/^.*medaka.james.local/BROMIUM/g' -e 's/^.*panaceas.*/HOME/g' )
+
+CFLAGS=-g -Wall -D${WHERE} -Wno-unused
+
+all: kmd
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $^
+
+OBJS=${CSRCS:%.c=%.o}
+
+
+kmd: ${OBJS} libdpf/libdpf.a
+ $(CC) -o $@ ${OBJS} libdpf/libdpf.a -lusb
+
+
+libdpf/libdpf.a:
+ make -C libdpf
+
+clean:
+ make -C libdpf clean
+ rm -f *.o kmd *~
+
+protos:
+ echo > prototypes.h
+ cproto -e -v ${CSRCS} >> prototypes.tmp
+ mv -f prototypes.tmp prototypes.h
+
+install: kmd
+ sleep 1
+ rsync -varP kmd /usr/local/bin/kmd
+ killall -9 kmd
+ telinit q
+
+
+
+
diff --git a/dispatch.c b/dispatch.c
new file mode 100644
index 0000000..ec8da7b
--- /dev/null
+++ b/dispatch.c
@@ -0,0 +1,233 @@
+#include "project.h"
+
+#define N_SCREENS 4
+#define GRACE 10
+
+#define W 2048
+#define H 2048
+
+static int current_computer = 0;
+static int keys_down;
+static int current_x, current_y;
+static int mouse_button[0x10];
+
+
+void
+dispatch_key (int key, int ud)
+{
+ static int keys[KEY_MAX];
+
+// ignore autorepeat
+ if (ud == 2)
+ return;
+
+ if (keys[key] != ud)
+ {
+ keys[key] = ud;
+ if (ud)
+ keys_down++;
+ else
+ keys_down--;
+ }
+
+ if (ud && keys[KEY_RIGHTALT] && (key == KEY_RIGHTMETA))
+ {
+ lcd_off();
+ output_reset ();
+ status_reset ();
+ }
+
+ if (ud && keys[KEY_LEFTALT] && (key == KEY_LEFTMETA))
+ layout_toggle_lock (current_computer);
+
+ send_keyboard_event (current_computer, key, ud);
+}
+
+void
+dispatch_mouse_button (int button, int ud)
+{
+
+ if (mouse_button[button] != ud)
+ {
+ mouse_button[button] = ud;
+ if (ud)
+ keys_down++;
+ else
+ keys_down--;
+ }
+
+ send_mouse_event (current_computer, current_x, current_y, 0,
+ mouse_button[0], mouse_button[2], mouse_button[1]);
+}
+
+
+void
+dispatch_mouse_wheel (int d)
+{
+ send_mouse_event (current_computer, current_x, current_y, d,
+ mouse_button[0], mouse_button[2], mouse_button[1]);
+}
+
+static int
+accell (int a)
+{
+
+ int m = a / 10;
+
+ if (m < 0)
+ m = -m;
+ if (m == 0)
+ m = 1;
+ if (m > 4)
+ m = 4;
+
+ return m * a;
+}
+
+
+void
+dispatch_mouse_motion (int rx, int ry)
+{
+
+ ry += ry;
+
+ rx = accell (rx);
+ ry = accell (ry);
+
+ current_x += rx;
+ current_y += ry;
+
+ if (current_y < 0)
+ current_y = 0;
+ if (current_y >= H)
+ current_y = H - 1;
+
+ if (current_x < 0)
+ {
+ if (map_grace_left (current_computer))
+ {
+ if (keys_down)
+ {
+ current_x = 0;
+ }
+ else if (current_x < -GRACE)
+ {
+ if (map_switch_left (&current_computer))
+ {
+ current_x = W - 1;
+ }
+ else
+ {
+ current_x = -GRACE;
+ }
+ }
+ }
+ else
+ {
+ if (map_switch_left (&current_computer))
+ {
+ current_x = W - 1;
+ }
+ else
+ {
+ current_x = 0;
+ }
+ }
+ }
+
+ if (current_x >= W)
+ {
+ if (map_grace_right (current_computer))
+ {
+ if (keys_down)
+ {
+ current_x = W - 1;
+ }
+ else if (current_x > (W + GRACE))
+ {
+ if (map_switch_right (&current_computer))
+ {
+ current_x = 0;
+ }
+ else
+ {
+ current_x = W + GRACE;
+ }
+ }
+ }
+ else
+ {
+ if (map_switch_right (&current_computer))
+ {
+ current_x = 0;
+ }
+ else
+ {
+ current_x = W - 1;
+ }
+ }
+ }
+
+ send_mouse_event (current_computer, current_x, current_y, 0,
+ mouse_button[0], mouse_button[2], mouse_button[1]);
+}
+
+
+void
+dispatch_event (struct input_event *ev)
+{
+ static int rel_x, rel_y, rel_wheel;
+
+ if (ev->type == EV_REL)
+ {
+
+ if (ev->code == REL_X)
+ rel_x = ev->value;
+ if (ev->code == REL_Y)
+ rel_y = ev->value;
+ if (ev->code == REL_WHEEL)
+ rel_wheel = ev->value;
+ }
+ else if (ev->type == EV_KEY)
+ {
+ switch (ev->code)
+ {
+ case BTN_LEFT:
+ case BTN_RIGHT:
+ case BTN_MIDDLE:
+ case BTN_SIDE:
+ case BTN_EXTRA:
+ case BTN_FORWARD:
+ case BTN_BACK:
+ case BTN_TASK:
+ dispatch_mouse_button (ev->code - BTN_LEFT, ev->value);
+ break;
+ default:
+ dispatch_key (ev->code, ev->value);
+ }
+ }
+ else if (ev->type == EV_SYN)
+ {
+ if (rel_x || rel_y)
+ {
+ dispatch_mouse_motion (rel_x, rel_y);
+ rel_x = 0;
+ rel_y = 0;
+ }
+ if (rel_wheel)
+ {
+ dispatch_mouse_wheel (rel_wheel);
+ rel_wheel = 0;
+ }
+
+ }
+
+//print_event(ev);
+
+}
+
+void
+dispatch_init (void)
+{
+ current_computer = map_init ();
+}
diff --git a/input.c b/input.c
new file mode 100644
index 0000000..bb1d82d
--- /dev/null
+++ b/input.c
@@ -0,0 +1,130 @@
+#include "project.h"
+
+input_dev_t *input_devs = NULL;
+
+
+static void
+set_nonblocking (int fd)
+{
+ long arg = 0;
+ arg = fcntl (fd, F_GETFL, arg);
+ arg |= O_NONBLOCK;
+ fcntl (fd, F_SETFL, arg);
+}
+
+static char *
+input_dev_name (int i)
+{
+ static char fn[1024];
+ sprintf (fn, "/dev/input/event%d", i);
+ return fn;
+}
+
+static input_dev_t *
+get_input_dev (int id)
+{
+ input_dev_t *ret;
+ int fd;
+ unsigned short ids[4];
+ char *fn;
+
+ for (ret = input_devs; ret; ret = ret->next)
+ if (ret->id == id)
+ return ret;
+
+
+ fn = input_dev_name (id);
+
+ fd = open (fn, O_RDWR);
+ if (fd < 0)
+ return NULL;
+
+ set_nonblocking (fd);
+
+ ret = malloc (sizeof (*ret));
+ bzero (ret, sizeof (*ret));
+
+ ret->id = id;
+ ret->fd = fd;
+
+ ioctl (fd, EVIOCGID, ids);
+
+ if ((ids[ID_VENDOR] == 0xea0) && (ids[ID_PRODUCT] == 0x2211))
+ ret->blacklistid = 1;
+
+ printf
+ ("New input device %s (%d) bus 0x%x vendor 0x%x product 0x%x version 0x%x\n",
+ fn, id, ids[ID_BUS], ids[ID_VENDOR], ids[ID_PRODUCT], ids[ID_VERSION]);
+
+ ret->next = input_devs;
+ input_devs = ret;
+
+ return ret;
+}
+
+static void
+free_input_dev (input_dev_t * d)
+{
+ printf ("Removid input device %s (%d)\n", input_dev_name (d->id), d->id);
+
+ if (d->fd > -1)
+ close (d->fd);
+ free (d);
+}
+
+
+void
+scan_input_devs (void)
+{
+ DIR *dir = opendir ("/dev/input");
+ struct dirent *de;
+ int i;
+ input_dev_t *id, **idp;
+ int version;
+
+
+ for (idp = &input_devs; (id = *idp);)
+ {
+ id->present = 0;
+ if (access (input_dev_name (id->id), F_OK)
+ || ioctl (id->fd, EVIOCGVERSION, &version))
+ {
+ *idp = id->next;
+ free_input_dev (id);
+ }
+ else
+ {
+ idp = &id->next;
+ }
+ }
+
+ if (dir)
+ {
+ while ((de = readdir (dir)))
+ {
+ if (!strcmp (de->d_name, "event"))
+ continue;
+ i = atoi (de->d_name + 5);
+ id = get_input_dev (i);
+ if (id)
+ id->present = 1;
+ }
+ closedir (dir);
+ }
+
+
+ for (idp = &input_devs; (id = *idp);)
+ {
+ if (!id->present)
+ {
+ *idp = id->next;
+ free_input_dev (id);
+ }
+ else
+ {
+ idp = &id->next;
+ }
+ }
+
+
+}
diff --git a/kmd.c b/kmd.c
new file mode 100644
index 0000000..ca2a66a
--- /dev/null
+++ b/kmd.c
@@ -0,0 +1,89 @@
+#include "project.h"
+
+
+
+
+static void
+check_bored (int b)
+{
+ static int lcd = 1;
+
+ if ((b > 8) && (lcd))
+ {
+ lcd_off ();
+ lcd = 0;
+ }
+
+ if ((b == 0) && (!lcd))
+ {
+ lcd_on ();
+ lcd = 1;
+ }
+}
+
+
+#define SCAN_TIME 4
+
+
+int
+main (int argc, char *argv[])
+{
+ struct input_event ev;
+ struct timeval tv = { 0 };
+ fd_set rfds;
+ int n;
+ int bored = 0;
+
+ usb_init ();
+
+ status_init ();
+
+ dispatch_init ();
+
+ scan_output_devs (1);
+ for (;;)
+ {
+ input_dev_t *id;
+
+ if (!tv.tv_usec && !tv.tv_sec)
+ {
+ scan_input_devs ();
+ scan_output_devs (0);
+ tv.tv_sec = SCAN_TIME;
+ bored++;
+ check_bored (bored);
+ }
+
+
+ FD_ZERO (&rfds);
+ n = 0;
+ for (id = input_devs; id; id = id->next)
+ {
+ if (id->fd == -1 || id->blacklistid)
+ continue;
+ FD_SET (id->fd, &rfds);
+ if (id->fd >= n)
+ n = id->fd + 1;
+ }
+
+ if (!select (n, &rfds, NULL, NULL, &tv))
+ continue;
+
+ for (id = input_devs; id; id = id->next)
+ {
+ if (id->fd == -1 || id->blacklistid)
+ continue;
+ if (!FD_ISSET (id->fd, &rfds))
+ continue;
+ if (read (id->fd, &ev, sizeof (struct input_event)) ==
+ sizeof (struct input_event))
+ {
+ dispatch_event (&ev);
+ bored = 0;
+ check_bored (bored);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/layout.c b/layout.c
new file mode 100644
index 0000000..32f1cdf
--- /dev/null
+++ b/layout.c
@@ -0,0 +1,156 @@
+#include "project.h"
+
+static int computer_to_console[N_COMPUTER + 1];
+static int console_to_computer[N_CONSOLE + 1];
+static int console_locked[N_CONSOLE + 1];
+
+static MM *mm;
+
+int
+layout_computer_to_console (int computer)
+{
+ if ((computer < 1) || (computer > N_COMPUTER))
+ return 0;
+ return computer_to_console[computer];
+
+}
+
+int
+layout_console_to_computer (int console)
+{
+ if ((console < 1) || (console > N_CONSOLE))
+ return 0;
+ return console_to_computer[console];
+}
+
+#ifdef LAYOUT_NULL
+int
+layout_possible (int console, int computer)
+{
+ if ((console < 1) || (console > N_CONSOLE))
+ return 0;
+ if ((computer < 1) || (computer > N_COMPUTER))
+ return 0;
+
+ if (console_locked[console])
+ return 0;
+
+return 1;
+}
+#elif defined(LAYOUT_HOME)
+int
+layout_possible (int console, int computer)
+{
+ if ((console < 1) || (console > N_CONSOLE))
+ return 0;
+ if ((computer < 1) || (computer > N_COMPUTER))
+ return 0;
+
+ if (console_locked[console])
+ return 0;
+
+ switch (computer)
+ {
+ case 1:
+ case 2:
+ case 3:
+ if (console != 1)
+ return 0;
+ return 1;
+ }
+
+ switch (console)
+ {
+ case 1:
+ if (computer > 3)
+ return 0;
+ return 1;
+ }
+
+
+ return 1;
+}
+#endif
+
+void
+layout_map (int console, int computer)
+{
+ int oc;
+
+ if ((console < 1) || (console > N_CONSOLE))
+ return;
+ if ((computer < 1) || (computer > N_COMPUTER))
+ return;
+
+ oc = console_to_computer[console];
+
+ if ((oc > 0) && (oc <= N_COMPUTER))
+ {
+ computer_to_console[oc] = 0;
+ }
+ computer_to_console[computer] = console;
+ console_to_computer[console] = computer;
+
+#ifdef LAYOUT_HOME
+ switch (console)
+ {
+ case 1:
+ VS_set (mm, 4 - computer);
+ break;
+ case 2:
+ MM_set (mm, computer - 3, -1);
+ break;
+ case 3:
+ MM_set (mm, -1, computer - 3);
+ break;
+ }
+#endif
+
+}
+
+void
+layout_status (int active_computer)
+{
+ int i;
+ for (i = 1; i <= N_COMPUTER; ++i)
+ {
+ int console = layout_computer_to_console (i);
+ status_draw_computer (i, console_locked[console], console,
+ active_computer == i, 0);
+ }
+
+ for (i = 1; i <= N_CONSOLE; ++i)
+ {
+ int computer = layout_console_to_computer (i);
+ status_draw_console (i, console_locked[i], computer,
+ active_computer == computer, 0);
+ }
+}
+
+
+void
+layout_toggle_lock (int computer)
+{
+ int console = layout_computer_to_console (computer);
+ if ((console < 1) || (console > N_CONSOLE))
+ return;
+
+ console_locked[console] = !console_locked[console];
+ layout_status (computer);
+}
+
+
+int
+layout_init (void)
+{
+ mm = MM_open ();
+
+ layout_map (1, 3);
+ layout_map (2, 4);
+ layout_map (3, 5);
+
+
+ layout_status (3);
+
+ return 3;
+}
diff --git a/lcd.c b/lcd.c
new file mode 100644
index 0000000..cd652b3
--- /dev/null
+++ b/lcd.c
@@ -0,0 +1,328 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <stdint.h>
+
+#include "libdpf/dpf.h"
+
+typedef struct
+{
+ unsigned char R;
+ unsigned char G;
+ unsigned char B;
+ unsigned char A;
+} RGBA;
+
+static DPFContext *dpf;
+static RGBA *fb;
+static RGBA *fbo;
+static uint8_t *fb_16;
+
+
+
+
+void
+lcd_on (void)
+{
+ DPFValue val;
+ if (!dpf)
+ return;
+ val.type = TYPE_INTEGER;
+ val.value.integer = 7;
+ dpf_setproperty (dpf, PROPERTY_BRIGHTNESS, &val);
+}
+
+
+
+void
+lcd_off (void)
+{
+ DPFValue val;
+ if (!dpf)
+ return;
+ val.type = TYPE_INTEGER;
+ val.value.integer = 0;
+ dpf_setproperty (dpf, PROPERTY_BRIGHTNESS, &val);
+}
+
+
+
+
+void
+lcd_close (void)
+{
+ if (!dpf)
+ return;
+ dpf_close (dpf);
+ dpf = NULL;
+ free (fb);
+ free (fb_16);
+}
+
+#define _RGB565_0(p) \
+ (( (((p)->R) & 0xf8) ) | ((((p)->G) & 0xe0) >> 5))
+#define _RGB565_1(p) \
+ (( (((p)->G) & 0x1c) << 3 ) | ((((p)->B) & 0xf8) >> 3))
+
+
+static int
+find_dr (short *rect)
+{
+ RGBA *p = fb, *po = fbo;
+ int e;
+ int x, y;
+ rect[0] = dpf->width;
+ rect[1] = dpf->height;
+ rect[2] = 0;
+ rect[3] = 0;
+
+ for (y = 0; y < dpf->height; y++)
+ {
+ e = 0;
+ for (x = 0; x < dpf->width; x++)
+ {
+ if (memcmp (p, po, 4))
+ {
+ if (x < rect[0])
+ rect[0] = x;
+ if (x >= rect[2])
+ rect[2] = x + 1;
+ e = 1;
+ }
+ p++;
+ po++;
+ }
+ if (e)
+ {
+ if (y < rect[1])
+ rect[1] = y;
+ if (y >= rect[3])
+ rect[3] = y + 1;
+ }
+ }
+ return rect[2];
+
+}
+
+static void
+blit (int x1, int y1, int x2, int y2)
+{
+ int r;
+ int c;
+ short rect[4] = { x1, y1, x2, y2 };
+
+ RGBA *p, *rp, *po, *rpo;
+ uint8_t *p_16;
+
+ if (!dpf)
+ return;
+
+ if (x1 == -1)
+ {
+ if (!find_dr (rect))
+ return;
+ }
+
+ rp = fb + (dpf->width * rect[1]) + rect[0];
+ rpo = fbo + (dpf->width * rect[1]) + rect[0];
+
+ p_16 = fb_16;
+
+ for (r = rect[1]; r < rect[3]; r++)
+ {
+ p = rp;
+ po = rpo;
+ for (c = rect[0]; c < rect[2]; c++)
+ {
+ *p_16++ = _RGB565_0 (p);
+ *p_16++ = _RGB565_1 (p);
+ memcpy (po, p, 4);
+ p++;
+ po++;
+ }
+ rp += dpf->width;
+ }
+
+ //printf ("%d %d %d %d\n", rect[0], rect[1], rect[2], rect[3]);
+
+
+ dpf_screen_blit (dpf, fb_16, rect);
+}
+
+
+void
+lcd_vline (int x, int y1, int y2, int r, int g, int b)
+{
+ RGBA c = {.R = r,.G = g,.B = b };
+ RGBA *p = fb;
+ int y;
+
+ if (!dpf)
+ return;
+
+ if (y1 > y2)
+ {
+ y = y1;
+ y1 = y2;
+ y2 = y;
+ }
+
+ p += x + y1 * dpf->width;
+
+
+ for (y = y1; y <= y2; ++y)
+ {
+ memcpy (p, &c, sizeof (c));
+ p += dpf->width;
+ }
+
+}
+
+void
+lcd_hline (int y, int x1, int x2, int r, int g, int b)
+{
+ RGBA c = {.R = r,.G = g,.B = b };
+ RGBA *p = fb;
+ int x;
+
+ if (!dpf)
+ return;
+
+
+ if (x1 > x2)
+ {
+ x = x1;
+ x1 = x2;
+ x2 = x;
+ }
+
+ p += x1 + y * dpf->width;
+
+ for (x = x1; x <= x2; ++x)
+ {
+ memcpy (p, &c, sizeof (c));
+ p++;
+ }
+
+}
+
+void
+lcd_box (int x1, int y1, int x2, int y2, int r, int g, int b)
+{
+ lcd_vline (x1, y1, y2, r, g, b);
+ blit (x1, y1, x1 + 1, y2 + 1);
+ lcd_vline (x2, y1, y2, r, g, b);
+ blit (x2, y1, x2 + 1, y2 + 1);
+ lcd_hline (y1, x1 + 1, x2 - 1, r, g, b);
+ blit (x1 + 1, y1, x2, y1 + 1);
+ lcd_hline (y2, x1 + 1, x2 - 1, r, g, b);
+ blit (x1 + 1, y2, x2, y2 + 1);
+}
+
+#define LCD_SS_A (1 << 0)
+#define LCD_SS_B (1 << 1)
+#define LCD_SS_C (1 << 2)
+#define LCD_SS_D (1 << 3)
+#define LCD_SS_E (1 << 4)
+#define LCD_SS_F (1 << 5)
+#define LCD_SS_G (1 << 6)
+
+void
+lcd_ss (int v, int x1, int y1, int w, int h)
+{
+ int x2 = x1 + w;
+ int y2 = y1 + (h / 2);
+ int y3 = y1 + h;
+
+ int lut[] =
+ { LCD_SS_A | LCD_SS_B | LCD_SS_C | LCD_SS_D | LCD_SS_E | LCD_SS_F,
+ LCD_SS_B | LCD_SS_C,
+ LCD_SS_A | LCD_SS_B | LCD_SS_D | LCD_SS_E | LCD_SS_G,
+ LCD_SS_A | LCD_SS_B | LCD_SS_C | LCD_SS_D | LCD_SS_G,
+ LCD_SS_B | LCD_SS_C | LCD_SS_F | LCD_SS_G,
+ LCD_SS_A | LCD_SS_C | LCD_SS_D | LCD_SS_F | LCD_SS_G,
+ LCD_SS_A | LCD_SS_C | LCD_SS_D | LCD_SS_E | LCD_SS_F | LCD_SS_G,
+ LCD_SS_A | LCD_SS_B | LCD_SS_C,
+ LCD_SS_A | LCD_SS_B | LCD_SS_C | LCD_SS_D | LCD_SS_E | LCD_SS_F |
+ LCD_SS_G,
+ LCD_SS_A | LCD_SS_B | LCD_SS_C | LCD_SS_D | LCD_SS_F | LCD_SS_G,
+ 0
+ };
+
+ int l;
+ int c;
+
+
+ if (v == 0)
+ v = 10;
+
+ l = lut[v];
+
+ printf ("SS %d %x %d %d %d %d %d\n", v, l, x1, x2, y1, y2, y3);
+
+ c = (l & LCD_SS_A) ? 255 : 0;
+ lcd_hline (y1, x1, x2, c, c, c);
+
+ c = (l & LCD_SS_B) ? 255 : 0;
+ lcd_vline (x2, y1, y2, c, c, c);
+
+ c = (l & LCD_SS_C) ? 255 : 0;
+ lcd_vline (x2, y2, y3, c, c, c);
+
+ c = (l & LCD_SS_D) ? 255 : 0;
+ lcd_hline (y3, x1, x2, c, c, c);
+
+ c = (l & LCD_SS_E) ? 255 : 0;
+ lcd_vline (x1, y2, y3, c, c, c);
+
+ c = (l & LCD_SS_F) ? 255 : 0;
+ lcd_vline (x1, y1, y2, c, c, c);
+
+ c = (l & LCD_SS_G) ? 255 : 0;
+ lcd_hline (y2, x1, x2, c, c, c);
+
+ blit (x1, y1, x1 + 1, y3 + 1);
+ blit (x2, y1, x2 + 1, y3 + 1);
+
+ blit (x1, y1, x2 + 1, y1 + 1);
+ blit (x1, y2, x2 + 1, y2 + 1);
+ blit (x1, y3, x2 + 1, y3 + 1);
+
+}
+
+
+
+int
+lcd_open (void)
+{
+ int err;
+ DPFValue val;
+
+
+ err = dpf_open ("usb0", &dpf);
+
+ if (err < 0)
+ {
+ dpf = NULL;
+ return -1;
+ }
+
+
+ val.type = TYPE_INTEGER;
+ val.value.integer = 1;
+ dpf_setproperty (dpf, PROPERTY_ORIENTATION, &val);
+
+
+ fb_16 = malloc (dpf->height * dpf->width * dpf->bpp);
+ fb = malloc (dpf->height * dpf->width * sizeof (RGBA));
+ fbo = malloc (dpf->height * dpf->width * sizeof (RGBA));
+
+ bzero (fb, dpf->height * dpf->width * sizeof (RGBA));
+ blit (0, 0, 320, 240);
+
+
+
+ return 0;
+}
diff --git a/libdpf/Makefile b/libdpf/Makefile
new file mode 100644
index 0000000..3c39ac5
--- /dev/null
+++ b/libdpf/Makefile
@@ -0,0 +1,12 @@
+OBJS = dpflib.o rawusb.o scsi.o bootload.o
+
+CFLAGS = -Wall -fPIC -I. -g
+# CFLAGS += -DDEBUG
+
+all: libdpf.a
+
+libdpf.a: $(OBJS)
+ ar ruv $@ $(OBJS)
+
+clean:
+ -rm -f libdpf.a *.o
diff --git a/libdpf/bootload.c b/libdpf/bootload.c
new file mode 100644
index 0000000..2d882cf
--- /dev/null
+++ b/libdpf/bootload.c
@@ -0,0 +1,379 @@
+// Bootstream generator for Buildwin firmware loader
+//
+// (c) 2011, <hackfin@section5.ch>
+//
+//
+
+#include "dpf.h"
+#include "usbuser.h" // our user defined flash commands
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+
+// Jump offsets for USB command:
+#define JMP_LOAD 0x0dae
+#define JMP_SPILIB 0x11bf
+#define JMP_USER 0x1000
+
+#define PAGESIZE 256
+#define BUFSIZE (64 - 6)
+#define PKTSIZE (64 - 7)
+
+typedef struct {
+ unsigned char len;
+ unsigned char chk;
+ unsigned char jmp[2];
+ union {
+ // Structures for various backends
+ // The default memory loader:
+ struct {
+ unsigned char offset[2]; // XDATA memory dest address
+ unsigned char buf[BUFSIZE]; // Binary data to write
+ } loader;
+ struct {
+ unsigned char opcode; // SPI operation opcode
+ unsigned char wnum; // Number of bytes to send (Host -> DPF)
+ unsigned char rnum; // Number of bytes to recv (DPF -> Host)
+ unsigned char seq[PKTSIZE]; // SPI cmd sequence
+ } spi;
+ } u;
+} UsbMsg;
+
+#define OPCODE_SPISEL 0x01 // assert SELECT
+#define OPCODE_CRYPT0 0x02
+#define OPCODE_CRYPT1 0x04
+#define OPCODE_SPIDES 0x10 // assert DESELECT
+
+int validate(UsbMsg *msg)
+{
+ unsigned short c = 0;
+ unsigned char *b = (unsigned char *) msg;
+ unsigned short l = msg->len;
+
+ if (l < 6 || l > 64) return -1;
+
+ while (l--) {
+ c += *b++;
+ }
+
+ msg->chk -= c;
+
+ return 0;
+}
+
+void hexdump(unsigned char *buf, unsigned long n)
+{
+ int i = 0;
+ int c = 0;
+
+ while (i < n) {
+ printf("%02x ", buf[i]);
+ c++;
+ if (c == 16) { c = 0; printf("\n"); }
+ i++;
+ }
+ if (c)
+ printf("\n");
+}
+
+int transmit(DPFContext *dpf, UsbMsg *m)
+{
+ int error;
+ unsigned char *s = (unsigned char *) m;
+ // hexdump(s, m->len);
+ error = usb_rawwrite(dpf->dev.udev, s, m->len);
+ if (error < 0) {
+ perror("Writing to USB");
+ }
+ return error;
+}
+
+int spilib_process(DPFContext *h, UsbMsg *umsg, unsigned char *out)
+{
+ int error;
+ umsg->jmp[0] = JMP_SPILIB & 0xff; umsg->jmp[1] = JMP_SPILIB >> 8;
+ umsg->len = 7 + umsg->u.spi.wnum;
+
+ validate(umsg);
+ error = transmit(h, umsg);
+ if (umsg->u.spi.rnum > 0 && error >= 0) {
+ error = usb_rawread(h->dev.udev, out, 64);
+ }
+ if (error < 0) perror("Reading USB");
+ else error = 0;
+ return error;
+}
+
+int go_hid(DPFContext *dpf, ADDR jmpoffset)
+{
+ UsbMsg umsg;
+ umsg.jmp[0] = jmpoffset; umsg.jmp[1] = jmpoffset >> 8;
+ umsg.len = 8;
+ validate(&umsg);
+ return transmit(dpf, &umsg);
+}
+
+int load(DPFContext *dpf, FILE *f, uint16_t jmpoffset)
+{
+ int size;
+ UsbMsg umsg;
+
+ unsigned short offset = jmpoffset - 0x800;
+
+ umsg.jmp[0] = JMP_LOAD & 0xff; umsg.jmp[1] = JMP_LOAD >> 8;
+ umsg.chk = 0xce;
+ size = fread(umsg.u.loader.buf, 1, BUFSIZE, f);
+ if (size < 0) return size;
+
+ while (size > 0) {
+ umsg.u.loader.offset[0] = offset;
+ umsg.u.loader.offset[1] = offset >> 8;
+ umsg.len = sizeof(UsbMsg) - BUFSIZE + size;
+ offset += size;
+ validate(&umsg);
+ transmit(dpf, &umsg);
+ size = fread(umsg.u.loader.buf, 1, BUFSIZE, f);
+ }
+
+ // And jump into the code:
+ if (jmpoffset != 0x0000) {
+ go_hid(dpf, jmpoffset);
+ }
+ return size;
+}
+/* Flash stuff, HID wrapped */
+
+static unsigned char s_rbuf[64];
+
+static
+int flash_probe_hid(DPFContext *h, unsigned char *id)
+{
+ int error;
+ UsbMsg umsg;
+ FILE *f;
+
+ // First, load spilib.bin
+ f = fopen("spilib.bin", "rb");
+
+ if (!f) {
+ printf("failed to open flash driver\n");
+ return -1;
+ }
+ umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES;
+
+ error = load(h, f, 0x0000); // Load, but do not execute
+ fclose(f);
+ usleep(500000);
+ if (error == 0) {
+ umsg.u.spi.wnum = 1;
+ umsg.u.spi.rnum = 4;
+ umsg.u.spi.seq[0] = SPM_RDID;
+ error = spilib_process(h, &umsg, s_rbuf);
+ id[0] = s_rbuf[0]; id[1] = s_rbuf[1]; id[2] = s_rbuf[2];
+ }
+ return error;
+}
+
+static
+int flash_cmd_hid(DPFContext *h, int command, int cmdlen, ADDR addr)
+{
+ UsbMsg umsg;
+ umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES;
+ umsg.u.spi.wnum = cmdlen;
+ umsg.u.spi.rnum = 0;
+ umsg.u.spi.seq[0] = command;
+ umsg.u.spi.seq[1] = addr >> 16;
+ umsg.u.spi.seq[2] = addr >> 8;
+ umsg.u.spi.seq[3] = addr;
+
+ return spilib_process(h, &umsg, 0);
+}
+
+int flash_status_hid(DPFHANDLE h, uint8_t *status)
+{
+ int error;
+ UsbMsg umsg;
+ umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES;
+ umsg.u.spi.wnum = 1;
+ umsg.u.spi.rnum = 1;
+ umsg.u.spi.seq[0] = SPM_RDSR;
+
+ error = spilib_process(h, &umsg, s_rbuf);
+ *status = s_rbuf[0];
+ return error;
+}
+
+static
+int chunk_read(DPFContext *h, unsigned char *buf, ADDR offset, int len)
+{
+ int error;
+ UsbMsg umsg;
+
+ if (len > PKTSIZE) len = PKTSIZE;
+
+ umsg.u.spi.opcode = OPCODE_SPISEL | OPCODE_SPIDES;
+ umsg.u.spi.wnum = 4;
+ umsg.u.spi.rnum = PKTSIZE;
+ umsg.u.spi.seq[0] = SPM_READ;
+ umsg.u.spi.seq[1] = offset >> 16;
+ umsg.u.spi.seq[2] = offset >> 8;
+ umsg.u.spi.seq[3] = offset;
+
+ error = spilib_process(h, &umsg, buf);
+ if (error < 0) return error;
+
+ return len;
+}
+
+
+static
+int flash_read_hid(DPFContext *h, unsigned char *buf, ADDR offset, int len)
+{
+ int n;
+
+ while (len > 0) {
+ n = chunk_read(h, buf, offset, len);
+ if (n < 0) return n;
+ len -= n; offset += n; buf += n;
+ }
+ return 0;
+}
+
+int fill_spimsg(UsbMsg *umsg, const unsigned char *buf,
+ unsigned short offset, int len)
+{
+ int n = PKTSIZE - offset;
+ if (len > n) len = n;
+ memcpy(&umsg->u.spi.seq[offset], buf, len);
+ umsg->u.spi.wnum = offset + len;
+ return len;
+}
+
+static
+int flash_writechunk_hid(DPFContext *h,
+ const unsigned char *buf, ADDR offset, int len)
+{
+ UsbMsg umsg;
+ int error;
+ int n;
+
+ if (len > PAGESIZE) len = PAGESIZE;
+
+ umsg.u.spi.rnum = 0;
+ umsg.u.spi.seq[0] = SPM_PP;
+ umsg.u.spi.seq[1] = offset >> 16;
+ umsg.u.spi.seq[2] = offset >> 8;
+ umsg.u.spi.seq[3] = offset;
+
+ n = fill_spimsg(&umsg, buf, 4, len);
+ len -= n; buf += n; offset += n;
+
+ umsg.u.spi.opcode = OPCODE_SPISEL;
+ error = spilib_process(h, &umsg, 0);
+ if (error < 0) return error;
+
+ umsg.u.spi.opcode = 0;
+ while (len > PKTSIZE) {
+ n = fill_spimsg(&umsg, buf, 0, PKTSIZE);
+ error = spilib_process(h, &umsg, 0);
+ if (error < 0) return error;
+ len -= n; buf += n; offset += n;
+ }
+
+ umsg.u.spi.opcode = OPCODE_SPIDES;
+ fill_spimsg(&umsg, buf, 0, len);
+ error = spilib_process(h, &umsg, 0);
+ if (error < 0) return error;
+
+ return PAGESIZE;
+}
+
+int blk_write(DPFContext *h, ADDR dst, const unsigned char *src,
+ unsigned short len)
+{
+ static UsbMsg umsg;
+
+ if (len > BUFSIZE) len = BUFSIZE;
+
+ umsg.jmp[0] = JMP_LOAD & 0xff; umsg.jmp[1] = JMP_LOAD >> 8;
+ memcpy(umsg.u.loader.buf, src, len);
+ umsg.u.loader.offset[0] = dst;
+ umsg.u.loader.offset[1] = dst >> 8;
+ umsg.len = sizeof(UsbMsg) - BUFSIZE + len;
+
+ validate(&umsg);
+ transmit(h, &umsg);
+ return len;
+}
+
+int mem_write_hid(DPFContext *h,
+ ADDR dst, const unsigned char *src, unsigned short n)
+{
+ int len;
+
+ while (n > 0) {
+ len = blk_write(h, dst, src, n);
+ n -= len; src += len; dst += len;
+ }
+ return n;
+}
+
+
+AccessMethods
+hid_methods = {
+ .mem_read = NULL,
+ .mem_write = mem_write_hid,
+ .go = go_hid,
+ .bootstrap = NULL,
+ .flash_probe = flash_probe_hid,
+ .flash_cmd = flash_cmd_hid,
+ .flash_status = flash_status_hid,
+ .flash_read = flash_read_hid,
+ .flash_writechunk = flash_writechunk_hid,
+ .flash_lock = NULL,
+};
+
+
+#ifdef TEST
+int main(int argc, char **argv)
+{
+ FILE *f;
+ int error;
+ DPFHANDLE dpf;
+ uint16_t startaddr = 0x1000;
+
+ if (argc >= 2) {
+
+ f = fopen(argv[1], "rb");
+
+ if (!f) {
+ printf("failed to open file\n");
+ return -1;
+ }
+ if (argc == 3) {
+ startaddr = strtol(argv[2], NULL, 16);
+ printf("Starting at %04x\n", startaddr);
+ }
+
+ error = dpf_open("usb0", &dpf);
+ if (error < 0) {
+ printf("Failed to open DPF\n");
+ return error;
+ }
+ if (dpf->mode == MODE_USBHID) {
+ error = load(dpf, f, startaddr);
+ } else {
+ printf("Not in BOOTLOAD mode! Press Reset and hold MENU\n");
+ }
+ dpf_close(dpf);
+ } else {
+ printf("Needs boot image argument\n");
+ }
+
+ if (error < 0) {
+ printf("Error\n");
+ }
+ return error;
+}
+#endif
diff --git a/libdpf/dpf.h b/libdpf/dpf.h
new file mode 100644
index 0000000..d8d698d
--- /dev/null
+++ b/libdpf/dpf.h
@@ -0,0 +1,189 @@
+/** libdpf header file
+ *
+ * (c) 2010, 2011 <hackfin@section5.ch>
+ *
+ */
+
+#include <stdint.h>
+#include <usb.h>
+#include "usbuser.h"
+#include "spiflash.h"
+
+#define ADDR unsigned int
+
+#define MODE_SG 0x00 ///< generic device mode (original)
+#define MODE_USB 0x01 ///< libusb operation mode (hacked)
+#define MODE_USBHID 0x02 ///< libusb HID boot mode
+
+#define FLAG_CAN_LOCK 0x80 ///< Has the locking feature (new firmware)
+
+enum {
+ DEVERR_FILE = -16,
+ DEVERR_OPEN,
+ DEVERR_HEX,
+ DEVERR_CHK,
+ DEVERR_IO,
+ DEVERR_MALLOC,
+ DEVERR_TIMEOUT,
+ DEVERR_UNSUPP,
+};
+
+/** The DPF context structure */
+struct dpf_context;
+#define DPFHANDLE struct dpf_context *
+
+typedef struct {
+ int (*mem_read)(DPFHANDLE h, unsigned char *buf, ADDR offset, int len);
+ int (*mem_write)(DPFHANDLE h,
+ ADDR dst, const unsigned char *buf, unsigned short n);
+ int (*go)(DPFHANDLE h, ADDR start);
+ int (*bootstrap)(DPFHANDLE h,
+ ADDR dest, unsigned char *src, unsigned short n, ADDR start);
+ int (*flash_probe)(DPFHANDLE h, unsigned char *id);
+ int (*flash_cmd)(DPFHANDLE h, int command, int cmdlen, ADDR addr);
+ int (*flash_status)(DPFHANDLE h, uint8_t *status);
+ int (*flash_read)(DPFHANDLE h, uint8_t *buf, ADDR offset, int len);
+ int (*flash_writechunk)(DPFHANDLE h,
+ const uint8_t *buf, ADDR offset, int len);
+ int (*flash_lock)(DPFHANDLE h, char enable);
+} AccessMethods;
+
+typedef
+struct dpf_context {
+ unsigned char mode;
+ unsigned char flags;
+ union {
+ usb_dev_handle *udev;
+ int fd;
+ } dev;
+ AccessMethods methods;
+ unsigned int width;
+ unsigned int height;
+ int bpp;
+ int proto;
+ char* buff;
+ unsigned char* oldpix;
+ int offx;
+ int offy;
+} DPFContext;
+
+
+/** A value proxy for the property API */
+typedef struct dpf_proxy {
+ union {
+ short integer;
+ char *sequence;
+ } value;
+ char type;
+} DPFValue;
+
+enum {
+ TYPE_INTEGER,
+ TYPE_STRING,
+};
+
+/**
+ Opens the DPF device. if dev is not NULL, open device, otherwise, look for
+ USB device.
+ */
+int dpf_open(const char *dev, DPFHANDLE *h);
+
+/** Close DPF device */
+void dpf_close(DPFHANDLE h);
+
+/** Set color register
+ * \param rgb RGB tuple */
+int dpf_setcol(DPFHANDLE h, const unsigned char *rgb);
+
+/** Blit data to screen
+ *
+ * \param buf buffer to 16 bpp RGB 565 image data
+ * \param rect rectangle tuple: [x0, y0, x1, y1]
+ */
+
+int dpf_screen_blit(DPFHANDLE h, const unsigned char *buf, short rect[4]);
+
+/** Set property on DPF
+ * \param token Property token
+ * \param value Pointer to value
+ */
+int dpf_setproperty(DPFHANDLE h, int token, const DPFValue *value);
+
+/* USB raw */
+
+int emulate_scsi(usb_dev_handle *d, unsigned char *cmd, int cmdlen, char out,
+ unsigned char *data, unsigned long block_len);
+
+const char *dev_errstr(int err);
+
+// Private stuff:
+int dpf_usb_open(int index, usb_dev_handle **u);
+int sgdev_open(const char *portname, int *fd);
+int usb_rawread(usb_dev_handle *dev, unsigned char *buf, int len);
+int usb_rawwrite(usb_dev_handle *dev, const unsigned char *buf, int len);
+int probe(DPFHANDLE h);
+
+////////////////////////////////////////////////////////////////////////////
+// Bootloader functionality
+
+int bl_go(DPFContext *dpf, uint16_t jmpoffset);
+
+////////////////////////////////////////////////////////////////////////////
+// FLASH stuff
+
+// Maximum size for flash_read
+#define MAX_CHUNKSIZE 0x10000
+
+int read_mem(DPFHANDLE h, unsigned char *buf, ADDR src, unsigned short len);
+int write_mem(DPFHANDLE h,
+ ADDR dst, const unsigned char *buf, unsigned short len);
+
+int load_hexfile(DPFHANDLE h, const char *hexfile);
+int code_go(DPFHANDLE h, ADDR start);
+
+int dpf_bootstrap(DPFHANDLE h,
+ ADDR dst, unsigned char *src, unsigned short n, ADDR start);
+
+int flash_cmd(DPFHANDLE h, int command, int cmdlen, ADDR addr);
+int flash_probe(DPFContext *h, unsigned char *id);
+int flash_erase(DPFHANDLE h, ADDR offset);
+int flash_erase_full(DPFHANDLE h);
+int flash_write(DPFHANDLE h, const unsigned char *buf, ADDR offset, int len);
+int flash_read(DPFHANDLE h, unsigned char *buf, ADDR offset, int len);
+
+int load_ihx(DPFHANDLE h, const char *fname, unsigned char *data,
+ unsigned int *buflen, unsigned int reloc);
+
+int patch_sector(DPFHANDLE h,
+ ADDR reloc, unsigned long addr, const char *hexfile);
+
+////////////////////////////////////////////////////////////////////////////
+/* DPF specific stuff: */
+
+#define RGB565_0(r, g, b) \
+ (( ((r) & 0xf8) ) | (((g) & 0xe0) >> 5))
+#define RGB565_1(r, g, b) \
+ (( ((g) & 0x1c) << 3 ) | (((b) & 0xf8) >> 3))
+
+#define RGB565(r, g, b) { RGB565_0(r, g, b), RGB565_1(r, g, b) }
+
+#define RGB565_S(r, g, b) ((RGB565_0(r, g, b) << 8) | RGB565_1(r, g, b))
+
+int dpfcpy(ADDR dst, unsigned char *src, unsigned short n);
+
+// int clr_screen(DPFHANDLE h, const unsigned char *col);
+int write_screen(DPFHANDLE h, const unsigned char *buf, unsigned int len);
+
+
+// Some internal address offsets. They may change, but so far all types
+// seem to have the same
+//
+// w: word, <n>: length, [LE, BE]
+//
+// FIXME: Use packed struct later.
+
+// FIXME: Should be 0x0020, once we have the firmware replaced
+#define OFFSET_PROPS 0x3f0020 ///< w[2]:LE : Resolution X, Y
+
+
+
diff --git a/libdpf/dpflib.c b/libdpf/dpflib.c
new file mode 100644
index 0000000..cfda55b
--- /dev/null
+++ b/libdpf/dpflib.c
@@ -0,0 +1,436 @@
+/** DPF access library for AX206 based HW
+ *
+ * 12/2010 <hackfin@section5.ch>
+ *
+ * This is an ugly hack, because we use existing SCSI vendor specific
+ * extensions to pass on our requests to the DPF.
+ *
+ * One day we might use a proper protocol like netpp.
+ *
+ */
+
+// FIXME: Put all those SCSI commands in one (wrapped) place.
+
+#include "dpf.h"
+
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+
+#ifdef DEBUG
+#define DEB(x) x
+#else
+#define DEB(x)
+#endif
+
+extern AccessMethods scsi_methods;
+extern AccessMethods hid_methods;
+
+
+/*
+static
+int dpf_query(DPFHANDLE h)
+{
+ int ret;
+ unsigned char buf[64]; // Do not change size
+
+ static
+ unsigned char cmd[16] = {
+ 0xcd, 0, 0, 0,
+ 0, 3, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+
+ return wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, buf, sizeof(buf));
+}
+*/
+
+
+
+int dpf_open(const char *dev, DPFHANDLE *h)
+{
+ int error = 0;
+ DPFContext *dpf;
+ int i;
+ usb_dev_handle *u;
+
+ int fd;
+
+ if (!dev) {
+ fprintf(stderr, "Please specify a string like 'usb0' or a sg device\n");
+ return DEVERR_OPEN;
+ }
+
+ if (strncmp(dev, "usb", 3) == 0) {
+ i = dev[3] - '0';
+ error = dpf_usb_open(i, &u);
+ if (error < 0) return error;
+ if (!u) return DEVERR_OPEN;
+ i = error; // USB mode
+ error = 0;
+ } else {
+ fprintf(stderr, "Opening generic SCSI device '%s'\n", dev);
+ if (sgdev_open(dev, &fd) < 0) return DEVERR_OPEN;
+ i = MODE_SG;
+ }
+
+ dpf = (DPFHANDLE) malloc(sizeof(DPFContext));
+ if (!dpf) return DEVERR_MALLOC;
+
+ dpf->flags = 0;
+ dpf->mode = i;
+
+ switch (dpf->mode) {
+ case MODE_USB:
+ dpf->dev.udev = u;
+ error = probe(dpf);
+ fprintf(stderr, "Got LCD dimensions: %dx%d\n",
+ dpf->width, dpf->height);
+ dpf->methods = scsi_methods;
+ break;
+ case MODE_USBHID:
+ dpf->dev.udev = u;
+ dpf->methods = hid_methods;
+ break;
+ case MODE_SG:
+ dpf->dev.fd = fd;
+ dpf->methods = scsi_methods;
+ break;
+ default:
+ fprintf(stderr, "Unknown interface mode\n");
+ error = -1;
+ }
+
+ *h = dpf;
+ return error;
+}
+
+void dpf_close(DPFContext *h)
+{
+ switch (h->mode) {
+ case MODE_USBHID:
+ case MODE_SG:
+ close(h->dev.fd);
+ break;
+ case MODE_USB:
+ usb_release_interface(h->dev.udev, 0);
+ usb_close(h->dev.udev);
+ break;
+ }
+ free(h);
+}
+
+const char *dev_errstr(int err)
+{
+ switch (err) {
+ case DEVERR_FILE: return "File I/O error";
+ case DEVERR_OPEN: return "File open error";
+ case DEVERR_HEX: return "Hex file error";
+ case DEVERR_CHK: return "Checksum error";
+ case DEVERR_IO: return "Common I/O error";
+ case DEVERR_UNSUPP: return "Unsupported feature";
+ default: return "Unknown error";
+ }
+}
+
+
+int flash_probe(DPFContext *h, unsigned char *id)
+{
+ return h->methods.flash_probe(h, id);
+}
+
+int flash_cmd(DPFContext *h, int command, int cmdlen, ADDR addr)
+{
+ return h->methods.flash_cmd(h, command, cmdlen, addr);
+}
+
+
+/* Flash functions, API */
+
+int flash_read(DPFContext *h, unsigned char *buf, ADDR offset, int len)
+{
+ return h->methods.flash_read(h, buf, offset, len);
+}
+
+int flash_status_wait(DPFContext *h, uint8_t mask)
+{
+ int error;
+ uint8_t status;
+
+ do {
+ error = h->methods.flash_status(h, &status);
+ } while ((status & mask) && !error);
+
+ return error;
+}
+
+
+int flash_write(DPFContext *h, const unsigned char *buf, ADDR offset, int len)
+{
+ int n;
+ int error = 0;
+
+ while (len > 0) {
+ error = h->methods.flash_cmd(h, SPM_WREN, 1, 0);
+ DEB(printf("Write pages at %06x\n", offset));
+ n = h->methods.flash_writechunk(h, buf, offset, len);
+ error = flash_status_wait(h, SPS_WIP);
+
+ if (n < 0) break;
+ len -= n; buf += n; offset += n;
+ }
+ return error;
+}
+
+/* Mid level flash */
+
+int load_ihx(DPFContext *h, const char *fname, unsigned char *data,
+ unsigned int *buflen, unsigned int reloc)
+{
+ unsigned char csum_is, csum_need;
+ int ret;
+ FILE *f;
+
+ static char line[512];
+ static unsigned char buf[0x100];
+ int count;
+ unsigned int addr, len, type;
+ unsigned short b;
+ unsigned int total = 0;
+
+ DEB(printf("Opening %s...\n", fname));
+ f = fopen(fname, "r");
+ if (f == NULL) {
+ return DEVERR_OPEN;
+ }
+
+ while(1) {
+ fgets(line, sizeof(line), f);
+
+ if (feof(f) || ferror(f)) break;
+
+ if ((line[0] != ':') || (strlen(line) < 9)) {
+ fprintf(stderr, "invalid line in ihx\n");
+ break;
+ }
+
+ ret = sscanf(&line[1], "%02x", &len);
+ if (ret != 1) { ret = DEVERR_HEX; break; }
+
+ ret = sscanf(&line[3], "%04x", &addr);
+ if (ret != 1) { ret = DEVERR_HEX; break; }
+
+ ret = sscanf(&line[7], "%02x", &type);
+ if (ret != 1) { ret = DEVERR_HEX; break; }
+
+#ifdef DEBUG
+ printf("len %u addr %04x type %u\n", len, addr, type);
+#endif
+
+ if (type == 1) break;
+
+ if (type != 0) {
+ fprintf(stderr, "ihx: unknown type %u\n", type);
+ continue;
+ }
+
+ csum_need = len + (addr & 0xff) + (addr >> 8) + type;
+
+ total += len;
+ if (total > *buflen) {
+ fprintf(stderr, "Buffer length exceeded. IHX file too big.\n");
+ ret = DEVERR_HEX;
+ break;
+ }
+
+ if (len > sizeof(buf)) {
+ fprintf(stderr, "Buffer length exceeded. Too long lines.\n");
+ ret = DEVERR_HEX;
+ break;
+ }
+
+ for(count = 0; count < len; count++) {
+ ret = sscanf(&line[9 + count * 2], "%02hx", &b);
+ if (ret != 1) {
+ fprintf(stderr, "hex file: could not parse data!\n");
+ break;
+ }
+
+ buf[count] = b;
+ csum_need += buf[count];
+ }
+
+ if (ret != 1) { ret = DEVERR_HEX; break; }
+
+ ret = sscanf(&line[9 + len * 2], "%02hx", &b);
+ if (ret != 1) { ret = DEVERR_HEX; break; }
+
+ csum_is = b;
+ if (((csum_need+csum_is) & 0xff) != 0x00) {
+ fprintf(stderr, "ihx: checksum failure! is: %02x should be:%02x\n",
+ csum_is, csum_need);
+ ret = DEVERR_CHK;
+ break;
+ }
+
+ if (addr < reloc) {
+ fprintf(stderr, "Bad relocation value\n");
+ ret = DEVERR_HEX;
+ break;
+ }
+ // Copy to data buffer at relocated address
+ if (data) {
+ DEB(printf("Patching at offset %08x, chunk size %d\n",
+ addr - reloc, len));
+ memcpy(&data[addr - reloc], buf, len);
+ } else {
+ DEB(printf("Writing to %04x (CODE: %04x), chunk size %d\n",
+ addr - reloc, addr, len));
+ h->methods.mem_write(h, addr - reloc, buf, len);
+ }
+ }
+ *buflen = total;
+ fclose(f);
+ return ret;
+}
+
+int flash_erase_full(DPFContext *h)
+{
+ flash_cmd(h, SPM_RES, 1, 0);
+ flash_cmd(h, SPM_WRSR, 2, 0); // clr status
+ flash_cmd(h, SPM_WREN, 1, 0);
+ flash_cmd(h, SPM_FLASH_BE, 1, 0);
+ printf("Erase full flash...\n");
+
+ return flash_status_wait(h, SPS_WIP);
+}
+
+int flash_erase(DPFContext *h, ADDR addr)
+{
+ int error;
+ flash_cmd(h, SPM_RES, 1, 0);
+ flash_cmd(h, SPM_WREN, 1, 0);
+ flash_cmd(h, SPM_WRSR, 2, 0); // clr status
+
+ // now erase flash sector:
+ flash_cmd(h, SPM_WREN, 1, 0);
+ flash_cmd(h, SPM_FLASH_SE, 4, addr);
+
+ error = flash_status_wait(h, SPS_WIP);
+ flash_cmd(h, SPM_WRDI, 1, 0);
+
+ return error;
+}
+
+int dpf_flash_lock(DPFContext *h, char enable)
+{
+ if (h->methods.flash_lock)
+ return h->methods.flash_lock(h, enable);
+ else
+ return DEVERR_UNSUPP;
+}
+
+
+int patch_sector(DPFContext *h,
+ ADDR reloc, unsigned long addr, const char *hexfile)
+{
+ int error;
+ unsigned short offset;
+ static
+ unsigned char readbuf[0x10000];
+ unsigned int len = sizeof(readbuf);
+
+ offset = addr & 0xffff;
+ addr -= offset;
+
+ error = flash_read(h, readbuf, addr, 0x10000);
+ if (error < 0) {
+ perror("Reading flash");
+ return error;
+ }
+
+ error = load_ihx(h, hexfile, &readbuf[offset], &len, reloc);
+ if (error < 0) {
+ fprintf(stderr, "Failed to load HEX file\n");
+ return error;
+ }
+ // Lock DPF handler so nothing can interfere with the flashing (in case
+ // we flash ourselves)
+ dpf_flash_lock(h, 1);
+ error = flash_cmd(h, SPM_WREN, 1, 0);
+ error = flash_cmd(h, SPM_WRSR, 2, 0); // clr status
+
+ error = flash_erase(h, addr);
+ if (error < 0) return error;
+
+ error = flash_write(h, readbuf, addr, 0x10000); // clr status
+ dpf_flash_lock(h, 0);
+
+ return error;
+}
+
+////////////////////////////////////////////////////////////////////////////
+// High level functions, generic
+// These require a hacked command handler with extended command set.
+
+
+int load_hexfile(DPFContext *h, const char *hexfile)
+{
+ unsigned int len = 0xc000;
+ int error;
+
+ error = load_ihx(h, hexfile, 0, &len, 0x800);
+ return error;
+}
+
+#define CHUNK_SIZE 1024
+
+int read_mem(DPFContext *h, unsigned char *buf, ADDR src, unsigned short len)
+{
+ int error = 0;
+ if (!h->methods.mem_read) return DEVERR_UNSUPP;
+
+ while (len > CHUNK_SIZE && error >= 0) {
+ error = h->methods.mem_read(h, buf, src, CHUNK_SIZE);
+ src += CHUNK_SIZE; len -= CHUNK_SIZE; buf += CHUNK_SIZE;
+ }
+ error = h->methods.mem_read(h, buf, src, len);
+
+ return error;
+}
+
+int write_mem(DPFContext *h, ADDR dst, const unsigned char *buf, unsigned short len)
+{
+ return h->methods.mem_write(h, dst, buf, len);
+}
+
+int code_go(DPFContext *h, ADDR start)
+{
+ printf("Executing applet..\n");
+ if (h->methods.go)
+ return h->methods.go(h, start);
+ return DEVERR_UNSUPP;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// High level functions, DPF specific
+
+/* Bootstrap mode: Expects contiguous memory block to download, then jumps
+ * into start address
+ */
+
+int dpf_bootstrap(DPFContext *h,
+ ADDR dest, unsigned char *src, unsigned short n, ADDR start)
+{
+ if (h->methods.bootstrap)
+ return h->methods.bootstrap(h, dest, src, n, start);
+ else
+ return DEVERR_UNSUPP;
+}
+
+
+
diff --git a/libdpf/flash.h b/libdpf/flash.h
new file mode 100644
index 0000000..f753bd5
--- /dev/null
+++ b/libdpf/flash.h
@@ -0,0 +1,19 @@
+// SPI STM flash commands:
+// stolen from BFloader
+
+#define SPM_RDID 0x9f // Read ID
+#define SPM_WREN 0x06 // Write enable
+#define SPM_WRDI 0x04 // Write disable
+#define SPM_RDSR 0x05 // Read status register
+#define SPM_WRSR 0x01 // Write status register
+#define SPM_READ 0x03 // Read data bytes
+#define SPM_PP 0x02 // Page program
+#define SPM_DP 0xb9 // Deep power down
+#define SPM_RES 0xab // Release from deep power down
+ // and read signature
+#define SPM_FLASH_SE 0xd8 // Sector erase
+#define SPM_FLASH_BE 0xc7 // Bulk erase
+#define SPM_FLASH_FAST_READ 0x0B // Read data bytes fast
+
+#define SPM_SR_SRWD 0x80 // SR write protection (HW)
+
diff --git a/libdpf/fwload.c b/libdpf/fwload.c
new file mode 100644
index 0000000..2b98762
--- /dev/null
+++ b/libdpf/fwload.c
@@ -0,0 +1,121 @@
+/** DPF firmware loader
+ *
+ * 12/2010 <hackfin@section5.ch>
+ *
+ * Based on the FX2 ihx loader
+ *
+ */
+
+#include "dpf.h"
+#include <stdio.h>
+
+////////////////////////////////////////////////////////////////////////////
+
+// Demo stuff:
+
+void memory_dump(unsigned char *buf, unsigned int n)
+{
+ int i = 0;
+ int c = 0;
+
+ while (i < n) {
+ printf("%02x ", buf[i]);
+ c++;
+ if (c == 16) { c = 0; printf("\n"); }
+ i++;
+ }
+ if (c)
+ printf("\n");
+}
+
+////////////////////////////////////////////////////////////////////////////
+
+
+#if EXPERIMENTAL
+
+int xmain(int argc, char **argv)
+{
+ int ret;
+ int i;
+ struct banktable *bt;
+
+ // flash offset, offset after jump table
+ unsigned int offset = 0x80000 + 0x200;
+
+
+ static unsigned char buf[0x10000];
+ unsigned int len = sizeof(buf);
+ ret = load_ihx(argv[1], buf, &len, 0x127c, g_banktab);
+ if (ret < 0) {
+ fprintf(stderr, "Failed to load HEX file\n");
+ return ret;
+ } else {
+ printf("Read %d banks\n", ret);
+ for (i = 0; i < ret; i++) {
+ bt = &g_banktab[i];
+ printf(" { XADDR(0x%04x), XADDR(0x%04x), FOFFS(0x%06x) },\n",
+ bt->reloc, bt->reloc + bt->len, offset + bt->offset);
+
+ }
+ }
+ return 0;
+}
+
+#endif
+
+int main(int argc, char **argv)
+{
+ int ret;
+ DPFHANDLE h;
+
+ int i = 2;
+
+ if (argc < 2 || argc > 3) {
+ fprintf(stderr, "Usage:\n"
+ "%s <generic scsi dev> <.ihx file>\n"
+ "or in USB mode:\n"
+ "%s <.ihx file>\n",
+ argv[0], argv[0]);
+ return -1;
+ }
+
+ if (argc == 2) {
+ ret = dpf_open(NULL, &h);
+ i--;
+ } else
+ if (argc == 3) {
+ ret = dpf_open(argv[1], &h);
+ }
+
+ if (ret < 0) {
+ perror("opening DPF device:");
+ return ret;
+ }
+
+// This patches a module to init the relocated jump table on a certain
+// menu action:
+// ret = patch_sector(h, 0x1330, 0x4af7a, "hack2.ihx");
+
+
+// patch_sector(h, 0x0, 0x100000, "jumptbl.ihx");
+
+ if (0) {
+ patch_sector(h, 0x0, 0x100000, "jumptbl.ihx");
+ ret = patch_sector(h, 0x1330, 0x110000, "hack.ihx");
+ ret = patch_sector(h, 0x132a, 0x120000, "main.ihx");
+ if (ret < 0) printf("Failed.\n");
+ } else {
+ // demo0(h);
+
+ }
+ ret = load_hexfile(h, argv[i]);
+ code_go(h, 0x18a0);
+ if (ret < 0) printf("Failed.\n");
+
+ // unsigned char buf[256];
+ // ret = read_mem(h, buf, 0x18a0, 64);
+ // memory_dump(buf, 64);
+
+ dpf_close(h);
+ return ret;
+}
diff --git a/libdpf/rawusb.c b/libdpf/rawusb.c
new file mode 100644
index 0000000..cbd344c
--- /dev/null
+++ b/libdpf/rawusb.c
@@ -0,0 +1,195 @@
+/* Low level USB code to access DPF.
+ *
+ * (c) 2010, 2011 <hackfin@section5.ch>
+ *
+ * This currently uses the SCSI command set
+ *
+ * The reason for this is that we want to access the hacked frame
+ * non-root and without having to wait for the SCSI interface to
+ * intialize.
+ *
+ * Later, we'll replace the SCSI command stuff.
+ */
+
+#include "dpf.h"
+#include "sglib.h"
+
+#include <string.h>
+#include <stdio.h>
+
+#define ENDPT_OUT 1
+#define ENDPT_IN 0x81
+
+struct known_device {
+ char *desc;
+ unsigned short vid;
+ unsigned short pid;
+} g_known_devices[] = {
+ { "AX206 DPF", 0x1908, 0x0102 },
+ { "AX206 DPF (bootloader)", 0x1908, 0x3318 },
+ { 0 , 0, 0 } /* NEVER REMOVE THIS */
+};
+
+int handle_error(char *txt)
+{
+ fprintf(stderr, "Error: %s\n", txt);
+ return -1;
+}
+
+void usb_flush(usb_dev_handle *dev)
+{
+ char buf[20];
+ usb_bulk_read(dev, ENDPT_IN, buf, 3, 1000);
+}
+
+int check_known_device(struct usb_device *d)
+{
+ struct known_device *dev = g_known_devices;
+
+ while (dev->desc) {
+ if ((d->descriptor.idVendor == dev->vid) &&
+ (d->descriptor.idProduct == dev->pid)) {
+ fprintf(stderr, "Found %s\n", dev->desc);
+ return 1;
+ }
+ dev++;
+ }
+ return 0;
+}
+
+static struct usb_device *find_dev(int index)
+{
+ struct usb_bus *b;
+ struct usb_device *d;
+ int enumeration = 0;
+
+ b = usb_get_busses();
+
+ while (b) {
+ d = b->devices;
+ while (d) {
+ if (check_known_device(d)) {
+ if (enumeration == index) return d;
+ else enumeration++;
+ }
+
+#ifdef DEBUG
+ printf("enum: %d index: %d\n", enumeration, index);
+ printf("%04x %04x\n",
+ d->descriptor.idVendor,
+ d->descriptor.idProduct);
+#endif
+ d = d->next;
+ }
+ b = b->next;
+ }
+ return NULL;
+}
+
+char g_buf[] = {
+ 0x55, 0x53, 0x42, 0x43, // dCBWSignature
+ 0xde, 0xad, 0xbe, 0xef, // dCBWTag
+ 0x00, 0x80, 0x00, 0x00, // dCBWLength
+ 0x00, // bmCBWFlags: 0x80: data in (dev to host), 0x00: Data out
+ 0x00, // bCBWLUN
+ 0x10, // bCBWCBLength
+
+ // SCSI cmd:
+ 0xcd, 0x00, 0x00, 0x00,
+ 0x00, 0x06, 0x11, 0xf8,
+ 0x70, 0x00, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+};
+
+int emulate_scsi(usb_dev_handle *dev, unsigned char *cmd, int cmdlen, char out,
+ unsigned char *data, unsigned long block_len)
+{
+ int len;
+ int ret;
+ static unsigned char ansbuf[13]; // Do not change size.
+
+ g_buf[14] = cmdlen;
+ memcpy(&g_buf[15], cmd, cmdlen);
+
+ g_buf[8] = block_len;
+ g_buf[9] = block_len >> 8;
+ g_buf[10] = block_len >> 16;
+ g_buf[11] = block_len >> 24;
+
+ ret = usb_bulk_write(dev, ENDPT_OUT, g_buf, sizeof(g_buf), 1000);
+ if (ret < 0) return ret;
+
+ if (out == DIR_OUT) {
+ if (data) {
+ ret = usb_bulk_write(dev, ENDPT_OUT, (char* )data,
+ block_len, 3000);
+ if (ret != block_len) {
+ perror("bulk write");
+ return ret;
+ }
+ }
+ } else if (data) {
+ ret = usb_bulk_read(dev, ENDPT_IN, (char *) data, block_len, 4000);
+ if (ret != block_len) {
+ perror("bulk data read");
+ }
+ }
+ // get ACK:
+ len = sizeof(ansbuf);
+ int retry = 0;
+ do {
+ ret = usb_bulk_read(dev, ENDPT_IN, (char *) ansbuf, len, 5000);
+ if (ret != len) {
+ perror("bulk ACK read");
+ ret = DEVERR_TIMEOUT;
+ }
+ retry++;
+ } while (ret == DEVERR_TIMEOUT && retry < 5);
+ if (strncmp((char *) ansbuf, "USBS", 4)) {
+ return handle_error("Got invalid reply\n");
+ }
+ // pass back return code set by peer:
+ return ansbuf[12];
+}
+
+int dpf_usb_open(int index, usb_dev_handle **u)
+{
+ struct usb_device *d;
+ usb_dev_handle *usb_dev;
+
+ usb_find_busses();
+ usb_find_devices();
+
+ d = find_dev(index);
+ if (!d) {
+ handle_error("No matching USB device found!");
+ return -1;
+ }
+
+ usb_dev = usb_open(d);
+ if (usb_dev == NULL) {
+ handle_error("Failed to open usb device!");
+ return -1;
+ }
+ if (usb_claim_interface(usb_dev, 0) < 0) {
+ handle_error("Failed to claim usb device!");
+ printf("Possibly you have to 'sudo libhid-detach-device 1908:3318'\n");
+ return -1;
+ }
+ *u = usb_dev;
+
+ if (d->descriptor.idProduct == 0x3318)
+ return MODE_USBHID;
+ else
+ return MODE_USB;
+}
+
+int usb_rawwrite(usb_dev_handle *dev, const unsigned char *buf, int len)
+{
+ return usb_interrupt_write(dev, ENDPT_OUT, (char *) buf, len, 1000);
+}
+
+int usb_rawread(usb_dev_handle *dev, unsigned char *buf, int len)
+{
+ return usb_interrupt_read(dev, ENDPT_IN, (char *) buf, len, 4000);
+}
diff --git a/libdpf/scsi.c b/libdpf/scsi.c
new file mode 100644
index 0000000..3f82fc7
--- /dev/null
+++ b/libdpf/scsi.c
@@ -0,0 +1,412 @@
+/**
+ * (c) 2011, <hackfin@section5.ch>
+ *
+ */
+
+#include "sglib.h"
+#include "usbuser.h" // our user defined flash commands
+#include "dpf.h"
+
+#include <scsi/scsi.h>
+#include <scsi/sg.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+
+int do_scsi(int fd, unsigned char *cmd, int cmdlen, char out,
+ unsigned char *data, unsigned long block_len)
+{
+ int error;
+ unsigned char sensebuf[32];
+ sg_io_hdr_t io_hdr;
+ memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
+
+ io_hdr.interface_id = 'S';
+ io_hdr.sbp = sensebuf;
+ io_hdr.mx_sb_len = sizeof(sensebuf);
+ if (data == 0) {
+ io_hdr.dxfer_direction = SG_DXFER_NONE;
+ } else {
+ if (out) {
+ io_hdr.dxfer_direction = SG_DXFER_TO_DEV;
+ } else {
+ io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;
+ }
+ }
+ io_hdr.dxferp = data;
+ io_hdr.dxfer_len = block_len;
+ io_hdr.cmdp = cmd;
+ io_hdr.cmd_len = cmdlen;
+ io_hdr.timeout = 5000; // in ms
+ error = ioctl(fd, SG_IO, &io_hdr);
+ if (error < 0) perror("calling SCSI ioctl()");
+ return error;
+}
+
+
+int wrap_scsi(DPFContext *h, unsigned char *cmd, int cmdlen, char out,
+ unsigned char *data, unsigned long block_len)
+{
+ int error;
+ switch (h->mode) {
+ case MODE_USB:
+ error = emulate_scsi(h->dev.udev,
+ cmd, cmdlen, out, data, block_len);
+ break;
+ case MODE_SG:
+ error = do_scsi(h->dev.fd, cmd, cmdlen, out, data, block_len);
+ break;
+ case MODE_USBHID:
+ fprintf(stderr, "USBHID mode not (yet) supported\n");
+ error = -1;
+ }
+ return error;
+}
+
+
+/** Vendor command for our hacks */
+static
+unsigned char g_excmd[16] = {
+ 0xcd, 0, 0, 0,
+ 0, 6, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+};
+
+
+/* device wrapper */
+
+const char idstring[] = "buildwin Photo Frame 1.01";
+
+#define INQ_REPLY_LEN 96
+
+int sgdev_open(const char *portname, int *fd)
+{
+ int error;
+
+ static
+ unsigned char inquiry[] = {
+ INQUIRY, 0, 0, 0,
+ INQ_REPLY_LEN, 0
+ };
+
+ static unsigned char inqbuf[INQ_REPLY_LEN + 2];
+
+ *fd = open(portname, O_RDONLY | O_NONBLOCK );
+ error = do_scsi(*fd, inquiry, sizeof(inquiry), DIR_IN, inqbuf,
+ INQ_REPLY_LEN);
+
+ if (error < 0) {
+ fprintf(stderr, "SCSI inquiry failed\n");
+ close(*fd); error = DEVERR_OPEN;
+ } else
+ if (memcmp(idstring, &inqbuf[8], sizeof(idstring) - 1) != 0) {
+ close(*fd); error = DEVERR_OPEN;
+ fprintf(stderr, "Not a photo frame. Refuse to open device.\n");
+ }
+ return error;
+}
+
+int probe(DPFHANDLE h)
+{
+ int ret;
+
+ // We abuse a command that just responds with a '0' status in the
+ // original firmware.
+ static unsigned char buf[5];
+
+
+ static
+ unsigned char cmd[16] = {
+ 0xcd, 0, 0, 0,
+ 0, 3, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0, 0, 0
+ };
+
+ cmd[5] = 3;
+ ret = wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, 0, 0);
+
+ switch (ret) {
+ case 0:
+ // The original protocol.
+ fprintf(stderr,
+ "Warning: This firmware can not lock the flash\n");
+ break;
+ case 1:
+ // The improved hack
+ h->flags |= FLAG_CAN_LOCK;
+ break;
+ }
+
+ cmd[5] = 2; // get LCD parameters
+ ret = wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, buf, 5);
+ h->width = (buf[0]) | (buf[1] << 8);
+ h->height = (buf[2]) | (buf[3] << 8);
+ h->bpp = 2;
+
+ return ret;
+}
+
+/* Memory stuff */
+
+static
+int mem_read_scsi(DPFContext *h, unsigned char *buf, ADDR offset, int len)
+{
+ unsigned char *cmd = g_excmd;
+
+ if (h->mode == MODE_USBHID) return DEVERR_UNSUPP;
+
+ cmd[6] = USBCMD_MEMREAD; // memory_read
+ cmd[7] = offset;
+ cmd[8] = offset >> 8;
+ cmd[9] = len;
+ cmd[10] = len >> 8;
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_IN, buf, len);
+}
+
+int mem_write_scsi(DPFContext *h,
+ ADDR dst, const unsigned char *src, unsigned short n)
+{
+ unsigned char *cmd = g_excmd;
+
+ cmd[6] = 0x01; // memory_write
+ cmd[7] = dst;
+ cmd[8] = dst >> 8;
+ cmd[9] = n;
+ cmd[10] = n >> 8;
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, (unsigned char *) src, n);
+}
+
+
+
+/* Flash stuff, SCSI wrapped */
+
+static
+int flash_cmd_scsi(DPFContext *h, int command, int cmdlen, ADDR addr)
+{
+ static
+ unsigned char cmd[16] = {
+ 0xcb, 0, 0, 0, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 0,
+ 0, 0
+ };
+
+ cmd[10] = command;
+ cmd[6] = cmdlen;
+
+ // Sector number or addr:
+ cmd[13] = addr;
+ cmd[12] = addr >> 8;
+ cmd[11] = addr >> 16;
+
+ return wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, 0, 0);
+}
+
+int flash_status_scsi(DPFHANDLE h, uint8_t *status)
+{
+ *status = 0;
+ // FIXME : Really get status
+ return 0;
+}
+
+static
+int flash_read_scsi(DPFContext *h, unsigned char *buf, ADDR offset, int len)
+{
+ static
+ unsigned char cmd[16] = {
+ 0xcd, 0, 0, 0, 0, 0,
+ 0x04, /* num of bytes: */ 0, 0, 0,
+ SPM_READ, /* SPI offset: */ 0, 0, 0,
+ 0, 0
+ };
+
+ cmd[9] = len >> 0;
+ cmd[8] = len >> 8;
+ cmd[7] = len >> 16;
+
+ cmd[13] = offset >> 0;
+ cmd[12] = offset >> 8;
+ cmd[11] = offset >> 16;
+
+ return wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, buf, len);
+}
+
+static
+int flash_writechunk_scsi(DPFContext *h,
+ const unsigned char *buf, ADDR offset, int len)
+{
+ int error;
+ static
+ unsigned char cmd[16] = {
+ 0xcb, 0, 0, 0, 0, 0,
+ 4, /* num of bytes: */ 0, 0, 0,
+ SPM_PP, /* SPI offset: */ 0, 0, 0,
+ 0, 0
+ };
+
+ if (len > MAX_CHUNKSIZE) len = MAX_CHUNKSIZE;
+
+ cmd[9] = len >> 0;
+ cmd[8] = len >> 8;
+ cmd[7] = len >> 16;
+
+ cmd[13] = offset >> 0;
+ cmd[12] = offset >> 8;
+ cmd[11] = offset >> 16;
+
+ error = wrap_scsi(h, cmd, sizeof(cmd), DIR_OUT,
+ (unsigned char*) buf, len);
+ if (error < 0) return error;
+ return len;
+}
+
+int flash_lock_usb(DPFContext *h, char enable)
+{
+ unsigned char *cmd = g_excmd;
+
+ if (!(h->flags & FLAG_CAN_LOCK)) return DEVERR_UNSUPP;
+
+ printf("Lock flash %d\n", enable);
+ cmd[6] = USBCMD_FLASHLOCK; // flash lock
+ cmd[7] = enable;
+
+ wrap_scsi(h, cmd, sizeof(g_excmd), DIR_IN, 0, 0);
+ return 0;
+}
+
+static
+int flash_probe_scsi(DPFContext *h, unsigned char *id)
+{
+ int error;
+ static
+ unsigned char buf[64];
+ static
+ unsigned char cmd[16] = {
+ 0xcd, 0, 0, 0, 0, 0,
+ 1, sizeof(buf) >> 16, sizeof(buf) >> 8, sizeof(buf) >> 0,
+ // flash command sequence:
+ SPM_RDID, 0, 0, 0,
+ 0, 0
+ };
+
+ error = wrap_scsi(h, cmd, sizeof(cmd), DIR_IN, buf, sizeof(buf));
+ id[0] = buf[0]; id[1] = buf[1]; id[2] = buf[2];
+ return error;
+}
+
+
+static
+int go_scsi(DPFContext *h, ADDR start)
+{
+ unsigned char *cmd = g_excmd;
+ cmd[6] = 0x02; // execute
+ cmd[7] = start;
+ cmd[8] = start >> 8;
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_IN, 0, 0);
+}
+
+static
+int bootstrap_scsi(DPFContext *h,
+ ADDR dest, unsigned char *src, unsigned short n, ADDR start)
+{
+ unsigned char *cmd = g_excmd;
+
+ cmd[6] = USBCMD_APPLOAD; // Enter bootstrap mode
+ cmd[7] = dest;
+ cmd[8] = dest >> 8;
+ cmd[9] = n;
+ cmd[10] = n >> 8;
+ cmd[11] = start;
+ cmd[12] = start >> 8;
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, src, n);
+}
+
+AccessMethods
+scsi_methods = {
+ .mem_read = mem_read_scsi,
+ .mem_write = mem_write_scsi,
+ .go = go_scsi,
+ .bootstrap = bootstrap_scsi,
+ .flash_probe = flash_probe_scsi,
+ .flash_cmd = flash_cmd_scsi,
+ .flash_status = flash_status_scsi,
+ .flash_read = flash_read_scsi,
+ .flash_writechunk = flash_writechunk_scsi,
+ .flash_lock = flash_lock_usb,
+};
+
+////////////////////////////////////////////////////////////////////////////
+// SCSI only high level commands:
+
+int dpf_setcol(DPFContext *h, const unsigned char *rgb)
+{
+ unsigned char *cmd = g_excmd;
+
+ if (h->mode == MODE_USBHID) return DEVERR_UNSUPP;
+
+ cmd[6] = USBCMD_SETPROPERTY;
+ cmd[7] = PROPERTY_FGCOLOR;
+ cmd[8] = PROPERTY_FGCOLOR >> 8;
+
+ cmd[9] = RGB565_0(rgb[0], rgb[1], rgb[2]);
+ cmd[10] = RGB565_1(rgb[0], rgb[1], rgb[2]);
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, NULL, 0);
+}
+
+int dpf_screen_blit(DPFContext *h,
+ const unsigned char *buf, short rect[4])
+{
+ unsigned long len = (rect[2] - rect[0]) * (rect[3] - rect[1]);
+ len <<= 1;
+ unsigned char *cmd = g_excmd;
+
+ if (h->mode == MODE_USBHID) return DEVERR_UNSUPP;
+
+ cmd[6] = USBCMD_BLIT;
+ cmd[7] = rect[0];
+ cmd[8] = rect[0] >> 8;
+ cmd[9] = rect[1];
+ cmd[10] = rect[1] >> 8;
+ cmd[11] = rect[2] - 1;
+ cmd[12] = (rect[2] - 1) >> 8;
+ cmd[13] = rect[3] - 1;
+ cmd[14] = (rect[3] - 1) >> 8;
+ cmd[15] = 0;
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT,
+ (unsigned char*) buf, len);
+}
+
+int dpf_setproperty(DPFContext *h, int token, const DPFValue *value)
+{
+ unsigned char *cmd = g_excmd;
+
+ if (h->mode == MODE_USBHID) return DEVERR_UNSUPP;
+
+ cmd[6] = USBCMD_SETPROPERTY;
+ cmd[7] = token;
+ cmd[8] = token >> 8;
+
+ switch (value->type) {
+ case TYPE_INTEGER:
+ cmd[9] = value->value.integer;
+ cmd[10] = value->value.integer >> 8;
+ break;
+ default:
+ break;
+ }
+
+ return wrap_scsi(h, cmd, sizeof(g_excmd), DIR_OUT, NULL, 0);
+}
+
+
diff --git a/libdpf/sglib.h b/libdpf/sglib.h
new file mode 100644
index 0000000..a2bc232
--- /dev/null
+++ b/libdpf/sglib.h
@@ -0,0 +1,19 @@
+#include <stdint.h>
+
+
+/* generic device wrapper: */
+
+const char* dev_errstr(int error);
+
+
+/* generic SCSI device stuff: */
+
+#define DIR_IN 0
+#define DIR_OUT 1
+
+
+/* Special functions */
+
+
+
+
diff --git a/libdpf/spiflash.h b/libdpf/spiflash.h
new file mode 100644
index 0000000..fe7a8fd
--- /dev/null
+++ b/libdpf/spiflash.h
@@ -0,0 +1,30 @@
+/** \file flashcmd_st.h
+ *
+ * ST compatible flash cmds
+ *
+ */
+
+
+#define SPM_RDID 0x9f // Read Id
+#define SPM_NO_CMD 0x00 // No command
+
+#define SPM_WREN 0x06 // Write enable
+#define SPM_WRDI 0x04 // Write disable
+#define SPM_RDSR 0x05 // Read status register
+#define SPM_WRSR 0x01 // Write status register
+#define SPM_READ 0x03 // Read data bytes
+#define SPM_PP 0x02 // Page program
+#define SPM_DP 0xb9 // Deep power down
+#define SPM_RES 0xab // Release from deep power down
+ // and read signature
+#define SPM_FLASH_SE 0xd8 // Sector erase
+#define SPM_FLASH_BE 0xc7 // Bulk erase
+#define SPM_FLASH_FAST_READ 0x0B // Read data bytes fast
+
+#define SPM_SR_SRWD 0x80 // SR write protection (HW)
+
+// Status register bit definitions
+#define SPS_WIP 0x01 // write in progress
+#define SPS_WEL 0x02 // write enable latch
+
+
diff --git a/libdpf/usbuser.h b/libdpf/usbuser.h
new file mode 100644
index 0000000..37fb705
--- /dev/null
+++ b/libdpf/usbuser.h
@@ -0,0 +1,29 @@
+/* USB user commands
+ *
+ * Only temporary. Should move to dpflib or into a dclib configuration.
+ *
+ */
+
+#define PROTOCOL_VERSION 1
+
+/** Our vendor specific USB commands to do stuff on the DPF */
+
+#define USBCMD_GETPROPERTY 0x00 ///< Get property
+#define USBCMD_SETPROPERTY 0x01 ///< Set property
+#define USBCMD_MEMREAD 0x04 ///< Memory read
+#define USBCMD_APPLOAD 0x05 ///< Load and run applet
+#define USBCMD_FILLRECT 0x11 ///< Fill screen rectangle
+#define USBCMD_BLIT 0x12 ///< Blit to screen
+#define USBCMD_COPYRECT 0x13 ///< Copy screen rectangle
+#define USBCMD_FLASHLOCK 0x20 ///< Lock USB for flash access
+#define USBCMD_PROBE 0xff ///< Get version code (probe)
+
+/* Some special return codes */
+#define USB_IN_SEQUENCE 0x7f ///< We're inside a command sequence
+
+// Property handling:
+
+#define PROPERTY_BRIGHTNESS 0x01
+#define PROPERTY_FGCOLOR 0x02
+#define PROPERTY_BGCOLOR 0x03
+#define PROPERTY_ORIENTATION 0x10
diff --git a/lirc.h b/lirc.h
new file mode 100644
index 0000000..4b3ab29
--- /dev/null
+++ b/lirc.h
@@ -0,0 +1,168 @@
+/*
+ * lirc.h - linux infrared remote control header file
+ * last modified 2010/07/13 by Jarod Wilson
+ */
+
+#ifndef _LINUX_LIRC_H
+#define _LINUX_LIRC_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define PULSE_BIT 0x01000000
+#define PULSE_MASK 0x00FFFFFF
+
+#define LIRC_MODE2_SPACE 0x00000000
+#define LIRC_MODE2_PULSE 0x01000000
+#define LIRC_MODE2_FREQUENCY 0x02000000
+#define LIRC_MODE2_TIMEOUT 0x03000000
+
+#define LIRC_VALUE_MASK 0x00FFFFFF
+#define LIRC_MODE2_MASK 0xFF000000
+
+#define LIRC_SPACE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_SPACE)
+#define LIRC_PULSE(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_PULSE)
+#define LIRC_FREQUENCY(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_FREQUENCY)
+#define LIRC_TIMEOUT(val) (((val)&LIRC_VALUE_MASK) | LIRC_MODE2_TIMEOUT)
+
+#define LIRC_VALUE(val) ((val)&LIRC_VALUE_MASK)
+#define LIRC_MODE2(val) ((val)&LIRC_MODE2_MASK)
+
+#define LIRC_IS_SPACE(val) (LIRC_MODE2(val) == LIRC_MODE2_SPACE)
+#define LIRC_IS_PULSE(val) (LIRC_MODE2(val) == LIRC_MODE2_PULSE)
+#define LIRC_IS_FREQUENCY(val) (LIRC_MODE2(val) == LIRC_MODE2_FREQUENCY)
+#define LIRC_IS_TIMEOUT(val) (LIRC_MODE2(val) == LIRC_MODE2_TIMEOUT)
+
+/* used heavily by lirc userspace */
+#define lirc_t int
+
+/*** lirc compatible hardware features ***/
+
+#define LIRC_MODE2SEND(x) (x)
+#define LIRC_SEND2MODE(x) (x)
+#define LIRC_MODE2REC(x) ((x) << 16)
+#define LIRC_REC2MODE(x) ((x) >> 16)
+
+#define LIRC_MODE_RAW 0x00000001
+#define LIRC_MODE_PULSE 0x00000002
+#define LIRC_MODE_MODE2 0x00000004
+#define LIRC_MODE_LIRCCODE 0x00000010
+
+
+#define LIRC_CAN_SEND_RAW LIRC_MODE2SEND(LIRC_MODE_RAW)
+#define LIRC_CAN_SEND_PULSE LIRC_MODE2SEND(LIRC_MODE_PULSE)
+#define LIRC_CAN_SEND_MODE2 LIRC_MODE2SEND(LIRC_MODE_MODE2)
+#define LIRC_CAN_SEND_LIRCCODE LIRC_MODE2SEND(LIRC_MODE_LIRCCODE)
+
+#define LIRC_CAN_SEND_MASK 0x0000003f
+
+#define LIRC_CAN_SET_SEND_CARRIER 0x00000100
+#define LIRC_CAN_SET_SEND_DUTY_CYCLE 0x00000200
+#define LIRC_CAN_SET_TRANSMITTER_MASK 0x00000400
+
+#define LIRC_CAN_REC_RAW LIRC_MODE2REC(LIRC_MODE_RAW)
+#define LIRC_CAN_REC_PULSE LIRC_MODE2REC(LIRC_MODE_PULSE)
+#define LIRC_CAN_REC_MODE2 LIRC_MODE2REC(LIRC_MODE_MODE2)
+#define LIRC_CAN_REC_LIRCCODE LIRC_MODE2REC(LIRC_MODE_LIRCCODE)
+
+#define LIRC_CAN_REC_MASK LIRC_MODE2REC(LIRC_CAN_SEND_MASK)
+
+#define LIRC_CAN_SET_REC_CARRIER (LIRC_CAN_SET_SEND_CARRIER << 16)
+#define LIRC_CAN_SET_REC_DUTY_CYCLE (LIRC_CAN_SET_SEND_DUTY_CYCLE << 16)
+
+#define LIRC_CAN_SET_REC_DUTY_CYCLE_RANGE 0x40000000
+#define LIRC_CAN_SET_REC_CARRIER_RANGE 0x80000000
+#define LIRC_CAN_GET_REC_RESOLUTION 0x20000000
+#define LIRC_CAN_SET_REC_TIMEOUT 0x10000000
+#define LIRC_CAN_SET_REC_FILTER 0x08000000
+
+#define LIRC_CAN_MEASURE_CARRIER 0x02000000
+#define LIRC_CAN_USE_WIDEBAND_RECEIVER 0x04000000
+
+#define LIRC_CAN_SEND(x) ((x)&LIRC_CAN_SEND_MASK)
+#define LIRC_CAN_REC(x) ((x)&LIRC_CAN_REC_MASK)
+
+#define LIRC_CAN_NOTIFY_DECODE 0x01000000
+
+/*** IOCTL commands for lirc driver ***/
+
+#define LIRC_GET_FEATURES _IOR('i', 0x00000000, __u32)
+
+#define LIRC_GET_SEND_MODE _IOR('i', 0x00000001, __u32)
+#define LIRC_GET_REC_MODE _IOR('i', 0x00000002, __u32)
+#define LIRC_GET_SEND_CARRIER _IOR('i', 0x00000003, __u32)
+#define LIRC_GET_REC_CARRIER _IOR('i', 0x00000004, __u32)
+#define LIRC_GET_SEND_DUTY_CYCLE _IOR('i', 0x00000005, __u32)
+#define LIRC_GET_REC_DUTY_CYCLE _IOR('i', 0x00000006, __u32)
+#define LIRC_GET_REC_RESOLUTION _IOR('i', 0x00000007, __u32)
+
+#define LIRC_GET_MIN_TIMEOUT _IOR('i', 0x00000008, __u32)
+#define LIRC_GET_MAX_TIMEOUT _IOR('i', 0x00000009, __u32)
+
+#define LIRC_GET_MIN_FILTER_PULSE _IOR('i', 0x0000000a, __u32)
+#define LIRC_GET_MAX_FILTER_PULSE _IOR('i', 0x0000000b, __u32)
+#define LIRC_GET_MIN_FILTER_SPACE _IOR('i', 0x0000000c, __u32)
+#define LIRC_GET_MAX_FILTER_SPACE _IOR('i', 0x0000000d, __u32)
+
+/* code length in bits, currently only for LIRC_MODE_LIRCCODE */
+#define LIRC_GET_LENGTH _IOR('i', 0x0000000f, __u32)
+
+#define LIRC_SET_SEND_MODE _IOW('i', 0x00000011, __u32)
+#define LIRC_SET_REC_MODE _IOW('i', 0x00000012, __u32)
+/* Note: these can reset the according pulse_width */
+#define LIRC_SET_SEND_CARRIER _IOW('i', 0x00000013, __u32)
+#define LIRC_SET_REC_CARRIER _IOW('i', 0x00000014, __u32)
+#define LIRC_SET_SEND_DUTY_CYCLE _IOW('i', 0x00000015, __u32)
+#define LIRC_SET_REC_DUTY_CYCLE _IOW('i', 0x00000016, __u32)
+#define LIRC_SET_TRANSMITTER_MASK _IOW('i', 0x00000017, __u32)
+
+/*
+ * when a timeout != 0 is set the driver will send a
+ * LIRC_MODE2_TIMEOUT data packet, otherwise LIRC_MODE2_TIMEOUT is
+ * never sent, timeout is disabled by default
+ */
+#define LIRC_SET_REC_TIMEOUT _IOW('i', 0x00000018, __u32)
+
+/* 1 enables, 0 disables timeout reports in MODE2 */
+#define LIRC_SET_REC_TIMEOUT_REPORTS _IOW('i', 0x00000019, __u32)
+
+/*
+ * pulses shorter than this are filtered out by hardware (software
+ * emulation in lirc_dev?)
+ */
+#define LIRC_SET_REC_FILTER_PULSE _IOW('i', 0x0000001a, __u32)
+/*
+ * spaces shorter than this are filtered out by hardware (software
+ * emulation in lirc_dev?)
+ */
+#define LIRC_SET_REC_FILTER_SPACE _IOW('i', 0x0000001b, __u32)
+/*
+ * if filter cannot be set independently for pulse/space, this should
+ * be used
+ */
+#define LIRC_SET_REC_FILTER _IOW('i', 0x0000001c, __u32)
+
+/*
+ * if enabled from the next key press on the driver will send
+ * LIRC_MODE2_FREQUENCY packets
+ */
+#define LIRC_SET_MEASURE_CARRIER_MODE _IOW('i', 0x0000001d, __u32)
+
+/*
+ * to set a range use
+ * LIRC_SET_REC_DUTY_CYCLE_RANGE/LIRC_SET_REC_CARRIER_RANGE with the
+ * lower bound first and later
+ * LIRC_SET_REC_DUTY_CYCLE/LIRC_SET_REC_CARRIER with the upper bound
+ */
+
+#define LIRC_SET_REC_DUTY_CYCLE_RANGE _IOW('i', 0x0000001e, __u32)
+#define LIRC_SET_REC_CARRIER_RANGE _IOW('i', 0x0000001f, __u32)
+
+#define LIRC_NOTIFY_DECODE _IO('i', 0x00000020)
+
+#define LIRC_SETUP_START _IO('i', 0x00000021)
+#define LIRC_SETUP_END _IO('i', 0x00000022)
+
+#define LIRC_SET_WIDEBAND_RECEIVER _IOW('i', 0x00000023, __u32)
+
+#endif
diff --git a/map.c b/map.c
new file mode 100644
index 0000000..d3bd341
--- /dev/null
+++ b/map.c
@@ -0,0 +1,167 @@
+#include "project.h"
+
+#ifdef MAP_NULL
+
+void
+map_output (int *computer, int *x, int *y)
+{
+}
+
+#elif defined(MAP_HOME)
+
+void
+map_output (int *computer, int *x, int *y)
+{
+
+ switch (*computer)
+ {
+ case 1:
+ *computer = 5;
+ break;
+ case 2:
+ *computer = 4;
+ break;
+ case 3:
+ *computer = 0;
+ if (x)
+ *x = *x / 2;
+ break;
+ case 4:
+ *computer = 0;
+ if (x)
+ *x = (*x / 2) + 1024;
+ break;
+ case 5:
+ case 6:
+ case 7:
+ (*computer) -= 4;
+ break;
+ }
+}
+
+#endif
+
+int
+map_grace_left (int computer)
+{
+ int console = layout_computer_to_console (computer);
+ int cl = layout_console_to_computer (console - 1);
+
+ if ((cl < 1) || (cl > N_COMPUTER))
+ return 1;
+
+ map_output (&computer, NULL, NULL);
+ map_output (&cl, NULL, NULL);
+
+ return cl != computer;
+}
+
+int
+map_grace_right (int computer)
+{
+ int console = layout_computer_to_console (computer);
+ int cl = layout_console_to_computer (console + 1);
+ if ((cl < 1) || (cl > N_COMPUTER))
+ return 1;
+
+ map_output (&computer, NULL, NULL);
+ map_output (&cl, NULL, NULL);
+
+ return cl != computer;
+}
+
+int
+map_switch_left (int *cc)
+{
+ int computer;
+ int console;
+ int ok;
+
+ for (computer = *cc - 1; computer > 0; computer--)
+ {
+
+/* First see if this computer is being displayed - if so easy*/
+
+ if (layout_computer_to_console (computer) > 0)
+ {
+ *cc = computer;
+ layout_status (*cc);
+ return 1;
+ }
+
+/* We're switching left so try console from the left to the right */
+ ok = 0;
+
+ for (console = 1; console <= N_CONSOLE; ++console)
+ {
+ if (layout_possible (console, computer))
+ {
+ layout_map (console, computer);
+ if (!ok)
+ *cc = computer;
+ computer++;
+ ok++;
+ }
+ }
+ if (ok)
+ {
+ layout_status (*cc);
+ return 1;
+ }
+ }
+
+
+ return 0;
+}
+
+int
+map_switch_right (int *cc)
+{
+ int computer;
+ int console;
+ int ok;
+
+
+ for (computer = *cc + 1; computer <= N_COMPUTER; computer++)
+ {
+
+/* First see if this computer is being displayed - if so easy*/
+
+ if (layout_computer_to_console (computer) > 0)
+ {
+ *cc = computer;
+ layout_status (*cc);
+ return 1;
+ }
+
+/* We're switching right so try console from the left to the right */
+ ok = 0;
+
+ for (console = N_CONSOLE; console > 0; --console)
+ {
+ if (layout_possible (console, computer))
+ {
+ layout_map (console, computer);
+ if (!ok)
+ *cc = computer;
+
+ computer--;
+ ok++;
+ }
+ }
+ if (ok)
+ {
+ layout_status (*cc);
+ return 1;
+ }
+ }
+
+
+ return 0;
+}
+
+int
+map_init (void)
+{
+ return layout_init ();
+}
diff --git a/output.c b/output.c
new file mode 100644
index 0000000..c12262c
--- /dev/null
+++ b/output.c
@@ -0,0 +1,441 @@
+#include "project.h"
+
+#include "output_map.h"
+
+output_dev_t *output_devs;
+
+static output_dev_t *
+iface_to_dev (int iface)
+{
+ output_dev_t *ret;
+ for (ret = output_devs; ret; ret = ret->next)
+ {
+ if (!(iface--))
+ return ret;
+ }
+ return NULL;
+}
+
+
+
+static int
+send_flush (output_dev_t * o)
+{
+ int ret;
+ uint8_t rbuf[36];
+ uint8_t xbuf[31] = {
+ 0x55, 0x53, 0x42, 0x43,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+ 0x00, 0x00
+ };
+ memcpy (&xbuf[4], &o->seq, 4);
+ o->seq++;
+
+/*Sends SCSI test unit ready*/
+
+ if (usb_bulk_write (o->devh, 0x2, (char *) xbuf, 31, 10) != 31)
+ return -1;
+ ret = usb_bulk_read (o->devh, 0x81, (char *) rbuf, 36, 10);
+ if (ret <= 0)
+ return -1;
+
+
+ return 0;
+}
+
+static int
+send_msg (output_dev_t * o, uint8_t * msg)
+{
+ int ret;
+ uint8_t xbuf[31] = {
+ 0x55, 0x53, 0x42, 0x43,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0xd9,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+ 0x4f, 0x54
+ };
+ uint8_t rbuf[36];
+
+ memcpy (&xbuf[16], msg, 13);
+ memcpy (&xbuf[4], &o->seq, 4);
+ o->seq++;
+
+/* READ CD-DA MSF !*/
+
+ if (usb_bulk_write (o->devh, 0x2, (char *) xbuf, 31, 10) != 31)
+ return -1;
+ ret = usb_bulk_read (o->devh, 0x81, (char *) rbuf, 36, 10);
+ if (ret <= 0)
+ return -1;
+
+
+ return 0;
+}
+
+static int
+mouse (output_dev_t * o, uint16_t x, uint16_t y, uint8_t s, int l,
+ int m, int r)
+{
+ uint8_t bmask = (l ? 1 : 0) | (m ? 4 : 0) | (r ? 2 : 0);
+ uint8_t msg[13] = { 0x33, bmask, s, x & 0xff,
+ x >> 8, y & 0xff, y >> 8, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ };
+
+// printf ("Mouse x=%4d y=%4d scroll=%2x bmask=%x\n", x, y, s, bmask);
+
+ return send_msg (o, msg);
+}
+
+static int
+send_key_list (output_dev_t * o, uint8_t modifiers)
+{
+ uint8_t msg[13] = { 0x34, modifiers, 0x00 };
+ memcpy (&msg[3], o->keys, OUTPUT_KEY_LIST_LEN);
+
+#if 0
+ int i;
+ printf ("Keybd modifiers mask=%x key list=", modifiers);
+
+ for (i = 0; i < OUTPUT_KEY_LIST_LEN; ++i)
+ {
+ if (o->keys[i])
+ printf ("%02x ", o->keys[i]);
+ }
+ printf ("\n");
+#endif
+
+ return send_msg (o, msg);
+}
+
+
+
+static int
+key_down (output_dev_t * o, uint8_t key, uint8_t modifiers)
+{
+ int i;
+
+//printf("Key %d down modifiers %x\n",key,modifiers);
+
+ if (key)
+ {
+ do
+ {
+ for (i = 0; i < sizeof (o->keys); ++i)
+ {
+ if (o->keys[i] == key)
+ break;
+ }
+
+ for (i = 0; i < sizeof (o->keys); ++i)
+ {
+ if (!o->keys[i])
+ {
+ o->keys[i] = key;
+ break;
+ }
+ }
+ }
+ while (0);
+ }
+
+ return send_key_list (o, modifiers);
+}
+
+
+static int
+key_up (output_dev_t * o, uint8_t key, uint8_t modifiers)
+{
+ int i;
+
+//printf("Key %d up modifiers %x\n",key,modifiers);
+
+ if (key)
+ {
+ for (i = 0; i < sizeof (o->keys); ++i)
+ {
+ if (o->keys[i] == key)
+ o->keys[i] = 0;
+ }
+ }
+
+ return send_key_list (o, modifiers);
+}
+
+
+
+
+
+struct map_ent *
+lookup_map_ent (int keycode, uint8_t modifiers)
+{
+ int i;
+
+ for (i = 0; i < MAP_LEN; ++i)
+ {
+ if (map[i].keycode == keycode)
+ {
+ if (map[i].hacks & (HACK_RCS | HACK_HS))
+ { /*Do we require a shift key to match ? */
+ if (modifiers & HACK_SHIFT_MASK)
+ return &map[i];
+ }
+ else
+ {
+ return &map[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+
+
+
+
+void
+send_keyboard_event (int computer, int k, int ud)
+{
+ static uint8_t modifiers;
+ uint8_t mods;
+ struct map_ent *e = lookup_map_ent (k, modifiers);
+ output_dev_t *o;
+
+ map_output (&computer, NULL, NULL);
+
+ o = iface_to_dev (computer);
+
+ if (!o)
+ return;
+
+ if (!e)
+ return;
+
+ if (e->hacks & HACK_MODIFIER_MASK)
+ {
+ if (ud)
+ {
+ modifiers |= e->hacks & HACK_MODIFIER_MASK;
+ }
+ else
+ {
+ modifiers &= ~(e->hacks & HACK_MODIFIER_MASK);
+ }
+ }
+
+ if (e->hacks & HACK_HS)
+ {
+ mods = modifiers & ~HACK_SHIFT_MASK;
+
+ if (ud)
+ {
+ if (modifiers & HACK_SHIFT_L)
+ key_up (o, 0xe1, mods);
+ if (modifiers & HACK_SHIFT_R)
+ key_up (o, 0xe5, mods);
+ }
+
+
+ }
+ else
+ {
+ mods = modifiers;
+ }
+
+#if 0
+ printf
+ ("Hacks %8x, modifiers=%4x, mods=%4x, e->keysym=%4x, e->keycode=%4x, e->code=%2x\n",
+ e->hacks, modifiers, mods, e->keysym, e->keycode, e->code);
+#endif
+
+ if (ud)
+ key_down (o, e->code, mods);
+ else
+ key_up (o, e->code, mods);
+
+ if (e->hacks & HACK_HS)
+ {
+ if (!ud)
+ {
+ if (modifiers & HACK_SHIFT_L)
+ key_down (o, 0xe1, modifiers);
+ if (modifiers & HACK_SHIFT_R)
+ key_down (o, 0xe5, modifiers);
+ }
+ }
+
+
+ send_flush (o);
+}
+
+
+
+void
+send_mouse_event (int computer, int x, int y, int s, int l, int m, int r)
+{
+ output_dev_t *o;
+
+
+ map_output (&computer, &x, &y);
+
+ o = iface_to_dev (computer);
+
+
+ if (!o)
+ return;
+
+ if (s < 0)
+ s += 256;
+
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ if (x > 2047)
+ x = 2047;
+ if (y > 2047)
+ y = 2047;
+
+ mouse (o, x, y, s, l, m, r);
+
+ if (s)
+ send_flush (o);
+}
+
+
+
+static output_dev_t *
+get_output_dev (struct usb_device *dev)
+{
+ struct usb_dev_handle *devh;
+
+ output_dev_t *o;
+
+
+ for (o = output_devs; o; o = o->next)
+ if (!strcmp (o->filename, dev->filename))
+ return o;
+
+
+ printf ("New output: %s\n", dev->filename);
+
+ devh = usb_open (dev);
+ if (!devh)
+ return NULL;
+
+ usb_reset (devh);
+ usb_close (devh);
+ usleep (100000);
+
+ devh = usb_open (dev);
+
+ if (!devh)
+ return NULL;
+
+
+
+ usb_detach_kernel_driver_np (devh, 0);
+ usb_detach_kernel_driver_np (devh, 1);
+ usb_detach_kernel_driver_np (devh, 2);
+ usb_claim_interface (devh, 0);
+
+
+ usb_clear_halt (devh, 0x81);
+ usb_clear_halt (devh, 0x2);
+
+ o = malloc (sizeof (*o));
+ bzero (o, sizeof (*o));
+
+ strcpy (o->filename, dev->filename);
+ o->devh = devh;
+
+ o->next = output_devs;
+
+ output_devs = o;
+
+ return o;
+}
+
+static void
+free_output_dev (output_dev_t * o)
+{
+ printf ("Lost output: %s\n", o->filename);
+ if (o->devh)
+ usb_close (o->devh);
+ free (o);
+}
+
+
+void
+scan_output_devs (int init)
+{
+ struct usb_bus *bus;
+ struct usb_device *dev;
+ output_dev_t *od, **odp;
+
+ usb_find_busses ();
+ if (!init && !usb_find_devices ())
+ return;
+
+ for (od = output_devs; od; od = od->next)
+ od->present = 0;
+
+ for (bus = usb_get_busses (); bus; bus = bus->next)
+ {
+ for (dev = bus->devices; dev; dev = dev->next)
+ {
+ if ((dev->descriptor.idVendor == 0x0ea0) &&
+ (dev->descriptor.idProduct == 0x2211))
+ {
+
+ od = get_output_dev (dev);
+ if (od)
+ od->present = 1;
+ }
+ }
+ }
+
+
+
+ for (odp = &output_devs; (od = *odp);)
+ {
+ if (!od->present)
+ {
+ *odp = od->next;
+ free_output_dev (od);
+ }
+ else
+ {
+ odp = &od->next;
+ }
+ }
+
+
+}
+
+void
+output_reset (void)
+{
+ output_dev_t *od, **odp;
+
+ for (odp = &output_devs; (od = *odp);)
+ {
+ *odp = od->next;
+ free_output_dev (od);
+ }
+
+ scan_output_devs (1);
+
+
+}
diff --git a/output_map.h b/output_map.h
new file mode 100644
index 0000000..978a17c
--- /dev/null
+++ b/output_map.h
@@ -0,0 +1,871 @@
+
+#define HACK_NONE 0UL /*Do nothing special */
+
+#define HACK_CTRL_L 1UL<<0
+#define HACK_SHIFT_L 1UL<<1
+#define HACK_ALT_L 1UL<<2
+#define HACK_SUPER_L 1UL<<3
+
+#define HACK_CTRL_R 1UL<<4
+#define HACK_SHIFT_R 1UL<<5
+#define HACK_ALT_R 1UL<<6
+#define HACK_SUPER_R 1UL<<7
+
+#define HACK_SHIFT_MASK 0x22
+#define HACK_MODIFIER_MASK 0xff
+
+#define HACK_RCS 1UL<<16 /*Require a shift key to be pressed and pass it through */
+#define HACK_HS 1UL<<17 /*Require and then hide a shift key */
+#define HACK_ILS 1UL<<18 /*Insert left shift */
+
+
+struct map_ent
+{
+ uint32_t hacks;
+ uint8_t code;
+ uint32_t keycode;
+};
+
+
+static struct map_ent map[] = {
+/* Crazy parenthesis*/
+ {
+ HACK_RCS, 0x26, KEY_9}, /* parenleft */
+ {
+ HACK_RCS, 0x27, KEY_0}, /* parenright */
+
+#ifdef APPLE_KEYBOARD
+ {
+ HACK_NONE, 0x29, KEY_102ND },
+ {
+ HACK_NONE, 0x65, KEY_ESC},
+ {
+ HACK_NONE, 0x48, KEY_F19},
+ {
+ HACK_NONE, 0x64, KEY_GRAVE},
+#endif
+
+#if 0
+#if 0
+/* UK - US misery for windows UK map*/
+ {
+ HACK_RCS, 0x34, 0x32}, /* shift 2 ->shift ' */
+ {
+ HACK_RCS, 0x1f, 0x27}, /* shift ' -> shift 2 */
+ {
+ HACK_RCS, 0x31, 0x60}, /* shift ` -> shift # */
+ {
+ HACK_HS, 0x31, 0x33}, /* shift 3 -> # */
+ {
+ HACK_NONE, 0x64, 0x5c}, /* backslash -> backslash */
+#endif
+#if 1
+/*misery for james' gbus keymap */
+ {
+ HACK_CTRL_L, 0xE0, 0xffe5}, /* Caps_Lock */
+ {
+ HACK_NONE, 0x39, 0xffe3}, /* Control_L */
+ {
+ HACK_NONE, 0x31, 0x60}, /* ` -> ` */
+ {
+ HACK_NONE, 0x64, 0x5c}, /* backslash -> backslash */
+#endif
+#endif
+
+/*Modifier keys*/
+ {
+ HACK_CTRL_L, 0xE0, KEY_LEFTCTRL}, /* Control_L */
+ {
+ HACK_SHIFT_L, 0xE1, KEY_LEFTSHIFT}, /* Shift_L */
+ {
+ HACK_ALT_L, 0xE2, KEY_LEFTALT}, /* Alt_L */
+ {
+ HACK_SUPER_L, 0xE3, KEY_LEFTMETA}, /* Super_L */
+ {
+ HACK_CTRL_R, 0xE4, KEY_RIGHTCTRL}, /* Control_R */
+ {
+ HACK_SHIFT_R, 0xE5, KEY_RIGHTSHIFT}, /* Shift_R */
+ {
+ HACK_ALT_R, 0xE6, KEY_RIGHTALT}, /* Alt_R */
+ {
+ HACK_SUPER_R, 0xE7, KEY_RIGHTMETA}, /* Super_R */
+/* normal service below here */
+ {
+ HACK_NONE, 0x04, KEY_A}, /* a */
+ {
+ HACK_NONE, 0x05, KEY_B}, /* b */
+ {
+ HACK_NONE, 0x06, KEY_C}, /* c */
+ {
+ HACK_NONE, 0x07, KEY_D}, /* d */
+ {
+ HACK_NONE, 0x08, KEY_E}, /* e */
+ {
+ HACK_NONE, 0x09, KEY_F}, /* f */
+ {
+ HACK_NONE, 0x0a, KEY_G}, /* g */
+ {
+ HACK_NONE, 0x0b, KEY_H}, /* h */
+ {
+ HACK_NONE, 0x0c, KEY_I}, /* i */
+ {
+ HACK_NONE, 0x0d, KEY_J}, /* j */
+ {
+ HACK_NONE, 0x0e, KEY_K}, /* k */
+ {
+ HACK_NONE, 0x0f, KEY_L}, /* l */
+ {
+ HACK_NONE, 0x10, KEY_M}, /* m */
+ {
+ HACK_NONE, 0x11, KEY_N}, /* n */
+ {
+ HACK_NONE, 0x12, KEY_O}, /* o */
+ {
+ HACK_NONE, 0x13, KEY_P}, /* p */
+ {
+ HACK_NONE, 0x14, KEY_Q}, /* q */
+ {
+ HACK_NONE, 0x15, KEY_R}, /* r */
+ {
+ HACK_NONE, 0x16, KEY_S}, /* s */
+ {
+ HACK_NONE, 0x17, KEY_T}, /* t */
+ {
+ HACK_NONE, 0x18, KEY_U}, /* u */
+ {
+ HACK_NONE, 0x19, KEY_V}, /* v */
+ {
+ HACK_NONE, 0x1a, KEY_W}, /* w */
+ {
+ HACK_NONE, 0x1b, KEY_X}, /* x */
+ {
+ HACK_NONE, 0x1c, KEY_Y}, /* y */
+ {
+ HACK_NONE, 0x1d, KEY_Z}, /* z */
+ {
+ HACK_NONE, 0x1e, KEY_1}, /* 1 */
+ {
+ HACK_NONE, 0x1f, KEY_2}, /* 2 */
+ {
+ HACK_NONE, 0x20, KEY_3}, /* 3 */
+ {
+ HACK_NONE, 0x21, KEY_4}, /* 4 */
+ {
+ HACK_NONE, 0x22, KEY_5}, /* 5 */
+ {
+ HACK_NONE, 0x23, KEY_6}, /* 6 */
+ {
+ HACK_NONE, 0x24, KEY_7}, /* 7 */
+ {
+ HACK_NONE, 0x25, KEY_8}, /* 8 */
+ {
+ HACK_NONE, 0x26, KEY_9}, /* 9 */
+ {
+ HACK_NONE, 0x27, KEY_0}, /* 0 */
+ {
+ HACK_NONE, 0x28, KEY_ENTER}, /* Return */
+ {
+ HACK_NONE, 0x29, KEY_ESC}, /* Escape */
+ {
+ HACK_NONE, 0x2a, KEY_BACKSPACE}, /* BackSpace */
+ {
+ HACK_NONE, 0x2b, KEY_TAB}, /* Tab */
+ {
+ HACK_NONE, 0x2c, KEY_SPACE}, /* space */
+ {
+ HACK_NONE, 0x2d, KEY_MINUS}, /* minus */
+ {
+ HACK_NONE, 0x2e, KEY_EQUAL}, /* equal */
+ {
+ HACK_NONE, 0x2f, KEY_LEFTBRACE}, /* bracketleft */
+ {
+ HACK_NONE, 0x30, KEY_RIGHTBRACE}, /* bracketright */
+ {
+ HACK_NONE, 0x31, KEY_BACKSLASH}, /* backslash */
+ {
+ HACK_NONE, 0x32, KEY_BACKSLASH}, /* backslash */
+ {
+ HACK_NONE, 0x33, KEY_SEMICOLON}, /* semicolon */
+ {
+ HACK_NONE, 0x34, KEY_APOSTROPHE}, /* apostrophe */
+ {
+ HACK_NONE, 0x35, KEY_GRAVE}, /* grave */
+ {
+ HACK_NONE, 0x36, KEY_COMMA}, /* comma */
+ {
+ HACK_NONE, 0x37, KEY_DOT}, /* period */
+ {
+ HACK_NONE, 0x38, KEY_SLASH}, /* slash */
+ {
+ HACK_NONE, 0x39, KEY_CAPSLOCK}, /* Caps_Lock */
+ {
+ HACK_NONE, 0x3A, KEY_F1}, /* F1 */
+ {
+ HACK_NONE, 0x3B, KEY_F2}, /* F2 */
+ {
+ HACK_NONE, 0x3C, KEY_F3}, /* F3 */
+ {
+ HACK_NONE, 0x3D, KEY_F4}, /* F4 */
+ {
+ HACK_NONE, 0x3E, KEY_F5}, /* F5 */
+ {
+ HACK_NONE, 0x3F, KEY_F6}, /* F6 */
+ {
+ HACK_NONE, 0x40, KEY_F7}, /* F7 */
+ {
+ HACK_NONE, 0x41, KEY_F8}, /* F8 */
+ {
+ HACK_NONE, 0x42, KEY_F9}, /* F9 */
+ {
+ HACK_NONE, 0x43, KEY_F10}, /* F10 */
+ {
+ HACK_NONE, 0x44, KEY_F11}, /* F11 */
+ {
+ HACK_NONE, 0x45, KEY_F12}, /* F12 */
+ {
+ HACK_NONE, 0x46, KEY_SYSRQ}, /* Print */
+ {
+ HACK_NONE, 0x47, KEY_SCROLLLOCK}, /* Scroll_Lock */
+ {
+ HACK_NONE, 0x48, KEY_PAUSE}, /* Pause */
+ {
+ HACK_NONE, 0x49, KEY_INSERT}, /* Insert */
+ {
+ HACK_NONE, 0x4A, KEY_HOME}, /* Home */
+ {
+ HACK_NONE, 0x4B, KEY_PAGEUP}, /* Prior */
+ {
+ HACK_NONE, 0x4C, KEY_DELETE}, /* Delete */
+ {
+ HACK_NONE, 0x4D, KEY_END}, /* End */
+ {
+ HACK_NONE, 0x4E, KEY_PAGEDOWN}, /* Next */
+ {
+ HACK_NONE, 0x4F, KEY_RIGHT}, /* Right */
+ {
+ HACK_NONE, 0x50, KEY_LEFT}, /* Left */
+ {
+ HACK_NONE, 0x51, KEY_DOWN}, /* Down */
+ {
+ HACK_NONE, 0x52, KEY_UP}, /* Up */
+ {
+ HACK_NONE, 0x53, KEY_NUMLOCK}, /* Num_Lock */
+ {
+ HACK_NONE, 0x54, KEY_KPSLASH}, /* KP_Divide */
+ {
+ HACK_NONE, 0x55, KEY_KPASTERISK}, /* KP_Multiply */
+ {
+ HACK_NONE, 0x56, KEY_KPMINUS}, /* KP_Subtract */
+ {
+ HACK_NONE, 0x57, KEY_KPPLUS}, /* KP_Add */
+ {
+ HACK_NONE, 0x58, KEY_KPENTER}, /* KP_Enter */
+ {
+ HACK_NONE, 0x59, KEY_KP1}, /* KP_1 */
+ {
+ HACK_NONE, 0x5A, KEY_KP2}, /* KP_2 */
+ {
+ HACK_NONE, 0x5B, KEY_KP3}, /* KP_3 */
+ {
+ HACK_NONE, 0x5C, KEY_KP4}, /* KP_4 */
+ {
+ HACK_NONE, 0x5D, KEY_KP5}, /* KP_5 */
+ {
+ HACK_NONE, 0x5E, KEY_KP6}, /* KP_6 */
+ {
+ HACK_NONE, 0x5F, KEY_KP7}, /* KP_7 */
+ {
+ HACK_NONE, 0x60, KEY_KP8}, /* KP_8 */
+ {
+ HACK_NONE, 0x61, KEY_KP9}, /* KP_9 */
+ {
+ HACK_NONE, 0x62, KEY_KP0}, /* KP_0 */
+ {
+ HACK_NONE, 0x63, KEY_KPDOT}, /* KP_Decimal */
+ {
+ HACK_NONE, 0x64, KEY_102ND}, /* less */
+ {
+ HACK_NONE, 0x65, KEY_COMPOSE}, /* Menu */
+ {
+ HACK_NONE, 0x65, KEY_MENU}, /* Menu */
+ {
+ HACK_NONE, 0x66, KEY_POWER}, /* XF86PowerOff */
+ {
+ HACK_NONE, 0x67, KEY_KPEQUAL}, /* KP_Equal */
+ {
+ HACK_NONE, 0x68, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x69, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x6A, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x6B, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x6C, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x6D, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x6E, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x6F, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x70, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x71, 0x0}, /* TouchpadToggle */
+ {
+ HACK_NONE, 0x72, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x73, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x74, KEY_OPEN}, /* SunOpen */
+ {
+ HACK_NONE, 0x75, KEY_HELP}, /* Help */
+ {
+ HACK_NONE, 0x76, KEY_PROPS}, /* SunProps */
+ {
+ HACK_NONE, 0x77, KEY_FRONT}, /* SunFront */
+ {
+ HACK_NONE, 0x78, KEY_STOP}, /* Cancel */
+ {
+ HACK_NONE, 0x79, KEY_AGAIN}, /* Again */
+ {
+ HACK_NONE, 0x7A, KEY_UNDO}, /* Undo */
+ {
+ HACK_NONE, 0x7B, KEY_CUT}, /* Cut */
+ {
+ HACK_NONE, 0x7C, KEY_COPY}, /* Copy */
+ {
+ HACK_NONE, 0x7D, KEY_PASTE}, /* Paste */
+ {
+ HACK_NONE, 0x7E, KEY_FIND}, /* Find */
+ {
+ HACK_NONE, 0x7F, KEY_MUTE}, /* Mute */
+ {
+ HACK_NONE, 0x80, KEY_VOLUMEDOWN}, /* RaiseVolume */
+ {
+ HACK_NONE, 0x81, KEY_VOLUMEUP}, /* LowerVolume */
+ {
+ HACK_NONE, 0x82, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x83, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x84, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x85, KEY_KPDOT}, /* KP_Decimal */
+ {
+ HACK_NONE, 0x86, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x87, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x88, KEY_KATAKANAHIRAGANA}, /* Hiragana_Katakana */
+ {
+ HACK_NONE, 0x89, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x8A, KEY_HENKAN}, /* Henkan_Mode */
+ {
+ HACK_NONE, 0x8B, KEY_MUHENKAN}, /* Muhenkan */
+ {
+ HACK_NONE, 0x8C, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x8D, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x8E, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x8F, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x90, KEY_HANGEUL}, /* Hangul */
+ {
+ HACK_NONE, 0x91, KEY_HANJA}, /* Hangul_Hanja */
+ {
+ HACK_NONE, 0x92, KEY_KATAKANA}, /* Katakana */
+ {
+ HACK_NONE, 0x93, KEY_HIRAGANA}, /* Hiragana */
+ {
+ HACK_NONE, 0x94, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x95, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x96, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x97, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x98, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x99, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x9A, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x9B, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x9C, KEY_DELETE}, /* Delete */
+ {
+ HACK_NONE, 0x9D, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x9E, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0x9F, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA0, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA1, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA2, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA3, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA4, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA5, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA6, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA7, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA8, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xA9, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xAA, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xAB, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xAC, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xAD, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xAE, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xAF, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xB0, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xB1, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xB2, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xB3, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xB4, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xB5, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xB6, KEY_9}, /* parenleft */
+ {
+ HACK_NONE, 0xB7, KEY_0}, /* parenright */
+ {
+ HACK_NONE, 0xB8, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xB9, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xBA, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xBB, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xBC, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xBD, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xBE, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xBF, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC0, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC1, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC2, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC3, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC4, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC5, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC6, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC7, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC8, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xC9, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xCA, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xCB, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xCC, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xCD, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xCE, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xCF, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xD0, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xD1, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xD2, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xD3, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xD4, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xD5, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xD6, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xD7, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xD8, KEY_DELETE}, /* Delete */
+ {
+ HACK_NONE, 0xD9, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xDA, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xDB, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xDC, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xDD, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xDE, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xDF, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xE0, KEY_LEFTCTRL}, /* Control_L */
+ {
+ HACK_NONE, 0xE1, KEY_LEFTSHIFT}, /* Shift_L */
+ {
+ HACK_NONE, 0xE2, KEY_LEFTALT}, /* Alt_L */
+ {
+ HACK_NONE, 0xE3, KEY_LEFTMETA}, /* Super_L */
+ {
+ HACK_NONE, 0xE4, KEY_RIGHTCTRL}, /* Control_R */
+ {
+ HACK_NONE, 0xE5, KEY_RIGHTSHIFT}, /* Shift_R */
+ {
+ HACK_NONE, 0xE6, KEY_RIGHTALT}, /* Alt_R */
+ {
+ HACK_NONE, 0xE7, KEY_RIGHTMETA}, /* Super_R */
+ {
+ HACK_NONE, 0xE8, KEY_PLAYPAUSE}, /* Play */
+ {
+ HACK_NONE, 0xE9, KEY_STOPCD}, /* Stop */
+ {
+ HACK_NONE, 0xEA, KEY_PREVIOUSSONG}, /* |< */
+ {
+ HACK_NONE, 0xEB, KEY_NEXTSONG}, /* >| */
+ {
+ HACK_NONE, 0xEC, KEY_EJECTCD}, /* XF86Eject */
+ {
+ HACK_NONE, 0xED, KEY_VOLUMEUP}, /* RaiseVolume */
+ {
+ HACK_NONE, 0xEE, KEY_VOLUMEDOWN}, /* LowerVolume */
+ {
+ HACK_NONE, 0xEF, KEY_MUTE}, /* Mute */
+ {
+ HACK_NONE, 0xF0, KEY_WWW}, /* WWW */
+ {
+ HACK_NONE, 0xF1, KEY_BACK}, /* Back */
+ {
+ HACK_NONE, 0xF2, KEY_FORWARD}, /* Forward */
+ {
+ HACK_NONE, 0xF3, KEY_CANCEL}, /* Cancel */
+ {
+ HACK_NONE, 0xF4, KEY_FIND}, /* Find */
+ {
+ HACK_NONE, 0xF5, KEY_SCROLLUP}, /* ScrollUp */
+ {
+ HACK_NONE, 0xF6, KEY_SCROLLDOWN}, /* ScrollDown */
+ {
+ HACK_NONE, 0xF7, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xF8, KEY_SLEEP}, /* Sleep */
+ {
+ HACK_NONE, 0xF9, KEY_COFFEE}, /* ScreenSaver */
+ {
+ HACK_NONE, 0xFA, KEY_REFRESH}, /* Reload */
+ {
+ HACK_NONE, 0xFB, KEY_CALC}, /* Calculator */
+ {
+ HACK_NONE, 0xFC, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xFD, 0x0}, /* NoSymbol */
+ {
+ HACK_NONE, 0xFE, 0x0}, /* NoSymbol */
+};
+
+#define MAP_LEN (sizeof(map)/sizeof(struct map_ent))
+
+
+#if 0
+#define MAP_LEN 256
+static int kc_map[MAP_LEN];
+static KeySym kc_map[MAP_LEN] = {
+ [0x04] = 0x61, /* a */
+ [0x05] = 0x62, /* b */
+ [0x06] = 0x63, /* c */
+ [0x07] = 0x64, /* d */
+ [0x08] = 0x65, /* e */
+ [0x09] = 0x66, /* f */
+ [0x0a] = 0x67, /* g */
+ [0x0b] = 0x68, /* h */
+ [0x0c] = 0x69, /* i */
+ [0x0d] = 0x6a, /* j */
+ [0x0e] = 0x6b, /* k */
+ [0x0f] = 0x6c, /* l */
+ [0x10] = 0x6d, /* m */
+ [0x11] = 0x6e, /* n */
+ [0x12] = 0x6f, /* o */
+ [0x13] = 0x70, /* p */
+ [0x14] = 0x71, /* q */
+ [0x15] = 0x72, /* r */
+ [0x16] = 0x73, /* s */
+ [0x17] = 0x74, /* t */
+ [0x18] = 0x75, /* u */
+ [0x19] = 0x76, /* v */
+ [0x1a] = 0x77, /* w */
+ [0x1b] = 0x78, /* x */
+ [0x1c] = 0x79, /* y */
+ [0x1d] = 0x7a, /* z */
+ [0x1e] = 0x31, /* 1 */
+ [0x1f] = 0x32, /* 2 */
+ [0x20] = 0x33, /* 3 */
+ [0x21] = 0x34, /* 4 */
+ [0x22] = 0x35, /* 5 */
+ [0x23] = 0x36, /* 6 */
+ [0x24] = 0x37, /* 7 */
+ [0x25] = 0x38, /* 8 */
+ [0x26] = 0x39, /* 9 */
+ [0x27] = 0x30, /* 0 */
+ [0x28] = 0xff0d, /* Return */
+ [0x29] = 0xff1b, /* Escape */
+ [0x2a] = 0xff08, /* BackSpace */
+ [0x2b] = 0xff09, /* Tab */
+ [0x2c] = 0x20, /* space */
+ [0x2d] = 0x2d, /* minus */
+ [0x2e] = 0x3d, /* equal */
+ [0x2f] = 0x5b, /* bracketleft */
+ [0x30] = 0x5d, /* bracketright */
+ [0x31] = 0x5c, /* backslash */
+ [0x32] = 0x5c, /* backslash */
+ [0x33] = 0x3b, /* semicolon */
+ [0x34] = 0x27, /* apostrophe */
+ [0x35] = 0x60, /* grave */
+ [0x36] = 0x2c, /* comma */
+ [0x37] = 0x2e, /* period */
+ [0x38] = 0x2f, /* slash */
+ [0x39] = 0xffe5, /* Caps_Lock */
+ [0x3A] = 0xffbe, /* F1 */
+ [0x3B] = 0xffbf, /* F2 */
+ [0x3C] = 0xffc0, /* F3 */
+ [0x3D] = 0xffc1, /* F4 */
+ [0x3E] = 0xffc2, /* F5 */
+ [0x3F] = 0xffc3, /* F6 */
+ [0x40] = 0xffc4, /* F7 */
+ [0x41] = 0xffc5, /* F8 */
+ [0x42] = 0xffc6, /* F9 */
+ [0x43] = 0xffc7, /* F10 */
+ [0x44] = 0xffc8, /* F11 */
+ [0x45] = 0xffc9, /* F12 */
+ [0x46] = 0xff61, /* Print */
+ [0x47] = 0xff14, /* Scroll_Lock */
+ [0x48] = 0xff13, /* Pause */
+ [0x49] = 0xff63, /* Insert */
+ [0x4A] = 0xff50, /* Home */
+ [0x4B] = 0xff55, /* Prior */
+ [0x4C] = 0xffff, /* Delete */
+ [0x4D] = 0xff57, /* End */
+ [0x4E] = 0xff56, /* Next */
+ [0x4F] = 0xff53, /* Right */
+ [0x50] = 0xff51, /* Left */
+ [0x51] = 0xff54, /* Down */
+ [0x52] = 0xff52, /* Up */
+ [0x53] = 0xff7f, /* Num_Lock */
+ [0x54] = 0xffaf, /* KP_Divide */
+ [0x55] = 0xffaa, /* KP_Multiply */
+ [0x56] = 0xffad, /* KP_Subtract */
+ [0x57] = 0xffab, /* KP_Add */
+ [0x58] = 0xff8d, /* KP_Enter */
+ [0x59] = 0xffb1, /* KP_1 */
+ [0x5A] = 0xffb2, /* KP_2 */
+ [0x5B] = 0xffb3, /* KP_3 */
+ [0x5C] = 0xffb4, /* KP_4 */
+ [0x5D] = 0xffb5, /* KP_5 */
+ [0x5E] = 0xffb6, /* KP_6 */
+ [0x5F] = 0xffb7, /* KP_7 */
+ [0x60] = 0xffb8, /* KP_8 */
+ [0x61] = 0xffb9, /* KP_9 */
+ [0x62] = 0xffb0, /* KP_0 */
+ [0x63] = 0xffae, /* KP_Decimal */
+ [0x64] = 0x3c, /* less */
+ [0x65] = 0xff67, /* Menu */
+ [0x66] = 0x1008ff2a, /* XF86PowerOff */
+ [0x67] = 0xffbd, /* KP_Equal */
+ [0x68] = 0x0, /* NoSymbol */
+ [0x69] = 0x0, /* NoSymbol */
+ [0x6A] = 0x0, /* NoSymbol */
+ [0x6B] = 0x0, /* NoSymbol */
+ [0x6C] = 0x0, /* NoSymbol */
+ [0x6D] = 0x0, /* NoSymbol */
+ [0x6E] = 0x0, /* NoSymbol */
+ [0x6F] = 0x0, /* NoSymbol */
+ [0x70] = 0x0, /* NoSymbol */
+ [0x71] = 0x1008ffa9, /* XF86TouchpadToggle */
+ [0x72] = 0x0, /* NoSymbol */
+ [0x73] = 0x0, /* NoSymbol */
+ [0x74] = 0x1005ff73, /* SunOpen */
+ [0x75] = 0xff6a, /* Help */
+ [0x76] = 0x1005ff70, /* SunProps */
+ [0x77] = 0x1005ff71, /* SunFront */
+ [0x78] = 0xff69, /* Cancel */
+ [0x79] = 0xff66, /* Redo */
+ [0x7A] = 0xff65, /* Undo */
+ [0x7B] = 0x1008ff58, /* XF86Cut */
+ [0x7C] = 0x1008ff57, /* XF86Copy */
+ [0x7D] = 0x1008ff6d, /* XF86Paste */
+ [0x7E] = 0xff68, /* Find */
+ [0x7F] = 0x1008ff12, /* XF86AudioMute */
+ [0x80] = 0x1008ff13, /* XF86AudioRaiseVolume */
+ [0x81] = 0x1008ff11, /* XF86AudioLowerVolume */
+ [0x82] = 0x0, /* NoSymbol */
+ [0x83] = 0x0, /* NoSymbol */
+ [0x84] = 0x0, /* NoSymbol */
+ [0x85] = 0xffae, /* KP_Decimal */
+ [0x86] = 0x0, /* NoSymbol */
+ [0x87] = 0x0, /* NoSymbol */
+ [0x88] = 0xff27, /* Hiragana_Katakana */
+ [0x89] = 0x0, /* NoSymbol */
+ [0x8A] = 0xff23, /* Henkan_Mode */
+ [0x8B] = 0xff22, /* Muhenkan */
+ [0x8C] = 0x0, /* NoSymbol */
+ [0x8D] = 0x0, /* NoSymbol */
+ [0x8E] = 0x0, /* NoSymbol */
+ [0x8F] = 0x0, /* NoSymbol */
+ [0x90] = 0xff31, /* Hangul */
+ [0x91] = 0xff34, /* Hangul_Hanja */
+ [0x92] = 0xff26, /* Katakana */
+ [0x93] = 0xff25, /* Hiragana */
+ [0x94] = 0x0, /* NoSymbol */
+ [0x95] = 0x0, /* NoSymbol */
+ [0x96] = 0x0, /* NoSymbol */
+ [0x97] = 0x0, /* NoSymbol */
+ [0x98] = 0x0, /* NoSymbol */
+ [0x99] = 0x0, /* NoSymbol */
+ [0x9A] = 0x0, /* NoSymbol */
+ [0x9B] = 0x0, /* NoSymbol */
+ [0x9C] = 0xffff, /* Delete */
+ [0x9D] = 0x0, /* NoSymbol */
+ [0x9E] = 0x0, /* NoSymbol */
+ [0x9F] = 0x0, /* NoSymbol */
+ [0xA0] = 0x0, /* NoSymbol */
+ [0xA1] = 0x0, /* NoSymbol */
+ [0xA2] = 0x0, /* NoSymbol */
+ [0xA3] = 0x0, /* NoSymbol */
+ [0xA4] = 0x0, /* NoSymbol */
+ [0xA5] = 0x0, /* NoSymbol */
+ [0xA6] = 0x0, /* NoSymbol */
+ [0xA7] = 0x0, /* NoSymbol */
+ [0xA8] = 0x0, /* NoSymbol */
+ [0xA9] = 0x0, /* NoSymbol */
+ [0xAA] = 0x0, /* NoSymbol */
+ [0xAB] = 0x0, /* NoSymbol */
+ [0xAC] = 0x0, /* NoSymbol */
+ [0xAD] = 0x0, /* NoSymbol */
+ [0xAE] = 0x0, /* NoSymbol */
+ [0xAF] = 0x0, /* NoSymbol */
+ [0xB0] = 0x0, /* NoSymbol */
+ [0xB1] = 0x0, /* NoSymbol */
+ [0xB2] = 0x0, /* NoSymbol */
+ [0xB3] = 0x0, /* NoSymbol */
+ [0xB4] = 0x0, /* NoSymbol */
+ [0xB5] = 0x0, /* NoSymbol */
+ [0xB6] = 0x28, /* parenleft */
+ [0xB7] = 0x29, /* parenright */
+ [0xB8] = 0x0, /* NoSymbol */
+ [0xB9] = 0x0, /* NoSymbol */
+ [0xBA] = 0x0, /* NoSymbol */
+ [0xBB] = 0x0, /* NoSymbol */
+ [0xBC] = 0x0, /* NoSymbol */
+ [0xBD] = 0x0, /* NoSymbol */
+ [0xBE] = 0x0, /* NoSymbol */
+ [0xBF] = 0x0, /* NoSymbol */
+ [0xC0] = 0x0, /* NoSymbol */
+ [0xC1] = 0x0, /* NoSymbol */
+ [0xC2] = 0x0, /* NoSymbol */
+ [0xC3] = 0x0, /* NoSymbol */
+ [0xC4] = 0x0, /* NoSymbol */
+ [0xC5] = 0x0, /* NoSymbol */
+ [0xC6] = 0x0, /* NoSymbol */
+ [0xC7] = 0x0, /* NoSymbol */
+ [0xC8] = 0x0, /* NoSymbol */
+ [0xC9] = 0x0, /* NoSymbol */
+ [0xCA] = 0x0, /* NoSymbol */
+ [0xCB] = 0x0, /* NoSymbol */
+ [0xCC] = 0x0, /* NoSymbol */
+ [0xCD] = 0x0, /* NoSymbol */
+ [0xCE] = 0x0, /* NoSymbol */
+ [0xCF] = 0x0, /* NoSymbol */
+ [0xD0] = 0x0, /* NoSymbol */
+ [0xD1] = 0x0, /* NoSymbol */
+ [0xD2] = 0x0, /* NoSymbol */
+ [0xD3] = 0x0, /* NoSymbol */
+ [0xD4] = 0x0, /* NoSymbol */
+ [0xD5] = 0x0, /* NoSymbol */
+ [0xD6] = 0x0, /* NoSymbol */
+ [0xD7] = 0x0, /* NoSymbol */
+ [0xD8] = 0xffff, /* Delete */
+ [0xD9] = 0x0, /* NoSymbol */
+ [0xDA] = 0x0, /* NoSymbol */
+ [0xDB] = 0x0, /* NoSymbol */
+ [0xDC] = 0x0, /* NoSymbol */
+ [0xDD] = 0x0, /* NoSymbol */
+ [0xDE] = 0x0, /* NoSymbol */
+ [0xDF] = 0x0, /* NoSymbol */
+ [0xE0] = 0xffe3, /* Control_L */
+ [0xE1] = 0xffe1, /* Shift_L */
+ [0xE2] = 0xffe9, /* Alt_L */
+ [0xE3] = 0xffeb, /* Super_L */
+ [0xE4] = 0xffe4, /* Control_R */
+ [0xE5] = 0xffe2, /* Shift_R */
+ [0xE6] = 0xffea, /* Alt_R */
+ [0xE7] = 0xffec, /* Super_R */
+ [0xE8] = 0x1008ff14, /* XF86AudioPlay */
+ [0xE9] = 0x1008ff15, /* XF86AudioStop */
+ [0xEA] = 0x1008ff16, /* XF86AudioPrev */
+ [0xEB] = 0x1008ff17, /* XF86AudioNext */
+ [0xEC] = 0x1008ff2c, /* XF86Eject */
+ [0xED] = 0x1008ff13, /* XF86AudioRaiseVolume */
+ [0xEE] = 0x1008ff11, /* XF86AudioLowerVolume */
+ [0xEF] = 0x1008ff12, /* XF86AudioMute */
+ [0xF0] = 0x1008ff2e, /* XF86WWW */
+ [0xF1] = 0x1008ff26, /* XF86Back */
+ [0xF2] = 0x1008ff27, /* XF86Forward */
+ [0xF3] = 0xff69, /* Cancel */
+ [0xF4] = 0xff68, /* Find */
+ [0xF5] = 0x1008ff78, /* XF86ScrollUp */
+ [0xF6] = 0x1008ff79, /* XF86ScrollDown */
+ [0xF7] = 0x0, /* NoSymbol */
+ [0xF8] = 0x1008ff2f, /* XF86Sleep */
+ [0xF9] = 0x1008ff2d, /* XF86ScreenSaver */
+ [0xFA] = 0x1008ff73, /* XF86Reload */
+ [0xFB] = 0x1008ff1d, /* XF86Calculator */
+ [0xFC] = 0x0, /* NoSymbol */
+ [0xFD] = 0x0, /* NoSymbol */
+ [0xFE] = 0x0, /* NoSymbol */
+};
+
+
+static uint8_t
+keycode_to_usb (int k)
+{
+ int i;
+ for (i = 0; i < MAP_LEN; ++i)
+ {
+ if (kc_map[i] == k)
+ return i;
+ }
+ return 0;
+}
+#endif
diff --git a/project.h b/project.h
new file mode 100644
index 0000000..eba3de8
--- /dev/null
+++ b/project.h
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <linux/input.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <malloc.h>
+#include <usb.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#ifdef BROMIUM
+#define APPLE_KEYBOARD
+#define N_COMPUTER 4
+#define N_CONSOLE 1
+#define MAP_NULL
+#define LAYOUT_NULL
+#endif
+
+#ifdef HOME
+#define N_COMPUTER 7
+#define N_CONSOLE 3
+#define MAP_HOME
+#define LAYOUT_HOME
+#endif
+
+typedef struct MM_struct MM;
+
+typedef struct input_dev
+{
+ struct input_dev *next;
+ int id; /* /dev/input/event%d */
+ int present; /* !0 if the device file exists */
+ int fd; /* fd if the device is open, -1 otherwise */
+ int blacklistid; /* !0 if the device is a km link */
+} input_dev_t;
+
+#define OUTPUT_KEY_LIST_LEN 10
+
+typedef struct output_dev
+{
+ struct output_dev *next;
+
+ char filename[PATH_MAX + 1];
+ int present;
+
+ struct usb_dev_handle *devh;
+ uint32_t seq;
+
+ uint8_t keys[OUTPUT_KEY_LIST_LEN];
+
+} output_dev_t;
+
+
+
+#include "prototypes.h"
diff --git a/prototypes.h b/prototypes.h
new file mode 100644
index 0000000..695315d
--- /dev/null
+++ b/prototypes.h
@@ -0,0 +1,52 @@
+/* kmd.c */
+extern int main(int argc, char *argv[]);
+/* status.c */
+extern void status_draw_computer(int computer, int locked, int console, int active, int force);
+extern void status_draw_console(int console, int locked, int computer, int active, int force);
+extern void status_init(void);
+extern void status_reset(void);
+/* lcd.c */
+extern void lcd_on(void);
+extern void lcd_off(void);
+extern void lcd_close(void);
+extern void lcd_vline(int x, int y1, int y2, int r, int g, int b);
+extern void lcd_hline(int y, int x1, int x2, int r, int g, int b);
+extern void lcd_box(int x1, int y1, int x2, int y2, int r, int g, int b);
+extern void lcd_ss(int v, int x1, int y1, int w, int h);
+extern int lcd_open(void);
+/* input.c */
+extern input_dev_t *input_devs;
+extern void scan_input_devs(void);
+/* dispatch.c */
+extern void dispatch_key(int key, int ud);
+extern void dispatch_mouse_button(int button, int ud);
+extern void dispatch_mouse_wheel(int d);
+extern void dispatch_mouse_motion(int rx, int ry);
+extern void dispatch_event(struct input_event *ev);
+extern void dispatch_init(void);
+/* output.c */
+extern output_dev_t *output_devs;
+extern struct map_ent *lookup_map_ent(int keycode, uint8_t modifiers);
+extern void send_keyboard_event(int computer, int k, int ud);
+extern void send_mouse_event(int computer, int x, int y, int s, int l, int m, int r);
+extern void scan_output_devs(int init);
+extern void output_reset(void);
+/* map.c */
+extern void map_output(int *computer, int *x, int *y);
+extern int map_grace_left(int computer);
+extern int map_grace_right(int computer);
+extern int map_switch_left(int *cc);
+extern int map_switch_right(int *cc);
+extern int map_init(void);
+/* layout.c */
+extern int layout_computer_to_console(int computer);
+extern int layout_console_to_computer(int console);
+extern int layout_possible(int console, int computer);
+extern void layout_map(int console, int computer);
+extern void layout_status(int active_computer);
+extern void layout_toggle_lock(int computer);
+extern int layout_init(void);
+/* video_switch.c */
+extern MM *MM_open(void);
+extern int MM_set(MM *m, int a, int b);
+extern int VS_set(MM *m, int v);
diff --git a/status.c b/status.c
new file mode 100644
index 0000000..e627338
--- /dev/null
+++ b/status.c
@@ -0,0 +1,141 @@
+#include "project.h"
+
+
+static int computer_old_locked[N_COMPUTER + 1];
+static int computer_old_active[N_COMPUTER + 1];
+static int computer_old_console[N_COMPUTER + 1];
+
+
+static int console_old_locked[N_CONSOLE + 1];
+static int console_old_active[N_CONSOLE + 1];
+static int console_old_computer[N_CONSOLE + 1];
+
+
+void
+status_draw_computer (int computer, int locked, int console, int active,
+ int force)
+{
+
+ int x = (computer - 1) * 45;
+ int y = 5;
+ x += 2;
+
+ if (force || (computer_old_locked[computer] != locked))
+ {
+ if (locked != -1)
+ computer_old_locked[computer] = locked;
+ else
+ locked = computer_old_locked[computer];
+ lcd_box (x, y, x + 44, y + 44, locked ? 255 : 0, locked ? 0 : 255,
+ locked ? 127 : 0);
+ }
+
+ if (force || (computer_old_console[computer] != console))
+ {
+ if (console != -1)
+ computer_old_console[computer] = console;
+ else
+ console = computer_old_console[computer];
+ lcd_ss (console ? console : 10, x + 17, y + 11, 11, 22);
+ }
+
+ if (force || (computer_old_active[computer] != active))
+ {
+ if (active != -1)
+ computer_old_active[computer] = active;
+ else
+ active = computer_old_active[computer];
+ lcd_box (x + 5, y + 5, x + 9, y + 9, active ? 255 : 0, active ? 255 : 0,
+ active ? 255 : 0);
+ }
+
+}
+
+void
+status_draw_console (int console, int locked, int computer, int active,
+ int force)
+{
+ int x = (console - 1) * 106;
+ int y = 100;
+
+
+ if (force || (console_old_locked[console] != locked))
+ {
+ if (locked != -1)
+ console_old_locked[console] = locked;
+ else
+ locked = console_old_locked[console];
+ lcd_box (x, y, x + 105, y + 105, locked ? 255 : 0, locked ? 0 : 255,
+ locked ? 127 : 0);
+ }
+
+ if (force || (console_old_computer[console] != computer))
+ {
+ if (computer != -1)
+ console_old_computer[console] = computer;
+ else
+ computer = console_old_computer[console];
+ lcd_ss (computer ? computer : 10, x + 35, y + 20, 30, 60);
+ }
+
+ if (force || (console_old_active[console] != active))
+ {
+ if (active != -1)
+ console_old_active[console] = active;
+ else
+ active = console_old_active[console];
+ lcd_box (x + 5, y + 5, x + 9, y + 9, active ? 255 : 0, active ? 255 : 0,
+ active ? 255 : 0);
+ }
+
+}
+
+
+void
+status_init (void)
+{
+ int i;
+
+ lcd_open ();
+ lcd_on ();
+
+ memset (computer_old_locked, 0xff, sizeof (computer_old_locked));
+ memset (computer_old_active, 0xff, sizeof (computer_old_active));
+ memset (computer_old_console, 0xff, sizeof (computer_old_console));
+
+ for (i = 1; i <= N_COMPUTER; ++i)
+ {
+ status_draw_computer (i, 0, 0, 0, 0);
+ }
+
+ memset (console_old_locked, 0xff, sizeof (console_old_locked));
+ memset (console_old_active, 0xff, sizeof (console_old_active));
+ memset (console_old_computer, 0xff, sizeof (console_old_computer));
+
+ for (i = 1; i <= N_CONSOLE; ++i)
+ {
+ status_draw_console (i, 0, 0, 0, 0);
+ }
+
+}
+
+void
+status_reset (void)
+{
+ int i;
+
+ lcd_close ();
+ lcd_open ();
+ lcd_on ();
+
+ for (i = 1; i <= N_COMPUTER; ++i)
+ {
+ status_draw_computer (i, -1, -1, -1, 0);
+ }
+
+ for (i = 1; i <= N_CONSOLE; ++i)
+ {
+ status_draw_console (i, -1, -1, -1, 0);
+ }
+
+}
diff --git a/video_switch.c b/video_switch.c
new file mode 100644
index 0000000..74d70b5
--- /dev/null
+++ b/video_switch.c
@@ -0,0 +1,365 @@
+#include "project.h"
+#include "lirc.h"
+
+#define NOTPULSE 0
+#define PULSE 0
+
+
+#define ONE(a) ((a) | PULSE)
+#define ZERO(a) ((a) | NOTPULSE)
+
+
+typedef struct
+{
+ int fd;
+ int a;
+ int b;
+ unsigned mask;
+} MS;
+
+struct MM_struct
+{
+ MS *left, *right, *top;
+};
+
+
+static uint8_t
+read_byte (int **bits, int *n)
+{
+ uint8_t c = 0;
+ int i = 8;
+
+ while (i-- && (*n)--)
+ {
+ c <<= 1;
+ c |= ! !(*((*bits)++));
+ }
+
+ return c;
+}
+
+static void
+dump_bits (int *bits, int n)
+{
+ uint8_t b;
+ int i;
+
+ for (i = 0; i < n; ++i)
+ {
+ printf ("%d", bits[i]);
+ if ((i % 8) == 7)
+ printf (" ");
+ }
+ printf ("\n");
+
+ while (n > 0)
+ {
+ b = read_byte (&bits, &n);
+ printf ("%02x ", b);
+ }
+ printf ("\n");
+
+
+}
+
+
+
+
+
+static void
+bit (int b)
+{
+ static int bits[1024];
+ static int bc;
+
+
+ if (b == 2)
+ {
+ bc = 0;
+ return;
+ }
+
+
+
+ if (b == 3)
+ {
+ if (bc)
+ dump_bits (bits, bc);
+ bc = 0;
+ return;
+ }
+
+// printf(" > bit[%3d]=%d\n",bc,b);
+
+ bits[bc++] = b;
+}
+
+
+static void
+ana (lirc_t * buf, int n, int mode)
+{
+ int s = 0;
+
+ while (n--)
+ {
+ lirc_t v = *(buf++);
+
+ if (mode == 2)
+ s = (v & 0xff000000U) ? 1 : 0;
+ else
+ s = !s;
+
+ v &= 0xffffff;
+
+// printf ("%5d %d\n", v, s);
+
+ if (s)
+ continue;
+
+ if ((v < 5000) && (v > 4000))
+ {
+ bit (2);
+ }
+ else if ((v < 750) && (v > 450))
+ {
+ bit (0);
+ }
+ else if ((v < 1850) && (v > 1500))
+ {
+ bit (1);
+ }
+ else
+ {
+ bit (3);
+ }
+ }
+
+
+
+}
+
+static void
+listen (int fd)
+{
+
+ for (;;)
+ {
+ lirc_t v;
+
+ read (fd, &v, sizeof (v));
+ ana (&v, 1, 2);
+
+
+
+ }
+}
+
+static int
+send_command (int fd, unsigned mask, uint8_t * buf, int n)
+{
+ lirc_t cbuf[128], *ptr = cbuf;
+ uint8_t c;
+ int b = 0;
+
+ printf ("Sending %x %x %x %x to fd %d mask %x\n",
+ buf[0], buf[1], buf[2], buf[3], fd, mask);
+
+ *(ptr++) = ONE (9300);
+ *(ptr++) = ZERO (4500);
+ b += 2;
+
+ while (n--)
+ {
+ for (c = 128; c; c >>= 1)
+ {
+ if ((*buf) & c)
+ {
+ *(ptr++) = ONE (550);
+ *(ptr++) = ZERO (1650);
+ }
+ else
+ {
+ *(ptr++) = ONE (550);
+ *(ptr++) = ZERO (600);
+ }
+ b += 2;
+
+
+ }
+ buf++;
+ }
+ *(ptr++) = ONE (550);
+ b++;
+
+
+
+
+#if 0
+ ana (cbuf, b, 0);
+ bit (3);
+#endif
+
+
+ ioctl (fd, LIRC_SET_TRANSMITTER_MASK, &mask);
+
+#if 0
+ if (write (fd, cbuf, sizeof (lirc_t) * b) != (b * sizeof (lirc_t)))
+ return -1;
+ usleep (20000);
+#endif
+ if (write (fd, cbuf, sizeof (lirc_t) * b) != (b * sizeof (lirc_t)))
+ return -1;
+ usleep (100000);
+ return 0;
+}
+
+
+static int
+send_command4 (int fd, unsigned m, uint8_t c1, uint8_t c2, uint8_t c3,
+ uint8_t c4)
+{
+ uint8_t c[] = { c1, c2, c3, c4 };
+ return send_command (fd, m, c, sizeof (c));
+}
+
+static int
+s42 (int fd, int ab, unsigned mask, int d)
+{
+ uint8_t c3[2][5] =
+ { {0xb0, 0x98, 0xa8, 0x0a, 0x52}, {0x40, 0x18, 0x8a, 0xca, 0xa2} };
+ uint8_t c4[2][5] =
+ { {0x4f, 0x67, 0x57, 0xf5, 0xad}, {0xbf, 0xe7, 0x75, 0x35, 0x5d} };
+
+ if (ab < 0)
+ return -1;
+ if (ab > 1)
+ return -1;
+ if (d < 0)
+ return -1;
+ if (d > 4)
+ return -1;
+
+
+ return send_command4 (fd, mask, 0x00, 0xff, c3[ab][d], c4[ab][d]);
+
+}
+
+static int
+s51 (int fd, unsigned mask, int d)
+{
+ uint8_t c3[6] = { 0x00, 0xa0, 0x10, 0x90, 0x50, 0xb0 };
+ uint8_t c4[6] = { 0x00, 0x5f, 0xef, 0x6f, 0xaf, 0x4f };
+
+ if (d < 1)
+ return -1;
+ if (d > 5)
+ return -1;
+
+
+ return send_command4 (fd, mask, 0x00, 0xfd, c3[d], c4[d]);
+}
+
+
+static int
+MS_set (MS * m, int a, int b)
+{
+ if (!m)
+ return -1;
+
+
+
+ if ((a != -1) && (m->a != a))
+ {
+
+ if (s42 (m->fd, 0, m->mask, a))
+ return -1;
+ m->a = a;
+ }
+
+
+ if ((b != -1) && (m->b != b))
+ {
+ if (s42 (m->fd, 1, m->mask, b))
+ return -1;
+ m->b = b;
+ }
+
+
+ return 0;
+}
+
+
+static MS *
+MS_open (int fd, unsigned mask)
+{
+ MS *ret = malloc (sizeof (MS));
+
+ ret->fd = fd;
+ ret->a = -1;
+ ret->b = -1;
+ ret->mask = mask;
+
+ return ret;
+}
+
+MM *
+MM_open (void)
+{
+ int fd;
+ MM *ret = malloc (sizeof (MM));
+ unsigned u;
+
+ fd = open ("/dev/lirc0", O_RDWR);
+ u = 40000;
+ ioctl (fd, LIRC_SET_SEND_CARRIER, &u);
+
+ //s51(fd,1,2);
+
+ //listen(fd);
+
+ ret->left = MS_open (fd, 1);
+ ret->right = NULL; //MS_open (fd, 2);
+
+ fd = open ("/dev/lirc1", O_RDWR);
+ u = 40000;
+ ioctl (fd, LIRC_SET_SEND_CARRIER, &u);
+ ret->top = NULL; // MS_open (fd, 1);
+
+
+
+ return ret;
+}
+
+
+int
+MM_set (MM * m, int a, int b)
+{
+
+ return MS_set (m->left, a, b);
+
+
+}
+
+int
+VS_set (MM * m, int v)
+{
+ return s51 (m->left->fd, 2, v);
+}
+
+
+
+
+#if 0
+main (int argc, char *argv[])
+{
+
+ MM *mm;
+
+ mm = MM_open ();
+
+// MM_set (mm,1, 2);
+ //MM_set (mm,-1, 1);
+// MM_set (mm,1, -1);
+
+}
+#endif