]>
code.delx.au - pulseaudio/blob - src/modules/bt-proximity-helper.c
2 * Small SUID helper that allows us to ping a BT device. Borrows
3 * heavily from bluez-utils' l2ping, which is licensed as GPL2+
4 * and comes with a copyright like this:
6 * Copyright (C) 2000-2001 Qualcomm Incorporated
7 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
8 * Copyright (C) 2002-2007 Marcel Holtmann <marcel@holtmann.org>
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
39 #include <sys/select.h>
41 #include <bluetooth/bluetooth.h>
42 #include <bluetooth/hci.h>
43 #include <bluetooth/hci_lib.h>
44 #include <bluetooth/l2cap.h>
46 #define PING_STRING "PulseAudio"
51 static void update_status(int found
) {
52 static int status
= -1;
54 if (!found
&& status
!= 0)
56 if (found
&& status
<= 0)
63 int main(int argc
, char *argv
[]) {
64 struct sockaddr_l2 addr
;
67 uint8_t buf
[L2CAP_CMD_HDR_SIZE
+ sizeof(PING_STRING
)];
85 if ((fd
= socket(PF_BLUETOOTH
, SOCK_RAW
, BTPROTO_L2CAP
)) < 0) {
86 fprintf(stderr
, "socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP) failed: %s", strerror(errno
));
90 memset(&addr
, 0, sizeof(addr
));
91 addr
.l2_family
= AF_BLUETOOTH
;
92 bacpy(&addr
.l2_bdaddr
, BDADDR_ANY
);
94 if (bind(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
95 fprintf(stderr
, "bind() failed: %s", strerror(errno
));
99 memset(&addr
, 0, sizeof(addr
));
100 addr
.l2_family
= AF_BLUETOOTH
;
101 str2ba(argv
[1], &addr
.l2_bdaddr
);
103 if (connect(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
105 if (errno
== EHOSTDOWN
|| errno
== ECONNRESET
|| errno
== ETIMEDOUT
) {
111 fprintf(stderr
, "connect() failed: %s", strerror(errno
));
120 memset(&packet
, 0, sizeof(packet
));
121 strcpy((char*) packet
.buf
+ L2CAP_CMD_HDR_SIZE
, PING_STRING
);
122 packet
.hdr
.ident
= id
;
123 packet
.hdr
.len
= htobs(sizeof(PING_STRING
));
124 packet
.hdr
.code
= L2CAP_ECHO_REQ
;
126 if ((r
= send(fd
, &packet
, sizeof(packet
), 0)) < 0) {
128 if (errno
== EHOSTDOWN
|| errno
== ECONNRESET
|| errno
== ETIMEDOUT
) {
135 fprintf(stderr
, "send() failed: %s", strerror(errno
));
139 assert(r
== sizeof(packet
));
141 gettimeofday(&end
, NULL
);
142 end
.tv_sec
+= TIMEOUT
;
145 struct timeval now
, delta
;
147 gettimeofday(&now
, NULL
);
149 if (timercmp(&end
, &now
, <=)) {
156 timersub(&end
, &now
, &delta
);
161 if (select(fd
+1, &fds
, NULL
, NULL
, &delta
) < 0) {
162 fprintf(stderr
, "select() failed: %s", strerror(errno
));
166 if ((r
= recv(fd
, &packet
, sizeof(packet
), 0)) <= 0) {
168 if (errno
== EHOSTDOWN
|| errno
== ECONNRESET
|| errno
== ETIMEDOUT
) {
175 fprintf(stderr
, "send() failed: %s", r
== 0 ? "EOF" : strerror(errno
));
179 assert(r
>= L2CAP_CMD_HDR_SIZE
);
181 if (packet
.hdr
.ident
!= id
)
184 if (packet
.hdr
.code
== L2CAP_ECHO_RSP
|| packet
.hdr
.code
== L2CAP_COMMAND_REJ
) {