1 /* $OpenBSD: bt_proto.c,v 1.4 2007/06/24 20:55:27 uwe Exp $ */ 2 3 /* 4 * Copyright (c) 2004 Alexander Yurchenko <grange@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/param.h> 20 #include <sys/domain.h> 21 #include <sys/protosw.h> 22 #include <sys/socket.h> 23 #include <sys/socketvar.h> 24 #include <sys/queue.h> 25 #include <sys/kernel.h> 26 #include <sys/mbuf.h> 27 #include <sys/sysctl.h> 28 #include <sys/bus.h> 29 #include <sys/malloc.h> 30 #include <net/if.h> 31 32 #include <netbt/bluetooth.h> 33 #include <netbt/hci.h> 34 #include <netbt/l2cap.h> 35 #include <netbt/rfcomm.h> 36 #include <netbt/sco.h> 37 38 MALLOC_DEFINE(M_BLUETOOTH, "Bluetooth", "Bluetooth system memory"); 39 40 extern struct pr_usrreqs hci_usrreqs; 41 42 static int 43 netbt_modevent(module_t mod, int type, void *data) 44 { 45 switch (type) { 46 case MOD_LOAD: 47 break; 48 case MOD_UNLOAD: 49 return EBUSY; 50 break; 51 default: 52 break; 53 } 54 return 0; 55 } 56 57 static moduledata_t netbt_mod = { 58 "netbt", 59 netbt_modevent, 60 NULL 61 }; 62 63 DECLARE_MODULE(netbt, netbt_mod, SI_SUB_EXEC, SI_ORDER_ANY); 64 MODULE_VERSION(netbt, 1); 65 66 struct domain btdomain; 67 68 struct protosw btsw[] = { 69 { /* raw HCI commands */ 70 .pr_type = SOCK_RAW, 71 .pr_domain = &btdomain, 72 .pr_protocol = BTPROTO_HCI, 73 .pr_flags = (PR_ADDR | PR_ATOMIC), 74 .pr_input = 0, 75 .pr_output = 0, 76 .pr_ctlinput = 0, 77 .pr_ctloutput = hci_ctloutput, 78 .pr_ctlport = NULL, 79 .pr_init = 0, 80 .pr_drain = 0, 81 .pr_usrreqs = &hci_usrreqs 82 }, 83 { /* HCI SCO data (audio) */ 84 .pr_type = SOCK_SEQPACKET, 85 .pr_domain = &btdomain, 86 .pr_protocol = BTPROTO_SCO, 87 .pr_flags = (PR_CONNREQUIRED | PR_ATOMIC ), 88 .pr_input = 0, 89 .pr_output = 0, 90 .pr_ctlinput = 0, 91 .pr_ctloutput = sco_ctloutput, 92 .pr_ctlport = NULL, 93 .pr_init = 0, 94 .pr_drain = 0, 95 .pr_usrreqs = &sco_usrreqs 96 97 }, 98 { /* L2CAP Connection Oriented */ 99 .pr_type = SOCK_SEQPACKET, 100 .pr_domain = &btdomain, 101 .pr_protocol = BTPROTO_L2CAP, 102 .pr_flags = (PR_CONNREQUIRED | PR_ATOMIC ), 103 .pr_input = 0, 104 .pr_output = 0, 105 .pr_ctlinput = 0, 106 .pr_ctloutput = l2cap_ctloutput, 107 .pr_ctlport = NULL, 108 .pr_init = 0, 109 .pr_drain = 0, 110 .pr_usrreqs = &l2cap_usrreqs 111 }, 112 { /* RFCOMM */ 113 .pr_type = SOCK_STREAM, 114 .pr_domain = &btdomain, 115 .pr_protocol = BTPROTO_RFCOMM, 116 .pr_flags = (PR_CONNREQUIRED | PR_WANTRCVD), 117 .pr_input = 0, 118 .pr_output = 0, 119 .pr_ctlinput = 0, 120 .pr_ctloutput = rfcomm_ctloutput, 121 .pr_ctlport = NULL, 122 .pr_init = 0, 123 .pr_drain = 0, 124 .pr_usrreqs = &rfcomm_usrreqs 125 }, 126 }; 127 128 static void 129 netbt_dispose(struct mbuf* m) 130 { 131 zdestroy(l2cap_pdu_pool); 132 zdestroy(l2cap_req_pool); 133 zdestroy(rfcomm_credit_pool); 134 } 135 136 static void 137 netbt_init(void) 138 { 139 l2cap_pdu_pool = zinit("l2cap_pdu", sizeof(struct l2cap_pdu), 1, 140 ZONE_DESTROYABLE); 141 if (l2cap_pdu_pool == NULL) 142 goto fail; 143 l2cap_req_pool = zinit("l2cap_req", sizeof(struct l2cap_req), 1, 144 ZONE_DESTROYABLE); 145 if (l2cap_req_pool == NULL) 146 goto fail; 147 rfcomm_credit_pool = zinit("rfcomm_credit", 148 sizeof(struct rfcomm_credit), 1, 149 ZONE_DESTROYABLE); 150 if (rfcomm_credit_pool == NULL) 151 goto fail; 152 return; 153 fail: 154 netbt_dispose(NULL); 155 panic("Can't create vm_zones"); 156 } 157 158 struct domain btdomain = { 159 .dom_family = AF_BLUETOOTH, 160 .dom_name = "bluetooth", 161 .dom_init = netbt_init, 162 .dom_externalize = NULL, 163 .dom_dispose = netbt_dispose, 164 .dom_protosw = btsw, 165 .dom_protoswNPROTOSW = &btsw[NELEM(btsw)], 166 .dom_next = SLIST_ENTRY_INITIALIZER, 167 .dom_rtattach = NULL, 168 .dom_rtoffset = 0, 169 .dom_maxrtkey = sizeof(struct sockaddr_bt), 170 .dom_ifattach = NULL, 171 .dom_ifdetach = NULL, 172 }; 173 174 DOMAIN_SET(bt); 175 SYSCTL_NODE(_net, OID_AUTO, bluetooth, CTLFLAG_RD, 0, 176 "Bluetooth Protocol Family"); 177 178 /* HCI sysctls */ 179 SYSCTL_NODE(_net_bluetooth, OID_AUTO, hci, CTLFLAG_RD, 0, 180 "Host Controller Interface"); 181 SYSCTL_INT(_net_bluetooth_hci, OID_AUTO, sendspace, CTLFLAG_RW, &hci_sendspace, 182 0, "Socket Send Buffer Size"); 183 SYSCTL_INT(_net_bluetooth_hci, OID_AUTO, recvspace, CTLFLAG_RW, &hci_recvspace, 184 0, "Socket Receive Buffer Size"); 185 SYSCTL_INT(_net_bluetooth_hci, OID_AUTO, acl_expiry, CTLFLAG_RW, 186 &hci_acl_expiry, 0, "ACL Connection Expiry Time"); 187 SYSCTL_INT(_net_bluetooth_hci, OID_AUTO, memo_expiry, CTLFLAG_RW, 188 &hci_memo_expiry, 0, "Memo Expiry Time"); 189 SYSCTL_INT(_net_bluetooth_hci, OID_AUTO, eventq_max, CTLFLAG_RW, 190 &hci_eventq_max, 0, "Max Event queue length"); 191 SYSCTL_INT(_net_bluetooth_hci, OID_AUTO, aclrxq_max, CTLFLAG_RW, 192 &hci_aclrxq_max, 0, "Max ACL rx queue length"); 193 SYSCTL_INT(_net_bluetooth_hci, OID_AUTO, scorxq_max, CTLFLAG_RW, 194 &hci_scorxq_max, 0, "Max SCO rx queue length"); 195 196 /* L2CAP sysctls */ 197 SYSCTL_NODE(_net_bluetooth, OID_AUTO, l2cap, CTLFLAG_RD, 0, 198 "Logical Link Control & Adaptation Protocol"); 199 SYSCTL_INT(_net_bluetooth_l2cap, OID_AUTO, sendspace, CTLFLAG_RW, 200 &l2cap_sendspace, 0, "Socket Send Buffer Size"); 201 SYSCTL_INT(_net_bluetooth_l2cap, OID_AUTO, recvspace, CTLFLAG_RW, 202 &l2cap_recvspace, 0, "Socket Receive Buffer Size"); 203 SYSCTL_INT(_net_bluetooth_l2cap, OID_AUTO, rtx, CTLFLAG_RW, 204 &l2cap_response_timeout, 0, "Response Timeout"); 205 SYSCTL_INT(_net_bluetooth_l2cap, OID_AUTO, ertx, CTLFLAG_RW, 206 &l2cap_response_extended_timeout, 0, "Extended Response Timeout"); 207 208 /* RFCOMM sysctls */ 209 SYSCTL_NODE(_net_bluetooth, OID_AUTO, rfcomm, CTLFLAG_RD, 0, 210 "Serial Cable Emulation"); 211 SYSCTL_INT(_net_bluetooth_rfcomm, OID_AUTO, sendspace, CTLFLAG_RW, 212 &rfcomm_sendspace, 0, "Socket Send Buffer Size"); 213 SYSCTL_INT(_net_bluetooth_rfcomm, OID_AUTO, recvspace, CTLFLAG_RW, 214 &rfcomm_recvspace, 0, "Socket Receive Buffer Size"); 215 SYSCTL_INT(_net_bluetooth_rfcomm, OID_AUTO, mtu_default, CTLFLAG_RW, 216 &rfcomm_mtu_default, 0, "Default MTU"); 217 SYSCTL_INT(_net_bluetooth_rfcomm, OID_AUTO, ack_timeout, CTLFLAG_RW, 218 &rfcomm_ack_timeout, 0, "Acknowledgement Timer"); 219 SYSCTL_INT(_net_bluetooth_rfcomm, OID_AUTO, mcc_timeout, CTLFLAG_RW, 220 &rfcomm_mcc_timeout, 0, "Response Timeout for Multiplexer Control Channel"); 221 222 /* SCO sysctls */ 223 SYSCTL_NODE(_net_bluetooth, OID_AUTO, sco, CTLFLAG_RD, 0, "SCO data"); 224 SYSCTL_INT(_net_bluetooth_sco, OID_AUTO, sendspace, CTLFLAG_RW, &sco_sendspace, 225 0, "Socket Send Buffer Size"); 226 SYSCTL_INT(_net_bluetooth_sco, OID_AUTO, recvspace, CTLFLAG_RW, &sco_recvspace, 227 0, "Socket Receive Buffer Size"); 228 229 static void 230 netisr_netbt_setup(void *dummy __unused) 231 { 232 netisr_register(NETISR_BLUETOOTH, btintr, NULL); 233 } 234 235 SYSINIT(netbt_setup, SI_BOOT2_KLD, SI_ORDER_ANY, netisr_netbt_setup, NULL); 236