Hi,
When i run simple application which call open system call for opeing /dev/ttyUSB0, segfault occurs? Can anyone know the reason. Take a look at the driver code for usb serial cp210x device.
Thanks
Lokesh.V
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/tty_flip.h>
#include <linux/serial.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/uaccess.h>
#include <linux/usb.h>
#include "cp210x.h"
#include "usb-serial.h"
/* Version Information */
#define DRIVER_VERSION "v1.0"
#define DRIVER_AUTHOR "Lokesh.V, Bhanu. T, Nandigital Technologies, Bangalore"
#define DRIVER_DESC "Silabs USB to Serial Driver"
#ifdef CONFIG_USB_SERIAL_DEBUG
static int debug = 1;
#else
static int debug;
#endif
//static int driverType ;
static int cp2102_open (struct usb_serial_port *port, struct file *filp);
static void cp2102_read_bulk_callback (struct urb *urb);
static void cp2102_write_bulk_callback (struct urb *urb);
static int cp2102_startup (struct usb_serial *serial);
static void cp2102_shutdown(struct usb_serial *serial);
static void cp2102_close (struct usb_serial_port *port, struct file *filp);
static struct usb_device_id cp210x_id_table [] = {
{ USB_DEVICE(CP210X_VENDOR_ID, CP210X_PRODUCT_ID) },/* Silabs factory default*/
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ } /* Terminating entry */
};
struct cp2102_private {
u8 driverType;
};
static struct usb_serial_device_type cp210x_device = {
.owner = THIS_MODULE,
.name = "CP2102",
.id_table = cp210x_id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = 1,
.num_bulk_out = 1,
.num_ports = 1,
.open = cp2102_open,
.close = cp2102_close,
// .write = pl2303_write,
// .ioctl = pl2303_ioctl,
// .break_ctl = pl2303_break_ctl,
// .set_termios = pl2303_set_termios,
.read_bulk_callback = cp2102_read_bulk_callback,
// .read_int_callback = cp2102_read_int_callback,
.write_bulk_callback = cp2102_write_bulk_callback,
// .startup = cp2102_startup,
// .shutdown = cp2102_shutdown,
};
static int cp2102_startup (struct usb_serial *serial)
{
struct cp2102_private *priv;
int i;
for (i = 0; i < serial->num_ports; ++i) {
priv = kmalloc (sizeof (struct cp2102_private), GFP_KERNEL);
if (!priv)
return -ENOMEM;
memset (priv,0x00, sizeof (struct cp2102_private));
serial->port[i].private = priv;
}
info(" in startup ");
return 0;
}
static void cp2102_shutdown(struct usb_serial *serial)
{
int i;
struct cp2102_private *prv = serial->private;
info ("%x ",prv->driverType);
for (i = 0; i < serial->num_ports; ++i)
kfree (serial->port[i].private);
}
static void cp2102_read_bulk_callback (struct urb *urb)
{
return ;
}
static void cp2102_write_bulk_callback (struct urb *urb)
{
return ;
}
static int cp2102_open (struct usb_serial_port *port, struct file *filp)
{
struct usb_serial *serial = port->serial;
int result;
struct cp2102_private *priv = port->private;
/* if (port_paranoia_check (port, __FUNCTION__))
return -ENODEV;
info("port %d", port->number);*/
//count = ++(serial->port->open_count);
// info(" no of devices opened %d\n",count);
if(serial->dev->descriptor.bDeviceClass == 0x02)
priv->driverType = 0;
else if(serial->dev->descriptor.bMaxPacketSize0 == 0x40)
priv->driverType = 1;
info("cp2102 driver type: %d", priv->driverType);
if (serial->num_bulk_in) {
/* Start reading from the device */
usb_fill_bulk_urb (port->read_urb, serial->dev,
usb_rcvbulkpipe(serial->dev,
port->bulk_in_endpointAddress),
port->read_urb->transfer_buffer,
port->read_urb->transfer_buffer_length,
cp2102_read_bulk_callback,
port);
result = usb_submit_urb(port->read_urb);
if (result)
info("failed resubmitting read urb, error %d", result);
else
info("success \n");
}
return result;
}
static void cp2102_close (struct usb_serial_port *port, struct file *filp)
{
int result,count;
struct usb_serial *serial = port->serial;
/*count = --(serial->port->open_count);
if(count != 0)
info("unable close the device \n");
*/
if(port->serial->dev)
{
/* shutdown our urbs */
/*result = usb_unlink_urb (port->write_urb);
if (result)
info("usb_unlink_urb (write_urb)"
" failed with reason: %d", result);
*/
result = usb_unlink_urb (port->read_urb);
if (result)
info("usb_unlink_urb (read_urb)"
" failed with reason: %d", result);
else
info("read urb unlink successful \n");
}
}
static int __init cp210x_init (void)
{
usb_serial_register (&cp210x_device);
printk("Registration Sucessful.\n");
return 0;
}
static void __exit cp210x_exit (void)
{
usb_serial_deregister (&cp210x_device);
}
module_init(cp210x_init);
module_exit(cp212x_exit);
MODULE_LICENSE("GPL");
MODULE_PARM(debug, "i");
MODULE_PARM_DESC(debug, "Debug enabled or not");
driver not registered properly maybe?
I don't think the driver is registered properly.
You may want to try the following:
1) You will need to export the table id with:
MODULE_DEVICE_TABLE (usb, cp210x_id_table);
2) you will need the usb core to know how to probe the new device.
So you need to add (in the usb driver structure that is registered) something like:
.probe = usb_serial_probe
or having your own probe callback that calls usb_serial_probe would allow you to add some printk to make sure the driver is the one used for your device.
Regards,
-Mathieu