1/*
2 * session.c
3 */
4
5/*-
6 * Copyright (c) 2006 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 *    notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in the
16 *    documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $Id: session.c,v 1.3 2006/09/07 21:06:53 max Exp $
31 * $FreeBSD: releng/11.0/usr.sbin/bluetooth/bthidd/session.c 281210 2015-04-07 16:48:23Z takawata $
32 */
33
34#include <sys/queue.h>
35#include <assert.h>
36#define L2CAP_SOCKET_CHECKED
37#include <bluetooth.h>
38#include <errno.h>
39#include <fcntl.h>
40#include <stdio.h>
41#include <stdlib.h>
42#include <string.h>
43#include <syslog.h>
44#include <unistd.h>
45#include <usbhid.h>
46#include "bthid_config.h"
47#include "bthidd.h"
48#include "kbd.h"
49
50/*
51 * Create new session
52 */
53
54bthid_session_p
55session_open(bthid_server_p srv, hid_device_p const d)
56{
57	bthid_session_p	s;
58
59	assert(srv != NULL);
60	assert(d != NULL);
61
62	if ((s = (bthid_session_p) malloc(sizeof(*s))) == NULL)
63		return (NULL);
64
65	s->srv = srv;
66	memcpy(&s->bdaddr, &d->bdaddr, sizeof(s->bdaddr));
67	s->ctrl = -1;
68	s->intr = -1;
69
70	if (d->keyboard) {
71		/* Open /dev/vkbdctl */
72		s->vkbd = open("/dev/vkbdctl", O_RDWR);
73		if (s->vkbd < 0) {
74			syslog(LOG_ERR, "Could not open /dev/vkbdctl " \
75				"for %s. %s (%d)", bt_ntoa(&s->bdaddr, NULL),
76				strerror(errno), errno);
77			free(s);
78			return (NULL);
79		}
80	} else
81		s->vkbd = -1;
82
83	s->state = CLOSED;
84
85	s->keys1 = bit_alloc(kbd_maxkey());
86	if (s->keys1 == NULL) {
87		free(s);
88		return (NULL);
89	}
90
91	s->keys2 = bit_alloc(kbd_maxkey());
92	if (s->keys2 == NULL) {
93		free(s->keys1);
94		free(s);
95		return (NULL);
96	}
97
98	LIST_INSERT_HEAD(&srv->sessions, s, next);
99
100	return (s);
101}
102
103/*
104 * Lookup session by bdaddr
105 */
106
107bthid_session_p
108session_by_bdaddr(bthid_server_p srv, bdaddr_p bdaddr)
109{
110	bthid_session_p	s;
111
112	assert(srv != NULL);
113	assert(bdaddr != NULL);
114
115	LIST_FOREACH(s, &srv->sessions, next)
116		if (memcmp(&s->bdaddr, bdaddr, sizeof(s->bdaddr)) == 0)
117			break;
118
119	return (s);
120}
121
122/*
123 * Lookup session by fd
124 */
125
126bthid_session_p
127session_by_fd(bthid_server_p srv, int32_t fd)
128{
129	bthid_session_p	s;
130
131	assert(srv != NULL);
132	assert(fd >= 0);
133
134	LIST_FOREACH(s, &srv->sessions, next)
135		if (s->ctrl == fd || s->intr == fd || s->vkbd == fd)
136			break;
137
138	return (s);
139}
140
141/*
142 * Close session
143 */
144
145void
146session_close(bthid_session_p s)
147{
148	assert(s != NULL);
149	assert(s->srv != NULL);
150
151	LIST_REMOVE(s, next);
152
153	if (s->intr != -1) {
154		FD_CLR(s->intr, &s->srv->rfdset);
155		FD_CLR(s->intr, &s->srv->wfdset);
156		close(s->intr);
157
158		if (s->srv->maxfd == s->intr)
159			s->srv->maxfd --;
160	}
161
162	if (s->ctrl != -1) {
163		FD_CLR(s->ctrl, &s->srv->rfdset);
164		FD_CLR(s->ctrl, &s->srv->wfdset);
165		close(s->ctrl);
166
167		if (s->srv->maxfd == s->ctrl)
168			s->srv->maxfd --;
169	}
170
171	if (s->vkbd != -1) {
172		FD_CLR(s->vkbd, &s->srv->rfdset);
173		close(s->vkbd);
174
175		if (s->srv->maxfd == s->vkbd)
176			s->srv->maxfd --;
177	}
178
179	free(s->keys1);
180	free(s->keys2);
181
182	memset(s, 0, sizeof(*s));
183	free(s);
184}
185
186