diff options
| author | root <root@lamia.panaceas.james.local> | 2015-06-13 13:08:23 +0100 | 
|---|---|---|
| committer | root <root@lamia.panaceas.james.local> | 2015-06-13 13:08:23 +0100 | 
| commit | cd568297a41e5a6f2e130de82c07b6b789d34f4b (patch) | |
| tree | a8ac2021e11d8a33d178fa521bde323c819e4c8d | |
| parent | 162fcd3f8d879615dc39181daea95ef6fcb83752 (diff) | |
| download | tims_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.c | 127 | ||||
| -rw-r--r-- | app/consumer.c | 15 | ||||
| -rw-r--r-- | app/keyboard.c | 21 | ||||
| -rw-r--r-- | app/keymap.c | 6 | ||||
| -rw-r--r-- | app/project.h | 4 | ||||
| -rw-r--r-- | app/prototypes.h | 7 | ||||
| -rw-r--r-- | app/ticker.c | 11 | ||||
| -rw-r--r-- | app/usb.c | 42 | 
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) @@ -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  | 
