Bluetooth: investigating dongle use for HID hardware: FreeBSD 13

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:
Code:
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:
Code:
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:
Code:
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.

Code:
# 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:
Code:
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:
Code:
Remote BD_ADDR    Handle Type Mode Role Encrypt Pending Queue State
Code:
hccontrol -n ubt0hci read_connection_list

Before, and after reloading the Bluetooth connection, it had:
Code:
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.
 
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
Code:
        BD_ADDR: 01:06:8b:5c:61:07
To simplify configuration, put this BD_ADDR into /etc/bluetooth/hosts:
Code:
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:
Code:
        BD_ADDR: gamepad
This can be used for hccontrol and other Bluetooth commands. Continuing:
hccontrol -n ubt0hci remote_name_request gamepad
Code:
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:
Code:
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]*
Code:
Binary file bthidcontrol matches
Binary file bthidd matches
/usr/sbin % grep usbhid [bt]*
Code:
Binary file bthidcontrol matches
Binary file bthidd matches
/usr/sbin % grep -i evdev [bt]*
Code:
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.
 
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
Name: ngctl25099 Type: socket ID: 00000043 Num hooks: 0
Name: btsock_hci_raw Type: btsock_hci_raw ID: 00000004 Num hooks: 1
Name: btsock_l2c_raw Type: btsock_l2c_raw ID: 00000005 Num hooks: 1
Name: btsock_l2c Type: btsock_l2c ID: 00000006 Num hooks: 1
Name: ubt0 Type: ubt ID: 00000027 Num hooks: 1
Name: btsock_sco Type: btsock_sco ID: 00000007 Num hooks: 0
Name: ubt0hci Type: hci ID: 00000039 Num hooks: 3
Name: ubt0l2cap Type: l2cap ID: 0000003d Num hooks: 3
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
Page Scan Period Mode: 0x2
Page Scan Mode: 00
Class: 00:25:08
Clock offset: 0x637b
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";
key nokey;
pin nopin;
}
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";
vendor_id 0x2dc8;
product_id 0x6006;
version 0x0100;
control_psm 0x11;
interrupt_psm 0x13;
reconnect_initiate true;
battery_power true;
normally_connectable false;
hid_descriptor {
0x05 0x01 0x09 0x05 0xa1 0x01 0x85 0x03
0x05 0x01 0x15 0x00 0x25 0x07 0x46 0x3b
0x01 0x95 0x01 0x75 0x04 0x65 0x14 0x09
0x39 0x81 0x42 0x75 0x01 0x95 0x04 0x81
0x01 0x15 0x00 0x26 0xff 0x00 0x09 0x30
0x09 0x31 0x09 0x32 0x09 0x35 0x95 0x04
0x75 0x08 0x81 0x02 0x05 0x02 0x15 0x00
0x26 0xff 0x00 0x09 0xc4 0x09 0xc5 0x95
0x02 0x75 0x08 0x81 0x02 0x05 0x09 0x19
0x01 0x29 0x10 0x15 0x00 0x25 0x01 0x75
0x01 0x95 0x10 0x81 0x02 0xc0 0x09 0x02
0x07 0x35 0x08 0x35 0x06 0x09 0x04
};
}
vi /etc/bluetooth/bthidd.conf
device {
bdaddr e4:17:d8:7b:6d:ce;
name "8BitDo Pro 2";
vendor_id 0x2dc8;
product_id 0x6006;
version 0x0100;
control_psm 0x11;
interrupt_psm 0x13;
reconnect_initiate true;
battery_power true;
normally_connectable false;
hid_descriptor {
0x05 0x01 0x09 0x05 0xa1 0x01 0x85 0x03
0x05 0x01 0x15 0x00 0x25 0x07 0x46 0x3b
0x01 0x95 0x01 0x75 0x04 0x65 0x14 0x09
0x39 0x81 0x42 0x75 0x01 0x95 0x04 0x81
0x01 0x15 0x00 0x26 0xff 0x00 0x09 0x30
0x09 0x31 0x09 0x32 0x09 0x35 0x95 0x04
0x75 0x08 0x81 0x02 0x05 0x02 0x15 0x00
0x26 0xff 0x00 0x09 0xc4 0x09 0xc5 0x95
0x02 0x75 0x08 0x81 0x02 0x05 0x09 0x19
0x01 0x29 0x10 0x15 0x00 0x25 0x01 0x75
0x01 0x95 0x10 0x81 0x02 0xc0 0x09 0x02
0x07 0x35 0x08 0x35 0x06 0x09 0x04
};
}
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
Input id=3 size=8 count=1 page=Generic_Desktop usage=Y Variable, logical range 0..255, physical range 0..315, unit=0x14 exp=0
Input id=3 size=8 count=1 page=Generic_Desktop usage=Z Variable, logical range 0..255, physical range 0..315, unit=0x14 exp=0
Input id=3 size=8 count=1 page=Generic_Desktop usage=Rz Variable, logical range 0..255, physical range 0..315, unit=0x14 exp=0
Input id=3 size=8 count=1 page=Simulation_Controls usage=Accelerator Variable, logical range 0..255, physical range 0..315, unit=0x14 exp=0
Input id=3 size=8 count=1 page=Simulation_Controls usage=Brake Variable, logical range 0..255, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_1 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_2 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_3 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_4 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_5 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_6 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_7 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_8 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_9 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_10 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_11 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_12 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_13 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_14 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_15 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
Input id=3 size=1 count=1 page=Button usage=Button_16 Variable, logical range 0..1, physical range 0..315, unit=0x14 exp=0
End collection
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?
 
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.
 
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
sysrc devfs_system_ruleset="localrules"
service devfs restart
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";
match "type" "ATTACH";
match "vendor" "0x0a12";
match "product" "(0x0001)";
action "chgrp wheel /dev/$cdev; chmod 660 /dev/$cdev";
};
service devd restart
But hcidump -i ubt0hci continues without showing anything when gamepad button is pressed.
 
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
 
Back
Top