Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/bluetooth/bthidd/bthidd.c
103352 views
1
/*
2
* bthidd.c
3
*/
4
5
/*-
6
* SPDX-License-Identifier: BSD-2-Clause
7
*
8
* Copyright (c) 2006 Maksim Yevmenkin <[email protected]>
9
* All rights reserved.
10
*
11
* Redistribution and use in source and binary forms, with or without
12
* modification, are permitted provided that the following conditions
13
* are met:
14
* 1. Redistributions of source code must retain the above copyright
15
* notice, this list of conditions and the following disclaimer.
16
* 2. Redistributions in binary form must reproduce the above copyright
17
* notice, this list of conditions and the following disclaimer in the
18
* documentation and/or other materials provided with the distribution.
19
*
20
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
* SUCH DAMAGE.
31
*
32
* $Id: bthidd.c,v 1.8 2006/09/07 21:06:53 max Exp $
33
*/
34
35
#include <sys/time.h>
36
#include <sys/queue.h>
37
#include <assert.h>
38
#define L2CAP_SOCKET_CHECKED
39
#include <bluetooth.h>
40
#include <err.h>
41
#include <errno.h>
42
#include <signal.h>
43
#include <stdio.h>
44
#include <stdlib.h>
45
#include <string.h>
46
#include <syslog.h>
47
#include <unistd.h>
48
#include <usbhid.h>
49
#include "bthid_config.h"
50
#include "bthidd.h"
51
52
static int32_t write_pid_file (char const *file);
53
static int32_t remove_pid_file (char const *file);
54
static int32_t elapsed (int32_t tval);
55
static void sighandler (int32_t s);
56
static void usage (void);
57
58
/*
59
* bthidd
60
*/
61
62
static int32_t done = 0; /* are we done? */
63
64
int32_t
65
main(int32_t argc, char *argv[])
66
{
67
struct bthid_server srv;
68
struct sigaction sa;
69
char const *pid_file = BTHIDD_PIDFILE;
70
char *ep;
71
int32_t opt, detach, tval, uinput;
72
73
memset(&srv, 0, sizeof(srv));
74
memset(&srv.bdaddr, 0, sizeof(srv.bdaddr));
75
detach = 1;
76
tval = 10; /* sec */
77
uinput = 0;
78
79
while ((opt = getopt(argc, argv, "a:c:dH:hp:t:u")) != -1) {
80
switch (opt) {
81
case 'a': /* BDADDR */
82
if (!bt_aton(optarg, &srv.bdaddr)) {
83
struct hostent *he;
84
85
if ((he = bt_gethostbyname(optarg)) == NULL)
86
errx(1, "%s: %s", optarg, hstrerror(h_errno));
87
88
memcpy(&srv.bdaddr, he->h_addr, sizeof(srv.bdaddr));
89
}
90
break;
91
92
case 'c': /* config file */
93
config_file = optarg;
94
break;
95
96
case 'd': /* do not detach */
97
detach = 0;
98
break;
99
100
case 'H': /* hids file */
101
hids_file = optarg;
102
break;
103
104
case 'p': /* pid file */
105
pid_file = optarg;
106
break;
107
108
case 't': /* rescan interval */
109
tval = strtol(optarg, (char **) &ep, 10);
110
if (*ep != '\0' || tval <= 0)
111
usage();
112
break;
113
114
case 'u': /* enable evdev support */
115
uinput = 1;
116
break;
117
118
case 'h':
119
default:
120
usage();
121
/* NOT REACHED */
122
}
123
}
124
125
openlog(BTHIDD_IDENT, LOG_PID|LOG_PERROR|LOG_NDELAY, LOG_USER);
126
127
/* Become daemon if required */
128
if (detach && daemon(0, 0) < 0) {
129
syslog(LOG_CRIT, "Could not become daemon. %s (%d)",
130
strerror(errno), errno);
131
exit(1);
132
}
133
134
/* Install signal handler */
135
memset(&sa, 0, sizeof(sa));
136
sa.sa_handler = sighandler;
137
138
if (sigaction(SIGTERM, &sa, NULL) < 0 ||
139
sigaction(SIGHUP, &sa, NULL) < 0 ||
140
sigaction(SIGINT, &sa, NULL) < 0) {
141
syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)",
142
strerror(errno), errno);
143
exit(1);
144
}
145
146
sa.sa_handler = SIG_IGN;
147
if (sigaction(SIGPIPE, &sa, NULL) < 0) {
148
syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)",
149
strerror(errno), errno);
150
exit(1);
151
}
152
153
sa.sa_handler = SIG_IGN;
154
sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT;
155
if (sigaction(SIGCHLD, &sa, NULL) < 0) {
156
syslog(LOG_CRIT, "Could not install signal handlers. %s (%d)",
157
strerror(errno), errno);
158
exit(1);
159
}
160
161
if (read_config_file() < 0 || read_hids_file() < 0 ||
162
server_init(&srv) < 0 || write_pid_file(pid_file) < 0)
163
exit(1);
164
165
srv.uinput = uinput;
166
167
for (done = 0; !done; ) {
168
if (elapsed(tval))
169
client_rescan(&srv);
170
171
if (server_do(&srv) < 0)
172
break;
173
}
174
175
server_shutdown(&srv);
176
remove_pid_file(pid_file);
177
clean_config();
178
closelog();
179
180
return (0);
181
}
182
183
/*
184
* Write pid file
185
*/
186
187
static int32_t
188
write_pid_file(char const *file)
189
{
190
FILE *pid;
191
192
assert(file != NULL);
193
194
if ((pid = fopen(file, "w")) == NULL) {
195
syslog(LOG_ERR, "Could not open file %s. %s (%d)",
196
file, strerror(errno), errno);
197
return (-1);
198
}
199
200
fprintf(pid, "%d", getpid());
201
fclose(pid);
202
203
return (0);
204
}
205
206
/*
207
* Remote pid file
208
*/
209
210
static int32_t
211
remove_pid_file(char const *file)
212
{
213
assert(file != NULL);
214
215
if (unlink(file) < 0) {
216
syslog(LOG_ERR, "Could not unlink file %s. %s (%d)",
217
file, strerror(errno), errno);
218
return (-1);
219
}
220
221
return (0);
222
}
223
224
/*
225
* Returns true if desired time interval has elapsed
226
*/
227
228
static int32_t
229
elapsed(int32_t tval)
230
{
231
static struct timeval last = { 0, 0 };
232
struct timeval now;
233
234
gettimeofday(&now, NULL);
235
236
if (now.tv_sec - last.tv_sec >= tval) {
237
last = now;
238
return (1);
239
}
240
241
return (0);
242
}
243
244
/*
245
* Signal handler
246
*/
247
248
static void
249
sighandler(int32_t s)
250
{
251
syslog(LOG_NOTICE, "Got signal %d, total number of signals %d",
252
s, ++ done);
253
}
254
255
/*
256
* Display usage and exit
257
*/
258
259
static void
260
usage(void)
261
{
262
fprintf(stderr,
263
"Usage: %s [options]\n" \
264
"Where options are:\n" \
265
" -a address specify address to listen on (default ANY)\n" \
266
" -c file specify config file name\n" \
267
" -d run in foreground\n" \
268
" -H file specify known HIDs file name\n" \
269
" -h display this message\n" \
270
" -p file specify PID file name\n" \
271
" -t tval specify client rescan interval (sec)\n" \
272
" -u enable evdev protocol support\n" \
273
"", BTHIDD_IDENT);
274
exit(255);
275
}
276
277
278