/*
* message.c - synchronous message handling
*/
#include <linux/config.h>
#include <linux/pci.h> /* for scatterlist macros */
#include <linux/usb.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/timer.h>
#include <linux/ctype.h>
#include <linux/device.h>
#include <asm/byteorder.h>
#include <asm/scatterlist.h>
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
{
complete((struct completion *)urb->context);
}
static void timeout_kill(unsigned long data)
{
struct urb *urb = (struct urb *) data;
usb_unlink_urb(urb);
}
// Starts urb and waits for completion or timeout
// note that this call is NOT interruptible, while
// many device driver i/o requests should be interruptible
static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
{
struct completion done;
struct timer_list timer;
int status;
init_completion(&done);
urb->context = &done;
urb->actual_length = 0;
status = usb_submit_urb(urb, GFP_NOIO);
if (status == 0) {
if (timeout > 0) {
init_timer(&timer);
timer.expires = jiffies + msecs_to_jiffies(timeout);
timer.data = (unsigned long)urb;
timer.function = timeout_kill;
/* grr. timeout _should_ include submit delays. */
add_timer(&timer);
}
wait_for_completion(&done);
status = urb->status;
/* note: HCDs return ETIMEDOUT for other reasons too */
if (status == -ECONNRESET) {
dev_dbg(&urb->dev->dev,
"%s timed out on ep%d%s len=%d/%d\n",
current->comm,
usb_pipeendpoint(urb->pipe),
usb_pipein(urb->pipe) ? "in" : "out",
urb->actual_length,
urb->transfer_buffer_length
);
if (urb->actual_length > 0)
status = 0;
else
status = -ETIMEDOUT;
}
if (timeout > 0)
del_timer_sync(&timer);
}
if (actual_length)
*actual_length = urb->actual_length;
usb_free_urb(urb);
return status;
}
/*-------------------------------------------------------------------*/
// returns status (negative) or length (positive)
static int usb_internal_control_msg(struct usb_device *usb_dev,
unsigned int pipe,
struct usb_ctrlrequest *cmd,
void *data, int len, int timeout)
{
struct urb *urb;
int retv;
int length;
urb = usb_allo
|