对从 Linux 连接 BLE 打印机感到困惑

对从 Linux 连接 BLE 打印机感到困惑

我正在开发一个嵌入式Linux系统(kernel-5.10.24),系统中有BT控制器。

现在我正在用 BLE 打印机进行测试。
当我进行以下测试时,我感到很困惑。

  1. 跑步bluetoothd -- -d -n -C &
  2. 跑步bluetooth power on
  3. 跑步bluetooth scan on
  4. 跑步bluetooth scan off
  5. 跑步bluetooth devices
  6. 将 Linux 板与打印机配对bluetooth trust 02:00:7A:05:BF:6C
  7. 运行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

相关内容