Exemple #1
0
static int
ipheth_attach(device_t dev)
{
	struct ipheth_softc *sc = device_get_softc(dev);
	struct usb_ether *ue = &sc->sc_ue;
	struct usb_attach_arg *uaa = device_get_ivars(dev);
	int error;

	sc->sc_iface_no = uaa->info.bIfaceIndex;

	device_set_usb_desc(dev);

	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);

	error = usbd_set_alt_interface_index(uaa->device,
	    uaa->info.bIfaceIndex, IPHETH_ALT_INTFNUM);
	if (error) {
		device_printf(dev, "Cannot set alternate setting\n");
		goto detach;
	}
	error = usbd_transfer_setup(uaa->device, &sc->sc_iface_no,
	    sc->sc_xfer, ipheth_config, IPHETH_N_TRANSFER, sc, &sc->sc_mtx);
	if (error) {
		device_printf(dev, "Cannot setup USB transfers\n");
		goto detach;
	}
	ue->ue_sc = sc;
	ue->ue_dev = dev;
	ue->ue_udev = uaa->device;
	ue->ue_mtx = &sc->sc_mtx;
	ue->ue_methods = &ipheth_ue_methods;

	error = ipheth_get_mac_addr(sc);
	if (error) {
		device_printf(dev, "Cannot get MAC address\n");
		goto detach;
	}

	error = uether_ifattach(ue);
	if (error) {
		device_printf(dev, "could not attach interface\n");
		goto detach;
	}
	return (0);			/* success */

detach:
	ipheth_detach(dev);
	return (ENXIO);			/* failure */
}
static int
rtwn_usb_attach(device_t self)
{
	struct usb_attach_arg *uaa = device_get_ivars(self);
	struct rtwn_usb_softc *uc = device_get_softc(self);
	struct rtwn_softc *sc = &uc->uc_sc;
	struct ieee80211com *ic = &sc->sc_ic;
	int error;

	device_set_usb_desc(self);
	uc->uc_udev = uaa->device;
	sc->sc_dev = self;
	ic->ic_name = device_get_nameunit(self);

	/* Need to be initialized early. */
	rtwn_sysctlattach(sc);
	rtwn_usb_sysctlattach(sc);
	mtx_init(&sc->sc_mtx, ic->ic_name, MTX_NETWORK_LOCK, MTX_DEF);

	rtwn_usb_attach_methods(sc);
	rtwn_usb_attach_private(uc, USB_GET_DRIVER_INFO(uaa));

	error = rtwn_usb_setup_endpoints(uc);
	if (error != 0)
		goto detach;

	/* Allocate Tx/Rx buffers. */
	error = rtwn_usb_alloc_rx_list(sc);
	if (error != 0)
		goto detach;

	error = rtwn_usb_alloc_tx_list(sc);
	if (error != 0)
		goto detach;

	/* Generic attach. */
	error = rtwn_attach(sc);
	if (error != 0)
		goto detach;

	return (0);

detach:
	rtwn_usb_detach(self);		/* failure */
	return (ENXIO);
}
Exemple #3
0
static int
ndisusb_attach(device_t self)
{
	const struct drvdb_ent	*db;
	struct ndisusb_softc *dummy = device_get_softc(self);
	struct usb_attach_arg *uaa = device_get_ivars(self);
	struct ndis_softc	*sc;
	struct ndis_usb_type	*t;
	driver_object		*drv;
	int			devidx = 0;

	device_set_usb_desc(self);
	db = uaa->driver_ivar;
	sc = (struct ndis_softc *)dummy;
	sc->ndis_dev = self;
	mtx_init(&sc->ndisusb_mtx, "NDIS USB", MTX_NETWORK_LOCK, MTX_DEF);
	sc->ndis_dobj = db->windrv_object;
	sc->ndis_regvals = db->windrv_regvals;
	sc->ndis_iftype = PNPBus;
	sc->ndisusb_dev = uaa->device;

	/* Create PDO for this device instance */

	drv = windrv_lookup(0, "USB Bus");
	windrv_create_pdo(drv, self);

	/* Figure out exactly which device we matched. */

	t = db->windrv_devlist;

	while (t->ndis_name != NULL) {
		if ((uaa->info.idVendor == t->ndis_vid) &&
		    (uaa->info.idProduct == t->ndis_did)) {
			sc->ndis_devidx = devidx;
			break;
		}
		t++;
		devidx++;
	}

	if (ndis_attach(self) != 0)
		return (ENXIO);

	return (0);
}
Exemple #4
0
static int
g_modem_attach(device_t dev)
{
	struct g_modem_softc *sc = device_get_softc(dev);
	struct usb_attach_arg *uaa = device_get_ivars(dev);
	int error;
	uint8_t iface_index[2];

	DPRINTFN(11, "\n");

	device_set_usb_desc(dev);

	lockinit(&sc->sc_lock, "g_modem", 0, 0);

	usb_callout_init_mtx(&sc->sc_callout, &sc->sc_lock, 0);
	usb_callout_init_mtx(&sc->sc_watchdog, &sc->sc_lock, 0);

	sc->sc_mode = G_MODEM_MODE_SILENT;

	iface_index[0] = uaa->info.bIfaceIndex;
	iface_index[1] = uaa->info.bIfaceIndex + 1;

	error = usbd_transfer_setup(uaa->device,
	    iface_index, sc->sc_xfer, g_modem_config,
	    G_MODEM_N_TRANSFER, sc, &sc->sc_lock);

	if (error) {
		DPRINTF("error=%s\n", usbd_errstr(error));
		goto detach;
	}
	usbd_set_parent_iface(uaa->device, iface_index[1], iface_index[0]);

	lockmgr(&sc->sc_lock, LK_EXCLUSIVE);
	g_modem_timeout_reset(sc);
	g_modem_watchdog_reset(sc);
	lockmgr(&sc->sc_lock, LK_RELEASE);

	return (0);			/* success */

detach:
	g_modem_detach(dev);

	return (ENXIO);			/* error */
}
Exemple #5
0
static int
ndis_attach_usb(device_t dev)
{
	const struct drvdb_ent *db;
	struct ndisusb_softc *dummy;
	struct usb_attach_arg *uaa;
	struct ndis_softc *sc;
	struct ndis_device_type *t;
	struct driver_object *drv;
	int devidx = 0;

	device_set_usb_desc(dev);
	dummy = device_get_softc(dev);
	uaa = device_get_ivars(dev);
	db = uaa->driver_ivar;
	sc = (struct ndis_softc *)dummy;
	sc->ndis_dev = dev;
	mtx_init(&sc->ndisusb_mtx, "NDIS USB", MTX_NETWORK_LOCK, MTX_DEF);
	sc->ndis_dobj = db->windrv_object;
	sc->ndis_regvals = db->windrv_regvals;
	sc->ndis_bus_type = NDIS_PNPBUS;
	sc->ndisusb_dev = uaa->device;

	drv = windrv_lookup(0, "USB Bus");
	windrv_create_pdo(drv, dev);

	/* Figure out exactly which device we matched. */
	for (t = db->windrv_devlist; t->name != NULL; t++, devidx++) {
		if ((uaa->info.idVendor == t->vendor) &&
		    (uaa->info.idProduct == t->device)) {
			sc->ndis_devidx = devidx;
			break;
		}
	}

	if (ndis_attach(dev) != 0)
		return (ENXIO);

	return (0);
}
Exemple #6
0
static int
usie_attach(device_t self)
{
	struct usie_softc *sc = device_get_softc(self);
	struct usb_attach_arg *uaa = device_get_ivars(self);
	struct ifnet *ifp;
	struct usb_interface *iface;
	struct usb_interface_descriptor *id;
	struct usb_device_request req;
	int err;
	uint16_t fwattr;
	uint8_t iface_index;
	uint8_t ifidx;
	uint8_t start;

	device_set_usb_desc(self);
	sc->sc_udev = uaa->device;
	sc->sc_dev = self;

	mtx_init(&sc->sc_mtx, "usie", MTX_NETWORK_LOCK, MTX_DEF);

	TASK_INIT(&sc->sc_if_status_task, 0, usie_if_status_cb, sc);
	TASK_INIT(&sc->sc_if_sync_task, 0, usie_if_sync_cb, sc);

	usb_callout_init_mtx(&sc->sc_if_sync_ch, &sc->sc_mtx, 0);

	mtx_lock(&sc->sc_mtx);

	/* set power mode to D0 */
	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
	req.bRequest = USIE_POWER;
	USETW(req.wValue, 0);
	USETW(req.wIndex, 0);
	USETW(req.wLength, 0);
	if (usie_do_request(sc, &req, NULL)) {
		mtx_unlock(&sc->sc_mtx);
		goto detach;
	}
	/* read fw attr */
	fwattr = 0;
	req.bmRequestType = UT_READ_VENDOR_DEVICE;
	req.bRequest = USIE_FW_ATTR;
	USETW(req.wValue, 0);
	USETW(req.wIndex, 0);
	USETW(req.wLength, sizeof(fwattr));
	if (usie_do_request(sc, &req, &fwattr)) {
		mtx_unlock(&sc->sc_mtx);
		goto detach;
	}
	mtx_unlock(&sc->sc_mtx);

	/* check DHCP supports */
	DPRINTF("fwattr=%x\n", fwattr);
	if (!(fwattr & USIE_FW_DHCP)) {
		device_printf(self, "DHCP is not supported. A firmware upgrade might be needed.\n");
	}

	/* find available interfaces */
	sc->sc_nucom = 0;
	for (ifidx = 0; ifidx < USIE_IFACE_MAX; ifidx++) {
		iface = usbd_get_iface(uaa->device, ifidx);
		if (iface == NULL)
			break;

		id = usbd_get_interface_descriptor(iface);
		if ((id == NULL) || (id->bInterfaceClass != UICLASS_VENDOR))
			continue;

		/* setup Direct IP transfer */
		if (id->bInterfaceNumber >= 7 && id->bNumEndpoints == 3) {
			sc->sc_if_ifnum = id->bInterfaceNumber;
			iface_index = ifidx;

			DPRINTF("ifnum=%d, ifidx=%d\n",
			    sc->sc_if_ifnum, ifidx);

			err = usbd_transfer_setup(uaa->device,
			    &iface_index, sc->sc_if_xfer, usie_if_config,
			    USIE_IF_N_XFER, sc, &sc->sc_mtx);

			if (err == 0)
				continue;

			device_printf(self,
			    "could not allocate USB transfers on "
			    "iface_index=%d, err=%s\n",
			    iface_index, usbd_errstr(err));
			goto detach;
		}

		/* setup ucom */
		if (sc->sc_nucom >= USIE_UCOM_MAX)
			continue;

		usbd_set_parent_iface(uaa->device, ifidx,
		    uaa->info.bIfaceIndex);

		DPRINTF("NumEndpoints=%d bInterfaceNumber=%d\n",
		    id->bNumEndpoints, id->bInterfaceNumber);

		if (id->bNumEndpoints == 2) {
			sc->sc_uc_xfer[sc->sc_nucom][0] = NULL;
			start = 1;
		} else
			start = 0;

		err = usbd_transfer_setup(uaa->device, &ifidx,
		    sc->sc_uc_xfer[sc->sc_nucom] + start,
		    usie_uc_config + start, USIE_UC_N_XFER - start,
		    &sc->sc_ucom[sc->sc_nucom], &sc->sc_mtx);

		if (err != 0) {
			DPRINTF("usbd_transfer_setup error=%s\n", usbd_errstr(err));
			continue;
		}

		mtx_lock(&sc->sc_mtx);
		for (; start < USIE_UC_N_XFER; start++)
			usbd_xfer_set_stall(sc->sc_uc_xfer[sc->sc_nucom][start]);
		mtx_unlock(&sc->sc_mtx);

		sc->sc_uc_ifnum[sc->sc_nucom] = id->bInterfaceNumber;

		sc->sc_nucom++;		/* found a port */
	}

	if (sc->sc_nucom == 0) {
		device_printf(self, "no comports found\n");
		goto detach;
	}

	err = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom,
	    sc->sc_nucom, sc, &usie_uc_callback, &sc->sc_mtx);

	if (err != 0) {
		DPRINTF("ucom_attach failed\n");
		goto detach;
	}
	DPRINTF("Found %d interfaces.\n", sc->sc_nucom);

	/* setup ifnet (Direct IP) */
	sc->sc_ifp = ifp = if_alloc(IFT_OTHER);

	if (ifp == NULL) {
		device_printf(self, "Could not allocate a network interface\n");
		goto detach;
	}
	if_initname(ifp, "usie", device_get_unit(self));

	ifp->if_softc = sc;
	ifp->if_mtu = USIE_MTU_MAX;
	ifp->if_flags |= IFF_NOARP;
	ifp->if_init = usie_if_init;
	ifp->if_ioctl = usie_if_ioctl;
	ifp->if_start = usie_if_start;
	ifp->if_output = usie_if_output;
	IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
	ifp->if_snd.ifq_drv_maxlen = ifqmaxlen;
	IFQ_SET_READY(&ifp->if_snd);

	if_attach(ifp);
	bpfattach(ifp, DLT_RAW, 0);

	if (fwattr & USIE_PM_AUTO) {
		usbd_set_power_mode(uaa->device, USB_POWER_MODE_SAVE);
		DPRINTF("enabling automatic suspend and resume\n");
	} else {
		usbd_set_power_mode(uaa->device, USB_POWER_MODE_ON);
		DPRINTF("USB power is always ON\n");
	}

	DPRINTF("device attached\n");
	return (0);

detach:
	usie_detach(self);
	return (ENOMEM);
}
Exemple #7
0
static int
cdce_attach(device_t dev)
{
	struct cdce_softc *sc = device_get_softc(dev);
	struct usb_ether *ue = &sc->sc_ue;
	struct usb_attach_arg *uaa = device_get_ivars(dev);
	struct usb_interface *iface;
	const struct usb_cdc_union_descriptor *ud;
	const struct usb_interface_descriptor *id;
	const struct usb_cdc_ethernet_descriptor *ued;
	const struct usb_config *pcfg;
	int error;
	uint8_t i;
	uint8_t data_iface_no;
	char eaddr_str[5 * ETHER_ADDR_LEN];	/* approx */

	sc->sc_flags = USB_GET_DRIVER_INFO(uaa);
	sc->sc_ue.ue_udev = uaa->device;

	device_set_usb_desc(dev);

	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF);

	ud = usbd_find_descriptor
	    (uaa->device, NULL, uaa->info.bIfaceIndex,
	    UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_UNION, 0 - 1);

	if ((ud == NULL) || (ud->bLength < sizeof(*ud)) ||
	    (sc->sc_flags & CDCE_FLAG_NO_UNION)) {
		DPRINTFN(1, "No union descriptor!\n");
		sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex;
		sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
		goto alloc_transfers;
	}
	data_iface_no = ud->bSlaveInterface[0];

	for (i = 0;; i++) {

		iface = usbd_get_iface(uaa->device, i);

		if (iface) {

			id = usbd_get_interface_descriptor(iface);

			if (id && (id->bInterfaceNumber == data_iface_no)) {
				sc->sc_ifaces_index[0] = i;
				sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex;
				usbd_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex);
				break;
			}
		} else {
			device_printf(dev, "no data interface found\n");
			goto detach;
		}
	}

	/*
	 * <quote>
	 *
	 *  The Data Class interface of a networking device shall have
	 *  a minimum of two interface settings. The first setting
	 *  (the default interface setting) includes no endpoints and
	 *  therefore no networking traffic is exchanged whenever the
	 *  default interface setting is selected. One or more
	 *  additional interface settings are used for normal
	 *  operation, and therefore each includes a pair of endpoints
	 *  (one IN, and one OUT) to exchange network traffic. Select
	 *  an alternate interface setting to initialize the network
	 *  aspects of the device and to enable the exchange of
	 *  network traffic.
	 *
	 * </quote>
	 *
	 * Some devices, most notably cable modems, include interface
	 * settings that have no IN or OUT endpoint, therefore loop
	 * through the list of all available interface settings
	 * looking for one with both IN and OUT endpoints.
	 */

alloc_transfers:

	pcfg = cdce_config;	/* Default Configuration */

	for (i = 0; i != 32; i++) {

		error = usbd_set_alt_interface_index(uaa->device,
		    sc->sc_ifaces_index[0], i);
		if (error)
			break;
#if CDCE_HAVE_NCM
		if ((i == 0) && (cdce_ncm_init(sc) == 0))
			pcfg = cdce_ncm_config;
#endif
		error = usbd_transfer_setup(uaa->device,
		    sc->sc_ifaces_index, sc->sc_xfer,
		    pcfg, CDCE_N_TRANSFER, sc, &sc->sc_mtx);

		if (error == 0)
			break;
	}

	if (error || (i == 32)) {
		device_printf(dev, "No valid alternate "
		    "setting found\n");
		goto detach;
	}

	ued = usbd_find_descriptor
	    (uaa->device, NULL, uaa->info.bIfaceIndex,
	    UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_ENF, 0 - 1);

	if ((ued == NULL) || (ued->bLength < sizeof(*ued))) {
		error = USB_ERR_INVAL;
	} else {
		error = usbd_req_get_string_any(uaa->device, NULL, 
		    eaddr_str, sizeof(eaddr_str), ued->iMacAddress);
	}

	if (error) {

		/* fake MAC address */

		device_printf(dev, "faking MAC address\n");
		sc->sc_ue.ue_eaddr[0] = 0x2a;
		memcpy(&sc->sc_ue.ue_eaddr[1], &ticks, sizeof(uint32_t));
		sc->sc_ue.ue_eaddr[5] = device_get_unit(dev);

	} else {

		memset(sc->sc_ue.ue_eaddr, 0, sizeof(sc->sc_ue.ue_eaddr));

		for (i = 0; i != (ETHER_ADDR_LEN * 2); i++) {

			char c = eaddr_str[i];

			if ('0' <= c && c <= '9')
				c -= '0';
			else if (c != 0)
				c -= 'A' - 10;
			else
				break;

			c &= 0xf;

			if ((i & 1) == 0)
				c <<= 4;
			sc->sc_ue.ue_eaddr[i / 2] |= c;
		}

		if (uaa->usb_mode == USB_MODE_DEVICE) {
			/*
			 * Do not use the same MAC address like the peer !
			 */
			sc->sc_ue.ue_eaddr[5] ^= 0xFF;
		}
	}

	ue->ue_sc = sc;
	ue->ue_dev = dev;
	ue->ue_udev = uaa->device;
	ue->ue_mtx = &sc->sc_mtx;
	ue->ue_methods = &cdce_ue_methods;

	error = uether_ifattach(ue);
	if (error) {
		device_printf(dev, "could not attach interface\n");
		goto detach;
	}
	return (0);			/* success */

detach:
	cdce_detach(dev);
	return (ENXIO);			/* failure */
}
Exemple #8
0
static int
g_audio_attach(device_t dev)
{
	struct g_audio_softc *sc = device_get_softc(dev);
	struct usb_attach_arg *uaa = device_get_ivars(dev);
	int error;
	int i;
	uint8_t iface_index[3];

	DPRINTFN(11, "\n");

	device_set_usb_desc(dev);

	mtx_init(&sc->sc_mtx, "g_audio", NULL, MTX_DEF);

	usb_callout_init_mtx(&sc->sc_callout, &sc->sc_mtx, 0);
	usb_callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0);

	sc->sc_mode = G_AUDIO_MODE_SILENT;

	sc->sc_noise_rem = 1;

	for (i = 0; i != G_AUDIO_FRAMES; i++) {
		sc->sc_data_len[0][i] = G_AUDIO_BUFSIZE / G_AUDIO_FRAMES;
		sc->sc_data_len[1][i] = G_AUDIO_BUFSIZE / G_AUDIO_FRAMES;
	}

	iface_index[0] = uaa->info.bIfaceIndex;
	iface_index[1] = uaa->info.bIfaceIndex + 1;
	iface_index[2] = uaa->info.bIfaceIndex + 2;

	error = usbd_set_alt_interface_index(uaa->device, iface_index[1], 1);
	if (error) {
		DPRINTF("alt iface setting error=%s\n", usbd_errstr(error));
		goto detach;
	}
	error = usbd_set_alt_interface_index(uaa->device, iface_index[2], 1);
	if (error) {
		DPRINTF("alt iface setting error=%s\n", usbd_errstr(error));
		goto detach;
	}
	error = usbd_transfer_setup(uaa->device,
	    iface_index, sc->sc_xfer, g_audio_config,
	    G_AUDIO_N_TRANSFER, sc, &sc->sc_mtx);

	if (error) {
		DPRINTF("error=%s\n", usbd_errstr(error));
		goto detach;
	}
	usbd_set_parent_iface(uaa->device, iface_index[1], iface_index[0]);
	usbd_set_parent_iface(uaa->device, iface_index[2], iface_index[0]);

	mtx_lock(&sc->sc_mtx);

	usbd_transfer_start(sc->sc_xfer[G_AUDIO_ISOC0_RD]);
	usbd_transfer_start(sc->sc_xfer[G_AUDIO_ISOC1_RD]);

	usbd_transfer_start(sc->sc_xfer[G_AUDIO_ISOC0_WR]);
	usbd_transfer_start(sc->sc_xfer[G_AUDIO_ISOC1_WR]);

	g_audio_timeout_reset(sc);

	g_audio_watchdog_reset(sc);

	mtx_unlock(&sc->sc_mtx);

	return (0);			/* success */

detach:
	g_audio_detach(dev);

	return (ENXIO);			/* error */
}
Exemple #9
0
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 */
Exemple #10
0
static int
uhid_attach(device_t dev)
{
	struct usb_attach_arg *uaa = device_get_ivars(dev);
	struct uhid_softc *sc = device_get_softc(dev);
	int unit = device_get_unit(dev);
	int error = 0;

	DPRINTFN(10, "sc=%p\n", sc);

	device_set_usb_desc(dev);

	mtx_init(&sc->sc_mtx, "uhid lock", NULL, MTX_DEF | MTX_RECURSE);

	sc->sc_udev = uaa->device;

	sc->sc_iface_no = uaa->info.bIfaceNum;
	sc->sc_iface_index = uaa->info.bIfaceIndex;

	error = usbd_transfer_setup(uaa->device,
	    &uaa->info.bIfaceIndex, sc->sc_xfer, uhid_config,
	    UHID_N_TRANSFER, sc, &sc->sc_mtx);

	if (error) {
		DPRINTF("error=%s\n", usbd_errstr(error));
		goto detach;
	}
	if (uaa->info.idVendor == USB_VENDOR_WACOM) {

		/* the report descriptor for the Wacom Graphire is broken */

		if (uaa->info.idProduct == USB_PRODUCT_WACOM_GRAPHIRE) {

			sc->sc_repdesc_size = sizeof(uhid_graphire_report_descr);
			sc->sc_repdesc_ptr = (void *)&uhid_graphire_report_descr;
			sc->sc_flags |= UHID_FLAG_STATIC_DESC;

		} else if (uaa->info.idProduct == USB_PRODUCT_WACOM_GRAPHIRE3_4X5) {

			static uint8_t reportbuf[] = {2, 2, 2};

			/*
			 * The Graphire3 needs 0x0202 to be written to
			 * feature report ID 2 before it'll start
			 * returning digitizer data.
			 */
			error = usbd_req_set_report(uaa->device, NULL,
			    reportbuf, sizeof(reportbuf),
			    uaa->info.bIfaceIndex, UHID_FEATURE_REPORT, 2);

			if (error) {
				DPRINTF("set report failed, error=%s (ignored)\n",
				    usbd_errstr(error));
			}
			sc->sc_repdesc_size = sizeof(uhid_graphire3_4x5_report_descr);
			sc->sc_repdesc_ptr = (void *)&uhid_graphire3_4x5_report_descr;
			sc->sc_flags |= UHID_FLAG_STATIC_DESC;
		}
	} else if ((uaa->info.bInterfaceClass == UICLASS_VENDOR) &&
		    (uaa->info.bInterfaceSubClass == UISUBCLASS_XBOX360_CONTROLLER) &&
	    (uaa->info.bInterfaceProtocol == UIPROTO_XBOX360_GAMEPAD)) {

		/* the Xbox 360 gamepad has no report descriptor */
		sc->sc_repdesc_size = sizeof(uhid_xb360gp_report_descr);
		sc->sc_repdesc_ptr = (void *)&uhid_xb360gp_report_descr;
		sc->sc_flags |= UHID_FLAG_STATIC_DESC;
	}
	if (sc->sc_repdesc_ptr == NULL) {

		error = usbd_req_get_hid_desc(uaa->device, NULL,
		    &sc->sc_repdesc_ptr, &sc->sc_repdesc_size,
		    M_USBDEV, uaa->info.bIfaceIndex);

		if (error) {
			device_printf(dev, "no report descriptor\n");
			goto detach;
		}
	}
	error = usbd_req_set_idle(uaa->device, NULL,
	    uaa->info.bIfaceIndex, 0, 0);

	if (error) {
		DPRINTF("set idle failed, error=%s (ignored)\n",
		    usbd_errstr(error));
	}
	sc->sc_isize = hid_report_size
	    (sc->sc_repdesc_ptr, sc->sc_repdesc_size, hid_input, &sc->sc_iid);

	sc->sc_osize = hid_report_size
	    (sc->sc_repdesc_ptr, sc->sc_repdesc_size, hid_output, &sc->sc_oid);

	sc->sc_fsize = hid_report_size
	    (sc->sc_repdesc_ptr, sc->sc_repdesc_size, hid_feature, &sc->sc_fid);

	if (sc->sc_isize > UHID_BSIZE) {
		DPRINTF("input size is too large, "
		    "%d bytes (truncating)\n",
		    sc->sc_isize);
		sc->sc_isize = UHID_BSIZE;
	}
	if (sc->sc_osize > UHID_BSIZE) {
		DPRINTF("output size is too large, "
		    "%d bytes (truncating)\n",
		    sc->sc_osize);
		sc->sc_osize = UHID_BSIZE;
	}
	if (sc->sc_fsize > UHID_BSIZE) {
		DPRINTF("feature size is too large, "
		    "%d bytes (truncating)\n",
		    sc->sc_fsize);
		sc->sc_fsize = UHID_BSIZE;
	}

	error = usb_fifo_attach(uaa->device, sc, &sc->sc_mtx,
	    &uhid_fifo_methods, &sc->sc_fifo,
	    unit, -1, uaa->info.bIfaceIndex,
	    UID_ROOT, GID_OPERATOR, 0644);
	if (error) {
		goto detach;
	}
	return (0);			/* success */

detach:
	uhid_detach(dev);
	return (ENOMEM);
}