一、为什么想到这个问题
昨天在电脑上看视频的时候,发现字幕有些问题。具体的问题就是视频是分两个文件的,但是字幕是单个文件的,所以在看第二个文件的时候字幕就对不上了,而且相差很大,这个时候就需要手动对齐字幕,这个误差大概是50分钟,也就是3K秒左右,播放器貌似又不支持直接设置一个偏移量,所以我就只能通过按键手动对齐,每次按键调整1秒的偏差。按下之后就体会到了长按自动重复的好处,只要按着不松手,播放器就会自动的发送按键事件。我搜索了下怎么样让这个按键生成的速度更快一些,找到了windows下
修改这配置的说明,因为作者的描述比较形象,例如作者说的“字符像机关枪的子弹一样射到屏幕上”这个生动的描述,感觉作者的脑洞开的有点大,并且也是个性情中人。我就把作者的描述搬过来了
Repeat delay: When you press and hold a key on a computer keyboard, the key eventually repeats itself, spewing out characters across the screen like bullets from a machine gun. The pause between pressing the key and when it starts repeating is the repeat delay.
Repeat rate: After you press and hold down a key on the keyboard, the key starts repeating itself. The speed at which it repeats is the repeat rate, which can be fast or slow.
对于win7的设置路径
系统左下角的“开始”按钮===>“设备与打印机”>===>>"USB NetVista Full WIdth Keyboard"右键===>>键盘设置===>>速度===>>字符重复
重复速度 重复延迟
设置之后效果非常明显,这样对齐字幕的时候就快很多了。
二、这个重复是谁做的
因为最近刚好在看gui相关内容,就考虑了下是谁执行的重复,是windows explorer、操作系统还是说是硬件执行的?好在开源的linux提供了类似的功能,最为直观的对应就是kbdrate,图形界面的xset也有相同功能,但是它的结构比较复杂,所以还是看命令行的kbdrate,这个基本就可以确定是软件还是硬件来实现。
tsecer@harry: strace kbdrate 2>&1| grep io
ioctl(0, KDKBDREP, 0xbf95d210) = -1 EINVAL (Invalid argument)
rt_sigaction(SIGALRM, {0x8048f30, [ALRM], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
tsecer@harry:
操作系统中对于这个命令的处理相关为
#define KDKBDREP 0x4B52 /* set keyboard delay/repeat rate;
* actually used values are returned */
#define ATKBD_CMD_SETREP 0x10f3
linux-3.12.6driversinputkeyboardatkbd.c
static int atkbd_set_repeat_rate(struct atkbd *atkbd)
{
const short period[32] =
{ 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
const short delay[4] =
{ 250, 500, 750, 1000 };
struct input_dev *dev = atkbd->dev;
unsigned char param;
int i = 0, j = 0;
while (i < ARRAY_SIZE(period) - 1 && period[i] < dev->rep[REP_PERIOD])
i++;
dev->rep[REP_PERIOD] = period[i];
while (j < ARRAY_SIZE(delay) - 1 && delay[j] < dev->rep[REP_DELAY])
j++;
dev->rep[REP_DELAY] = delay[j];
param = i | (j << 5);
return ps2_command(&atkbd->ps2dev, ¶m, ATKBD_CMD_SETREP);
}
三、这个重复可以有多快
kbdrate的man手册中说明
OPTIONS
-s Silent. No messages are printed.
-r rate
Change the keyboard repeat rate to rate cps. For Intel-based
systems, the allowable range is from 2.0 to 30.0 cps. Only cer-
tain, specific values are possible, and the program will select
the nearest possible value to the one specified. The possible
values are given, in characters per second, as follows: 2.0,
2.1, 2.3, 2.5, 2.7, 3.0, 3.3, 3.7, 4.0, 4.3, 4.6, 5.0, 5.5, 6.0,
6.7, 7.5, 8.0, 8.6, 9.2, 10.0, 10.9, 12.0, 13.3, 15.0, 16.0,
17.1, 18.5, 20.0, 21.8, 24.0, 26.7, 30.0. For SPARC-based sys-
tems, the allowable range is from 0 (no repeat) to 50 cps.
-d delay
Change the delay to delay milliseconds. For Intel-based sys-
tems, the allowable range is from 250 to 1000 ms, in 250 ms
steps. For SPARC systems, possible values are between 10 ms and
1440 ms, in 10 ms steps.
从前面内核中的代码来看,它有这样的一组对应的数字
const short period[32] =
{ 33, 37, 42, 46, 50, 54, 58, 63, 67, 75, 83, 92, 100, 109, 116, 125,
133, 149, 167, 182, 200, 217, 232, 250, 270, 303, 333, 370, 400, 435, 470, 500 };
可以看到这个顺序是和man手册中 -r rate说明的数字相对应,并且刚好顺序相反,两者的乘积大概是1000。这里也说明了重复按键的最大频率,也就是1秒钟最多重复30次。以需要同步50分钟为例,秒钟最多重复30次,所以字幕同步时间大概为50*60/30=100秒。
四、关于键盘驱动中的命令说明
由于这个笔记比较短,而
这个文档挺重要的,我就多搬了点过来:
Below are all the commands the host may send to the keyboard:
- 0xFF (Reset) - Keyboard responds with "ack" (0xFA), then enters "Reset" mode. (See "Reset" section.)
- 0xFE (Resend) - Keyboard responds by resending the last-sent byte. The exception to this is if the last-sent byte was "resend" (0xFE). If this is the case, the keyboard resends the last non-0xFE byte. This command is used by the host to indicate an error in reception.
The next six commands can be issued when the keyboard is in any mode, but it only effects the behavior of the keyboard when in "mode 3" (ie, set to scan code set 3.)
- *0xFD (Set Key Type Make) - Disable break codes and typematic repeat for specified keys. Keyboard responds with "ack" (0xFA), then disables scanning (if enabled) and reads a list of keys from the host. These keys are specified by their set 3 make codes. Keyboard responds to each make code with "ack". Host terminates this list by sending an invalid set 3 make code (eg, a valid command.) The keyboard then re-enables scanning (if previously disabled).
- *0xFC (Set Key Type Make/Break) - Similar to previous command, except this one only disables typematic repeat.
- *0xFB (Set Key Type Typematic) - Similar to previous two, except this one only disables break codes.
- *0xFA (Set All Keys Typematic/Make/Break) - Keyboard responds with "ack" (0xFA). Sets all keys to their normal setting (generate scan codes on make, break, and typematic repeat)
- *0xF9 (Set All Keys Make) - Keyboard responds with "ack" (0xFA). Similar to 0xFD, except applies to all keys.
- *0xF8 (Set All Keys Make/Break) - Keyboard responds with "ack" (0xFA). Similar to 0xFC, except applies to all keys.
- *0xF7 (Set All Keys Typematic) - Keyboard responds with "ack" (0xFA). Similar to 0xFB, except applies to all keys.
- 0xF6 (Set Default) - Load default typematic rate/delay (10.9cps / 500ms), key types (all keys typematic/make/break), and scan code set (2).
- 0xF5 (Disable) - Keyboard stops scanning, loads default values (see "Set Default" command), and waits further instructions.
- 0xF4 (Enable) - Re-enables keyboard after disabled using previous command.
- 0xF3 (Set Typematic Rate/Delay) - Host follows this command with one argument byte that defines the typematic rate and delay as follows:
Repeat RateBits 0-4 | Rate(cps) | | Bits 0-4 | Rate(cps) | | Bits 0-4 | Rate(cps) | | Bits 0-4 | Rate(cps) |
00h | 30.0 | | 08h | 15.0 | | 10h | 7.5 | | 18h | 3.7 |
01h | 26.7 | | 09h | 13.3 | | 11h | 6.7 | | 19h | 3.3 |
02h | 24.0 | | 0Ah | 12.0 | | 12h | 6.0 | | 1Ah | 3.0 |
03h | 21.8 | | 0Bh | 10.9 | | 13h | 5.5 | | 1Bh | 2.7 |
04h | 20.7 | | 0Ch | 10.0 | | 14h | 5.0 | | 1Ch | 2.5 |
05h | 18.5 | | 0Dh | 9.2 | | 15h | 4.6 | | 1Dh | 2.3 |
06h | 17.1 | | 0Eh | 8.6 | | 16h | 4.3 | | 1Eh | 2.1 |
07h | 16.0 | | 0Fh | 8.0 | | 17h | 4.0 | | 1Fh | 2.0 |
Delay
Bits 5-6 | Delay (seconds) |
00b | 0.25 |
01b | 0.50 |
10b | 0.75 |
11b | 1.00 |
- *0xF2 (Read ID) - The keyboard responds by sending a two-byte device ID of 0xAB, 0x83. (0xAB is sent first, followed by 0x83.)
- *0xF0 (Set Scan Code Set) - Keyboard responds with "ack", then reads argument byte from the host. This argument byte may be 0x01, 0x02, or 0x03 to select scan code set 1, 2, or 3, respectively. The keyboard responds to this argument byte with "ack". If the argument byte is 0x00, the keyboard responds with "ack" followed by the current scan code set.
- 0xEE (Echo) - The keyboard responds with "Echo" (0xEE).
- 0xED (Set/Reset LEDs) - The host follows this command with one argument byte, that specifies the state of the keyboard's Num Lock, Caps Lock, and Scroll Lock LEDs. This argument byte is defined as follows:
Always 0 | Always 0 | Always 0 | Always 0 | Always 0 | Caps Lock | Num Lock | Scroll Lock |
- "Scroll Lock" - Scroll Lock LED off(0)/on(1)
- "Num Lock" - Num Lock LED off(0)/on(1)
- "Caps Lock" - Caps Lock LED off(0)/on(1)
*Originally available in PS/2 keyboards only.