server.c (831a4264afc5501532d7072033f3e95e31253e35) | server.c (6490c2ffabe2a6e5df2545d164f1c257e0d471de) |
---|---|
1/* 2 * server.c | 1/* 2 * server.c |
3 */ 4 5/*- 6 * Copyright (c) 2006 Maksim Yevmenkin <m_evmenkin@yahoo.com> | 3 * 4 * Copyright (c) 2004 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 --- 7 unchanged lines hidden (view full) --- 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 * | 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright --- 7 unchanged lines hidden (view full) --- 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * |
30 * $Id: server.c,v 1.9 2006/09/07 21:06:53 max Exp $ | 28 * $Id: server.c,v 1.5 2004/02/26 21:43:36 max Exp $ |
31 * $FreeBSD$ 32 */ 33 34#include <sys/queue.h> 35#include <assert.h> 36#include <bluetooth.h> | 29 * $FreeBSD$ 30 */ 31 32#include <sys/queue.h> 33#include <assert.h> 34#include <bluetooth.h> |
37#include <dev/vkbd/vkbd_var.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> | 35#include <errno.h> 36#include <fcntl.h> 37#include <stdio.h> 38#include <stdlib.h> 39#include <string.h> 40#include <syslog.h> 41#include <unistd.h> 42#include <usbhid.h> |
46#include "bthid_config.h" | |
47#include "bthidd.h" | 43#include "bthidd.h" |
48#include "kbd.h" | 44#include "bthid_config.h" |
49 50#undef max 51#define max(x, y) (((x) > (y))? (x) : (y)) 52 | 45 46#undef max 47#define max(x, y) (((x) > (y))? (x) : (y)) 48 |
53static int32_t server_accept (bthid_server_p srv, int32_t fd); 54static int32_t server_process(bthid_server_p srv, int32_t fd); | 49static int server_accept (bthid_server_p srv, int fd); 50static int server_process(bthid_server_p srv, int fd); |
55 56/* 57 * Initialize server 58 */ 59 | 51 52/* 53 * Initialize server 54 */ 55 |
60int32_t | 56int |
61server_init(bthid_server_p srv) 62{ 63 struct sockaddr_l2cap l2addr; 64 65 assert(srv != NULL); 66 67 srv->ctrl = srv->intr = -1; 68 FD_ZERO(&srv->rfdset); --- 15 unchanged lines hidden (view full) --- 84 "%s (%d)", strerror(errno), errno); 85 close(srv->cons); 86 return (-1); 87 } 88 89 l2addr.l2cap_len = sizeof(l2addr); 90 l2addr.l2cap_family = AF_BLUETOOTH; 91 memcpy(&l2addr.l2cap_bdaddr, &srv->bdaddr, sizeof(l2addr.l2cap_bdaddr)); | 57server_init(bthid_server_p srv) 58{ 59 struct sockaddr_l2cap l2addr; 60 61 assert(srv != NULL); 62 63 srv->ctrl = srv->intr = -1; 64 FD_ZERO(&srv->rfdset); --- 15 unchanged lines hidden (view full) --- 80 "%s (%d)", strerror(errno), errno); 81 close(srv->cons); 82 return (-1); 83 } 84 85 l2addr.l2cap_len = sizeof(l2addr); 86 l2addr.l2cap_family = AF_BLUETOOTH; 87 memcpy(&l2addr.l2cap_bdaddr, &srv->bdaddr, sizeof(l2addr.l2cap_bdaddr)); |
92 l2addr.l2cap_psm = htole16(0x11); | 88 l2addr.l2cap_psm = 0x11; |
93 94 if (bind(srv->ctrl, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0) { 95 syslog(LOG_ERR, "Could not bind control L2CAP socket. " \ 96 "%s (%d)", strerror(errno), errno); | 89 90 if (bind(srv->ctrl, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0) { 91 syslog(LOG_ERR, "Could not bind control L2CAP socket. " \ 92 "%s (%d)", strerror(errno), errno); |
97 close(srv->ctrl); | |
98 close(srv->cons); 99 return (-1); 100 } 101 102 if (listen(srv->ctrl, 10) < 0) { 103 syslog(LOG_ERR, "Could not listen on control L2CAP socket. " \ 104 "%s (%d)", strerror(errno), errno); | 93 close(srv->cons); 94 return (-1); 95 } 96 97 if (listen(srv->ctrl, 10) < 0) { 98 syslog(LOG_ERR, "Could not listen on control L2CAP socket. " \ 99 "%s (%d)", strerror(errno), errno); |
105 close(srv->ctrl); | |
106 close(srv->cons); 107 return (-1); 108 } 109 110 /* Create intrrupt socket */ 111 srv->intr = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); 112 if (srv->intr < 0) { 113 syslog(LOG_ERR, "Could not create interrupt L2CAP socket. " \ 114 "%s (%d)", strerror(errno), errno); 115 close(srv->ctrl); 116 close(srv->cons); 117 return (-1); 118 } 119 | 100 close(srv->cons); 101 return (-1); 102 } 103 104 /* Create intrrupt socket */ 105 srv->intr = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); 106 if (srv->intr < 0) { 107 syslog(LOG_ERR, "Could not create interrupt L2CAP socket. " \ 108 "%s (%d)", strerror(errno), errno); 109 close(srv->ctrl); 110 close(srv->cons); 111 return (-1); 112 } 113 |
120 l2addr.l2cap_psm = htole16(0x13); | 114 l2addr.l2cap_psm = 0x13; |
121 122 if (bind(srv->intr, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0) { 123 syslog(LOG_ERR, "Could not bind interrupt L2CAP socket. " \ 124 "%s (%d)", strerror(errno), errno); | 115 116 if (bind(srv->intr, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0) { 117 syslog(LOG_ERR, "Could not bind interrupt L2CAP socket. " \ 118 "%s (%d)", strerror(errno), errno); |
125 close(srv->intr); | |
126 close(srv->ctrl); 127 close(srv->cons); 128 return (-1); 129 } 130 131 if (listen(srv->intr, 10) < 0) { 132 syslog(LOG_ERR, "Could not listen on interrupt L2CAP socket. "\ 133 "%s (%d)", strerror(errno), errno); | 119 close(srv->ctrl); 120 close(srv->cons); 121 return (-1); 122 } 123 124 if (listen(srv->intr, 10) < 0) { 125 syslog(LOG_ERR, "Could not listen on interrupt L2CAP socket. "\ 126 "%s (%d)", strerror(errno), errno); |
134 close(srv->intr); | |
135 close(srv->ctrl); 136 close(srv->cons); 137 return (-1); 138 } 139 140 FD_SET(srv->ctrl, &srv->rfdset); 141 FD_SET(srv->intr, &srv->rfdset); 142 srv->maxfd = max(srv->ctrl, srv->intr); --- 19 unchanged lines hidden (view full) --- 162 163 memset(srv, 0, sizeof(*srv)); 164} 165 166/* 167 * Do one server iteration 168 */ 169 | 127 close(srv->ctrl); 128 close(srv->cons); 129 return (-1); 130 } 131 132 FD_SET(srv->ctrl, &srv->rfdset); 133 FD_SET(srv->intr, &srv->rfdset); 134 srv->maxfd = max(srv->ctrl, srv->intr); --- 19 unchanged lines hidden (view full) --- 154 155 memset(srv, 0, sizeof(*srv)); 156} 157 158/* 159 * Do one server iteration 160 */ 161 |
170int32_t | 162int |
171server_do(bthid_server_p srv) 172{ 173 struct timeval tv; 174 fd_set rfdset, wfdset; | 163server_do(bthid_server_p srv) 164{ 165 struct timeval tv; 166 fd_set rfdset, wfdset; |
175 int32_t n, fd; | 167 int n, fd; |
176 177 assert(srv != NULL); 178 179 tv.tv_sec = 1; 180 tv.tv_usec = 0; 181 182 /* Copy cached version of the fd sets and call select */ 183 memcpy(&rfdset, &srv->rfdset, sizeof(rfdset)); --- 28 unchanged lines hidden (view full) --- 212 213 return (0); 214} 215 216/* 217 * Accept new connection 218 */ 219 | 168 169 assert(srv != NULL); 170 171 tv.tv_sec = 1; 172 tv.tv_usec = 0; 173 174 /* Copy cached version of the fd sets and call select */ 175 memcpy(&rfdset, &srv->rfdset, sizeof(rfdset)); --- 28 unchanged lines hidden (view full) --- 204 205 return (0); 206} 207 208/* 209 * Accept new connection 210 */ 211 |
220static int32_t 221server_accept(bthid_server_p srv, int32_t fd) | 212static int 213server_accept(bthid_server_p srv, int fd) |
222{ | 214{ |
223 bthid_session_p s; 224 hid_device_p d; | 215 bthid_session_p s = NULL; 216 hid_device_p d = NULL; |
225 struct sockaddr_l2cap l2addr; | 217 struct sockaddr_l2cap l2addr; |
226 int32_t new_fd; 227 socklen_t len; | 218 int len, new_fd; |
228 229 len = sizeof(l2addr); 230 if ((new_fd = accept(fd, (struct sockaddr *) &l2addr, &len)) < 0) { 231 syslog(LOG_ERR, "Could not accept %s connection. %s (%d)", 232 (fd == srv->ctrl)? "control" : "interrupt", 233 strerror(errno), errno); 234 return (-1); 235 } 236 | 219 220 len = sizeof(l2addr); 221 if ((new_fd = accept(fd, (struct sockaddr *) &l2addr, &len)) < 0) { 222 syslog(LOG_ERR, "Could not accept %s connection. %s (%d)", 223 (fd == srv->ctrl)? "control" : "interrupt", 224 strerror(errno), errno); 225 return (-1); 226 } 227 |
237 /* Is device configured? */ 238 if ((d = get_hid_device(&l2addr.l2cap_bdaddr)) == NULL) { 239 syslog(LOG_ERR, "Rejecting %s connection from %s. " \ 240 "Device not configured", 241 (fd == srv->ctrl)? "control" : "interrupt", 242 bt_ntoa(&l2addr.l2cap_bdaddr, NULL)); 243 close(new_fd); 244 return (-1); 245 } 246 | |
247 /* Check if we have session for the device */ 248 if ((s = session_by_bdaddr(srv, &l2addr.l2cap_bdaddr)) == NULL) { | 228 /* Check if we have session for the device */ 229 if ((s = session_by_bdaddr(srv, &l2addr.l2cap_bdaddr)) == NULL) { |
230 /* Is device configured? */ 231 if ((d = get_hid_device(&l2addr.l2cap_bdaddr)) == NULL) { 232 syslog(LOG_ERR, "Rejecting %s connection from %s. " \ 233 "Device not configured", 234 (fd == srv->ctrl)? "control" : "interrupt", 235 bt_ntoa(&l2addr.l2cap_bdaddr, NULL)); 236 close(new_fd); 237 return (-1); 238 } 239 |
|
249 d->new_device = 0; /* reset new device flag */ 250 write_hids_file(); 251 252 /* Create new inbound session */ | 240 d->new_device = 0; /* reset new device flag */ 241 write_hids_file(); 242 243 /* Create new inbound session */ |
253 if ((s = session_open(srv, d)) == NULL) { 254 syslog(LOG_CRIT, "Could not open inbound session " 255 "for %s", bt_ntoa(&l2addr.l2cap_bdaddr, NULL)); | 244 if ((s = session_open(srv, &l2addr.l2cap_bdaddr)) == NULL) { 245 syslog(LOG_CRIT, "Could not open inbound session " \ 246 "for %s. Not enough memory", 247 bt_ntoa(&l2addr.l2cap_bdaddr, NULL)); |
256 close(new_fd); 257 return (-1); 258 } 259 } 260 261 /* Update descriptors */ 262 if (fd == srv->ctrl) { 263 assert(s->ctrl == -1); --- 8 unchanged lines hidden (view full) --- 272 FD_SET(new_fd, &srv->rfdset); 273 if (new_fd > srv->maxfd) 274 srv->maxfd = new_fd; 275 276 syslog(LOG_NOTICE, "Accepted %s connection from %s", 277 (fd == srv->ctrl)? "control" : "interrupt", 278 bt_ntoa(&l2addr.l2cap_bdaddr, NULL)); 279 | 248 close(new_fd); 249 return (-1); 250 } 251 } 252 253 /* Update descriptors */ 254 if (fd == srv->ctrl) { 255 assert(s->ctrl == -1); --- 8 unchanged lines hidden (view full) --- 264 FD_SET(new_fd, &srv->rfdset); 265 if (new_fd > srv->maxfd) 266 srv->maxfd = new_fd; 267 268 syslog(LOG_NOTICE, "Accepted %s connection from %s", 269 (fd == srv->ctrl)? "control" : "interrupt", 270 bt_ntoa(&l2addr.l2cap_bdaddr, NULL)); 271 |
280 /* Register session's vkbd descriptor (if needed) for read */ 281 if (s->state == OPEN && d->keyboard) { 282 assert(s->vkbd != -1); 283 284 FD_SET(s->vkbd, &srv->rfdset); 285 if (s->vkbd > srv->maxfd) 286 srv->maxfd = s->vkbd; 287 } 288 | |
289 return (0); 290} 291 292/* 293 * Process data on the connection 294 */ 295 | 272 return (0); 273} 274 275/* 276 * Process data on the connection 277 */ 278 |
296static int32_t 297server_process(bthid_server_p srv, int32_t fd) | 279static int 280server_process(bthid_server_p srv, int fd) |
298{ | 281{ |
299 bthid_session_p s = session_by_fd(srv, fd); 300 int32_t len, to_read; 301 int32_t (*cb)(bthid_session_p, uint8_t *, int32_t); 302 union { 303 uint8_t b[1024]; 304 vkbd_status_t s; 305 } data; | 282 bthid_session_p s = session_by_fd(srv, fd); 283 char data[1024]; 284 int len; |
306 | 285 |
307 if (s == NULL) 308 return (0); /* can happen on device disconnect */ | 286 assert(s != NULL); |
309 | 287 |
310 311 if (fd == s->ctrl) { 312 cb = hid_control; 313 to_read = sizeof(data.b); 314 } else if (fd == s->intr) { 315 cb = hid_interrupt; 316 to_read = sizeof(data.b); 317 } else { 318 assert(fd == s->vkbd); 319 320 cb = kbd_status_changed; 321 to_read = sizeof(data.s); 322 } 323 | |
324 do { | 288 do { |
325 len = read(fd, &data, to_read); | 289 len = read(fd, data, sizeof(data)); |
326 } while (len < 0 && errno == EINTR); 327 328 if (len < 0) { 329 syslog(LOG_ERR, "Could not read data from %s (%s). %s (%d)", 330 bt_ntoa(&s->bdaddr, NULL), 331 (fd == s->ctrl)? "control" : "interrupt", 332 strerror(errno), errno); 333 session_close(s); 334 return (0); 335 } 336 337 if (len == 0) { 338 syslog(LOG_NOTICE, "Remote device %s has closed %s connection", 339 bt_ntoa(&s->bdaddr, NULL), 340 (fd == s->ctrl)? "control" : "interrupt"); 341 session_close(s); 342 return (0); 343 } 344 | 290 } while (len < 0 && errno == EINTR); 291 292 if (len < 0) { 293 syslog(LOG_ERR, "Could not read data from %s (%s). %s (%d)", 294 bt_ntoa(&s->bdaddr, NULL), 295 (fd == s->ctrl)? "control" : "interrupt", 296 strerror(errno), errno); 297 session_close(s); 298 return (0); 299 } 300 301 if (len == 0) { 302 syslog(LOG_NOTICE, "Remote device %s has closed %s connection", 303 bt_ntoa(&s->bdaddr, NULL), 304 (fd == s->ctrl)? "control" : "interrupt"); 305 session_close(s); 306 return (0); 307 } 308 |
345 (*cb)(s, (uint8_t *) &data, len); | 309 if (fd == s->ctrl) 310 hid_control(s, data, len); 311 else 312 hid_interrupt(s, data, len); |
346 347 return (0); 348} 349 | 313 314 return (0); 315} 316 |