-
-
Notifications
You must be signed in to change notification settings - Fork 678
/
Copy pathsuperBrl.py
112 lines (98 loc) · 2.99 KB
/
superBrl.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# A part of NonVisual Desktop Access (NVDA)
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
# Copyright (C) 2017-2023 NV Access Limited, Coscell Kao, Babbage B.V.
from typing import List
import serial
import bdDetect
import braille
import hwIo
from hwIo import intToByte
import time
import inputCore
from logHandler import log
BAUD_RATE = 9600
TIMEOUT = 0.5
# Tags sent by the SuperBraille
# Sent to identify the display and receive amount of cells this unit has
DESCRIBE_TAG = b"\xff\xff\x0a"
# Sent to request displaying of cells
DISPLAY_TAG = b"\xff\xff\x04\x00\x99\x00\x50\x00"
class BrailleDisplayDriver(braille.BrailleDisplayDriver):
name = "superBrl"
# Translators: Names of braille displays.
description = _("SuperBraille")
isThreadSafe = True
supportsAutomaticDetection = True
@classmethod
def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
driverRegistrar.addUsbDevices(
bdDetect.ProtocolType.SERIAL,
{
"VID_10C4&PID_EA60", # SuperBraille 3.2
},
)
@classmethod
def getManualPorts(cls):
return braille.getSerialPorts()
def __init__(self, port="Auto"):
super(BrailleDisplayDriver, self).__init__()
for portType, portId, port, portInfo in self._getTryPorts(port):
try:
self._dev = hwIo.Serial(
port,
baudrate=BAUD_RATE,
stopbits=serial.STOPBITS_ONE,
parity=serial.PARITY_NONE,
timeout=TIMEOUT,
writeTimeout=TIMEOUT,
onReceive=self._onReceive,
)
except EnvironmentError:
log.debugWarning("", exc_info=True)
continue
# try to initialize the device and request number of cells
self._dev.write(DESCRIBE_TAG)
self._dev.waitForRead(TIMEOUT)
# Check for cell information
if self.numCells:
# ok, it is a SuperBraille
log.info("Found superBraille device, version %s" % self.version)
break
else:
self._dev.close()
else:
raise RuntimeError("No SuperBraille found")
def terminate(self):
try:
super(BrailleDisplayDriver, self).terminate()
finally:
# We must sleep before closing the COM port as not doing this can leave the display in a bad state where it can not be re-initialized
time.sleep(TIMEOUT)
self._dev.close()
self._dev = None
def _onReceive(self, data: bytes):
# The only info this display ever sends is number of cells and the display version.
# It sends 0x00, 0x05, number of cells, then version string of 8 bytes.
if data != b"\x00":
return
data = self._dev.read(1)
if data != b"\x05":
return
self.numCells = ord(self._dev.read(1))
self._dev.read(1)
self.version = self._dev.read(8)
def display(self, cells: List[int]):
writeBytes: List[bytes] = [DISPLAY_TAG]
for cell in cells:
writeBytes.append(b"\x00")
writeBytes.append(intToByte(cell))
self._dev.write(b"".join(writeBytes))
gestureMap = inputCore.GlobalGestureMap(
{
"globalCommands.GlobalCommands": {
"braille_scrollBack": ("kb:numpadMinus",),
"braille_scrollForward": ("kb:numpadPlus",),
},
},
)