Cómo configurar Bluetooth en Linux de una manera complicada


En preparación para el foro anual de TI, surgió la idea de crear un manipulador simple controlado por un gamepad inalámbrico para demostrar las capacidades de los microcontroladores y las computadoras de una sola placa. A la mano había un controlador TRIC, varios servomotores, un constructor de hierro y un mes antes del inicio del foro.


"Todo va según lo planeado", pero no en este caso.


Etapa 1. Preparación


El TRIC a bordo de Linux fue un fracaso para tal manipulador, pero "la cosa es la usabilidad y el mantenimiento banales" (cita de ClusterM sobre Linux en un intercomunicador inteligente ).


Después de leer la especificación , se descubrió que tiene Bluetooth. Si trabajó con este controlador, entonces sabe que la transferencia de programas se realiza a través de Wi-Fi y que no hay otras formas convenientes de comunicarse con él. No hay mención de Bluetooth en el menú. Pero como es eso?


Armado con SSH, un destornillador y curiosidad, comencé a buscar Bluetooth. El sistema incluía hcitool, hciconfig y el demonio bluetoothd. Todos dijeron que él no estaba allí.


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 

Llamando a amigos en busca de un módulo USB externo, continué buscando.


Después de desmontar el controlador, se encontró el módulo Jorjin WG7311-0A. La especificación establece que realmente hay Wi-Fi, Bluetooth e incluso una radio FM. La interfaz para comunicarse con Bluetooth es UART, y se activa a través de BT_EN.



Después de leer cómo se conecta el módulo Bluetooth a través de UART a través de hcitool, probé suerte y nada. Dos de los tres puertos UART libres estaban en silencio.


Pero tenemos contacto BT_EN! Es posible que el módulo simplemente esté apagado y no responda a las solicitudes. Después de examinar el dispositivo del kernel de Linux para dispositivos ARM, se encontró un archivo donde se registran todos los contactos utilizados por SoC. Al abrir arch/arm/mach-davinci/board-da850-trik.c en el código fuente del núcleo, se encontró un contacto GPIO para Bluetooth. Victoria! Pensé


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

Etapa 2. Ofensiva


Para habilitar un contacto a través de GPIO, debe encontrar su número de serie de extremo a extremo. Encontramos la siguiente línea en el código del kernel con una solicitud para inicializar el contacto BT_EN_33 en arch/arm/mach-davinci/board-da850-trik.c :


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

Utiliza la macro GPIO_TO_PIN. Consulte la descripción de la macro en 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)) 

Utilizándolo, puede encontrar el número de contacto de extremo a extremo. Obtenemos que 16 * 6 + 11 = 107. Ahora pasamos a la inclusión del contacto.


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

0 o 1 en el comando echo es el estado del contacto.


Ejecute el comando para conectarse y ...


 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 

incomprensible para nosotros (por el momento) mensajes de error. Intentamos configurar el dispositivo a través de hcitool:


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

No hay dispositivos, aunque la inicialización supuestamente pasó. Intentamos conectarnos por segunda vez, pero con un tipo diferente de adaptador:


 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 

Y de nuevo, nada. Volvamos al primer error y apliquemos el conocimiento del inglés:


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

Abrimos la carpeta / lib / firmware con firmware y no encontramos el archivo que necesitamos. Después de una larga búsqueda en Internet, encontramos el archivo deseado en el repositorio de TI y lo descargamos. Otras versiones del mismo archivo se negaron a funcionar.


 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 

Reiniciamos el controlador y volvemos a conectar:


 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 

¡Hurra! El firmware ha arrancado. Comprobando 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 

Iniciamos el servicio bluetoothd, buscamos dispositivos y detectamos nuestro módulo:


 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 

Una búsqueda en la computadora encuentra un dispositivo:



Para habilitar Bluetooth, puede hacer un 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) ;; *) ;; 

Y agréguelo a la ejecución automática:


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

El reinicio y el apagado del módulo se comportan de manera impredecible, por lo tanto, las opciones de detención y reinicio no tienen comandos.


Etapa 3. Verificación de comunicación


La forma más fácil de verificar la comunicación en ambas direcciones es el servicio del puerto COM. Con unos pocos comandos, enciéndalo:


 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 

Nos conectamos desde el teléfono y vemos una invitación para ingresar al sistema:



Ninguno de los terminales probados permitió ingresar una contraseña de usuario vacía, por lo que tuve que enviar información de inicio de sesión utilizando la redirección de hilos en una sesión SSH.


Etapa 4. ./configure && make


Siguiendo las instrucciones para conectar un gamepad a Linux, encontramos los siguientes problemas:


  • BlueZ en la distribución está desactualizado y no entiende los comandos del sixad daemon, que establece una conexión con el gamepad
  • La nueva versión de BlueZ de la fuente se niega a compilar debido a muchas dependencias
  • FreshZian BlueZ requiere udev y systemd, que faltan en la distribución actual

La única dependencia que pudo satisfacer fue el módulo del núcleo uinput.


Para hacer esto:


  • obtener la configuración del núcleo actual en el dispositivo

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

  • descargar el código del kernel
  • descargar e instalar toolchain
  • copie la configuración del kernel a la carpeta con el código del kernel
  • agregue el módulo uinput a la configuración

 echo "CONFIG_INPUT_UINPUT=m" >> config 

  • comience el ensamblaje encendiendo primero la cadena de herramientas

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

  • copie los módulos del núcleo a la tarjeta de memoria

 make INSTALL_MOD_PATH=/mnt/trik-sd modules_install 

  • construya la imagen uBoot y cópiela en / boot

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

Ahora el programa no jura por la falta de un módulo de kernel, pero entonces no podemos hacer nada. Las instrucciones para el gamepad serán útiles más tarde.


Etapa 5. Cocine las gachas del hacha


Llegando al plan "tyap-blooper". Como no hay una manera conveniente de poner los programas necesarios en la distribución original, pondremos algo popular. El procesador tiene una arquitectura ARMv5TE, lo que significa que hay distribuciones para él.


Intentamos desempaquetar y ejecutar Arch Linux universal para ARM y al cargar en la consola vemos que systemd requiere una versión de kernel más nueva, que no tenemos. Los intentos de transferir el kernel 4.16 no tuvieron éxito y tomó demasiado tiempo.


Pasamos a otra opción: Debian. Existe una imagen de disco con un sistema instalado para ARM, pero es mejor poner un sistema limpio con los paquetes y configuraciones necesarias para nosotros.


Instalación en QEMU


Descargue la imagen de instalación (enlace a .iso ) e instale QEMU.
También necesitamos el núcleo y la imagen initrd para iniciar la instalación, que se puede descargar desde aquí .


Cree una imagen de una tarjeta de memoria con el tamaño de una tarjeta de memoria real (en este caso, 4 GB):


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

Comenzamos la instalación:


 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 

Si va a hacer un diseño de disco de una distribución original relativa no estándar, primero deje la partición raíz, de lo contrario tendrá que cambiar los parámetros de arranque del núcleo en uBoot. Existe el número de la partición en la que se encuentra el sistema de archivos raíz.


El marcado estándar contiene:


  1. Partición EXT4 para root 1.3 GB del sistema de archivos raíz
  2. Partición FAT32 para almacenar datos de usuario ≈ 500 MB de tamaño

La salida de fdisk para la imagen de la distribución original:


 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 

Después de configurar los parámetros, dejamos tomar unas tazas de té, porque El emulador no es mucho más rápido que un procesador ARM real.


Para iniciar el sistema instalado, necesita otra imagen initrd, que se puede tomar desde aquí .


Iniciamos el sistema:


 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" 

Configuración del sistema


Después de comenzar, ingresamos al superusuario, verificamos la conexión a Internet, actualizamos los repositorios y el sistema, colocamos el conjunto mínimo de programas:


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

Terminales


Editamos /etc/inittab , eliminamos terminales innecesarios, activamos el UART que necesitamos para nosotros y agregamos la entrada automática para el usuario correcto (use root solo cuando depure). La entrada automática es útil si planea ejecutar el shell para el control en el controlador.


 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 y wifi


Instale bluez-utils y wpasupplicant para acceder a Wi-Fi y Bluetooth.


 apt-get install bluez-utils wpasupplicant 

Desactivamos la interfaz eth0 y configuramos la interfaz wlan1 en /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 

Agregue la red por adelantado a /etc/wpa_supplicant.conf , porque hacer esto en el controlador en sí no es tan conveniente:


 wpa_passphrase ssid password >> /etc/wpa_supplicant.conf 

Si no tiene acceso a Wi-Fi, puede usar UART para una configuración adicional, pero tenga en cuenta que, de forma predeterminada, el núcleo muestra todos los errores en este terminal. Por lo tanto, durante la operación, un mensaje repentino del núcleo o servicio puede interrumpirlo.


Agregue un script para habilitar Bluetooth. Esta vez, modifique /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 ;; 

Por lo tanto, todos los servicios que requieren el servicio Bluetooth ejecutarán los comandos necesarios para inicializar.


Deslizar hacia la izquierda, deslizar hacia la derecha


Eliminamos programas y servicios innecesarios que se pueden ver usando htop, porque ocupan un lugar precioso en la RAM:



En este caso, el servicio ConsoleKit tiene muchos procesos . Mueva el archivo de este servicio a la carpeta raíz en caso de recuperación:


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

Antes de cerrar el servicio, el consumo de RAM era de 19 MB y, después, de 16 MB.


Secciones del sistema


Aunque uBoot transfiere al núcleo el dispositivo en el que se encuentra la partición raíz, vale la pena escribirlo en /etc/fstab para mayor confiabilidad. Cambiamos la primera línea responsable de la sección raíz:


 /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 

Si no hizo la partición raíz la primera, no olvide especificar el número de partición deseado.


Si dejó la segunda partición FAT para datos de usuario, entonces necesita crear una carpeta para montar la partición en ella


 mkdir /usr/share/trik 

y escriba la sección en /etc/fstab :


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

Etapa 6. Probamos nuestras gachas


Después de configurar la imagen del sistema, debe montarla para instalar los módulos del núcleo y el núcleo mismo:


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

donde, NNNN = tamaño del sector * inicio de sección. El tamaño de sector predeterminado es 512 bytes.


También montamos la distribución original:


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

Eliminamos el kernel para QEMU y sus módulos, como No están destinados a nuestra plataforma. Copiamos el nuevo núcleo y los módulos, al igual que en la distribución original.


 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 

Necesitaremos firmware para el módulo Wi-Fi, que se encuentra en la distribución original en la carpeta / lib / firmware y el firmware de Bluetooth que encontramos anteriormente.


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

Desconectar imágenes de disco:


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

Y comience a copiar la imagen a la tarjeta de memoria usando dd:


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

Etapa 7. La línea de meta.


Compilamos los programas para conectar el gamepad en el nuevo sistema e instalamos el demonio sixad.


Conectamos el gamepad por USB al controlador y ejecutamos el programa para crear un par:


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

Cuando el gamepad está conectado, no pasa nada y el servicio sixad está en silencio:


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

Pero la comunidad Raspberry Pi ya ha hecho una "muleta" para arreglar la conexión .


Reconstruimos el programa y nos regocijamos.


 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] 

Ahora el gamepad está disponible para el sistema como dispositivo de entrada y el programa jstest mostrará el estado de todos los botones y sensores analógicos:


 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 

donde X es el número de dispositivo en el sistema, por defecto - 2. Aquí se puede ver la cantidad de botones y ejes.


Usar en la práctica


Video que muestra el gamepad en YouTube .


Fotos de la distribución.

Kernel cargando:

Terminal que se ejecuta en X11:



Y según la tradición:



Enlaces utiles


Programas para conectar el gamepad Dualshock 3: sixpair y sixad .


Para gamepads y otros dispositivos de entrada, hay una biblioteca C ligera: libenjoy .


El código fuente del programa para controlar servomotores y motores es el repositorio de GitHub .


Todos los archivos de configuración del artículo para un kit de distribución improvisado son el repositorio de GitHub .


La fuente del núcleo es el repositorio de GitHub .


Datos interesantes sobre el controlador


  • La especificación establece que la RAM es de 256 MB. Pero si ejecuta htop, verá que solo 128 MB están disponibles. Esto está limitado por las opciones del kernel que se pueden ver en la consola uBoot:

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

El chip de memoria está marcado 3PC22 D9MTD fabricado por Micron. No fue posible encontrar información sobre su volumen actual.


  • uBoot se almacena en la memoria flash SPI en la que el núcleo también está conectado y no se usa. Puede intentar usar este lugar para sus tareas o copiar un nuevo kernel y reconfigurar uBoot para que lo use.

Direcciones de imágenes de 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" 

  • La pantalla del controlador, aunque pequeña, en realidad tiene un sensor resistivo. Se desconoce si el sensor está conectado.
  • Dualshock 3 tiene LED en el conector USB que muestra el número del gamepad / joystick. Hay un gamepad en el video, pero su número es 3. Esto no es un error, porque Hay dos "joysticks" más en el sistema: un acelerómetro y un giroscopio.

Problemas encontrados al usar


  • El robot a veces se cuelga con fuerza, sin apagar los servomotores, lo que les permite cambiar su posición del ruido en la línea de datos. Esto se ha visto incluso en una distribución estándar .
  • La inclusión de controladores PWM es diferente de lo que está escrito en la documentación . Al menos en C puro esto no funcionó.
  • USB a veces deja de funcionar en Debian.

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


All Articles