fix 2 byte scancodes for pc-xt VMs.

This commit is contained in:
Matthew Hooker 2018-04-19 17:02:39 -07:00
parent 675eae1e92
commit 7e9af8247a
No known key found for this signature in database
GPG Key ID: 7B5F933D9CE8C6A1
2 changed files with 78 additions and 52 deletions

View File

@ -14,17 +14,27 @@ import (
// SendCodeFunc will be called to send codes to the VM // SendCodeFunc will be called to send codes to the VM
type SendCodeFunc func([]string) error type SendCodeFunc func([]string) error
type scMap map[string]*scancode
type pcXTDriver struct { type pcXTDriver struct {
interval time.Duration interval time.Duration
sendImpl SendCodeFunc sendImpl SendCodeFunc
specialMap map[string][]string specialMap scMap
scancodeMap map[rune]byte scancodeMap map[rune]byte
buffer [][]string buffer [][]string
// TODO: set from env // TODO: set from env
scancodeChunkSize int 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 // 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 // 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. // 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 // Scancodes are recorded here in pairs. The first entry represents
// the key press and the second entry represents the key release and is // the key press and the second entry represents the key release and is
// derived from the first by the addition of 0x80. // derived from the first by the addition of 0x80.
sMap := make(map[string][]string) sMap := make(scMap)
sMap["bs"] = []string{"0e", "8e"} sMap["bs"] = &scancode{[]string{"0e"}, []string{"8e"}}
sMap["del"] = []string{"e053", "e0d3"} sMap["del"] = &scancode{[]string{"e0", "53"}, []string{"e0", "d3"}}
sMap["down"] = []string{"e050", "e0d0"} sMap["down"] = &scancode{[]string{"e0", "50"}, []string{"e0", "d0"}}
sMap["end"] = []string{"e04f", "e0cf"} sMap["end"] = &scancode{[]string{"e0", "4f"}, []string{"e0", "cf"}}
sMap["enter"] = []string{"1c", "9c"} sMap["enter"] = &scancode{[]string{"1c"}, []string{"9c"}}
sMap["esc"] = []string{"01", "81"} sMap["esc"] = &scancode{[]string{"01"}, []string{"81"}}
sMap["f1"] = []string{"3b", "bb"} sMap["f1"] = &scancode{[]string{"3b"}, []string{"bb"}}
sMap["f2"] = []string{"3c", "bc"} sMap["f2"] = &scancode{[]string{"3c"}, []string{"bc"}}
sMap["f3"] = []string{"3d", "bd"} sMap["f3"] = &scancode{[]string{"3d"}, []string{"bd"}}
sMap["f4"] = []string{"3e", "be"} sMap["f4"] = &scancode{[]string{"3e"}, []string{"be"}}
sMap["f5"] = []string{"3f", "bf"} sMap["f5"] = &scancode{[]string{"3f"}, []string{"bf"}}
sMap["f6"] = []string{"40", "c0"} sMap["f6"] = &scancode{[]string{"40"}, []string{"c0"}}
sMap["f7"] = []string{"41", "c1"} sMap["f7"] = &scancode{[]string{"41"}, []string{"c1"}}
sMap["f8"] = []string{"42", "c2"} sMap["f8"] = &scancode{[]string{"42"}, []string{"c2"}}
sMap["f9"] = []string{"43", "c3"} sMap["f9"] = &scancode{[]string{"43"}, []string{"c3"}}
sMap["f10"] = []string{"44", "c4"} sMap["f10"] = &scancode{[]string{"44"}, []string{"c4"}}
sMap["f11"] = []string{"57", "d7"} sMap["f11"] = &scancode{[]string{"57"}, []string{"d7"}}
sMap["f12"] = []string{"58", "d8"} sMap["f12"] = &scancode{[]string{"58"}, []string{"d8"}}
sMap["home"] = []string{"e047", "e0c7"} sMap["home"] = &scancode{[]string{"e0", "47"}, []string{"e0", "c7"}}
sMap["insert"] = []string{"e052", "e0d2"} sMap["insert"] = &scancode{[]string{"e0", "52"}, []string{"e0", "d2"}}
sMap["left"] = []string{"e04b", "e0cb"} sMap["left"] = &scancode{[]string{"e0", "4b"}, []string{"e0", "cb"}}
sMap["leftalt"] = []string{"38", "b8"} sMap["leftalt"] = &scancode{[]string{"38"}, []string{"b8"}}
sMap["leftctrl"] = []string{"1d", "9d"} sMap["leftctrl"] = &scancode{[]string{"1d"}, []string{"9d"}}
sMap["leftshift"] = []string{"2a", "aa"} sMap["leftshift"] = &scancode{[]string{"2a"}, []string{"aa"}}
sMap["leftsuper"] = []string{"e05b", "e0db"} sMap["leftsuper"] = &scancode{[]string{"e0", "5b"}, []string{"e0", "db"}}
sMap["menu"] = []string{"e05d", "e0dd"} sMap["menu"] = &scancode{[]string{"e0", "5d"}, []string{"e0", "dd"}}
sMap["pagedown"] = []string{"e051", "e0d1"} sMap["pagedown"] = &scancode{[]string{"e0", "51"}, []string{"e0", "d1"}}
sMap["pageup"] = []string{"e049", "e0c9"} sMap["pageup"] = &scancode{[]string{"e0", "49"}, []string{"e0", "c9"}}
sMap["return"] = []string{"1c", "9c"} sMap["return"] = &scancode{[]string{"1c"}, []string{"9c"}}
sMap["right"] = []string{"e04d", "e0cd"} sMap["right"] = &scancode{[]string{"e0", "4d"}, []string{"e0", "cd"}}
sMap["rightalt"] = []string{"e038", "e0b8"} sMap["rightalt"] = &scancode{[]string{"e0", "38"}, []string{"e0", "b8"}}
sMap["rightctrl"] = []string{"e01d", "e09d"} sMap["rightctrl"] = &scancode{[]string{"e0", "1d"}, []string{"e0", "9d"}}
sMap["rightshift"] = []string{"36", "b6"} sMap["rightshift"] = &scancode{[]string{"36"}, []string{"b6"}}
sMap["rightsuper"] = []string{"e05c", "e0dc"} sMap["rightsuper"] = &scancode{[]string{"e0", "5c"}, []string{"e0", "dc"}}
sMap["spacebar"] = []string{"39", "b9"} sMap["spacebar"] = &scancode{[]string{"39"}, []string{"b9"}}
sMap["tab"] = []string{"0f", "8f"} sMap["tab"] = &scancode{[]string{"0f"}, []string{"8f"}}
sMap["up"] = []string{"e048", "e0c8"} sMap["up"] = &scancode{[]string{"e0", "48"}, []string{"e0", "c8"}}
scancodeIndex := make(map[string]byte) scancodeIndex := make(map[string]byte)
scancodeIndex["1234567890-="] = 0x02 scancodeIndex["1234567890-="] = 0x02
@ -132,28 +142,28 @@ func (d *pcXTDriver) Flush() error {
func (d *pcXTDriver) SendKey(key rune, action KeyAction) error { func (d *pcXTDriver) SendKey(key rune, action KeyAction) error {
keyShift := unicode.IsUpper(key) || strings.ContainsRune(shiftedChars, key) keyShift := unicode.IsUpper(key) || strings.ContainsRune(shiftedChars, key)
var scancode []string var sc []string
if action&(KeyOn|KeyPress) != 0 { if action&(KeyOn|KeyPress) != 0 {
scancodeInt := d.scancodeMap[key] scInt := d.scancodeMap[key]
if keyShift { 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 { if action&(KeyOff|KeyPress) != 0 {
scancodeInt := d.scancodeMap[key] + 0x80 scInt := d.scancodeMap[key] + 0x80
if keyShift { 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", 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 return nil
} }
@ -166,11 +176,11 @@ func (d *pcXTDriver) SendSpecial(special string, action KeyAction) error {
switch action { switch action {
case KeyOn: case KeyOn:
d.send([]string{keyCode[0]}) d.send(keyCode.make)
case KeyOff: case KeyOff:
d.send([]string{keyCode[1]}) d.send(keyCode.break_)
case KeyPress: case KeyPress:
d.send(keyCode) d.send(keyCode.makeBreak())
} }
return nil return nil
} }

View File

@ -71,7 +71,7 @@ func Test_chunkScanCodeError(t *testing.T) {
assert.Error(t, err) assert.Error(t, err)
} }
func Test_pcxtSpecialLookup(t *testing.T) { func Test_pcxtSpecialOnOff(t *testing.T) {
in := "<rightShift><rightshiftoff><RIGHTSHIFTON>" in := "<rightShift><rightshiftoff><RIGHTSHIFTON>"
expected := []string{"36", "b6", "b6", "36"} expected := []string{"36", "b6", "b6", "36"}
var codes []string var codes []string
@ -87,6 +87,22 @@ func Test_pcxtSpecialLookup(t *testing.T) {
assert.Equal(t, expected, codes) assert.Equal(t, expected, codes)
} }
func Test_pcxtSpecial(t *testing.T) {
in := "<left>"
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) { func Test_flushes(t *testing.T) {
in := "abc123<wait>098" in := "abc123<wait>098"
expected := [][]string{ expected := [][]string{