16490c2ffSMaksim Yevmenkin /*
26490c2ffSMaksim Yevmenkin * session.c
37aebfa93SMaksim Yevmenkin */
47aebfa93SMaksim Yevmenkin
57aebfa93SMaksim Yevmenkin /*-
6*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
71de7b4b8SPedro F. Giffuni *
87aebfa93SMaksim Yevmenkin * Copyright (c) 2006 Maksim Yevmenkin <m_evmenkin@yahoo.com>
96490c2ffSMaksim Yevmenkin * All rights reserved.
106490c2ffSMaksim Yevmenkin *
116490c2ffSMaksim Yevmenkin * Redistribution and use in source and binary forms, with or without
126490c2ffSMaksim Yevmenkin * modification, are permitted provided that the following conditions
136490c2ffSMaksim Yevmenkin * are met:
146490c2ffSMaksim Yevmenkin * 1. Redistributions of source code must retain the above copyright
156490c2ffSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer.
166490c2ffSMaksim Yevmenkin * 2. Redistributions in binary form must reproduce the above copyright
176490c2ffSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer in the
186490c2ffSMaksim Yevmenkin * documentation and/or other materials provided with the distribution.
196490c2ffSMaksim Yevmenkin *
206490c2ffSMaksim Yevmenkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
216490c2ffSMaksim Yevmenkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
226490c2ffSMaksim Yevmenkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
236490c2ffSMaksim Yevmenkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
246490c2ffSMaksim Yevmenkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
256490c2ffSMaksim Yevmenkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
266490c2ffSMaksim Yevmenkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
276490c2ffSMaksim Yevmenkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
286490c2ffSMaksim Yevmenkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
296490c2ffSMaksim Yevmenkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
306490c2ffSMaksim Yevmenkin * SUCH DAMAGE.
316490c2ffSMaksim Yevmenkin *
327aebfa93SMaksim Yevmenkin * $Id: session.c,v 1.3 2006/09/07 21:06:53 max Exp $
336490c2ffSMaksim Yevmenkin */
346490c2ffSMaksim Yevmenkin
356490c2ffSMaksim Yevmenkin #include <sys/queue.h>
366490c2ffSMaksim Yevmenkin #include <assert.h>
378d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
386490c2ffSMaksim Yevmenkin #include <bluetooth.h>
397aebfa93SMaksim Yevmenkin #include <errno.h>
407aebfa93SMaksim Yevmenkin #include <fcntl.h>
416490c2ffSMaksim Yevmenkin #include <stdio.h>
426490c2ffSMaksim Yevmenkin #include <stdlib.h>
436490c2ffSMaksim Yevmenkin #include <string.h>
447aebfa93SMaksim Yevmenkin #include <syslog.h>
456490c2ffSMaksim Yevmenkin #include <unistd.h>
467aebfa93SMaksim Yevmenkin #include <usbhid.h>
477aebfa93SMaksim Yevmenkin #include "bthid_config.h"
486490c2ffSMaksim Yevmenkin #include "bthidd.h"
4944af5666SVladimir Kondratyev #include "btuinput.h"
503adfd74aSMaksim Yevmenkin #include "kbd.h"
516490c2ffSMaksim Yevmenkin
526490c2ffSMaksim Yevmenkin /*
536490c2ffSMaksim Yevmenkin * Create new session
546490c2ffSMaksim Yevmenkin */
556490c2ffSMaksim Yevmenkin
566490c2ffSMaksim Yevmenkin bthid_session_p
session_open(bthid_server_p srv,hid_device_p const d)577aebfa93SMaksim Yevmenkin session_open(bthid_server_p srv, hid_device_p const d)
586490c2ffSMaksim Yevmenkin {
597aebfa93SMaksim Yevmenkin bthid_session_p s;
606490c2ffSMaksim Yevmenkin
616490c2ffSMaksim Yevmenkin assert(srv != NULL);
627aebfa93SMaksim Yevmenkin assert(d != NULL);
636490c2ffSMaksim Yevmenkin
647aebfa93SMaksim Yevmenkin if ((s = (bthid_session_p) malloc(sizeof(*s))) == NULL)
657aebfa93SMaksim Yevmenkin return (NULL);
667aebfa93SMaksim Yevmenkin
676490c2ffSMaksim Yevmenkin s->srv = srv;
687aebfa93SMaksim Yevmenkin memcpy(&s->bdaddr, &d->bdaddr, sizeof(s->bdaddr));
693adfd74aSMaksim Yevmenkin s->ctrl = -1;
703adfd74aSMaksim Yevmenkin s->intr = -1;
717aebfa93SMaksim Yevmenkin s->vkbd = -1;
7244af5666SVladimir Kondratyev s->ctx = NULL;
737aebfa93SMaksim Yevmenkin s->state = CLOSED;
7444af5666SVladimir Kondratyev s->ukbd = -1;
7544af5666SVladimir Kondratyev s->umouse = -1;
7644af5666SVladimir Kondratyev s->obutt = 0;
777aebfa93SMaksim Yevmenkin
787aebfa93SMaksim Yevmenkin s->keys1 = bit_alloc(kbd_maxkey());
797aebfa93SMaksim Yevmenkin if (s->keys1 == NULL) {
807aebfa93SMaksim Yevmenkin free(s);
817aebfa93SMaksim Yevmenkin return (NULL);
827aebfa93SMaksim Yevmenkin }
837aebfa93SMaksim Yevmenkin
847aebfa93SMaksim Yevmenkin s->keys2 = bit_alloc(kbd_maxkey());
857aebfa93SMaksim Yevmenkin if (s->keys2 == NULL) {
867aebfa93SMaksim Yevmenkin free(s->keys1);
877aebfa93SMaksim Yevmenkin free(s);
887aebfa93SMaksim Yevmenkin return (NULL);
897aebfa93SMaksim Yevmenkin }
907aebfa93SMaksim Yevmenkin
917aebfa93SMaksim Yevmenkin LIST_INSERT_HEAD(&srv->sessions, s, next);
926490c2ffSMaksim Yevmenkin
936490c2ffSMaksim Yevmenkin return (s);
946490c2ffSMaksim Yevmenkin }
956490c2ffSMaksim Yevmenkin
966490c2ffSMaksim Yevmenkin /*
9744af5666SVladimir Kondratyev * Initialize virtual keyboard and mouse after both channels are established
9844af5666SVladimir Kondratyev */
9944af5666SVladimir Kondratyev
10044af5666SVladimir Kondratyev int32_t
session_run(bthid_session_p s)10144af5666SVladimir Kondratyev session_run(bthid_session_p s)
10244af5666SVladimir Kondratyev {
10344af5666SVladimir Kondratyev hid_device_p d = get_hid_device(&s->bdaddr);
10444af5666SVladimir Kondratyev struct sockaddr_l2cap local;
10544af5666SVladimir Kondratyev socklen_t len;
10644af5666SVladimir Kondratyev
10744af5666SVladimir Kondratyev if (d->keyboard) {
10844af5666SVladimir Kondratyev /* Open /dev/vkbdctl */
10944af5666SVladimir Kondratyev s->vkbd = open("/dev/vkbdctl", O_RDWR);
11044af5666SVladimir Kondratyev if (s->vkbd < 0) {
11144af5666SVladimir Kondratyev syslog(LOG_ERR, "Could not open /dev/vkbdctl " \
11244af5666SVladimir Kondratyev "for %s. %s (%d)", bt_ntoa(&s->bdaddr, NULL),
11344af5666SVladimir Kondratyev strerror(errno), errno);
11444af5666SVladimir Kondratyev return (-1);
11544af5666SVladimir Kondratyev }
11644af5666SVladimir Kondratyev /* Register session's vkbd descriptor (if needed) for read */
11744af5666SVladimir Kondratyev FD_SET(s->vkbd, &s->srv->rfdset);
11844af5666SVladimir Kondratyev if (s->vkbd > s->srv->maxfd)
11944af5666SVladimir Kondratyev s->srv->maxfd = s->vkbd;
12044af5666SVladimir Kondratyev }
12144af5666SVladimir Kondratyev
12244af5666SVladimir Kondratyev /* Pass device for probing */
12344af5666SVladimir Kondratyev hid_initialise(s);
12444af5666SVladimir Kondratyev
12544af5666SVladimir Kondratyev /* Take local bdaddr */
12644af5666SVladimir Kondratyev len = sizeof(local);
12744af5666SVladimir Kondratyev getsockname(s->ctrl, (struct sockaddr *) &local, &len);
12844af5666SVladimir Kondratyev
12944af5666SVladimir Kondratyev if (d->mouse && s->srv->uinput) {
13044af5666SVladimir Kondratyev s->umouse = uinput_open_mouse(d, &local.l2cap_bdaddr);
13144af5666SVladimir Kondratyev if (s->umouse < 0) {
13244af5666SVladimir Kondratyev syslog(LOG_ERR, "Could not open /dev/uinput " \
13344af5666SVladimir Kondratyev "for %s. %s (%d)", bt_ntoa(&s->bdaddr,
13444af5666SVladimir Kondratyev NULL), strerror(errno), errno);
13544af5666SVladimir Kondratyev return (-1);
13644af5666SVladimir Kondratyev }
13744af5666SVladimir Kondratyev }
13844af5666SVladimir Kondratyev if (d->keyboard && s->srv->uinput) {
13944af5666SVladimir Kondratyev s->ukbd = uinput_open_keyboard(d, &local.l2cap_bdaddr);
14044af5666SVladimir Kondratyev if (s->ukbd < 0) {
14144af5666SVladimir Kondratyev syslog(LOG_ERR, "Could not open /dev/uinput " \
14244af5666SVladimir Kondratyev "for %s. %s (%d)", bt_ntoa(&s->bdaddr,
14344af5666SVladimir Kondratyev NULL), strerror(errno), errno);
14444af5666SVladimir Kondratyev return (-1);
14544af5666SVladimir Kondratyev }
14644af5666SVladimir Kondratyev /* Register session's ukbd descriptor (if needed) for read */
14744af5666SVladimir Kondratyev FD_SET(s->ukbd, &s->srv->rfdset);
14844af5666SVladimir Kondratyev if (s->ukbd > s->srv->maxfd)
14944af5666SVladimir Kondratyev s->srv->maxfd = s->ukbd;
15044af5666SVladimir Kondratyev }
15144af5666SVladimir Kondratyev return (0);
15244af5666SVladimir Kondratyev }
15344af5666SVladimir Kondratyev
15444af5666SVladimir Kondratyev /*
1556490c2ffSMaksim Yevmenkin * Lookup session by bdaddr
1566490c2ffSMaksim Yevmenkin */
1576490c2ffSMaksim Yevmenkin
1586490c2ffSMaksim Yevmenkin bthid_session_p
session_by_bdaddr(bthid_server_p srv,bdaddr_p bdaddr)1596490c2ffSMaksim Yevmenkin session_by_bdaddr(bthid_server_p srv, bdaddr_p bdaddr)
1606490c2ffSMaksim Yevmenkin {
1617aebfa93SMaksim Yevmenkin bthid_session_p s;
1626490c2ffSMaksim Yevmenkin
1636490c2ffSMaksim Yevmenkin assert(srv != NULL);
1646490c2ffSMaksim Yevmenkin assert(bdaddr != NULL);
1656490c2ffSMaksim Yevmenkin
1666490c2ffSMaksim Yevmenkin LIST_FOREACH(s, &srv->sessions, next)
1676490c2ffSMaksim Yevmenkin if (memcmp(&s->bdaddr, bdaddr, sizeof(s->bdaddr)) == 0)
1686490c2ffSMaksim Yevmenkin break;
1696490c2ffSMaksim Yevmenkin
1706490c2ffSMaksim Yevmenkin return (s);
1716490c2ffSMaksim Yevmenkin }
1726490c2ffSMaksim Yevmenkin
1736490c2ffSMaksim Yevmenkin /*
1746490c2ffSMaksim Yevmenkin * Lookup session by fd
1756490c2ffSMaksim Yevmenkin */
1766490c2ffSMaksim Yevmenkin
1776490c2ffSMaksim Yevmenkin bthid_session_p
session_by_fd(bthid_server_p srv,int32_t fd)1787aebfa93SMaksim Yevmenkin session_by_fd(bthid_server_p srv, int32_t fd)
1796490c2ffSMaksim Yevmenkin {
1807aebfa93SMaksim Yevmenkin bthid_session_p s;
1816490c2ffSMaksim Yevmenkin
1826490c2ffSMaksim Yevmenkin assert(srv != NULL);
1836490c2ffSMaksim Yevmenkin assert(fd >= 0);
1846490c2ffSMaksim Yevmenkin
1856490c2ffSMaksim Yevmenkin LIST_FOREACH(s, &srv->sessions, next)
18644af5666SVladimir Kondratyev if (s->ctrl == fd || s->intr == fd ||
18744af5666SVladimir Kondratyev s->vkbd == fd || s->ukbd == fd)
1886490c2ffSMaksim Yevmenkin break;
1896490c2ffSMaksim Yevmenkin
1906490c2ffSMaksim Yevmenkin return (s);
1916490c2ffSMaksim Yevmenkin }
1926490c2ffSMaksim Yevmenkin
1936490c2ffSMaksim Yevmenkin /*
1946490c2ffSMaksim Yevmenkin * Close session
1956490c2ffSMaksim Yevmenkin */
1966490c2ffSMaksim Yevmenkin
1976490c2ffSMaksim Yevmenkin void
session_close(bthid_session_p s)1986490c2ffSMaksim Yevmenkin session_close(bthid_session_p s)
1996490c2ffSMaksim Yevmenkin {
2006490c2ffSMaksim Yevmenkin assert(s != NULL);
2016490c2ffSMaksim Yevmenkin assert(s->srv != NULL);
2026490c2ffSMaksim Yevmenkin
2036490c2ffSMaksim Yevmenkin LIST_REMOVE(s, next);
2046490c2ffSMaksim Yevmenkin
2056490c2ffSMaksim Yevmenkin if (s->intr != -1) {
2066490c2ffSMaksim Yevmenkin FD_CLR(s->intr, &s->srv->rfdset);
2076490c2ffSMaksim Yevmenkin FD_CLR(s->intr, &s->srv->wfdset);
2086490c2ffSMaksim Yevmenkin close(s->intr);
2096490c2ffSMaksim Yevmenkin
2106490c2ffSMaksim Yevmenkin if (s->srv->maxfd == s->intr)
2116490c2ffSMaksim Yevmenkin s->srv->maxfd --;
2126490c2ffSMaksim Yevmenkin }
2136490c2ffSMaksim Yevmenkin
2146490c2ffSMaksim Yevmenkin if (s->ctrl != -1) {
2156490c2ffSMaksim Yevmenkin FD_CLR(s->ctrl, &s->srv->rfdset);
2166490c2ffSMaksim Yevmenkin FD_CLR(s->ctrl, &s->srv->wfdset);
2176490c2ffSMaksim Yevmenkin close(s->ctrl);
2186490c2ffSMaksim Yevmenkin
2196490c2ffSMaksim Yevmenkin if (s->srv->maxfd == s->ctrl)
2206490c2ffSMaksim Yevmenkin s->srv->maxfd --;
2216490c2ffSMaksim Yevmenkin }
2226490c2ffSMaksim Yevmenkin
2237aebfa93SMaksim Yevmenkin if (s->vkbd != -1) {
2247aebfa93SMaksim Yevmenkin FD_CLR(s->vkbd, &s->srv->rfdset);
2257aebfa93SMaksim Yevmenkin close(s->vkbd);
2267aebfa93SMaksim Yevmenkin
2277aebfa93SMaksim Yevmenkin if (s->srv->maxfd == s->vkbd)
2287aebfa93SMaksim Yevmenkin s->srv->maxfd --;
2297aebfa93SMaksim Yevmenkin }
2307aebfa93SMaksim Yevmenkin
23144af5666SVladimir Kondratyev if (s->umouse != -1)
23244af5666SVladimir Kondratyev close(s->umouse);
23344af5666SVladimir Kondratyev
23444af5666SVladimir Kondratyev if (s->ukbd != -1) {
23544af5666SVladimir Kondratyev FD_CLR(s->ukbd, &s->srv->rfdset);
23644af5666SVladimir Kondratyev close(s->ukbd);
23744af5666SVladimir Kondratyev
23844af5666SVladimir Kondratyev if (s->srv->maxfd == s->ukbd)
23944af5666SVladimir Kondratyev s->srv->maxfd --;
24044af5666SVladimir Kondratyev }
24144af5666SVladimir Kondratyev
242a9a8884bSVladimir Kondratyev free(s->ctx);
2437aebfa93SMaksim Yevmenkin free(s->keys1);
2447aebfa93SMaksim Yevmenkin free(s->keys2);
2453adfd74aSMaksim Yevmenkin
2466490c2ffSMaksim Yevmenkin memset(s, 0, sizeof(*s));
2476490c2ffSMaksim Yevmenkin free(s);
2486490c2ffSMaksim Yevmenkin }
2496490c2ffSMaksim Yevmenkin
250