From 7e9af8247a3bfc7a70e70f0e9a8d71c3e3e71aef Mon Sep 17 00:00:00 2001 From: Matthew Hooker Date: Thu, 19 Apr 2018 17:02:39 -0700 Subject: [PATCH] fix 2 byte scancodes for pc-xt VMs. --- common/bootcommand/pc_xt_driver.go | 112 +++++++++++++----------- common/bootcommand/pc_xt_driver_test.go | 18 +++- 2 files changed, 78 insertions(+), 52 deletions(-) diff --git a/common/bootcommand/pc_xt_driver.go b/common/bootcommand/pc_xt_driver.go index 8b6a75d92..7aca80852 100644 --- a/common/bootcommand/pc_xt_driver.go +++ b/common/bootcommand/pc_xt_driver.go @@ -14,17 +14,27 @@ import ( // SendCodeFunc will be called to send codes to the VM type SendCodeFunc func([]string) error +type scMap map[string]*scancode type pcXTDriver struct { interval time.Duration sendImpl SendCodeFunc - specialMap map[string][]string + specialMap scMap scancodeMap map[rune]byte buffer [][]string // TODO: set from env scancodeChunkSize int } +type scancode struct { + make []string + break_ []string +} + +func (sc *scancode) makeBreak() []string { + return append(sc.make, sc.break_...) +} + // NewPCXTDriver creates a new boot command driver for VMs that expect PC-XT // keyboard codes. `send` should send its argument to the VM. `chunkSize` should // be the maximum number of keyboard codes to send to `send` at one time. @@ -41,44 +51,44 @@ func NewPCXTDriver(send SendCodeFunc, chunkSize int) *pcXTDriver { // Scancodes are recorded here in pairs. The first entry represents // the key press and the second entry represents the key release and is // derived from the first by the addition of 0x80. - sMap := make(map[string][]string) - sMap["bs"] = []string{"0e", "8e"} - sMap["del"] = []string{"e053", "e0d3"} - sMap["down"] = []string{"e050", "e0d0"} - sMap["end"] = []string{"e04f", "e0cf"} - sMap["enter"] = []string{"1c", "9c"} - sMap["esc"] = []string{"01", "81"} - sMap["f1"] = []string{"3b", "bb"} - sMap["f2"] = []string{"3c", "bc"} - sMap["f3"] = []string{"3d", "bd"} - sMap["f4"] = []string{"3e", "be"} - sMap["f5"] = []string{"3f", "bf"} - sMap["f6"] = []string{"40", "c0"} - sMap["f7"] = []string{"41", "c1"} - sMap["f8"] = []string{"42", "c2"} - sMap["f9"] = []string{"43", "c3"} - sMap["f10"] = []string{"44", "c4"} - sMap["f11"] = []string{"57", "d7"} - sMap["f12"] = []string{"58", "d8"} - sMap["home"] = []string{"e047", "e0c7"} - sMap["insert"] = []string{"e052", "e0d2"} - sMap["left"] = []string{"e04b", "e0cb"} - sMap["leftalt"] = []string{"38", "b8"} - sMap["leftctrl"] = []string{"1d", "9d"} - sMap["leftshift"] = []string{"2a", "aa"} - sMap["leftsuper"] = []string{"e05b", "e0db"} - sMap["menu"] = []string{"e05d", "e0dd"} - sMap["pagedown"] = []string{"e051", "e0d1"} - sMap["pageup"] = []string{"e049", "e0c9"} - sMap["return"] = []string{"1c", "9c"} - sMap["right"] = []string{"e04d", "e0cd"} - sMap["rightalt"] = []string{"e038", "e0b8"} - sMap["rightctrl"] = []string{"e01d", "e09d"} - sMap["rightshift"] = []string{"36", "b6"} - sMap["rightsuper"] = []string{"e05c", "e0dc"} - sMap["spacebar"] = []string{"39", "b9"} - sMap["tab"] = []string{"0f", "8f"} - sMap["up"] = []string{"e048", "e0c8"} + sMap := make(scMap) + sMap["bs"] = &scancode{[]string{"0e"}, []string{"8e"}} + sMap["del"] = &scancode{[]string{"e0", "53"}, []string{"e0", "d3"}} + sMap["down"] = &scancode{[]string{"e0", "50"}, []string{"e0", "d0"}} + sMap["end"] = &scancode{[]string{"e0", "4f"}, []string{"e0", "cf"}} + sMap["enter"] = &scancode{[]string{"1c"}, []string{"9c"}} + sMap["esc"] = &scancode{[]string{"01"}, []string{"81"}} + sMap["f1"] = &scancode{[]string{"3b"}, []string{"bb"}} + sMap["f2"] = &scancode{[]string{"3c"}, []string{"bc"}} + sMap["f3"] = &scancode{[]string{"3d"}, []string{"bd"}} + sMap["f4"] = &scancode{[]string{"3e"}, []string{"be"}} + sMap["f5"] = &scancode{[]string{"3f"}, []string{"bf"}} + sMap["f6"] = &scancode{[]string{"40"}, []string{"c0"}} + sMap["f7"] = &scancode{[]string{"41"}, []string{"c1"}} + sMap["f8"] = &scancode{[]string{"42"}, []string{"c2"}} + sMap["f9"] = &scancode{[]string{"43"}, []string{"c3"}} + sMap["f10"] = &scancode{[]string{"44"}, []string{"c4"}} + sMap["f11"] = &scancode{[]string{"57"}, []string{"d7"}} + sMap["f12"] = &scancode{[]string{"58"}, []string{"d8"}} + sMap["home"] = &scancode{[]string{"e0", "47"}, []string{"e0", "c7"}} + sMap["insert"] = &scancode{[]string{"e0", "52"}, []string{"e0", "d2"}} + sMap["left"] = &scancode{[]string{"e0", "4b"}, []string{"e0", "cb"}} + sMap["leftalt"] = &scancode{[]string{"38"}, []string{"b8"}} + sMap["leftctrl"] = &scancode{[]string{"1d"}, []string{"9d"}} + sMap["leftshift"] = &scancode{[]string{"2a"}, []string{"aa"}} + sMap["leftsuper"] = &scancode{[]string{"e0", "5b"}, []string{"e0", "db"}} + sMap["menu"] = &scancode{[]string{"e0", "5d"}, []string{"e0", "dd"}} + sMap["pagedown"] = &scancode{[]string{"e0", "51"}, []string{"e0", "d1"}} + sMap["pageup"] = &scancode{[]string{"e0", "49"}, []string{"e0", "c9"}} + sMap["return"] = &scancode{[]string{"1c"}, []string{"9c"}} + sMap["right"] = &scancode{[]string{"e0", "4d"}, []string{"e0", "cd"}} + sMap["rightalt"] = &scancode{[]string{"e0", "38"}, []string{"e0", "b8"}} + sMap["rightctrl"] = &scancode{[]string{"e0", "1d"}, []string{"e0", "9d"}} + sMap["rightshift"] = &scancode{[]string{"36"}, []string{"b6"}} + sMap["rightsuper"] = &scancode{[]string{"e0", "5c"}, []string{"e0", "dc"}} + sMap["spacebar"] = &scancode{[]string{"39"}, []string{"b9"}} + sMap["tab"] = &scancode{[]string{"0f"}, []string{"8f"}} + sMap["up"] = &scancode{[]string{"e0", "48"}, []string{"e0", "c8"}} scancodeIndex := make(map[string]byte) scancodeIndex["1234567890-="] = 0x02 @@ -132,28 +142,28 @@ func (d *pcXTDriver) Flush() error { func (d *pcXTDriver) SendKey(key rune, action KeyAction) error { keyShift := unicode.IsUpper(key) || strings.ContainsRune(shiftedChars, key) - var scancode []string + var sc []string if action&(KeyOn|KeyPress) != 0 { - scancodeInt := d.scancodeMap[key] + scInt := d.scancodeMap[key] if keyShift { - scancode = append(scancode, "2a") + sc = append(sc, "2a") } - scancode = append(scancode, fmt.Sprintf("%02x", scancodeInt)) + sc = append(sc, fmt.Sprintf("%02x", scInt)) } if action&(KeyOff|KeyPress) != 0 { - scancodeInt := d.scancodeMap[key] + 0x80 + scInt := d.scancodeMap[key] + 0x80 if keyShift { - scancode = append(scancode, "aa") + sc = append(sc, "aa") } - scancode = append(scancode, fmt.Sprintf("%02x", scancodeInt)) + sc = append(sc, fmt.Sprintf("%02x", scInt)) } log.Printf("Sending char '%c', code '%s', shift %v", - key, strings.Join(scancode, ""), keyShift) + key, strings.Join(sc, ""), keyShift) - d.send(scancode) + d.send(sc) return nil } @@ -166,11 +176,11 @@ func (d *pcXTDriver) SendSpecial(special string, action KeyAction) error { switch action { case KeyOn: - d.send([]string{keyCode[0]}) + d.send(keyCode.make) case KeyOff: - d.send([]string{keyCode[1]}) + d.send(keyCode.break_) case KeyPress: - d.send(keyCode) + d.send(keyCode.makeBreak()) } return nil } diff --git a/common/bootcommand/pc_xt_driver_test.go b/common/bootcommand/pc_xt_driver_test.go index b3a3c94ea..eb4ac621f 100644 --- a/common/bootcommand/pc_xt_driver_test.go +++ b/common/bootcommand/pc_xt_driver_test.go @@ -71,7 +71,7 @@ func Test_chunkScanCodeError(t *testing.T) { assert.Error(t, err) } -func Test_pcxtSpecialLookup(t *testing.T) { +func Test_pcxtSpecialOnOff(t *testing.T) { in := "" expected := []string{"36", "b6", "b6", "36"} var codes []string @@ -87,6 +87,22 @@ func Test_pcxtSpecialLookup(t *testing.T) { assert.Equal(t, expected, codes) } +func Test_pcxtSpecial(t *testing.T) { + in := "" + expected := []string{"0e", "4b", "e0", "cb"} + var codes []string + sendCodes := func(c []string) error { + codes = c + return nil + } + d := NewPCXTDriver(sendCodes, -1) + seq, err := GenerateExpressionSequence(in) + assert.NoError(t, err) + err = seq.Do(context.Background(), d) + assert.NoError(t, err) + assert.Equal(t, expected, codes) +} + func Test_flushes(t *testing.T) { in := "abc123098" expected := [][]string{