如何与蓝牙键盘对话?

发布于 2024-10-04 06:34:36 字数 868 浏览 2 评论 0原文

我编写了一个连接蓝牙键盘的 Android 应用程序。它通过 BT 套接字连接到键盘并获取套接字的输入流。

InputStream inStrm = socket.getInputStream();

接下来我尝试读取输入流,但它说没有可用的字节。

int nBytesAvail = inStrm.available(); // always gives me 0

或者

int  dataByte = inStrm.read(); // always generates IOException

异常显示:软件导致连接中止

如果我尝试写入流,则会收到另一个异常:传输端点未连接。

可能会发生两件事之一。

  1. 我的第一个担心是 HID 协议需要与键盘对话,并且在我说出正确的咒语之前它不会泄露其秘密。这是正确的吗?或者应该由 BT 套接字堆栈自动处理?套接字流似乎是一个标准的串行流,我不确定这是正确的。

  2. 我的第二个担心是,由于这是 Galaxy Tab,我的问题可能只是操作系统的特定部分已被三星删除(但我仍然可以从套接字连接获得有效的输入流吗?)。据广泛报道,美国版本的 Tab 根本无法使用标准 Android BT 实用程序连接到任何 BT HID,尽管 BT 文件传输确实可以正常工作。

我想第三种可能性是我只是错过了击键发生的情况。我不知道 Java 对来自 HID 的 BT 数据做了多少缓冲,但如果建立了套接字连接,数据应该出现在输入流中,不是吗?

我不愿意投入更多的时间,以防万一我完全以错误的方式处理它(参见#1),或者它注定会失败(参见#2)。

I've written an Android app that connects to a Bluetooth keyboard. It connects through a BT socket to the keyboard and acquires the socket's input stream.

InputStream inStrm = socket.getInputStream();

Next I tried to read the input stream, but it says there are no bytes available.

int nBytesAvail = inStrm.available(); // always gives me 0

Or

int  dataByte = inStrm.read(); // always generates IOException

The exception says: Software caused connection to abort

If I try to write to the stream, I get another exception: Transport endpoint is not connected.

One of two things can be happening.

  1. My first fear is that there is the HID protocol to be spoken to the keyboard, and it will not divulge its secrets until I utter the proper incantation. Is that correct? Or should that be taken care of by the BT socket stack automatically? The socket stream seems to be a standard serial stream, and I'm not sure that's correct.

  2. My second fear is that since this is a Galaxy Tab, my problem might simply be that that particular part of the OS has been removed by Samsung (but would I still get a valid input stream from the socket connection?). It is widely reported that the US versions of the Tab simply will not connect to any BT HID using the standard Android BT utilities, although BT file transfers do work fine.

I suppose a third possibility is that I'm simply missing the keystrokes as they happen. I don't know how much buffering Java does of BT data coming in from a HID, but if the socket connection is made, the data should appear in the input stream, no?

I'm reluctant to put in much more time into this in case I'm going about it completely the wrong way (see #1), or it is doomed to fail (see #2).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

沩ん囻菔务 2024-10-11 06:34:36

所有普通蓝牙键盘均实现 HID 配置文件,这需要 L2CAP 连接。 Android 到目前为止仅提供使用 RFCOMM 连接的能力。您需要使用本机开发套件并用 C 语言编写键盘代码以使用 bluez 来实现您的目标。查看使用 Nintendo WiiMote 的应用程序。 WiiMote 还实现了 HID 配置文件。

All normal Bluetooth keyboards implement the HID profile, which requires an L2CAP connection. Android so far only provides the ability to use RFCOMM connections. You would need to use the Native Development Kit and write your keyboard code in C to using bluez to achieve your goal. Have a look at apps that use the Nintendo WiiMote. The WiiMote also implements the HID profile.

甜味超标? 2024-10-11 06:34:36

mringwal的答案是正确的,除了NDK方法之外,还可以在某些设备上使用反射来实现L2CAP连接:

public static BluetoothSocket createL2CAPBluetoothSocket(String address, int psm){
        return createBluetoothSocket(TYPE_L2CAP, -1, false,false, address, psm);
    }
    // method for creating a bluetooth client socket
    private static BluetoothSocket createBluetoothSocket(
            int type, int fd, boolean auth, boolean encrypt, String address, int port){
        try {
            Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(
                    int.class, int.class,boolean.class,boolean.class,String.class, int.class);
            constructor.setAccessible(true);
            BluetoothSocket clientSocket = (BluetoothSocket) 
                constructor.newInstance(type,fd,auth,encrypt,address,port);
            return clientSocket;
        }catch (Exception e) { return null; }
    }

其中TYPE_L2CAP是一个具有常量值3的整数

。请注意,这种方法仅适用于某些android设备。

编写 HID 应用程序并不是一项简单的任务。您需要实现一个报告描述符解析器,该组件用于“发现”远程 HID 设备的功能(特殊键、功能)。
您还需要学习 HID 协议和工作流程,可在此处获取副本:
http://www.dawidurbanski.pl/public/download/projekty/bluepad /HID_SPEC_V10.pdf

已经有专业程序可以做到这一点,支持 Android 上的 HID,例如,请参阅此软件:http://teksoftco.com/index.php?section=product&pid=24

由于堆栈限制,L2CAP 协议并非在所有设备上都可用,因此解决方案目前不可能在所有设备上运行。

mringwal's answer is correct, besides the NDK approach, it is possible to use reflection on some devices, to achieve L2CAP connectivity:

public static BluetoothSocket createL2CAPBluetoothSocket(String address, int psm){
        return createBluetoothSocket(TYPE_L2CAP, -1, false,false, address, psm);
    }
    // method for creating a bluetooth client socket
    private static BluetoothSocket createBluetoothSocket(
            int type, int fd, boolean auth, boolean encrypt, String address, int port){
        try {
            Constructor<BluetoothSocket> constructor = BluetoothSocket.class.getDeclaredConstructor(
                    int.class, int.class,boolean.class,boolean.class,String.class, int.class);
            constructor.setAccessible(true);
            BluetoothSocket clientSocket = (BluetoothSocket) 
                constructor.newInstance(type,fd,auth,encrypt,address,port);
            return clientSocket;
        }catch (Exception e) { return null; }
    }

where TYPE_L2CAP is an integer having the constant value 3.

Note that this approach will only work on SOME android devices.

Writing a HID application is not a simple task. You need to implement a Report descriptor parser, a component used to "discover" the capabilities (special keys, functions) of a remote HID device.
You will also need to learn the HID protocol and work flow , a copy is available here:
http://www.dawidurbanski.pl/public/download/projekty/bluepad/HID_SPEC_V10.pdf

There are already professional programs doing exactly that, supporting HID on Android, see for example this software: http://teksoftco.com/index.php?section=product&pid=24

Because of Stack limitations, the L2CAP protocol is not available on all devices, so a solution that works on ALL devices is currently impossible.

吐个泡泡 2024-10-11 06:34:36

有些 Galaxy Tab 支持 HID 协议,有些则不支持。这取决于运营商,而不是三星。我的 Verizon Galaxy Tab 没有 HID 支持,尽管 T-Mobile 有 HID 支持。但今年 4 月,Verizon(不是三星)推出了固件升级,其中包括 HID 支持,因此我的 BT 键盘和蓝牙键盘可以使用。鼠标开始工作。我运行的是 Android 2.2,固件版本号是 SCH-I800.EC02。

我猜测您尝试执行此操作是因为您的 Tab 根本无法连接到 BT 键盘。这正是我在四月份之前想做的事情。据我记得读过的内容,魔法咒语部分应该由 Android 自动处理:当您进行 HID 连接时,Android 会弹出一个消息窗口,在键盘上输入代码,然后将套接字连接返回给您的程序(或类似的东西)。

因此,如果您无法让 Tab 正常连接到键盘,那么您的 HID 配置文件已被禁用,并且(据我所知)无论进行多少编程都无法使其正常工作,除非用 Java 重写 HID 配置文件。

我确信您已经尝试过此操作,但要测试它,请转到“设置”>“无线和网络>蓝牙设置中,无论您是否支持 HID,您都应该在列表中看到键盘。点击键盘输入,它应该立即连接。如果它只是无限期地延迟或者您收到错误消息,那么您就没有 HID 支持。

Some Galaxy Tabs support the HID protocol, some don't. It depends on the carrier, not on Samsung. My Verizon Galaxy Tab came without HID support even though the T-Mobile ones had it. But in April of this year Verizon (not Samsung) pushed out a firmware upgrade that included HID support so my BT keyboard & mouse started working. I'm running Android 2.2, and my firmware build number is SCH-I800.EC02.

It's my guess that you're trying to do this because your Tab won't connect to the BT keyboard at all. This is exactly what I was trying to do before April. From what I remember reading, the magic incantation part is supposed to be handled by Android automatically: when you make the HID connection, Android pops up a message window to enter a code on the keyboard, then the socket connection is returned to your program (or something to that effect).

So if you can't get the Tab to connect to the keyboard normally, then your HID profile has been disabled and (afaik) no amount of programming will make it work, except maybe a rewrite of the HID profile in Java.

I'm sure you tried this already, but to test it go to Settings > Wireless and Networks > Blutetooth settings, you should see the keyboard in the list whether or not you have HID support. Tap the keyboard entry, it should connect right away. If it just delays indefinitely or if you get an error message, then you have no HID support.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文