1 /* $NetBSD: sco_socket.c,v 1.34 2015/04/03 20:01:07 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.34 2015/04/03 20:01:07 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 sockaddr *nam, struct lwp *l) 129 { 130 struct sco_pcb *pcb = so->so_pcb; 131 struct sockaddr_bt *sa = (struct sockaddr_bt *)nam; 132 133 KASSERT(solocked(so)); 134 KASSERT(nam != NULL); 135 136 if (pcb == NULL) 137 return EINVAL; 138 139 if (sa->bt_len != sizeof(struct sockaddr_bt)) 140 return EINVAL; 141 142 if (sa->bt_family != AF_BLUETOOTH) 143 return EAFNOSUPPORT; 144 145 return sco_bind_pcb(pcb, sa); 146 } 147 148 static int 149 sco_listen(struct socket *so, struct lwp *l) 150 { 151 struct sco_pcb *pcb = so->so_pcb; 152 153 KASSERT(solocked(so)); 154 155 if (pcb == NULL) 156 return EINVAL; 157 158 return sco_listen_pcb(pcb); 159 } 160 161 static int 162 sco_connect(struct socket *so, struct mbuf *nam, struct lwp *l) 163 { 164 struct sco_pcb *pcb = so->so_pcb; 165 struct sockaddr_bt *sa; 166 167 KASSERT(solocked(so)); 168 KASSERT(nam != NULL); 169 170 if (pcb == NULL) 171 return EINVAL; 172 173 sa = mtod(nam, struct sockaddr_bt *); 174 if (sa->bt_len != sizeof(struct sockaddr_bt)) 175 return EINVAL; 176 177 if (sa->bt_family != AF_BLUETOOTH) 178 return EAFNOSUPPORT; 179 180 soisconnecting(so); 181 return sco_connect_pcb(pcb, sa); 182 } 183 184 static int 185 sco_connect2(struct socket *so, struct socket *so2) 186 { 187 struct sco_pcb *pcb = so->so_pcb; 188 189 KASSERT(solocked(so)); 190 191 if (pcb == NULL) 192 return EINVAL; 193 194 return EOPNOTSUPP; 195 } 196 197 static int 198 sco_disconnect(struct socket *so) 199 { 200 struct sco_pcb *pcb = so->so_pcb; 201 202 KASSERT(solocked(so)); 203 204 if (pcb == NULL) 205 return EINVAL; 206 207 soisdisconnecting(so); 208 return sco_disconnect_pcb(pcb, so->so_linger); 209 } 210 211 static int 212 sco_shutdown(struct socket *so) 213 { 214 KASSERT(solocked(so)); 215 216 socantsendmore(so); 217 return 0; 218 } 219 220 static int 221 sco_abort(struct socket *so) 222 { 223 struct sco_pcb *pcb = so->so_pcb; 224 225 KASSERT(solocked(so)); 226 227 if (pcb == NULL) 228 return EINVAL; 229 230 sco_disconnect_pcb(pcb, 0); 231 soisdisconnected(so); 232 sco_detach(so); 233 return 0; 234 } 235 236 static int 237 sco_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) 238 { 239 return EOPNOTSUPP; 240 } 241 242 static int 243 sco_stat(struct socket *so, struct stat *ub) 244 { 245 KASSERT(solocked(so)); 246 247 return 0; 248 } 249 250 static int 251 sco_peeraddr(struct socket *so, struct mbuf *nam) 252 { 253 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; 254 struct sockaddr_bt *sa; 255 256 KASSERT(solocked(so)); 257 KASSERT(pcb != NULL); 258 KASSERT(nam != NULL); 259 260 sa = mtod(nam, struct sockaddr_bt *); 261 nam->m_len = sizeof(struct sockaddr_bt); 262 return sco_peeraddr_pcb(pcb, sa); 263 } 264 265 static int 266 sco_sockaddr(struct socket *so, struct mbuf *nam) 267 { 268 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; 269 struct sockaddr_bt *sa; 270 271 KASSERT(solocked(so)); 272 KASSERT(pcb != NULL); 273 KASSERT(nam != NULL); 274 275 sa = mtod(nam, struct sockaddr_bt *); 276 nam->m_len = sizeof(struct sockaddr_bt); 277 return sco_sockaddr_pcb(pcb, sa); 278 } 279 280 static int 281 sco_rcvd(struct socket *so, int flags, struct lwp *l) 282 { 283 KASSERT(solocked(so)); 284 285 return EOPNOTSUPP; 286 } 287 288 static int 289 sco_recvoob(struct socket *so, struct mbuf *m, int flags) 290 { 291 KASSERT(solocked(so)); 292 293 return EOPNOTSUPP; 294 } 295 296 static int 297 sco_send(struct socket *so, struct mbuf *m, struct mbuf *nam, 298 struct mbuf *control, struct lwp *l) 299 { 300 struct sco_pcb *pcb = so->so_pcb; 301 int err = 0; 302 struct mbuf *m0; 303 304 KASSERT(solocked(so)); 305 KASSERT(m != NULL); 306 307 if (control) /* no use for that */ 308 m_freem(control); 309 310 if (pcb == NULL) { 311 err = EINVAL; 312 goto release; 313 } 314 315 if (m->m_pkthdr.len == 0) 316 goto release; 317 318 if (m->m_pkthdr.len > pcb->sp_mtu) { 319 err = EMSGSIZE; 320 goto release; 321 } 322 323 m0 = m_copypacket(m, M_DONTWAIT); 324 if (m0 == NULL) { 325 err = ENOMEM; 326 goto release; 327 } 328 329 sbappendrecord(&so->so_snd, m); 330 return sco_send_pcb(pcb, m0); 331 332 release: 333 m_freem(m); 334 return err; 335 } 336 337 static int 338 sco_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) 339 { 340 KASSERT(solocked(so)); 341 342 if (m) 343 m_freem(m); 344 if (control) 345 m_freem(control); 346 347 return EOPNOTSUPP; 348 } 349 350 static int 351 sco_purgeif(struct socket *so, struct ifnet *ifp) 352 { 353 354 return EOPNOTSUPP; 355 } 356 357 /* 358 * User Request. 359 * up is socket 360 * m is optional mbuf chain containing message 361 * nam is optional mbuf chain containing an address 362 * ctl is optional mbuf chain containing socket options 363 * l is pointer to process requesting action (if any) 364 * 365 * we are responsible for disposing of m and ctl if 366 * they are mbuf chains 367 */ 368 static int 369 sco_usrreq(struct socket *up, int req, struct mbuf *m, 370 struct mbuf *nam, struct mbuf *ctl, struct lwp *l) 371 { 372 struct sco_pcb *pcb = up->so_pcb; 373 int err = 0; 374 375 DPRINTFN(2, "%s\n", prurequests[req]); 376 KASSERT(req != PRU_ATTACH); 377 KASSERT(req != PRU_DETACH); 378 KASSERT(req != PRU_ACCEPT); 379 KASSERT(req != PRU_BIND); 380 KASSERT(req != PRU_LISTEN); 381 KASSERT(req != PRU_CONNECT); 382 KASSERT(req != PRU_CONNECT2); 383 KASSERT(req != PRU_DISCONNECT); 384 KASSERT(req != PRU_SHUTDOWN); 385 KASSERT(req != PRU_ABORT); 386 KASSERT(req != PRU_CONTROL); 387 KASSERT(req != PRU_SENSE); 388 KASSERT(req != PRU_PEERADDR); 389 KASSERT(req != PRU_SOCKADDR); 390 KASSERT(req != PRU_RCVD); 391 KASSERT(req != PRU_RCVOOB); 392 KASSERT(req != PRU_SEND); 393 KASSERT(req != PRU_SENDOOB); 394 KASSERT(req != PRU_PURGEIF); 395 396 /* anything after here *requires* a pcb */ 397 if (pcb == NULL) { 398 err = EINVAL; 399 goto release; 400 } 401 402 switch(req) { 403 case PRU_FASTTIMO: 404 case PRU_SLOWTIMO: 405 case PRU_PROTORCV: 406 case PRU_PROTOSEND: 407 err = EOPNOTSUPP; 408 break; 409 410 default: 411 UNKNOWN(req); 412 err = EOPNOTSUPP; 413 break; 414 } 415 416 release: 417 if (m) m_freem(m); 418 if (ctl) m_freem(ctl); 419 return err; 420 } 421 422 /* 423 * get/set socket options 424 */ 425 int 426 sco_ctloutput(int req, struct socket *so, struct sockopt *sopt) 427 { 428 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; 429 int err = 0; 430 431 DPRINTFN(2, "req %s\n", prcorequests[req]); 432 433 if (pcb == NULL) 434 return EINVAL; 435 436 if (sopt->sopt_level != BTPROTO_SCO) 437 return ENOPROTOOPT; 438 439 switch(req) { 440 case PRCO_GETOPT: 441 err = sco_getopt(pcb, sopt); 442 break; 443 444 case PRCO_SETOPT: 445 err = sco_setopt(pcb, sopt); 446 break; 447 448 default: 449 err = ENOPROTOOPT; 450 break; 451 } 452 453 return err; 454 } 455 456 /***************************************************************************** 457 * 458 * SCO Protocol socket callbacks 459 * 460 */ 461 static void 462 sco_connecting(void *arg) 463 { 464 struct socket *so = arg; 465 466 DPRINTF("Connecting\n"); 467 soisconnecting(so); 468 } 469 470 static void 471 sco_connected(void *arg) 472 { 473 struct socket *so = arg; 474 475 DPRINTF("Connected\n"); 476 soisconnected(so); 477 } 478 479 static void 480 sco_disconnected(void *arg, int err) 481 { 482 struct socket *so = arg; 483 484 DPRINTF("Disconnected (%d)\n", err); 485 486 so->so_error = err; 487 soisdisconnected(so); 488 } 489 490 static void * 491 sco_newconn(void *arg, struct sockaddr_bt *laddr, 492 struct sockaddr_bt *raddr) 493 { 494 struct socket *so = arg; 495 496 DPRINTF("New Connection\n"); 497 so = sonewconn(so, false); 498 if (so == NULL) 499 return NULL; 500 501 soisconnecting(so); 502 return so->so_pcb; 503 } 504 505 static void 506 sco_complete(void *arg, int num) 507 { 508 struct socket *so = arg; 509 510 while (num-- > 0) 511 sbdroprecord(&so->so_snd); 512 513 sowwakeup(so); 514 } 515 516 static void 517 sco_linkmode(void *arg, int mode) 518 { 519 } 520 521 static void 522 sco_input(void *arg, struct mbuf *m) 523 { 524 struct socket *so = arg; 525 526 /* 527 * since this data is time sensitive, if the buffer 528 * is full we just dump data until the latest one 529 * will fit. 530 */ 531 532 while (m->m_pkthdr.len > sbspace(&so->so_rcv)) 533 sbdroprecord(&so->so_rcv); 534 535 DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len); 536 537 sbappendrecord(&so->so_rcv, m); 538 sorwakeup(so); 539 } 540 541 PR_WRAP_USRREQS(sco) 542 543 #define sco_attach sco_attach_wrapper 544 #define sco_detach sco_detach_wrapper 545 #define sco_accept sco_accept_wrapper 546 #define sco_bind sco_bind_wrapper 547 #define sco_listen sco_listen_wrapper 548 #define sco_connect sco_connect_wrapper 549 #define sco_connect2 sco_connect2_wrapper 550 #define sco_disconnect sco_disconnect_wrapper 551 #define sco_shutdown sco_shutdown_wrapper 552 #define sco_abort sco_abort_wrapper 553 #define sco_ioctl sco_ioctl_wrapper 554 #define sco_stat sco_stat_wrapper 555 #define sco_peeraddr sco_peeraddr_wrapper 556 #define sco_sockaddr sco_sockaddr_wrapper 557 #define sco_rcvd sco_rcvd_wrapper 558 #define sco_recvoob sco_recvoob_wrapper 559 #define sco_send sco_send_wrapper 560 #define sco_sendoob sco_sendoob_wrapper 561 #define sco_purgeif sco_purgeif_wrapper 562 #define sco_usrreq sco_usrreq_wrapper 563 564 const struct pr_usrreqs sco_usrreqs = { 565 .pr_attach = sco_attach, 566 .pr_detach = sco_detach, 567 .pr_accept = sco_accept, 568 .pr_bind = sco_bind, 569 .pr_listen = sco_listen, 570 .pr_connect = sco_connect, 571 .pr_connect2 = sco_connect2, 572 .pr_disconnect = sco_disconnect, 573 .pr_shutdown = sco_shutdown, 574 .pr_abort = sco_abort, 575 .pr_ioctl = sco_ioctl, 576 .pr_stat = sco_stat, 577 .pr_peeraddr = sco_peeraddr, 578 .pr_sockaddr = sco_sockaddr, 579 .pr_rcvd = sco_rcvd, 580 .pr_recvoob = sco_recvoob, 581 .pr_send = sco_send, 582 .pr_sendoob = sco_sendoob, 583 .pr_purgeif = sco_purgeif, 584 .pr_generic = sco_usrreq, 585 }; 586