This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
Re: USB serial linux kernel module
- From: Andrew Lunn <andrew at lunn dot ch>
- To: Frank Pagliughi <fpagliughi at mindspring dot com>
- Cc: Andrew Lunn <andrew at lunn dot ch>, eCos Patches <ecos-patches at ecos dot sourceware dot org>
- Date: Thu, 14 Aug 2008 21:04:44 +0200
- Subject: Re: USB serial linux kernel module
- References: <20080713130144.GL4167@lunn.ch> <489DA9D5.1010606@mindspring.com>
On Sat, Aug 09, 2008 at 10:29:41AM -0400, Frank Pagliughi wrote:
> Andrew Lunn wrote:
>> Hi Frank
>>
>> I worked on the Linux kernel module for the USB serial interface.
>>
>> Attached is a patch that allows it to compile with 2.6.26-rc9. The
>> patch also handles the device when it is in ACM mode. I found that
>> Linux attaches a device to the ACM interface which just has an
>> interrupt endpoint. This device is useless. By adding a probe function
>> i can detect this interface and tell the usb-serial layer to ignore
>> it.
>>
>> Please could you test this patch and let me know if it works for
>> you. If so, i will commit it.
>>
>> Thanks
>> Andrew
>>
> Andrew,
>
> This should patch your version of the ecos_usbserial.c Linux driver. It
> brings in endpoint check functions for older versions of the kernel. I
> tried this on Fedora 6 (older) and Fedora 8 (newer) and it worked on
> both.
Thanks.
I committed everything. Attached is the patch. It is a little large
because i tabified it to be consistent with the linux coding scheme.
Andrew
Index: packages/io/usb/serial/slave/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/usb/serial/slave/current/ChangeLog,v
retrieving revision 1.1
diff -u -r1.1 ChangeLog
--- packages/io/usb/serial/slave/current/ChangeLog 12 Jul 2008 10:30:34 -0000 1.1
+++ packages/io/usb/serial/slave/current/ChangeLog 14 Aug 2008 19:01:35 -0000
@@ -1,3 +1,15 @@
+2008-08-09 Frank Pagliughi <fpagliughi@mindspring.com>
+
+ * host/linux/ecos_usbserial.c (ecos_usbserial_probe): fix compiling
+ on older kernels.
+
+2008-07-13 Andrew Lunn <andrew.lunn@ascom.ch>
+
+ * host/linux/ecos_usbserial.c (ecos_usbserial_probe): new probe
+ function so that we ignore the ACM interface, otherwise we end up
+ with a useless /dev/ttyUSB device. Also allow to compile with
+ kernel 2.6.26-rc9.
+
2008-07-12 Frank Pagliughi <fpagliughi@mindspring.com>
* Generic USB Serial package created.
Index: packages/io/usb/serial/slave/current/host/linux/.cvsignore
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/usb/serial/slave/current/host/linux/.cvsignore,v
retrieving revision 1.1
diff -u -r1.1 .cvsignore
--- packages/io/usb/serial/slave/current/host/linux/.cvsignore 12 Jul 2008 10:30:34 -0000 1.1
+++ packages/io/usb/serial/slave/current/host/linux/.cvsignore 14 Aug 2008 19:01:35 -0000
@@ -1,3 +1,7 @@
.ecos_usbserial.o.d
.tmp_versions
-*.ko
\ No newline at end of file
+*.ko
+*.cmd
+Module.symvers
+ecos_usbserial.mod.c
+modules.order
\ No newline at end of file
Index: packages/io/usb/serial/slave/current/host/linux/ecos_usbserial.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/io/usb/serial/slave/current/host/linux/ecos_usbserial.c,v
retrieving revision 1.1
diff -u -r1.1 ecos_usbserial.c
--- packages/io/usb/serial/slave/current/host/linux/ecos_usbserial.c 12 Jul 2008 10:30:34 -0000 1.1
+++ packages/io/usb/serial/slave/current/host/linux/ecos_usbserial.c 14 Aug 2008 19:01:35 -0000
@@ -1,8 +1,8 @@
//==========================================================================
//
-// ecos_usbserial.c
+// ecos_usbserial.c
//
-// Kernel driver for the eCos USB serial driver
+// Kernel driver for the eCos USB serial driver
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
@@ -37,14 +37,15 @@
//===========================================================================
//#####DESCRIPTIONBEGIN####
//
-// Author(s): Frank M. Pagliughi (fmp), SoRo Systems, Inc.
+// Author(s): Frank M. Pagliughi (fmp), SoRo Systems, Inc.
// Contributors:
-// Date: 2008-06-02
-// Description: Kernel driver for the eCos USB serial driver
+// Date: 2008-06-02
+// Description: Kernel driver for the eCos USB serial driver
//
//####DESCRIPTIONEND####
//===========================================================================
+#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/tty.h>
@@ -55,6 +56,62 @@
#define VENDOR_ID 0xFFFF
#define PRODUCT_ID 1
+static int debug;
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
+static inline int
+usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *endpoint) {
+
+ return (endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
+ USB_ENDPOINT_XFER_BULK;
+}
+
+static inline int
+usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) {
+
+ return (epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN;
+}
+#endif
+
+/* Our probe function will detect if the interface has sufficient bulk
+ * in and out endpoints to be useful. The ACM interface only has an
+ * interrupt endpoint, so we don't want a serial device bound to it.
+ */
+
+static int ecos_usbserial_probe(struct usb_serial *serial,
+ const struct usb_device_id *id)
+{
+ struct usb_interface *interface = serial->interface;
+ struct usb_host_interface *iface_desc;
+ struct usb_endpoint_descriptor *endpoint;
+ int num_bulk_in = 0;
+ int num_bulk_out = 0;
+ int i;
+
+ iface_desc = interface->cur_altsetting;
+ for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+ endpoint = &iface_desc->endpoint[i].desc;
+
+ if (usb_endpoint_xfer_bulk(endpoint)) {
+ if (usb_endpoint_dir_in(endpoint)) {
+ /* we found a bulk in endpoint */
+ dbg("found bulk in on endpoint %d", i);
+ ++num_bulk_in;
+ } else {
+ /* we found a bulk out endpoint */
+ dbg("found bulk out on endpoint %d", i);
+ ++num_bulk_out;
+ }
+ }
+ }
+
+ if (!num_bulk_in || !num_bulk_out) {
+ info("Ignoring interface, insufficient endpoints");
+ return -ENODEV;
+ }
+ return 0;
+}
+
static struct usb_device_id id_table[] = {
{ USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
{ }
@@ -63,7 +120,7 @@
MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver ecos_usbserial_driver = {
- .name = "ecos_usbserial",
+ .name = "ecos_usbserial",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table
@@ -74,11 +131,17 @@
.owner = THIS_MODULE,
.name = "ecos_usbserial",
},
- .id_table = id_table,
+ .id_table = id_table,
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
- .num_ports = 1
+#else
+ .usb_driver = &ecos_usbserial_driver,
+#endif
+ .num_ports = 1,
+ .probe = ecos_usbserial_probe,
+
};
static int __init ecos_usbserial_init(void)
@@ -108,4 +171,6 @@
module_exit(ecos_usbserial_exit);
MODULE_LICENSE("GPL");
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");