#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <linux/smp_lock.h>
#include <linux/wait.h>
+#include <linux/mutex.h>
#include <linux/usb.h>
#include <linux/fs.h>
int out_count; // Bytes in the buffer
int open; // Camera device open ?
- struct semaphore io_lock; // IO -lock
+ struct mutex io_lock; // IO -lock
char in [8]; // Command Input Buffer
int in_count;
/*
* USB IRQ Handler for InputLine
*/
-static void mdc800_usb_irq (struct urb *urb, struct pt_regs *res)
+static void mdc800_usb_irq (struct urb *urb)
{
int data_received=0, wake_up;
unsigned char* b=urb->transfer_buffer;
struct mdc800_data* mdc800=urb->context;
+ int status = urb->status;
- if (urb->status >= 0)
- {
+ if (status >= 0) {
//dbg ("%i %i %i %i %i %i %i %i \n",b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7]);
||
((mdc800->camera_request_ready == 3) && (mdc800->camera_busy))
||
- (urb->status < 0)
+ (status < 0)
);
if (wake_up)
if (mdc800->camera_request_ready>0)
{
mdc800->camera_request_ready=0;
- err ("timeout waiting for camera.");
+ dev_err(&mdc800->dev->dev, "timeout waiting for camera.\n");
return -1;
}
if (mdc800->state == NOT_CONNECTED)
{
- warn ("Camera gets disconnected during waiting for irq.");
+ printk(KERN_WARNING "mdc800: Camera gets disconnected "
+ "during waiting for irq.\n");
mdc800->camera_request_ready=0;
return -2;
}
/*
* The write_urb callback function
*/
-static void mdc800_usb_write_notify (struct urb *urb, struct pt_regs *res)
+static void mdc800_usb_write_notify (struct urb *urb)
{
struct mdc800_data* mdc800=urb->context;
+ int status = urb->status;
- if (urb->status != 0)
- {
- err ("writing command fails (status=%i)", urb->status);
- }
+ if (status != 0)
+ dev_err(&mdc800->dev->dev,
+ "writing command fails (status=%i)\n", status);
else
- {
mdc800->state=READY;
- }
mdc800->written = 1;
wake_up (&mdc800->write_wait);
}
/*
* The download_urb callback function
*/
-static void mdc800_usb_download_notify (struct urb *urb, struct pt_regs *res)
+static void mdc800_usb_download_notify (struct urb *urb)
{
struct mdc800_data* mdc800=urb->context;
+ int status = urb->status;
- if (urb->status == 0)
- {
+ if (status == 0) {
/* Fill output buffer with these data */
memcpy (mdc800->out, urb->transfer_buffer, 64);
mdc800->out_count=64;
{
mdc800->state=READY;
}
- }
- else
- {
- err ("request bytes fails (status:%i)", urb->status);
+ } else {
+ dev_err(&mdc800->dev->dev,
+ "request bytes fails (status:%i)\n", status);
}
mdc800->downloaded = 1;
wake_up (&mdc800->download_wait);
***************************************************************************/
static struct usb_driver mdc800_usb_driver;
-static struct file_operations mdc800_device_ops;
+static const struct file_operations mdc800_device_ops;
static struct usb_class_driver mdc800_class = {
- .name = "usb/mdc800%d",
+ .name = "mdc800%d",
.fops = &mdc800_device_ops,
- .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,
.minor_base = MDC800_DEVICE_MINOR_BASE,
};
if (mdc800->dev != NULL)
{
- warn ("only one Mustek MDC800 is supported.");
+ dev_warn(&intf->dev, "only one Mustek MDC800 is supported.\n");
return -ENODEV;
}
if (dev->descriptor.bNumConfigurations != 1)
{
- err ("probe fails -> wrong Number of Configuration");
+ dev_err(&intf->dev,
+ "probe fails -> wrong Number of Configuration\n");
return -ENODEV;
}
intf_desc = intf->cur_altsetting;
|| ( intf_desc->desc.bNumEndpoints != 4)
)
{
- err ("probe fails -> wrong Interface");
+ dev_err(&intf->dev, "probe fails -> wrong Interface\n");
return -ENODEV;
}
{
irq_interval=intf_desc->endpoint [j].desc.bInterval;
}
-
- continue;
}
}
if (mdc800->endpoint[i] == -1)
{
- err ("probe fails -> Wrong Endpoints.");
+ dev_err(&intf->dev, "probe fails -> Wrong Endpoints.\n");
return -ENODEV;
}
}
- info ("Found Mustek MDC800 on USB.");
+ dev_info(&intf->dev, "Found Mustek MDC800 on USB.\n");
- down (&mdc800->io_lock);
+ mutex_lock(&mdc800->io_lock);
retval = usb_register_dev(intf, &mdc800_class);
if (retval) {
- err ("Not able to get a minor for this device.");
+ dev_err(&intf->dev, "Not able to get a minor for this device.\n");
+ mutex_unlock(&mdc800->io_lock);
return -ENODEV;
}
mdc800->state=READY;
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
usb_set_intfdata(intf, mdc800);
return 0;
usb_deregister_dev(intf, &mdc800_class);
+ /* must be under lock to make sure no URB
+ is submitted after usb_kill_urb() */
+ mutex_lock(&mdc800->io_lock);
mdc800->state=NOT_CONNECTED;
usb_kill_urb(mdc800->irq_urb);
usb_kill_urb(mdc800->write_urb);
usb_kill_urb(mdc800->download_urb);
+ mutex_unlock(&mdc800->io_lock);
mdc800->dev = NULL;
usb_set_intfdata(intf, NULL);
}
- info ("Mustek MDC800 disconnected from USB.");
+ dev_info(&intf->dev, "Mustek MDC800 disconnected from USB.\n");
}
int retval=0;
int errn=0;
- down (&mdc800->io_lock);
+ mutex_lock(&mdc800->io_lock);
if (mdc800->state == NOT_CONNECTED)
{
retval=0;
mdc800->irq_urb->dev = mdc800->dev;
- if (usb_submit_urb (mdc800->irq_urb, GFP_KERNEL))
- {
- err ("request USB irq fails (submit_retval=%i urb_status=%i).",retval, mdc800->irq_urb->status);
+ retval = usb_submit_urb (mdc800->irq_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&mdc800->dev->dev,
+ "request USB irq fails (submit_retval=%i).\n", retval);
errn = -EIO;
goto error_out;
}
dbg ("Mustek MDC800 device opened.");
error_out:
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return errn;
}
int retval=0;
dbg ("Mustek MDC800 device closed.");
- down (&mdc800->io_lock);
+ mutex_lock(&mdc800->io_lock);
if (mdc800->open && (mdc800->state != NOT_CONNECTED))
{
usb_kill_urb(mdc800->irq_urb);
retval=-EIO;
}
- up(&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return retval;
}
{
size_t left=len, sts=len; /* single transfer size */
char __user *ptr = buf;
+ int retval;
- down (&mdc800->io_lock);
+ mutex_lock(&mdc800->io_lock);
if (mdc800->state == NOT_CONNECTED)
{
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EBUSY;
}
if (mdc800->state == WORKING)
{
- warn ("Illegal State \"working\" reached during read ?!");
- up (&mdc800->io_lock);
+ printk(KERN_WARNING "mdc800: Illegal State \"working\""
+ "reached during read ?!\n");
+ mutex_unlock(&mdc800->io_lock);
return -EBUSY;
}
if (!mdc800->open)
{
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EBUSY;
}
{
if (signal_pending (current))
{
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EINTR;
}
/* Download -> Request new bytes */
mdc800->download_urb->dev = mdc800->dev;
- if (usb_submit_urb (mdc800->download_urb, GFP_KERNEL))
- {
- err ("Can't submit download urb (status=%i)",mdc800->download_urb->status);
- up (&mdc800->io_lock);
+ retval = usb_submit_urb (mdc800->download_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&mdc800->dev->dev,
+ "Can't submit download urb "
+ "(retval=%i)\n", retval);
+ mutex_unlock(&mdc800->io_lock);
return len-left;
}
wait_event_timeout(mdc800->download_wait, mdc800->downloaded,
mdc800->downloaded = 0;
if (mdc800->download_urb->status != 0)
{
- err ("request download-bytes fails (status=%i)",mdc800->download_urb->status);
- up (&mdc800->io_lock);
+ dev_err(&mdc800->dev->dev,
+ "request download-bytes fails "
+ "(status=%i)\n",
+ mdc800->download_urb->status);
+ mutex_unlock(&mdc800->io_lock);
return len-left;
}
}
else
{
/* No more bytes -> that's an error*/
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EIO;
}
}
/* Copy Bytes */
if (copy_to_user(ptr, &mdc800->out [mdc800->out_ptr],
sts)) {
- up(&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EFAULT;
}
ptr+=sts;
}
}
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return len-left;
}
static ssize_t mdc800_device_write (struct file *file, const char __user *buf, size_t len, loff_t *pos)
{
size_t i=0;
+ int retval;
- down (&mdc800->io_lock);
+ mutex_lock(&mdc800->io_lock);
if (mdc800->state != READY)
{
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EBUSY;
}
if (!mdc800->open )
{
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EBUSY;
}
unsigned char c;
if (signal_pending (current))
{
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EINTR;
}
if(get_user(c, buf+i))
{
- up(&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EFAULT;
}
}
else
{
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EIO;
}
if (mdc800_usb_waitForIRQ (0,TO_GET_READY))
{
- err ("Camera didn't get ready.\n");
- up (&mdc800->io_lock);
+ dev_err(&mdc800->dev->dev,
+ "Camera didn't get ready.\n");
+ mutex_unlock(&mdc800->io_lock);
return -EIO;
}
mdc800->state=WORKING;
memcpy (mdc800->write_urb->transfer_buffer, mdc800->in,8);
mdc800->write_urb->dev = mdc800->dev;
- if (usb_submit_urb (mdc800->write_urb, GFP_KERNEL))
- {
- err ("submitting write urb fails (status=%i)", mdc800->write_urb->status);
- up (&mdc800->io_lock);
+ retval = usb_submit_urb (mdc800->write_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&mdc800->dev->dev,
+ "submitting write urb fails "
+ "(retval=%i)\n", retval);
+ mutex_unlock(&mdc800->io_lock);
return -EIO;
}
wait_event_timeout(mdc800->write_wait, mdc800->written, TO_WRITE_GET_READY*HZ/1000);
if (mdc800->state == WORKING)
{
usb_kill_urb(mdc800->write_urb);
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EIO;
}
case 0x3e: /* Take shot in Fine Mode (WCam Mode) */
if (mdc800->pic_len < 0)
{
- err ("call 0x07 before 0x05,0x3e");
+ dev_err(&mdc800->dev->dev,
+ "call 0x07 before "
+ "0x05,0x3e\n");
mdc800->state=READY;
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return -EIO;
}
mdc800->pic_len=-1;
if (mdc800_usb_waitForIRQ (1,TO_READ_FROM_IRQ))
{
- err ("requesting answer from irq fails");
- up (&mdc800->io_lock);
+ dev_err(&mdc800->dev->dev, "requesting answer from irq fails\n");
+ mutex_unlock(&mdc800->io_lock);
return -EIO;
}
{
if (mdc800_usb_waitForIRQ (0,TO_DEFAULT_COMMAND))
{
- err ("Command Timeout.");
- up (&mdc800->io_lock);
+ dev_err(&mdc800->dev->dev, "Command Timeout.\n");
+ mutex_unlock(&mdc800->io_lock);
return -EIO;
}
}
}
i++;
}
- up (&mdc800->io_lock);
+ mutex_unlock(&mdc800->io_lock);
return i;
}
****************************************************************************/
/* File Operations of this drivers */
-static struct file_operations mdc800_device_ops =
+static const struct file_operations mdc800_device_ops =
{
.owner = THIS_MODULE,
.read = mdc800_device_read,
*/
static struct usb_driver mdc800_usb_driver =
{
- .owner = THIS_MODULE,
.name = "mdc800",
.probe = mdc800_usb_probe,
.disconnect = mdc800_usb_disconnect,
Init and Cleanup this driver (Main Functions)
*************************************************************************/
-#define try(A) if (!(A)) goto cleanup_on_fail;
-
static int __init usb_mdc800_init (void)
{
int retval = -ENODEV;
/* Allocate Memory */
- try (mdc800=kmalloc (sizeof (struct mdc800_data), GFP_KERNEL));
+ mdc800=kzalloc (sizeof (struct mdc800_data), GFP_KERNEL);
+ if (!mdc800)
+ goto cleanup_on_fail;
- memset(mdc800, 0, sizeof(struct mdc800_data));
mdc800->dev = NULL;
- mdc800->open=0;
mdc800->state=NOT_CONNECTED;
- init_MUTEX (&mdc800->io_lock);
+ mutex_init (&mdc800->io_lock);
init_waitqueue_head (&mdc800->irq_wait);
init_waitqueue_head (&mdc800->write_wait);
mdc800->downloaded = 0;
mdc800->written = 0;
- try (mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL));
- try (mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL));
- try (mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL));
+ mdc800->irq_urb_buffer=kmalloc (8, GFP_KERNEL);
+ if (!mdc800->irq_urb_buffer)
+ goto cleanup_on_fail;
+ mdc800->write_urb_buffer=kmalloc (8, GFP_KERNEL);
+ if (!mdc800->write_urb_buffer)
+ goto cleanup_on_fail;
+ mdc800->download_urb_buffer=kmalloc (64, GFP_KERNEL);
+ if (!mdc800->download_urb_buffer)
+ goto cleanup_on_fail;
- try (mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL));
- try (mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL));
- try (mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL));
+ mdc800->irq_urb=usb_alloc_urb (0, GFP_KERNEL);
+ if (!mdc800->irq_urb)
+ goto cleanup_on_fail;
+ mdc800->download_urb=usb_alloc_urb (0, GFP_KERNEL);
+ if (!mdc800->download_urb)
+ goto cleanup_on_fail;
+ mdc800->write_urb=usb_alloc_urb (0, GFP_KERNEL);
+ if (!mdc800->write_urb)
+ goto cleanup_on_fail;
/* Register the driver */
retval = usb_register(&mdc800_usb_driver);
if (retval)
goto cleanup_on_fail;
- info (DRIVER_VERSION ":" DRIVER_DESC);
+ printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
+ DRIVER_DESC "\n");
return 0;
if (mdc800 != NULL)
{
- err ("can't alloc memory!");
+ printk(KERN_ERR "mdc800: can't alloc memory!\n");
kfree(mdc800->download_urb_buffer);
kfree(mdc800->write_urb_buffer);