我正在开发一个嵌入式Linux系统(kernel-5.10.24),系统中有BT控制器。
现在我正在用 BLE 打印机进行测试。
当我进行以下测试时,我感到很困惑。
- 跑步
bluetoothd -- -d -n -C &
- 跑步
bluetooth power on
- 跑步
bluetooth scan on
- 跑步
bluetooth scan off
- 跑步
bluetooth devices
- 将 Linux 板与打印机配对
bluetooth trust 02:00:7A:05:BF:6C
- 运行
rctest -s 02:00:7A:05:BF:6C
,等待约15秒,打印机开始工作。
然后我得到了一个 rfcomm_client.chttps://github.com/balle/bluetooth-snippets/blob/master/rfcomm-client.c。
/*
BlueZ example code to build an rfcomm client.
This code just creates a socket and connects
to a remote bluetooth device and sends a string.
Programmed by Bastian Ballmann
http://www.geektown.de
Compile with gcc -lbluetooth <executable> <source>
*/
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>
#include <bluetooth/hci.h>
int main(int argc, char *argv[])
{
int sock, d;
struct sockaddr_rc laddr, raddr;
struct hci_dev_info di;
if(argc < 4)
{
printf("%s <btaddr> <channel> <cmd>\n", argv[0]);
exit(0);
}
if(hci_devinfo(0, &di) < 0)
{
perror("HCI device info failed");
exit(1);
}
printf("Local device %s\n", batostr(&di.bdaddr));
laddr.rc_family = AF_BLUETOOTH;
laddr.rc_bdaddr = di.bdaddr;
laddr.rc_channel = 0;
raddr.rc_family = AF_BLUETOOTH;
str2ba(argv[1],&raddr.rc_bdaddr);
raddr.rc_channel = atoi(argv[2]);
if( (sock = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM)) < 0)
{
perror("socket");
}
if(bind(sock, (struct sockaddr *)&laddr, sizeof(laddr)) < 0)
{
perror("bind");
exit(1);
}
printf("Remote device %s\n", argv[1]);
if(connect(sock, (struct sockaddr *)&raddr, sizeof(raddr)) < 0)
{
perror("connect");
exit(1);
}
printf("Connected.\nSending data %s\n",argv[3]);
send(sock,argv[3],strlen(argv[3]),0);
printf("Disconnect.\n");
close(sock);
return 0;
}
通过参考rctest.c,我在Linux板上运行了上面的代码,rfcomm_client 02:00:7A:05:BF:6C 10 "Hello world"
将“Hello World”发送到打印机,日志说它有效,但没有打印任何内容。
# ./rfcomm_client 02:00:7A:05:BF:6C 10 "Hello world"
Local device CD:9C:8C:87:95:30
Remote device 02:00:7A:05:BF:6C
Connected.
Sending data Hello world
Disconnect.
内核日志是
[ 3377.840051] Bluetooth: hu 031a528d retransmitting 1 pkts
[ 3377.846977] rtk_btcoex: hci create connection, start paging
[ 3378.017929] rtk_btcoex: connected, handle 000a, status 0x00
[ 3378.023824] rtk_btcoex: Page success
[ 3378.047249] rtk_btcoex: io capability request
[ 3378.888706] rtk_btcoex: link key notify
[ 3378.932547] rtk_btcoex: l2cap op 2, len 16, out 1
[ 3378.937489] rtk_btcoex: TX l2cap conn req, hndl 0x000a, PSM 0x0003, scid 0x0040
[ 3378.945664] rtk_btcoex: l2cap op 3, len 20, out 0
[ 3378.950647] rtk_btcoex: RX l2cap conn rsp, hndl 0x000a, dcid 0x0051, scid 0x0040, result 0x0000
[ 3378.959714] rtk_btcoex: l2cap connection success, update connection
[ 3378.966218] rtk_btcoex: update_profile_connection: is_add 1, profile_index 3
[ 3378.973533] rtk_btcoex: update_profile_connection: phci_conn->profile_bitmap 0x08
[ 3378.981289] rtk_btcoex: rtk_notify_profileinfo_to_fw: BufferSize 5
[ 3378.987690] rtk_btcoex: rtk_notify_profileinfo_to_fw: NumberOfHandles 1
[ 3378.994553] rtk_btcoex: rtk_notify_profileinfo_to_fw: handle 0x000a
[ 3379.001058] rtk_btcoex: rtk_notify_profileinfo_to_fw: profile_bitmap 0x08
[ 3379.008117] rtk_btcoex: rtk_vendor_cmd_to_fw: opcode 0xfc19
[ 3379.053843] rtk_btcoex: l2cap op 6, len 16, out 1
[ 3379.058794] rtk_btcoex: TX l2cap disconn req, hndl 0x000a, dcid 0x0051, scid 0x0040
[ 3379.066767] rtk_btcoex: handle_l2cap_discon_req: handle 0x000a, dcid 0x0051, scid 0x0040, dir 1
[ 3379.075799] rtk_btcoex: update_profile_connection: is_add 0, profile_index 3
[ 3379.083122] rtk_btcoex: rtk_check_del_timer: handle 0x a
[ 3379.088817] rtk_btcoex: update_profile_connection: phci_conn->profile_bitmap 0x00
[ 3379.096592] rtk_btcoex: rtk_notify_profileinfo_to_fw: BufferSize 2
[ 3379.103003] rtk_btcoex: rtk_notify_profileinfo_to_fw: NumberOfHandles 0
[ 3379.109845] rtk_btcoex: rtk_vendor_cmd_to_fw: opcode 0xfc19
[ 3379.115646] rtk_btcoex: Delete profile: hndl 0x000a, psm 0x0003, dcid 0x0051, scid 0x0040
[ 3379.714324] rtk_btcoex: disconn cmpl evt: status 0x00, handle 000a, reason 0x13
[ 3379.721942] rtk_btcoex: process disconn complete event.
我重新检查了do_send()
rctest.c中的(它用于channel=10
在do_connect()函数中连接到打印机,我在运行时使用了相同的通道10 rfcomm_client
),并发现了以下代码,
577 seq = 0;
578 while ((num_frames == -1) || (num_frames-- > 0)) {
579 put_le32(seq, buf);
580 put_le16(data_size, buf + 4);
581
582 seq++;
583
584 if (send(sk, buf, data_size, 0) <= 0) {
585 syslog(LOG_ERR, "Send failed: %s (%d)",
586 strerror(errno), errno);
587 exit(1);
588 }
589
590 if (num_frames && delay && count && !(seq % count))
591 usleep(delay);
592 }
num_frames = -1;
, count = 1
, delay = 0
, data_size=127
,似乎rctest
正在紧密循环地发送 127 个字节,并且打印机工作了。
但rfcomm_client.c
没有用。
问题是什么?如何解决?
答案1
经过大量测试,我想我找到了一些东西。
打印机能够工作是因为rctest
向打印机发送了一些数据,并且这些数据恰好是有效的打印机命令。
因此,需要向打印机制造商寻求打印机的SDK,以实现对打印机的完全控制。
到目前为止,我找到了两个可以由打印机响应的数据帧。我会询问打印机的 SDK。
答案2
您发送的行不包含行尾字符(\n
或者可能不包含行尾字符\r\n
,具体取决于打印机配置)。
大多数逐行打印机会等到收到完整的行后才开始打印,然后一次性打印该行,以最大程度地减少任何机械误差的影响。
激光打印机通常会一次打印整个页面,因此只有在获得足够的文本行完全填满页面或换页字符后才会启动\f
。