Commit 05f0ffbc authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab
Browse files

[media] siano: use USB endpoint descriptors for in/out endp

Instead of using hardcoded descriptors, detect them from the
USB descriptors.
This patch is rebased form Doron Cohen's patch:
	http://patchwork.linuxtv.org/patch/7883/



Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent db30567a
Loading
Loading
Loading
Loading
+73 −26
Original line number Diff line number Diff line
@@ -35,14 +35,21 @@ module_param_named(debug, sms_dbg, int, 0644);
MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");

#define USB1_BUFFER_SIZE		0x1000
#define USB2_BUFFER_SIZE		0x4000
#define USB2_BUFFER_SIZE		0x2000

#define MAX_BUFFERS		50
#define MAX_URBS		10

struct smsusb_device_t;

enum smsusb_state {
	SMSUSB_DISCONNECTED,
	SMSUSB_SUSPENDED,
	SMSUSB_ACTIVE
};

struct smsusb_urb_t {
	struct list_head entry;
	struct smscore_buffer_t *cb;
	struct smsusb_device_t *dev;

@@ -57,11 +64,23 @@ struct smsusb_device_t {

	int		response_alignment;
	int		buffer_size;

	unsigned char in_ep;
	unsigned char out_ep;
	enum smsusb_state state;
};

static int smsusb_submit_urb(struct smsusb_device_t *dev,
			     struct smsusb_urb_t *surb);

/**
 * Completing URB's callback handler - top half (interrupt context)
 * adds completing sms urb to the global surbs list and activtes the worker
 * thread the surb
 * IMPORTANT - blocking functions must not be called from here !!!

 * @param urb pointer to a completing urb object
 */
static void smsusb_onresponse(struct urb *urb)
{
	struct smsusb_urb_t *surb = (struct smsusb_urb_t *) urb->context;
@@ -140,7 +159,7 @@ static int smsusb_submit_urb(struct smsusb_device_t *dev,
	usb_fill_bulk_urb(
		&surb->urb,
		dev->udev,
		usb_rcvbulkpipe(dev->udev, 0x81),
		usb_rcvbulkpipe(dev->udev, dev->in_ep),
		surb->cb->p,
		dev->buffer_size,
		smsusb_onresponse,
@@ -192,6 +211,9 @@ static int smsusb_sendrequest(void *context, void *buffer, size_t size)
		  smscore_translate_msg(phdr->msgType), phdr->msgType,
		  phdr->msgLength);

	if (dev->state != SMSUSB_ACTIVE)
		return -ENOENT;

	smsendian_handle_message_header((struct SmsMsgHdr_ST *)buffer);
	return usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 2),
			    buffer, size, &dummy, 1000);
@@ -301,13 +323,15 @@ static void smsusb_term_device(struct usb_interface *intf)
	struct smsusb_device_t *dev = usb_get_intfdata(intf);

	if (dev) {
		dev->state = SMSUSB_DISCONNECTED;

		smsusb_stop_streaming(dev);

		/* unregister from smscore */
		if (dev->coredev)
			smscore_unregister_device(dev->coredev);

		sms_info("device %p destroyed", dev);
		sms_info("device 0x%p destroyed", dev);
		kfree(dev);
	}

@@ -330,6 +354,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
	memset(&params, 0, sizeof(params));
	usb_set_intfdata(intf, dev);
	dev->udev = interface_to_usbdev(intf);
	dev->state = SMSUSB_DISCONNECTED;

	params.device_type = sms_get_board(board_id)->type;

@@ -346,6 +371,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
	case SMS_NOVA_A0:
	case SMS_NOVA_B0:
	case SMS_VEGA:
	case SMS_VENICE:
	case SMS_DENVER_1530:
		dev->buffer_size = USB2_BUFFER_SIZE;
		dev->response_alignment =
		    le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) -
@@ -355,6 +382,16 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
		break;
	}

	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
		if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN)
			dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
		else
			dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress;
	}

	sms_info("in_ep = %02x, out_ep = %02x",
		dev->in_ep, dev->out_ep);

	params.device = &dev->udev->dev;
	params.buffer_size = dev->buffer_size;
	params.num_buffers = MAX_BUFFERS;
@@ -386,6 +423,8 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
		return rc;
	}

	dev->state = SMSUSB_ACTIVE;

	rc = smscore_start_device(dev->coredev);
	if (rc < 0) {
		sms_err("smscore_start_device(...) failed");
@@ -393,7 +432,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id)
		return rc;
	}

	sms_info("device %p created", dev);
	sms_info("device 0x%p created", dev);

	return rc;
}
@@ -402,15 +441,23 @@ static int smsusb_probe(struct usb_interface *intf,
			const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(intf);
	char devpath[32];
	int i, rc;

	rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
	rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
	sms_info("interface number %d",
		 intf->cur_altsetting->desc.bInterfaceNumber);

	if (sms_get_board(id->driver_info)->intf_num !=
	    intf->cur_altsetting->desc.bInterfaceNumber) {
		sms_err("interface number is %d expecting %d",
			sms_get_board(id->driver_info)->intf_num,
			intf->cur_altsetting->desc.bInterfaceNumber);
		return -ENODEV;
	}

	if (intf->num_altsetting > 0) {
		rc = usb_set_interface(
			udev, intf->cur_altsetting->desc.bInterfaceNumber, 0);
	if (intf->num_altsetting > 1) {
		rc = usb_set_interface(udev,
				       intf->cur_altsetting->desc.bInterfaceNumber,
				       0);
		if (rc < 0) {
			sms_err("usb_set_interface failed, rc %d", rc);
			return rc;
@@ -419,27 +466,25 @@ static int smsusb_probe(struct usb_interface *intf,

	sms_info("smsusb_probe %d",
	       intf->cur_altsetting->desc.bInterfaceNumber);
	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) {
		sms_info("endpoint %d %02x %02x %d", i,
		       intf->cur_altsetting->endpoint[i].desc.bEndpointAddress,
		       intf->cur_altsetting->endpoint[i].desc.bmAttributes,
		       intf->cur_altsetting->endpoint[i].desc.wMaxPacketSize);

		if (intf->cur_altsetting->endpoint[i].desc.bEndpointAddress &
		    USB_DIR_IN)
			rc = usb_clear_halt(udev, usb_rcvbulkpipe(udev,
				intf->cur_altsetting->endpoint[i].desc.bEndpointAddress));
		else
			rc = usb_clear_halt(udev, usb_sndbulkpipe(udev,
				intf->cur_altsetting->endpoint[i].desc.bEndpointAddress));
	}
	if ((udev->actconfig->desc.bNumInterfaces == 2) &&
	    (intf->cur_altsetting->desc.bInterfaceNumber == 0)) {
		sms_err("rom interface 0 is not used");
		return -ENODEV;
	}

	if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
		snprintf(devpath, sizeof(devpath), "usb\\%d-%s",
			 udev->bus->busnum, udev->devpath);
		sms_info("stellar device was found.");
		return smsusb1_load_firmware(
				udev, smscore_registry_getmode(devpath),
				id->driver_info);
	}

	rc = smsusb_init_device(intf, id->driver_info);
	sms_info("rc %d", rc);
	sms_board_load_modules(id->driver_info);
@@ -454,7 +499,9 @@ static void smsusb_disconnect(struct usb_interface *intf)
static int smsusb_suspend(struct usb_interface *intf, pm_message_t msg)
{
	struct smsusb_device_t *dev = usb_get_intfdata(intf);
	printk(KERN_INFO "%s: Entering status %d.\n", __func__, msg.event);
	printk(KERN_INFO "%s  Entering status %d.\n", __func__, msg.event);
	dev->state = SMSUSB_SUSPENDED;
	/*smscore_set_power_mode(dev, SMS_POWER_MODE_SUSPENDED);*/
	smsusb_stop_streaming(dev);
	return 0;
}
@@ -465,9 +512,9 @@ static int smsusb_resume(struct usb_interface *intf)
	struct smsusb_device_t *dev = usb_get_intfdata(intf);
	struct usb_device *udev = interface_to_usbdev(intf);

	printk(KERN_INFO "%s: Entering.\n", __func__);
	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x81));
	usb_clear_halt(udev, usb_rcvbulkpipe(udev, 0x02));
	printk(KERN_INFO "%s  Entering.\n", __func__);
	usb_clear_halt(udev, usb_rcvbulkpipe(udev, dev->in_ep));
	usb_clear_halt(udev, usb_sndbulkpipe(udev, dev->out_ep));

	for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++)
		printk(KERN_INFO "endpoint %d %02x %02x %d\n", i,