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$
32 */
33
34#include <sys/queue.h>
35#include <assert.h>
36#include <bluetooth.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
42#include <syslog.h>
43#include <unistd.h>
44#include <usbhid.h>
45#include "bthid_config.h"
46#include "bthidd.h"
47#include "kbd.h"
48
49/*
50 * Create new session
51 */
52
53bthid_session_p
54session_open(bthid_server_p srv, hid_device_p const d)
55{
56	bthid_session_p	s;
57
58	assert(srv != NULL);
59	assert(d != NULL);
60
61	if ((s = (bthid_session_p) malloc(sizeof(*s))) == NULL)
62		return (NULL);
63
64	s->srv = srv;
65	memcpy(&s->bdaddr, &d->bdaddr, sizeof(s->bdaddr));
66	s->ctrl = -1;
67	s->intr = -1;
68
69	if (d->keyboard) {
70		/* Open /dev/vkbdctl */
71		s->vkbd = open("/dev/vkbdctl", O_RDWR);
72		if (s->vkbd < 0) {
73			syslog(LOG_ERR, "Could not open /dev/vkbdctl " \
74				"for %s. %s (%d)", bt_ntoa(&s->bdaddr, NULL),
75				strerror(errno), errno);
76			free(s);
77			return (NULL);
78		}
79	} else
80		s->vkbd = -1;
81
82	s->state = CLOSED;
83
84	s->keys1 = bit_alloc(kbd_maxkey());
85	if (s->keys1 == NULL) {
86		free(s);
87		return (NULL);
88	}
89
90	s->keys2 = bit_alloc(kbd_maxkey());
91	if (s->keys2 == NULL) {
92		free(s->keys1);
93		free(s);
94		return (NULL);
95	}
96
97	LIST_INSERT_HEAD(&srv->sessions, s, next);
98
99	return (s);
100}
101
102/*
103 * Lookup session by bdaddr
104 */
105
106bthid_session_p
107session_by_bdaddr(bthid_server_p srv, bdaddr_p bdaddr)
108{
109	bthid_session_p	s;
110
111	assert(srv != NULL);
112	assert(bdaddr != NULL);
113
114	LIST_FOREACH(s, &srv->sessions, next)
115		if (memcmp(&s->bdaddr, bdaddr, sizeof(s->bdaddr)) == 0)
116			break;
117
118	return (s);
119}
120
121/*
122 * Lookup session by fd
123 */
124
125bthid_session_p
126session_by_fd(bthid_server_p srv, int32_t fd)
127{
128	bthid_session_p	s;
129
130	assert(srv != NULL);
131	assert(fd >= 0);
132
133	LIST_FOREACH(s, &srv->sessions, next)
134		if (s->ctrl == fd || s->intr == fd || s->vkbd == fd)
135			break;
136
137	return (s);
138}
139
140/*
141 * Close session
142 */
143
144void
145session_close(bthid_session_p s)
146{
147	assert(s != NULL);
148	assert(s->srv != NULL);
149
150	LIST_REMOVE(s, next);
151
152	if (s->intr != -1) {
153		FD_CLR(s->intr, &s->srv->rfdset);
154		FD_CLR(s->intr, &s->srv->wfdset);
155		close(s->intr);
156
157		if (s->srv->maxfd == s->intr)
158			s->srv->maxfd --;
159	}
160
161	if (s->ctrl != -1) {
162		FD_CLR(s->ctrl, &s->srv->rfdset);
163		FD_CLR(s->ctrl, &s->srv->wfdset);
164		close(s->ctrl);
165
166		if (s->srv->maxfd == s->ctrl)
167			s->srv->maxfd --;
168	}
169
170	if (s->vkbd != -1) {
171		FD_CLR(s->vkbd, &s->srv->rfdset);
172		close(s->vkbd);
173
174		if (s->srv->maxfd == s->vkbd)
175			s->srv->maxfd --;
176	}
177
178	free(s->keys1);
179	free(s->keys2);
180
181	memset(s, 0, sizeof(*s));
182	free(s);
183}
184
185