]>
code.delx.au - pulseaudio/blob - src/modules/bt-proximity-helper.c
4 This file is part of PulseAudio.
6 Copyright 2007 Lennart Poettering
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published
10 by the Free Software Foundation; either version 2 of the License,
11 or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
25 * Small SUID helper that allows us to ping a BT device. Borrows
26 * heavily from bluez-utils' l2ping, which is licensed as GPL2+, too
27 * and comes with a copyright like this:
29 * Copyright (C) 2000-2001 Qualcomm Incorporated
30 * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com>
31 * Copyright (C) 2002-2007 Marcel Holtmann <marcel@holtmann.org>
47 #include <sys/select.h>
49 #include <bluetooth/bluetooth.h>
50 #include <bluetooth/hci.h>
51 #include <bluetooth/hci_lib.h>
52 #include <bluetooth/l2cap.h>
54 #define PING_STRING "PulseAudio"
59 static void update_status(int found
) {
60 static int status
= -1;
62 if (!found
&& status
!= 0)
64 if (found
&& status
<= 0)
71 int main(int argc
, char *argv
[]) {
72 struct sockaddr_l2 addr
;
75 uint8_t buf
[L2CAP_CMD_HDR_SIZE
+ sizeof(PING_STRING
)];
93 if ((fd
= socket(PF_BLUETOOTH
, SOCK_RAW
, BTPROTO_L2CAP
)) < 0) {
94 fprintf(stderr
, "socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_L2CAP) failed: %s", strerror(errno
));
98 memset(&addr
, 0, sizeof(addr
));
99 addr
.l2_family
= AF_BLUETOOTH
;
100 bacpy(&addr
.l2_bdaddr
, BDADDR_ANY
);
102 if (bind(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
103 fprintf(stderr
, "bind() failed: %s", strerror(errno
));
107 memset(&addr
, 0, sizeof(addr
));
108 addr
.l2_family
= AF_BLUETOOTH
;
109 str2ba(argv
[1], &addr
.l2_bdaddr
);
111 if (connect(fd
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
113 if (errno
== EHOSTDOWN
|| errno
== ECONNRESET
|| errno
== ETIMEDOUT
) {
119 fprintf(stderr
, "connect() failed: %s", strerror(errno
));
128 memset(&packet
, 0, sizeof(packet
));
129 strcpy((char*) packet
.buf
+ L2CAP_CMD_HDR_SIZE
, PING_STRING
);
130 packet
.hdr
.ident
= id
;
131 packet
.hdr
.len
= htobs(sizeof(PING_STRING
));
132 packet
.hdr
.code
= L2CAP_ECHO_REQ
;
134 if ((r
= send(fd
, &packet
, sizeof(packet
), 0)) < 0) {
136 if (errno
== EHOSTDOWN
|| errno
== ECONNRESET
|| errno
== ETIMEDOUT
) {
143 fprintf(stderr
, "send() failed: %s", strerror(errno
));
147 assert(r
== sizeof(packet
));
149 gettimeofday(&end
, NULL
);
150 end
.tv_sec
+= TIMEOUT
;
153 struct timeval now
, delta
;
155 gettimeofday(&now
, NULL
);
157 if (timercmp(&end
, &now
, <=)) {
164 timersub(&end
, &now
, &delta
);
169 if (select(fd
+1, &fds
, NULL
, NULL
, &delta
) < 0) {
170 fprintf(stderr
, "select() failed: %s", strerror(errno
));
174 if ((r
= recv(fd
, &packet
, sizeof(packet
), 0)) <= 0) {
176 if (errno
== EHOSTDOWN
|| errno
== ECONNRESET
|| errno
== ETIMEDOUT
) {
183 fprintf(stderr
, "send() failed: %s", r
== 0 ? "EOF" : strerror(errno
));
187 assert(r
>= L2CAP_CMD_HDR_SIZE
);
189 if (packet
.hdr
.ident
!= id
)
192 if (packet
.hdr
.code
== L2CAP_ECHO_RSP
|| packet
.hdr
.code
== L2CAP_COMMAND_REJ
) {