# Bluetooth: investigating dongle use for HID hardware: FreeBSD 13



## sidetone (Jun 8, 2022)

Bluetooth Human Interface Device peripherals are on BTHIDD architecture, rather than UHID, IICHID or USBHID architectures. BTHIDD is based on libusb, so it doesn't have the range of hardware compatibility that USBHID has. HID-over-I2C was by Microsoft, so wasn't supported by Apple, and it isn't as flexible for newer kinds of hardware. IICHID seems to be named from it, and FreeBSD drivers that used it were adapted to USBHID.

Human Interface Device (HID) Support in FreeBSD 13 of July/August 2021 in the FreeBSD Journal, states how work is being done to move bthidd to usrhid. Does this mean, that it still relies on uhid? What's the progress on it for 13.1 or Stable?


I was considering attempting to set up my Bluetooth dongle as much as possible, even if it relies on older drivers, or if the dongle isn't fully supported yet. It has recognized a peripheral device over Bluetooth before in this state. Thinking about it, my only Bluetooth device uses hgame, and a gamepad driver may not be available on uhid. If I use uhid, I'll have to recompile my kernel. I've used this controller before with Antimicro and x11-drivers/xf86-input-joystick on older versions of FreeBSD that didn't have hgame(4).


Bluetooth on FreeBSD works on top of Netgraph, which has many functions and drivers outside of Bluetooth. You can see this by typing `man -k netgraph`.

It's better to have these compiled into the kernel:

```
options    NETGRAPH
options NETGRAPH_SOCKET
options NETGRAPH_BLUETOOTH
options NETGRAPH_BLUETOOTH_SOCKET
```
Without these, there can be minor warning messages about drivers loading after "domainfinalize()". The drivers can also be loaded through `kldload` before plugging in the dongle. Other specific drivers to the dongle's needs that aren't pre-loaded will also be auto-loaded when attaching the hardware.

When attaching dongle:

```
usb_alloc_device: set address 2 failed (USB_ERR_TIMEOUT, ignored)
ugen0.2: <vendor 0x0a12 product 0x0001> at usbus0
ubt0 on uhub0
ubt0: <vendor 0x0a12 product 0x0001, class 224/1, rev 2.00/52.76, addr 9> on usbus0
hardware_error: ubt0hci - hardware error 0x37
```

When detaching dongle:

```
ubt0: ubt_bulk_read_callback:1119: bulk-in transfer failed: USB_ERR_IOERROR
ubt0: ubt_intr_read_callback:1020: interrupt transfer failed: USB_ERR_IOERROR
ugen0.2: <vendor 0x0a12 product 0x0001> at usbus0 (disconnected)
ubt0: at uhub0, port 1, addr 8 (disconnected)
ubt0: detached
```

The Bluetooth dongle's permissions may need to be set up, so other programs have a chance to access it and peripheral potentially connected to it. This will be the hub, and may not be ugen for peripherals connected. Permissions and configurations of peripherals connected to this dongle may need to be set with Bluetooth's drivers as a hub, rather than based on ugen.


```
# testing Bluetooth dongle;
# permissions for /dev/usb/
notify 100 {
        match "system"          "USB";
        match "subsystem"       "DEVICE";
        match "type"            "ATTACH";
        match "vendor"          "0x0a12";
        match "product"         "0x0001";
        action "chgrp wheel /dev/$cdev; chmod 775 /dev/$cdev";
};
```
In this, additional o+rx permissions are added, as well as additional permissions to user and group. Run `service devd restart` to adjust these permissions. This is for testing.

After setting up the bthidd(8) connection with hccontrol(8) (from instructions in https://freebsdfoundation.org/freebsd-project/resources/networking-basics-wifi-and-bluetooth/, and adapted as https://forums.freebsd.org/threads/...oysticks-for-desktop-usbhid.84464/post-570160):

Received this in `dmesg` which occurs from time to time inconsistently:

```
ng_l2cap_lp_discon_ind: ubt0l2cap - unexpected LP_DisconnectInd event. Connection does not exist, con_handle=42
```
No other `dmesg` message has come up than this, and for connecting and reconnecting the dongle.

Then, the device was shown as disconnected:

```
Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State
```


```
hccontrol -n ubt0hci read_connection_list
```

Before, and after reloading the Bluetooth connection, it had:

```
Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State
01:06:8b:5c:61:07     42  ACL    0 MAST    NONE       0     0 OPEN
```

After reconnecting it, tried Antimicro, emulators/joytran, and xev, but no result.

I don't have much more expectations for this on FreeBSD 13.1, which I'm using now, but I wonder if it's possible to make my system go a little further. Looking at comms/hcidump to see about communications between the gamepad and the dongle.


----------



## sidetone (Jun 11, 2022)

I've made some progress for further identifying and configuring connections for Bluetooth HID peripherals. (Select output from commands will be shown. The examples will be of my particular hardware.)


*hccontrol*
`hccontrol -n ubt0hci inquiry`

```
BD_ADDR: 01:06:8b:5c:61:07
```
To simplify configuration, put this BD_ADDR into /etc/bluetooth/hosts:

```
01:06:8b:5c:61:07       gamepad
```
In this, I chose "gamepad". Choose a descriptive name.
Now, when `hccontrol -n ubt0hci inquiry` inquiry is run, the alias is shown:

```
BD_ADDR: gamepad
```
This can be used for `hccontrol` and other Bluetooth commands. Continuing:
`hccontrol -n ubt0hci remote_name_request gamepad`

```
BD_ADDR: gamepad
Name: 8Bitdo FC30 Pro
```
`hccontrol -n ubt0hci inquiry`, then the output shows the BD_ADDRSS, Status, and other information. Use, `hccontrol -n ubt0hci create_connection gamepad`, to connect. Then, `hccontrol -n ubt0hci read_connection_list` will show the status.


*hcsecd*
If a pin or key is needed, edit /etc/bluetooth/hcsecd.conf. An example of this file is at /usr/src/usr.sbin/bluetooth/hcsecd.conf. This configuration is optional for Bluetooth peripherals which don't need a key or pin:

```
device {
        bdaddr  01:06:8b:5c:61:07;
        name    "gamepad";
        key     nokey;
        pin     nopin;
      }
```
This configuration file needs the actual bdaddr, and not the alias. `nokey` and `nopin` needs to be used for peripherals which don't have these. Quotes can be used for specific names. `hcsecd` can be run.


*bthidcontrol*
Then, use bthidcontrol(8). For your bdaddr, the hostname alias can also be used with bthidcontrol.

Run, `bthidcontrol -a gamepad Query`. Here, you'll get an output which can be placed into the end of /etc/bluetooth/bthidd.conf. This output gives the word name of the product, Vendor Id, Product ID, `hid_descriptor` and other information. From this, my gamepad's Vendor ID and Product ID are different than from this same physical controller when connected through a wired USB cable. The other Vendor and Product ID were a match for my gamepad for that type of connection, because using those settings caused the desired effects from it.

`bthidcontrol -a gamepad Dump` gives information about peripheral inputs (useful mapping controls).


*Event output*
xev, joytrans and antimicro didn't show output. However, `hcidump -i ubt0hci` showed events when I pressed controls on my gamepad! Services may have been needed to be started for this to work.


*About HID backends*
Midway through the steps from above, I looked into finding about the progress about the libusb or usbhid backend in FreeBSD 13.1 on my computer, since a previous version of FreeBSD last year.

`libusb` and `usbhid` are in the sourcecode of Bluetooth components in FreeBSD 13.1.

`/usr/sbin % grep libusb [bt]*`

```
Binary file bthidcontrol matches
Binary file bthidd matches
```
`/usr/sbin % grep usbhid [bt]*`

```
Binary file bthidcontrol matches
Binary file bthidd matches
```
`/usr/sbin % grep -i evdev [bt]*`

```
Binary file bthidd matches
```
`usbhid` is in base Makefiles of previous FreeBSD versions for Bluetooth, but it may have been limited to that, for testing.


*Clarifications*
On trying this, my Bluetooth dongle is version 3, which isn't documented as supported. Though, the configuration got this far.

In my first post, I've gotten this gamepad to work with Antimicro and xf86-input-joystick, not as Bluetooth, but with a wired connection on previous versions of FreeBSD.


*Comments*
This would be a howto, but there's a lot of early stage problem solving and questions, for something that's not near complete. From a user's perspective, there's a possibility that Bluetooth over usbhid with hgame(4) could work on FreeBSD 13.1.

Events from my gamepad over Bluetooth were received with this connection over hcidump(1). I'm curious to see if this gamepad can work with xf86-input-joystick as it is now.

I'm interested in investigating bthidd(8), other Bluetooth commands, and other programs that can interact with Bluetooth.


----------



## kr0m (Jun 27, 2022)

Hello i have a 8bitdo pro2 gamepad and TP-Link UB400 Nano usb dongle under FreeBSD13.1
I have followed handbook steps:


> kldload ng_ubt
> sysrc kld_list+=ng_ubt


Netgraph nodes seems to be ok: ubt0, ubt0hci and ubt0l2cap:


> ngctl list
> There are 10 total nodes:
> Name: em0             Type: ether           ID: 00000001   Num hooks: 0
> Name: vm-public       Type: ether           ID: 00000002   Num hooks: 0
> ...


I enabled usbhid


> vi /boot/loader.conf
> hw.usb.usbhid.enable="1"





> sysrc kld_list+=usbhid


And rebooted.


I can query my gamepad:
hccontrol -n ubt0hci inquiry


> Inquiry result, num_responses=1
> Inquiry result #0
> BD_ADDR: e4:17:d8:7b:6d:ce
> Page Scan Rep. Mode: 0x1
> ...


Getting device name:


> hccontrol -n ubt0hci remote_name_request e4:17:d8:7b:6d:ce
> BD_ADDR: e4:17:d8:7b:6d:ce
> Name: 8BitDo Pro 2


My hcsecd configuration:


> vi /etc/bluetooth/hcsecd.conf
> device {
> bdaddr  e4:17:d8:7b:6d:ce;
> name    "8BitDo Pro 2";
> ...


I make an alias for easier management:


> vi /etc/bluetooth/hosts
> e4:17:d8:7b:6d:ce       8BitDo-Pro-2


I can create a connection manually:


> hccontrol -n ubt0hci create_connection 8BitDo-Pro-2
> BD_ADDR: 8BitDo-Pro-2
> Connection handle: 76
> Encryption mode: Disabled [0]


And i can see the active connection:


> hccontrol -n ubt0hci read_connection_list
> Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State
> 8BitDo-Pro-2          76  ACL    0 MAST    NONE       0     0 OPEN


I start hcsecd service:


> sysrc hcsecd_enable=YES
> service hcsecd start


I configured bthidcontrol


> bthidcontrol -a 8BitDo-Pro-2 Query
> device {
> bdaddr      e4:17:d8:7b:6d:ce;
> name      "8BitDo Pro 2";
> ...





> vi /etc/bluetooth/bthidd.conf
> device {
> bdaddr      e4:17:d8:7b:6d:ce;
> name      "8BitDo Pro 2";
> ...





> bthidcontrol -a 8BitDo-Pro-2 Dump
> Collection page=Generic_Desktop usage=Game_Pad
> Input   id=3 size=4 count=1 page=Generic_Desktop usage=Hat_Switch Variable NullState, logical range 0..7, physical range 0..315, unit=0x14 exp=0
> Input   id=3 size=8 count=1 page=Generic_Desktop usage=X Variable, logical range 0..255, physical range 0..315, unit=0x14 exp=0
> ...


But i cant read any gamepad event with:


> hcidump -i ubt0hci



Maybe is there any additional service to be started? some kind of error in my configuration?


----------



## sidetone (Jun 27, 2022)

Did u enable permissions of the dongle through a custom .conf file in /usr/local/etc/devd/? Enabling the Bluetooth permissions of the dongle may be enough to do it for the gamepad. One gamepad can have two different vendors and product numbers depending on if it's on a wired connection or Bluetooth connection. I tried to set this for the gamepad's vendor/product # over the Bluetooth connection anyway, even if this was the wrong system (USB rather then Bluetooth) for devd and of no consequence. I think the setting for the gamepad over Bluetooth either not relevant, or it needs to be on a Bluetooth system over a USB subsystem. The dongle's permission settings over the USB hub is relevant, bc that Bluetooth dongle is over the USB system.

I have instructions for setting devd and seeing the permissions on Thread howto-enabling-multimedia-keys-gamepads-joysticks-for-desktop-usbhid.84464. Post #19, and a few other posts on it tell how to find the vendor and product model from the command line. Also, how to confirm and check those settings. This can make the difference in it showing output with `hcidump`. It seems like some information on your gamepad was dumped, even if it wasn't gamepad events.

Antimicro can unlock other gamepads without setting those permissions needed for Joytran, but these can't access Bluetooth.

A service could have also been missed.

Maybe months later, I'll check my gamepad out again to attempt to go further with it.


----------



## kr0m (Jun 27, 2022)

Thank you sidetone for the tips, i have done the following configuration without success:


> vi /etc/devfs.rules
> [localrules=10]
> add path 'input'   mode 0775 group wheel
> add path 'input/*' mode 0660 group wheel
> ...


usbconfig shows the following information:


> usbconfig
> ugen0.2: <vendor 0x0a12 product 0x0001> at usbus0, cfg=0 md=HOST spd=FULL (12Mbps) pwr=ON (0mA)





> vi /usr/local/etc/devd/8bitdo.conf
> notify 100 {
> match "system"          "USB";
> match "subsystem"       "INTERFACE";
> ...





> service devd restart


But hcidump -i ubt0hci continues without showing anything when gamepad button is pressed.


----------



## kr0m (Jun 27, 2022)

I have noticed that after some seconds of the connection(hccontrol -n ubt0hci create_connection 8BitDo-Pro-2) it appears that log:


> Jun 27 20:45:49 Garrus kernel: ng_l2cap_lp_discon_ind: ubt0l2cap - unexpected LP_DisconnectInd event. Connection does not exist, con_handle=76


And connection_list appears empty:


> hccontrol -n ubt0hci read_connection_list
> Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State


----------

