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