aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/frontier/alphatrack.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/frontier/alphatrack.c')
-rw-r--r--drivers/staging/frontier/alphatrack.c195
1 files changed, 74 insertions, 121 deletions
diff --git a/drivers/staging/frontier/alphatrack.c b/drivers/staging/frontier/alphatrack.c
index bcba17eae92..226b2316310 100644
--- a/drivers/staging/frontier/alphatrack.c
+++ b/drivers/staging/frontier/alphatrack.c
@@ -24,22 +24,21 @@
* raw interrupt reports.
*/
-/* Note: this currently uses a dumb ringbuffer for reads and writes.
+/*
+ * Note: this currently uses a dumb ringbuffer for reads and writes.
* A more optimal driver would cache and kill off outstanding urbs that are
* now invalid, and ignore ones that already were in the queue but valid
* as we only have 30 commands for the alphatrack. In particular this is
* key for getting lights to flash in time as otherwise many commands
* can be buffered up before the light change makes it to the interface.
-*/
+ */
#include <linux/kernel.h>
#include <linux/errno.h>
-#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/mutex.h>
-#include <linux/version.h>
#include <linux/uaccess.h>
#include <linux/input.h>
@@ -59,7 +58,7 @@
#endif
/* table of devices that work with this driver */
-static struct usb_device_id usb_alphatrack_table[] = {
+static const struct usb_device_id usb_alphatrack_table[] = {
{USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
{} /* Terminating entry */
};
@@ -90,7 +89,7 @@ static int debug = ALPHATRACK_DEBUG;
/* Use our own dbg macro */
#define dbg_info(dev, format, arg...) do \
- { if (debug) dev_info(dev , format , ## arg); } while (0)
+ { if (debug) dev_info(dev , format , ## arg); } while (0)
#define alphatrack_ocmd_info(dev, cmd, format, arg...)
@@ -101,7 +100,8 @@ static int debug = ALPHATRACK_DEBUG;
module_param(debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Debug enabled or not");
-/* All interrupt in transfers are collected in a ring buffer to
+/*
+ * All interrupt in transfers are collected in a ring buffer to
* avoid racing conditions and get better performance of the driver.
*/
@@ -110,8 +110,7 @@ static int ring_buffer_size = RING_BUFFER_SIZE;
module_param(ring_buffer_size, int, S_IRUGO);
MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size");
-/* The write_buffer can one day contain more than one interrupt out transfer.
- */
+/* The write_buffer can one day contain more than one interrupt out transfer.*/
static int write_buffer_size = WRITE_BUFFER_SIZE;
module_param(write_buffer_size, int, S_IRUGO);
@@ -135,7 +134,7 @@ MODULE_PARM_DESC(min_interrupt_out_interval,
/* Structure to hold all of our device specific stuff */
struct usb_alphatrack {
- struct semaphore sem; /* locks this structure */
+ struct mutex mtx; /* locks this structure */
struct usb_interface *intf; /* save off the usb interface pointer */
int open_count; /* number of times this port has been opened */
@@ -200,9 +199,7 @@ static void usb_alphatrack_abort_transfers(struct usb_alphatrack *dev)
usb_kill_urb(dev->interrupt_out_urb);
}
-/**
- * usb_alphatrack_delete
- */
+/** usb_alphatrack_delete */
static void usb_alphatrack_delete(struct usb_alphatrack *dev)
{
usb_alphatrack_abort_transfers(dev);
@@ -211,12 +208,12 @@ static void usb_alphatrack_delete(struct usb_alphatrack *dev)
kfree(dev->ring_buffer);
kfree(dev->interrupt_in_buffer);
kfree(dev->interrupt_out_buffer);
- kfree(dev); /* fixme oldi_buffer */
+ kfree(dev->oldi_buffer);
+ kfree(dev->write_buffer);
+ kfree(dev);
}
-/**
- * usb_alphatrack_interrupt_in_callback
- */
+/** usb_alphatrack_interrupt_in_callback */
static void usb_alphatrack_interrupt_in_callback(struct urb *urb)
{
@@ -238,8 +235,8 @@ static void usb_alphatrack_interrupt_in_callback(struct urb *urb)
if (urb->actual_length != INPUT_CMD_SIZE) {
dev_warn(&dev->intf->dev,
- "Urb length was %d bytes!!"
- "Do something intelligent \n", urb->actual_length);
+ "Urb length was %d bytes!! Do something intelligent\n",
+ urb->actual_length);
} else {
alphatrack_ocmd_info(&dev->intf->dev,
&(*dev->ring_buffer)[dev->ring_tail].cmd,
@@ -297,9 +294,7 @@ exit:
wake_up_interruptible(&dev->read_wait);
}
-/**
- * usb_alphatrack_interrupt_out_callback
- */
+/** usb_alphatrack_interrupt_out_callback */
static void usb_alphatrack_interrupt_out_callback(struct urb *urb)
{
struct usb_alphatrack *dev = urb->context;
@@ -316,9 +311,7 @@ static void usb_alphatrack_interrupt_out_callback(struct urb *urb)
wake_up_interruptible(&dev->write_wait);
}
-/**
- * usb_alphatrack_open
- */
+/** usb_alphatrack_open */
static int usb_alphatrack_open(struct inode *inode, struct file *file)
{
struct usb_alphatrack *dev;
@@ -334,8 +327,8 @@ static int usb_alphatrack_open(struct inode *inode, struct file *file)
interface = usb_find_interface(&usb_alphatrack_driver, subminor);
if (!interface) {
- err("%s - error, can't find device for minor %d\n",
- __func__, subminor);
+ pr_err("%s - error, can't find device for minor %d\n",
+ __func__, subminor);
retval = -ENODEV;
goto unlock_disconnect_exit;
}
@@ -348,7 +341,7 @@ static int usb_alphatrack_open(struct inode *inode, struct file *file)
}
/* lock this device */
- if (down_interruptible(&dev->sem)) {
+ if (mutex_lock_interruptible(&dev->mtx)) {
retval = -ERESTARTSYS;
goto unlock_disconnect_exit;
}
@@ -391,7 +384,7 @@ static int usb_alphatrack_open(struct inode *inode, struct file *file)
file->private_data = dev;
unlock_exit:
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
unlock_disconnect_exit:
mutex_unlock(&disconnect_mutex);
@@ -399,9 +392,7 @@ unlock_disconnect_exit:
return retval;
}
-/**
- * usb_alphatrack_release
- */
+/** usb_alphatrack_release */
static int usb_alphatrack_release(struct inode *inode, struct file *file)
{
struct usb_alphatrack *dev;
@@ -414,7 +405,7 @@ static int usb_alphatrack_release(struct inode *inode, struct file *file)
goto exit;
}
- if (down_interruptible(&dev->sem)) {
+ if (mutex_lock_interruptible(&dev->mtx)) {
retval = -ERESTARTSYS;
goto exit;
}
@@ -426,7 +417,7 @@ static int usb_alphatrack_release(struct inode *inode, struct file *file)
if (dev->intf == NULL) {
/* the device was unplugged before the file was released */
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
/* unlock here as usb_alphatrack_delete frees dev */
usb_alphatrack_delete(dev);
retval = -ENODEV;
@@ -442,16 +433,14 @@ static int usb_alphatrack_release(struct inode *inode, struct file *file)
dev->open_count = 0;
unlock_exit:
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
exit:
return retval;
}
-/**
- * usb_alphatrack_poll
- */
-static unsigned int usb_alphatrack_poll(struct file *file, poll_table * wait)
+/** usb_alphatrack_poll */
+static unsigned int usb_alphatrack_poll(struct file *file, poll_table *wait)
{
struct usb_alphatrack *dev;
unsigned int mask = 0;
@@ -469,9 +458,7 @@ static unsigned int usb_alphatrack_poll(struct file *file, poll_table * wait)
return mask;
}
-/**
- * usb_alphatrack_read
- */
+/** usb_alphatrack_read */
static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer,
size_t count, loff_t *ppos)
{
@@ -487,7 +474,7 @@ static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer,
goto exit;
/* lock this object */
- if (down_interruptible(&dev->sem)) {
+ if (mutex_lock_interruptible(&dev->mtx)) {
retval = -ERESTARTSYS;
goto exit;
}
@@ -495,7 +482,8 @@ static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer,
/* verify that the device wasn't unplugged */
if (dev->intf == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d\n", retval);
+ pr_err("%s: No device or device unplugged %d\n",
+ __func__, retval);
goto unlock_exit;
}
@@ -533,15 +521,13 @@ static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer,
unlock_exit:
/* unlock the device */
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
exit:
return retval;
}
-/**
- * usb_alphatrack_write
- */
+/** usb_alphatrack_write */
static ssize_t usb_alphatrack_write(struct file *file,
const char __user *buffer, size_t count,
loff_t *ppos)
@@ -557,7 +543,7 @@ static ssize_t usb_alphatrack_write(struct file *file,
goto exit;
/* lock this object */
- if (down_interruptible(&dev->sem)) {
+ if (mutex_lock_interruptible(&dev->mtx)) {
retval = -ERESTARTSYS;
goto exit;
}
@@ -565,7 +551,8 @@ static ssize_t usb_alphatrack_write(struct file *file,
/* verify that the device wasn't unplugged */
if (dev->intf == NULL) {
retval = -ENODEV;
- err("No device or device unplugged %d\n", retval);
+ pr_err("%s: No device or device unplugged %d\n",
+ __func__, retval);
goto unlock_exit;
}
@@ -600,7 +587,7 @@ static ssize_t usb_alphatrack_write(struct file *file,
}
if (dev->interrupt_out_endpoint == NULL) {
- err("Endpoint should not be be null! \n");
+ dev_err(&dev->intf->dev, "Endpoint should not be null!\n");
goto unlock_exit;
}
@@ -620,7 +607,8 @@ static ssize_t usb_alphatrack_write(struct file *file,
retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
if (retval) {
dev->interrupt_out_busy = 0;
- err("Couldn't submit interrupt_out_urb %d\n", retval);
+ dev_err(&dev->intf->dev,
+ "Couldn't submit interrupt_out_urb %d\n", retval);
atomic_dec(&dev->writes_pending);
goto unlock_exit;
}
@@ -628,7 +616,7 @@ static ssize_t usb_alphatrack_write(struct file *file,
unlock_exit:
/* unlock the device */
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
exit:
return retval;
@@ -642,6 +630,7 @@ static const struct file_operations usb_alphatrack_fops = {
.open = usb_alphatrack_open,
.release = usb_alphatrack_release,
.poll = usb_alphatrack_poll,
+ .llseek = no_llseek,
};
/*
@@ -672,14 +661,13 @@ static int usb_alphatrack_probe(struct usb_interface *intf,
int true_size;
int retval = -ENOMEM;
- /* allocate memory for our device state and intialize it */
+ /* allocate memory for our device state and initialize it */
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (dev == NULL) {
- dev_err(&intf->dev, "Out of memory\n");
+ if (dev == NULL)
goto exit;
- }
- init_MUTEX(&dev->sem);
+
+ mutex_init(&dev->mtx);
dev->intf = intf;
init_waitqueue_head(&dev->read_wait);
init_waitqueue_head(&dev->write_wait);
@@ -702,8 +690,7 @@ static int usb_alphatrack_probe(struct usb_interface *intf,
}
if (dev->interrupt_out_endpoint == NULL)
dev_warn(&intf->dev,
- "Interrupt out endpoint not found"
- "(using control endpoint instead)\n");
+ "Interrupt out endpoint not found (using control endpoint instead)\n");
dev->interrupt_in_endpoint_size =
le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
@@ -716,30 +703,25 @@ static int usb_alphatrack_probe(struct usb_interface *intf,
true_size = min(ring_buffer_size, RING_BUFFER_SIZE);
- /* FIXME - there are more usb_alloc routines for dma correctness.
- Needed? */
- dev->ring_buffer =
- kmalloc((true_size * sizeof(struct alphatrack_icmd)), GFP_KERNEL);
-
- if (!dev->ring_buffer) {
- dev_err(&intf->dev,
- "Couldn't allocate input ring_buffer of size %d\n",
- true_size);
+ /*
+ * FIXME - there are more usb_alloc routines for dma correctness.
+ * Needed?
+ */
+ dev->ring_buffer = kmalloc_array(true_size,
+ sizeof(struct alphatrack_icmd),
+ GFP_KERNEL);
+ if (!dev->ring_buffer)
goto error;
- }
-
- dev->interrupt_in_buffer =
- kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
- if (!dev->interrupt_in_buffer) {
- dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n");
+ dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size,
+ GFP_KERNEL);
+ if (!dev->interrupt_in_buffer)
goto error;
- }
+
dev->oldi_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
- if (!dev->oldi_buffer) {
- dev_err(&intf->dev, "Couldn't allocate old buffer\n");
+ if (!dev->oldi_buffer)
goto error;
- }
+
dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->interrupt_in_urb) {
dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
@@ -761,20 +743,17 @@ static int usb_alphatrack_probe(struct usb_interface *intf,
true_size = min(write_buffer_size, WRITE_BUFFER_SIZE);
dev->interrupt_out_buffer =
- kmalloc(true_size * dev->interrupt_out_endpoint_size, GFP_KERNEL);
-
- if (!dev->interrupt_out_buffer) {
- dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n");
+ kmalloc_array(true_size,
+ dev->interrupt_out_endpoint_size,
+ GFP_KERNEL);
+ if (!dev->interrupt_out_buffer)
goto error;
- }
-
- dev->write_buffer =
- kmalloc(sizeof(struct alphatrack_ocmd) * true_size, GFP_KERNEL);
- if (!dev->write_buffer) {
- dev_err(&intf->dev, "Couldn't allocate write_buffer \n");
+ dev->write_buffer = kmalloc_array(true_size,
+ sizeof(struct alphatrack_ocmd),
+ GFP_KERNEL);
+ if (!dev->write_buffer)
goto error;
- }
dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!dev->interrupt_out_urb) {
@@ -836,7 +815,7 @@ static void usb_alphatrack_disconnect(struct usb_interface *intf)
dev = usb_get_intfdata(intf);
usb_set_intfdata(intf, NULL);
- down(&dev->sem);
+ mutex_lock(&dev->mtx);
minor = intf->minor;
@@ -845,14 +824,14 @@ static void usb_alphatrack_disconnect(struct usb_interface *intf)
/* if the device is not opened, then we clean up right now */
if (!dev->open_count) {
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
usb_alphatrack_delete(dev);
} else {
+ atomic_set(&dev->writes_pending, 0);
dev->intf = NULL;
- up(&dev->sem);
+ mutex_unlock(&dev->mtx);
}
- atomic_set(&dev->writes_pending, 0);
mutex_unlock(&disconnect_mutex);
dev_info(&intf->dev, "Alphatrack Surface #%d now disconnected\n",
@@ -867,30 +846,4 @@ static struct usb_driver usb_alphatrack_driver = {
.id_table = usb_alphatrack_table,
};
-/**
- * usb_alphatrack_init
- */
-static int __init usb_alphatrack_init(void)
-{
- int retval;
-
- /* register this driver with the USB subsystem */
- retval = usb_register(&usb_alphatrack_driver);
- if (retval)
- err("usb_register failed for the " __FILE__
- " driver. Error number %d\n", retval);
-
- return retval;
-}
-
-/**
- * usb_alphatrack_exit
- */
-static void __exit usb_alphatrack_exit(void)
-{
- /* deregister this driver with the USB subsystem */
- usb_deregister(&usb_alphatrack_driver);
-}
-
-module_init(usb_alphatrack_init);
-module_exit(usb_alphatrack_exit);
+module_usb_driver(usb_alphatrack_driver);