/*
* sapphire.c
*
- * Copyright Mark Lord <mlord@pobox.com>, 2012-2019.
+ * Copyright Mark Lord <mlord@pobox.com>, 2012-2020.
* http://rtr.ca/sapphire_remote/
*
* This is a HID driver for the TopSeed Cyberlink receiver
#include "sapphire.h"
#define SAPPHIRE_NAME "sapphire"
-#define SAPPHIRE_VERSION "7.3"
+#define SAPPHIRE_VERSION "7.4"
/*
* "LONGKEY": Any button can be used to generate a second, different keycode,
{SAPPHIRE_PAUSE , KEY_P , NO_REPEAT }, /* Play/Pause */
{SAPPHIRE_VOLUP , KEY_RIGHTBRACE , FAST_REPEAT }, /* Volume Up */
{SAPPHIRE_VOLDOWN , KEY_LEFTBRACE , FAST_REPEAT }, /* Volume Down */
- {SAPPHIRE_CHUP , KEY_PAGEUP , SLOW_REPEAT }, /* channel up (CUSTOM) */
- {SAPPHIRE_CHDOWN , KEY_PAGEDOWN , SLOW_REPEAT }, /* channel down (CUSTOM) */
+ {SAPPHIRE_CHUP , KEY_PAGEUP , MED_REPEAT }, /* channel up (CUSTOM) */
+ {SAPPHIRE_CHDOWN , KEY_PAGEDOWN , MED_REPEAT }, /* channel down (CUSTOM) */
{SAPPHIRE_MUTE , KEY_F9 , LONGKEY|KEY_F15 }, /* Mute (tap) or Audiosync (hold) */
{SAPPHIRE_RECORD , KEY_R , NO_REPEAT }, /* Record/Delete (CUSTOM) */
{SAPPHIRE_FWD , KEY_DOT , NO_REPEAT }, /* FFwd */
} sapphire_dev, *dev = &sapphire_dev;
enum {
+ SLOW_RATE = HZ / 4, /* repeat rate for SLOW_REPEAT */
+ MED_RATE = HZ / 6, /* repeat rate for MED_REPEAT */
+ FAST_RATE = HZ / 8, /* repeat rate for FAST_REPEAT */
+ RAMP_MAX = HZ / 10, /* max repeat rate for RAMP_REPEAT */
+ RAMP_ADJ = HZ / 40, /* amount to speed up by after each repeat */
RAMPING = 0x80000000, /* flag to indicate current dev->down_key is using RAMP_REPEAT */
- RAMPING_RATE = HZ / 40, /* amount to speed up by after each repeat */
- RAMPING_MAX = HZ / 10, /* max repeats/sec when RAMPING */
MODIFIERS = CTRL|SHIFT|ALT|META, /* convenient mask of all modifier keys */
PRESSED = 1, /* for use with input_event() */
RELEASED = 0, /* for use with input_event() */
};
-static unsigned int ramping_rate = RAMPING_RATE;
-static unsigned int ramping_max = RAMPING_MAX;
+static unsigned int slow_rate = SLOW_RATE;
+static unsigned int med_rate = MED_RATE;
+static unsigned int fast_rate = FAST_RATE;
+static unsigned int ramp_adj = RAMP_ADJ;
+static unsigned int ramp_max = RAMP_MAX;
/*
* Translate a [XS]APPHIRE_ "button" into a KEY_ "keycode" or "macro".
unsigned int next_repeat = dev->next_repeat & ~RAMPING;
if (dev->next_repeat & RAMPING) {
/* Gradually ramp-up the repeat rate for this key */
- if (next_repeat > ramping_max) {
- next_repeat -= ramping_rate;
- if (next_repeat < ramping_max)
- next_repeat = ramping_max;
+ if (next_repeat > ramp_max) {
+ next_repeat -= ramp_adj;
+ if (next_repeat < ramp_max)
+ next_repeat = ramp_max;
}
dev->next_repeat = next_repeat | RAMPING;
}
*/
static void sapphire_handle_key (unsigned int key, unsigned int repeats)
{
- unsigned int repeat_delay = NO_REPEAT, next_repeat = 0;
+ const unsigned int REPEAT_DELAY = (HZ/2) - (HZ/6);
+ unsigned int next_repeat = 0;
switch (repeats) {
case RAWKEY:
dev->raw_key = key;
return;
case SLOW_REPEAT:
- repeat_delay = HZ/2;
- next_repeat = HZ/SLOW_REPEAT;
+ next_repeat = slow_rate;
+ break;
+ case MED_REPEAT:
+ next_repeat = med_rate;
break;
case FAST_REPEAT:
- repeat_delay = HZ/3;
- next_repeat = HZ/FAST_REPEAT;
+ next_repeat = fast_rate;
break;
case RAMP_REPEAT:
- repeat_delay = (HZ/2) - (HZ/6);
next_repeat = (HZ/3) | RAMPING;
break;
default:
return;
}
}
- sapphire_send_key(key, repeat_delay);
+ sapphire_send_key(key, next_repeat ? REPEAT_DELAY : NO_REPEAT);
if (next_repeat ) {
dev->down_key = key;
dev->next_repeat = next_repeat;
return len;
}
+static int sapphire_get_HZ_vals (u8 *line, const char *keyword, int *val1, int *val2)
+{
+ int v1, v2, keyword_len = strlen(keyword);
+
+ if (0 != strncmp(line, keyword, keyword_len) || line[keyword_len] != ' ')
+ return -EAGAIN;
+ line += keyword_len + 1;
+ if ((val2 && 2 == sscanf(line, "%u %u", &v1, &v2)) || (1 == sscanf(line, "%u", &v1))) {
+ *val1 = HZ / v1;
+ if (val2)
+ *val2 = HZ / v2;
+ return 0;
+ }
+ return -EINVAL;
+}
+
/*
* Handles writes to /proc/ for altering key/macro mappings on the fly,
* and also for injecting keycodes from scripts etc.
*/
static int sapphire_oldproc_write(struct file *file, const char __user *ubuf, unsigned long count, void *data)
{
- static const char SENDKEY[] = "SENDKEY ";
- static const char REPEAT_RATE[] = "REPEAT_RATE ";
+ static const char SENDKEY[7] = "SENDKEY";
+ static const char REPEAT_RATE[] = "REPEAT_RATE"; // Original backward-compatible name for RAMP_RATE
+ static const char RAMP_RATE[] = "RAMP_RATE";
+ static const char SLOW_RATE[] = "SLOW_RATE";
+ static const char MED_RATE[] = "MED_RATE";
+ static const char FAST_RATE[] = "FAST_RATE";
unsigned int len = count, val, ret = 0;
u8 *buf = kmalloc(len + 2, GFP_KERNEL), *line, *eol;
struct sapphire_map *map;
int sendkey = 0;
for (eol = line; *eol != '\n'; ++eol);
*eol = '\0';
- if (0 == strncmp(line, SENDKEY, sizeof(SENDKEY)-1)) {
- line += sizeof(SENDKEY)-1;
+ if (0 == strncmp(line, SENDKEY, sizeof(SENDKEY))) {
+ line += sizeof(SENDKEY);
sendkey = 1;
- } else if (0 == strncmp(line, REPEAT_RATE, sizeof(REPEAT_RATE)-1)) {
- unsigned int rate, max;
- line += sizeof(REPEAT_RATE)-1;
- if (2 != sscanf(line, "%u %u", &rate, &max)) {
- ret = -EINVAL;
+ } else {
+ ret = sapphire_get_HZ_vals(line, REPEAT_RATE, &ramp_adj, &ramp_max);
+ if (ret == -EAGAIN)
+ ret = sapphire_get_HZ_vals(line, RAMP_RATE, &ramp_adj, &ramp_max);
+ if (ret == -EAGAIN)
+ ret = sapphire_get_HZ_vals(line, SLOW_RATE, &slow_rate, NULL);
+ if (ret == -EAGAIN)
+ ret = sapphire_get_HZ_vals(line, MED_RATE, &med_rate, NULL);
+ if (ret == -EAGAIN)
+ ret = sapphire_get_HZ_vals(line, FAST_RATE, &fast_rate, NULL);
+ if (ret != -EAGAIN) {
+ if (ret == 0)
+ goto next_line;
break;
}
- ramping_rate = HZ / rate;
- ramping_max = HZ / max;
- goto next_line;
}
if (1 != sscanf(line, "%x", &val)) {
ret = -EINVAL;