static int ng_btsocket_hci_raw_node_shutdown(node_p node) { int error = 0; NG_NODE_UNREF(node); error = ng_make_node_common(&typestruct, &ng_btsocket_hci_raw_node); if (error != 0) { NG_BTSOCKET_HCI_RAW_ALERT( "%s: Could not create Netgraph node, error=%d\n", __func__, error); ng_btsocket_hci_raw_node = NULL; return (ENOMEM); } error = ng_name_node(ng_btsocket_hci_raw_node, NG_BTSOCKET_HCI_RAW_NODE_TYPE); if (error != 0) { NG_BTSOCKET_HCI_RAW_ALERT( "%s: Could not name Netgraph node, error=%d\n", __func__, error); NG_NODE_UNREF(ng_btsocket_hci_raw_node); ng_btsocket_hci_raw_node = NULL; return (EINVAL); } return (0); } /* ng_btsocket_hci_raw_node_shutdown */
static int ng_bt3c_shutdown(node_p node) { bt3c_softc_p sc = (bt3c_softc_p) NG_NODE_PRIVATE(node); /* Let old node go */ NG_NODE_SET_PRIVATE(node, NULL); NG_NODE_UNREF(node); /* Create new fresh one if we are not going down */ if (sc == NULL) goto out; /* Create new Netgraph node */ if (ng_make_node_common(&typestruct, &sc->node) != 0) { device_printf(sc->dev, "Could not create Netgraph node\n"); sc->node = NULL; goto out; } /* Name new Netgraph node */ if (ng_name_node(sc->node, device_get_nameunit(sc->dev)) != 0) { device_printf(sc->dev, "Could not name Netgraph node\n"); NG_NODE_UNREF(sc->node); sc->node = NULL; goto out; } NG_NODE_SET_PRIVATE(sc->node, sc); out: return (0); } /* ng_bt3c_shutdown */
int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext) { char nam[NG_NODESIZ]; struct ifnet *ifp; node_p node; RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; VBOXCURVNET_SET_FROM_UCRED(); NOREF(pvContext); ifp = ifunit(pThis->szName); if (ifp == NULL) return VERR_INTNET_FLT_IF_NOT_FOUND; /* Create a new netgraph node for this instance */ if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0) return VERR_INTERNAL_ERROR; RTSpinlockAcquireNoInts(pThis->hSpinlock, &Tmp); ASMAtomicUoWritePtr(&pThis->u.s.ifp, ifp); pThis->u.s.node = node; bcopy(IF_LLADDR(ifp), &pThis->u.s.MacAddr, ETHER_ADDR_LEN); ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false); /* Initialize deferred input queue */ bzero(&pThis->u.s.inq, sizeof(struct ifqueue)); mtx_init(&pThis->u.s.inq.ifq_mtx, "vboxnetflt inq", NULL, MTX_SPIN); TASK_INIT(&pThis->u.s.tskin, 0, vboxNetFltFreeBSDinput, pThis); /* Initialize deferred output queue */ bzero(&pThis->u.s.outq, sizeof(struct ifqueue)); mtx_init(&pThis->u.s.outq.ifq_mtx, "vboxnetflt outq", NULL, MTX_SPIN); TASK_INIT(&pThis->u.s.tskout, 0, vboxNetFltFreeBSDoutput, pThis); RTSpinlockReleaseNoInts(pThis->hSpinlock, &Tmp); NG_NODE_SET_PRIVATE(node, pThis); /* Attempt to name it vboxnetflt_<ifname> */ snprintf(nam, NG_NODESIZ, "vboxnetflt_%s", pThis->szName); ng_name_node(node, nam); /* Report MAC address, promiscuous mode and GSO capabilities. */ /** @todo keep these reports up to date, either by polling for changes or * intercept some control flow if possible. */ if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) { Assert(pThis->pSwitchPort); pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltFreeBsdIsPromiscuous(pThis)); pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); vboxNetFltRelease(pThis, true /*fBusy*/); } VBOXCURVNET_RESTORE(); return VINF_SUCCESS; }
static int ng_attach_cntl(struct socket *so) { struct ngsock *priv; struct ngpcb *pcbp; int error; /* Allocate node private info */ priv = kmalloc(sizeof(*priv), M_NETGRAPH_SOCK, M_WAITOK | M_ZERO); /* Setup protocol control block */ if ((error = ng_attach_common(so, NG_CONTROL)) != 0) { kfree(priv, M_NETGRAPH_SOCK); return (error); } pcbp = sotongpcb(so); /* Link the pcb the private data. */ priv->ctlsock = pcbp; pcbp->sockdata = priv; priv->refs++; /* Initialize mutex. */ mtx_init(&priv->mtx, "ng_socket"); /* Make the generic node components */ if ((error = ng_make_node_common(&typestruct, &priv->node)) != 0) { kfree(priv, M_NETGRAPH_SOCK); ng_detach_common(pcbp, NG_CONTROL); return (error); } /* Link the node and the private data. */ NG_NODE_SET_PRIVATE(priv->node, priv); NG_NODE_REF(priv->node); priv->refs++; return (0); }
/* * Do local shutdown processing.. * We are a persistant device, we refuse to go away, and * only remove our links and reset ourself. */ Static int ng_udbp_rmnode(node_p node) { const udbp_p sc = NG_NODE_PRIVATE(node); int err; if (sc->flags & DISCONNECTED) { /* * WE are really going away.. hardware must have gone. * Assume that the hardware drive part will clear up the * sc, in fact it may already have done so.. * In which case we may have just segfaulted..XXX */ return (0); } /* stolen from attach routine */ /* Drain the queues */ IF_DRAIN(&sc->xmitq_hipri); IF_DRAIN(&sc->xmitq); sc->packets_in = 0; /* reset stats */ sc->packets_out = 0; NG_NODE_UNREF(node); /* forget it ever existed */ if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) { char nodename[128]; sprintf(nodename, "%s", USBDEVNAME(sc->sc_dev)); if ((err = ng_name_node(sc->node, nodename))) { NG_NODE_UNREF(sc->node); /* out damned spot! */ sc->flags &= ~NETGRAPH_INITIALISED; sc->node = NULL; } else { NG_NODE_SET_PRIVATE(sc->node, sc); } } return (err); }
/* * Handle the first completed incoming connection, assumed to be already * on the socket's so_comp queue. */ static void ng_ksocket_finish_accept(priv_p priv) { struct socket *const head = priv->so; struct socket *so; struct sockaddr *sa = NULL; struct ng_mesg *resp; struct ng_ksocket_accept *resp_data; node_p node; priv_p priv2; int len; int error; ACCEPT_LOCK(); so = TAILQ_FIRST(&head->so_comp); if (so == NULL) { /* Should never happen */ ACCEPT_UNLOCK(); return; } TAILQ_REMOVE(&head->so_comp, so, so_list); head->so_qlen--; so->so_qstate &= ~SQ_COMP; so->so_head = NULL; SOCK_LOCK(so); soref(so); sosetstate(so, SS_NBIO); SOCK_UNLOCK(so); ACCEPT_UNLOCK(); /* XXX KNOTE(&head->so_rcv.sb_sel.si_note, 0); */ soaccept(so, &sa); len = OFFSETOF(struct ng_ksocket_accept, addr); if (sa != NULL) len += sa->sa_len; NG_MKMESSAGE(resp, NGM_KSOCKET_COOKIE, NGM_KSOCKET_ACCEPT, len, M_WAITOK | M_NULLOK); if (resp == NULL) { soclose(so); goto out; } resp->header.flags |= NGF_RESP; resp->header.token = priv->response_token; /* Clone a ksocket node to wrap the new socket */ error = ng_make_node_common(&ng_ksocket_typestruct, &node); if (error) { kfree(resp, M_NETGRAPH); soclose(so); goto out; } if (ng_ksocket_constructor(node) != 0) { NG_NODE_UNREF(node); kfree(resp, M_NETGRAPH); soclose(so); goto out; } priv2 = NG_NODE_PRIVATE(node); priv2->so = so; priv2->flags |= KSF_CLONED | KSF_EMBRYONIC; /* * Insert the cloned node into a list of embryonic children * on the parent node. When a hook is created on the cloned * node it will be removed from this list. When the parent * is destroyed it will destroy any embryonic children it has. */ LIST_INSERT_HEAD(&priv->embryos, priv2, siblings); so->so_upcallarg = (caddr_t)node; so->so_upcall = ng_ksocket_incoming; SOCKBUF_LOCK(&so->so_rcv); so->so_rcv.sb_flags |= SB_UPCALL; SOCKBUF_UNLOCK(&so->so_rcv); SOCKBUF_LOCK(&so->so_snd); so->so_snd.sb_flags |= SB_UPCALL; SOCKBUF_UNLOCK(&so->so_snd); /* Fill in the response data and send it or return it to the caller */ resp_data = (struct ng_ksocket_accept *)resp->data; resp_data->nodeid = NG_NODE_ID(node); if (sa != NULL) bcopy(sa, &resp_data->addr, sa->sa_len); NG_SEND_MSG_ID(error, node, resp, priv->response_addr, 0); out: if (sa != NULL) kfree(sa, M_SONAME); }
static int bt3c_pccard_attach(device_t dev) { bt3c_softc_p sc = (bt3c_softc_p) device_get_softc(dev); /* Allocate I/O ports */ sc->iobase_rid = 0; sc->iobase = bus_alloc_resource_anywhere(dev, SYS_RES_IOPORT, &sc->iobase_rid, 8, RF_ACTIVE); if (sc->iobase == NULL) { device_printf(dev, "Could not allocate I/O ports\n"); goto bad; } sc->iot = rman_get_bustag(sc->iobase); sc->ioh = rman_get_bushandle(sc->iobase); /* Allocate IRQ */ sc->irq_rid = 0; sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irq_rid, RF_ACTIVE); if (sc->irq == NULL) { device_printf(dev, "Could not allocate IRQ\n"); goto bad; } sc->irq_cookie = NULL; if (bus_setup_intr(dev, sc->irq, INTR_TYPE_TTY, NULL, bt3c_intr, sc, &sc->irq_cookie) != 0) { device_printf(dev, "Could not setup ISR\n"); goto bad; } /* Attach handler to TTY SWI thread */ sc->ith = NULL; if (swi_add(&tty_intr_event, device_get_nameunit(dev), bt3c_swi_intr, sc, SWI_TTY, 0, &sc->ith) < 0) { device_printf(dev, "Could not setup SWI ISR\n"); goto bad; } /* Create Netgraph node */ if (ng_make_node_common(&typestruct, &sc->node) != 0) { device_printf(dev, "Could not create Netgraph node\n"); sc->node = NULL; goto bad; } /* Name Netgraph node */ if (ng_name_node(sc->node, device_get_nameunit(dev)) != 0) { device_printf(dev, "Could not name Netgraph node\n"); NG_NODE_UNREF(sc->node); sc->node = NULL; goto bad; } sc->dev = dev; sc->debug = NG_BT3C_WARN_LEVEL; sc->inq.ifq_maxlen = sc->outq.ifq_maxlen = BT3C_DEFAULTQLEN; mtx_init(&sc->inq.ifq_mtx, "BT3C inq", NULL, MTX_DEF); mtx_init(&sc->outq.ifq_mtx, "BT3C outq", NULL, MTX_DEF); sc->state = NG_BT3C_W4_PKT_IND; sc->want = 1; NG_NODE_SET_PRIVATE(sc->node, sc); return (0); bad: if (sc->ith != NULL) { swi_remove(sc->ith); sc->ith = NULL; } if (sc->irq != NULL) { if (sc->irq_cookie != NULL) bus_teardown_intr(dev, sc->irq, sc->irq_cookie); bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, sc->irq); sc->irq = NULL; sc->irq_rid = 0; } if (sc->iobase != NULL) { bus_release_resource(dev, SYS_RES_IOPORT, sc->iobase_rid, sc->iobase); sc->iobase = NULL; sc->iobase_rid = 0; } return (ENXIO); } /* bt3c_pccacd_attach */
static int ubt_attach(device_t dev) { struct usb_attach_arg *uaa = device_get_ivars(dev); struct ubt_softc *sc = device_get_softc(dev); struct usb_endpoint_descriptor *ed; struct usb_interface_descriptor *id; struct usb_interface *iface; uint16_t wMaxPacketSize; uint8_t alt_index, i, j; uint8_t iface_index[2] = { 0, 1 }; device_set_usb_desc(dev); sc->sc_dev = dev; sc->sc_debug = NG_UBT_WARN_LEVEL; /* * Create Netgraph node */ if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) { UBT_ALERT(sc, "could not create Netgraph node\n"); return (ENXIO); } /* Name Netgraph node */ if (ng_name_node(sc->sc_node, device_get_nameunit(dev)) != 0) { UBT_ALERT(sc, "could not name Netgraph node\n"); NG_NODE_UNREF(sc->sc_node); return (ENXIO); } NG_NODE_SET_PRIVATE(sc->sc_node, sc); NG_NODE_FORCE_WRITER(sc->sc_node); /* * Initialize device softc structure */ /* initialize locks */ mtx_init(&sc->sc_ng_mtx, "ubt ng", NULL, MTX_DEF); mtx_init(&sc->sc_if_mtx, "ubt if", NULL, MTX_DEF | MTX_RECURSE); /* initialize packet queues */ NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN); NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN); NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN); /* initialize glue task */ TASK_INIT(&sc->sc_task, 0, ubt_task, sc); /* * Configure Bluetooth USB device. Discover all required USB * interfaces and endpoints. * * USB device must present two interfaces: * 1) Interface 0 that has 3 endpoints * 1) Interrupt endpoint to receive HCI events * 2) Bulk IN endpoint to receive ACL data * 3) Bulk OUT endpoint to send ACL data * * 2) Interface 1 then has 2 endpoints * 1) Isochronous IN endpoint to receive SCO data * 2) Isochronous OUT endpoint to send SCO data * * Interface 1 (with isochronous endpoints) has several alternate * configurations with different packet size. */ /* * For interface #1 search alternate settings, and find * the descriptor with the largest wMaxPacketSize */ wMaxPacketSize = 0; alt_index = 0; i = 0; j = 0; ed = NULL; /* * Search through all the descriptors looking for the largest * packet size: */ while ((ed = (struct usb_endpoint_descriptor *)usb_desc_foreach( usbd_get_config_descriptor(uaa->device), (struct usb_descriptor *)ed))) { if ((ed->bDescriptorType == UDESC_INTERFACE) && (ed->bLength >= sizeof(*id))) { id = (struct usb_interface_descriptor *)ed; i = id->bInterfaceNumber; j = id->bAlternateSetting; } if ((ed->bDescriptorType == UDESC_ENDPOINT) && (ed->bLength >= sizeof(*ed)) && (i == 1)) { uint16_t temp; temp = UGETW(ed->wMaxPacketSize); if (temp > wMaxPacketSize) { wMaxPacketSize = temp; alt_index = j; } } } /* Set alt configuration on interface #1 only if we found it */ if (wMaxPacketSize > 0 && usbd_set_alt_interface_index(uaa->device, 1, alt_index)) { UBT_ALERT(sc, "could not set alternate setting %d " \ "for interface 1!\n", alt_index); goto detach; } /* Setup transfers for both interfaces */ if (usbd_transfer_setup(uaa->device, iface_index, sc->sc_xfer, ubt_config, UBT_N_TRANSFER, sc, &sc->sc_if_mtx)) { UBT_ALERT(sc, "could not allocate transfers\n"); goto detach; } /* Claim all interfaces belonging to the Bluetooth part */ for (i = 1;; i++) { iface = usbd_get_iface(uaa->device, i); if (iface == NULL) break; id = usbd_get_interface_descriptor(iface); if ((id != NULL) && (id->bInterfaceClass == UICLASS_WIRELESS) && (id->bInterfaceSubClass == UISUBCLASS_RF) && (id->bInterfaceProtocol == UIPROTO_BLUETOOTH)) { usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); } } return (0); /* success */ detach: ubt_detach(dev); return (ENXIO); } /* ubt_attach */