1/* 2 * client.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 --- 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 * |
30 * $Id: client.c,v 1.7 2006/09/07 21:06:53 max Exp $ 31 * $FreeBSD: head/usr.sbin/bluetooth/bthidd/client.c 162128 2006-09-07 21:47:49Z emax $ |
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 |
48static int32_t client_socket(bdaddr_p bdaddr, int32_t psm); |
49 50/* 51 * Get next config entry and create outbound connection (if required) 52 * 53 * XXX Do only one device at a time. At least one of my devices (3COM 54 * Bluetooth PCCARD) rejects Create_Connection command if another 55 * Create_Connection command is still pending. Weird... 56 */ 57 |
58static int32_t connect_in_progress = 0; |
59 |
60int32_t |
61client_rescan(bthid_server_p srv) 62{ |
63 static hid_device_p d; 64 bthid_session_p s; |
65 66 assert(srv != NULL); 67 68 if (connect_in_progress) 69 return (0); /* another connect is still pending */ 70 71 d = get_next_hid_device(d); 72 if (d == NULL) --- 6 unchanged lines hidden (view full) --- 79 if (d->reconnect_initiate) 80 return (0); /* device will initiate reconnect */ 81 } 82 83 syslog(LOG_NOTICE, "Opening outbound session for %s " \ 84 "(new_device=%d, reconnect_initiate=%d)", 85 bt_ntoa(&d->bdaddr, NULL), d->new_device, d->reconnect_initiate); 86 |
87 if ((s = session_open(srv, d)) == NULL) { 88 syslog(LOG_CRIT, "Could not create outbound session for %s", 89 bt_ntoa(&d->bdaddr, NULL)); |
90 return (-1); 91 } 92 93 /* Open control channel */ 94 s->ctrl = client_socket(&s->bdaddr, d->control_psm); 95 if (s->ctrl < 0) { 96 syslog(LOG_ERR, "Could not open control channel to %s. %s (%d)", 97 bt_ntoa(&s->bdaddr, NULL), strerror(errno), errno); --- 11 unchanged lines hidden (view full) --- 109 110 return (0); 111} 112 113/* 114 * Process connect on the socket 115 */ 116 |
117int32_t 118client_connect(bthid_server_p srv, int32_t fd) |
119{ |
120 bthid_session_p s; 121 hid_device_p d; 122 int32_t error, len; |
123 124 assert(srv != NULL); 125 assert(fd >= 0); 126 127 s = session_by_fd(srv, fd); 128 assert(s != NULL); 129 130 d = get_hid_device(&s->bdaddr); --- 47 unchanged lines hidden (view full) --- 178 break; 179 180 case W4INTR: /* Interrupt channel is open */ 181 assert(s->ctrl != -1); 182 assert(s->intr == fd); 183 184 s->state = OPEN; 185 connect_in_progress = 0; |
186 187 /* Register session's vkbd descriptor (if any) for read */ 188 if (s->state == OPEN && d->keyboard) { 189 assert(s->vkbd != -1); 190 191 FD_SET(s->vkbd, &srv->rfdset); 192 if (s->vkbd > srv->maxfd) 193 srv->maxfd = s->vkbd; 194 } |
195 break; 196 197 default: 198 assert(0); 199 break; 200 } 201 202 /* Move fd to from the write fd set into read fd set */ 203 FD_CLR(fd, &srv->wfdset); 204 FD_SET(fd, &srv->rfdset); 205 206 return (0); 207} 208 209/* 210 * Create bound non-blocking socket and initiate connect 211 */ 212 213static int |
214client_socket(bdaddr_p bdaddr, int32_t psm) |
215{ 216 struct sockaddr_l2cap l2addr; |
217 int32_t s, m; |
218 219 s = socket(PF_BLUETOOTH, SOCK_SEQPACKET, BLUETOOTH_PROTO_L2CAP); 220 if (s < 0) 221 return (-1); 222 223 m = fcntl(s, F_GETFL); 224 if (m < 0) { 225 close(s); 226 return (-1); 227 } 228 229 if (fcntl(s, F_SETFL, (m|O_NONBLOCK)) < 0) { 230 close(s); 231 return (-1); 232 } 233 234 l2addr.l2cap_len = sizeof(l2addr); 235 l2addr.l2cap_family = AF_BLUETOOTH; |
236 memset(&l2addr.l2cap_bdaddr, 0, sizeof(l2addr.l2cap_bdaddr)); |
237 l2addr.l2cap_psm = 0; 238 239 if (bind(s, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0) { 240 close(s); 241 return (-1); 242 } 243 244 memcpy(&l2addr.l2cap_bdaddr, bdaddr, sizeof(l2addr.l2cap_bdaddr)); |
245 l2addr.l2cap_psm = psm; |
246 247 if (connect(s, (struct sockaddr *) &l2addr, sizeof(l2addr)) < 0 && 248 errno != EINPROGRESS) { 249 close(s); 250 return (-1); 251 } 252 253 return (s); 254} 255 |