diff --git a/oec/__main__.py b/oec/__main__.py index 3012449..c1169cf 100644 --- a/oec/__main__.py +++ b/oec/__main__.py @@ -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}') diff --git a/oec/device.py b/oec/device.py index 6c65cf8..47211a4 100644 --- a/oec/device.py +++ b/oec/device.py @@ -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] diff --git a/oec/keymap_3278_2.py b/oec/keymap_3278_typewriter.py similarity index 95% rename from oec/keymap_3278_2.py rename to oec/keymap_3278_typewriter.py index a3727f8..4b30298 100644 --- a/oec/keymap_3278_2.py +++ b/oec/keymap_3278_typewriter.py @@ -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) diff --git a/oec/keymap_3483_102.py b/oec/keymap_ibm_enhanced.py similarity index 94% rename from oec/keymap_3483_102.py rename to oec/keymap_ibm_enhanced.py index 9b45eb8..bd6e059 100644 --- a/oec/keymap_3483_102.py +++ b/oec/keymap_ibm_enhanced.py @@ -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) diff --git a/oec/keymap_3483.py b/oec/keymap_ibm_typewriter.py similarity index 94% rename from oec/keymap_3483.py rename to oec/keymap_ibm_typewriter.py index 46fae36..8d70533 100644 --- a/oec/keymap_3483.py +++ b/oec/keymap_ibm_typewriter.py @@ -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) diff --git a/tests/test_device.py b/tests/test_device.py index 5cd3bf2..692fa5a 100644 --- a/tests/test_device.py +++ b/tests/test_device.py @@ -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)]: diff --git a/tests/test_display.py b/tests/test_display.py index 70abf50..88869a2 100644 --- a/tests/test_display.py +++ b/tests/test_display.py @@ -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) diff --git a/tests/test_keyboard.py b/tests/test_keyboard.py index 86d2e3a..ec880ed 100644 --- a/tests/test_keyboard.py +++ b/tests/test_keyboard.py @@ -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)) diff --git a/tests/test_terminal.py b/tests/test_terminal.py index fe5cbc8..03decb0 100644 --- a/tests/test_terminal.py +++ b/tests/test_terminal.py @@ -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) diff --git a/tests/test_tn3270.py b/tests/test_tn3270.py index 31331b1..febb701 100644 --- a/tests/test_tn3270.py +++ b/tests/test_tn3270.py @@ -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) diff --git a/tests/test_vt100.py b/tests/test_vt100.py index 3016b12..eb31474 100644 --- a/tests/test_vt100.py +++ b/tests/test_vt100.py @@ -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)