need help to fix segfault

Submitted by Anonymous
on November 9, 2008 - 11:54am

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?

on
November 12, 2008 - 4:57pm

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

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.