Como configurar o Bluetooth no Linux de uma maneira complicada


Em preparação para o fórum anual de TI, surgiu a idéia de criar um manipulador simples controlado por um gamepad sem fio para demonstrar os recursos de microcontroladores e computadores de placa única. Estava à mão um controlador TRIC, vários servomotores, um construtor de ferro e um mês antes do início do fórum.


"Tudo está indo conforme o planejado", mas não neste caso.


Etapa 1. Preparação


O TRIC a bordo do Linux foi um fracasso para um manipulador desse tipo, mas “a coisa é usabilidade e manutenção banais” (citação do ClusterM sobre o Linux em um interfone inteligente ).


Depois de ler a especificação , descobriu-se que ele possui Bluetooth. Se você trabalhou com este controlador, sabe que a transferência de programas é via Wi-Fi e não há outras maneiras convenientes de se comunicar com ele. Não há menção de Bluetooth no menu. Mas como assim?


Armado com SSH, uma chave de fenda e curiosidade, comecei a procurar por Bluetooth. O sistema incluía hcitool, hciconfig e o daemon bluetoothd. Todos eles disseram que ele não estava lá.


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 

Ligando para amigos em busca de um módulo USB externo, continuei pesquisando.


Depois de desmontar o controlador, o módulo Jorjin WG7311-0A foi encontrado. A especificação afirma que realmente há Wi-Fi, Bluetooth e até um rádio FM. A interface para comunicação com Bluetooth é UART e é ativada via BT_EN.



Depois de ler como o módulo Bluetooth é conectado via UART via hcitool, tentei a sorte e nada. Duas das três portas UART gratuitas estavam silenciosas.


Mas temos o contato BT_EN! É possível que o módulo esteja simplesmente desligado e não responda às solicitações. Após examinar o dispositivo do kernel do Linux para dispositivos ARM, foi encontrado um arquivo em que todos os contatos usados ​​pelo SoC são registrados. Ao abrir arch/arm/mach-davinci/board-da850-trik.c no código-fonte do kernel, um contato GPIO para Bluetooth foi realmente encontrado. Vitória! Eu pensei.


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

Etapa 2. Ofensivo


Para habilitar um contato através do GPIO, você precisa encontrar o número de série de ponta a ponta. Encontramos a seguinte linha no código do kernel com uma solicitação para inicializar o contato BT_EN_33 em arch/arm/mach-davinci/board-da850-trik.c :


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

Ele usa a macro GPIO_TO_PIN. Veja a descrição da macro em 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)) 

Usando-o, você pode encontrar o número de contato completo. Nós entendemos que 16 * 6 + 11 = 107. Agora nos voltamos para a inclusão do contato.


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

0 ou 1 no comando echo é o estado do contato.


Execute o comando para conectar e ...


 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 

incompreensível para nós (no momento) mensagens de erro. Tentamos configurar o dispositivo através do hcitool:


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

Não há dispositivos, embora a inicialização supostamente tenha sido aprovada. Tentamos conectar uma segunda vez, mas com um 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 

E novamente, nada. Vamos voltar ao primeiro erro e aplicar o conhecimento de inglês:


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

Abrimos a pasta / lib / firmware com firmware e não encontramos o arquivo que precisamos. Após uma longa pesquisa na Internet, encontramos o arquivo desejado no repositório da TI e o fazemos o download. Outras versões do mesmo arquivo se recusaram 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 

Reinicializamos o controlador e reconectamos:


 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 

Viva! O firmware foi inicializado. Verificando 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 o serviço bluetoothd, procuramos dispositivos e detectamos nosso 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 

Uma pesquisa por computador encontra um dispositivo:



Para ativar o Bluetooth, você pode criar um 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) ;; *) ;; 

E adicione-o à execução automática:


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

A reinicialização e o desligamento do módulo se comportam de maneira imprevisível, portanto, as opções de parada e reinicialização não possuem comandos.


Etapa 3. Verificação da comunicação


A maneira mais fácil de verificar a comunicação nas duas direções é o serviço da porta COM. Com alguns comandos, ative-o:


 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 

Nós nos conectamos a partir do telefone e vemos um convite para entrar no sistema:



Nenhum dos terminais testados permitiu inserir uma senha de usuário vazia, então tive que enviar informações de login usando o redirecionamento de thread em uma sessão SSH.


Etapa 4. ./configure && make


Seguindo as instruções para conectar um gamepad ao Linux, encontramos os seguintes problemas:


  • O BlueZ na distribuição está desatualizado e não entende os comandos do sixad daemon, que estabelece uma conexão com o gamepad
  • Nova versão BlueZ da fonte se recusa a compilar devido a muitas dependências
  • O BlueZ do Debian fresco requer udev e systemd, que estão ausentes na distribuição atual

A única dependência que foi capaz de satisfazer foi o módulo do kernel uinput.


Para fazer isso:


  • obtenha a configuração do kernel atual no dispositivo

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

  • baixar código do kernel
  • baixar e instalar toolchain
  • copie a configuração do kernel para a pasta com o código do kernel
  • adicione o módulo uinput à configuração

 echo "CONFIG_INPUT_UINPUT=m" >> config 

  • inicie a montagem ativando primeiro a cadeia de ferramentas

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

  • copie os módulos do kernel para o cartão de memória

 make INSTALL_MOD_PATH=/mnt/trik-sd modules_install 

  • construa a imagem do uBoot e copie-a para / boot

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

Agora, o programa não jura pela falta de um módulo do kernel, mas não podemos fazer nada. Instruções para o gamepad serão úteis mais tarde.


Etapa 5. Cozinhe o mingau no machado


Chegando ao plano "tyap-blooper". Como não há uma maneira conveniente de colocar os programas necessários na distribuição original, colocaremos algo popular. O processador possui uma arquitetura ARMv5TE, o que significa que existem distribuições para ele.


Tentamos descompactar e executar o Arch Linux universal para ARM e, ao carregar no console, vemos que o systemd requer uma versão mais recente do kernel, que não possuímos. Tentativas de transferência do kernel 4.16 não tiveram êxito e levaram muito tempo.


Passamos para outra opção - Debian. Existe uma imagem de disco com um sistema instalado para ARM, mas é melhor colocar um sistema limpo com os pacotes e configurações necessários para nós.


Instalação no QEMU


Faça o download da imagem de instalação (link para .iso ) e instale o QEMU.
Também precisamos da imagem do kernel e do initrd para inicializar a instalação, que pode ser baixada aqui .


Crie uma imagem de um cartão de memória com o tamanho de um cartão de memória real (neste caso, 4 GB):


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

Iniciamos a instalação:


 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 

Se você deseja criar um layout de disco com uma distribuição original relativa não padrão, deixe a partição raiz primeiro; caso contrário, você precisará alterar os parâmetros de inicialização do kernel no uBoot. Há o número da partição na qual o sistema de arquivos raiz está localizado.


A marcação padrão contém:


  1. Partição EXT4 para sistema de arquivos raiz de 1.3 GB
  2. Partição FAT32 para armazenar dados do usuário ≈ 500 MB de tamanho

A saída do fdisk para a imagem da distribuição 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 

Depois de definir os parâmetros, deixamos de beber algumas xícaras de chá, porque o emulador não é muito mais rápido que um processador ARM real.


Para iniciar o sistema instalado, você precisa de outra imagem initrd, que pode ser obtida aqui .


Iniciamos o 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" 

Configuração do sistema


Após o início, entramos no superusuário, checamos a conexão com a Internet, atualizamos os repositórios e o sistema, colocamos o conjunto mínimo de programas:


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

Terminais


/etc/inittab , removemos terminais desnecessários, ligamos o UART de que precisamos e adicionamos entrada automática para o usuário certo (use o root somente ao depurar). A entrada automática é útil se você planeja executar o shell para controle no 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 e wifi


Instale o bluez-utils e o wpasupplicant para acessar o Wi-Fi e o Bluetooth.


 apt-get install bluez-utils wpasupplicant 

Desabilitamos a interface eth0 e configuramos a interface wlan1 em /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 

Adicione a rede com antecedência ao /etc/wpa_supplicant.conf , porque fazer isso no próprio controlador não é tão conveniente:


 wpa_passphrase ssid password >> /etc/wpa_supplicant.conf 

Se você não possui acesso Wi-Fi, pode usar o UART para outras configurações, mas lembre-se de que, por padrão, o kernel exibe todos os erros neste terminal. Portanto, durante a operação, uma mensagem repentina do kernel ou serviço pode interrompê-lo.


Adicione um script para ativar o Bluetooth. Desta 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 ;; 

Assim, todos os serviços que requerem o serviço Bluetooth executam os comandos necessários para inicializar.


Deslize para a esquerda, deslize para a direita


Removemos programas e serviços desnecessários que podem ser visualizados usando o htop, porque eles ocupam um lugar precioso na RAM:



Nesse caso, o serviço ConsoleKit possui muitos processos . Mova o arquivo deste serviço para a pasta raiz em caso de recuperação:


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

Antes de desligar o serviço, o consumo de RAM era de 19 MB e depois - de 16 MB.


Seções do sistema


Embora o uBoot transfira para o kernel o dispositivo no qual a partição raiz está localizada, vale a pena escrevê-lo em /etc/fstab para /etc/fstab a confiabilidade. Mudamos a primeira linha responsável pela seção raiz:


 /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 

Se você não criou a partição raiz a primeira, não se esqueça de especificar o número da partição desejada.


Se você deixou a segunda partição FAT para obter dados do usuário, precisa criar uma pasta para montar a partição nela


 mkdir /usr/share/trik 

e escreva a seção em /etc/fstab :


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

Etapa 6. Tentamos nosso mingau


Após configurar a imagem do sistema, você deve montá-la para instalar os módulos do kernel e o próprio kernel:


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

onde, NNNN = tamanho do setor * início da seção. O tamanho padrão do setor é 512 bytes.


Também montamos a distribuição original:


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

Nós removemos o kernel do QEMU e seus módulos, como eles não são destinados à nossa plataforma. Copiamos o novo kernel e módulos, assim como na distribuição 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 

Necessitaremos de firmware para o módulo Wi-Fi, que está na distribuição original na pasta / lib / firmware e no firmware Bluetooth que encontramos anteriormente.


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

Desconecte as imagens de disco:


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

E comece a copiar a imagem para o cartão de memória usando dd:


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

Etapa 7. A linha de chegada


Nós compilamos os programas para conectar o gamepad no novo sistema e instalamos o daemon sixad.


Conectamos o gamepad via USB ao controlador e executamos o programa para criar um par:


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

Quando o gamepad está conectado, nada acontece e o serviço sixad é silencioso:


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

Mas a comunidade Raspberry Pi já fez uma "muleta" para consertar a conexão .


Nós reconstruímos o programa e nos alegramos.


 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] 

Agora o gamepad está disponível para o sistema como um dispositivo de entrada e o programa jstest mostrará o status de todos os botões e 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 

onde X é o número do dispositivo no sistema, por padrão - 2. Os números de botões e eixos podem ser vistos aqui .


Use na prática


Vídeo mostrando o gamepad no YouTube .


Fotos da distribuição

Carregamento do kernel:

Terminal rodando no X11:



E de acordo com a tradição:



Links úteis


Programas para conectar o gamepad Dualshock 3 - sixpair e sixad .


Para gamepads e outros dispositivos de entrada, existe uma biblioteca C leve - libenjoy .


O código fonte do programa para controlar servomotores e motores é o repositório GitHub .


Todos os arquivos de configuração do artigo para um kit de distribuição improvisado são o repositório GitHub .


A fonte do kernel é o repositório do GitHub .


Fatos interessantes sobre o controlador


  • A especificação afirma que a RAM é de 256 MB. Mas se você executar o htop, verá que apenas 128 MB estão disponíveis. Isso é limitado pelas opções do kernel que podem ser exibidas no console do uBoot:

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

O chip de memória está marcado com 3PC22 D9MTD, fabricado pela Micron. Não foi possível encontrar informações sobre o volume atual.


  • O uBoot é armazenado na memória flash SPI na qual o kernel também está conectado e não é usado. Você pode tentar usar este local para suas tarefas ou copiar um novo kernel e reconfigurar o uBoot para usá-lo.

Endereços das imagens do 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" 

  • A tela do controlador, embora pequena, na verdade possui um sensor resistivo. Se o próprio sensor está conectado é desconhecido.
  • O Dualshock 3 possui LEDs no conector USB que mostram o número do gamepad / joystick. Há um gamepad no vídeo, mas seu número é 3. Isso não é um erro, porque existem mais dois "joysticks" no sistema: um acelerômetro e um giroscópio.

Problemas encontrados ao usar


  • Às vezes, o robô fica firme, sem desligar os servomotores, o que lhes permite mudar de posição com relação ao ruído na linha de dados. Isso foi visto mesmo em uma distribuição padrão .
  • A inclusão de controladores PWM é diferente do que está escrito na documentação . Pelo menos em C puro, isso não funcionou.
  • Às vezes, o USB para de funcionar no Debian.

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


All Articles