1 /*
2 * session.c
3 */
4
5 /*-
6 * SPDX-License-Identifier: BSD-2-Clause
7 *
8 * Copyright (c) 2006 Maksim Yevmenkin <m_evmenkin@yahoo.com>
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: session.c,v 1.3 2006/09/07 21:06:53 max Exp $
33 */
34
35 #include <sys/queue.h>
36 #include <assert.h>
37 #define L2CAP_SOCKET_CHECKED
38 #include <bluetooth.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <syslog.h>
45 #include <unistd.h>
46 #include <usbhid.h>
47 #include "bthid_config.h"
48 #include "bthidd.h"
49 #include "btuinput.h"
50 #include "kbd.h"
51
52 /*
53 * Create new session
54 */
55
56 bthid_session_p
session_open(bthid_server_p srv,hid_device_p const d)57 session_open(bthid_server_p srv, hid_device_p const d)
58 {
59 bthid_session_p s;
60
61 assert(srv != NULL);
62 assert(d != NULL);
63
64 if ((s = (bthid_session_p) malloc(sizeof(*s))) == NULL)
65 return (NULL);
66
67 s->srv = srv;
68 memcpy(&s->bdaddr, &d->bdaddr, sizeof(s->bdaddr));
69 s->ctrl = -1;
70 s->intr = -1;
71 s->vkbd = -1;
72 s->ctx = NULL;
73 s->state = CLOSED;
74 s->ukbd = -1;
75 s->umouse = -1;
76 s->obutt = 0;
77
78 s->keys1 = bit_alloc(kbd_maxkey());
79 if (s->keys1 == NULL) {
80 free(s);
81 return (NULL);
82 }
83
84 s->keys2 = bit_alloc(kbd_maxkey());
85 if (s->keys2 == NULL) {
86 free(s->keys1);
87 free(s);
88 return (NULL);
89 }
90
91 LIST_INSERT_HEAD(&srv->sessions, s, next);
92
93 return (s);
94 }
95
96 /*
97 * Initialize virtual keyboard and mouse after both channels are established
98 */
99
100 int32_t
session_run(bthid_session_p s)101 session_run(bthid_session_p s)
102 {
103 hid_device_p d = get_hid_device(&s->bdaddr);
104 struct sockaddr_l2cap local;
105 socklen_t len;
106
107 if (d->keyboard) {
108 /* Open /dev/vkbdctl */
109 s->vkbd = open("/dev/vkbdctl", O_RDWR);
110 if (s->vkbd < 0) {
111 syslog(LOG_ERR, "Could not open /dev/vkbdctl " \
112 "for %s. %s (%d)", bt_ntoa(&s->bdaddr, NULL),
113 strerror(errno), errno);
114 return (-1);
115 }
116 /* Register session's vkbd descriptor (if needed) for read */
117 FD_SET(s->vkbd, &s->srv->rfdset);
118 if (s->vkbd > s->srv->maxfd)
119 s->srv->maxfd = s->vkbd;
120 }
121
122 /* Pass device for probing */
123 hid_initialise(s);
124
125 /* Take local bdaddr */
126 len = sizeof(local);
127 getsockname(s->ctrl, (struct sockaddr *) &local, &len);
128
129 if (d->mouse && s->srv->uinput) {
130 s->umouse = uinput_open_mouse(d, &local.l2cap_bdaddr);
131 if (s->umouse < 0) {
132 syslog(LOG_ERR, "Could not open /dev/uinput " \
133 "for %s. %s (%d)", bt_ntoa(&s->bdaddr,
134 NULL), strerror(errno), errno);
135 return (-1);
136 }
137 }
138 if (d->keyboard && s->srv->uinput) {
139 s->ukbd = uinput_open_keyboard(d, &local.l2cap_bdaddr);
140 if (s->ukbd < 0) {
141 syslog(LOG_ERR, "Could not open /dev/uinput " \
142 "for %s. %s (%d)", bt_ntoa(&s->bdaddr,
143 NULL), strerror(errno), errno);
144 return (-1);
145 }
146 /* Register session's ukbd descriptor (if needed) for read */
147 FD_SET(s->ukbd, &s->srv->rfdset);
148 if (s->ukbd > s->srv->maxfd)
149 s->srv->maxfd = s->ukbd;
150 }
151 return (0);
152 }
153
154 /*
155 * Lookup session by bdaddr
156 */
157
158 bthid_session_p
session_by_bdaddr(bthid_server_p srv,bdaddr_p bdaddr)159 session_by_bdaddr(bthid_server_p srv, bdaddr_p bdaddr)
160 {
161 bthid_session_p s;
162
163 assert(srv != NULL);
164 assert(bdaddr != NULL);
165
166 LIST_FOREACH(s, &srv->sessions, next)
167 if (memcmp(&s->bdaddr, bdaddr, sizeof(s->bdaddr)) == 0)
168 break;
169
170 return (s);
171 }
172
173 /*
174 * Lookup session by fd
175 */
176
177 bthid_session_p
session_by_fd(bthid_server_p srv,int32_t fd)178 session_by_fd(bthid_server_p srv, int32_t fd)
179 {
180 bthid_session_p s;
181
182 assert(srv != NULL);
183 assert(fd >= 0);
184
185 LIST_FOREACH(s, &srv->sessions, next)
186 if (s->ctrl == fd || s->intr == fd ||
187 s->vkbd == fd || s->ukbd == fd)
188 break;
189
190 return (s);
191 }
192
193 /*
194 * Close session
195 */
196
197 void
session_close(bthid_session_p s)198 session_close(bthid_session_p s)
199 {
200 assert(s != NULL);
201 assert(s->srv != NULL);
202
203 LIST_REMOVE(s, next);
204
205 if (s->intr != -1) {
206 FD_CLR(s->intr, &s->srv->rfdset);
207 FD_CLR(s->intr, &s->srv->wfdset);
208 close(s->intr);
209
210 if (s->srv->maxfd == s->intr)
211 s->srv->maxfd --;
212 }
213
214 if (s->ctrl != -1) {
215 FD_CLR(s->ctrl, &s->srv->rfdset);
216 FD_CLR(s->ctrl, &s->srv->wfdset);
217 close(s->ctrl);
218
219 if (s->srv->maxfd == s->ctrl)
220 s->srv->maxfd --;
221 }
222
223 if (s->vkbd != -1) {
224 FD_CLR(s->vkbd, &s->srv->rfdset);
225 close(s->vkbd);
226
227 if (s->srv->maxfd == s->vkbd)
228 s->srv->maxfd --;
229 }
230
231 if (s->umouse != -1)
232 close(s->umouse);
233
234 if (s->ukbd != -1) {
235 FD_CLR(s->ukbd, &s->srv->rfdset);
236 close(s->ukbd);
237
238 if (s->srv->maxfd == s->ukbd)
239 s->srv->maxfd --;
240 }
241
242 free(s->ctx);
243 free(s->keys1);
244 free(s->keys2);
245
246 memset(s, 0, sizeof(*s));
247 free(s);
248 }
249
250