readline中的鍵盤碼^[[A,^[[B,^[[D,^[[C (ANSI控制碼)
阿新 • • 發佈:2018-12-24
最近除錯u-boot的readline,對一些特殊按鍵鍵值有些疑惑,比如↑↓←→四個鍵,在linux的minicom敲下這幾個鍵,串列埠會輸出什麼資料。
其實不需要用串列埠測試,我們可以寫個小程式測試一下:
測試:
或者執行cat -v,然後輸入↑↓←→(其他鍵也可以F1~F12)。
參考知乎一位大俠的說法:
http://www.zhihu.com/question/21518507
這下就明白了。再聯絡cread_line的程式碼片段:
這些都是ANSI 控制碼,以ESC起始為標記,百度就知道了。
在測試這個問題的時候,需要使用virtual box虛擬機器中的xp串列埠進行測試,百度半天也沒找到能完全說清楚的文章,下面介紹我個人的試驗結果和理解:
第一種是裸檔案,這種模式只能讓虛擬機器串列埠輸出資訊到宿主機(我的是ubuntu)的某個檔案中,開啟可以檢視虛擬機器串列埠發來的文字資訊,基本沒什麼用。
第二種是主機管道,這個模式可以讓主機和虛擬機器進行串列埠通訊,相當於建立一個模擬的串列埠通道,主機和虛擬機器互聯,這個模式非常有用,對於測試串列埠提供了很方便的測試條件,即使你電腦沒有真是串列埠也沒關係。再也不需要想辦法去破解windows那些收費的虛擬串列埠軟體了。
注意使用主機管道模式時,應在管道路徑前加上字首unix#,例如virtual box中設定了串列埠位置為/dev/xpserial,那麼minicom中應設定Serial Device 為 unix#/dev/xpserial
第三種是主機裝置,這個就相當於將真實主機繫結到虛擬機器了,這時候真串列埠只能給虛擬機器用,但是有延遲,有時候會丟資料,實際上個人認為如果只是簡單資料收發沒必要用這個模式,真串列埠給宿主機用就可以了。
F8:
ASCII 碼:^[[19~
十六進位制0x1b 0x5b 0x31 0x39 0x7e
第一個位元組0x1b是"^[",第二個位元組0x5b是'[',第3個位元組是0x31,第4位元組就得到'9', 同理,0x39得到'9',最後0x7e是'~'
\033\133\061\071\176
在securecrt做對映時可以使用 "\e[\061\071\176"
↑:
^[[A
^[是第一個位元組0x1b,第二個位元組0x5b是[,最後的0x41是A
0x1b 0x5b 0x41
\033\133\101
Shift + F8:
^[[19;2~
0x1b 0x5b 0x31 0x39 0x3b 0x32 0x7e
"\e[\061\071\073\062\176"
關於控制碼還可以參考:
http://bbs.csdn.net/topics/320015593
其實不需要用串列埠測試,我們可以寫個小程式測試一下:
點選(此處)摺疊或開啟
-
#include <stdio.h>
-
#include <curses.h>
-
int main(int argc, char **argv)
-
{
-
char a;
-
char b[80];
-
int i;
-
printf("Please input a string
-
:\n");
-
// a = getc(
-
scanf("%s",b);
-
// printf("The
input a string is : 0x%x\n", a);
-
printf("The input char is:\n");
-
for(i = 0; b[i] !='\0' && i < 80; i++ )
-
printf("0x%x ",b[i]);
-
printf("\n");
-
return 0;
- }
測試:
點選(此處)摺疊或開啟
- [email protected]:~/work/driver/test$ ./test
- Please input a string:
- ^[[A^[[B^[[D^[[C
- The input char is:
- 0x1b 0x5b 0x41 0x1b 0x5b 0x42 0x1b 0x5b 0x44 0x1b 0x5b 0x43
或者執行cat -v,然後輸入↑↓←→(其他鍵也可以F1~F12)。
參考知乎一位大俠的說法:
http://www.zhihu.com/question/21518507
這下就明白了。再聯絡cread_line的程式碼片段:
點選(此處)摺疊或開啟
-
static int cread_line(const char *const
prompt, char *buf,
-
int timeout)
-
{
-
unsigned long num = 0;
-
unsigned long eol_num = 0;
-
unsigned long wlen;
-
char ichar;
-
int insert = 1;
-
int esc_len = 0;
-
char esc_save[8];
-
int init_len = strlen(buf);
-
int first = 1;
-
if (init_len)
-
cread_add_str(buf, init_len, 1, &num, &eol_num, buf, *len);
-
while (1) {
-
#ifdef CONFIG_BOOT_RETRY_TIME
-
while (!tstc()) { /* while no
incoming data */
-
if (retry_time >= 0
&& get_ticks() > endtime)
-
return (-2); /* timed out */
-
WATCHDOG_RESET();
-
}
-
#endif
-
if (first && timeout) {
-
uint64_t etime = endtick(timeout);
-
while (!tstc()) { /* while no
incoming data */
-
if (get_ticks() >= etime)
-
return -2; /* timed out */
-
WATCHDOG_RESET();
-
}
-
first = 0;
-
}
-
ichar = getcmd_getch();
-
if ((ichar == '\n') || (ichar == '\r')) {
-
putc('\n');
-
break;
-
}
-
/*
-
* handle standard linux xterm esc sequences for arrow key, etc.
-
*/
-
if (esc_len != 0) {
-
if (esc_len == 1) {
-
if (ichar == '[') {
-
esc_save[esc_len] = ichar;
-
esc_len = 2;
-
} else {
-
cread_add_str(esc_save, esc_len, insert,
-
&num, &eol_num, buf, *len);
-
esc_len = 0;
-
}
-
continue;
-
}
-
switch (ichar) {
-
case 'D': /* <- key */
-
ichar = CTL_CH('b');
-
esc_len = 0;
-
break;
-
case 'C': /* -> key */
-
ichar = CTL_CH('f');
-
esc_len = 0;
-
break; /* pass off to ^F handler */
-
case 'H': /* Home key */
-
ichar = CTL_CH('a');
-
esc_len = 0;
-
break; /* pass off to ^A handler */
-
case 'A': /* up arrow */
-
ichar = CTL_CH('p');
-
esc_len = 0;
-
break; /* pass off to ^P handler */
-
case 'B': /* down arrow */
-
ichar = CTL_CH('n');
-
esc_len = 0;
-
break; /* pass off to ^N handler */
-
default:
-
esc_save[esc_len++] = ichar;
-
cread_add_str(esc_save, esc_len, insert,
-
&num, &eol_num, buf, *len);
-
esc_len = 0;
-
continue;
-
}
-
}
-
switch (ichar) {
-
case 0x1b:
-
if (esc_len == 0) {
-
esc_save[esc_len] = ichar;
-
esc_len = 1;
-
} else {
-
puts("impossible condition #876\n");
-
esc_len = 0;
-
}
-
break;
-
case CTL_CH('a'):
-
BEGINNING_OF_LINE();
-
break;
-
case CTL_CH('c'): /* ^C - break */
-
*buf = '\0'; /* discard
input */
-
return (-1);
-
case CTL_CH('f'):
-
if (num < eol_num) {
-
getcmd_putch(buf[num]);
-
num++;
-
}
-
break;
-
case CTL_CH('b'):
-
if (num) {
-
getcmd_putch(CTL_BACKSPACE);
-
num--;
-
}
-
break;
-
case CTL_CH('d'):
-
if (num < eol_num) {
-
wlen = eol_num - num - 1;
-
if (wlen) {
-
memmove(&buf[num], &buf[num+1], wlen);
-
putnstr(buf + num, wlen);
-
}
-
getcmd_putch(' ');
-
do {
-
getcmd_putch(CTL_BACKSPACE);
-
} while (wlen--);
-
eol_num--;
-
}
-
break;
-
case CTL_CH('k'):
-
ERASE_TO_EOL();
-
break;
-
case CTL_CH('e'):
-
REFRESH_TO_EOL();
-
break;
-
case CTL_CH('o'):
-
insert = !insert;
-
break;
-
case CTL_CH('x'):
-
case CTL_CH('u'):
-
BEGINNING_OF_LINE();
-
ERASE_TO_EOL();
-
break;
-
case DEL:
-
case DEL7:
-
case 8:
-
if (num) {
-
wlen = eol_num - num;
-
num--;
-
memmove(&buf[num], &buf[num+1], wlen);
-
getcmd_putch(CTL_BACKSPACE);
-
putnstr(buf + num, wlen);
-
getcmd_putch(' ');
-
do {
-
getcmd_putch(CTL_BACKSPACE);
-
} while (wlen--);
-
eol_num--;
-
}
-
break;
-
case CTL_CH('p'):
-
case CTL_CH('n'):
-
{
-
char * hline;
-
esc_len = 0;
-
if (ichar == CTL_CH('p'))
-
hline = hist_prev();
-
else
-
hline = hist_next();
-
if (!hline) {
-
getcmd_cbeep();
-
continue;
-
}
-
/* nuke the current line */
-
/* first, go home */
-
BEGINNING_OF_LINE();
-
/* erase to end of line */
-
ERASE_TO_EOL();
-
/* copy new line into place and display */
-
strcpy(buf, hline);
-
eol_num = strlen(buf);
-
REFRESH_TO_EOL();
-
continue;
-
}
-
#ifdef CONFIG_AUTO_COMPLETE
-
case '\t': {
-
int num2, col;
-
/* do not autocomplete when in the middle */
-
if (num < eol_num) {
-
getcmd_cbeep();
-
break;
-
}
-
buf[num] = '\0';
-
col = strlen(prompt) + eol_num;
-
num2 = num;
-
if (cmd_auto_complete(prompt, buf, &num2, &col)) {
-
col = num2 - num;
-
num += col;
-
eol_num += col;
-
}
-
break;
-
}
-
#endif
-
default:
-
cread_add_char(ichar, insert, &num, &eol_num, buf, *len);
-
break;
-
}
-
}
-
*len = eol_num;
-
buf[eol_num] = '\0'; /* lose
the newline */
-
if (buf[0] &&
buf[0] != CREAD_HIST_CHAR)
-
cread_add_to_hist(buf);
-
hist_cur = hist_add_idx;
-
return 0;
- }
這些都是ANSI 控制碼,以ESC起始為標記,百度就知道了。
在測試這個問題的時候,需要使用virtual box虛擬機器中的xp串列埠進行測試,百度半天也沒找到能完全說清楚的文章,下面介紹我個人的試驗結果和理解:
第一種是裸檔案,這種模式只能讓虛擬機器串列埠輸出資訊到宿主機(我的是ubuntu)的某個檔案中,開啟可以檢視虛擬機器串列埠發來的文字資訊,基本沒什麼用。
第二種是主機管道,這個模式可以讓主機和虛擬機器進行串列埠通訊,相當於建立一個模擬的串列埠通道,主機和虛擬機器互聯,這個模式非常有用,對於測試串列埠提供了很方便的測試條件,即使你電腦沒有真是串列埠也沒關係。再也不需要想辦法去破解windows那些收費的虛擬串列埠軟體了。
注意使用主機管道模式時,應在管道路徑前加上字首unix#,例如virtual box中設定了串列埠位置為/dev/xpserial,那麼minicom中應設定Serial Device 為 unix#/dev/xpserial
第三種是主機裝置,這個就相當於將真實主機繫結到虛擬機器了,這時候真串列埠只能給虛擬機器用,但是有延遲,有時候會丟資料,實際上個人認為如果只是簡單資料收發沒必要用這個模式,真串列埠給宿主機用就可以了。
F8:
ASCII 碼:^[[19~
十六進位制0x1b 0x5b 0x31 0x39 0x7e
第一個位元組0x1b是"^[",第二個位元組0x5b是'[',第3個位元組是0x31,第4位元組就得到'9', 同理,0x39得到'9',最後0x7e是'~'
\033\133\061\071\176
在securecrt做對映時可以使用 "\e[\061\071\176"
↑:
^[[A
^[是第一個位元組0x1b,第二個位元組0x5b是[,最後的0x41是A
0x1b 0x5b 0x41
\033\133\101
Shift + F8:
^[[19;2~
0x1b 0x5b 0x31 0x39 0x3b 0x32 0x7e
"\e[\061\071\073\062\176"
關於控制碼還可以參考:
http://bbs.csdn.net/topics/320015593