3 * BlueZ - Bluetooth protocol stack for Linux
5 * Copyright (C) 2000-2001 Qualcomm Incorporated
6 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
7 * Copyright (C) 2002-2008 Marcel Holtmann <marcel@holtmann.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
39 #include <sys/socket.h>
41 #include <bluetooth/bluetooth.h>
42 #include <bluetooth/hci.h>
43 #include <bluetooth/hci_lib.h>
44 #include <bluetooth/l2cap.h>
47 static bdaddr_t bdaddr;
49 static int ident = 200;
51 static int count = -1;
52 static int timeout = 10;
53 static int reverse = 0;
56 static int sent_pkt = 0;
57 static int recv_pkt = 0;
59 static float tv2fl(struct timeval tv)
61 return (float)(tv.tv_sec*1000.0) + (float)(tv.tv_usec/1000.0);
64 static void stat(int sig)
66 int loss = sent_pkt ? (float)((sent_pkt-recv_pkt)/(sent_pkt/100.0)) : 0;
67 printf("%d sent, %d received, %d%% loss\n", sent_pkt, recv_pkt, loss);
71 static void ping(char *svr)
74 struct sockaddr_l2 addr;
81 memset(&sa, 0, sizeof(sa));
83 sigaction(SIGINT, &sa, NULL);
85 buf = malloc(L2CAP_CMD_HDR_SIZE + size);
87 perror("Can't allocate buffer");
92 sk = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP);
94 perror("Can't create socket");
99 /* Bind to local address */
100 memset(&addr, 0, sizeof(addr));
101 addr.l2_family = AF_BLUETOOTH;
102 bacpy(&addr.l2_bdaddr, &bdaddr);
104 if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
105 perror("Can't bind socket");
111 /* Connect to remote device */
112 memset(&addr, 0, sizeof(addr));
113 addr.l2_family = AF_BLUETOOTH;
114 str2ba(svr, &addr.l2_bdaddr);
116 if (connect(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
117 perror("Can't connect");
123 /* Get local address */
124 memset(&addr, 0, sizeof(addr));
125 optlen = sizeof(addr);
127 if (getsockname(sk, (struct sockaddr *) &addr, &optlen) < 0) {
128 perror("Can't get local address");
134 ba2str(&addr.l2_bdaddr, str);
135 printf("Ping: %s from %s (data size %d) ...\n", svr, str, size);
137 /* Initialize buffer */
138 for (i = 0; i < size; i++)
139 buf[L2CAP_CMD_HDR_SIZE + i] = (i % 40) + 'A';
143 while (count == -1 || count-- > 0) {
144 struct timeval tv_send, tv_recv, tv_diff;
145 l2cap_cmd_hdr *cmd = (l2cap_cmd_hdr *) buf;
147 /* Build command header */
149 cmd->len = htobs(size);
152 cmd->code = L2CAP_ECHO_RSP;
154 cmd->code = L2CAP_ECHO_REQ;
156 gettimeofday(&tv_send, NULL);
158 /* Send Echo Command */
159 if (send(sk, buf, L2CAP_CMD_HDR_SIZE + size, 0) <= 0) {
160 perror("Send failed");
164 /* Wait for Echo Response */
171 pf[0].events = POLLIN;
173 if ((err = poll(pf, 1, timeout * 1000)) < 0) {
174 perror("Poll failed");
183 if ((err = recv(sk, buf, L2CAP_CMD_HDR_SIZE + size, 0)) < 0) {
184 perror("Recv failed");
189 printf("Disconnected\n");
193 cmd->len = btohs(cmd->len);
195 /* Check for our id */
196 if (cmd->ident != id)
200 if (!reverse && cmd->code == L2CAP_ECHO_RSP)
203 if (cmd->code == L2CAP_COMMAND_REJ) {
204 printf("Peer doesn't support Echo packets\n");
214 gettimeofday(&tv_recv, NULL);
215 timersub(&tv_recv, &tv_send, &tv_diff);
217 printf("%d bytes from %s id %d time %.2fms\n", cmd->len, svr, id - ident, tv2fl(tv_diff));
222 printf("no response from %s: id %d\n", svr, id - ident);
231 static void usage(void)
233 printf("l2ping - L2CAP ping\n");
235 printf("\tl2ping [-i device] [-s size] [-c count] [-t timeout] [-d delay] [-f] [-r] <bdaddr>\n");
238 int main(int argc, char *argv[])
242 /* Default options */
243 bacpy(&bdaddr, BDADDR_ANY);
245 while ((opt=getopt(argc,argv,"i:d:s:c:t:fr")) != EOF) {
248 if (!strncasecmp(optarg, "hci", 3))
249 hci_devba(atoi(optarg + 3), &bdaddr);
251 str2ba(optarg, &bdaddr);
255 delay = atoi(optarg);
259 /* Kinda flood ping */
264 /* Use responses instead of requests */
269 count = atoi(optarg);
273 timeout = atoi(optarg);
286 if (!(argc - optind)) {