summaryrefslogtreecommitdiffstats
path: root/output.c
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 /output.c
downloadkmd_usb-470457e22a1b5537013603d5e367c51e47bb61bf.tar.gz
kmd_usb-470457e22a1b5537013603d5e367c51e47bb61bf.tar.bz2
kmd_usb-470457e22a1b5537013603d5e367c51e47bb61bf.zip
fish
Diffstat (limited to 'output.c')
-rw-r--r--output.c441
1 files changed, 441 insertions, 0 deletions
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);
+
+
+}