text:
/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 */

#include <linux/module.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <asm/unaligned.h>
#include <asm/byteorder.h>
#include <linux/input.h>
#include <linux/wait.h>
#include <linux/workqueue.h>
#include <linux/string.h>

#include <linux/usb.h>

#include <linux/hid.h>
#include <linux/hiddev.h>
#include <linux/hid-debug.h>
#include <linux/hidraw.h>
#include "usbhid.h"

/*
 * Version Information
 */

#define DRIVER_DESC "USB HID core driver"
#define DRIVER_LICENSE "GPL"

/*
 * Module parameters.
 */

static unsigned int hid_mousepoll_interval;
module_param_named(mousepoll, hid_mousepoll_interval, uint, 0644);
MODULE_PARM_DESC(mousepoll, "Polling interval of mice");

static unsigned int ignoreled;
module_param_named(ignoreled, ignoreled, uint, 0644);
MODULE_PARM_DESC(ignoreled, "Autosuspend with active leds");

/* Quirks specified at module load time */
static char *quirks_param[MAX_USBHID_BOOT_QUIRKS];
module_param_array_named(quirks, quirks_param, charp, NULL, 0444);
MODULE_PARM_DESC(quirks, "Add/modify USB HID quirks by specifying "
		" quirks=vendorID:productID:quirks"
		" where vendorID, productID, and quirks are all in"
		" 0x-prefixed hex");
/*
 * Input submission and I/O error handler.
 */
static DEFINE_MUTEX(hid_open_mut);

static void hid_io_error(struct hid_device *hid);
static int hid_submit_out(struct hid_device *hid);
static int hid_submit_ctrl(struct hid_device *hid);
static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid);

/* Start up the input URB */
static int hid_start_in(struct hid_device *hid)
{
	unsigned long flags;
	int rc = 0;
	struct usbhid_device *usbhid = hid->driver_data;

	spin_lock_irqsave(&usbhid->lock, flags);
	if ((hid->open > 0 || hid->quirks & HID_QUIRK_ALWAYS_POLL) &&
			!test_bit(HID_DISCONNECTED, &usbhid->iofl) &&
			!test_bit(HID_SUSPENDED, &usbhid->iofl) &&
			!test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
		rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
		if (rc != 0) {
			clear_bit(HID_IN_RUNNING, &usbhid->iofl);
			if (rc == -ENOSPC)
				set_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
		} else {
			clear_bit(HID_NO_BANDWIDTH, &usbhid->iofl);
		}
	}
	spin_unlock_irqrestore(&usbhid->lock, flags);
	return rc;
}

/* I/O retry timer routine */
static void hid_retry_timeout(unsigned long _hid)
{
	struct hid_device *hid = (struct hid_device *) _hid;
	struct usbhid_device *usbhid = hid->driver_data;

	dev_dbg(&usbhid->intf->dev, "retrying intr urb\n");
	if (hid_start_in(hid))
		hid_io_error(hid);
}

/* Workqueue routine to reset the device or clear a halt */
static void hid_reset(struct work_struct *work)
{
	struct usbhid_device *usbhid =
		container_of(work, struct usbhid_device, reset_work);
	struct hid_device *hid = usbhid->hid;
	int rc;

	if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
		dev_dbg(&usbhid->intf->dev, "clear halt\n");
		rc = usb_clear_halt(hid_to_usb_dev(hid), usbhid->urbin->pipe);
		clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
		if (rc == 0) {
			hid_start_in(hid);
		} else {
			dev_dbg(&usbhid->intf->dev,
					"clear-halt failed: %d\n", rc);
			set_bit(HID_RESET_PENDING, &usbhid->iofl);
		}
	}

	if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
		dev_dbg(&usbhid->intf->dev, "resetting device\n");
		usb_queue_reset_device(usbhid->intf);
	}
}

/* Main I/O error handler */
static void hid_io_error(struct hid_device *hid)
{
	unsigned long flags;
	struct usbhid_device *usbhid = hid->driver_data;

	spin_lock_irqsave(&usbhid->lock, flags);

	/* Stop when disconnected */
	if (test_bit(HID_DISCONNECTED, &usbhid->iofl))
		goto done;

	/* If it has been a while since the last error, we'll assume
	 * this a brand new error and reset the retry timeout. */
	if (time_after(jiffies, usbhid->stop_retry + HZ/2))
		usbhid->retry_delay = 0;

	/* When an error occurs, retry at increasing intervals */
	if (usbhid->retry_delay == 0) {
		usbhid->retry_delay = 13;	/* Then 26, 52, 104, 104, ... */
		usbhid->stop_retry = jiffies + msecs_to_jiffies(1000);
	} else if (usbhid->retry_delay < 100)
		usbhid->retry_delay *= 2;

	if (time_after(jiffies, usbhid->stop_retry)) {

		/* Retries failed, so do a port reset unless we lack bandwidth*/
		if (!test_bit(HID_NO_BANDWIDTH, &usbhid->iofl)
		     && !test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {

			schedule_work(&usbhid->reset_work);
			goto done;
		}
	}

	mod_timer(&usbhid->io_retry,
			jiffies + msecs_to_jiffies(usbhid->retry_delay));
done:
	spin_unlock_irqrestore(&usbhid->lock, flags);
}

static void usbhid_mark_busy(struct usbhid_device *usbhid)
{
	struct usb_interface *intf = usbhid->intf;

	usb_mark_last_busy(interface_to_usbdev(intf));
}

static int usbhid_restart_out_queue(struct usbhid_device *usbhid)
{
	struct hid_device *hid = usb_get_intfdata(usbhid->intf);
	int kicked;
	int r;

	if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) ||
			test_bit(HID_SUSPENDED, &usbhid->iofl))
		return 0;

	if ((kicked = (usbhid->outhead != usbhid->outtail))) {
		hid_dbg(hid, "Kicking head %d tail %d", usbhid->outhead, usbhid->outtail);

		/* Try to wake up from autosuspend... */
		r = usb_autopm_get_interface_async(usbhid->intf);
		if (r < 0)
			return r;

		/*
		 * If still suspended, don't submit.  Submission will
		 * occur if/when resume drains the queue.
		 */
		if (test_bit(HID_SUSPENDED, &usbhid->iofl)) {
			usb_autopm_put_interface_no_suspend(usbhid->intf);
			return r;
		}

		/* Asynchronously flush queue. */
		set_bit(HID_OUT_RUNNING, &usbhid->iofl);
		if (hid_submit_out(hid)) {
			clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
			usb_autopm_put_interface_async(usbhid->intf);
		}
		wake_up(&usbhid->wait);
	}
	return kicked;
}

static int usbhid_restart_ctrl_queue(struct usbhid_device *usbhid)
{
	struct hid_device *hid = usb_get_intfdata(usbhid->intf);
	int kicked;
	int r;

	WARN_ON(hid == NULL);
	if (!hid || test_bit(HID_RESET_PENDING, &usbhid->iofl) ||
			test_bit(HID_SUSPENDED, &usbhid->iofl))
		return 0;

	if ((kicked = (usbhid->ctrlhead != usbhid->ctrltail))) {
		hid_dbg(hid, "Kicking head %d tail %d", usbhid->ctrlhead, usbhid->ctrltail);

		/* Try to wake up from autosuspend... */
		r = usb_autopm_get_interface_async(usbhid->intf);
		if (r < 0)
			return r;

		/*
		 * If still suspended, don't submit.  Submission will
		 * occur if/when resume drains the queue.
		 */
		if (test_bit(HID_SUSPENDED, &usbhid->iofl)) {
			usb_autopm_put_interface_no_suspend(usbhid->intf);
			return r;
		}

		/* Asynchronously flush queue. */
		set_bit(HID_CTRL_RUNNING, &usbhid->iofl);
		if (hid_submit_ctrl(hid)) {
			clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
			usb_autopm_put_interface_async(usbhid->intf);
		}
		wake_up(&usbhid->wait);
	}
	return kicked;
}

/*
 * Input interrupt completion handler.
 */

static void hid_irq_in(struct urb *urb)
{
	struct hid_device	*hid = urb->context;
	struct usbhid_device 	*usbhid = hid->driver_data;
	int			status;

	switch (urb->status) {
	case 0:			/* success */
		usbhid->retry_delay = 0;
		if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open)
			break;
		usbhid_mark_busy(usbhid);
		if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) {
			hid_input_report(urb->context, HID_INPUT_REPORT,
					 urb->transfer_buffer,
					 urb->actual_length, 1);
			/*
			 * autosuspend refused while keys are pressed
			 * because most keyboards don't wake up when
			 * a key is released
			 */
			if (hid_check_keys_pressed(hid))
				set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
			else
				clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
		}
		break;
	case -EPIPE:		/* stall */
		usbhid_mark_busy(usbhid);
		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
		set_bit(HID_CLEAR_HALT, &usbhid->iofl);
		schedule_work(&usbhid->reset_work);
		return;
	case -ECONNRESET:	/* unlink */
	case -ENOENT:
	case -ESHUTDOWN:	/* unplug */
		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
		return;
	case -EILSEQ:		/* protocol error or unplug */
	case -EPROTO:		/* protocol error or unplug */
	case -ETIME:		/* protocol error or unplug */
	case -ETIMEDOUT:	/* Should never happen, but... */
		usbhid_mark_busy(usbhid);
		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
		hid_io_error(hid);
		return;
	default:		/* error */
		hid_warn(urb->dev, "input irq status %d received\n",
			 urb->status);
	}

	status = usb_submit_urb(urb, GFP_ATOMIC);
	if (status) {
		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
		if (status != -EPERM) {
			hid_err(hid, "can't resubmit intr, %s-%s/input%d, status %d\n",
				hid_to_usb_dev(hid)->bus->bus_name,
				hid_to_usb_dev(hid)->devpath,
				usbhid->ifnum, status);
			hid_io_error(hid);
		}
	}
}

static int hid_submit_out(struct hid_device *hid)
{
	struct hid_report *report;
	char *raw_report;
	struct usbhid_device *usbhid = hid->driver_data;
	int r;

	report = usbhid->out[usbhid->outtail].report;
	raw_report = usbhid->out[usbhid->outtail].raw_report;

	usbhid->urbout->transfer_buffer_length = hid_report_len(report);
	usbhid->urbout->dev = hid_to_usb_dev(hid);
	if (raw_report) {
		memcpy(usbhid->outbuf, raw_report,
				usbhid->urbout->transfer_buffer_length);
		kfree(raw_report);
		usbhid->out[usbhid->outtail].raw_report = NULL;
	}

	dbg_hid("submitting out urb\n");

	r = usb_submit_urb(usbhid->urbout, GFP_ATOMIC);
	if (r < 0) {
		hid_err(hid, "usb_submit_urb(out) failed: %d\n", r);
		return r;
	}
	usbhid->last_out = jiffies;
	return 0;
}

static int hid_submit_ctrl(struct hid_device *hid)
{
	struct hid_report *report;
	unsigned char dir;
	char *raw_report;
	int len, r;
	struct usbhid_device *usbhid = hid->driver_data;

	report = usbhid->ctrl[usbhid->ctrltail].report;
	raw_report = usbhid->ctrl[usbhid->ctrltail].raw_report;
	dir = usbhid->ctrl[usbhid->ctrltail].dir;

	len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
	if (dir == USB_DIR_OUT) {
		usbhid->urbctrl->pipe = usb_sndctrlpipe(hid_to_usb_dev(hid), 0);
		usbhid->urbctrl->transfer_buffer_length = len;
		if (raw_report) {
			memcpy(usbhid->ctrlbuf, raw_report, len);
			kfree(raw_report);
			usbhid->ctrl[usbhid->ctrltail].raw_report = NULL;
		}
	} else {
		int maxpacket, padlen;

		usbhid->urbctrl->pipe = usb_rcvctrlpipe(hid_to_usb_dev(hid), 0);
		maxpacket = usb_maxpacket(hid_to_usb_dev(hid),
					  usbhid->urbctrl->pipe, 0);
		if (maxpacket > 0) {
			padlen = DIV_ROUND_UP(len, maxpacket);
			padlen *= maxpacket;
			if (padlen > usbhid->bufsize)
				padlen = usbhid->bufsize;
		} else
			padlen = 0;
		usbhid->urbctrl->transfer_buffer_length = padlen;
	}
	usbhid->urbctrl->dev = hid_to_usb_dev(hid);

	usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
	usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT :
						      HID_REQ_GET_REPORT;
	usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) |
					 report->id);
	usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
	usbhid->cr->wLength = cpu_to_le16(len);

	dbg_hid("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u\n",
		usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" :
							     "Get_Report",
		usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);

	r = usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC);
	if (r < 0) {
		hid_err(hid, "usb_submit_urb(ctrl) failed: %d\n", r);
		return r;
	}
	usbhid->last_ctrl = jiffies;
	return 0;
}

/*
 * Output interrupt completion handler.
 */

static void hid_irq_out(struct urb *urb)
{
	struct hid_device *hid = urb->context;
	struct usbhid_device *usbhid = hid->driver_data;
	unsigned long flags;
	int unplug = 0;

	switch (urb->status) {
	case 0:			/* success */
		break;
	case -ESHUTDOWN:	/* unplug */
		unplug = 1;
	case -EILSEQ:		/* protocol error or unplug */
	case -EPROTO:		/* protocol error or unplug */
	case -ECONNRESET:	/* unlink */
	case -ENOENT:
		break;
	default:		/* error */
		hid_warn(urb->dev, "output irq status %d received\n",
			 urb->status);
	}

	spin_lock_irqsave(&usbhid->lock, flags);

	if (unplug) {
		usbhid->outtail = usbhid->outhead;
	} else {
		usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);

		if (usbhid->outhead != usbhid->outtail &&
				hid_submit_out(hid) == 0) {
			/* Successfully submitted next urb in queue */
			spin_unlock_irqrestore(&usbhid->lock, flags);
			return;
		}
	}

	clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
	spin_unlock_irqrestore(&usbhid->lock, flags);
	usb_autopm_put_interface_async(usbhid->intf);
	wake_up(&usbhid->wait);
}

/*
 * Control pipe completion handler.
 */

static void hid_ctrl(struct urb *urb)
{
	struct hid_device *hid = urb->context;
	struct usbhid_device *usbhid = hid->driver_data;
	int unplug = 0, status = urb->status;

	switch (status) {
	case 0:			/* success */
		if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
			hid_input_report(urb->context,
				usbhid->ctrl[usbhid->ctrltail].report->type,
				urb->transfer_buffer, urb->actual_length, 0);
		break;
	case -ESHUTDOWN:	/* unplug */
		unplug = 1;
	case -EILSEQ:		/* protocol error or unplug */
	case -EPROTO:		/* protocol error or unplug */
	case -ECONNRESET:	/* unlink */
	case -ENOENT:
	case -EPIPE:		/* report not available */
		break;
	default:		/* error */
		hid_warn(urb->dev, "ctrl urb status %d received\n", status);
	}

	spin_lock(&usbhid->lock);

	if (unplug) {
		usbhid->ctrltail = usbhid->ctrlhead;
	} else {
		usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);

		if (usbhid->ctrlhead != usbhid->ctrltail &&
				hid_submit_ctrl(hid) == 0) {
			/* Successfully submitted next urb in queue */
			spin_unlock(&usbhid->lock);
			return;
		}
	}

	clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
	spin_unlock(&usbhid->lock);
	usb_autopm_put_interface_async(usbhid->intf);
	wake_up(&usbhid->wait);
}

static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *report,
				   unsigned char dir)
{
	int head;
	struct usbhid_device *usbhid = hid->driver_data;

	if (((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN) ||
		test_bit(HID_DISCONNECTED, &usbhid->iofl))
		return;

	if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
		if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
			hid_warn(hid, "output queue full\n");
			return;
		}

		usbhid->out[usbhid->outhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
		if (!usbhid->out[usbhid->outhead].raw_report) {
			hid_warn(hid, "output queueing failed\n");
			return;
		}
		hid_output_report(report, usbhid->out[usbhid->outhead].raw_report);
		usbhid->out[usbhid->outhead].report = report;
		usbhid->outhead = head;

		/* If the queue isn't running, restart it */
		if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) {
			usbhid_restart_out_queue(usbhid);

		/* Otherwise see if an earlier request has timed out */
		} else if (time_after(jiffies, usbhid->last_out + HZ * 5)) {

			/* Prevent autosuspend following the unlink */
			usb_autopm_get_interface_no_resume(usbhid->intf);

			/*
			 * Prevent resubmission in case the URB completes
			 * before we can unlink it.  We don't want to cancel
			 * the wrong transfer!
			 */
			usb_block_urb(usbhid->urbout);

			/* Drop lock to avoid deadlock if the callback runs */
			spin_unlock(&usbhid->lock);

			usb_unlink_urb(usbhid->urbout);
			spin_lock(&usbhid->lock);
			usb_unblock_urb(usbhid->urbout);

			/* Unlink might have stopped the queue */
			if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl))
				usbhid_restart_out_queue(usbhid);

			/* Now we can allow autosuspend again */
			usb_autopm_put_interface_async(usbhid->intf);
		}
		return;
	}

	if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
		hid_warn(hid, "control queue full\n");
		return;
	}

	if (dir == USB_DIR_OUT) {
		usbhid->ctrl[usbhid->ctrlhead].raw_report = hid_alloc_report_buf(report, GFP_ATOMIC);
		if (!usbhid->ctrl[usbhid->ctrlhead].raw_report) {
			hid_warn(hid, "control queueing failed\n");
			return;
		}
		hid_output_report(report, usbhid->ctrl[usbhid->ctrlhead].raw_report);
	}
	usbhid->ctrl[usbhid->ctrlhead].report = report;
	usbhid->ctrl[usbhid->ctrlhead].dir = dir;
	usbhid->ctrlhead = head;

	/* If the queue isn't running, restart it */
	if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) {
		usbhid_restart_ctrl_queue(usbhid);

	/* Otherwise see if an earlier request has timed out */
	} else if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) {

		/* Prevent autosuspend following the unlink */
		usb_autopm_get_interface_no_resume(usbhid->intf);

		/*
		 * Prevent resubmission in case the URB completes
		 * before we can unlink it.  We don't want to cancel
		 * the wrong transfer!
		 */
		usb_block_urb(usbhid->urbctrl);

		/* Drop lock to avoid deadlock if the callback runs */
		spin_unlock(&usbhid->lock);

		usb_unlink_urb(usbhid->urbctrl);
		spin_lock(&usbhid->lock);
		usb_unblock_urb(usbhid->urbctrl);

		/* Unlink might have stopped the queue */
		if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
			usbhid_restart_ctrl_queue(usbhid);

		/* Now we can allow autosuspend again */
		usb_autopm_put_interface_async(usbhid->intf);
	}
}

static void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
{
	struct usbhid_device *usbhid = hid->driver_data;
	unsigned long flags;

	spin_lock_irqsave(&usbhid->lock, flags);
	__usbhid_submit_report(hid, report, dir);
	spin_unlock_irqrestore(&usbhid->lock, flags);
}

static int usbhid_wait_io(struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;

	if (!wait_event_timeout(usbhid->wait,
				(!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
				!test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
					10*HZ)) {
		dbg_hid("timeout waiting for ctrl or out queue to clear\n");
		return -1;
	}

	return 0;
}

static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle)
{
	return usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
		HID_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE, (idle << 8) | report,
		ifnum, NULL, 0, USB_CTRL_SET_TIMEOUT);
}

static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
		unsigned char type, void *buf, int size)
{
	int result, retries = 4;

	memset(buf, 0, size);

	do {
		result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
				USB_REQ_GET_DESCRIPTOR, USB_RECIP_INTERFACE | USB_DIR_IN,
				(type << 8), ifnum, buf, size, USB_CTRL_GET_TIMEOUT);
		retries--;
	} while (result < size && retries);
	return result;
}

int usbhid_open(struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;
	int res = 0;

	mutex_lock(&hid_open_mut);
	if (!hid->open++) {
		res = usb_autopm_get_interface(usbhid->intf);
		/* the device must be awake to reliably request remote wakeup */
		if (res < 0) {
			hid->open--;
			res = -EIO;
			goto done;
		}
		usbhid->intf->needs_remote_wakeup = 1;
		set_bit(HID_RESUME_RUNNING, &usbhid->iofl);
		res = hid_start_in(hid);
		if (res) {
			if (res != -ENOSPC) {
				hid_io_error(hid);
				res = 0;
			} else {
				/* no use opening if resources are insufficient */
				hid->open--;
				res = -EBUSY;
				usbhid->intf->needs_remote_wakeup = 0;
			}
		}
		usb_autopm_put_interface(usbhid->intf);

		/*
		 * In case events are generated while nobody was listening,
		 * some are released when the device is re-opened.
		 * Wait 50 msec for the queue to empty before allowing events
		 * to go through hid.
		 */
		if (res == 0 && !(hid->quirks & HID_QUIRK_ALWAYS_POLL))
			msleep(50);
		clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
	}
done:
	mutex_unlock(&hid_open_mut);
	return res;
}

void usbhid_close(struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;

	mutex_lock(&hid_open_mut);

	/* protecting hid->open to make sure we don't restart
	 * data acquistion due to a resumption we no longer
	 * care about
	 */
	spin_lock_irq(&usbhid->lock);
	if (!--hid->open) {
		spin_unlock_irq(&usbhid->lock);
		hid_cancel_delayed_stuff(usbhid);
		if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
			usb_kill_urb(usbhid->urbin);
			usbhid->intf->needs_remote_wakeup = 0;
		}
	} else {
		spin_unlock_irq(&usbhid->lock);
	}
	mutex_unlock(&hid_open_mut);
}

/*
 * Initialize all reports
 */

void usbhid_init_reports(struct hid_device *hid)
{
	struct hid_report *report;
	struct usbhid_device *usbhid = hid->driver_data;
	struct hid_report_enum *report_enum;
	int err, ret;

	if (!(hid->quirks & HID_QUIRK_NO_INIT_INPUT_REPORTS)) {
		report_enum = &hid->report_enum[HID_INPUT_REPORT];
		list_for_each_entry(report, &report_enum->report_list, list)
			usbhid_submit_report(hid, report, USB_DIR_IN);
	}

	report_enum = &hid->report_enum[HID_FEATURE_REPORT];
	list_for_each_entry(report, &report_enum->report_list, list)
		usbhid_submit_report(hid, report, USB_DIR_IN);

	err = 0;
	ret = usbhid_wait_io(hid);
	while (ret) {
		err |= ret;
		if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
			usb_kill_urb(usbhid->urbctrl);
		if (test_bit(HID_OUT_RUNNING, &usbhid->iofl))
			usb_kill_urb(usbhid->urbout);
		ret = usbhid_wait_io(hid);
	}

	if (err)
		hid_warn(hid, "timeout initializing reports\n");
}

/*
 * Reset LEDs which BIOS might have left on. For now, just NumLock (0x01).
 */
static int hid_find_field_early(struct hid_device *hid, unsigned int page,
    unsigned int hid_code, struct hid_field **pfield)
{
	struct hid_report *report;
	struct hid_field *field;
	struct hid_usage *usage;
	int i, j;

	list_for_each_entry(report, &hid->report_enum[HID_OUTPUT_REPORT].report_list, list) {
		for (i = 0; i < report->maxfield; i++) {
			field = report->field[i];
			for (j = 0; j < field->maxusage; j++) {
				usage = &field->usage[j];
				if ((usage->hid & HID_USAGE_PAGE) == page &&
				    (usage->hid & 0xFFFF) == hid_code) {
					*pfield = field;
					return j;
				}
			}
		}
	}
	return -1;
}

static void usbhid_set_leds(struct hid_device *hid)
{
	struct hid_field *field;
	int offset;

	if ((offset = hid_find_field_early(hid, HID_UP_LED, 0x01, &field)) != -1) {
		hid_set_field(field, offset, 0);
		usbhid_submit_report(hid, field->report, USB_DIR_OUT);
	}
}

/*
 * Traverse the supplied list of reports and find the longest
 */
static void hid_find_max_report(struct hid_device *hid, unsigned int type,
		unsigned int *max)
{
	struct hid_report *report;
	unsigned int size;

	list_for_each_entry(report, &hid->report_enum[type].report_list, list) {
		size = ((report->size - 1) >> 3) + 1 + hid->report_enum[type].numbered;
		if (*max < size)
			*max = size;
	}
}

static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;

	usbhid->inbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
			&usbhid->inbuf_dma);
	usbhid->outbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
			&usbhid->outbuf_dma);
	usbhid->cr = kmalloc(sizeof(*usbhid->cr), GFP_KERNEL);
	usbhid->ctrlbuf = usb_alloc_coherent(dev, usbhid->bufsize, GFP_KERNEL,
			&usbhid->ctrlbuf_dma);
	if (!usbhid->inbuf || !usbhid->outbuf || !usbhid->cr ||
			!usbhid->ctrlbuf)
		return -1;

	return 0;
}

static int usbhid_get_raw_report(struct hid_device *hid,
		unsigned char report_number, __u8 *buf, size_t count,
		unsigned char report_type)
{
	struct usbhid_device *usbhid = hid->driver_data;
	struct usb_device *dev = hid_to_usb_dev(hid);
	struct usb_interface *intf = usbhid->intf;
	struct usb_host_interface *interface = intf->cur_altsetting;
	int skipped_report_id = 0;
	int ret;

	/* Byte 0 is the report number. Report data starts at byte 1.*/
	buf[0] = report_number;
	if (report_number == 0x0) {
		/* Offset the return buffer by 1, so that the report ID
		   will remain in byte 0. */
		buf++;
		count--;
		skipped_report_id = 1;
	}
	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
		HID_REQ_GET_REPORT,
		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
		((report_type + 1) << 8) | report_number,
		interface->desc.bInterfaceNumber, buf, count,
		USB_CTRL_SET_TIMEOUT);

	/* count also the report id */
	if (ret > 0 && skipped_report_id)
		ret++;

	return ret;
}

static int usbhid_set_raw_report(struct hid_device *hid, unsigned int reportnum,
				 __u8 *buf, size_t count, unsigned char rtype)
{
	struct usbhid_device *usbhid = hid->driver_data;
	struct usb_device *dev = hid_to_usb_dev(hid);
	struct usb_interface *intf = usbhid->intf;
	struct usb_host_interface *interface = intf->cur_altsetting;
	int ret, skipped_report_id = 0;

	/* Byte 0 is the report number. Report data starts at byte 1.*/
	if ((rtype == HID_OUTPUT_REPORT) &&
	    (hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORT_ID))
		buf[0] = 0;
	else
		buf[0] = reportnum;

	if (buf[0] == 0x0) {
		/* Don't send the Report ID */
		buf++;
		count--;
		skipped_report_id = 1;
	}

	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
			HID_REQ_SET_REPORT,
			USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
			((rtype + 1) << 8) | reportnum,
			interface->desc.bInterfaceNumber, buf, count,
			USB_CTRL_SET_TIMEOUT);
	/* count also the report id, if this was a numbered report. */
	if (ret > 0 && skipped_report_id)
		ret++;

	return ret;
}

static int usbhid_output_report(struct hid_device *hid, __u8 *buf, size_t count)
{
	struct usbhid_device *usbhid = hid->driver_data;
	struct usb_device *dev = hid_to_usb_dev(hid);
	int actual_length, skipped_report_id = 0, ret;

	if (!usbhid->urbout)
		return -ENOSYS;

	if (buf[0] == 0x0) {
		/* Don't send the Report ID */
		buf++;
		count--;
		skipped_report_id = 1;
	}

	ret = usb_interrupt_msg(dev, usbhid->urbout->pipe,
				buf, count, &actual_length,
				USB_CTRL_SET_TIMEOUT);
	/* return the number of bytes transferred */
	if (ret == 0) {
		ret = actual_length;
		/* count also the report id */
		if (skipped_report_id)
			ret++;
	}

	return ret;
}

static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;

	usb_free_coherent(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
	usb_free_coherent(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
	kfree(usbhid->cr);
	usb_free_coherent(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
}

static int usbhid_parse(struct hid_device *hid)
{
	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
	struct usb_host_interface *interface = intf->cur_altsetting;
	struct usb_device *dev = interface_to_usbdev (intf);
	struct hid_descriptor *hdesc;
	u32 quirks = 0;
	unsigned int rsize = 0;
	char *rdesc;
	int ret, n;

	quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
			le16_to_cpu(dev->descriptor.idProduct));

	if (quirks & HID_QUIRK_IGNORE)
		return -ENODEV;

	/* Many keyboards and mice don't like to be polled for reports,
	 * so we will always set the HID_QUIRK_NOGET flag for them. */
	if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT) {
		if (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_KEYBOARD ||
			interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE)
				quirks |= HID_QUIRK_NOGET;
	}

	if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
	    (!interface->desc.bNumEndpoints ||
	     usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
		dbg_hid("class descriptor not present\n");
		return -ENODEV;
	}

	hid->version = le16_to_cpu(hdesc->bcdHID);
	hid->country = hdesc->bCountryCode;

	for (n = 0; n < hdesc->bNumDescriptors; n++)
		if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
			rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);

	if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) {
		dbg_hid("weird size of report descriptor (%u)\n", rsize);
		return -EINVAL;
	}

	if (!(rdesc = kmalloc(rsize, GFP_KERNEL))) {
		dbg_hid("couldn't allocate rdesc memory\n");
		return -ENOMEM;
	}

	hid_set_idle(dev, interface->desc.bInterfaceNumber, 0, 0);

	ret = hid_get_class_descriptor(dev, interface->desc.bInterfaceNumber,
			HID_DT_REPORT, rdesc, rsize);
	if (ret < 0) {
		dbg_hid("reading report descriptor failed\n");
		kfree(rdesc);
		goto err;
	}

	ret = hid_parse_report(hid, rdesc, rsize);
	kfree(rdesc);
	if (ret) {
		dbg_hid("parsing report descriptor failed\n");
		goto err;
	}

	hid->quirks |= quirks;

	return 0;
err:
	return ret;
}

static int usbhid_start(struct hid_device *hid)
{
	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
	struct usb_host_interface *interface = intf->cur_altsetting;
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usbhid_device *usbhid = hid->driver_data;
	unsigned int n, insize = 0;
	int ret;

	clear_bit(HID_DISCONNECTED, &usbhid->iofl);

	usbhid->bufsize = HID_MIN_BUFFER_SIZE;
	hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize);
	hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize);
	hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize);

	if (usbhid->bufsize > HID_MAX_BUFFER_SIZE)
		usbhid->bufsize = HID_MAX_BUFFER_SIZE;

	hid_find_max_report(hid, HID_INPUT_REPORT, &insize);

	if (insize > HID_MAX_BUFFER_SIZE)
		insize = HID_MAX_BUFFER_SIZE;

	if (hid_alloc_buffers(dev, hid)) {
		ret = -ENOMEM;
		goto fail;
	}

	for (n = 0; n < interface->desc.bNumEndpoints; n++) {
		struct usb_endpoint_descriptor *endpoint;
		int pipe;
		int interval;

		endpoint = &interface->endpoint[n].desc;
		if (!usb_endpoint_xfer_int(endpoint))
			continue;

		interval = endpoint->bInterval;

		/* Some vendors give fullspeed interval on highspeed devides */
		if (hid->quirks & HID_QUIRK_FULLSPEED_INTERVAL &&
		    dev->speed == USB_SPEED_HIGH) {
			interval = fls(endpoint->bInterval*8);
			printk(KERN_INFO "%s: Fixing fullspeed to highspeed interval: %d -> %d\n",
			       hid->name, endpoint->bInterval, interval);
		}

		/* Change the polling interval of mice. */
		if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
			interval = hid_mousepoll_interval;

		ret = -ENOMEM;
		if (usb_endpoint_dir_in(endpoint)) {
			if (usbhid->urbin)
				continue;
			if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
				goto fail;
			pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
			usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize,
					 hid_irq_in, hid, interval);
			usbhid->urbin->transfer_dma = usbhid->inbuf_dma;
			usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
		} else {
			if (usbhid->urbout)
				continue;
			if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
				goto fail;
			pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress);
			usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0,
					 hid_irq_out, hid, interval);
			usbhid->urbout->transfer_dma = usbhid->outbuf_dma;
			usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
		}
	}

	usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
	if (!usbhid->urbctrl) {
		ret = -ENOMEM;
		goto fail;
	}

	usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
			     usbhid->ctrlbuf, 1, hid_ctrl, hid);
	usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
	usbhid->urbctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;

	if (!(hid->quirks & HID_QUIRK_NO_INIT_REPORTS))
		usbhid_init_reports(hid);

	set_bit(HID_STARTED, &usbhid->iofl);

	if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
		ret = usb_autopm_get_interface(usbhid->intf);
		if (ret)
			goto fail;
		usbhid->intf->needs_remote_wakeup = 1;
		ret = hid_start_in(hid);
		if (ret) {
			dev_err(&hid->dev,
				"failed to start in urb: %d\n", ret);
		}
		usb_autopm_put_interface(usbhid->intf);
	}

	/* Some keyboards don't work until their LEDs have been set.
	 * Since BIOSes do set the LEDs, it must be safe for any device
	 * that supports the keyboard boot protocol.
	 * In addition, enable remote wakeup by default for all keyboard
	 * devices supporting the boot protocol.
	 */
	if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT &&
			interface->desc.bInterfaceProtocol ==
				USB_INTERFACE_PROTOCOL_KEYBOARD) {
		usbhid_set_leds(hid);
		device_set_wakeup_enable(&dev->dev, 1);
	}
	return 0;

fail:
	usb_free_urb(usbhid->urbin);
	usb_free_urb(usbhid->urbout);
	usb_free_urb(usbhid->urbctrl);
	usbhid->urbin = NULL;
	usbhid->urbout = NULL;
	usbhid->urbctrl = NULL;
	hid_free_buffers(dev, hid);
	return ret;
}

static void usbhid_stop(struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;

	if (WARN_ON(!usbhid))
		return;

	if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
		usbhid->intf->needs_remote_wakeup = 0;

	clear_bit(HID_STARTED, &usbhid->iofl);
	spin_lock_irq(&usbhid->lock);	/* Sync with error and led handlers */
	set_bit(HID_DISCONNECTED, &usbhid->iofl);
	spin_unlock_irq(&usbhid->lock);
	usb_kill_urb(usbhid->urbin);
	usb_kill_urb(usbhid->urbout);
	usb_kill_urb(usbhid->urbctrl);

	hid_cancel_delayed_stuff(usbhid);

	hid->claimed = 0;

	usb_free_urb(usbhid->urbin);
	usb_free_urb(usbhid->urbctrl);
	usb_free_urb(usbhid->urbout);
	usbhid->urbin = NULL; /* don't mess up next start */
	usbhid->urbctrl = NULL;
	usbhid->urbout = NULL;

	hid_free_buffers(hid_to_usb_dev(hid), hid);
}

static int usbhid_power(struct hid_device *hid, int lvl)
{
	int r = 0;

	switch (lvl) {
	case PM_HINT_FULLON:
		r = usbhid_get_power(hid);
		break;
	case PM_HINT_NORMAL:
		usbhid_put_power(hid);
		break;
	}
	return r;
}

static void usbhid_request(struct hid_device *hid, struct hid_report *rep, int reqtype)
{
	switch (reqtype) {
	case HID_REQ_GET_REPORT:
		usbhid_submit_report(hid, rep, USB_DIR_IN);
		break;
	case HID_REQ_SET_REPORT:
		usbhid_submit_report(hid, rep, USB_DIR_OUT);
		break;
	}
}

static int usbhid_raw_request(struct hid_device *hid, unsigned char reportnum,
			      __u8 *buf, size_t len, unsigned char rtype,
			      int reqtype)
{
	switch (reqtype) {
	case HID_REQ_GET_REPORT:
		return usbhid_get_raw_report(hid, reportnum, buf, len, rtype);
	case HID_REQ_SET_REPORT:
		return usbhid_set_raw_report(hid, reportnum, buf, len, rtype);
	default:
		return -EIO;
	}
}

static int usbhid_idle(struct hid_device *hid, int report, int idle,
		int reqtype)
{
	struct usb_device *dev = hid_to_usb_dev(hid);
	struct usb_interface *intf = to_usb_interface(hid->dev.parent);
	struct usb_host_interface *interface = intf->cur_altsetting;
	int ifnum = interface->desc.bInterfaceNumber;

	if (reqtype != HID_REQ_SET_IDLE)
		return -EINVAL;

	return hid_set_idle(dev, ifnum, report, idle);
}

static struct hid_ll_driver usb_hid_driver = {
	.parse = usbhid_parse,
	.start = usbhid_start,
	.stop = usbhid_stop,
	.open = usbhid_open,
	.close = usbhid_close,
	.power = usbhid_power,
	.request = usbhid_request,
	.wait = usbhid_wait_io,
	.raw_request = usbhid_raw_request,
	.output_report = usbhid_output_report,
	.idle = usbhid_idle,
};

static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_host_interface *interface = intf->cur_altsetting;
	struct usb_device *dev = interface_to_usbdev(intf);
	struct usbhid_device *usbhid;
	struct hid_device *hid;
	unsigned int n, has_in = 0;
	size_t len;
	int ret;

	dbg_hid("HID probe called for ifnum %d\n",
			intf->altsetting->desc.bInterfaceNumber);

	for (n = 0; n < interface->desc.bNumEndpoints; n++)
		if (usb_endpoint_is_int_in(&interface->endpoint[n].desc))
			has_in++;
	if (!has_in) {
		hid_err(intf, "couldn't find an input interrupt endpoint\n");
		return -ENODEV;
	}

	hid = hid_allocate_device();
	if (IS_ERR(hid))
		return PTR_ERR(hid);

	usb_set_intfdata(intf, hid);
	hid->ll_driver = &usb_hid_driver;
	hid->ff_init = hid_pidff_init;
#ifdef CONFIG_USB_HIDDEV
	hid->hiddev_connect = hiddev_connect;
	hid->hiddev_disconnect = hiddev_disconnect;
	hid->hiddev_hid_event = hiddev_hid_event;
	hid->hiddev_report_event = hiddev_report_event;
#endif
	hid->dev.parent = &intf->dev;
	hid->bus = BUS_USB;
	hid->vendor = le16_to_cpu(dev->descriptor.idVendor);
	hid->product = le16_to_cpu(dev->descriptor.idProduct);
	hid->name[0] = 0;
	hid->quirks = usbhid_lookup_quirk(hid->vendor, hid->product);
	if (intf->cur_altsetting->desc.bInterfaceProtocol ==
			USB_INTERFACE_PROTOCOL_MOUSE)
		hid->type = HID_TYPE_USBMOUSE;
	else if (intf->cur_altsetting->desc.bInterfaceProtocol == 0)
		hid->type = HID_TYPE_USBNONE;

	if (dev->manufacturer)
		strlcpy(hid->name, dev->manufacturer, sizeof(hid->name));

	if (dev->product) {
		if (dev->manufacturer)
			strlcat(hid->name, " ", sizeof(hid->name));
		strlcat(hid->name, dev->product, sizeof(hid->name));
	}

	if (!strlen(hid->name))
		snprintf(hid->name, sizeof(hid->name), "HID %04x:%04x",
			 le16_to_cpu(dev->descriptor.idVendor),
			 le16_to_cpu(dev->descriptor.idProduct));

	usb_make_path(dev, hid->phys, sizeof(hid->phys));
	strlcat(hid->phys, "/input", sizeof(hid->phys));
	len = strlen(hid->phys);
	if (len < sizeof(hid->phys) - 1)
		snprintf(hid->phys + len, sizeof(hid->phys) - len,
			 "%d", intf->altsetting[0].desc.bInterfaceNumber);

	if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
		hid->uniq[0] = 0;

	usbhid = kzalloc(sizeof(*usbhid), GFP_KERNEL);
	if (usbhid == NULL) {
		ret = -ENOMEM;
		goto err;
	}

	hid->driver_data = usbhid;
	usbhid->hid = hid;
	usbhid->intf = intf;
	usbhid->ifnum = interface->desc.bInterfaceNumber;

	init_waitqueue_head(&usbhid->wait);
	INIT_WORK(&usbhid->reset_work, hid_reset);
	setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
	spin_lock_init(&usbhid->lock);

	ret = hid_add_device(hid);
	if (ret) {
		if (ret != -ENODEV)
			hid_err(intf, "can't add hid device: %d\n", ret);
		goto err_free;
	}

	return 0;
err_free:
	kfree(usbhid);
err:
	hid_destroy_device(hid);
	return ret;
}

static void usbhid_disconnect(struct usb_interface *intf)
{
	struct hid_device *hid = usb_get_intfdata(intf);
	struct usbhid_device *usbhid;

	if (WARN_ON(!hid))
		return;

	usbhid = hid->driver_data;
	spin_lock_irq(&usbhid->lock);	/* Sync with error and led handlers */
	set_bit(HID_DISCONNECTED, &usbhid->iofl);
	spin_unlock_irq(&usbhid->lock);
	hid_destroy_device(hid);
	kfree(usbhid);
}

static void hid_cancel_delayed_stuff(struct usbhid_device *usbhid)
{
	del_timer_sync(&usbhid->io_retry);
	cancel_work_sync(&usbhid->reset_work);
}

static void hid_cease_io(struct usbhid_device *usbhid)
{
	del_timer_sync(&usbhid->io_retry);
	usb_kill_urb(usbhid->urbin);
	usb_kill_urb(usbhid->urbctrl);
	usb_kill_urb(usbhid->urbout);
}

static void hid_restart_io(struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;
	int clear_halt = test_bit(HID_CLEAR_HALT, &usbhid->iofl);
	int reset_pending = test_bit(HID_RESET_PENDING, &usbhid->iofl);

	spin_lock_irq(&usbhid->lock);
	clear_bit(HID_SUSPENDED, &usbhid->iofl);
	usbhid_mark_busy(usbhid);

	if (clear_halt || reset_pending)
		schedule_work(&usbhid->reset_work);
	usbhid->retry_delay = 0;
	spin_unlock_irq(&usbhid->lock);

	if (reset_pending || !test_bit(HID_STARTED, &usbhid->iofl))
		return;

	if (!clear_halt) {
		if (hid_start_in(hid) < 0)
			hid_io_error(hid);
	}

	spin_lock_irq(&usbhid->lock);
	if (usbhid->urbout && !test_bit(HID_OUT_RUNNING, &usbhid->iofl))
		usbhid_restart_out_queue(usbhid);
	if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
		usbhid_restart_ctrl_queue(usbhid);
	spin_unlock_irq(&usbhid->lock);
}

/* Treat USB reset pretty much the same as suspend/resume */
static int hid_pre_reset(struct usb_interface *intf)
{
	struct hid_device *hid = usb_get_intfdata(intf);
	struct usbhid_device *usbhid = hid->driver_data;

	spin_lock_irq(&usbhid->lock);
	set_bit(HID_RESET_PENDING, &usbhid->iofl);
	spin_unlock_irq(&usbhid->lock);
	hid_cease_io(usbhid);

	return 0;
}

/* Same routine used for post_reset and reset_resume */
static int hid_post_reset(struct usb_interface *intf)
{
	struct usb_device *dev = interface_to_usbdev (intf);
	struct hid_device *hid = usb_get_intfdata(intf);
	struct usbhid_device *usbhid = hid->driver_data;
	struct usb_host_interface *interface = intf->cur_altsetting;
	int status;
	char *rdesc;

	/* Fetch and examine the HID report descriptor. If this
	 * has changed, then rebind. Since usbcore's check of the
	 * configuration descriptors passed, we already know that
	 * the size of the HID report descriptor has not changed.
	 */
	rdesc = kmalloc(hid->dev_rsize, GFP_KERNEL);
	if (!rdesc) {
		dbg_hid("couldn't allocate rdesc memory (post_reset)\n");
		return 1;
	}
	status = hid_get_class_descriptor(dev,
				interface->desc.bInterfaceNumber,
				HID_DT_REPORT, rdesc, hid->dev_rsize);
	if (status < 0) {
		dbg_hid("reading report descriptor failed (post_reset)\n");
		kfree(rdesc);
		return 1;
	}
	status = memcmp(rdesc, hid->dev_rdesc, hid->dev_rsize);
	kfree(rdesc);
	if (status != 0) {
		dbg_hid("report descriptor changed\n");
		return 1;
	}

	/* No need to do another reset or clear a halted endpoint */
	spin_lock_irq(&usbhid->lock);
	clear_bit(HID_RESET_PENDING, &usbhid->iofl);
	clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
	spin_unlock_irq(&usbhid->lock);
	hid_set_idle(dev, intf->cur_altsetting->desc.bInterfaceNumber, 0, 0);

	hid_restart_io(hid);

	return 0;
}

int usbhid_get_power(struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;

	return usb_autopm_get_interface(usbhid->intf);
}

void usbhid_put_power(struct hid_device *hid)
{
	struct usbhid_device *usbhid = hid->driver_data;

	usb_autopm_put_interface(usbhid->intf);
}

#ifdef CONFIG_PM
static int hid_resume_common(struct hid_device *hid, bool driver_suspended)
{
	int status = 0;

	hid_restart_io(hid);
	if (driver_suspended && hid->driver && hid->driver->resume)
		status = hid->driver->resume(hid);
	return status;
}

static int hid_suspend(struct usb_interface *intf, pm_message_t message)
{
	struct hid_device *hid = usb_get_intfdata(intf);
	struct usbhid_device *usbhid = hid->driver_data;
	int status = 0;
	bool driver_suspended = false;
	unsigned int ledcount;

	if (PMSG_IS_AUTO(message)) {
		ledcount = hidinput_count_leds(hid);
		spin_lock_irq(&usbhid->lock);	/* Sync with error handler */
		if (!test_bit(HID_RESET_PENDING, &usbhid->iofl)
		    && !test_bit(HID_CLEAR_HALT, &usbhid->iofl)
		    && !test_bit(HID_OUT_RUNNING, &usbhid->iofl)
		    && !test_bit(HID_CTRL_RUNNING, &usbhid->iofl)
		    && !test_bit(HID_KEYS_PRESSED, &usbhid->iofl)
		    && (!ledcount || ignoreled))
		{
			set_bit(HID_SUSPENDED, &usbhid->iofl);
			spin_unlock_irq(&usbhid->lock);
			if (hid->driver && hid->driver->suspend) {
				status = hid->driver->suspend(hid, message);
				if (status < 0)
					goto failed;
			}
			driver_suspended = true;
		} else {
			usbhid_mark_busy(usbhid);
			spin_unlock_irq(&usbhid->lock);
			return -EBUSY;
		}

	} else {
		/* TODO: resume() might need to handle suspend failure */
		if (hid->driver && hid->driver->suspend)
			status = hid->driver->suspend(hid, message);
		driver_suspended = true;
		spin_lock_irq(&usbhid->lock);
		set_bit(HID_SUSPENDED, &usbhid->iofl);
		spin_unlock_irq(&usbhid->lock);
		if (usbhid_wait_io(hid) < 0)
			status = -EIO;
	}

	hid_cancel_delayed_stuff(usbhid);
	hid_cease_io(usbhid);

	if (PMSG_IS_AUTO(message) && test_bit(HID_KEYS_PRESSED, &usbhid->iofl)) {
		/* lost race against keypresses */
		status = -EBUSY;
		goto failed;
	}
	dev_dbg(&intf->dev, "suspend\n");
	return status;

 failed:
	hid_resume_common(hid, driver_suspended);
	return status;
}

static int hid_resume(struct usb_interface *intf)
{
	struct hid_device *hid = usb_get_intfdata (intf);
	int status;

	status = hid_resume_common(hid, true);
	dev_dbg(&intf->dev, "resume status %d\n", status);
	return 0;
}

static int hid_reset_resume(struct usb_interface *intf)
{
	struct hid_device *hid = usb_get_intfdata(intf);
	int status;

	status = hid_post_reset(intf);
	if (status >= 0 && hid->driver && hid->driver->reset_resume) {
		int ret = hid->driver->reset_resume(hid);
		if (ret < 0)
			status = ret;
	}
	return status;
}

#endif /* CONFIG_PM */

static const struct usb_device_id hid_usb_ids[] = {
	{ .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS,
		.bInterfaceClass = USB_INTERFACE_CLASS_HID },
	{ }						/* Terminating entry */
};

MODULE_DEVICE_TABLE (usb, hid_usb_ids);

static struct usb_driver hid_driver = {
	.name =		"usbhid",
	.probe =	usbhid_probe,
	.disconnect =	usbhid_disconnect,
#ifdef CONFIG_PM
	.suspend =	hid_suspend,
	.resume =	hid_resume,
	.reset_resume =	hid_reset_resume,
#endif
	.pre_reset =	hid_pre_reset,
	.post_reset =	hid_post_reset,
	.id_table =	hid_usb_ids,
	.supports_autosuspend = 1,
};

struct usb_interface *usbhid_find_interface(int minor)
{
	return usb_find_interface(&hid_driver, minor);
}

static int __init hid_init(void)
{
	int retval = -ENOMEM;

	retval = usbhid_quirks_init(quirks_param);
	if (retval)
		goto usbhid_quirks_init_fail;
	retval = usb_register(&hid_driver);
	if (retval)
		goto usb_register_fail;
	printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n");

	return 0;
usb_register_fail:
	usbhid_quirks_exit();
usbhid_quirks_init_fail:
	return retval;
}

static void __exit hid_exit(void)
{
	usb_deregister(&hid_driver);
	usbhid_quirks_exit();
}

module_init(hid_init);
module_exit(hid_exit);

MODULE_AUTHOR("Andreas Gal");
MODULE_AUTHOR("Vojtech Pavlik");
MODULE_AUTHOR("Jiri Kosina");
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);

redpajama_set_name: RedPajamaGithub


text:
CUEmmunity Blog Events CUE Records Gallery About Contact Join Our Email CUEmmunity
CUEmmunity BlogEventsCUE RecordsGalleryAboutContactJoin Our Email CUEmmunity
Artist Spotlight: An Interview with Austin Speed
Luis: So Austin, how did you first come to find yourself in the world of electronic music? What attracted you to the scene?
Austin: I've been into music since I was a little kid, I used to play guitar and bass in metal and hardcore bands in junior high and high school. One of my friends turned me on to industrial music back when I was in junior high and I was really intrigued by the sounds I was hearing, I was trying to figure out how it was all made. Around that same time I got a DOS-based sample tracker and started making my own beats and sketches, and it just kinda progressed from there. I started listening to more electronic music than metal, started going to raves and really fell in love with the whole thing.
L: Who were some of your favorite artists back when you first started raving? Who are some of your inspirations or artists you are just generally enjoying now a days?
A: Well I got into the music first and raves second, so a lot of what I was listening to I wasn't hearing at raves. I'd have to say one of my all-time favorite acts is Autechre. When I first heard them it was like hearing something from another dimension, like it's just so out there that it takes a while to grasp what's going on. I still listen to them a lot and even though their newer stuff is mind-blowing on a sound design level, it's really kind of amazing how their stuff from the 90's still sounds like it's from the future. Orbital and Chemical Brothers were a couple of other acts that I enjoyed when I first started. I've always been into live performances and they both do it proper. Nowadays I've been listening to a lot of electro and I've been going back to IDM. Some artists would be Jensen Interceptor, Carl Finlow, Sync 24, Morphology, 214, Plaid, Proem, Jon Hopkins etc.
L: You focus on bringing a live element to your own performances. Can you explain your creative process a little bit, and what your audience can expect to look forward to? How has you performance evolved over your years on stage?
Austin Speed performing live at World Beat Center during Acid Varity The Deep End Present: Dj Pierre
A: I used to do all-hardware sets a few years back but it was a really cumbersome setup as I'd have to drag out a huge chunk of my studio every time. I started DJing more after that but picked up the live setup again recently. When I restarted it was an Ableton-based setup but I was never happy with it. I was always struggling with latency and getting it to sync up to other gear and no matter what controller I used it just never "felt" right. After a lot of research I ended up going with an Elektron-based setup and it'g been great. The Elektron stuff is built for performance, the timing is rock-solid and you can do some wild stuff that you'd never think of doing in software. So I have my tracks set up in basic blueprints but I rework the structures and mess with a lot of synth parameters in real-time. It's really cool because it gives me the flexibility to make shifts in energy happen as I see fit, for instance I can extend a part or make a breakdown happen at any given time really.
L: Now I'm even more excited and curious to see and hear what you have in store for us on the 22nd.
If you had to slap a label on the type of music you've been most interested in producing lately what would you call it?
A: I call it electro but that word gets misconstrued and confused with electro-house, which it's vastly different from. It's more akin to breaks but it's more synthesizer-based. There are also a lot of other influences going on as well, some bits of techno and IDM will peek out here and there.
Austin Speed performing at World Beat Center during Acid Varity The Deep End Present: Dj Pierre
L: Anything particularly exciting you've been working on? Or shows in addition to the upcoming toy drive at Kava that you'd like to mention? I saw we both are playing Bloom NYE, that should be a great way to ring in the New Year.
A: Yeah Bloom is looking to be really great! They're pulling from lots of different segments of the scene so it'll be cool to get everyone together at one party. I just finished a remix for Carl Finlow, he's taking submissions and picking six people to get their remix pressed to vinyl so I'm keeping my fingers crossed on that one. He's doing it in a really cool way too as you submit your remix in an alphanumeric code so that he doesn't know who did it keeping the playing field level. Also shout out to Brandon Vazquez for letting me know about that and to Brian Millar for his help and input.
Austin Speed Live at Broken Beat, Space October 2018
L: Heck yeah, best of luck to you being selected my dude. Really looking forward to working with you in the coming weeks for the toy drive and ringing in 2019. Thanks for taking a little bit of time to answer some questions so we could get a chance to learn a little more about your history and evolution as an artist.
A: Thank you guys for having me and I'm really looking forward to playing for you guys! I always love the vibe that Triptych brings!
Every time we work with Austin he is a total professional and we really admire and respect him for that. It certainly doesn't hurt that his is a killer performer to boot! We are incredibly honored to have him collaborating with us this year for Hope for the Holidays. We are also looking forward to taking the stage with him again for New Years Eve for Bloom being produced by ENTER THE TECH, Mindfruit, In Da Hoody as well as Monarch who is providing a lot of the stage design elements.
InterviewCue Together December 19, 2018 austin speed, electro, hope for the holidays, kava lounge, bloom, enter the tech, mindfruit, monarch, in da hoody, carl finlow, bloom nye, nye san diego, kava, cue, interview, san diego, jensen interceptor, sync 24, morphology, plaid, proem, jon hopkins, live set, live electronic music, broken beat, acid varcity, the deep end, techno, idm1 Comment
Track Release: god particle - Something
Cue Together December 19, 2018
The Artists of Hope For The Holidays 2018
NewsCue Together December 17, 2018 art, cale mc, william lyday, cue, rady, toy drive, radys, hope for the holidays, fashion show, san diego, kava lounge, lyday, san diego artist, original art
Sign up with your email address to receive news, updates, and special offers.
Create Unite Engage

redpajama_set_name: RedPajamaCommonCrawl


text:
Kate Middleton Seeks A "Healthier And Happier Society" In A New Op-Ed
Murdaugh Said He Knew Killer's Motive on Night His Wife and Son Were Slain
Cops Didn't See Alex Murdaugh Shed a Tear at Murder Scene
DirecTV Adds Another Right-Wing Network After Dumping Newsmax
Even as the British royal family maintains its political neutrality, members still champion causes close to their hearts. For Catherine, the Princess of Wales, that list is long, and issues like children, physical and mental health, and poverty are high priorities. Case in point? The future queen wrote an op-ed that was published in The Telegraph on Nov. 25 highlighting the importance of children's "first crucial years of life" — for both them as individuals and for society at large.
In her 10 years as a member of the royal family, Kate wrote, "talking to a wide range of experts about how we deal with societal issues like poor mental and physical health" has opened her eyes to a key period in children's lives. "If we are going to create a healthier and happier society for future generations, we must start by understanding and acknowledging the unique importance of the first five years of life," she added.
Early childhood "fundamentally impacts our whole life," the mom of three said, citing three decades of evidence tying brain development in the first five years to later relationships and success. However, she believes "not enough is being done." That makes it harder to "tackle the sorts of complex challenges we face today like homelessness, violence and addiction," she indicated.
Moving forward, she pledged make sure the issue gets the attention it needs. "I am determined to continue to shine a light on this issue and to do everything I can to secure much greater focus on those first crucial few years for the youngest members of our society – they are, after all, our future," she added.
On a personal level, Kate and her husband, Prince William, are shaping the early development of their three little ones — Prince George, 9, Princess Charlotte, 7, and Prince Louis, 4 — as they grow up in the public eye. One recent challenge was providing as much normalcy as possible as the world grieved the trio's great-grandmother, the late Queen Elizabeth II. "We're trying to keep everything constant and settled for them," William told a supporter in footage posted to Twitter on Sept. 15. Kate told another well wisher that the Wales children were "in school, being well looked after."
In addition to raising the next generation of senior royals, Kate is a patron of several youth-focused charities, from Action for Children to the Evelina London Children's Hospital. During a recent visit to the Reading Ukrainian Community Centre, she could be seen chatting with kids, admiring their artwork, and even painting alongside them. Expect more of that as she fulfills her promise to nurture children and strive for a "healthier and happier society."
The post Kate Middleton Seeks A "Healthier And Happier Society" In A New Op-Ed appeared first on Bustle.
Tech tycoon, 45, reportedly spends $2 million a year on his extreme anti-aging regimen. His goal? To achieve the body, inside and out, of an 18-year-old.
Covid Cases Spread to 9/11 Defendants at Guantánamo Bay
Demystifying the metaverse: How CIOs can keep it real


text:
KUHT Film and Video[remove]48
You searched for: Format Moving Image Remove constraint Format: Moving Image Collection KUHT Film and Video Remove constraint Collection: KUHT Film and Video Date 1963 Remove constraint Date: 1963
10. Education for Survival, Episode 8: Decontamination (29:55)
12. Essay On Death: A Memorial to John F. Kennedy (1:16:34)
A memorial program for JFK, this is an exploration of death and grief.
13. Expedition Houston Outtakes 1 (23:10)
"Expedition Houston" outtakes, including Houston skyline, oil and cotton production, and scenes from Texas history.
"Expedition Houston" outtakes, including scenes of farming, ranching, city streets, construction sites, department stores, and the zoo.
15. Expedition Houston, Episode 5: The Dark Hours (21:56)
A co-production of KTRK-TV, this television program depicts Houston activities from dusk-to-dawn. The film includes locations such as The Alley, Playhouse & Theater, Inc. Credits: Thomas, Wayne (di...
16. Help Wanted (21:16)
A report of the mental health study group of the Junior League of Houston. No sound on film.
17. Houston Ship Channel aerial footage (01:42)
Silent aerial footage of the Houston Ship Channel.
19. Local Issue: Integration: Two Towns in Texas (29:27)
This television program explores the subject of integration in a Texas school district. As subjects, it examines the towns of La Marque and Crosby and the way in which the two town's school distric...
20. NASA Moon Documentary (09:20)
NASA documentary about the moon. This film describes the technology used to map the moon's surface and the equipment utilized to house men on moon missions. Footage includes a detailed description ...


text:
House Panel Wants to Cut Off Judge Samuel Kent, and Quick
By Kevin Fayle on June 09, 2009 6:10 PM
As much as I am loath to focus even more attention on a man who has already been publicly shamed, broken and will soon begin serving time in federal prison, Judge Samuel Kent is just too colorful and controversial of a figure to avoid commenting on.
In addition to his 33-month sentence for obstruction of justice during an investigation into allegations of sexual assault (which he later admitted to), it looks like the process of stripping Kent of his judicial robes has shifted into high gear in Congress.
After a 20 minute hearing, the House subcommittee on judicial impeachment unanimously voted to recommend articles of impeachment to the House Judiciary Committee. The Committee has opted for a fast-track impeachment, and will hold a vote on the issue tomorrow.
Since it seems likely that the Committee will issue the articles of impeachment to the full House, the next step of the process will involve a vote on the matter by the entire House. Assuming that the House impeaches Kent, the next stop is a trial before the Senate. It's likely that Congress will take extreme measures to expedite the impeachment at every stage of the process.
The cause of all the rush is indignation over Judge Kent's attempt to continue drawing his federal salary while he serves a portion of his sentence. The judge announced that he would resign effective in June 2010, which would allow him to keep getting paid for a year while in prison.
Kent's strategy hinged on the fact that impeachments usually take a long time. Because impeachments have to go through all the stages outlined above, Kent thought that he could convince Congress to forgo a full impeachment and allow him to keep his salary for a year by agreeing to resign. Under Kent's plan, Congress wouldn't have to spend the time and money to impeach him, he would get a year of paid vacation (albeit in prison) and would eventually leave the bench anyway.
The plan backfired when members of the House committee became enraged over Kent's machinations.
"Judge Kent and his lawyer are banking on the fact that impeachments take time, literally," said Rep. Lamar Smith (R-TX) after a hearing last week. "Judge Kent receives $465 of his taxpayer-funded salary every day he remains in office. We are here today to put an end to Judge Kent's abuse of authority and exploitation of American taxpayers."
Kent had originally tried to claim a disability, which would have allowed him to continue receiving his salary for life. The Fifth Circuit Court of Appeals denied his claim and recommended his impeachment.


text:
The East Indian is a 1799 comedy play by the British writer Matthew Lewis. It premiered at the Theatre Royal, Drury Lane on 22 April 1799. It was partly inspired by characters from Frances Burney's Cecilia while the playbill advertised it as being inspired by the 1790 play Die Indianer in England by August von Kotzebue. The original Drury Lane cast included Robert Palmer as Lord Listless, William Barrymore as Modish, John Philip Kemble as Rivers, Charles Kemble as Beauchamp, James Aickin as Walsingham, Ralph Wewitzer as Friponeau, Thomas Hollingsworth as Squeez'em, John Bannister as Frank, Jane Powell as Mrs. Ormond, Dorothea Jordan as Zorayda and Charlotte Tidswell as Mrs. Blaball. Lewis had written the play several years earlier, and it was published in 1800 by John Bell.

References

Bibliography
 Hogan, C.B (ed.) The London Stage, 1660–1800: Volume V. Southern Illinois University Press, 1968.
 Irwin, Joseph James. M. G. "Monk" Lewis. Twayne Publishers, 1976.
 Parisian, Catherine M. Frances Burney's Cecilia: A Publishing History. Routledge, 2016.

References

Plays by Matthew Lewis
1799 plays
West End plays
Comedy plays
British plays

redpajama_set_name: RedPajamaWikipedia


Pembroke Colts & Fillies section is devoted to creating an honest, safe, friendly and supportive environment for young people - from 1st Class and 4th Year - to learn and develop their team and individual hockey skills.
Players are coached to respect the game, coaches, team mates, opponents and officials whilst developing a sense of competitiveness, team camaraderie and sportsmanship. Pembroke coaches aim to provide a high standard of coaching that creates a positive, fun and challenging experience for each player.
Pembroke Wanderers Hockey Club strives to create an environment where opportunities for excellence exist, healthy competitiveness encouraged, friendships are forged and a sense of fun and enthusiasm for the game of hockey is fostered.
Existing members (with 75% higher attendance from this season) have been invoiced (for the coming season) and the invoice must be paid in full by 30th June, 2018 to secure your place for the following season.
If 'No Communication' has been received by this date, it will be assumed that you are not returning to the club and you will be removed from our database.
Renewal is the sole responsibility of the parent and not the Club - please ensure you have paid by this date, so that you/your child/ren are not disappointed.
Existing members with less than 75% attendance from this season 'may not be invited to renew their membership for the coming season'.
Membership fee – must be paid through Smart Club – you will be invoiced to your email address, you then need to set up your account, follow the online payment instructions and make payment – Payment must be paid to secure place for next season.
Parents and Players – it is your responsibility to make sure the Club is kept informed of any changed to email, mobile phone number or address so you will always be kept informed of matches, events etc.
If any of your contact details change please email all relevant details to us ASAP. If we do not have your correct contact details you will miss out on getting important information.
Parents must ensure that their childs' "TEAMER" contact information is correct – in order to receive invitations to matches/blitzes etc.
Gum shields and shin guards are compulsory. Face masks (defending short corners) and hand guards are recommended. Footwear should be suitable for Astro Turf pitches.
Under age sides play in black tracksuit/shorts with purple Pembroke socks. A Pembroke t-shirt and hoody are available in Ed Sports, located in the Pembroke Grounds.
League teams (boys and girls (1st - 4th Year) play in full Pembroke league kit - also available in Ed Sports).
Coaches: Alison Pigot (Lead), Ivan Cooke, Ali Farrell, Paul Harrington.
Coaches: Gary Johnson (Lead), Dave Simmons, Adam Keating.
Coaches: Zack Waters (Lead), Matt Treacy, Richard / Lorraine Bryce.
Coaches: Devin Donnelly (Lead), Richard Bryce, Simon Watchorn (Management).
Purple: Hannah Watchorn (Lead), Sarah Byrne, Shane Hynes.
Boys (and U8 mixed) matches normally take place on Sunday afternoons. Girls matches take place on Sunday mornings/afternoons.
Boys U14, U16's and Girls U14, U16's play in organised Leinster Leagues.
The younger age groups play in occasional friendly matches, but the priority for these age groups is the development of hockey skills, teamwork and of course, to have fun and be safe.
Deirdre Waters our Manager has four children involved in the Junior Club, two children coaching and two children playing in the club and is a member of the Pembroke Vets.
Deirdre has several years' experience in hockey – coaching to level 1 standard, umpiring, and has held executive positions within various clubs and schools. Deirdre has held this role for the past 5 years, the junior club has grown under her leadership and direction.
Deirdre is ably assisted in Pembroke by Zack Waters, Leinster Development Coach and Junior Coach with PWHC who will take on the role as Assistant Manager.
The Designated Person is responsible for reporting any concern about the protection of children to the Statutory authorities.
A popular and long time member of the club - Sinead recently wore the green for the Masters at last summer's Home Nations.
Pembroke works closely with the IHA in order to ensure that best practice is followed in children's sport.
The Children's Officer manages all activities and issues in relation to young people at club level.
In applying the guidelines of the Code of Ethics and Good Practice for Children's Sport, Pembroke have adopted and implemented a code of conduct for all participants and must appoint a Children's Officer and a Designated Person.


Mimeo The Optical Shop - We provide no frills, affordable and personalized way of making your new pair of spectacles. Our prescription lenses and optical frames are so competitively priced making them possibly the most affordable in town. With our personalized services, you would not want to look anywhere else again to make your next pair of spectacles.
Why don't most of us put on different eyewear, like how we wear different clothing everyday to match our unique lifestyle and fashion acumen?
Complete collection of optical frames for all walks of life. If you are looking to be either Trendy+Fun, Smart Formal or Cool Classics, we have something for you.
While some customers hunt down the best deals, some value quality above all. Whether affordable or premium, we have them both at competitive prices. See it to believe it.
We like to keep things simple. We give you the right kind of service. Nothing more, nothing less, just the way you like it. Our prices are clearly listed so that you know exactly what you are paying for.
Sit back, relax and book your appointment.
Why walk into a retail store and join the crowd? We provide personalized service and commit our time to you during your appointment. You can freely browse through our frames without any pressure. Making an appointment is a breeze. Simply choose your desired time-slot preferably 2 days in advance and we will get back to you with the confirmation.


AskMeMom: Welcome Baby Kyle Nash!
On April 15th (Monday), I went to the hospital for another check-up and even went for ultrasound check, I was literally inside the hospital for half a day and comes night time, I've decided to visit my OB and let her know if I'm still fit to do 3 hours of walking per day plus some medications to help soften my pelvic bones! I was then checked for IE and was told I'm ready to give birth anytime as I'm already 3-4cm away! Mr. AMW and I looked at each other as panic struck at Mr. AMW's face. Several weeks before giving birth, I have sleepless nights worrying about labor, the pain, baby's health..everything! On that very day that the doctor advised me I'm ready to give birth, I immediately felt a rush of courage and was actually relaxed and even decided to have a light dinner at my favorite Chinese restaurant to prevent ulcer attacks!
At 10:00pm, Mr. AMW and my parents-in-law accompanied me to the hospital and we went straight to the labor room. I even joined Mr. AMW in walking from the parking lot to the labor room just to make sure the baby goes further "down". As I went in the Labor room, the lovely nurses were there cheerfully welcoming me and I'm glad because it kept my nervousness at bay! In just an hour I was told I was 5cm away and my Doctor arrived and I was instructed to be induced! In just an hour, I was rolled out to the delivery room and I wasn't able to see Mr. AMW anymore!
Though painful, I was surprisingly calm and quiet! I even had the chance to chitchat with the nurses and doctors which made it easier for me not to think about the pain! I also requested for an epidural so thankfully, the anesthesiologist came in just in time! Thank God I'm not that scared of needles and I had my appendectomy surgery many years ago so the feeling of injecting something into my spine is not foreign anymore!
A couple of waiting, I was told I'm nearing 10 cm and ready to be on active labor anytime soon! The funny thing about my pregnancy, I was very busy with working I didn't have chance to attend any pregnancy classes so I absolutely have NO IDEA how to breath! Again, thankfully, the nurses and doctor are quite supportive I was instructed on what to do and let me tell you, it's not easy and it's the most uncomfortable feeling ever but after experiencing labor, I have a million more respect to mothers now and I can't help but muster "I love you mom" inside my head!
At exactly 1:29am, for around 3.5 hours of labor, Kyle Nash finally came into the world! He was placed for a split second on my tummy area but was taken out immediately for some checks as he was born really small --- 4.8lbs to be exact!
As I was rolled out to the recovery room, I was really exhausted yet excited to meet Baby Kyle! Unfortunately, I wasn't able to seem him for awhile as several checks were done on him to make sure everything is alright!
Thankfully, we were told Kyle is one healthy and strong baby! All we need to do is to make sure he increases his weight and height and so far, after first checkup, his Pediatrician was quite happy with his weight gain!
Baby AMW today at 2 weeks 6 days!
wow lucky you your baby is safe and sound, I can't imagine 3 day labor!!! Congrats sis pa rin for a healthy baby ! 8lbs! wow!
aww thanks Gwama and thanks for visiting! i really appreciate it!
Hooray for your cutie pie!
Kisses to the whole AMW family!
yay hooray to both of us for a wonderful 2013! how's mommyhood?
thanks dear! hope to meet you in person!!!
awww..thanks! it just shows you have a lovely heart!
Such a cutie! I'm so happy for you. Being a mother is one of the best and most exciting things that can ever happen to a woman. It's hard especially if you're a working mom, but everything becomes easy as soon as you see your baby's smile. Enjoy your little bundle of joy!
Join My Super Mom + Me Giveaway.
I super agree! no matter how tired I am, I can easily do my regular job and mommy duties in no time amidst the backaches and sleepiness...with just one huge SMILE from Kyle, I am one happy and energized mom!
Congratulations Nikki! Glad that you had a normal delivery and that Kyle Nash is healthy.
Thanks PB, Kyle can't wait to meet you!
Congratulations Mr. and Mrs. AMW! So happy for you!
so happy for you too as you have a li'l bundle of joy coming your way!
Congrats Nikki! He's so cute!
thanks Gio for your well wishes!
Congratulations! He's so adorable! Nakaka-gigil!
hahahahha but I'm sure I made first 2 trimester sounds like HELL to all the girls out there! hahaha I had an awful time during pregnancy so this is a wonderful gift!
Congratulations! I have been following your blogs quietly for awhile now. Well this post just make my heart bursts with love and warmth! :) Thanks for sharing your experience!
same as you, no hubbies allowed and no mobile phone or anything so it's really lonely and boring no? I'm just lucky the nurses are nice even my doctor so I spent a bit of time chit chatting with them!
Wow..mother of 2! I can't wait to be one as well but I'm enjoying 1 bundle of joy for now! And true..daming ups and downs but super worth every single second of it!
such a cutie! welcome to the mom world miss AMW! =)please follow my blog too..


Versace has opened a boutique in Bal Harbour that mixes sustainability with an unexpected energy infused with light and shadow, substance and emptiness, and flow and focus.
The new store, located at 9700 Collins Avenue in Bal Harbour Shops was designed by renowned architect Gwenael Nicolas with the highest sustainability standards in mind, the space features a striking floor and ceiling. The brass ceiling radiates beams of rays, held delicately by a forest of bronze strings. The floor, assembled by hand by Italian artisans, is a mosaic that mixes modernity with tradition. In its commitment to sustainability, the house has reached LEED Gold-level for interior design and construction through the boutique's construction of recycled, recyclable, and responsible materials, including the glass in the mosaic, FSC-certified wood in the structure, and recomposed marble in elements throughout the space. In addition, dimmable lights with central control and climate control equipment ensure efficient use of energy.


text:
Toronto New generation of activists helping change attitudes about a persecuted minority — drug users
New generation of activists helping change attitudes about a persecuted minority — drug users
Marcus Gee
On a breezy afternoon this week, volunteers were setting up at Toronto's latest overdose-prevention site – this one established in defiance of government authority.
They erected a white tent. They unfolded three card tables. They placed the same items on each table: small, round mirror; battery-powered lamp; alcohol wipes; bottle of hand sanitizer; needle-disposal unit. They filled syringes with naloxone, the life-saving drug that reverses the effects of overdose. They put out oxygen tanks. Oxygen, too, can be a lifesaver when a drug user's respiration slows. By 6 p.m., they were ready to welcome visitors.
A scene like this is sure to make Doug Ford, Ontario's new premier, uncomfortable. A place, right out in the open, deliberately designed and equipped for taking illegal drugs? The Progressive Conservative Leader has said he is "dead against" supervised drug-use sites. This month his government hit pause on a move to open three new overdose-prevention sites. It wants to determine whether the sites – fully supported by Toronto's chief medical officer – "have merit."
One of them was to open in Parkdale, a low-income area in the west of central Toronto that has seen a rash of recent overdose deaths. So, rather than wait for the government review, a group of activists set up their tent and opened this unsanctioned site on King Street West. That must make Mr. Ford see red. He says the word "activist" like a curse. But Toronto is lucky to have dedicated, caring people like these, willing to donate their time and energy to saving lives. If this is activism, the city needs more of it.
Toronto, like the rest of the country, is suffering through what the medical officer calls an "opioid poisoning emergency." More than 300 people died of overdose in the city last year, triple the number in 2013. In the course of 12 days this summer, seven people died of overdose in just one west-end police division. Drugs are taking far more lives than the upswing in shootings and stabbings that has afflicted the city.
Governments, at first, moved slowly to face the emergency. Activists goaded them into action. They have been goading for years.
It was activists in Vancouver's rough Downtown Eastside who started needle-exchange programs to prevent the spread of AIDS and Hepatitis C. It was activists who opened Vancouver's first unsanctioned supervised-injection site. That led to the opening of the first legal injection site in North America, Insite. Encouraged by Vancouver's example, activists opened an unsanctioned site in a tent in Toronto's Moss Park last summer. The city's first official site, The Works, followed last fall.
Like the angry gay-rights leaders who pressured sluggish governments to invest in the fight against AIDS, this generation of activists is helping to change attitudes about a persecuted minority. They want us to see chronic users of illegal drugs not as ragged and dangerous subhumans but as individuals with mothers and fathers, brothers and sisters, sons and daughters. The least we owe them is a chance to survive.
Molly Bannerman, 40, was helping set up at the Parkdale site, located on a grassy strip on King near Roncesvalles Avenue. With a background in social work, she has been working for some time in harm reduction – limiting the dangers from drug use. So she was dismayed when the Ford government stopped the official Parkdale site from opening. "We know there is an acute crisis," she says. "We know that people are dying. The Parkdale community can't wait for another review."
Ms. Bannerman rejects the notion that the site somehow encourages drug use. People are using anyway, like it or not. The point of the site is to give them a safe place to do it, with trained volunteers and a nurse standing by. If someone starts showing signs of overdosing, the crew at the tent will step in. They may rub the user's sternum. They may bring out a device to check the user's oxygen levels. If things look bad, they may administer oxygen from the tank or, if necessary, inject a syringe full of naloxone in the user's thigh or arm. Scores of lives are being saved in this way.
It may make Doug Ford frown, but it's working. Toronto should thank this band of activists for leading the way.
Ontario police to meet with province over naloxone concerns
Activist group opens unsanctioned overdose-prevention site in Toronto, despite Ford government freeze
Don't ostracize drugs users – empathize with them
Follow Marcus Gee on Twitter @marcusbgee


Etihad has decided to end its Abu Dhabi to Dhaka, Bangladesh service from October 1, the airline has said according to a report.
'We can confirm that Etihad Airways will suspend flights from Abu Dhabi to Dhaka, effective on 1 October 2018," a spokesperson for the UAE's national carrier was quoted to state by from Bangladesh news outlet New Age.
However, the decision does not affect Etihad's codeshare partnership with Jet airways in Mumbai, New Delhi and Kolkata which will continue serve Bangladesh's capital, the spokesperson added.
No word has emerged on whether cargo operations between the cities would also be affected. Arabian Business has reached out to Etihad Airways for comment.


text:
SAN FRANCISCO — Elon Musk will begin laying off Twitter employees on Friday, culling the social media company's 7,500-person work force a little over a week after completing his blockbuster buyout.
Twitter employees were notified in a company-wide email that the layoffs were set to begin, according to a copy of the message seen by The New York Times. About half the company's workers appeared set to lose their jobs, according to internal messages and an investor, though the final count may take time to become clear. The email instructed Twitter employees to go home and not return to the offices on Friday as the cuts proceeded.
Mr. Musk completed his $44 billion purchase of Twitter on Oct. 27 and immediately fired its chief executive and other top managers. More executives have since resigned or were let go, while managers were asked to draw up lists of high- and low-performing employees, likely with an eye toward job cuts.
Mr. Musk, the world's richest man, faces pressure to make Twitter work financially. The deal was the largest leveraged buyout of a technology company in history. The billionaire also loaded about $13 billion in debt on Twitter for the acquisition and is on the hook to pay about $1 billion a year in interest payments. But Twitter has often lost money, and its cash flow is not robust. Mr. Musk may benefit from cutting costs so the company is less expensive to operate.
Twitter's layoffs are unlikely to be the largest in the tech industry by total number. The computer manufacturer HP cut 24,600 of its employees, about 7.5 percent, in 2008. It later cut tens of thousands more, reaching about 30 percent of its work force.
Elon Musk's Acquisition of Twitter
Card 1 of 8
A blockbuster deal. In April, Elon Musk made an unsolicited bid worth $44 billion for the social media platform, saying he wanted to turn Twitter into a private company and allow people to speak more freely on the service. Here's how the monthslong battle that followed played out:
A surprise move. On Oct. 4, Mr. Musk proposed a deal to acquire Twitter for $44 billion, the price he agreed to pay for the company in April. On Oct. 27, the purchase was completed. Mr. Musk quickly began cleaning house, with at least four top Twitter executives — including the chief executive and chief financial officer — getting fired.
More recently, other tech companies have slashed jobs. On Thursday, Lyft said it would lay off 13 percent, or about 650, of its 5,000 employees. Stripe, a payment processing platform, said it would cut 14 percent of its jobs, or roughly 1,100.
Mr. Musk has tapped advisers and investors to help him take over Twitter. He also brought in more than 50 engineers and employees from his other companies, including the electric carmaker Tesla, to review the layoff lists of Twitter employees and the social platform's technology.
While federal and California laws require companies to provide advance notice of mass layoffs, it was not clear whether Mr. Musk had done so. A spokesman for California's Employment Development Department said on Thursday evening that it had received no such notices from Twitter, which is based in San Francisco and is expected to report mass layoffs to the agency.
Rumors of impending layoffs have been swirling at Twitter. On Wednesday, employees took note of a Slack message that suggested 3,738 people could be laid off. The message noted that changes could still be made to the list, according to a copy seen by The New York Times.
That evening, some employees circulated a "Layoff Guide" with tips on corporate surveillance and employment rights. One worker created software to help colleagues download important emails and documents. He was later fired, he said.
Understand Elon Musk's Twitter Takeover
On Thursday, workers got another signal that their workplace was changing. Twitter's "Days of Rest," which are monthly days off so employees can rest and recharge, were removed from their calendars, two people with knowledge of the matter said.
Under the terms of his deal to acquirer Twitter, Mr. Musk agreed to keep employee compensation and benefits the same for one year. Twitter workers are typically paid at least two months' salary and the cash value of equity they were scheduled to receive within three months of a layoff date, according to an internal benefits summary seen by The Times.
Ryan Mac contributed reporting.
Begins, Elon, Layoffs, Musk, Twitter


I'm looking for a Packaging Engineering Technician to join a team in Newcastle.
The role is a permanent contract for a pharmaceutical organisation that offer services to the healthcare sector.
The salary range is between £26,000-£32000 (dependent on experience). Benefits include private healthcare contribution, other healthcare benefits, bonus scheme, and more.
Have served a recognised apprenticeship in an engineering discipline or equivalent.
Attained an HNC or equivalent in Electrical, Mechanical, Instrumentation & control.
An understanding of PLC/Control, Electrical/Mechanical and Pneumatic systems.
Be familiar with problem solving and process improvement techniques.
Familiarity with planned maintenance systems.
Experience of tablet filling and packaging equipment and associated systems.
Have experience within the Pharmaceutical / FMCG / Food Industry.
Be used to working in a fast moving production environment and demonstrate a methodical, proactive approach to all aspects of engineering.