1 /* $NetBSD: sco_socket.c,v 1.33 2014/08/09 05:33:01 rtr Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Itronix Inc. 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 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of Itronix Inc. may not be used to endorse 16 * or promote products derived from this software without specific 17 * prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 __KERNEL_RCSID(0, "$NetBSD: sco_socket.c,v 1.33 2014/08/09 05:33:01 rtr Exp $"); 34 35 /* load symbolic names */ 36 #ifdef BLUETOOTH_DEBUG 37 #define PRUREQUESTS 38 #define PRCOREQUESTS 39 #endif 40 41 #include <sys/param.h> 42 #include <sys/domain.h> 43 #include <sys/kernel.h> 44 #include <sys/mbuf.h> 45 #include <sys/proc.h> 46 #include <sys/protosw.h> 47 #include <sys/socket.h> 48 #include <sys/socketvar.h> 49 #include <sys/systm.h> 50 51 #include <netbt/bluetooth.h> 52 #include <netbt/hci.h> 53 #include <netbt/sco.h> 54 55 /******************************************************************************* 56 * 57 * SCO SOCK_SEQPACKET sockets - low latency audio data 58 */ 59 60 static void sco_connecting(void *); 61 static void sco_connected(void *); 62 static void sco_disconnected(void *, int); 63 static void *sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); 64 static void sco_complete(void *, int); 65 static void sco_linkmode(void *, int); 66 static void sco_input(void *, struct mbuf *); 67 68 static const struct btproto sco_proto = { 69 sco_connecting, 70 sco_connected, 71 sco_disconnected, 72 sco_newconn, 73 sco_complete, 74 sco_linkmode, 75 sco_input, 76 }; 77 78 int sco_sendspace = 4096; 79 int sco_recvspace = 4096; 80 81 static int 82 sco_attach(struct socket *so, int proto) 83 { 84 int error; 85 86 KASSERT(so->so_pcb == NULL); 87 88 if (so->so_lock == NULL) { 89 mutex_obj_hold(bt_lock); 90 so->so_lock = bt_lock; 91 solock(so); 92 } 93 KASSERT(solocked(so)); 94 95 error = soreserve(so, sco_sendspace, sco_recvspace); 96 if (error) { 97 return error; 98 } 99 return sco_attach_pcb((struct sco_pcb **)&so->so_pcb, &sco_proto, so); 100 } 101 102 static void 103 sco_detach(struct socket *so) 104 { 105 KASSERT(so->so_pcb != NULL); 106 sco_detach_pcb((struct sco_pcb **)&so->so_pcb); 107 KASSERT(so->so_pcb == NULL); 108 } 109 110 static int 111 sco_accept(struct socket *so, struct mbuf *nam) 112 { 113 struct sco_pcb *pcb = so->so_pcb; 114 struct sockaddr_bt *sa; 115 116 KASSERT(solocked(so)); 117 KASSERT(nam != NULL); 118 119 if (pcb == NULL) 120 return EINVAL; 121 122 sa = mtod(nam, struct sockaddr_bt *); 123 nam->m_len = sizeof(struct sockaddr_bt); 124 return sco_peeraddr_pcb(pcb, sa); 125 } 126 127 static int 128 sco_bind(struct socket *so, struct mbuf *nam, struct lwp *l) 129 { 130 struct sco_pcb *pcb = so->so_pcb; 131 struct sockaddr_bt *sa; 132 133 KASSERT(solocked(so)); 134 KASSERT(nam != NULL); 135 136 if (pcb == NULL) 137 return EINVAL; 138 139 sa = mtod(nam, struct sockaddr_bt *); 140 if (sa->bt_len != sizeof(struct sockaddr_bt)) 141 return EINVAL; 142 143 if (sa->bt_family != AF_BLUETOOTH) 144 return EAFNOSUPPORT; 145 146 return sco_bind_pcb(pcb, sa); 147 } 148 149 static int 150 sco_listen(struct socket *so, struct lwp *l) 151 { 152 struct sco_pcb *pcb = so->so_pcb; 153 154 KASSERT(solocked(so)); 155 156 if (pcb == NULL) 157 return EINVAL; 158 159 return sco_listen_pcb(pcb); 160 } 161 162 static int 163 sco_connect(struct socket *so, struct mbuf *nam, struct lwp *l) 164 { 165 struct sco_pcb *pcb = so->so_pcb; 166 struct sockaddr_bt *sa; 167 168 KASSERT(solocked(so)); 169 KASSERT(nam != NULL); 170 171 if (pcb == NULL) 172 return EINVAL; 173 174 sa = mtod(nam, struct sockaddr_bt *); 175 if (sa->bt_len != sizeof(struct sockaddr_bt)) 176 return EINVAL; 177 178 if (sa->bt_family != AF_BLUETOOTH) 179 return EAFNOSUPPORT; 180 181 soisconnecting(so); 182 return sco_connect_pcb(pcb, sa); 183 } 184 185 static int 186 sco_connect2(struct socket *so, struct socket *so2) 187 { 188 struct sco_pcb *pcb = so->so_pcb; 189 190 KASSERT(solocked(so)); 191 192 if (pcb == NULL) 193 return EINVAL; 194 195 return EOPNOTSUPP; 196 } 197 198 static int 199 sco_disconnect(struct socket *so) 200 { 201 struct sco_pcb *pcb = so->so_pcb; 202 203 KASSERT(solocked(so)); 204 205 if (pcb == NULL) 206 return EINVAL; 207 208 soisdisconnecting(so); 209 return sco_disconnect_pcb(pcb, so->so_linger); 210 } 211 212 static int 213 sco_shutdown(struct socket *so) 214 { 215 KASSERT(solocked(so)); 216 217 socantsendmore(so); 218 return 0; 219 } 220 221 static int 222 sco_abort(struct socket *so) 223 { 224 struct sco_pcb *pcb = so->so_pcb; 225 226 KASSERT(solocked(so)); 227 228 if (pcb == NULL) 229 return EINVAL; 230 231 sco_disconnect_pcb(pcb, 0); 232 soisdisconnected(so); 233 sco_detach(so); 234 return 0; 235 } 236 237 static int 238 sco_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) 239 { 240 return EOPNOTSUPP; 241 } 242 243 static int 244 sco_stat(struct socket *so, struct stat *ub) 245 { 246 KASSERT(solocked(so)); 247 248 return 0; 249 } 250 251 static int 252 sco_peeraddr(struct socket *so, struct mbuf *nam) 253 { 254 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; 255 struct sockaddr_bt *sa; 256 257 KASSERT(solocked(so)); 258 KASSERT(pcb != NULL); 259 KASSERT(nam != NULL); 260 261 sa = mtod(nam, struct sockaddr_bt *); 262 nam->m_len = sizeof(struct sockaddr_bt); 263 return sco_peeraddr_pcb(pcb, sa); 264 } 265 266 static int 267 sco_sockaddr(struct socket *so, struct mbuf *nam) 268 { 269 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; 270 struct sockaddr_bt *sa; 271 272 KASSERT(solocked(so)); 273 KASSERT(pcb != NULL); 274 KASSERT(nam != NULL); 275 276 sa = mtod(nam, struct sockaddr_bt *); 277 nam->m_len = sizeof(struct sockaddr_bt); 278 return sco_sockaddr_pcb(pcb, sa); 279 } 280 281 static int 282 sco_rcvd(struct socket *so, int flags, struct lwp *l) 283 { 284 KASSERT(solocked(so)); 285 286 return EOPNOTSUPP; 287 } 288 289 static int 290 sco_recvoob(struct socket *so, struct mbuf *m, int flags) 291 { 292 KASSERT(solocked(so)); 293 294 return EOPNOTSUPP; 295 } 296 297 static int 298 sco_send(struct socket *so, struct mbuf *m, struct mbuf *nam, 299 struct mbuf *control, struct lwp *l) 300 { 301 struct sco_pcb *pcb = so->so_pcb; 302 int err = 0; 303 struct mbuf *m0; 304 305 KASSERT(solocked(so)); 306 KASSERT(m != NULL); 307 308 if (control) /* no use for that */ 309 m_freem(control); 310 311 if (pcb == NULL) { 312 err = EINVAL; 313 goto release; 314 } 315 316 if (m->m_pkthdr.len == 0) 317 goto release; 318 319 if (m->m_pkthdr.len > pcb->sp_mtu) { 320 err = EMSGSIZE; 321 goto release; 322 } 323 324 m0 = m_copypacket(m, M_DONTWAIT); 325 if (m0 == NULL) { 326 err = ENOMEM; 327 goto release; 328 } 329 330 sbappendrecord(&so->so_snd, m); 331 return sco_send_pcb(pcb, m0); 332 333 release: 334 m_freem(m); 335 return err; 336 } 337 338 static int 339 sco_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) 340 { 341 KASSERT(solocked(so)); 342 343 if (m) 344 m_freem(m); 345 if (control) 346 m_freem(control); 347 348 return EOPNOTSUPP; 349 } 350 351 static int 352 sco_purgeif(struct socket *so, struct ifnet *ifp) 353 { 354 355 return EOPNOTSUPP; 356 } 357 358 /* 359 * User Request. 360 * up is socket 361 * m is optional mbuf chain containing message 362 * nam is optional mbuf chain containing an address 363 * ctl is optional mbuf chain containing socket options 364 * l is pointer to process requesting action (if any) 365 * 366 * we are responsible for disposing of m and ctl if 367 * they are mbuf chains 368 */ 369 static int 370 sco_usrreq(struct socket *up, int req, struct mbuf *m, 371 struct mbuf *nam, struct mbuf *ctl, struct lwp *l) 372 { 373 struct sco_pcb *pcb = up->so_pcb; 374 int err = 0; 375 376 DPRINTFN(2, "%s\n", prurequests[req]); 377 KASSERT(req != PRU_ATTACH); 378 KASSERT(req != PRU_DETACH); 379 KASSERT(req != PRU_ACCEPT); 380 KASSERT(req != PRU_BIND); 381 KASSERT(req != PRU_LISTEN); 382 KASSERT(req != PRU_CONNECT); 383 KASSERT(req != PRU_CONNECT2); 384 KASSERT(req != PRU_DISCONNECT); 385 KASSERT(req != PRU_SHUTDOWN); 386 KASSERT(req != PRU_ABORT); 387 KASSERT(req != PRU_CONTROL); 388 KASSERT(req != PRU_SENSE); 389 KASSERT(req != PRU_PEERADDR); 390 KASSERT(req != PRU_SOCKADDR); 391 KASSERT(req != PRU_RCVD); 392 KASSERT(req != PRU_RCVOOB); 393 KASSERT(req != PRU_SEND); 394 KASSERT(req != PRU_SENDOOB); 395 KASSERT(req != PRU_PURGEIF); 396 397 /* anything after here *requires* a pcb */ 398 if (pcb == NULL) { 399 err = EINVAL; 400 goto release; 401 } 402 403 switch(req) { 404 case PRU_FASTTIMO: 405 case PRU_SLOWTIMO: 406 case PRU_PROTORCV: 407 case PRU_PROTOSEND: 408 err = EOPNOTSUPP; 409 break; 410 411 default: 412 UNKNOWN(req); 413 err = EOPNOTSUPP; 414 break; 415 } 416 417 release: 418 if (m) m_freem(m); 419 if (ctl) m_freem(ctl); 420 return err; 421 } 422 423 /* 424 * get/set socket options 425 */ 426 int 427 sco_ctloutput(int req, struct socket *so, struct sockopt *sopt) 428 { 429 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; 430 int err = 0; 431 432 DPRINTFN(2, "req %s\n", prcorequests[req]); 433 434 if (pcb == NULL) 435 return EINVAL; 436 437 if (sopt->sopt_level != BTPROTO_SCO) 438 return ENOPROTOOPT; 439 440 switch(req) { 441 case PRCO_GETOPT: 442 err = sco_getopt(pcb, sopt); 443 break; 444 445 case PRCO_SETOPT: 446 err = sco_setopt(pcb, sopt); 447 break; 448 449 default: 450 err = ENOPROTOOPT; 451 break; 452 } 453 454 return err; 455 } 456 457 /***************************************************************************** 458 * 459 * SCO Protocol socket callbacks 460 * 461 */ 462 static void 463 sco_connecting(void *arg) 464 { 465 struct socket *so = arg; 466 467 DPRINTF("Connecting\n"); 468 soisconnecting(so); 469 } 470 471 static void 472 sco_connected(void *arg) 473 { 474 struct socket *so = arg; 475 476 DPRINTF("Connected\n"); 477 soisconnected(so); 478 } 479 480 static void 481 sco_disconnected(void *arg, int err) 482 { 483 struct socket *so = arg; 484 485 DPRINTF("Disconnected (%d)\n", err); 486 487 so->so_error = err; 488 soisdisconnected(so); 489 } 490 491 static void * 492 sco_newconn(void *arg, struct sockaddr_bt *laddr, 493 struct sockaddr_bt *raddr) 494 { 495 struct socket *so = arg; 496 497 DPRINTF("New Connection\n"); 498 so = sonewconn(so, false); 499 if (so == NULL) 500 return NULL; 501 502 soisconnecting(so); 503 return so->so_pcb; 504 } 505 506 static void 507 sco_complete(void *arg, int num) 508 { 509 struct socket *so = arg; 510 511 while (num-- > 0) 512 sbdroprecord(&so->so_snd); 513 514 sowwakeup(so); 515 } 516 517 static void 518 sco_linkmode(void *arg, int mode) 519 { 520 } 521 522 static void 523 sco_input(void *arg, struct mbuf *m) 524 { 525 struct socket *so = arg; 526 527 /* 528 * since this data is time sensitive, if the buffer 529 * is full we just dump data until the latest one 530 * will fit. 531 */ 532 533 while (m->m_pkthdr.len > sbspace(&so->so_rcv)) 534 sbdroprecord(&so->so_rcv); 535 536 DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len); 537 538 sbappendrecord(&so->so_rcv, m); 539 sorwakeup(so); 540 } 541 542 PR_WRAP_USRREQS(sco) 543 544 #define sco_attach sco_attach_wrapper 545 #define sco_detach sco_detach_wrapper 546 #define sco_accept sco_accept_wrapper 547 #define sco_bind sco_bind_wrapper 548 #define sco_listen sco_listen_wrapper 549 #define sco_connect sco_connect_wrapper 550 #define sco_connect2 sco_connect2_wrapper 551 #define sco_disconnect sco_disconnect_wrapper 552 #define sco_shutdown sco_shutdown_wrapper 553 #define sco_abort sco_abort_wrapper 554 #define sco_ioctl sco_ioctl_wrapper 555 #define sco_stat sco_stat_wrapper 556 #define sco_peeraddr sco_peeraddr_wrapper 557 #define sco_sockaddr sco_sockaddr_wrapper 558 #define sco_rcvd sco_rcvd_wrapper 559 #define sco_recvoob sco_recvoob_wrapper 560 #define sco_send sco_send_wrapper 561 #define sco_sendoob sco_sendoob_wrapper 562 #define sco_purgeif sco_purgeif_wrapper 563 #define sco_usrreq sco_usrreq_wrapper 564 565 const struct pr_usrreqs sco_usrreqs = { 566 .pr_attach = sco_attach, 567 .pr_detach = sco_detach, 568 .pr_accept = sco_accept, 569 .pr_bind = sco_bind, 570 .pr_listen = sco_listen, 571 .pr_connect = sco_connect, 572 .pr_connect2 = sco_connect2, 573 .pr_disconnect = sco_disconnect, 574 .pr_shutdown = sco_shutdown, 575 .pr_abort = sco_abort, 576 .pr_ioctl = sco_ioctl, 577 .pr_stat = sco_stat, 578 .pr_peeraddr = sco_peeraddr, 579 .pr_sockaddr = sco_sockaddr, 580 .pr_rcvd = sco_rcvd, 581 .pr_recvoob = sco_recvoob, 582 .pr_send = sco_send, 583 .pr_sendoob = sco_sendoob, 584 .pr_purgeif = sco_purgeif, 585 .pr_generic = sco_usrreq, 586 }; 587