Currently uses wait_for_completion() instead of
wait_for_completion_interruptible().
Signed-off-by: Sarah Bailey <[EMAIL PROTECTED]>
---
I've sucessfully tested it on the (one) USB device I have with bulk
endpoints, but please test.
drivers/usb/core/endpoint_fops.c | 116 +++++++++++++++++++++++++++++++++++++-
1 files changed, 114 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/core/endpoint_fops.c b/drivers/usb/core/endpoint_fops.c
index 5c85559..e7f0e97 100644
--- a/drivers/usb/core/endpoint_fops.c
+++ b/drivers/usb/core/endpoint_fops.c
@@ -1,7 +1,7 @@
/*
* drivers/usb/core/endpoint_fops.c
*
- * (C) Copyright 2006 Sarah Bailey
+ * (C) Copyright 2006,2007 Sarah Bailey
*
* Endpoint file operations
*/
@@ -9,6 +9,8 @@
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/usb.h>
+#include <linux/completion.h>
+#include <asm/uaccess.h>
#include "usb.h"
int endpoint_open(struct inode *inode, struct file *filp)
@@ -21,15 +23,123 @@ int endpoint_open(struct inode *inode, struct file *filp)
return 0;
}
+void callback(struct urb *urb)
+{
+ complete(urb->context);
+}
+
ssize_t control_read(struct file * filp, char __user *buff,
size_t count, loff_t * offp)
{
struct ep_device *ep_dev;
ep_dev = filp->private_data;
- dev_dbg(&ep_dev->dev, "%s called for %s\n", __FUNCTION__,
ep_dev->dev.bus_id);
+ dev_dbg(&ep_dev->dev, "%s called for %s\n", __FUNCTION__,
+ ep_dev->dev.bus_id);
return 0;
}
+ssize_t ep_read(struct file * filp, char __user *buff,
+ size_t count, loff_t * offp)
+{
+ struct ep_device *ep_dev;
+ char *k_buff;
+ struct urb *urb;
+ unsigned int pipe;
+ int retval = -ENOMEM;
+ DECLARE_COMPLETION_ONSTACK(completion);
+
+ ep_dev = filp->private_data;
+ dev_dbg(&ep_dev->dev, "%s called for %s\n", __FUNCTION__,
+ ep_dev->dev.bus_id);
+
+ if(!usb_endpoint_xfer_bulk(ep_dev->desc))
+ return 0;
+
+ k_buff = kmalloc(count, GFP_KERNEL);
+ if(k_buff == NULL)
+ goto exit;
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if(urb == NULL)
+ goto error_urb_alloc;
+ pipe = usb_rcvbulkpipe(ep_dev->udev, ep_dev->desc->bEndpointAddress);
+ usb_fill_bulk_urb(urb, ep_dev->udev, pipe, k_buff, count,
+ callback, &completion);
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ if(retval)
+ goto error_urb_submit;
+ wait_for_completion(&completion);
+
+ if(urb->status)
+ retval = urb->status;
+ else {
+ retval = urb->actual_length;
+ if(copy_to_user(buff, k_buff, urb->actual_length))
+ retval = -EFAULT;
+ }
+
+error_urb_submit:
+ usb_free_urb(urb);
+error_urb_alloc:
+ kfree(k_buff);
+exit:
+ return retval;
+}
+
+ssize_t ep_write(struct file * filp, const char __user *buff,
+ size_t count, loff_t * offp)
+{
+ struct ep_device *ep_dev;
+ char *k_buff;
+ struct urb *urb;
+ unsigned int pipe;
+ int retval;
+ DECLARE_COMPLETION_ONSTACK(completion);
+
+ ep_dev = filp->private_data;
+ dev_dbg(&ep_dev->dev, "%s called for %s\n", __FUNCTION__,
+ ep_dev->dev.bus_id);
+
+ if(!usb_endpoint_xfer_bulk(ep_dev->desc))
+ return 0;
+
+ k_buff = kmalloc(count, GFP_KERNEL);
+ if(k_buff == NULL) {
+ retval = -ENOMEM;
+ goto exit;
+ }
+ if(copy_from_user(k_buff, buff, count)) {
+ retval = -EFAULT;
+ goto error_copy_buff;
+ }
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if(urb == NULL) {
+ retval = -ENOMEM;
+ goto error_copy_buff;
+ }
+
+ // endpoint specific init
+ pipe = usb_sndbulkpipe(ep_dev->udev, ep_dev->desc->bEndpointAddress);
+ usb_fill_bulk_urb(urb, ep_dev->udev, pipe, k_buff, count,
+ callback, &completion);
+
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ if(retval)
+ goto error_urb_submit;
+ wait_for_completion(&completion);
+
+ if(urb->status)
+ retval = urb->status;
+ else
+ retval = urb->actual_length;
+
+error_urb_submit:
+ usb_free_urb(urb);
+error_copy_buff:
+ kfree(k_buff);
+exit:
+ return retval;
+}
+
struct file_operations usb_endpoint_control_fops = {
.owner = THIS_MODULE,
.open = endpoint_open,
@@ -39,9 +149,11 @@ struct file_operations usb_endpoint_control_fops = {
struct file_operations usb_endpoint_in_fops = {
.owner = THIS_MODULE,
.open = endpoint_open,
+ .read = ep_read,
};
struct file_operations usb_endpoint_out_fops = {
.owner = THIS_MODULE,
.open = endpoint_open,
+ .write = ep_write,
};
--
1.4.4.1
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel