Request for help implementing HID protocol in BrailleTouch project #14829
Replies: 29 comments 35 replies
-
Have you read our documentation on braille HID? |
Beta Was this translation helpful? Give feedback.
-
CC @LeonarddeR I'm not sure, but it is possible you might have some knowledge
that would guide this effort in some better direction.
|
Beta Was this translation helpful? Give feedback.
-
This has been the problem we've been facing, and I've been searching for programmers, but none have been able to help because it seems that no one has seen code for HID braille on the braille display (firmware). Would it be necessary to reverse engineer a braille display? Apparently, the part that goes on the screen reader's side (the driver) is known, but no one knows how to do the firmware or the HID part that goes from the braille display side. There is no starting example. It would be a great advancement to have a sample HID braille display code in C that can display braille content on the console and have at least two buttons to navigate through the content. With this code, we could show how to pass buttons and receive and display content on the console. It would be a perfect example for developing anything, but unfortunately, it doesn't exist. I even tried using artificial intelligence to generate code, but it also failed because everyone only works on the code that goes to a controller for making a controller, and AI does the same. |
Beta Was this translation helpful? Give feedback.
-
cc: @FalkoBabbage @discapacidad5 which HID library did you use on your platine? Maybe these sources could help in how to design the class and the internal library on the platine to comunicate with the HiD driver in NVDA or with Windows independently. I guess you need these enhanced libraries for your platine to comunicate via HID efficiently: and this is also very useful since you can specify your own HID classes with your own enums: Does your braille display work already without any screen reader? Or is a screen reader required to use it? This treat might help further in finding some hints for functions required to be written to your HID device in order to comunicate with Windows. |
Beta Was this translation helpful? Give feedback.
-
It seems Helptech from Germany they claim at least some of their braille devices are pure HID devices: |
Beta Was this translation helpful? Give feedback.
-
I guess you already used the HID conventions in this HID usage table right? |
Beta Was this translation helpful? Give feedback.
-
Hi, Hi, I'm sure you may have read through NVDA's own source code, but have you tried looking at HID braille standard file (source/brailleDisplayDrivers/hidBrailleStandard.py) to get a sense of how NVDA understands HID protocol? Thanks. |
Beta Was this translation helpful? Give feedback.
-
The big problem lies in the fact that those who provide explanations and the manufacturers never explain how to send the HiD report. They explain how to interpret it and there are instructions on how to interpret the HiD report to use it on a screen reader to create a driver, but there is no information on how to create or generate the HiD report itself, only its interpretation and structure. Sometimes I think there is a great interest in preventing anyone from understanding this, so that no one can develop a screen that can be compatible with all screen readers. I have always believed that Braille screens end up being a business. They are so expensive and there are ways to make Braille screens so affordable, but if there is no way to communicate with the screen reader, what is the point of manufacturing a screen if it cannot be functional with screen readers or if I have to wait a long time for a custom driver for a screen reader. And of course, if I want to try to bring it to paid readers like Jaws or iPhone or even Android, how long do I have to wait to see if my device driver can be recognized in their device list? The advantage of HiD is precisely that it would give that freedom to play with all this and start designing, testing and evaluating Braille screens that work without waiting for a custom driver for a screen reader. Having a working sample code would open the doors to many projects that could use HiD to offer more accessible devices to people with disabilities. Today, people with disabilities are not using Braille precisely because of the cost of the devices and only first-world countries that have the capacity or whose governments donate the devices have the ability to have a Braille screen. The rest of the people in the world do not have that possibility, and that is the vast majority. |
Beta Was this translation helpful? Give feedback.
-
Sorry if I am being dummy...
The HID protocol is not only for USB devices?
If you say that
ESP32 only supports Bluetooth, you should not devellop a specific driver for your Braille display?
Rui Fontes
Às 21:16 de 15/04/2023, discapacidad5 escreveu:
… "In the case of the projects you mentioned, such as the Android HID project and USBD-Human-Interface, they provide HID support only for USB devices and do not work with Bluetooth devices. In my case, I am facing a problem with the ESP32, which does not have native USB support for HID Braille. I can only work with it through Bluetooth.
However, as I mentioned before, the problem is not that the computer does not recognize the device as HID. The problem is that NVDA, or more specifically HID Braille, has a specific structure to define the cells and many other things, which is not the same as the structures for a keyboard or a mouse. These libraries that convert HID do not have a structure for HID Braille. Therefore, even if I manually change the descriptor and add the HID and Braille descriptor, the computer recognizes it but the screen reader does not, because there are many things that are not properly structured.
That's why it is necessary to create a specific library for HID Braille or add HID Braille support to the existing library."
|
Beta Was this translation helpful? Give feedback.
-
@discapacidad5 I am totally with you, sometimes big players announce a lot of things such as standards but often they are not being thought to the end. Especially when it comes to guidance on how to achieve them. I am not total expert, but it seems you have found some how a way to design your in report and now you need an out report for the report descriptor. Is this correct? So can you already send key presses to an application in Windows without any screen reader? Anyway, I found a good tutorial on how to create a USB report descriptor, it defines in general how to create it for some usual examples like gamepads and mouse. Now we have to find examples for some code that describes a report descriptor for bluetooth devices and then for a HID braille device. And here is a tutorial which shows how to create custom HID devices with custom report descriptors in circuitpython. I could find an usage file that has been approved from Microsoft for the HID standard, I guess this is the filtered information from the table that I have already posted above. It could make it easier to find here all the relevant info without having to scroll through the whole HID conventions: @discapacidad5 did you already try the win-hid-dump tool to extract the propper HID report descriptor for the custom device? I guess this will give you an in report rather than an out report but might be worthy to try. Then you could use a report descriptor decoder such as this one to create C structures: |
Beta Was this translation helpful? Give feedback.
-
I found on stack overflow a code example for sending and receiving data on a custom HID device, but not sure if it works:
A couple of things to note: Source: https://stackoverflow.com/questions/21606991/custom-hid-device-hid-report-descriptor |
Beta Was this translation helpful? Give feedback.
-
@discapacidad5 did you raise your questions on this forum ast well? I have the impression there could be some really good experts that can help further in this regard. |
Beta Was this translation helpful? Give feedback.
-
For anyone's reference, here is an example of a bluetooth device that uses the Gatt profile to comunicate with the host: It also describes how a report descriptor for a bluetooth device could look like. |
Beta Was this translation helpful? Give feedback.
-
And here is a complete report descriptor for a smart remote which might also help. |
Beta Was this translation helpful? Give feedback.
-
Finally, here is some more Info on how HID input and output can works between HID device and host, here is a dualshock game controller as an example:. |
Beta Was this translation helpful? Give feedback.
-
"Thank you for all the information you've sent, I will look into it to see if I can achieve something. However, I have seen many examples and have actually been able to make a HID device work. There are many examples of how a HID device works and there are libraries that do the job. But what I have noticed is that even if you have a HID device configured, it does not work with the screen reader. In fact, key presses on the HID Braille device do not go directly to the operating system like on a normal keyboard. The key presses are captured by the screen reader. Currently, the operating system does not recognize the HID Braille to work with it directly. That is the big problem. That's why I mentioned that it's not about just passing examples. There are many examples, but it's about making an example that works with HID Braille. When you start working on it, you realize that existing examples do not work with HID Braille because it's not enough to be recognized by the computer. It has to carry certain structures that the screen reader must recognize. All key presses have to go to the screen reader, and the screen reader looks for the desktop in a specific location. Therefore, both the input and output go to the screen reader, and the screen reader processes it. I will analyze all the examples you sent, but even those that claim to provide an example of a descriptor do so theoretically. No one has done it in practice. The theory is not enough when thinking about how HID works. Braille input is a bit different and requires certain different operating parameters. I encourage you to try to make a functional code that can receive the content of Braille and can be recognized by the screen reader, not just recognized by the operating system, as that can already be done. There are already libraries that help with that, and you simply need to load the library to be automatically recognized. But it's not enough to be recognized by the operating system. The goal is to make the screen reader recognize the HID Braille, and that's where we are falling short. There is a part of the code that is missing, something needs to be done, and there are some parameters that are not being set. Therefore, the screen reader is not recognizing it, and that's the unclear part. Everyone explains it theoretically, but no one provides a practical example. Sometimes, a practical example is necessary to understand." |
Beta Was this translation helpful? Give feedback.
-
Hi, Hmmm, even after reading NVDA's own source code? If yes, then we might as well discuss how we (NVDA folks) can make our source code better so others can understand what's going on, because when discussing HID and screen readers, NVDA's own HID standard implementation is the closest we have to seeing the protocol in action. As long as a screen reader (or some assistive tech software) is running, the screen reader will process input before anyone can do so, and that also involves understanding input coming from a braille display as communicated by its driver. In case of HID, HID input is first processed by the screen reader, therefore the screen reader's job is to parse protocol messages from the braille device and translate it into actual input mechanism the operating system supports. As for actually writing support for a braille display, yes, it involves looking at or asking for basic protocol documentation, and lots of debugging to get it right (more so if one wishes to support multiple models). The last time I did something with braille input and output, I have added support for specific models of HumanWare BrailleNote family, involving different models and input styles. This work involved printing protocol messages sent by the braille display, mapping messages into a form that could be understood by NVDA (key mappings, for example), and getting NVDA to recognize specific input and perform commands and/or send the equivalent command to the operating system. As for braille and HID, what makes it a bit difficult is that the input side is not seen as a typical keyboard - it ic akin to a controller or a specialized input device. If we're dealing with a computer keyboard, then it is better to get the OS/keyboard driver to recognize the input and do whatever it needs to do. But we're talking about an input style that cannot be readily translated into scan codes and virtual key codes (that's how Windows knows about keyboard input), thus the screen reader is involved in:
In other words, the way the term "human interface device" is understood, interpreted, and implemented differs based on who you ask:
As a repository for screen reader development, we fall under the last category, with some folks wearing different hats. Hope all of this makes sense. Thanks. |
Beta Was this translation helpful? Give feedback.
-
Unless there could be a Standard Windows driver that translates the commands from the braille display into windows standard Input, without having a screen reader. I was hoping USB-IF would have thought about this before shouding out such a standard promising that HID braille displays would work without a screen reader. I think still the example that comes nearest to a Braille input / output interpretation is a dualshock game controler as a HID device. Those have input mapings that need to match some how to keyboard and mouse, and they have output mappings such as vibrations to indicate something which has been sent from the HID host to the HID device.
This could be done via a custom hid miniport driver. Here are all the classes supported so far, but I think Microsoft didn't think of Braille driver API as an own class, so it could be a good start to also talk with them about how to create a custom HID Miniport Driver for Braille Input and Output. |
Beta Was this translation helpful? Give feedback.
-
Hi, A completely different direction, but have you looked at BRLTTY and see how it can serve as a bridge between different braille displays and screen readers? Yes, different braille displays implement different protocols, and some have standardized around a common set of messages (protocols) i.e. Baum protocol (talking about braille display protocols will require looking at a history of braille display development for the last twenty years or so). Thanks. |
Beta Was this translation helpful? Give feedback.
-
BRLTTY causes many conflicts between screen readers, for example when Narator and braille displays are added via BRLTTY, some of the braille displays are totally overtaken by Narator ynd you cannot find them in NVDA's menu anymore. I had this problem with an user here in Germany and the solution was to remove BRLTTY and all the Braille drivers from Narator. After that the Braille displays appeared again in NVDA's menu and they have been recognized automatically again. |
Beta Was this translation helpful? Give feedback.
-
Hello, I've also been wanting to do something similar. I have used RP2040 and programmed it using Micropython. Even I have been facing issue in implementing it as Braille HID device. @discapacidad5 It would be great to know if you found out a way on how it's done. I'm very new to this HID thing and it's quiet honestly getting very complicated for me to understand. |
Beta Was this translation helpful? Give feedback.
-
I have looked at implementing a hid braille display with a RP2040 as well last week since I was tagged in this discussion and I am relatively interested in HID devices in general. I'll see if I can make some time this week to see if I can make a minimal example and put it online. |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
Hi there, Thanks again for sharing your progress and the specific issue you're facing with receiving the Braille data on your ESP32 BLE HID project. It's definitely an interesting challenge, and getting it working would be a great step for the community interested in this topic here on GitHub. To help troubleshoot this effectively as a group, understanding the exact state of your code is the most crucial first step. Collaborative problem-solving works best when we can all look at the same code that's producing the behavior. Request for Current Code & Details: Could you please share the current version of the relevant code snippets from your project? Seeing the code that is running right now when you observe the uint64_t (single character) issue would be extremely helpful. This would ideally include: Your actual onWrite callback function (wherever it resides – likely in KeyboardCallbacks or a similar class – handling data received from the screen reader). Any modifications to how the BLE characteristic for the Output report is defined or handled. The essential parts of your main .ino sketch showing initialization. Key setup details (ESP32 board model, library versions like NimBLE, Arduino core version). Analysis and Potential Solution Based on Previously Shared Code: Looking back at the KeyboardDevice.cpp code you shared earlier from your fork, there's a specific point in the KeyboardCallbacks::onWrite function that stands out as a likely cause if your current code is still similar:
If your current onWrite function uses getValue<uint64_t>() or getValue<uint8_t>() or any method that reads only a small, fixed number of bytes, it would explain why you're not seeing the full 40 bytes expected from the Braille Output report (which your HID descriptor correctly defines). The uint64_t value would just be the first 8 bytes interpreted as a number. Suggestion to Try: Based on this analysis, if your current onWrite code resembles the above, consider modifying it to read the entire data buffer sent by the host. A standard way to do this with NimBLE is using getLength() and getData():
Moving Forward Together: Please share your current code snippets and setup details. This is the most important step for accurate group diagnosis. Please also try the suggested change in your onWrite function (using getData()/getLength()) if your current code uses a method like getValue<uint64_t>() that reads limited bytes. Crucially, please report back! Share the results of trying the suggested fix. Share the modified code, whether the fix worked or not. If it didn't work, having your current code + the tried modification will give us the best information to figure out the next steps together. Integrating the Solution: Since you're already working within a fork (ESP32-BLE-BrailleHID) based on the ESP32-BLE-CompositeHID library, it would be highly beneficial for everyone if the Braille implementation was structured cleanly. Instead of modifying KeyboardDescriptors.h and KeyboardDevice.cpp directly, consider creating new, dedicated files like BrailleDescriptors.h (containing your Braille HID report descriptor) and BrailleDevice.cpp (containing the specific logic for handling Braille input/output, including the corrected onWrite callback). This approach would cleanly separate the Braille functionality within the composite HID framework. If your changes and fixes work, structuring them this way could bring us much closer to having a definitive, reusable BLE Braille HID solution for the ESP32 that benefits the whole community. That's why sharing the details of what you've done, the specific ESP32 code causing the issue (but which was successfully recognized!), and any subsequent fixes is so important for our collective progress. We're keen to collaborate and crack this BLE Braille HID puzzle. Your detailed feedback and code sharing are key! |
Beta Was this translation helpful? Give feedback.
-
Hi That's fantastic progress! Thank you so much for sharing the update, the code snippet, and the output log. It's really exciting to see you're now receiving the full 41 bytes from the screen reader. Excellent work refactoring the code into dedicated BrailleDevice and BrailleDescriptors files as well – that makes things much cleaner for future integration! Regarding the data interpretation challenge: what you're describing and the hex output you shared look very familiar and promising! I've been working extensively with Braille screen reader data received via serial connections, and I've managed to decode the messages successfully in that context. While HID is a different transport layer, the fundamental data structure sent by the screen reader for the Braille cells should be very similar, if not identical. Your observation about receiving 41 bytes, where the first byte is 0x40 (the Report ID you defined!), is exactly correct. This confirms the HID report structure is working as intended, and the actual Braille cell data (the 40 bytes you care about) starts from the second byte (data[1] in your code snippet). The hex data you posted (40DD00..., 401D00..., etc.) looks very much like the raw cell data I've seen over serial. Regarding the constant stream and interpretation: You mentioned the binary conversion doesn't seem to match the announcement directly yet (except for the simple "aaaaaa" test with an offset). This is also something I've encountered. Here are a few points based on my serial experience that might apply here: Constant Updates: Screen readers often send the entire Braille line (all 40 cells in your case) very frequently, even if only a small part of the screen changes or just the cursor blinks. Cursor Blinking: A very common pattern is seeing the same 40 bytes of cell data sent twice in quick succession, with only one difference: the cursor dots (usually dots 7 and 8) toggling on/off in one specific cell. If you see data streams like: 40 ... [cell data with cursor off] ... 40 ... [cell data with cursor on] ... 40 ... [cell data with cursor off] ... VoiceOver Specifics: VoiceOver (especially on macOS) might have its own quirks in how it represents certain states or characters compared to, say, NVDA. The "offset" you found for "aaaaaa" might be a clue related to this. Decoding might require specific mapping tables or handling rules. How I Can Help: Since I have the decoding logic worked out for serial data, and the raw hex data you're receiving via HID looks so similar, I'm quite confident we can figure out the final interpretation step. The most effective way forward would be if I could run your current code directly on my ESP32 test setup. This would allow me to: See the exact hex output (Serial.printf("%02X", data[i]);) you are getting. Simultaneously see what VoiceOver (or NVDA) is announcing on my end. Apply my existing decoding knowledge directly to the HID data stream you're receiving. This would let me give you much more precise feedback on how to map those bytes (data[1] to data[40]) to the actual Braille dots and characters. We've been trying to achieve reliable BLE Braille HID for a long time, and it feels like you're incredibly close! Would you be willing to ensure your GitHub repo (jwlilly/ESP32-BLE-BrailleHID) is fully up-to-date with the exact code that produced the log output you shared? If so, I can clone it, flash it, and hopefully help crack the final decoding piece together. Thanks again for your work and for sharing the progress! Let's get this solved. |
Beta Was this translation helpful? Give feedback.
-
Following up on the idea of creating separate files for the Braille functionality ( However, when I try to compile a basic sketch using this new
The error points specifically to the line It seems like this Because of this compilation error, I'm currently unable to build and test the code to try and replicate the original output data issue you were seeing (receiving only partial data/single character) or test potential fixes like adjusting the Could you perhaps take a look at your Getting past this compilation hurdle is the necessary first step so we can properly test the setup and work together on resolving the data interpretation problem. Thanks for your help! |
Beta Was this translation helpful? Give feedback.
-
Thanks again for sharing your work on the ESP32-BLE-BrailleHID project and the updates! I've cloned your latest changes and tried running the Braille example provided (examples/BrailleExample/BrailleExample.ino). I made sure to install the "Callback" library dependency as well. The good news is that the code compiles successfully in the Arduino IDE without any errors. However, I'm running into an issue where the ESP32 doesn't seem to be advertising itself over Bluetooth. I've checked using BLE scanner apps on my Android phone and also looked for it in the Bluetooth devices list on my PC, but it doesn't appear in either case. I wanted to check if I might be missing any additional configuration steps beyond just using the example code as-is. Are there any specific board settings, NimBLE configurations (like in menuconfig if not using standard Arduino IDE, although I am), or other prerequisites needed that aren't mentioned in the README? Or could there potentially be something in the current library code preventing the advertising from starting correctly? I just wanted to confirm if I'm using the exact same setup/code as you intended for this example. Any insights you might have would be greatly appreciated! Thanks, |
Beta Was this translation helpful? Give feedback.
-
Have you tried using the keyboard code from the library you saw to see if
it gives the same error? I think it would be good to try the original code
before searching to see if it has the same problem. If you don't have it we
could look for a solution from it. What was the code you forked from?
El mié., 16 abr. 2025 3:07 p. m., John Lilly ***@***.***>
escribió:
… I get a similar issue. It won't pick up on Android, but if you use the nRF
Connect app, you can bond it with it. On Windows, iOS, and macOS, I can
connect to it, but it doesn't advertise the expected name until it is
bonded. On macOS, it is identified as "Bluetooth Device". I think on
Windows, it is advertised as just "Input" if I'm not mistaken.
Sorry, I forgot to mention that problem. I had the same problem with the
project I forked from and haven't dug into that yet. It seems that the name
isn't getting added to the advertisement data for some reason.
—
Reply to this email directly, view it on GitHub
<#14829 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACL5OJVAFC7J5C4ALRAHPVL2Z2TAHAVCNFSM6AAAAABNJPWWNOVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTEOBVHA4TAMY>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
-
I was looking for drivers on nbda for HID and they don't really take the
name into account and it's very likely that on Android they won't either
because they look for devices connected by USB in principle. I think it
has more to do with the name of the manufacturer and another code related
to the developer and I think it would be an alternative to get a braille
display that connects via HB pair.
I don't have one anymore, I would have solved that problem a long time ago
because with a braille display you could understand how it works. That's
why we've been working on trial and error tests all this time, but we're
going to get there. I still haven't gotten him to send me any
texts.However, you have managed to get me to answer something on Windows
and on iPhone. I don't have an iPhone, but I will try to see how I can get
some answers on Windows.
El mié., 16 abr. 2025 4:54 p. m., John Lilly ***@***.***>
escribió:
… I'll give that a shot! Thank you! In the mean time, this is what I got
"HID" from for the device name:
https://github.com/google/talkback/blob/26a27dc009d5b3605e744222541f045a3c24e038/braille/brltty/src/phone/java/com/google/android/accessibility/braille/brltty/SupportedDevicesHelper.java#L539
It seems that Android is filtering known devices and applying the
communication methods using what I guess is the name of the device. But
there may be more to it. Do you have access to a Braille HID device that
actually connects to Android using HID? We could attempt to emulate the
device data if so. And now that I'm looking at the TalkBack source a little
closer, it specifies this in a comment above the line I linked:
// HID devices
// The keys match the key set in
// //depot/google3/third_party/brltty/Drivers/Braille/HID/brldefs-hid.h;rcl=626237007;l=16`
I'm not sure what brldefs-hid.h contains, but if that file is public, it
might help us figure out the Android piece.
—
Reply to this email directly, view it on GitHub
<#14829 (reply in thread)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ACL5OJVN6HDFNSLK2TGPU532Z27SHAVCNFSM6AAAAABNJPWWNOVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTEOBVHE3DONA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Hello,
I hope this message finds you well. I am reaching out to you because I am working on an open-source project called BrailleTouch. Our goal is to create affordable Braille displays for blind and deaf-blind individuals.
We are currently stuck and unable to get the HID Braille to receive information from the screen reader and continue programming. As someone with experience in this area, your expertise could be of great help to our project.
I believe that an open-source Braille display could be incredibly useful and have many benefits for those who are blind and deaf-blind. Your knowledge of the HID protocol could be particularly helpful in implementing the protocol in our Braille display.
Please take a moment to review our project on GitHub at https://github.com/brailletouch. If you're interested in helping, please let me know.
Thank you for your time and consideration. I look forward to hearing back from you.
Best regards,
Cergio Monasterio
Beta Was this translation helpful? Give feedback.
All reactions