summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root@lamia.panaceas.james.local>2015-06-13 13:08:23 +0100
committerroot <root@lamia.panaceas.james.local>2015-06-13 13:08:23 +0100
commitcd568297a41e5a6f2e130de82c07b6b789d34f4b (patch)
treea8ac2021e11d8a33d178fa521bde323c819e4c8d
parent162fcd3f8d879615dc39181daea95ef6fcb83752 (diff)
downloadtims_keyboard-cd568297a41e5a6f2e130de82c07b6b789d34f4b.tar.gz
tims_keyboard-cd568297a41e5a6f2e130de82c07b6b789d34f4b.tar.bz2
tims_keyboard-cd568297a41e5a6f2e130de82c07b6b789d34f4b.zip
add usb wakeup support, all keys up on bad data, and resend for parity errors
-rw-r--r--app/atkbd.c127
-rw-r--r--app/consumer.c15
-rw-r--r--app/keyboard.c21
-rw-r--r--app/keymap.c6
-rw-r--r--app/project.h4
-rw-r--r--app/prototypes.h7
-rw-r--r--app/ticker.c11
-rw-r--r--app/usb.c42
8 files changed, 185 insertions, 48 deletions
diff --git a/app/atkbd.c b/app/atkbd.c
index d450bc2..c12f70e 100644
--- a/app/atkbd.c
+++ b/app/atkbd.c
@@ -10,11 +10,11 @@
/*Cope with lost sync */
/*If we've had no bits for this long, it's definately the start of a new word, 72MHz units */
-#define RESYNC_GAP (7200000) /* 100ms */
+#define RESYNC_GAP (100 * MS)
-#define ATKBD_TIMEOUT 1000 /*how long to wait for the keyboard to respond to a command in ms */
+#define ATKBD_TIMEOUT (1000 * MS) /*how long to wait for the keyboard to respond to a command in ms */
-#define ATKBD_CLOCK_SEIZE_DELAY 200 /* how many us from pulling clock low to pulling data low, when we xmit */
+#define ATKBD_CLOCK_SEIZE_DELAY 200 /* how many us from pulling clock low to pulling data low, when we xmit*/
#define ATKBD_BIT_DELAY 10 /* how many us we allow from the KBD to pull clock back up */
@@ -96,11 +96,22 @@ cycle_diff (uint32_t a, uint32_t b)
return b - a;
}
+
+static int fake_ctrl, pause_down;
+
+void
+atkbd_dispatch_error (void)
+{
+ pause_down = 0;
+ fake_ctrl = 0;
+ scancode_error ();
+}
+
+
static void
atkbd_dispatch (int key, int updown)
{
/* the logic here is batshit, consult scancode.doc in the DOCS dir */
- static int fake_ctrl, pause_down;
switch (key)
{
@@ -150,7 +161,7 @@ atkbd_data_dispatch (uint8_t byte)
static int emul;
#ifdef DEBUG
- printf ("ATKBD < 0x%02x\r\n", byte);
+ printf ("ATKBD_RX < 0x%02x\r\n", byte);
#endif
switch (byte)
@@ -162,6 +173,7 @@ atkbd_data_dispatch (uint8_t byte)
atkbd_nack++;
break;
case ATKBD_RET_BAT:
+ atkbd_dispatch_error ();
atkbd_bat++;
break;
case ATKBD_RET_ECHO:
@@ -219,7 +231,16 @@ exti0_isr (void)
atkbd_byte = 0;
parity = 0;
if (!d)
- state++;
+ {
+ state++;
+ }
+ else
+ {
+ atkbd_dispatch_error ();
+#ifdef DEBUG
+ printf ("ATKBD_ISR ! start bit non-zero\r\n");
+#endif
+ }
break;
case STATE_BIT0:
case STATE_BIT1:
@@ -236,8 +257,28 @@ exti0_isr (void)
state++;
break;
case STATE_STOP:
- if (d && parity)
- atkbd_data_dispatch (atkbd_byte);
+ if (d)
+ {
+ if (parity)
+ atkbd_data_dispatch (atkbd_byte);
+
+ if (!parity)
+ {
+ atkbd_dispatch_error ();
+#ifdef DEBUG
+ printf ("ATKBD_ISR ! bad parity - issuing resend\r\n");
+#endif
+ atkbd_send (ATKBD_CMD_RESEND);
+ }
+ }
+ else
+ {
+ atkbd_dispatch_error ();
+#ifdef DEBUG
+ printf ("ATKBD_ISR ! stop bit zero\r\n");
+#endif
+ }
+
state = STATE_START;
break;
}
@@ -275,7 +316,7 @@ atkbd_set (int clk, int dat)
int
atkbd_send (uint8_t d)
{
- uint32_t then = ticks;
+ uint32_t then = dwt_read_cycle_counter ();;
int parity = 1;
uint32_t c;
@@ -293,46 +334,46 @@ atkbd_send (uint8_t d)
for (c = 1; c < 0x100; c <<= 1)
{
while (GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
atkbd_set (1, c & d);
parity ^= ! !(c & d);
while (!GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
}
/* A parity bit */
while (GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
atkbd_set (1, parity);
while (!GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
/* two stop bits */
while (GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
atkbd_set (1, 1);
while (!GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
while (GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
atkbd_set (1, 1);
while (!GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
while (!GET (KBDAT))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
while (!GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
atkbd_unmask_flush_irq ();
@@ -346,10 +387,10 @@ atkbd_send (uint8_t d)
err:
atkbd_set (1, 1);
while (!GET (KBDAT))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
while (!GET (KBCLK))
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
goto err;
atkbd_unmask_flush_irq ();
@@ -363,18 +404,18 @@ err:
static int
atkbd_reset (void)
{
- uint32_t then = ticks;
+ uint32_t then = dwt_read_cycle_counter ();;
atkbd_bat = 0;
atkbd_send (ATKBD_CMD_RESET_BAT);
while (!atkbd_bat)
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
return -1;
- then = ticks;
+ then = dwt_read_cycle_counter ();;
atkbd_ack = 0;
atkbd_send (ATKBD_CMD_SETALL_MBR);
while (!atkbd_ack)
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
return -1;
@@ -384,11 +425,11 @@ atkbd_reset (void)
int
atkbd_request_echo (void)
{
- uint32_t then = ticks;
+ uint32_t then = dwt_read_cycle_counter ();;
atkbd_ack = 0;
atkbd_send (ATKBD_CMD_ECHO);
while (!atkbd_echo)
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
return -1;
return 0;
@@ -405,18 +446,18 @@ atkbd_set_leds (uint8_t leds)
if (!ready)
return 0;
- then = ticks;
+ then = dwt_read_cycle_counter ();;
atkbd_ack = 0;
atkbd_send (ATKBD_CMD_SETLEDS);
while (!atkbd_ack)
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
return -1;
- then = ticks;
+ then = dwt_read_cycle_counter ();;
atkbd_ack = 0;
atkbd_send (leds);
while (!atkbd_ack)
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
return -1;
return 0;
@@ -426,18 +467,18 @@ atkbd_set_leds (uint8_t leds)
int
atkbd_set_scanset (uint8_t scanset)
{
- uint32_t then = ticks;
+ uint32_t then = dwt_read_cycle_counter ();;
atkbd_ack = 0;
atkbd_send (ATKBD_CMD_SSCANSET);
while (!atkbd_ack)
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
return -1;
- then = ticks;
+ then = dwt_read_cycle_counter ();;
atkbd_ack = 0;
atkbd_send (scanset);
while (!atkbd_ack)
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
return -1;
return 0;
@@ -446,11 +487,11 @@ atkbd_set_scanset (uint8_t scanset)
int
atkbd_set_mb (void)
{
- uint32_t then = ticks;
+ uint32_t then = dwt_read_cycle_counter ();;
atkbd_ack = 0;
atkbd_send (ATKBD_CMD_SETALL_MB);
while (!atkbd_ack)
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
return -1;
return 0;
@@ -459,11 +500,11 @@ atkbd_set_mb (void)
int
atkbd_set_mbr (void)
{
- uint32_t then = ticks;
+ uint32_t then = dwt_read_cycle_counter ();;
atkbd_ack = 0;
atkbd_send (ATKBD_CMD_SETALL_MBR);
while (!atkbd_ack)
- if (timed_out (then, ATKBD_TIMEOUT))
+ if (timed_out_cycles (then, ATKBD_TIMEOUT))
return -1;
return 0;
@@ -477,9 +518,11 @@ atkbd_init (void)
atkbd_set (1, 1);
}
-void atkbd_start(void)
+void
+atkbd_start (void)
{
- if (ready) return;
+ if (ready)
+ return;
nvic_enable_irq (NVIC_EXTI0_IRQ);
@@ -491,7 +534,7 @@ void atkbd_start(void)
exti_reset_request (KBCLK);
nvic_enable_irq (KBCLK_IRQ);
- delay_ms(AT_KBD_INIT_TIME);
+ delay_ms (AT_KBD_INIT_TIME);
atkbd_reset ();
diff --git a/app/consumer.c b/app/consumer.c
index 79d25bb..b1b6290 100644
--- a/app/consumer.c
+++ b/app/consumer.c
@@ -99,13 +99,15 @@ consumer_send (uint16_t keys)
/*Last byte is the power wakeup stuff that we don't yet support */
uint8_t buf[CONSUMER_EP_TXN_SIZE] = { keys & 0xff, keys >> 8 };
- usbd_ep_write_packet (usbd_dev, CONSUMER_EP, buf, sizeof (buf));
+ if (!usb_is_suspended)
+ usbd_ep_write_packet (usbd_dev, CONSUMER_EP, buf, sizeof (buf));
}
+static uint16_t keys;
+
void
consumer_dispatch (int bit, int updown)
{
- static uint16_t keys;
if (updown)
keys |= bit;
@@ -117,7 +119,14 @@ consumer_dispatch (int bit, int updown)
printf ("CNS> %02x %02x\r\n", keys & 0xff, keys >> 8);
#endif
- consumer_send (keys);
+ usb_wakeup_host();
+ consumer_send (keys);
+}
+void
+consumer_error (void)
+{
+ keys = 0;
+ consumer_send (keys);
}
diff --git a/app/keyboard.c b/app/keyboard.c
index d35f466..f780ccc 100644
--- a/app/keyboard.c
+++ b/app/keyboard.c
@@ -127,19 +127,23 @@ keyboard_send (uint8_t modifiers, uint8_t * key_list)
key_list[4], key_list[5], 0
};
- usbd_ep_write_packet (usbd_dev, KEYBOARD_EP, buf, sizeof (buf));
+ if (!usb_is_suspended)
+ usbd_ep_write_packet (usbd_dev, KEYBOARD_EP, buf, sizeof (buf));
}
+static uint8_t modifiers;
+static uint8_t key_list[KEY_LIST_LEN];
+
void
keyboard_dispatch (int sc, int updown)
{
- static uint8_t modifiers;
- static uint8_t key_list[KEY_LIST_LEN];
int i;
/*Windows needs the modifiers spliting out, so we do this as per our
* descriptor, others need them in the list so we do that as well */
+ usb_wakeup_host();
+
switch (sc)
{
case USB_K_SC_LEFTCTRL:
@@ -156,6 +160,7 @@ keyboard_dispatch (int sc, int updown)
modifiers &= ~(1 << (sc - USB_K_SC_LEFTCTRL));
break;
default:
+
/* Some oses are picky and need these not to move about so we make
* a list of the down keys */
@@ -195,6 +200,16 @@ keyboard_dispatch (int sc, int updown)
}
+void
+keyboard_error (void)
+{
+ modifiers = 0;
+ memset (key_list, 0, sizeof (key_list));
+ keyboard_send (modifiers, key_list);
+}
+
+
+
int
keyboard_control_request (usbd_device * usbd_dev, struct usb_setup_data *req,
uint8_t ** buf, uint16_t * len,
diff --git a/app/keymap.c b/app/keymap.c
index d812911..5710237 100644
--- a/app/keymap.c
+++ b/app/keymap.c
@@ -129,6 +129,12 @@ static int at_to_usb_consumer[AT_SC_MAX] = {
+void
+scancode_error (void)
+{
+ keyboard_error ();
+ consumer_error ();
+}
void
scancode_dispatch (int key, int updown)
diff --git a/app/project.h b/app/project.h
index 87363f9..e477856 100644
--- a/app/project.h
+++ b/app/project.h
@@ -14,6 +14,7 @@
#include <libopencm3/usb/dfu.h>
#include <stdio.h>
+#include <string.h>
#include <errno.h>
#include "ring.h"
@@ -34,5 +35,8 @@
#define AT_KBD_INIT_TIME 200
+#define US (72)
+#define MS ( US * 1000 )
+
#include "prototypes.h"
diff --git a/app/prototypes.h b/app/prototypes.h
index 16aa300..1c692f8 100644
--- a/app/prototypes.h
+++ b/app/prototypes.h
@@ -9,12 +9,15 @@ extern const struct usb_endpoint_descriptor keyboard_endpoint;
extern const struct usb_interface_descriptor keyboard_iface;
extern void keyboard_get_descriptor(uint8_t **buf, uint16_t *len);
extern void keyboard_dispatch(int sc, int updown);
+extern void keyboard_error(void);
extern int keyboard_control_request(usbd_device *usbd_dev, struct usb_setup_data *req, uint8_t **buf, uint16_t *len, void (**complete)(usbd_device *usbd_dev, struct usb_setup_data *req));
/* usb.c */
extern const struct usb_device_descriptor dev;
extern const struct usb_interface ifaces[];
extern const struct usb_config_descriptor config;
extern usbd_device *usbd_dev;
+extern int usb_is_suspended;
+extern int usb_wakeup_host(void);
extern void usb_set_config(usbd_device *usbd_dev, uint16_t wValue);
extern void usb_init(void);
extern void usb_poll(void);
@@ -24,7 +27,9 @@ extern const struct usb_endpoint_descriptor consumer_endpoint;
extern const struct usb_interface_descriptor consumer_iface;
extern void consumer_get_descriptor(uint8_t **buf, uint16_t *len);
extern void consumer_dispatch(int bit, int updown);
+extern void consumer_error(void);
/* atkbd.c */
+extern void atkbd_dispatch_error(void);
extern void exti0_isr(void);
extern void atkbd_set(int clk, int dat);
extern int atkbd_send(uint8_t d);
@@ -63,6 +68,8 @@ extern void delay_us(uint32_t d);
extern void sys_tick_handler(void);
extern void delay_ms(uint32_t d);
extern int timed_out(uint32_t then, unsigned int ms);
+extern int timed_out_cycles(uint32_t then, unsigned int cycles);
extern void ticker_init(void);
/* keymap.c */
+extern void scancode_error(void);
extern void scancode_dispatch(int key, int updown);
diff --git a/app/ticker.c b/app/ticker.c
index e3ff474..2c0d532 100644
--- a/app/ticker.c
+++ b/app/ticker.c
@@ -43,6 +43,17 @@ timed_out (uint32_t then, unsigned int ms)
return 0;
}
+int
+timed_out_cycles (uint32_t then, unsigned int cycles)
+{
+ then = dwt_read_cycle_counter () - then;
+
+ if (then > cycles)
+ return 1;
+ return 0;
+}
+
+
void
ticker_init (void)
diff --git a/app/usb.c b/app/usb.c
index 9d8c6f8..b03eb9c 100644
--- a/app/usb.c
+++ b/app/usb.c
@@ -59,6 +59,45 @@ static const char *usb_strings[] = {
usbd_device *usbd_dev;
+int usb_is_suspended = 1;
+
+
+static void
+usb_suspended (void)
+{
+ *USB_CNTR_REG |= USB_CNTR_FSUSP;
+
+ usb_is_suspended = 1;
+}
+
+static void
+usb_resumed (void)
+{
+
+ *USB_CNTR_REG &= ~USB_CNTR_FSUSP;
+
+ usb_is_suspended = 0;
+}
+
+int
+usb_wakeup_host (void)
+{
+ if (!usb_is_suspended)
+ return 1;
+
+
+ *USB_CNTR_REG |= USB_CNTR_RESUME;
+
+ delay_us (1000);
+ delay_us (1000);
+ delay_us (1000);
+ delay_us (1000);
+ delay_us (1000);
+
+ *USB_CNTR_REG &= ~USB_CNTR_RESUME;
+
+ return 0;
+}
static int
usb_control_class_request (usbd_device * usbd_dev, struct usb_setup_data *req,
@@ -139,6 +178,9 @@ usb_init (void)
usbd_register_set_config_callback (usbd_dev, usb_set_config);
+ usbd_register_suspend_callback (usbd_dev, usb_suspended);
+ usbd_register_resume_callback (usbd_dev, usb_resumed);
+
}
void