例一:发送Signaling Packet:
Signaling Command是2个Bluetooth实体之间的L2CAP层命令传输。所以得Signaling Command使用CID 0x0001.
多个Command可以在一个C-frame(control frame)中发送。
<wbr></wbr>
<wbr>如果要直接发送Signaling Command.需要建立SOCK_RAW类型的L2CAP连接Socket。这样才有机会自己填充Command Code,Identifier等。</wbr>
<wbr></wbr>
以下是一个发送signaling Command以及接收Response的简单例子:
int main(int argc, char** argv)
{
<wbr>int l2_sck = 0;<br><wbr>int iRel<wbr> = 0;<br><wbr>struct sockaddr_l2 local_l2_addr;<br><wbr>struct sockaddr_l2 remote_l2_addr;<br><wbr>char str[24] ={0};<br><wbr>int len = 0;<br><wbr>int size = 50;<br><wbr>char* send_buf;<br><wbr>char* recv_buf;<br><wbr>int i = 0;<br><wbr>int id = 1; //不要为0<br><wbr><br><wbr>send_buf = malloc(L2CAP_CMD_HDR_SIZE + size);<br><wbr>recv_buf = malloc(L2CAP_CMD_HDR_SIZE + size);<br><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>if(argc < 2)<br><wbr>{<br><wbr><wbr>printf("\n%s <bdaddr>\n", argv[0]);<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>// create l2cap raw socket<br><wbr>l2_sck = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP); //创建L2CAP protocol的RAW Packet<br><wbr>if(l2_sck < 0)<br><wbr>{<br><wbr><wbr>perror("\nsocket:");<br><wbr><wbr>return -1;<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>//bind<br><wbr>memset(&local_l2_addr, 0, sizeof(struct sockaddr_l2));<br><wbr>local_l2_addr.l2_family = PF_BLUETOOTH;<br><wbr>bacpy(&local_l2_addr.l2_bdaddr , BDADDR_ANY);</wbr></wbr></wbr></wbr>
<wbr>iRel = bind(l2_sck, (struct sockaddr*) &local_l2_addr, sizeof(struct sockaddr_l2));<br><wbr>if(iRel < 0)<br><wbr>{<br><wbr><wbr>perror("\nbind()");<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>//connect<br><wbr>memset(&remote_l2_addr, 0 , sizeof(struct sockaddr_l2));<br><wbr>remote_l2_addr.l2_family = PF_BLUETOOTH;<br><wbr>//printf("\nConnect to %s\n", argv[1]);<br><wbr>str2ba(argv[1], &remote_l2_addr.l2_bdaddr);</wbr></wbr></wbr></wbr></wbr>
<wbr>iRel = connect(l2_sck, (struct sockaddr*)&remote_l2_addr, sizeof(struct sockaddr_l2));<br><wbr>if(iRel < 0)<br><wbr>{<br><wbr><wbr>perror("\nconnect()");<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>//get local bdaddr<br><wbr>len = sizeof(struct sockaddr_l2);<br><wbr>memset(&local_l2_addr, 0, sizeof(struct sockaddr_l2));</wbr></wbr></wbr>
//注意,getsockname()参数三是一个输入输出参数。输入时,为参数二的总体长度。输出时,
//为实际长度。
<wbr>iRel = getsockname(l2_sck, (struct sockaddr*) &local_l2_addr, &len);<br><wbr>if(iRel < 0)<br><wbr>{<br><wbr><wbr>perror("\ngetsockname()");<br><wbr><wbr>exit(0);<br><wbr>}<br><wbr>ba2str(&(local_l2_addr.l2_bdaddr), str);<br><wbr>//printf("\nLocal Socket bdaddr:[%s]\n", str);<br><wbr>printf("l2ping: [%s] from [%s](data size %d) ...\n", argv[1], str, size);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>for (i = 0; i < size; i++)<br><wbr><wbr>send_buf[L2CAP_CMD_HDR_SIZE + i] = 'A';</wbr></wbr></wbr>
<wbr>l2cap_cmd_hdr *send_cmd = (l2cap_cmd_hdr *) send_buf;<br><wbr>l2cap_cmd_hdr *recv_cmd = (l2cap_cmd_hdr *) recv_buf;</wbr></wbr>
<wbr>send_cmd->ident = id;<wbr><wbr>//如上图所示,这一项为此Command Identifier<br><wbr>send_cmd->len<wbr><wbr> = htobs(size);<br><wbr>send_cmd->code = L2CAP_ECHO_REQ;<wbr><strong>//如上图所示,此项为Command code.这项定为:</strong></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
//Echo Request。对端会发送Response回来。code=L2CAP_ECHO_RSP
<wbr><br><wbr>while(1)<br><wbr>{<br><wbr><wbr>send_cmd->ident = id;<br><wbr><wbr>if(send(l2_sck, send_buf, size + L2CAP_CMD_HDR_SIZE, 0) <= 0)<br><wbr><wbr>{<br><wbr><wbr><wbr>perror("\nsend():");<br><wbr><wbr>}<br><wbr><wbr><br><wbr><wbr>while(1)<br><wbr><wbr>{<br><wbr><wbr><wbr>if(recv(l2_sck, recv_buf, size + L2CAP_CMD_HDR_SIZE, 0) <= 0)<br><wbr><wbr><wbr>{<br><wbr><wbr><wbr><wbr>perror("\nrecv()");<br><wbr><wbr><wbr>}<br><wbr><wbr><wbr><br><wbr><wbr><wbr>if (recv_cmd->ident != id)<br><wbr><wbr><wbr><wbr>continue;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>if( recv_cmd->code == L2CAP_ECHO_RSP)<br><wbr><wbr><wbr>{<br><wbr><wbr><wbr><wbr>//printf("\nReceive Response Packet.\n");<br><wbr><wbr><wbr><wbr>printf("%d bytes from [%s] id %d\n", recv_cmd->len, argv[1], recv_cmd->ident);<br><wbr><wbr><wbr><wbr>break;<br><wbr><wbr><wbr>}<br><wbr><wbr><wbr><br><wbr><wbr>}<br><wbr><wbr>sleep(1);<br><wbr><wbr>id ++;<br><wbr><wbr><br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>close(l2_sck);<br><wbr><br><wbr><br><wbr></wbr></wbr></wbr></wbr>
<wbr>return 0;<br>
}<br></wbr>
所以说,如果想要发送接收signaling Command。只需要建立l2cap RAW socket. 并按规则填充command id, command code等。就可以接收发送了。
<wbr></wbr>
Command Code: 这个值放在l2cap.h中。
#define L2CAP_COMMAND_REJ<wbr>0x01<br>
#define L2CAP_CONN_REQ<wbr><wbr>0x02<br>
#define L2CAP_CONN_RSP<wbr><wbr>0x03<br>
#define L2CAP_CONF_REQ<wbr><wbr>0x04<br>
#define L2CAP_CONF_RSP<wbr><wbr>0x05<br>
#define L2CAP_DISCONN_REQ<wbr>0x06<br>
#define L2CAP_DISCONN_RSP<wbr>0x07<br>
#define L2CAP_ECHO_REQ<wbr><wbr>0x08<br>
#define L2CAP_ECHO_RSP<wbr><wbr>0x09<br>
#define L2CAP_INFO_REQ<wbr><wbr>0x0a<br>
#define L2CAP_INFO_RSP<wbr><wbr>0x0b<br></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr></wbr>
<wbr></wbr>
<wbr></wbr>
例二:任意PSM的L2CAP连接间数据的传输:
此例子中:Server,client其实是使用网络的概念定义的。
server用来监听指定PSM的连接,并监听数据。同时,利用poll来查看peer是否断掉了。
Server:
<wbr></wbr>
#include <stdio.h>
#include <sys/types.h><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><br>
#include <sys/socket.h><br>
#include <stdlib.h><br>
#include <poll.h></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/l2cap.h>
void * Read_thread(void* pSK);
int main(int argc, char** argv)
{
<wbr>int iRel = 0;<br><wbr>int sk = 0;<br><wbr>struct sockaddr_l2 local_addr;<br><wbr>struct sockaddr_l2 remote_addr;<br><wbr>int len;<br><wbr>int nsk = 0;<br><wbr>pthread_t nth = 0;<br><wbr>struct l2cap_options opts;<br><wbr>int optlen = 0;<br><wbr>int slen = 0;<br><wbr>char str[16] = {0};</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>if(argc < 2)<br><wbr>{<br><wbr><wbr>printf("\nUsage:%s psm\n", argv[0]);<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><br><wbr>// create l2cap socket<br><wbr>sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);<wbr> //发送数据,使用SOCK_SEQPACKET为好<br><wbr>if(sk < 0)<br><wbr>{<br><wbr><wbr>perror("\nsocket():");<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>//bind<br><wbr>local_addr.l2_family = PF_BLUETOOTH;<br><wbr>local_addr.l2_psm = htobs(atoi(argv[argc -1]));<wbr> //last psm<br><wbr>bacpy(&local_addr.l2_bdaddr, BDADDR_ANY);<br><wbr>iRel = bind(sk, (struct sockaddr *)&local_addr, sizeof(struct sockaddr));<br><wbr>if(iRel < 0)<br><wbr>{<br><wbr><wbr>perror("\nbind()");<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>//get opts</wbr>
//<wbr></wbr>in mtu 和 out mtu.每个包的最大值
<wbr>memset(&opts, 0, sizeof(opts));<br><wbr>optlen = sizeof(opts);<br><wbr>getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &optlen);<br><wbr>printf("\nomtu:[%d]. imtu:[%d]. flush_to:[%d]. mode:[%d]\n", opts.omtu, opts.imtu, opts.flush_to, opts.mode);</wbr></wbr></wbr></wbr>
<wbr>//set opts. default value<br><wbr>opts.omtu = 0;<br><wbr>opts.imtu = 672;<br><wbr>if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0)<br><wbr>{<br><wbr><wbr>perror("\nsetsockopt():");<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>//listen<br><wbr>iRel = listen(sk, 10);<br><wbr>if(iRel < 0)<br><wbr>{<br><wbr><wbr>perror("\nlisten()");<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr></wbr>
<wbr>len = sizeof(struct sockaddr_l2);<br><wbr>while(1)<br><wbr>{<br><wbr><wbr>memset(&remote_addr, 0, sizeof(struct sockaddr_l2));<br><wbr><wbr>nsk = accept(sk, (struct sockaddr*)(&remote_addr), &len);<br><wbr><wbr>if(nsk < 0)<br><wbr><wbr>{<br><wbr><wbr><wbr>perror("\naccept():");<br><wbr><wbr><wbr>continue;<br><wbr><wbr>}<br><wbr><wbr>ba2str(&(remote_addr.l2_bdaddr), str);<br><wbr><wbr>printf("\npeer bdaddr:[%s].\n", str);<wbr> //得到peer的信息</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr>iRel = pthread_create(&nth, NULL, Read_thread, &nsk);<br><wbr><wbr>if(iRel != 0)<br><wbr><wbr>{<br><wbr><wbr><wbr>perror("pthread_create():");<br><wbr><wbr><wbr>continue;<br><wbr><wbr>}<br><wbr><wbr>pthread_detach(nth);<wbr> // 分离之<br><wbr><wbr><br><wbr>}<br><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>return 0;<br>
}</wbr>
void * Read_thread(void* pSK)
{
<wbr>//struct pollfd fds[10];<br><wbr>struct<wbr><wbr> pollfd<wbr><wbr> fds[100];<br><wbr>char buf[1024] = {0};<br><wbr>int iRel = 0;<br><wbr>int exit_val = 0;<br><wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>//fds[0].fd = *(int*)pSK;<br><wbr>//fds[0].events = POLLIN | POLLHUP;</wbr></wbr>
<wbr>fds[0].fd<wbr><wbr> =<wbr><wbr> (int)(*(int*)pSK);<br><wbr>fds[0].events<wbr><wbr> =<wbr><wbr> POLLIN<wbr><wbr> |<wbr><wbr> POLLHUP;</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr></wbr>
<wbr>while(1)<br><wbr>{<br><wbr><wbr>if(poll(fds, 1, -1) < 0)<br><wbr><wbr>{<br><wbr><wbr><wbr>perror("\npoll():");<br><wbr><wbr>}<br><wbr><wbr>if(fds[0].revents & POLLHUP)<br><wbr><wbr>{<br><wbr><wbr><wbr>//hang up<br><wbr><wbr><wbr>printf("\n[%d] Hang up\n", *(int*)pSK);<br><wbr><wbr><wbr>close(*(int*)pSK);<br><wbr><wbr><wbr>pthread_exit(&exit_val);</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr><wbr><wbr>break;<br><wbr><wbr>}</wbr></wbr></wbr></wbr></wbr>
<wbr><wbr>if(fds[0].revents & POLLIN)<br><wbr><wbr>{<br><wbr><wbr><wbr>memset(buf, 0 , 1024);<br><wbr><wbr><wbr>//read data<br><wbr><wbr><wbr>iRel = recv(*(int*)pSK, buf, 572, 0);<br><wbr><wbr><wbr>//printf("\nHandle[%d] Receive [%d] data:[%s]", *(int*)pSK, iRel, buf);<br><wbr><wbr>}<br><wbr><wbr><br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>return 0;<br>
}<br></wbr>
<wbr></wbr>
<wbr></wbr>
client:
#include <stdio.h>
#include <sys/types.h><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><wbr><br>
#include <sys/socket.h><br>
#include <unistd.h></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/l2cap.h>
int main(int argc, char** argv)
{
<wbr>int sk;<br><wbr>int i = 0;<br><wbr>char buf[24] = "Sam is Good Guy!";<br><wbr>struct sockaddr_l2 local_addr;<br><wbr>struct sockaddr_l2 remote_addr;<br><wbr>int iRel = 0;</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>if(argc < 3)<br><wbr>{<br><wbr><wbr>printf("\nUsage:%s <bdaddr> <PSM>\n", argv[0]);<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>sk = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP);<br><wbr>if(sk < 0)<br><wbr>{<br><wbr><wbr>perror("\nsocket():");<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>//bind. bluetooth好像不许有无名Socket<br><wbr>local_addr.l2_family = PF_BLUETOOTH;<br><wbr>bacpy(&local_addr.l2_bdaddr, BDADDR_ANY);<br><wbr>iRel = bind(sk, (struct sockaddr *)&local_addr, sizeof(struct sockaddr));<br><wbr>if(iRel < 0)<br><wbr>{<br><wbr><wbr>perror("\nbind()");<br><wbr><wbr>exit(0);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>memset(&remote_addr, 0, sizeof(struct sockaddr_l2));<br><wbr>remote_addr.l2_family = PF_BLUETOOTH;<br><wbr>str2ba(argv[1], &remote_addr.l2_bdaddr);<br><wbr>remote_addr.l2_psm = htobs(atoi(argv[argc -1]));<br><wbr><br><wbr>connect(sk, (struct sockaddr*)&remote_addr, sizeof(struct sockaddr_l2));</wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>for(i = 0; i < 60; i++)<br><wbr>{<br><wbr><wbr>iRel = send(sk, buf, strlen(buf)+1, 0);<br><wbr><wbr>printf("Send [%d] data\n", strlen(buf)+1);<br><wbr><wbr>sleep(1);<br><wbr>}</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>
<wbr>close(sk);<br><wbr>return 0;<br>
}</wbr></wbr>
<wbr></wbr>
<wbr></wbr>
注意:
1. 在Linux 网络编程中,主动发起连接方,因为不关心地址具体是什么,所以可以作为无名socket,也就是说可以不bind. 但Bluetooth则不可以,一定需要bind.
2. poll可以查出连接断连,但需要注意:断开的revent值为:11001B。也就是说:POLLIN | POLLERR |POLLHUP。
3. 被连接一方,一定要指定PSM。
分享到:
相关推荐
this source code contains the way of data transmission over l2cap sockets of bluetooth under Linux Environment.
实战Linux Bluetooth编程, 用了bluez,有图有真相
Linux Bluetooth 编程介绍
实战Linux_Bluetooth编程,熟悉蓝牙开发...
Linux Bluetooth编程原理和实践
驱动层、蓝牙核心及 HCI 层、L2CAP 与 SCO 音频层、 RFCOMM, BNEP, CMTP 与 HIDP 层、通用蓝牙 SDP 库和后 台服务及面向所有层的标准套接字接口;在用户空间提供了 蓝牙配置、测试及协议分析等工具。其组织结构如图 ...
最详细的linux蓝牙协议栈的讲解,完全从代码的角度分析,从运行态log进行总结
5.2 L2CAP层编程 5.3 SDP层编程 六Bluetooth 之启动过程实 6.1 Bluetooth 启动步骤 6.2 Bluetooth 启动流程 6.3 Bluetooth数据流向 6.4 Bluez控制流程 .6.5 Bluetooth 启动过程分 七 Bluetooth 之驱动移植 7.1 ...
EEE
蓝牙协议l2cap层封包细节文档,方便底层开发
一份介绍bluetooth编程的pdf资料,很详细。介绍了在linux windows等OS上如何对bluetooth进行操作。
Affix is a Bluetooth Protocol Stack for Linux developed by Nokia Research Center in Helsinki and released under GPL. See CREDITS. Affix supports core Bluetooth protocols like HCI, L2CAP 1.1, L2CAP 1.2...
基于嵌入式Linux的Bluetooth数据通信.pdf
蓝牙协议栈 Bluetooth stack 这是一个包含传统蓝牙跟低功耗蓝牙的协议栈,属于超轻量级蓝牙协议栈,用作学习蓝牙协议栈的人使用 我根据此部分也搭建了一个开发环境,来作为额外收入,希望大家多多支持。有不足支持...
realtek 蓝牙 linux驱动源码和移植指导文档
linux下蓝牙驱动代码的阅读笔记,希望能够给需要的人带来启发。
BlueZ - Bluetooth protocol stack for Linux for Linux v2.13.6.
BlueZ,Linux Bluetooth Development,Linux 蓝牙开发
Linux网络系统中 蓝牙部分的相关程序
Bluetooth Low Energy technology recap and Linux Bluetooth Stack Introduction.