1 /* $NetBSD: sco_socket.c,v 1.39 2024/07/05 04:31:53 rin 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.39 2024/07/05 04:31:53 rin 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 sockaddr *nam) 112 { 113 struct sco_pcb *pcb = so->so_pcb; 114 115 KASSERT(solocked(so)); 116 KASSERT(nam != NULL); 117 118 if (pcb == NULL) 119 return EINVAL; 120 121 return sco_peeraddr_pcb(pcb, (struct sockaddr_bt *)nam); 122 } 123 124 static int 125 sco_bind(struct socket *so, struct sockaddr *nam, struct lwp *l) 126 { 127 struct sco_pcb *pcb = so->so_pcb; 128 struct sockaddr_bt *sa = (struct sockaddr_bt *)nam; 129 130 KASSERT(solocked(so)); 131 KASSERT(nam != NULL); 132 133 if (pcb == NULL) 134 return EINVAL; 135 136 if (sa->bt_len != sizeof(struct sockaddr_bt)) 137 return EINVAL; 138 139 if (sa->bt_family != AF_BLUETOOTH) 140 return EAFNOSUPPORT; 141 142 return sco_bind_pcb(pcb, sa); 143 } 144 145 static int 146 sco_listen(struct socket *so, struct lwp *l) 147 { 148 struct sco_pcb *pcb = so->so_pcb; 149 150 KASSERT(solocked(so)); 151 152 if (pcb == NULL) 153 return EINVAL; 154 155 return sco_listen_pcb(pcb); 156 } 157 158 static int 159 sco_connect(struct socket *so, struct sockaddr *nam, struct lwp *l) 160 { 161 struct sco_pcb *pcb = so->so_pcb; 162 struct sockaddr_bt *sa = (struct sockaddr_bt *)nam; 163 164 KASSERT(solocked(so)); 165 KASSERT(nam != NULL); 166 167 if (pcb == NULL) 168 return EINVAL; 169 170 if (sa->bt_len != sizeof(struct sockaddr_bt)) 171 return EINVAL; 172 173 if (sa->bt_family != AF_BLUETOOTH) 174 return EAFNOSUPPORT; 175 176 soisconnecting(so); 177 return sco_connect_pcb(pcb, sa); 178 } 179 180 static int 181 sco_connect2(struct socket *so, struct socket *so2) 182 { 183 struct sco_pcb *pcb = so->so_pcb; 184 185 KASSERT(solocked(so)); 186 187 if (pcb == NULL) 188 return EINVAL; 189 190 return EOPNOTSUPP; 191 } 192 193 static int 194 sco_disconnect(struct socket *so) 195 { 196 struct sco_pcb *pcb = so->so_pcb; 197 198 KASSERT(solocked(so)); 199 200 if (pcb == NULL) 201 return EINVAL; 202 203 soisdisconnecting(so); 204 return sco_disconnect_pcb(pcb, so->so_linger); 205 } 206 207 static int 208 sco_shutdown(struct socket *so) 209 { 210 KASSERT(solocked(so)); 211 212 socantsendmore(so); 213 return 0; 214 } 215 216 static int 217 sco_abort(struct socket *so) 218 { 219 struct sco_pcb *pcb = so->so_pcb; 220 221 KASSERT(solocked(so)); 222 223 if (pcb == NULL) 224 return EINVAL; 225 226 sco_disconnect_pcb(pcb, 0); 227 soisdisconnected(so); 228 sco_detach(so); 229 return 0; 230 } 231 232 static int 233 sco_ioctl(struct socket *so, u_long cmd, void *nam, struct ifnet *ifp) 234 { 235 return EOPNOTSUPP; 236 } 237 238 static int 239 sco_stat(struct socket *so, struct stat *ub) 240 { 241 KASSERT(solocked(so)); 242 243 return 0; 244 } 245 246 static int 247 sco_peeraddr(struct socket *so, struct sockaddr *nam) 248 { 249 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; 250 251 KASSERT(solocked(so)); 252 KASSERT(pcb != NULL); 253 KASSERT(nam != NULL); 254 255 return sco_peeraddr_pcb(pcb, (struct sockaddr_bt *)nam); 256 } 257 258 static int 259 sco_sockaddr(struct socket *so, struct sockaddr *nam) 260 { 261 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; 262 263 KASSERT(solocked(so)); 264 KASSERT(pcb != NULL); 265 KASSERT(nam != NULL); 266 267 return sco_sockaddr_pcb(pcb, (struct sockaddr_bt *)nam); 268 } 269 270 static int 271 sco_rcvd(struct socket *so, int flags, struct lwp *l) 272 { 273 KASSERT(solocked(so)); 274 275 return EOPNOTSUPP; 276 } 277 278 static int 279 sco_recvoob(struct socket *so, struct mbuf *m, int flags) 280 { 281 KASSERT(solocked(so)); 282 283 return EOPNOTSUPP; 284 } 285 286 static int 287 sco_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, 288 struct mbuf *control, struct lwp *l) 289 { 290 struct sco_pcb *pcb = so->so_pcb; 291 int err = 0; 292 struct mbuf *m0; 293 294 KASSERT(solocked(so)); 295 KASSERT(m != NULL); 296 297 m_freem(control); /* no use for that */ 298 299 if (pcb == NULL) { 300 err = EINVAL; 301 goto release; 302 } 303 304 if (m->m_pkthdr.len == 0) 305 goto release; 306 307 if (m->m_pkthdr.len > pcb->sp_mtu) { 308 err = EMSGSIZE; 309 goto release; 310 } 311 312 m0 = m_copypacket(m, M_DONTWAIT); 313 if (m0 == NULL) { 314 err = ENOMEM; 315 goto release; 316 } 317 318 sbappendrecord(&so->so_snd, m); 319 return sco_send_pcb(pcb, m0); 320 321 release: 322 m_freem(m); 323 return err; 324 } 325 326 static int 327 sco_sendoob(struct socket *so, struct mbuf *m, struct mbuf *control) 328 { 329 KASSERT(solocked(so)); 330 331 m_freem(m); 332 m_freem(control); 333 334 return EOPNOTSUPP; 335 } 336 337 static int 338 sco_purgeif(struct socket *so, struct ifnet *ifp) 339 { 340 341 return EOPNOTSUPP; 342 } 343 344 /* 345 * get/set socket options 346 */ 347 int 348 sco_ctloutput(int req, struct socket *so, struct sockopt *sopt) 349 { 350 struct sco_pcb *pcb = (struct sco_pcb *)so->so_pcb; 351 int err = 0; 352 353 DPRINTFN(2, "req %s\n", prcorequests[req]); 354 355 if (pcb == NULL) 356 return EINVAL; 357 358 if (sopt->sopt_level != BTPROTO_SCO) 359 return ENOPROTOOPT; 360 361 switch(req) { 362 case PRCO_GETOPT: 363 err = sco_getopt(pcb, sopt); 364 break; 365 366 case PRCO_SETOPT: 367 err = sco_setopt(pcb, sopt); 368 break; 369 370 default: 371 err = ENOPROTOOPT; 372 break; 373 } 374 375 return err; 376 } 377 378 /***************************************************************************** 379 * 380 * SCO Protocol socket callbacks 381 * 382 */ 383 static void 384 sco_connecting(void *arg) 385 { 386 struct socket *so = arg; 387 388 DPRINTF("Connecting\n"); 389 soisconnecting(so); 390 } 391 392 static void 393 sco_connected(void *arg) 394 { 395 struct socket *so = arg; 396 397 DPRINTF("Connected\n"); 398 soisconnected(so); 399 } 400 401 static void 402 sco_disconnected(void *arg, int err) 403 { 404 struct socket *so = arg; 405 406 DPRINTF("Disconnected (%d)\n", err); 407 408 so->so_error = err; 409 soisdisconnected(so); 410 } 411 412 static void * 413 sco_newconn(void *arg, struct sockaddr_bt *laddr, 414 struct sockaddr_bt *raddr) 415 { 416 struct socket *so = arg; 417 418 DPRINTF("New Connection\n"); 419 so = sonewconn(so, false); 420 if (so == NULL) 421 return NULL; 422 423 soisconnecting(so); 424 return so->so_pcb; 425 } 426 427 static void 428 sco_complete(void *arg, int num) 429 { 430 struct socket *so = arg; 431 432 while (num-- > 0) 433 sbdroprecord(&so->so_snd); 434 435 sowwakeup(so); 436 } 437 438 static void 439 sco_linkmode(void *arg, int mode) 440 { 441 } 442 443 static void 444 sco_input(void *arg, struct mbuf *m) 445 { 446 struct socket *so = arg; 447 448 /* 449 * since this data is time sensitive, if the buffer 450 * is full we just dump data until the latest one 451 * will fit. 452 */ 453 454 while (m->m_pkthdr.len > sbspace(&so->so_rcv)) 455 sbdroprecord(&so->so_rcv); 456 457 DPRINTFN(10, "received %d bytes\n", m->m_pkthdr.len); 458 459 sbappendrecord(&so->so_rcv, m); 460 sorwakeup(so); 461 } 462 463 PR_WRAP_USRREQS(sco) 464 465 #define sco_attach sco_attach_wrapper 466 #define sco_detach sco_detach_wrapper 467 #define sco_accept sco_accept_wrapper 468 #define sco_bind sco_bind_wrapper 469 #define sco_listen sco_listen_wrapper 470 #define sco_connect sco_connect_wrapper 471 #define sco_connect2 sco_connect2_wrapper 472 #define sco_disconnect sco_disconnect_wrapper 473 #define sco_shutdown sco_shutdown_wrapper 474 #define sco_abort sco_abort_wrapper 475 #define sco_ioctl sco_ioctl_wrapper 476 #define sco_stat sco_stat_wrapper 477 #define sco_peeraddr sco_peeraddr_wrapper 478 #define sco_sockaddr sco_sockaddr_wrapper 479 #define sco_rcvd sco_rcvd_wrapper 480 #define sco_recvoob sco_recvoob_wrapper 481 #define sco_send sco_send_wrapper 482 #define sco_sendoob sco_sendoob_wrapper 483 #define sco_purgeif sco_purgeif_wrapper 484 485 const struct pr_usrreqs sco_usrreqs = { 486 .pr_attach = sco_attach, 487 .pr_detach = sco_detach, 488 .pr_accept = sco_accept, 489 .pr_bind = sco_bind, 490 .pr_listen = sco_listen, 491 .pr_connect = sco_connect, 492 .pr_connect2 = sco_connect2, 493 .pr_disconnect = sco_disconnect, 494 .pr_shutdown = sco_shutdown, 495 .pr_abort = sco_abort, 496 .pr_ioctl = sco_ioctl, 497 .pr_stat = sco_stat, 498 .pr_peeraddr = sco_peeraddr, 499 .pr_sockaddr = sco_sockaddr, 500 .pr_rcvd = sco_rcvd, 501 .pr_recvoob = sco_recvoob, 502 .pr_send = sco_send, 503 .pr_sendoob = sco_sendoob, 504 .pr_purgeif = sco_purgeif, 505 }; 506