Hi Greg,

here is a patch that adds three URB setup helpers that will allocate the
transfer buffer using kmalloc() and set the new URB_FREE_BUFFER flage to
make it free together with the URB. Please apply.

Regards

Marcel

USB: Introduce usb_setup_{control,bulk,int}_urb helpers

This patch adds usb_setup_{control,bulk,int}_urb helpers that will
allocate the transfer buffer and set URB_FREE_BUFFER flag for freeing
it when the reference count of an URB goes down to zero. This allows
an easy and simple construction of one-shot URBs.

Signed-off-by: Marcel Holtmann <[EMAIL PROTECTED]>

---
commit 2a3deb451a56722f4943f03e1a2b44a85f3b8db5
tree 21ce3f7992f969dfeb8ee8c9c9adce1c5d9d35d7
parent 189548642c5962e60c3667bdb3a703fe0bed12a6
author Marcel Holtmann <[EMAIL PROTECTED]> Tue, 26 Jun 2007 03:02:33 +0200
committer Marcel Holtmann <[EMAIL PROTECTED]> Tue, 26 Jun 2007 03:02:33 +0200

 drivers/usb/core/urb.c |  106 ++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/usb.h    |   15 +++++++
 2 files changed, 121 insertions(+), 0 deletions(-)

diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c
index 94ea972..fc00e49 100644
--- a/drivers/usb/core/urb.c
+++ b/drivers/usb/core/urb.c
@@ -478,6 +478,109 @@ void usb_kill_urb(struct urb *urb)
        spin_unlock_irq(&urb->lock);
 }
 
+/**
+ * usb_setup_control_urb - macro to help initializes a control urb
+ * @urb: pointer to the urb to initialize.
+ * @dev: pointer to the struct usb_device for this urb.
+ * @pipe: the endpoint pipe
+ * @setup_packet: pointer to the setup_packet buffer
+ * @size: requested buffer size
+ * @mem_flags: affect whether allocation may block
+ * @complete_fn: pointer to the usb_complete_t function
+ * @context: what to set the urb context to.
+ *
+ * Initializes a control urb with the proper information needed to submit
+ * it to a device and allocate transfer buffer for it.
+ */
+int usb_setup_control_urb(struct urb *urb, struct usb_device *dev,
+                               unsigned int pipe,
+                               unsigned char *setup_packet,
+                               size_t size, gfp_t mem_flags,
+                               usb_complete_t complete_fn, void *context)
+{
+       void *buffer;
+
+       buffer = kmalloc(size, mem_flags);
+       if (!buffer)
+               return -ENOMEM;
+
+       usb_fill_control_urb(urb, dev, pipe, setup_packet,
+                                       buffer, size, complete_fn, context);
+
+       urb->transfer_flags |= URB_FREE_BUFFER;
+
+       return 0;
+}
+
+/**
+ * usb_setup_bulk_urb - macro to help initialize a bulk urb
+ * @urb: pointer to the urb to initialize.
+ * @dev: pointer to the struct usb_device for this urb.
+ * @pipe: the endpoint pipe
+ * @size: requested buffer size
+ * @mem_flags: affect whether allocation may block
+ * @complete_fn: pointer to the usb_complete_t function
+ * @context: what to set the urb context to.
+ *
+ * Initializes a bulk urb with the proper information needed to submit it
+ * to a device and allocate transfer buffer for it.
+ */
+int usb_setup_bulk_urb(struct urb *urb, struct usb_device *dev,
+                               unsigned int pipe,
+                               size_t size, gfp_t mem_flags,
+                               usb_complete_t complete_fn, void *context)
+{
+       void *buffer;
+
+       buffer = kmalloc(size, mem_flags);
+       if (!buffer)
+               return -ENOMEM;
+
+       usb_fill_bulk_urb(urb, dev, pipe, buffer, size, complete_fn, context);
+
+       urb->transfer_flags |= URB_FREE_BUFFER;
+
+       return 0;
+}
+
+/**
+ * usb_setup_int_urb - macro to help initialize a interrupt urb
+ * @urb: pointer to the urb to initialize.
+ * @dev: pointer to the struct usb_device for this urb.
+ * @pipe: the endpoint pipe
+ * @size: requested buffer size
+ * @mem_flags: affect whether allocation may block
+ * @complete_fn: pointer to the usb_complete_t function
+ * @context: what to set the urb context to.
+ * @interval: what to set the urb interval to, encoded like
+ *     the endpoint descriptor's bInterval value.
+ *
+ * Initializes a interrupt urb with the proper information needed to submit
+ * it to a device and allocate transfer buffer for it.
+ * Note that high speed interrupt endpoints use a logarithmic encoding of
+ * the endpoint interval, and express polling intervals in microframes
+ * (eight per millisecond) rather than in frames (one per millisecond).
+ */
+int usb_setup_int_urb(struct urb *urb, struct usb_device *dev,
+                               unsigned int pipe,
+                               size_t size, gfp_t mem_flags,
+                               usb_complete_t complete_fn, void *context,
+                               int interval)
+{
+       void *buffer;
+
+       buffer = kmalloc(size, mem_flags);
+       if (!buffer)
+               return -ENOMEM;
+
+       usb_fill_int_urb(urb, dev, pipe, buffer, size,
+                                       complete_fn, context, interval);
+
+       urb->transfer_flags |= URB_FREE_BUFFER;
+
+       return 0;
+}
+
 EXPORT_SYMBOL(usb_init_urb);
 EXPORT_SYMBOL(usb_alloc_urb);
 EXPORT_SYMBOL(usb_free_urb);
@@ -485,4 +588,7 @@ EXPORT_SYMBOL(usb_get_urb);
 EXPORT_SYMBOL(usb_submit_urb);
 EXPORT_SYMBOL(usb_unlink_urb);
 EXPORT_SYMBOL(usb_kill_urb);
+EXPORT_SYMBOL(usb_setup_control_urb);
+EXPORT_SYMBOL(usb_setup_bulk_urb);
+EXPORT_SYMBOL(usb_setup_int_urb);
 
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 94bd38a..ee75560 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1271,6 +1271,21 @@ extern int usb_submit_urb(struct urb *urb, gfp_t 
mem_flags);
 extern int usb_unlink_urb(struct urb *urb);
 extern void usb_kill_urb(struct urb *urb);
 
+int usb_setup_control_urb(struct urb *urb, struct usb_device *dev,
+                               unsigned int pipe,
+                               unsigned char *setup_packet,
+                               size_t size, gfp_t mem_flags,
+                               usb_complete_t complete_fn, void *context);
+int usb_setup_bulk_urb(struct urb *urb, struct usb_device *dev,
+                               unsigned int pipe,
+                               size_t size, gfp_t mem_flags,
+                               usb_complete_t complete_fn, void *context);
+int usb_setup_int_urb(struct urb *urb, struct usb_device *dev,
+                               unsigned int pipe,
+                               size_t size, gfp_t mem_flags,
+                               usb_complete_t complete_fn, void *context,
+                               int interval);
+
 void *usb_buffer_alloc (struct usb_device *dev, size_t size,
        gfp_t mem_flags, dma_addr_t *dma);
 void usb_buffer_free (struct usb_device *dev, size_t size,
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to