How to set up Bluetooth in Linux in a complicated way


Preparing to work for the annual IT forum, the idea arose to create a simple manipulator controlled by a wireless gamepad to demonstrate the capabilities of microcontrollers and single board computers. At hand was the TRIK controller, several servomotors, an iron constructor, and a month before the start of the forum.


“Everything is going according to plan”, but not in this case.


Stage 1. Preparation


TRIK on board with Linux was a brute force for such a manipulator, but “the matter is in the banal usability and maintenance” (quote ClusterM about Linux in a smart intercom ).


After reading the specification , it was discovered that it has Bluetooth. If you worked with this controller, then you know that the transfer of programs is carried out via Wi-Fi and there are no other convenient ways to communicate with it. The menu does not mention the presence of Bluetooth. But how?


Armed with SSH, I began to look for Bluetooth with a screwdriver and curiosity. The system contains utilities hcitool, hciconfig and the demon bluetoothd. They all said that he was not.


root@trik-7dda93:~# hcitool dev Devices: 

 root@trik-7dda93:~# hciconfig hci0 Can't get device info: No such device 

 root@trik-7dda93:~# bluetoothd -n & [1] 5449 root@trik-7dda93:~# bluetoothd[5449]: Bluetooth daemon 4.101 bluetoothd[5449]: Starting SDP server bluetoothd[5449]: Bluetooth Management interface initialized 

Calling friends in search of an external USB module, I continued to search.


Having examined the controller, the Jorjin WG7311-0A module was found. The specification states that, indeed, there is Wi-Fi, Bluetooth and even FM radio. The interface for communicating with Bluetooth is the UART, and it is turned on via the BT_EN contact.



After reading how the Bluetooth module is connected via UART via hcitool, I was lucky and nothing. Two of the three free UART ports were silent.


But we have contact BT_EN! It is possible that the module is simply turned off and does not respond to requests. Having studied the Linux kernel device for ARM devices, a file was found where all the contacts used by the SoC are written. Having opened arch/arm/mach-davinci/board-da850-trik.c in the kernel source code, a GPIO contact for Bluetooth was indeed found. Victory! - I thought.


 static const short da850_trik_bluetooth_pins[] __initconst = { DA850_GPIO6_11, /*BT_EN_33 */ DA850_GPIO6_10, /*BT_WU_33*/ -1 }; 

Stage 2. Offensive


To enable a contact through GPIO, you need to find its pass-through sequence number. We find the following line in the kernel code with the request to initialize the BT_EN_33 contact in arch/arm/mach-davinci/board-da850-trik.c :


 ret = gpio_request_one(GPIO_TO_PIN(6, 11), GPIOF_OUT_INIT_LOW, "BT_EN_33"); 

It uses the macro GPIO_TO_PIN. See the macro description in arch/arm/mach-davinci/include/mach/gpio-davinci.h :


 /* Convert GPIO signal to GPIO pin number */ #define GPIO_TO_PIN(bank, gpio) (16 * (bank) + (gpio)) 

With the help of it and you can find out the through number of the contact. We get that 16 * 6 + 11 = 107. Now we turn to the inclusion of the contact.


 echo 1 >> /sys/devices/virtual/gpio/gpio107/value 

0 or 1 in the echo command is the contact state.


Run the command to connect and ...


 root@trik-7dda93:~# hciattach /dev/ttyS0 texas Found a Texas Instruments' chip! Firmware file : /lib/firmware/TIInit_7.6.15.bts can't open firmware file: No such file or directory Warning: cannot find BTS file: /lib/firmware/TIInit_7.6.15.bts Device setup complete 

incomprehensible for us (at the moment) error messages. We try to configure the device through hcitool:


 root@trik-7dda93:~# hcitool dev Devices: 

No devices, although the initialization allegedly passed. We try to connect a second time, but with a different type of adapter:


 root@trik-7dda93:~# hciattach /dev/ttyS0 texasalt Texas module LMP version : 0x06 Texas module LMP sub-version : 0x1f0f internal version freeze: 15 software version: 6 chip: wl1271 (7) Opening firmware file: /etc/firmware/wl1271.bin Could not open firmware file /etc/firmware/wl1271.bin: No such file or directory (2). Device setup complete 

Again, nothing. Let's go back to the first error and apply the knowledge of English:


 Warning: cannot find BTS file: /lib/firmware/TIInit_7.6.15.bts 

Open the folder / lib / firmware with firmware and do not find the desired file. After a long search on the Internet, we find the necessary file on the TI repository and download it. Other versions of the same file refused to work.


 curl -k https://git.ti.com/wilink8-bt/ti-bt-firmware/blobs/raw/45897a170bc30afb841b1491642e774f0c89b584/TIInit_7.6.15.bts > TIInit_7.6.15.bts cp TIInit_7.6.15.bts /lib/firmware/TIInit_7.6.15.bts 

Reboot the controller and reconnect:


 root@trik-7dda93:~# echo 1 >> /sys/devices/virtual/gpio/gpio107/value root@trik-7dda93:~# hciattach /dev/ttyS0 texas Found a Texas Instruments' chip! Firmware file : /lib/firmware/TIInit_7.6.15.bts Loaded BTS script version 1 Device setup complete 

Hooray! The firmware has loaded. Check hciconfig:


 root@trik-7dda93:~# hciconfig hci0: Type: BR/EDR Bus: UART BD Address: 78:**:**:**:**:B3 ACL MTU: 1021:4 SCO MTU: 180:4 DOWN RX bytes:509 acl:0 sco:0 events:21 errors:0 TX bytes:388 acl:0 sco:0 commands:21 errors:0 

We start the bluetoothd service, scan devices and detect our module:


 root@trik-7dda93:~# bluetoothd -n & [1] 4689 bluetoothd[4689]: Bluetooth daemon 4.101 bluetoothd[4689]: Starting SDP server bluetoothd[4689]: Bluetooth Management interface initialized bluetoothd[4689]: Parsing /etc/bluetooth/serial.conf failed: No such file or directory bluetoothd[4689]: Could not get the contents of DMI chassis type bluetoothd[4689]: Adapter /org/bluez/4689/hci0 has been enabled root@trik-7dda93:~# hciconfig hci0 piscan 

A search on the computer detects the device:



To enable Bluetooth, you can make a script:


 #!/bin/bash case "$1" in start) echo 1 >> /sys/devices/virtual/gpio/gpio107/value bluetoothd -n & hciattach /dev/ttyS0 texas hciconfig hci0 piscan ;; stop) ;; restart) ;; status) ;; *) ;; 

And add it to autorun:


 cp init-bluetooth /etc/init.d/init-bluetooth update-rc.d init-bluetooth enable 99 

Restarting and disabling the module behave unpredictably, so the options stop and restart have no commands.


Stage 3. Checking the connection


The easiest way to verify communication in both directions is the COM port service. With the help of several commands we include it:


 root@trik-7dda93:~# sdptool add --channel=3 SP Serial Port service registered root@trik-7dda93:~# mknod -m 666 /dev/rfcomm0 c 216 0 root@trik-7dda93:~# rfcomm watch /dev/rfcomm0 3 /sbin/getty rfcomm0 115200 linux Waiting for connection on channel 3 

Connect from the phone and see an invitation to enter the system:



None of the verified terminals gave an empty user password, so I had to send the login information using the redirection of flows in the SSH session.


Stage 4. ./configure && make


Following the instructions for connecting the gamepad in Linux, we encounter the following problems:



The only dependency that we managed to satisfy is the uinput kernel module.


For this:



 cp /proc/config.gz config.gz gunzip config.gz 


 echo "CONFIG_INPUT_UINPUT=m" >> config 


 source /opt/trik-sdk/environment-setup-arm926ejste-oe-linux-gnueabi make 


 make INSTALL_MOD_PATH=/mnt/trik-sd modules_install 


 make uImage cp arch/arm/boot/uImage /mnt/trik-sd/boot/uImage-3.6.7 

Now the program does not swear at the absence of a kernel module, but then we can not do anything. Instructions for the gamepad will be useful to us later.


Stage 5. Cook the porridge from the ax


We start the plan "tyap-lyap". If there is no convenient way to put the necessary programs on the original distribution, then we put something popular. The processor has the architecture of ARMv5TE, which means that distributions are there for it.


We try to unpack and run the universal Arch Linux for ARM and when loading into the console we see that systemd requires a newer version of the kernel, which we do not have. Attempts to transfer the 4.16 kernel were not crowned with great success, and too much time was spent on it.


Moving on to another option is Debian. A disk image with the installed system for ARM exists, but it is better to put a clean system with the necessary packages and settings for us.


Installation in QEMU


Download the installation image (link to .iso ) and install QEMU.
We also need a kernel and an initrd image to boot the installation, which can be downloaded from here .


Create an image of a memory card with the size of a real memory card (in this case 4 GB):


 qemu-img create -f raw debian.img 4G 

Run the installation:


 qemu-system-arm -M versatilepb -kernel vmlinuz-3.2.0-4-versatile -initrd initrd.gz -hda debian.img -cdrom debian-7.11.0-armel-CD-1.iso 

If you are going to partition the disk with a non-standard relative original distribution, leave the root partition first, otherwise you will have to change the kernel boot options in uBoot. There is registered the number of the partition on which the root file system is located.


Standard markup contains:


  1. Section EXT4 for the root file system of size ≈ 1.3 GB
  2. FAT32 section for storing user data in the size of ≈ 500 MB

The fdisk output for the original distribution image:


 Disk: trik-distro.img geometry: 893/64/63 [3604478 sectors] Signature: 0xAA55 Starting Ending #: id cyl hd sec - cyl hd sec [ start - size] ------------------------------------------------------------------------ 1: 83 1023 3 32 - 1023 3 32 [ 1040382 - 2564096] Linux files* 2: 0C 64 0 1 - 1023 3 32 [ 8192 - 1032190] Win95 FAT32L 3: 00 0 0 0 - 0 0 0 [ 0 - 0] unused 4: 00 0 0 0 - 0 0 0 [ 0 - 0] unused 

After setting the parameters, we go to drink a few cups of tea, because The emulator is not much faster than a real ARM processor.


To start the installed system, you will need another initrd image, which can be taken from here .


Run the system:


 qemu-system-arm -M versatilepb -kernel vmlinuz-3.2.0-4-versatile -initrd initrd.img-3.2.0-4-versatile -hda debian.img -append "root=/dev/sda1" 

System Setup


After the launch, we enter the superuser, check the connection with the Internet, update the repositories and the system, set a minimum set of programs:


 apt-get update apt-get upgrade apt-get install curl git mc htop joystick 

Terminals


We edit /etc/inittab , remove unnecessary terminals, enable the UART we need and add autologin for the desired user (use root only for debugging). Autologin is useful if you plan to run a shell to control the controller.


 1:2345:respawn:/sbin/getty 38400 tty1 --autologin root #2:23:respawn:/sbin/getty 38400 tty2 #3:23:respawn:/sbin/getty 38400 tty3 #4:23:respawn:/sbin/getty 38400 tty4 #5:23:respawn:/sbin/getty 38400 tty5 #6:23:respawn:/sbin/getty 38400 tty6 uart:12345:respawn:/sbin/getty -L 115200 ttyS1 

Bluetooth and Wi-Fi


Install bluez-utils and wpasupplicant to access Wi-Fi and Bluetooth.


 apt-get install bluez-utils wpasupplicant 

Disable the eth0 interface and configure the wlan1 interface in /etc/network/interfaces :


 # /etc/network/interfaces -- configuration file for ifup(8), ifdown(8) # The loopback interface auto lo iface lo inet loopback # Wireless interfaces auto wlan1 iface wlan1 inet dhcp wireless_mode managed wireless_essid any wpa-driver wext wpa-conf /etc/wpa_supplicant.conf 

Add the network in advance in /etc/wpa_supplicant.conf , because doing it on the controller itself is not so convenient:


 wpa_passphrase ssid password >> /etc/wpa_supplicant.conf 

If you do not have access to Wi-Fi, you can use the UART for further configuration, but note that by default the kernel sends all errors to this terminal. Therefore, while running, you may be interrupted by a sudden message from the kernel or service.


Add a script to turn on Bluetooth. This time, we modify /etc/init.d/bluetooth :


  139: case $1 in start) echo 1 >> /sys/devices/virtual/gpio/gpio107/value  168: hciattach /dev/ttyS0 texas log_end_msg 0 ;; 

Thus, all services that require the Bluetooth service will run the necessary commands for initialization.


Swipe left, swing right


We remove unnecessary programs and services that can be viewed with the help of htop, because they occupy precious space in RAM:



In this case, the ConsoleKit service has a lot of processes . Move the file of this service to the home folder of the superuser in case of recovery:


 mv /usr/share/dbus-1/system-services/org.freedesktop.ConsoleKit.service /root/ 

Before shutting down the service, the consumption of RAM was 19 MB, and after - 16 MB.


System sections


Although uBoot passes the device on which the root partition is located to the kernel, you should write it in /etc/fstab for reliability. Change the first line responsible for the root section:


 /dev/mmcblk0p1 / auto defaults 1 1 proc /proc proc defaults 0 0 devpts /dev/pts devpts mode=0620,gid=5 0 0 usbdevfs /proc/bus/usb usbdevfs noauto 0 0 tmpfs /run tmpfs mode=0755,nodev,nosuid,strictatime 0 0 tmpfs /var/volatile tmpfs defaults 0 0 

If you did not make the root partition the first, do not forget to specify the desired partition number.


If you left the second FAT partition for user data, then you need to create a folder to mount the partition into it.


 mkdir /usr/share/trik 

and register the section in /etc/fstab :


 /dev/mmcblk0p2 /usr/share/trik vfat defaults 0 0 

Stage 6. We taste our porridge


Having configured the system image, you need to mount it to install the kernel modules and the kernel itself:


 # ,     (start) fdisk -l debian.img mount -o loop,offset=NNNN debian.img /mnt/debian 

where, NNNN = sector size * beginning of the section. The default sector size is 512 bytes.


We also mount the original distribution:


 fdisk -l trik-distro.img mount -o loop,offset=NNNN trik-distro.img /mnt/trik-clean 

Remove the kernel for QEMU and its modules, since they are not intended for our platform. We copy the new kernel and modules, as well as on the original distribution.


 rm -rf /mnt/debian/boot/ rm -rf /mnt/debian/lib/modules/3.2.0-4-versatile rm -rf /mnt/debian/lib/modules/3.2.0-5-versatile mkdir /mnt/debian/boot/ cp arch/arm/boot/uImage /mnt/debian/boot/ make INSTALL_MOD_PATH=/mnt/debian modules_install 

We will need the firmware for the Wi-Fi module, which is in the original distribution in the folder / lib / firmware and the Bluetooth firmware that we found earlier.


 cp /mnt/trik-clean/lib/firmware/* /mnt/debian/lib/firmware/ cp TIInit_7.6.15.bts /mnt/debian/lib/firmware/ 

Disconnect disk images:


 umount /mnt/trik-clean umount /mnt/debian 

And start copying the image to the memory card using dd:


 #    ( ) lsblk dd if=debian.img of=/dev/sdX bs=4M 

Stage 7. Finish line


Compile the program to connect the gamepad on the new system and install the sixad daemon.


Connect the gamepad via USB to the controller and run the program to create a pair:


 root@trik:~/bt# ./sixpair Current Bluetooth master: 78:**:**:**:**:b9 Setting master bd_addr to 78:**:**:**:**:b9 

When the gamepad is connected, nothing happens and the sixad service is silent:


 sixad-bin[2675]: started sixad-bin[2675]: sixad started, press the PS button now sixad-bin[2675]: unable to connect to sdp session 

But in the community Raspberry Pi have already made a "crutch" to fix the connection .


Rebuild the program and enjoy.


 sixad-bin[2833]: started sixad-bin[2833]: sixad started, press the PS button now sixad-bin[2833]: unable to connect to sdp session sixad-sixaxis[2836]: started sixad-sixaxis[2836]: Connected 'PLAYSTATION(R)3 Controller (00:**:**:**:**:09)' [Battery 02] 

Now the gamepad is available to the system as an input device and the jstest program will show the status of all buttons and analog sensors:


 root@trik:~# ls /dev/input/ by-path event0 event1 event2 event3 js0 js1 js2 mice root@trik:~# jstest --normal /dev/input/jsX Driver version is 2.1.0. Joystick (PLAYSTATION(R)3 Controller (00:**:**:**:**:09)) has 29 axes (X, Y, Z, Rx, Ry, Rz, Throttle, Rudder, Wheel, Gas, Brake, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, (null), (null), (null), (null), (null), (null), (null), (null)) and 17 buttons (Trigger, ThumbBtn, ThumbBtn2, TopBtn, TopBtn2, PinkieBtn, BaseBtn, BaseBtn2, BaseBtn3, BaseBtn4, BaseBtn5, BaseBtn6, BtnDead, BtnA, BtnB, BtnC, BtnX). Testing ... (interrupt to exit) Axes: 0: 0 1: 0 2: 0 3: 0 4: -7150 5: -7746 6:-32767 7: 0 8: 0 9: 0 10: 0 11: 0 12: 0 13: 0 14: 0 15: 0 16: 0 17: 0 18: 0 19: 0 20: 0 21: 0 22: 0 23: 0 24: 0 25: 0 26: 0 27: 0 28: 0 Buttons: 0:off 1:off 2:off 3:off 4:off 5:off 6:off 7:off 8:off 9:off 10:off 11:off 12:off 13:off 14:off 15:off 16:off 

where X is the device number in the system, the default is 2. The numbers of the buttons and axes can be found here .


We use in practice


Video demonstration of the gamepad on YouTube .


Photos of the distribution

Kernel load:

Terminal running on X11:



And by tradition:



useful links


Programs for connecting the gamepad Dualshock 3 - sixpair and sixad .


For gamepads and other input devices there is an easy library on C - libenjoy .


The source code for servomotor and motor control is the GitHub repository .


All configuration files from the article for homemade distribution - the GitHub repository .


The source code for the kernel is the GitHub repository .


Interesting facts about the controller



 mem=128M console=ttyS1,115200n8 rw noinitrd rootwait root=/dev/mmcblk0p1 vt.global_cursor_default=0 consoleblank=0 

The memory chip is marked 3PC22 D9MTD production Micron. Find information about its present volume failed.



Image addresses from dmesg:


 [ 11.598170] 0x000000000000-0x000000040000 : "uboot" [ 11.642985] 0x000000040000-0x000000080000 : "uboot-env1" [ 11.706256] 0x000000080000-0x0000000c0000 : "uboot-env2" [ 11.761827] 0x0000000c0000-0x000000100000 : "config-periph" [ 11.805129] 0x000000100000-0x000000400000 : "kernel" [ 11.861864] 0x000000400000-0x000001000000 : "RootFS" 


Problems encountered when using


Source: https://habr.com/ru/post/415007/


All Articles