如何以复杂的方式在Linux上设置蓝牙


在筹备年度IT论坛时,提出了创建一个由无线游戏手柄控制的简单操纵器的想法,以演示微控制器和单板计算机的功能。 在论坛开始前一个月,手边有一个TRIC控制器,几个伺服电机,一个铁结构构造器。


“一切都按计划进行,”但在这种情况下并非如此。


阶段1.准备


Linux上的TRIC对于这样的操纵器来说是一个破灭,但是“问题是过时的可用性和维护性”(关于智能对讲机中 Linux的ClusterM引用)。


阅读规范后 ,发现它具有蓝牙。 如果您使用此控制器,那么您将知道程序是通过Wi-Fi进行传输的,并且没有其他便捷的通讯方式。 菜单中没有提到蓝牙。 但是,如何呢?


带着SSH,螺丝起子和好奇心,我开始寻找蓝牙。 该系统包括hcitool,hciconfig和bluetoothd守护程序。 他们所有人都说他不在那儿。


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 

我继续打电话寻找外部USB模块的朋友。


拆卸控制器后,找到了Jorjin WG7311-0A模块。 该规范指出,确实存在Wi-Fi,蓝牙甚至FM收音机。 与蓝牙通信的接口是UART,并且已通过BT_EN打开。



在阅读了如何通过hcitool通过UART连接蓝牙模块后,我一无所获。 三个空闲UART端口中的两个处于静默状态。


但是我们已经联系BT_EN! 可能只是简单地关闭了模块并且不响应请求。 在检查用于ARM设备的Linux内核设备后,找到了一个文件,在该文件中注册了SoC使用的所有联系人。 通过在内核源代码中打开arch/arm/mach-davinci/board-da850-trik.c ,实际上找到了用于蓝牙的GPIO触点。 胜利了! 我以为


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

第二阶段。进攻


要通过GPIO启用联系人,您需要找到其端到端的序列号。 我们在内核代码中找到以下行,其中包含初始化arch/arm/mach-davinci/board-da850-trik.c


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

它使用宏GPIO_TO_PIN。 请参阅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)) 

使用它,您可以找到端到端的联系电话。 我们得到的是16 * 6 + 11 =107。现在我们转到包含联系。


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

echo命令中的0或1是接触状态。


运行命令进行连接并...


 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 

我们目前无法理解的错误消息。 我们尝试通过hcitool配置设备:


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

尽管据称初始化已通过,但没有设备。 我们尝试使用不同类型的适配器进行第二次连接:


 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 

再说一遍,什么都没有。 让我们回到第一个错误,运用英语知识:


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

我们使用固件打开文件夹/ lib / firmware,但找不到所需的文件。 在Internet上进行长时间搜索后,我们在TI存储库中找到了所需的文件并下载了该文件。 同一文件的其他版本拒绝工作。


 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 

我们重新启动控制器并重新连接:


 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 

万岁! 固件已启动。 检查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 

我们启动蓝牙服务,扫描设备并检测我们的模块:


 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 

计算机搜索找到设备:



要启用蓝牙,您可以创建一个脚本:


 #!/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) ;; *) ;; 

并将其添加到自动运行:


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

模块的重启和关机行为异常,因此stop和restart选项没有命令。


第三阶段。沟通检查


双向验证通讯的最简单方法是COM端口服务。 使用一些命令,将其打开:


 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 

我们通过电话连接,并看到进入系统的邀请:



没有一个经过测试的终端允许输入空的用户密码,因此我不得不在SSH会话中使用线程重定向发送登录信息。


阶段4. ./configure && make


按照将游戏手柄连接到Linux的说明进行操作我们遇到以下问题:


  • 发行版中的BlueZ已过时,无法理解来自Sixad守护程序的命令,该守护程序与游戏手柄建立了连接
  • 由于许多依赖性,源中的新BlueZ版本拒绝编译
  • Fresh Debian的BlueZ需要udev和systemd,这是当前发行版中所缺少的

唯一可以满足的依赖性是uinput内核模块。


为此:


  • 获取设备上当前内核的配置

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

  • 下载内核代码
  • 下载并安装工具链
  • 将内核配置复制到包含内核代码的文件夹中
  • 将uinput模块添加到配置中

 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 

  • 构建uBoot映像并将其复制到/ boot

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

现在程序不会因为缺少内核模块而发誓,但是我们什么也做不了。 游戏手柄的说明将在以后派上用场。


阶段5.从斧头煮粥


进入计划“窃贼”。 由于没有方便的方法将必要的程序放在原始发行版中,因此我们将流行一些。 该处理器具有ARMv5TE架构,这意味着它具有发行版。


我们尝试解压缩并运行适用于ARM的通用Arch Linux,并在将其加载到控制台中时发现systemd需要更新的内核版本,而我们没有。 尝试转移4.16内核失败,并且花费了太多时间。


我们转到另一个选项-Debian。 存在一个带有用于ARM的已安装系统的磁盘映像,但是最好为我们提供一个具有必要程序包和设置的干净系统。


在QEMU中安装


下载安装映像(链接到.iso )并安装QEMU。
我们还需要内核和initrd映像来启动安装,可以从此处下载。


创建具有实际存储卡大小(在本例中为4 GB)的存储卡映像:


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

我们开始安装:


 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 

如果要使用非标准相对原始发行版进行磁盘布局,请先保留根分区,否则必须在uBoot中更改内核启动参数。 根文件系统所在的分区号。


标准标记包含:


  1. ≈1.3 GB根文件系统的EXT4分区
  2. FAT32分区,用于存储≈500 MB的用户数据

原始发行版映像的fdisk输出:


 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 

设置完参数后,我们离开去喝几杯茶,因为 仿真器并不比真正的ARM处理器快多少。


要启动已安装的系统,您需要另一个initrd映像,可从此处获取


我们启动系统:


 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" 

系统设定


启动后,我们输入超级用户,检查与Internet的连接,更新存储库和系统,放入最少的程序集:


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

码头


我们编辑/etc/inittab ,删除不必要的端子,打开我们需要的UART并为正确的用户添加自动输入(仅在调试时使用root)。 如果您打算运行外壳程序以在控制器上进行控制,则自动输入很有用。


 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 

蓝牙和WiFi


安装bluez-utils和wpasupplicant以访问Wi-Fi和蓝牙。


 apt-get install bluez-utils wpasupplicant 

我们禁用eth0接口,并在/etc/network/interfaces配置wlan1 /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 

预先将网络添加到/etc/wpa_supplicant.conf ,因为 在控制器本身上执行此操作不太方便:


 wpa_passphrase ssid password >> /etc/wpa_supplicant.conf 

如果您没有Wi-Fi访问权限,则可以使用UART进行进一步的配置,但是请记住,默认情况下,内核会向该终端显示所有错误。 因此,在运行期间,来自内核或服务的突然消息可能会打扰您。


添加脚本以启用蓝牙。 这次,修改/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 ;; 

因此,所有需要蓝牙服务的服务都将运行必要的命令以进行初始化。


向左滑动,向右滑动


我们删除了可以使用htop查看的不必要的程序和服务,因为它们在RAM中占据了宝贵的位置:



在这种情况下,ConsoleKit服务具有许多进程 。 如果恢复,请将此服务的文件移动到根文件夹:


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

关闭服务之前,RAM消耗为19 MB,之后为16 MB。


系统部分


尽管uBoot将根分区所在的设备转移到内核,但是值得一提的是将其写入/etc/fstab以提高可靠性。 我们更改负责根部分的第一行:


 /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 

如果您没有将根分区设为第一个分区,请不要忘记指定所需的分区号。


如果您将第二个FAT分区留给用户数据,则需要创建一个文件夹来将分区挂载到其中


 mkdir /usr/share/trik 

并在/etc/fstab编写该部分:


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

第六阶段,我们尝试粥


配置系统映像之后,必须将其挂载以安装内核模块和内核本身:


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

其中,NNNN =扇区大小*部分的开头。 默认扇区大小为512字节。


我们还安装了原始发行版:


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

我们删除了QEMU及其模块的内核,如下所示: 它们不适用于我们的平台。 我们复制新的内核和模块,就像在原始发行版上一样。


 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 

我们将需要用于Wi-Fi模块的固件,该固件位于/ lib /固件文件夹中的原始发行版中,以及我们之前找到的Bluetooth固件。


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

断开磁盘映像:


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

然后开始使用dd将映像复制到存储卡:


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

阶段7.终点线


我们在新系统上编译用于连接游戏手柄的程序,并安装sixad守护程序。


我们通过USB将游戏手柄连接到控制器,然后运行程序以创建一个配对:


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

连接游戏手柄后,什么也没有发生,并且Sixad服务处于静默状态:


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

但是Raspberry Pi社区已经做出了“拐杖”来修复连接


我们重建程序并欣喜。


 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] 

现在游戏手柄可以作为输入设备供系统使用,并且jstest程序将显示所有按钮和模拟传感器的状态:


 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 

其中X是系统中的设备编号,默认为-2。可以在此处查看按钮和轴的数量。


实际使用


YouTube上显示游戏手柄的视频


发行照片

内核加载:

在X11上运行的终端:



并根据传统:



有用的链接


连接Dualshock 3游戏手柄-SixpairSixad的程序


对于游戏手柄和其他输入设备,有一个轻量级的C库-libenjoy


用于控制伺服电动机和电动机的程序的源代码是GitHub存储库


临时分发工具包文章中的所有配置文件都是GitHub存储库


内核源是GitHub存储库


关于控制器的有趣事实


  • 规范指出RAM为256 MB。 但是,如果运行htop,您将看到只有128 MB可用。 这受可在uBoot控制台中查看的内核选项的限制:

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

该存储芯片标有Micron生产的3PC22 D9MTD。 无法找到有关其当前数量的信息。


  • uBoot存储在也连接了内核的SPI闪存中,因此不使用。 您可以尝试使用该位置执行任务,或者复制新内核并重新配置uBoot,以便它使用它。

来自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" 

  • 控制器的屏幕虽然很小,但实际上有一个电阻传感器。 传感器本身是否已连接尚不清楚。
  • Dualshock 3在USB连接器上具有LED,这些LED显示游戏手柄/操纵杆的编号。 视频中只有一个游戏手柄,但数量为3。这不是错误,因为 系统中还有两个“操纵杆”:一个加速度计和一个陀螺仪。

使用中遇到的问题


  • 机器人有时会挂得很紧,而没有关闭伺服电机,这使它们可以根据数据线上的噪声来改变位置。 即使在标准发行版中也可以看到这一点。
  • PWM控制器的内容与文档中的内容有所不同。 至少在纯C中这是行不通的。
  • USB有时会在Debian上停止工作。

Source: https://habr.com/ru/post/zh-CN415007/


All Articles