[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: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Mauro Carvalho Chehab 2013-03-06 09:53:50 -03:00
parent db30567a63
commit 05f0ffbc48

View File

@ -35,16 +35,23 @@ 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;
struct smsusb_device_t *dev;
struct urb urb;
};
@ -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 (intf->num_altsetting > 0) {
rc = usb_set_interface(
udev, intf->cur_altsetting->desc.bInterfaceNumber, 0);
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 > 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,