Esempio n. 1
0
static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
{
	struct btusb_data *data = hdev->driver_data;
	struct usb_interface *intf = data->isoc;
	struct usb_endpoint_descriptor *ep_desc;
	int i, err;

	if (!data->isoc)
		return -ENODEV;

	err = usb_set_interface(data->udev, 1, altsetting);
	if (err < 0) {
		BT_ERR("%s setting interface failed (%d)", hdev->name, -err);
		return err;
	}

	data->isoc_altsetting = altsetting;

	data->isoc_tx_ep = NULL;
	data->isoc_rx_ep = NULL;

	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
		ep_desc = &intf->cur_altsetting->endpoint[i].desc;

		if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) {
			data->isoc_tx_ep = ep_desc;
			continue;
		}

		if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) {
			data->isoc_rx_ep = ep_desc;
			continue;
		}
	}

	if (!data->isoc_tx_ep || !data->isoc_rx_ep) {
		BT_ERR("%s invalid SCO descriptors", hdev->name);
		return -ENODEV;
	}

	return 0;
}
Esempio n. 2
0
static void find_usb_pipe(struct baseband_usb *usb)
{
	struct usb_device *usbdev = usb->usb.device;
	struct usb_interface *intf = usb->usb.interface;
	unsigned char numendpoint = intf->cur_altsetting->desc.bNumEndpoints;
	struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint;
	unsigned char n;

	for (n = 0; n < numendpoint; n++) {
		if (usb_endpoint_is_isoc_in(&endpoint[n].desc)) {
			pr_debug("endpoint[%d] isochronous in\n", n);
			usb->usb.pipe.isoch.in = usb_rcvisocpipe(usbdev,
				endpoint[n].desc.bEndpointAddress);
		} else if (usb_endpoint_is_isoc_out(&endpoint[n].desc)) {
			pr_debug("endpoint[%d] isochronous out\n", n);
			usb->usb.pipe.isoch.out = usb_sndisocpipe(usbdev,
				endpoint[n].desc.bEndpointAddress);
		} else if (usb_endpoint_is_bulk_in(&endpoint[n].desc)) {
			pr_debug("endpoint[%d] bulk in\n", n);
			usb->usb.pipe.bulk.in = usb_rcvbulkpipe(usbdev,
				endpoint[n].desc.bEndpointAddress);
		} else if (usb_endpoint_is_bulk_out(&endpoint[n].desc)) {
			pr_debug("endpoint[%d] bulk out\n", n);
			usb->usb.pipe.bulk.out = usb_sndbulkpipe(usbdev,
				endpoint[n].desc.bEndpointAddress);
		} else if (usb_endpoint_is_int_in(&endpoint[n].desc)) {
			pr_debug("endpoint[%d] interrupt in\n", n);
			usb->usb.pipe.interrupt.in = usb_rcvintpipe(usbdev,
				endpoint[n].desc.bEndpointAddress);
		} else if (usb_endpoint_is_int_out(&endpoint[n].desc)) {
			pr_debug("endpoint[%d] interrupt out\n", n);
			usb->usb.pipe.interrupt.out = usb_sndintpipe(usbdev,
				endpoint[n].desc.bEndpointAddress);
		} else {
			pr_debug("endpoint[%d] skipped\n", n);
		}
	}
}
Esempio n. 3
0
static int detect_usb_format(struct ua101 *ua)
{
	const struct uac_format_type_i_discrete_descriptor *fmt_capture;
	const struct uac_format_type_i_discrete_descriptor *fmt_playback;
	const struct usb_endpoint_descriptor *epd;
	unsigned int rate2;

	fmt_capture = find_format_descriptor(ua->intf[INTF_CAPTURE]);
	fmt_playback = find_format_descriptor(ua->intf[INTF_PLAYBACK]);
	if (!fmt_capture || !fmt_playback)
		return -ENXIO;

	switch (fmt_capture->bSubframeSize) {
	case 3:
		ua->format_bit = SNDRV_PCM_FMTBIT_S24_3LE;
		break;
	case 4:
		ua->format_bit = SNDRV_PCM_FMTBIT_S32_LE;
		break;
	default:
		dev_err(&ua->dev->dev, "sample width is not 24 or 32 bits\n");
		return -ENXIO;
	}
	if (fmt_capture->bSubframeSize != fmt_playback->bSubframeSize) {
		dev_err(&ua->dev->dev,
			"playback/capture sample widths do not match\n");
		return -ENXIO;
	}

	if (fmt_capture->bBitResolution != 24 ||
	    fmt_playback->bBitResolution != 24) {
		dev_err(&ua->dev->dev, "sample width is not 24 bits\n");
		return -ENXIO;
	}

	ua->rate = combine_triple(fmt_capture->tSamFreq[0]);
	rate2 = combine_triple(fmt_playback->tSamFreq[0]);
	if (ua->rate != rate2) {
		dev_err(&ua->dev->dev,
			"playback/capture rates do not match: %u/%u\n",
			rate2, ua->rate);
		return -ENXIO;
	}

	switch (ua->dev->speed) {
	case USB_SPEED_FULL:
		ua->packets_per_second = 1000;
		break;
	case USB_SPEED_HIGH:
		ua->packets_per_second = 8000;
		break;
	default:
		dev_err(&ua->dev->dev, "unknown device speed\n");
		return -ENXIO;
	}

	ua->capture.channels = fmt_capture->bNrChannels;
	ua->playback.channels = fmt_playback->bNrChannels;
	ua->capture.frame_bytes =
		fmt_capture->bSubframeSize * ua->capture.channels;
	ua->playback.frame_bytes =
		fmt_playback->bSubframeSize * ua->playback.channels;

	epd = &ua->intf[INTF_CAPTURE]->altsetting[1].endpoint[0].desc;
	if (!usb_endpoint_is_isoc_in(epd)) {
		dev_err(&ua->dev->dev, "invalid capture endpoint\n");
		return -ENXIO;
	}
	ua->capture.usb_pipe = usb_rcvisocpipe(ua->dev, usb_endpoint_num(epd));
	ua->capture.max_packet_bytes = le16_to_cpu(epd->wMaxPacketSize);

	epd = &ua->intf[INTF_PLAYBACK]->altsetting[1].endpoint[0].desc;
	if (!usb_endpoint_is_isoc_out(epd)) {
		dev_err(&ua->dev->dev, "invalid playback endpoint\n");
		return -ENXIO;
	}
	ua->playback.usb_pipe = usb_sndisocpipe(ua->dev, usb_endpoint_num(epd));
	ua->playback.max_packet_bytes = le16_to_cpu(epd->wMaxPacketSize);
	return 0;
}