Ajouter un commentaire

dillinger91
aide pour programation driver usb

voila je me lance dans la programation de mon premier driver usb-pour un recepteur irda-.
j'ai codé la majorité du driver et la a l'heure des tests je n'arrive pas a ouvrir mon driver via un programme C et l'appel systeme open().
j'ai l'impression que c'est une question de permission parce ce que une fois ne root j'ai reussi a acceder au driver mais une fois seulement car le comportement de mon driver est assez alleatoire.et il rend le systeme instable.donc je poste ici le code source de mon driver en esperant que vous pourez m'aider a corriger ce qui ne va pas.

    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/usb.h>
    #include <linux/slab.h>
    #include <linux/errno.h>
    #include <linux/smp_lock.h>
    #include <linux/fs.h>
    #include <asm/current.h>
    #include <asm/uaccess.h>
    
    #define ID_VENDOR     0x2102 
    #define ID_PRODUCT    0x3046
    #define TEST_USB_MINOR_BASE 0
    #define to_test_dev(d) container_of(d, struct usb_priv, kref)
    MODULE_AUTHOR("dillinger,r.zenine@hotmail.Com");
    MODULE_DESCRIPTION("dataman usb irda");
    MODULE_SUPPORTED_DEVICE("0x2102,0x3046");
    MODULE_LICENSE("GPL");
    int test_probe (struct usb_interface *intf,const struct usb_device_id *id);
    void test_disconnect (struct usb_interface *intf);
    int test_open(struct inode *inode,struct file *filp);
    int test_release(struct inode *inode,struct file *filp);
    static ssize_t test_read(struct file *filp,char* buf,size_t count,loff_t* pos);
    static void test_read_int_callback(struct urb *urb, struct pt_regs *regs);
    struct usb_priv
    {
    	unsigned char *mess;
    	struct usb_device *udev;
    	struct usb_interface *interface;
    	struct urb *test_urb;
    	struct kref kref;
    };
    static void test_delete(struct kref *kref)
    {	
    	struct usb_priv *dev = to_test_dev(kref);
    
    	usb_put_dev(dev->udev);
    	kfree (dev);
    }
    static struct usb_device_id ID_Table[] = {
        {USB_DEVICE(ID_VENDOR,ID_PRODUCT)},
        {},
    };
    MODULE_DEVICE_TABLE(usb,ID_Table);
    
    static struct usb_driver test_driver = {
        .name = "irda_usb",
        .id_table = ID_Table,
        .probe = test_probe,
        .disconnect = test_disconnect,
    };
    
    struct file_operations test_fops={
    	.open = test_open,
    	.release = test_release,
    	.read = test_read,
    };
    struct usb_class_driver test_class ={
    	.name = "irda_usb",
    	.fops = &test_fops,
    	.minor_base=TEST_USB_MINOR_BASE,
    };
    
    int test_probe (struct usb_interface *intf,const struct usb_device_id *id)
    {
    	struct usb_priv *dev=NULL;
    	int retval = -ENOMEM;
    	printk(KERN_DEBUG"data usb :entrée dans probe\n");
    	dev=kmalloc(sizeof(struct usb_priv),GFP_KERNEL);
    	if (dev == NULL)
    	{
    		printk(KERN_DEBUG"data usb :OUT OF MEMORY\n");
    		goto error;
    	}
    	memset(dev,0x00,sizeof(*dev));
    	kref_init(&dev->kref);
    	dev->udev= usb_get_dev(interface_to_usbdev(intf));
    	dev->interface=intf;
    	retval = usb_register_dev(intf,&test_class);
    	if (retval==-EINVAL)
    	{	
    		printk(KERN_DEBUG"usb test :no able to get minor for this interface\n");
    		usb_set_intfdata(intf,NULL);
    		goto error;
    	}
    	printk(KERN_DEBUG"data usb minor:%d\n",intf->minor);
    	usb_set_intfdata(intf,dev);
    	return 0;
    error:
    	if (dev)
    		kref_put(&dev->kref, test_delete);
    	return retval;
    	
    }
    void test_disconnect (struct usb_interface *intf)
    {
    	int minor = intf->minor;
    	struct usb_priv *dev;
    	printk(KERN_DEBUG"data usb :entrée dans probe\n");
    	lock_kernel();//previent contre l'appel de test_open() pendant test_disconnect()
    	dev = usb_get_intfdata(intf);
    	usb_set_intfdata(intf,NULL);
    	usb_deregister_dev(intf,&test_class);
    	kfree(dev);
    	unlock_kernel();//on deverouille
    	kref_put(&dev->kref, test_delete);//decremente l'utilisation du peripherique
    	printk (KERN_DEBUG"test_usb %d :diconnected\n",minor);
    }
    int test_open(struct inode *inode,struct file *filp)
    {
    	struct usb_priv *dev=NULL;
    	struct usb_interface *interface;
    	int subminor;
    	int retval=0;
    	subminor=iminor(inode);
    	interface = usb_find_interface(&test_driver,subminor);
    	printk(KERN_DEBUG"data usb :entrée dans open\n");
    	if(!interface)
    	{
    		retval = -ENODEV;
    		goto exit;
    	}
    	dev = usb_get_intfdata(interface);
    	if(!dev)
    	{
    		retval = -ENODEV;
    		goto exit;
    	}
    	kref_get(&dev->kref);
    	filp->private_data=dev;
    exit:
    	return retval;
    }
    int test_release(struct inode *inode,struct file *filp)
    {
    	struct usb_priv *dev;
    
    	dev = (struct usb_priv *)filp->private_data;
    	if (dev == NULL)
    		return -ENODEV;
    
    	/* decrement the count on our device */
    	kref_put(&dev->kref,test_delete);
    	
    	return 0;
    }
    static void test_read_int_callback(struct urb *urb, struct pt_regs *regs)
    {
    	printk(KERN_DEBUG"test usb:entrée dans read_int_callback\n");
    	/* sync/async unlink faults aren't errors */
    	if (urb->status && 
    	    !(urb->status == -ENOENT || 
    	      urb->status == -ECONNRESET ||
    	      urb->status == -ESHUTDOWN)) 
    	{
    		dbg("%s - nonzero read int status received: %d",
    		    __FUNCTION__, urb->status);
    		usb_kill_urb(urb);  
    	}
    	else{usb_unlink_urb(urb);}
    }	
    static ssize_t test_read(struct file *filp,char* buf,size_t count,loff_t* pos)
    {
    	struct usb_priv *dev;
    	int res;
    	printk(KERN_DEBUG"test usb:entrée dans read\n");
    	dev = (struct usb_priv*)filp->private_data;
    	dev->test_urb = usb_alloc_urb(0,GFP_KERNEL);
    	if(!dev->test_urb){return -ENOMEM;}
    	usb_fill_int_urb(dev->test_urb,dev->udev,usb_rcvintpipe(dev->udev,0x81),(void*) dev->mess,8,test_read_int_callback,dev,0x01);
    	dev->mess=kmalloc(sizeof(char)*64,GFP_KERNEL);
    	res=usb_submit_urb(dev->test_urb,GFP_KERNEL);
    	if(res!=0){return -1;}
    	else{usb_free_urb(dev->test_urb);}
    	if(count == 0)
    	{
    		printk(KERN_DEBUG"data usb:erreur lecture!!!!!!");
    		return -1;
    	}
    	if(copy_to_user(buf,dev->mess,dev->test_urb->actual_length)!=0){return -3;}
    	kfree(dev->mess);
    	printk(KERN_DEBUG"data usb:urb actual lenght: %d\n",dev->test_urb->actual_length);
    	return (dev->test_urb->actual_length);
    }
    static int __init test_init(void)
    {
    	int result;
    	printk(KERN_DEBUG"Test_Mod : entrée dans test_init\n");
    	result=usb_register(&test_driver);
    	if(result){printk(KERN_DEBUG"usb_register failed. Error number %d", result);}
    	else
    	{
    		printk(KERN_ALERT"Test_Mod : Enregistrement du driver OK\n");
    		return 0;
    	}
    	return result;
    }
    	
    	
    static void __exit test_exit(void)
    {
        printk(KERN_DEBUG"Test_Mod : entrée dans test_exit\n");
        usb_deregister(&test_driver);
        printk(KERN_ALERT"Test_Mod : Liberation du driver OK\n");
    }
    module_init(test_init);
    module_exit(test_exit);
    
    désole pour la longueur du post.
    je suis ouvert a toute remarque ou autre critique donc ne vous genez pas.

    Filtered HTML

    Plain text

    CAPTCHA
    Cette question permet de vérifier que vous n'êtes pas un robot spammeur :-)
      CCC   GGG    QQQ     SSS   III 
    C G Q Q S I
    C G GG Q Q SSS I
    C G G Q QQ S I
    CCC GGG QQQQ SSSS III
    Q