Improve how keyboard is determined

This commit is contained in:
Andrew Kay 2023-01-10 23:30:39 -06:00
parent 2581b7bc6f
commit 074ffce9ed
11 changed files with 126 additions and 51 deletions

View File

@ -7,7 +7,7 @@ from coax import open_serial_interface, TerminalType
from .interface import InterfaceWrapper
from .controller import Controller
from .device import get_ids, get_features, UnsupportedDeviceError
from .device import get_ids, get_features, get_keyboard_description, UnsupportedDeviceError
from .terminal import Terminal
from .tn3270 import TN3270Session
@ -19,9 +19,9 @@ if os.name == 'posix':
IS_VT100_AVAILABLE = True
from .keymap_3278_2 import KEYMAP as KEYMAP_3278_2
from .keymap_3483 import KEYMAP as KEYMAP_3483
from .keymap_3483_102 import KEYMAP as KEYMAP_3483_102
from .keymap_3278_typewriter import KEYMAP as KEYMAP_3278_TYPEWRITER
from .keymap_ibm_typewriter import KEYMAP as KEYMAP_IBM_TYPEWRITER
from .keymap_ibm_enhanced import KEYMAP as KEYMAP_IBM_ENHANCED
logging.basicConfig(level=logging.INFO)
@ -29,19 +29,15 @@ logger = logging.getLogger('oec.main')
CONTROLLER = None
def _get_keymap(terminal_id, extended_id):
keymap = KEYMAP_3278_2
def _get_keymap(keyboard_description):
if keyboard_description.startswith('3278'):
return KEYMAP_3278_TYPEWRITER
elif keyboard_description.startswith('IBM-TYPEWRITER'):
return KEYMAP_IBM_TYPEWRITER
elif keyboard_description.startswith('IBM-ENHANCED'):
return KEYMAP_IBM_ENHANCED
if extended_id == 'c1348300':
keymap = KEYMAP_3483
if extended_id == 'c1348301':
keymap = KEYMAP_3483_102
if extended_id == 'c1347200':
keymap = KEYMAP_3483
return keymap
return KEYMAP_3278_TYPEWRITER
def _get_character_encoding(encoding):
try:
@ -55,18 +51,23 @@ def _create_device(args, interface, device_address, poll_response):
# Read the terminal identifiers.
(terminal_id, extended_id) = get_ids(interface, device_address)
logger.info(f'Terminal ID = {terminal_id}, Extended ID = {extended_id}')
logger.info(f'Terminal ID = {terminal_id}')
logger.info(f'Extended ID = {extended_id}')
if terminal_id.type != TerminalType.CUT:
raise UnsupportedDeviceError('Only CUT type terminals are supported')
keyboard_description = get_keyboard_description(terminal_id, extended_id)
logger.info(f'Keyboard = {keyboard_description}')
# Read the terminal features.
features = get_features(interface, device_address)
logger.info(f'Features = {features}')
# Get the keymap.
keymap = _get_keymap(terminal_id, extended_id)
keymap = _get_keymap(keyboard_description)
logger.info(f'Keymap = {keymap.name}')

View File

@ -111,6 +111,65 @@ def get_features(interface, device_address):
return parse_features(ids, commands)
def get_keyboard_description(terminal_id, extended_id):
is_3278 = extended_id is None or not int(extended_id[0:2], 16) & 0x80
if is_3278:
description = '3278'
id_map = {
0b0001: 'APL',
0b0010: 'TEXT',
0b0100: 'TYPEWRITER-PSHICO',
0b0101: 'APL',
0b0110: 'TEXT',
0b0111: 'APL-PSHICO',
0b1000: 'DATAENTRY-2',
0b1001: 'DATAENTRY-1',
0b1010: 'TYPEWRITER',
0b1100: 'DATAENTRY-2',
0b1101: 'DATAENTRY-1',
0b1110: 'TYPEWRITER'
}
if terminal_id.keyboard in id_map:
description += '-' + id_map[terminal_id.keyboard]
return description
id_ = int(extended_id[0:2], 16) & 0x1f
is_user = int(extended_id[0:2], 16) & 0x20
if is_user:
description = 'USER'
if id_ in [1, 2, 3, 4]:
description += f'-{id_}'
return description
is_ibm = not int(extended_id[6:8], 16) & 0x80
description = 'IBM' if is_ibm else 'UNKNOWN'
is_enhanced = int(extended_id[6:8], 16) & 0x01
if is_enhanced:
if id_ == 1:
return description + '-ENHANCED'
return None
if id_ == 1:
return description + '-TYPEWRITER'
elif id_ == 2:
return description + '-DATAENTRY'
elif id_ == 3:
return description + '-APL'
return None
def _jumbo_write_split_data(data, max_length, first_chunk_max_length_adjustment=-1):
if max_length is None:
return [data]

View File

@ -1,6 +1,6 @@
"""
oec.keymap_3278_2
~~~~~~~~~~~~~~~~~
oec.keymap_3278_typewriter
~~~~~~~~~~~~~~~~~~~~~~~~~~
"""
from .keyboard import Key, Keymap
@ -198,4 +198,4 @@ MODIFIER_RELEASE_MAP = {
207: Key.RIGHT_ALT
}
KEYMAP = Keymap('3278-2', KEYMAP_DEFAULT, KEYMAP_SHIFT, KEYMAP_ALT, MODIFIER_RELEASE_MAP)
KEYMAP = Keymap('3278 Typewriter', KEYMAP_DEFAULT, KEYMAP_SHIFT, KEYMAP_ALT, MODIFIER_RELEASE_MAP)

View File

@ -1,13 +1,10 @@
"""
oec.keymap_3483_102
~~~~~~~~~~~~~~~
oec.keymap_ibm_enhanced
~~~~~~~~~~~~~~~~~~~~~~~
"""
from .keyboard import Key, Keymap
# I have a 5250 keyboard for my 3483-V, this mapping is based on photographs
# of the 3270 keyboard and may not be correct.
KEYMAP_DEFAULT = {
# Function Keys
7: Key.PF1,
@ -240,4 +237,4 @@ KEYMAP_ALT = {
106: Key.RIGHT_2
}
KEYMAP = Keymap('3483_102', KEYMAP_DEFAULT, KEYMAP_SHIFT, KEYMAP_ALT, modifier_release=240)
KEYMAP = Keymap('IBM Enhanced', KEYMAP_DEFAULT, KEYMAP_SHIFT, KEYMAP_ALT, modifier_release=240)

View File

@ -1,13 +1,10 @@
"""
oec.keymap_3483
~~~~~~~~~~~~~~~
oec.keymap_ibm_typewriter
~~~~~~~~~~~~~~~~~~~~~~~~~
"""
from .keyboard import Key, Keymap
# I have a 5250 keyboard for my 3483-V, this mapping is based on photographs
# of the 3270 keyboard and may not be correct.
KEYMAP_DEFAULT = {
# Function Keys
7: Key.PF1,
@ -235,4 +232,4 @@ KEYMAP_ALT = {
106: Key.RIGHT_2
}
KEYMAP = Keymap('3483', KEYMAP_DEFAULT, KEYMAP_SHIFT, KEYMAP_ALT, modifier_release=240)
KEYMAP = Keymap('IBM Typewriter', KEYMAP_DEFAULT, KEYMAP_SHIFT, KEYMAP_ALT, modifier_release=240)

View File

@ -8,7 +8,7 @@ from coax.protocol import TerminalId
import context
from oec.interface import InterfaceWrapper
from oec.device import address_commands, format_address, get_ids, get_features, _jumbo_write_split_data
from oec.device import address_commands, format_address, get_ids, get_features, get_keyboard_description, _jumbo_write_split_data
from mock_interface import MockInterface
@ -161,6 +161,27 @@ class GetFeaturesTestCase(unittest.TestCase):
# Assert
self.assertEqual(features, { Feature.EAB: 7 })
class GetKeyboardDescriptionTestCase(unittest.TestCase):
def test(self):
CASES = [
(10, None, '3278-TYPEWRITER'),
(0, 'c1347200', 'IBM-TYPEWRITER'),
(10, '41347200', '3278-TYPEWRITER'),
(0, 'c2347200', 'IBM-DATAENTRY'),
(0, 'c3347200', 'IBM-APL'),
(0, 'c1348301', 'IBM-ENHANCED'),
(0, 'e1347200', 'USER-1'),
(0, 'e4347200', 'USER-4')
]
for (keyboard, extended_id, expected_description) in CASES:
with self.subTest(keyboard=keyboard, extended_id=extended_id):
terminal_id = TerminalId(0b0000_0100 | (keyboard << 4))
description = get_keyboard_description(terminal_id, extended_id)
self.assertEqual(description, expected_description)
class JumboWriteSplitDataTestCase(unittest.TestCase):
def test_no_split_strategy(self):
for data in [bytes(range(0, 64)), (bytes.fromhex('00'), 64)]:

View File

@ -9,7 +9,7 @@ import context
from oec.interface import InterfaceWrapper
from oec.terminal import Terminal
from oec.display import Display, Dimensions, StatusLine, BufferedDisplay, encode_character, encode_string
from oec.keymap_3278_2 import KEYMAP as KEYMAP_3278_2
from oec.keymap_3278_typewriter import KEYMAP
from mock_interface import MockInterface
@ -833,7 +833,7 @@ def _create_display(interface):
terminal_id = TerminalId(0b11110100)
extended_id = 'c1348300'
features = { }
keymap = KEYMAP_3278_2
keymap = KEYMAP
terminal = Terminal(InterfaceWrapper(interface), None, terminal_id, extended_id, features, keymap)
@ -845,7 +845,7 @@ def _create_buffered_display(interface, has_eab=False):
terminal_id = TerminalId(0b11110100)
extended_id = 'c1348300'
features = { Feature.EAB: 7 } if has_eab else { }
keymap = KEYMAP_3278_2
keymap = KEYMAP
terminal = Terminal(InterfaceWrapper(interface), None, terminal_id, extended_id, features, keymap)

View File

@ -3,8 +3,8 @@ import unittest
import context
from oec.keyboard import KeyboardModifiers, Key, Keymap, Keyboard, get_character_for_key
from oec.keymap_3278_2 import KEYMAP as KEYMAP_3278_2
from oec.keymap_3483 import KEYMAP as KEYMAP_3483
from oec.keymap_3278_typewriter import KEYMAP as KEYMAP_3278_TYPEWRITER
from oec.keymap_ibm_typewriter import KEYMAP as KEYMAP_IBM_TYPEWRITER
class KeyboardModifiersTestCase(unittest.TestCase):
def test_is_shift(self):
@ -39,7 +39,7 @@ class KeyboardModifiersTestCase(unittest.TestCase):
class KeyboardGetKeySingleModifierReleaseTestCase(unittest.TestCase):
def setUp(self):
self.keyboard = Keyboard(KEYMAP_3483)
self.keyboard = Keyboard(KEYMAP_IBM_TYPEWRITER)
def test_single_modifier_release_is_true(self):
self.assertTrue(self.keyboard.single_modifier_release)
@ -120,13 +120,13 @@ class KeyboardGetKeySingleModifierReleaseTestCase(unittest.TestCase):
self._assert_get_key(240, None, KeyboardModifiers.NONE, False)
self._assert_get_key(20, None, KeyboardModifiers.NONE, False)
self._assert_get_key(36, Key.LOWER_E, KeyboardModifiers.NONE, False)
def _assert_get_key(self, scan_code, key, modifiers, modifiers_changed):
self.assertEqual(self.keyboard.get_key(scan_code), (key, modifiers, modifiers_changed))
class KeyboardGetKeyMultipleModifierReleaseTestCase(unittest.TestCase):
def setUp(self):
self.keyboard = Keyboard(KEYMAP_3278_2)
self.keyboard = Keyboard(KEYMAP_3278_TYPEWRITER)
def test_single_modifier_release_is_false(self):
self.assertFalse(self.keyboard.single_modifier_release)
@ -196,7 +196,7 @@ class KeyboardGetKeyMultipleModifierReleaseTestCase(unittest.TestCase):
self._assert_get_key(76, Key.CAPS_LOCK, KeyboardModifiers.NONE, True)
self._assert_get_key(204, None, KeyboardModifiers.NONE, False)
self._assert_get_key(100, Key.LOWER_E, KeyboardModifiers.NONE, False)
def _assert_get_key(self, scan_code, key, modifiers, modifiers_changed):
self.assertEqual(self.keyboard.get_key(scan_code), (key, modifiers, modifiers_changed))

View File

@ -9,7 +9,7 @@ from oec.interface import InterfaceWrapper
from oec.device import UnsupportedDeviceError
from oec.terminal import Terminal
from oec.display import Display, StatusLine
from oec.keymap_3278_2 import KEYMAP as KEYMAP_3278_2
from oec.keymap_3278_typewriter import KEYMAP
from mock_interface import MockInterface
@ -19,7 +19,7 @@ class InitTerminalTestCase(unittest.TestCase):
terminal_id = TerminalId(0b11110100)
# Act
Terminal(None, None, terminal_id, None, { }, KEYMAP_3278_2)
Terminal(None, None, terminal_id, None, { }, KEYMAP)
def test_unsupported_terminal_model(self):
# Arrange
@ -29,7 +29,7 @@ class InitTerminalTestCase(unittest.TestCase):
# Act and assert
with self.assertRaises(UnsupportedDeviceError):
Terminal(None, None, terminal_id, None, { }, KEYMAP_3278_2)
Terminal(None, None, terminal_id, None, { }, KEYMAP)
class TerminalSetupTestCase(unittest.TestCase):
def setUp(self):
@ -79,7 +79,7 @@ def _create_terminal(interface):
terminal_id = TerminalId(0b11110100)
extended_id = 'c1348300'
features = { }
keymap = KEYMAP_3278_2
keymap = KEYMAP
terminal = Terminal(InterfaceWrapper(interface), None, terminal_id, extended_id, features, keymap)

View File

@ -12,7 +12,7 @@ from oec.interface import InterfaceWrapper
from oec.terminal import Terminal
from oec.display import Dimensions, BufferedDisplay, StatusLine
from oec.keyboard import Key, KeyboardModifiers
from oec.keymap_3278_2 import KEYMAP as KEYMAP_3278_2
from oec.keymap_3278_typewriter import KEYMAP
from oec.session import SessionDisconnectedError
from oec.tn3270 import TN3270Session
@ -396,7 +396,7 @@ def _create_terminal(interface):
terminal_id = TerminalId(0b11110100)
extended_id = 'c1348300'
features = { }
keymap = KEYMAP_3278_2
keymap = KEYMAP
terminal = Terminal(InterfaceWrapper(interface), None, terminal_id, extended_id, features, keymap)

View File

@ -11,7 +11,7 @@ from oec.interface import InterfaceWrapper
from oec.terminal import Terminal
from oec.display import Dimensions, BufferedDisplay
from oec.keyboard import Key, KeyboardModifiers
from oec.keymap_3278_2 import KEYMAP as KEYMAP_3278_2
from oec.keymap_3278_typewriter import KEYMAP
from oec.session import SessionDisconnectedError
from oec.vt100 import VT100Session
@ -183,7 +183,7 @@ def _create_terminal(interface):
terminal_id = TerminalId(0b11110100)
extended_id = 'c1348300'
features = { }
keymap = KEYMAP_3278_2
keymap = KEYMAP
terminal = Terminal(InterfaceWrapper(interface), None, terminal_id, extended_id, features, keymap)