Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native driver for Freedom Scientific displays #8853

Merged
merged 59 commits into from May 21, 2019
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
c1784f0
Attempt to create a new hwIo class for USB bulk devices
Sep 25, 2017
dd6fae5
Merge branch 'bulk' into freedomscientific-native
bramd Sep 25, 2017
20da169
Native driver for Freedom Scientific braille displays, work in progre…
bramd Sep 25, 2017
882a307
Key and extended key handling
bramd Sep 27, 2017
52f041e
Merge remote-tracking branch 'upstream/master' into freedomscientific…
bramd Sep 28, 2017
bff76e8
Add support for routing and second row of buttons on older Focus/Pacm…
bramd Oct 1, 2017
2bddae8
Merge remote-tracking branch 'upstream/master' into freedomscientific…
bramd Oct 14, 2017
f17a225
Properly implement Freedom Scientific displays connected via Bluetooth
bramd Oct 14, 2017
a4b647a
Merge remote-tracking branch 'upstream/master' into freedomscientific…
bramd Oct 24, 2017
685d360
Fix output on Focus series 1 (44/70/84), improve initialization
bramd Oct 24, 2017
fd7e914
Add USB VID/PID for Focus/PAC mate displays
bramd Nov 4, 2017
e37038a
Code documentation and cleanup
bramd Nov 4, 2017
d49a493
Merge remote-tracking branch 'upstream/master' into freedomscientific…
bramd Nov 4, 2017
d60639f
Fix typo in br(breedomscientific]:leftBumerbarUp gesture. Fix merged …
bramd Nov 4, 2017
331e13d
Mark brailleDisplayDrivers/freedomScientific.py as UTF-8
bramd Nov 4, 2017
2249037
Fixed reference from numCells to self.numCells
bramd Nov 8, 2017
f54e54e
Merge branch 'master' into freedomscientific-native
bramd Aug 4, 2018
cef92d2
Enable auto detection of Freedom Scientific braille displays
bramd Aug 5, 2018
d783b49
Some code cleanup
bramd Aug 5, 2018
8364932
Fix mistake in display initialization introduced in the previous comm…
bramd Aug 5, 2018
4a50975
Fix key handling if multiple keys are released at the same time
bramd Aug 5, 2018
5ad6818
Don't set _awaitingAck manually in display method
bramd Aug 5, 2018
d0f6e6e
Merge branch 'master' into freedomscientific-native
bramd Sep 8, 2018
a3fb229
Merge remote-tracking branch 'upstream/master' into freedomscientific…
bramd Sep 29, 2018
4f4d6ce
Merge remote-tracking branch 'upstream/master' into freedomscientific…
bramd Oct 13, 2018
363ea52
Code cleanup
bramd Oct 14, 2018
224bdca
The Focus displays seem to switch to USB as soon as a USB cable is co…
bramd Oct 14, 2018
2194af1
The Focus displays seem to switch to USB as soon as a USB cable is co…
bramd Oct 14, 2018
4125f0f
Update UserGuide:Freedom Scientific displays support auto detection
bramd Oct 15, 2018
318439b
Add key bindings for win+tab and alt+shift+tab
bramd Oct 15, 2018
4a2020c
Support model specific gestures
bramd Oct 17, 2018
9da6213
Use self.timeout instead of the TIMEOUTconstant
bramd Oct 17, 2018
2422b3d
Review comment:use BytesIO instead of StringIO
bramd Oct 21, 2018
50c8a89
Handle bumper keys correctly (#8849)
bramd Oct 21, 2018
3cae439
Merge remote-tracking branch 'origin/master' into freedomscientific-n…
Dec 18, 2018
7baac86
Get rid of heavily confusing _resumeDetection method on the braille h…
Dec 18, 2018
78bdc84
Additional clarifying comment
Dec 18, 2018
f5984e4
Respect limitToDevices when bluetooth polling or when a rescan is tri…
Dec 18, 2018
82d2120
Also respect a dedetector without bluetooth when a new device is added
Dec 18, 2018
e43fa7a
Merge remote-tracking branch 'upstream/master' into freedomscientific…
bramd Dec 27, 2018
1b7f7f3
Merge pull request #2 from leonardder/freedomChanges
bramd Dec 27, 2018
4a5f6c7
Fix double and
Dec 27, 2018
1778224
Fix top routing for Focus 2nd generation
Dec 27, 2018
7b29486
Improve python 3 compat
Dec 27, 2018
06d7efc
Make a constant for TOP_ROUTING_KEY_GROUP
Dec 27, 2018
0eccac8
isTopRow now treates the keygroup as a boolean. It looks like key gro…
Dec 27, 2018
bd6384d
Merge remote-tracking branch 'origin/master' into freedomscientific-n…
Mar 5, 2019
a88f6d9
Fixed issues in braille module
Mar 5, 2019
1719423
Review actions for bdDetect
Mar 25, 2019
72ce2f1
Merge remote-tracking branch 'origin/master' into freedomscientific-n…
Mar 25, 2019
f411a43
Review actions
bramd Mar 31, 2019
9beffd1
Use FS_BYTE_NULL instead of FS_DATA_EMPTY in string replacement for m…
bramd Apr 10, 2019
99cbc02
Use constants for offsets in INFO packet
bramd Apr 13, 2019
90447e1
Fix documentation ans usage of special translation table for Focus 1
bramd Apr 13, 2019
1545299
Improve documentation
bramd May 4, 2019
52dc60b
Documentation and code clarification.
feerrenrut May 6, 2019
2869c9e
Update source/brailleDisplayDrivers/freedomScientific.py
feerrenrut May 20, 2019
4cd583c
Merge pull request #3 from nvaccess/freedomscientific-native
bramd May 20, 2019
dc2913b
Merge remote-tracking branch 'upstream/master' into freedomscientific…
bramd May 20, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 31 additions & 11 deletions source/bdDetect.py
Expand Up @@ -163,7 +163,7 @@ class Detector(object):
This should only be used by the L{braille} module.
"""

def __init__(self):
def __init__(self, usb=True, bluetooth=True, limitToDevices=None):
bramd marked this conversation as resolved.
Show resolved Hide resolved
self._BgScanApc = winKernel.PAPCFUNC(self._bgScan)
self._btDevsLock = threading.Lock()
self._btDevs = None
Expand All @@ -172,11 +172,12 @@ def __init__(self):
self._stopEvent = threading.Event()
self._queuedScanLock = threading.Lock()
self._scanQueued = False
self._detectUsb = False
self._detectBluetooth = False
self._detectUsb = usb
self._detectBluetooth = bluetooth
self._limitToDevices = limitToDevices
self._runningApcLock = threading.Lock()
# Perform initial scan.
self._startBgScan(usb=True, bluetooth=True)
self._startBgScan(usb=usb, bluetooth=bluetooth, limitToDevices=limitToDevices)

@property
def _scanQueuedSafe(self):
Expand All @@ -190,10 +191,11 @@ def _scanQueuedSafe(self, state):
with self._queuedScanLock:
self._scanQueued = state

def _startBgScan(self, usb=False, bluetooth=False):
def _startBgScan(self, usb=False, bluetooth=False, limitToDevices=None):
bramd marked this conversation as resolved.
Show resolved Hide resolved
with self._queuedScanLock:
self._detectUsb = usb
self._detectBluetooth = bluetooth
self._limitToDevices = limitToDevices
if not self._scanQueued:
self._scanQueued = True
if self._runningApcLock.locked():
Expand Down Expand Up @@ -224,11 +226,12 @@ def _bgScan(self, param):
self._scanQueued = False
detectUsb = self._detectUsb
detectBluetooth = self._detectBluetooth
limitToDevices = self._limitToDevices
if detectUsb:
if self._stopEvent.isSet():
continue
for driver, match in getDriversForConnectedUsbDevices():
if self._stopEvent.isSet():
if self._stopEvent.isSet() or (self._limitToDevices and driver not in self._limitToDevices):
continue
if braille.handler.setDisplayByName(driver, detected=match):
return
Expand All @@ -244,7 +247,7 @@ def _bgScan(self, param):
btDevs = self._btDevs
btDevsCache = btDevs
for driver, match in btDevs:
if self._stopEvent.isSet():
if self._stopEvent.isSet() or (self._limitToDevices and driver not in self._limitToDevices):
continue
if btDevsCache is not btDevs:
btDevsCache.append((driver, match))
Expand All @@ -256,25 +259,28 @@ def _bgScan(self, param):
with self._btDevsLock:
self._btDevs = btDevsCache

def rescan(self):
def rescan(self, usb=True, bluetooth=True, limitToDevices=None):
bramd marked this conversation as resolved.
Show resolved Hide resolved
"""Stop a current scan when in progress, and start scanning from scratch."""
self._stopBgScan()
with self._btDevsLock:
# A Bluetooth com port or HID device might have been added.
self._btDevs = None
self._startBgScan(usb=True, bluetooth=True)
self._startBgScan(usb=usb, bluetooth=bluetooth, limitToDevices=limitToDevices)

def handleWindowMessage(self, msg=None, wParam=None):
if msg == WM_DEVICECHANGE and wParam == DBT_DEVNODES_CHANGED:
self.rescan()
self.rescan(bluetooth=self._detectBluetooth, limitToDevices=self._limitToDevices)

def pollBluetoothDevices(self):
"""Poll bluetooth devices that might be in range.
This does not cancel the current scan."""
if not self._detectBluetooth:
# Do not poll bluetooth devices at all when bluetooth is disabled.
return
with self._btDevsLock:
if not self._btDevs:
return
self._startBgScan(bluetooth=True)
self._startBgScan(bluetooth=self._detectBluetooth, limitToDevices=self._limitToDevices)

def terminate(self):
appModuleHandler.post_appSwitch.unregister(self.pollBluetoothDevices)
Expand Down Expand Up @@ -466,6 +472,20 @@ def driverSupportsAutoDetection(driver):

addBluetoothDevices("eurobraille", lambda m: m.id.startswith("Esys"))

# freedomScientific
addUsbDevices("freedomScientific", KEY_CUSTOM, {
"VID_0F4E&PID_0100", # Focus 1
"VID_0F4E&PID_0111", # PAC Mate
"VID_0F4E&PID_0112", # Focus 2
"VID_0F4E&PID_0114", # Focus Blue
})

addBluetoothDevices("freedomScientific", lambda m: any(m.id.startswith(prefix) for prefix in (
"F14", "Focus 14 BT",
"Focus 40 BT",
"Focus 80 BT",
)))

# handyTech
addUsbDevices("handyTech", KEY_SERIAL, {
"VID_0403&PID_6001", # FTDI chip
Expand Down
31 changes: 15 additions & 16 deletions source/braille.py
Expand Up @@ -1669,8 +1669,11 @@ def setDisplayByName(self, name, isFallback=False, detected=None):
self.display = newDisplay
self.displaySize = newDisplay.numCells
self.enabled = bool(self.displaySize)
if isFallback:
self._resumeDetection()
if isFallback and self._detectionEnabled:
# As this is the fallback display, which is usually noBraille,
# we can keep the current display when enabling detection.
# Note that in this case, L{_detectionEnabled} is set by L{handleDisplayUnavailable}
self.__enableDetection(keepCurrentDisplay=True)
elif not detected:
config.conf["braille"]["display"] = name
else: # detected:
Expand All @@ -1684,6 +1687,8 @@ def setDisplayByName(self, name, isFallback=False, detected=None):
# We should handle this more gracefully, since this is no reason
# to stop a display from loading successfully.
log.debugWarning("Error in initial display after display load", exc_info=True)
if detected and 'bluetoothName' in detected.deviceInfo:
self._enableDetection(bluetooth=False, keepCurrentDisplay=True, limitToDevices=[name])
return True
except:
# For auto display detection, logging an error for every failure is too obnoxious.
Expand Down Expand Up @@ -1990,18 +1995,20 @@ def handleDisplayUnavailable(self):
log.error("Braille display unavailable. Disabling", exc_info=True)
self._detectionEnabled = config.conf["braille"]["display"] == AUTO_DISPLAY_NAME
self.setDisplayByName("noBraille", isFallback=True)

def _enableDetection(self):
def _enableDetection(self, usb=True, bluetooth=True, keepCurrentDisplay=False, limitToDevices=None):
"""Enables automatic detection of braille displays.
When auto detection is already active, this will force a rescan for devices.
This should also be executed when auto detection should be resumed due to loss of display connectivity.
"""
if self._detectionEnabled and self._detector:
self._detector.rescan()
self._detector.rescan(usb=usb, bluetooth=bluetooth, limitToDevices=limitToDevices)
return
_BgThread.start()
config.conf["braille"]["display"] = AUTO_DISPLAY_NAME
self.setDisplayByName("noBraille", isFallback=True)
self._detector = bdDetect.Detector()
if not keepCurrentDisplay:
config.conf["braille"]["display"] = AUTO_DISPLAY_NAME
self.setDisplayByName("noBraille", isFallback=True)
self._detector = bdDetect.Detector(usb=usb, bluetooth=bluetooth, limitToDevices=limitToDevices)
self._detectionEnabled = True

def _disableDetection(self):
Expand All @@ -2013,14 +2020,6 @@ def _disableDetection(self):
self._detector = None
self._detectionEnabled = False

def _resumeDetection(self):
"""Resumes automatic detection of braille displays.
This is executed when auto detection should be resumed due to loss of display connectivity.
"""
if not self._detectionEnabled or self._detector:
return
self._detector = bdDetect.Detector()

class _BgThread:
"""A singleton background thread used for background writes and raw braille display I/O.
"""
Expand Down