Changeset - 7d59926031ba
[Not reviewed]
default
0 1 0
drewp@bigasterisk.com - 14 years ago 2011-06-15 07:54:58
drewp@bigasterisk.com
attempted fixes to dmx_usb kernel module for 2.6.38. untested; may crash you
Ignore-this: 7d3167e0c028a60f152114a8addcb18
1 file changed with 15 insertions and 3 deletions:
0 comments (0 inline, 0 general)
dmx_usb_module/dmx_usb.c
Show inline comments
 
@@ -17,48 +17,54 @@
 
#include <linux/kernel.h>
 
#include <linux/errno.h>
 
#include <linux/init.h>
 
#include <linux/slab.h>
 
#include <linux/module.h>
 
#include <linux/smp_lock.h>
 
#include <linux/completion.h>
 
#include <asm/uaccess.h>
 
#include <linux/usb.h>
 
#include <linux/version.h>
 

	
 
#include "dmx_usb.h"
 

	
 
#ifdef CONFIG_USB_DEBUG
 
	static int debug = 1;
 
#else
 
	static int debug;
 
#endif
 

	
 
/* Use our own dbg macro */
 
#undef dbg
 
#define dbg(format, arg...) do { if (debug) printk(KERN_DEBUG __FILE__ ": " format "\n" , ## arg); } while (0)
 

	
 

	
 
// from http://www.linuxinsight.com/vmware-workstation-7.1.3-runs-great-on-linux-kernel-2.6.37.html
 
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
 
   #define DECLARE_MUTEX(_m) DEFINE_SEMAPHORE(_m)
 
   #define init_MUTEX(_m) sema_init(_m, 1)
 
#endif
 

	
 
/* Version Information */
 
#define DRIVER_VERSION "v0.1.20060816"
 
#define DRIVER_AUTHOR "Erwin Rol, erwin@erwinrol.com"
 
#define DRIVER_DESC "DMX USB Driver"
 

	
 
/* Module parameters */
 
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) )
 
MODULE_PARM(debug, "i");
 
MODULE_PARM_DESC(debug, "Debug enabled or not");
 
#else
 
module_param(debug, bool, S_IRUGO | S_IWUSR);
 
MODULE_PARM_DESC(debug, "Debug enabled or not");
 
#endif
 

	
 
static struct usb_device_id dmx_usb_table [] = {
 
	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
 
	{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
 
	{ }                                             /* Terminating entry */
 
};
 

	
 
MODULE_DEVICE_TABLE (usb, dmx_usb_table);
 

	
 
/* Get a minor range for your devices from the usb maintainer */
 
#define DMX_USB_MINOR_BASE	192
 
@@ -75,72 +81,72 @@ struct dmx_usb_device {
 

	
 
	unsigned char *		bulk_in_buffer;		/* the buffer to receive data */
 
	size_t			bulk_in_size;		/* the size of the receive buffer */
 
	__u8			bulk_in_endpointAddr;	/* the address of the bulk in endpoint */
 

	
 
	unsigned char *		bulk_out_buffer;	/* the buffer to send data */
 
	size_t			bulk_out_size;		/* the size of the send buffer */
 
	struct urb *		write_urb;		/* the urb used to send data */
 
	__u8			bulk_out_endpointAddr;	/* the address of the bulk out endpoint */
 
	atomic_t		write_busy;		/* true iff write urb is busy */
 
	struct completion	write_finished;		/* wait for the write to finish */
 

	
 
	int			open;			/* if the port is open or not */
 
	int			present;		/* if the device is not disconnected */
 
	struct semaphore	sem;			/* locks this structure */
 
};
 

	
 

	
 
/* prevent races between open() and disconnect() */
 
static DECLARE_MUTEX (disconnect_sem);
 

	
 
/* local function prototypes */
 
//static ssize_t dmx_usb_read	(struct file *file, char *buffer, size_t count, loff_t *ppos);
 
static ssize_t dmx_usb_write	(struct file *file, const char *buffer, size_t count, loff_t *ppos);
 
static int dmx_usb_ioctl	(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
 
static int dmx_usb_ioctl	(struct file *file, unsigned int cmd, unsigned long arg);
 
static int dmx_usb_open		(struct inode *inode, struct file *file);
 
static int dmx_usb_release	(struct inode *inode, struct file *file);
 

	
 
static int dmx_usb_probe	(struct usb_interface *interface, const struct usb_device_id *id);
 
static void dmx_usb_disconnect	(struct usb_interface *interface);
 

	
 
static void dmx_usb_write_bulk_callback	(struct urb *urb, struct pt_regs *regs);
 

	
 
static struct file_operations dmx_usb_fops = {
 
	/*
 
	 * The owner field is part of the module-locking
 
	 * mechanism. The idea is that the kernel knows
 
	 * which module to increment the use-counter of
 
	 * BEFORE it calls the device's open() function.
 
	 * This also means that the kernel can decrement
 
	 * the use-counter again before calling release()
 
	 * or should the open() function fail.
 
	 */
 
	.owner =	THIS_MODULE,
 

	
 
	/* .read =		dmx_usb_read, */ 
 
	.write =	dmx_usb_write,
 
	.ioctl =	dmx_usb_ioctl,
 
	.unlocked_ioctl = dmx_usb_ioctl,
 
	.open =		dmx_usb_open,
 
	.release =	dmx_usb_release,
 
};
 

	
 
/* 
 
 * usb class driver info in order to get a minor number from the usb core,
 
 * and to have the device registered with devfs and the driver core
 
 */
 
static struct usb_class_driver dmx_usb_class = {
 
	.name =		"usb/dmx%d",
 
	.fops =		&dmx_usb_fops,
 
	.minor_base =	DMX_USB_MINOR_BASE,
 
};
 

	
 
/* usb specific object needed to register this driver with the usb subsystem */
 
static struct usb_driver dmx_usb_driver = {
 
#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16) )
 
	.owner =	THIS_MODULE,
 
#endif
 
	.name =		"dmx_usb",
 
	.probe =	dmx_usb_probe,
 
	.disconnect =	dmx_usb_disconnect,
 
	.id_table =	dmx_usb_table,
 
};
 
@@ -505,71 +511,77 @@ static ssize_t dmx_usb_write (struct fil
 
	/* send the data out the bulk port */
 
	/* a character device write uses GFP_KERNEL,
 
	 unless a spinlock is held */
 
	init_completion (&dev->write_finished);
 
	atomic_set (&dev->write_busy, 1);
 
	retval = usb_submit_urb(dev->write_urb, GFP_KERNEL);
 
	if (retval) {
 
		atomic_set (&dev->write_busy, 0);
 
		err("%s - failed submitting write urb, error %d",
 
		    __FUNCTION__, retval);
 
	} else {
 
		retval = bytes_written;
 
	}
 

	
 
exit:
 
	/* unlock the device */
 
	up (&dev->sem);
 

	
 
	return retval;
 
}
 

	
 

	
 
/**
 
 */
 
static int dmx_usb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 
static int dmx_usb_ioctl (struct file *file, unsigned int cmd, unsigned long arg)
 
{
 
	struct dmx_usb_device *dev;
 

	
 
	lock_kernel(); // this was originally getting the Big Kernel
 
	// Lock. I don't know if that was needed, but I don't want to
 
	// destabilize anything as I move to unlocked_ioctl
 

	
 
	dev = (struct dmx_usb_device *)file->private_data;
 

	
 
	/* lock this object */
 
	down (&dev->sem);
 

	
 
	/* verify that the device wasn't unplugged */
 
	if (!dev->present) {
 
		up (&dev->sem);
 
		unlock_kernel();
 
		return -ENODEV;
 
	}
 

	
 
	dbg("%s - minor %d, cmd 0x%.4x, arg %ld", __FUNCTION__,
 
	    dev->minor, cmd, arg);
 

	
 
	/* fill in your device specific stuff here */
 

	
 
	/* unlock the device */
 
	up (&dev->sem);
 

	
 
	unlock_kernel();
 
	/* return that we did not understand this ioctl call */
 
	return -ENOTTY;
 
}
 

	
 

	
 
/**
 
 */
 
static void dmx_usb_write_bulk_callback (struct urb *urb, struct pt_regs *regs)
 
{
 
	struct dmx_usb_device *dev = (struct dmx_usb_device *)urb->context;
 

	
 
	dbg("%s - minor %d", __FUNCTION__, dev->minor);
 

	
 
	/* sync/async unlink faults aren't errors */
 
	if (urb->status && !(urb->status == -ENOENT ||
 
				urb->status == -ECONNRESET)) {
 
		dbg("%s - nonzero write bulk status received: %d",
 
		    __FUNCTION__, urb->status);
 
	}
 

	
 
	/* notify anyone waiting that the write has finished */
 
	atomic_set (&dev->write_busy, 0);
 
	complete (&dev->write_finished);
 
}
0 comments (0 inline, 0 general)