From patchwork Fri Oct 14 17:32:51 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oliver Neukum X-Patchwork-Id: 8131 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1REljv-0006b6-Et; Fri, 14 Oct 2011 19:40:42 +0200 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.75/mailfrontend-4) with esmtp id 1REljg-0006yN-C5; Fri, 14 Oct 2011 19:39:57 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755848Ab1JNRjy (ORCPT + 3 others); Fri, 14 Oct 2011 13:39:54 -0400 Received: from smtp-out003.kontent.com ([81.88.40.217]:34455 "EHLO smtp-out003.kontent.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755123Ab1JNRjx (ORCPT ); Fri, 14 Oct 2011 13:39:53 -0400 X-Greylist: delayed 441 seconds by postgrey-1.27 at vger.kernel.org; Fri, 14 Oct 2011 13:39:52 EDT Received: from vanamonde.suse.de (p5DDC13F0.dip.t-dialin.net [93.220.19.240]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: neukum_org@smtp-out003.kontent.com) by smtp-out003.kontent.com (Postfix) with ESMTPSA id CCFC64000B4C; Fri, 14 Oct 2011 19:32:39 +0200 (CEST) From: Oliver Neukum To: Antti Palosaari Subject: Re: serial device name for smart card reader that is integrated to Anysee DVB USB device Date: Fri, 14 Oct 2011 19:32:51 +0200 User-Agent: KMail/1.13.5 (Linux/3.1.0-rc9-12-desktop+; KDE/4.4.4; x86_64; ; ) Cc: Greg KH , linux-serial@vger.kernel.org, linux-media@vger.kernel.org, linux-usb@vger.kernel.org, =?iso-8859-1?q?Bj=F8rn_Mork?= , "James Courtier-Dutton" , HoP , =?iso-8859-1?q?Istv=E1n_V=E1radi?= References: <4E8B7901.2050700@iki.fi> <4E8BF6DE.1010105@iki.fi> <201110051016.06291.oneukum@suse.de> In-Reply-To: <201110051016.06291.oneukum@suse.de> MIME-Version: 1.0 Message-Id: <201110141932.51378.oliver@neukum.org> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 5.6.1.2065439, Antispam-Engine: 2.7.2.376379, Antispam-Data: 2011.10.14.173021 X-PMX-Spam: Gauge=IIIIIIII, Probability=8%, Report=' MULTIPLE_RCPTS 0.1, BODY_SIZE_10000_PLUS 0, ECARD_WORD 0, NO_URI_FOUND 0, __BOUNCE_CHALLENGE_SUBJ 0, __BOUNCE_NDR_SUBJ_EXEMPT 0, __CT 0, __CTE 0, __CT_TEXT_PLAIN 0, __HAS_MSGID 0, __HAS_X_MAILING_LIST 0, __MIME_TEXT_ONLY 0, __MIME_VERSION 0, __MULTIPLE_RCPTS_CC_X2 0, __SANE_MSGID 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __USER_AGENT 0' X-LSpam-Score: 1.0 (+) X-LSpam-Report: No, score=1.0 required=5.0 tests=BAYES_00=-1.9, KB_DATE_CONTAINS_TAB=2.751, RCVD_IN_DNSWL_MED=-2.3, TAB_IN_FROM=2.494 autolearn=no Am Mittwoch, 5. Oktober 2011, 10:16:06 schrieb Oliver Neukum: > Am Mittwoch, 5. Oktober 2011, 08:19:10 schrieb Antti Palosaari: > > On 10/05/2011 09:15 AM, Oliver Neukum wrote: > > > > But, Greg, Antti makes a very valid point here. The generic code assumes that > > > it owns intfdata, that is you cannot use it as is for access to anything that lacks > > > its own interface. But this is not a fatal flaw. We can alter the generic code to use > > > an accessor function the driver can provide and make it default to get/set_intfdata > > > > > > What do you think? > > > > Oliver, I looked your old thread reply but I didn't catch how you meant > > it to happen. Could you give some small example? Hi, here is the code I come up with at an early, extremely incomplete stage. Just for your information because I'll stop working on this for a few days. Regards Oliver --- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/media/dvb/dvb-usb/anysee.c b/drivers/media/dvb/dvb-usb/anysee.c index 2cbf19a..34c950a 100644 --- a/drivers/media/dvb/dvb-usb/anysee.c +++ b/drivers/media/dvb/dvb-usb/anysee.c @@ -31,6 +31,12 @@ * is highly welcome! */ +#include +#include +#include +#include +#include +#include #include "anysee.h" #include "tda1002x.h" #include "mt352.h" @@ -898,6 +904,8 @@ static int anysee_probe(struct usb_interface *intf, if (ret) return ret; + usb_serial_start(d->card_dev, intf); + return anysee_init(d); } @@ -973,6 +981,10 @@ static int __init anysee_module_init(void) if (ret) err("%s: usb_register failed. Error number %d", __func__, ret); + ret = usb_serial_register(&anysee_card_driver); + if (ret) + usb_deregister(&anysee_driver); + return ret; } diff --git a/drivers/media/dvb/dvb-usb/anysee.h b/drivers/media/dvb/dvb-usb/anysee.h index ad6ccd1..f1ca088 100644 --- a/drivers/media/dvb/dvb-usb/anysee.h +++ b/drivers/media/dvb/dvb-usb/anysee.h @@ -61,6 +61,9 @@ struct anysee_state { u8 seq; }; +static struct usb_serial_driver anysee_card_driver = { +}; + #define ANYSEE_HW_507T 2 /* E30 */ #define ANYSEE_HW_507CD 6 /* E30 Plus */ #define ANYSEE_HW_507DC 10 /* E30 C Plus */ diff --git a/drivers/media/dvb/dvb-usb/dvb-usb.h b/drivers/media/dvb/dvb-usb/dvb-usb.h index 7d35d07..5333c4d 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb.h +++ b/drivers/media/dvb/dvb-usb/dvb-usb.h @@ -425,6 +425,7 @@ struct dvb_usb_device { /* remote control */ struct rc_dev *rc_dev; struct input_dev *input_dev; + struct usb_serial *card_dev; char rc_phys[64]; struct delayed_work rc_query_work; u32 last_event; diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index e4db5ad..4c387ab 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -175,6 +175,12 @@ int usb_serial_generic_prepare_write_buffer(struct usb_serial_port *port, return kfifo_out_locked(&port->write_fifo, dest, size, &port->lock); } +void usb_serial_generic_set_private_data(struct usb_interface *intf, struct usb_serial *serial) +{ + usb_set_intfdata(intf, serial); +} +EXPORT_SYMBOL_GPL(usb_serial_generic_set_private_data); + /** * usb_serial_generic_write_start - kick off an URB write * @port: Pointer to the &struct usb_serial_port data diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 1c03130..dd8cf75 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -707,19 +707,18 @@ static const struct tty_port_operations serial_port_ops = { .shutdown = serial_down, }; -int usb_serial_probe(struct usb_interface *interface, - const struct usb_device_id *id) +int usb_serial_start(struct usb_serial *serial, struct usb_interface *interface) { struct usb_device *dev = interface_to_usbdev(interface); - struct usb_serial *serial = NULL; - struct usb_serial_port *port; + struct usb_serial_driver *type = NULL; struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *interrupt_in_endpoint[MAX_NUM_PORTS]; struct usb_endpoint_descriptor *interrupt_out_endpoint[MAX_NUM_PORTS]; struct usb_endpoint_descriptor *bulk_in_endpoint[MAX_NUM_PORTS]; struct usb_endpoint_descriptor *bulk_out_endpoint[MAX_NUM_PORTS]; - struct usb_serial_driver *type = NULL; + struct usb_serial_port *port; + int retval; unsigned int minor; int buffer_size; @@ -731,28 +730,6 @@ int usb_serial_probe(struct usb_interface *interface, int num_ports = 0; int max_endpoints; - mutex_lock(&table_lock); - type = search_serial_device(interface); - if (!type) { - mutex_unlock(&table_lock); - dbg("none matched"); - return -ENODEV; - } - - if (!try_module_get(type->driver.owner)) { - mutex_unlock(&table_lock); - dev_err(&interface->dev, "module get failed, exiting\n"); - return -EIO; - } - mutex_unlock(&table_lock); - - serial = create_serial(dev, interface, type); - if (!serial) { - module_put(type->driver.owner); - dev_err(&interface->dev, "%s - out of memory\n", __func__); - return -ENOMEM; - } - /* if this device type has a probe function, call it */ if (type->probe) { const struct usb_device_id *id; @@ -1087,7 +1064,8 @@ int usb_serial_probe(struct usb_interface *interface, exit: /* success */ - usb_set_intfdata(interface, serial); + serial->type->set_private_data(interface, serial); + //usb_set_intfdata(interface, serial); module_put(type->driver.owner); return 0; @@ -1096,6 +1074,39 @@ probe_error: module_put(type->driver.owner); return -EIO; } +EXPORT_SYMBOL_GPL(usb_serial_start); + +int usb_serial_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct usb_device *dev = interface_to_usbdev(interface); + struct usb_serial *serial = NULL; + struct usb_serial_driver *type = NULL; + + mutex_lock(&table_lock); + type = search_serial_device(interface); + if (!type) { + mutex_unlock(&table_lock); + dbg("none matched"); + return -ENODEV; + } + + if (!try_module_get(type->driver.owner)) { + mutex_unlock(&table_lock); + dev_err(&interface->dev, "module get failed, exiting\n"); + return -EIO; + } + mutex_unlock(&table_lock); + + serial = create_serial(dev, interface, type); + if (!serial) { + module_put(type->driver.owner); + dev_err(&interface->dev, "%s - out of memory\n", __func__); + return -ENOMEM; + } + + return usb_serial_start(serial, interface); +} EXPORT_SYMBOL_GPL(usb_serial_probe); void usb_serial_disconnect(struct usb_interface *interface) @@ -1109,7 +1120,8 @@ void usb_serial_disconnect(struct usb_interface *interface) dbg("%s", __func__); mutex_lock(&serial->disc_mutex); - usb_set_intfdata(interface, NULL); + serial->type->set_private_data(interface, NULL); + /* must set a flag, to signal subdrivers */ serial->disconnected = 1; mutex_unlock(&serial->disc_mutex); @@ -1148,11 +1160,11 @@ void usb_serial_disconnect(struct usb_interface *interface) usb_serial_put(serial); dev_info(dev, "device disconnected\n"); } + EXPORT_SYMBOL_GPL(usb_serial_disconnect); -int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) +int usb_serial_do_suspend(struct usb_serial *serial, pm_message_t message) { - struct usb_serial *serial = usb_get_intfdata(intf); struct usb_serial_port *port; int i, r = 0; @@ -1175,11 +1187,18 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) err_out: return r; } -EXPORT_SYMBOL(usb_serial_suspend); -int usb_serial_resume(struct usb_interface *intf) +EXPORT_SYMBOL(usb_serial_do_suspend); + +int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) { struct usb_serial *serial = usb_get_intfdata(intf); + return usb_serial_do_suspend(serial, message); +} +EXPORT_SYMBOL(usb_serial_suspend); + +int usb_serial_do_resume(struct usb_serial *serial) +{ int rv; serial->suspending = 0; @@ -1190,8 +1209,17 @@ int usb_serial_resume(struct usb_interface *intf) return rv; } +EXPORT_SYMBOL(usb_serial_do_resume); + +int usb_serial_resume(struct usb_interface *intf) +{ + struct usb_serial *serial = usb_get_intfdata(intf); + return usb_serial_do_resume(serial); +} + EXPORT_SYMBOL(usb_serial_resume); + static const struct tty_operations serial_ops = { .open = serial_open, .close = serial_close, @@ -1332,6 +1360,7 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, release); set_to_generic_if_null(device, process_read_urb); set_to_generic_if_null(device, prepare_write_buffer); + set_to_generic_if_null(device, set_private_data); } int usb_serial_register(struct usb_serial_driver *driver) diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index b29f70b..396de61 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -243,6 +243,7 @@ struct usb_serial_driver { int (*probe)(struct usb_serial *serial, const struct usb_device_id *id); int (*attach)(struct usb_serial *serial); int (*calc_num_ports) (struct usb_serial *serial); + void (*set_private_data) (struct usb_interface *intf, struct usb_serial *serial); void (*disconnect)(struct usb_serial *serial); void (*release)(struct usb_serial *serial); @@ -301,10 +302,13 @@ extern void usb_serial_port_softint(struct usb_serial_port *port); extern int usb_serial_probe(struct usb_interface *iface, const struct usb_device_id *id); +extern int usb_serial_start(struct usb_serial *serial, struct usb_interface *iface); extern void usb_serial_disconnect(struct usb_interface *iface); extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message); +extern int usb_serial_do_suspend(struct usb_serial *serial, pm_message_t message); extern int usb_serial_resume(struct usb_interface *intf); +extern int usb_serial_do_resume(struct usb_serial *serial); extern int ezusb_writememory(struct usb_serial *serial, int address, unsigned char *data, int length, __u8 bRequest); @@ -329,6 +333,7 @@ extern int usb_serial_generic_open(struct tty_struct *tty, extern int usb_serial_generic_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count); extern void usb_serial_generic_close(struct usb_serial_port *port); +extern void usb_serial_generic_set_private_data(struct usb_interface *intf, struct usb_serial *serial); extern int usb_serial_generic_resume(struct usb_serial *serial); extern int usb_serial_generic_write_room(struct tty_struct *tty); extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);