コード例 #1
0
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_mark_busy(usbhid);
		usbhid->retry_delay = 0;
		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 -EOVERFLOW:
	case -EPIPE:		/* stall */
		usbhid_mark_busy(usbhid);
		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
		set_bit((urb->status == -EPIPE)? HID_CLEAR_HALT:HID_RESET_PENDING, &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 */
		dev_warn(&urb->dev->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) {
			err_hid("can't resubmit intr, %s-%s/input%d, status %d",
					hid_to_usb_dev(hid)->bus->bus_name,
					hid_to_usb_dev(hid)->devpath,
					usbhid->ifnum, status);
			hid_io_error(hid);
		}
	}
}
コード例 #2
0
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:			
		usbhid_mark_busy(usbhid);
		usbhid->retry_delay = 0;
		hid_input_report(urb->context, HID_INPUT_REPORT,
				 urb->transfer_buffer,
				 urb->actual_length, 1);
		
		if (hid_check_keys_pressed(hid))
			set_bit(HID_KEYS_PRESSED, &usbhid->iofl);
		else
			clear_bit(HID_KEYS_PRESSED, &usbhid->iofl);
		break;
	case -EPIPE:		
		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:	
	case -ENOENT:
	case -ESHUTDOWN:	
		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
		return;
	case -EILSEQ:		
	case -EPROTO:		
	case -ETIME:		
	case -ETIMEDOUT:	
		usbhid_mark_busy(usbhid);
		clear_bit(HID_IN_RUNNING, &usbhid->iofl);
		hid_io_error(hid);
		return;
	default:		
		dev_warn(&urb->dev->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) {
			err_hid("can't resubmit intr, %s-%s/input%d, status %d",
					hid_to_usb_dev(hid)->bus->bus_name,
					hid_to_usb_dev(hid)->devpath,
					usbhid->ifnum, status);
			hid_io_error(hid);
		}
	}
}
コード例 #3
0
ファイル: hid-ff.c プロジェクト: maliyu/SOM2416
int hid_ff_init(struct hid_device* hid)
{
	struct hid_ff_initializer *init;
	int vendor = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idVendor);
	int product = le16_to_cpu(hid_to_usb_dev(hid)->descriptor.idProduct);

	for (init = inits; init->idVendor; init++)
		if (init->idVendor == vendor && init->idProduct == product)
			break;

	return init->init(hid);
}
コード例 #4
0
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;

	r = usb_autopm_get_interface_async(usbhid->intf);
	if (r < 0)
		return -1;

	/*
	 * if the device hasn't been woken, we leave the output
	 * to resume()
	 */
	if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
		usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
		usbhid->urbout->dev = hid_to_usb_dev(hid);
		memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length);
		kfree(raw_report);

		dbg_hid("submitting out urb\n");

		if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
			hid_err(hid, "usb_submit_urb(out) failed\n");
			usb_autopm_put_interface_async(usbhid->intf);
			return -1;
		}
		usbhid->last_out = jiffies;
	}
コード例 #5
0
static int hid_submit_out(struct hid_device *hid)
{
	struct hid_report *report;
	char *raw_report;
	struct usbhid_device *usbhid = hid->driver_data;

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

	if (!test_bit(HID_REPORTED_IDLE, &usbhid->iofl)) {
		usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
		usbhid->urbout->dev = hid_to_usb_dev(hid);
		memcpy(usbhid->outbuf, raw_report, usbhid->urbout->transfer_buffer_length);
		kfree(raw_report);

		dbg_hid("submitting out urb\n");

		if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
			err_hid("usb_submit_urb(out) failed");
			return -1;
		}
	} else {
コード例 #6
0
ファイル: hid-u2fzero.c プロジェクト: avagin/linux
static int u2fzero_fill_in_urb(struct u2fzero_device *dev)
{
	struct hid_device *hdev = dev->hdev;
	struct usb_device *udev;
	struct usbhid_device *usbhid = hdev->driver_data;
	unsigned int pipe_in;
	struct usb_host_endpoint *ep;

	if (dev->hdev->bus != BUS_USB)
		return -EINVAL;

	udev = hid_to_usb_dev(hdev);

	if (!usbhid->urbout || !usbhid->urbin)
		return -ENODEV;

	ep = usb_pipe_endpoint(udev, usbhid->urbin->pipe);
	if (!ep)
		return -ENODEV;

	dev->urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->urb)
		return -ENOMEM;

	pipe_in = (usbhid->urbin->pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);

	usb_fill_int_urb(dev->urb,
		udev,
		pipe_in,
		dev->buf_in,
		HID_REPORT_SIZE,
		u2fzero_read_callback,
		NULL,
		ep->desc.bInterval);

	return 0;
}
コード例 #7
0
/* 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 = 0;

	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);
		hid_start_in(hid);
	}

	else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
		dev_dbg(&usbhid->intf->dev, "resetting device\n");
		rc = usb_lock_device_for_reset(hid_to_usb_dev(hid), usbhid->intf);
		if (rc == 0) {
			rc = usb_reset_device(hid_to_usb_dev(hid));
			usb_unlock_device(hid_to_usb_dev(hid));
		}
		clear_bit(HID_RESET_PENDING, &usbhid->iofl);
	}

	switch (rc) {
	case 0:
		if (!test_bit(HID_IN_RUNNING, &usbhid->iofl))
			hid_io_error(hid);
		break;
	default:
		hid_err(hid, "can't reset device, %s-%s/input%d, status %d\n",
			hid_to_usb_dev(hid)->bus->bus_name,
			hid_to_usb_dev(hid)->devpath,
			usbhid->ifnum, rc);
		/* FALLTHROUGH */
	case -EHOSTUNREACH:
	case -ENODEV:
	case -EINTR:
		break;
	}
}
コード例 #8
0
ファイル: hid-huion.c プロジェクト: AkyZero/wrapfs-latest
/**
 * Enable fully-functional tablet mode and determine device parameters.
 *
 * @hdev:	HID device
 */
static int huion_tablet_enable(struct hid_device *hdev)
{
	int rc;
	struct usb_device *usb_dev = hid_to_usb_dev(hdev);
	struct huion_drvdata *drvdata = hid_get_drvdata(hdev);
	__le16 buf[6];

	/*
	 * Read string descriptor containing tablet parameters. The specific
	 * string descriptor and data were discovered by sniffing the Windows
	 * driver traffic.
	 * NOTE: This enables fully-functional tablet mode.
	 */
	rc = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
				USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
				(USB_DT_STRING << 8) + 0x64,
				0x0409, buf, sizeof(buf),
				USB_CTRL_GET_TIMEOUT);
	if (rc == -EPIPE)
		hid_warn(hdev, "device parameters not found\n");
	else if (rc < 0)
		hid_warn(hdev, "failed to get device parameters: %d\n", rc);
	else if (rc != sizeof(buf))
		hid_warn(hdev, "invalid device parameters\n");
	else {
		s32 params[HUION_PH_ID_NUM];
		s32 resolution;
		__u8 *p;
		s32 v;

		/* Extract device parameters */
		params[HUION_PH_ID_X_LM] = le16_to_cpu(buf[1]);
		params[HUION_PH_ID_Y_LM] = le16_to_cpu(buf[2]);
		params[HUION_PH_ID_PRESSURE_LM] = le16_to_cpu(buf[4]);
		resolution = le16_to_cpu(buf[5]);
		if (resolution == 0) {
			params[HUION_PH_ID_X_PM] = 0;
			params[HUION_PH_ID_Y_PM] = 0;
		} else {
			params[HUION_PH_ID_X_PM] = params[HUION_PH_ID_X_LM] *
							1000 / resolution;
			params[HUION_PH_ID_Y_PM] = params[HUION_PH_ID_Y_LM] *
							1000 / resolution;
		}

		/* Allocate fixed report descriptor */
		drvdata->rdesc = devm_kmalloc(&hdev->dev,
					sizeof(huion_tablet_rdesc_template),
					GFP_KERNEL);
		if (drvdata->rdesc == NULL) {
			hid_err(hdev, "failed to allocate fixed rdesc\n");
			return -ENOMEM;
		}
		drvdata->rsize = sizeof(huion_tablet_rdesc_template);

		/* Format fixed report descriptor */
		memcpy(drvdata->rdesc, huion_tablet_rdesc_template,
			drvdata->rsize);
		for (p = drvdata->rdesc;
		     p <= drvdata->rdesc + drvdata->rsize - 4;) {
			if (p[0] == 0xFE && p[1] == 0xED && p[2] == 0x1D &&
			    p[3] < sizeof(params)) {
				v = params[p[3]];
				put_unaligned(cpu_to_le32(v), (s32 *)p);
				p += 4;
			} else {
				p++;
			}
		}
	}

	return 0;
}
コード例 #9
0
ファイル: hid-core.c プロジェクト: amuxtux/exynos4210
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_mark_busy(usbhid);
		usbhid->retry_delay = 0;
#if defined(CONFIG_TOUCHSCREEN_NEXIO_USB)
		if((hid->vendor == NEXIO_USB_TOUCH_VENDOR) && (hid->product == NEXIO_USB_TOUCH_PRODUCT))	{
			if(nexio_touch_driver_open)	{
				nexio_touch_report_data(urb->transfer_buffer, urb->actual_length);
			}
		}
		else	
#endif
#if defined(CONFIG_TOUCHSCREEN_EGALAX_USB)
		if((hid->vendor == EGALAX_USB_TOUCH_VENDOR) && (hid->product == EGALAX_USB_TOUCH_PRODUCT))	{
			if(egalax_touch_driver_open)	{
				egalax_touch_report_data(urb->transfer_buffer, urb->actual_length);
			}
		}
		else	
#endif
		{
			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);
		}
	}
}
コード例 #10
0
ファイル: hid-lg.c プロジェクト: 7799/linux
/*
 * Certain Logitech keyboards send in report #3 keys which are far
 * above the logical maximum described in descriptor. This extends
 * the original value of 0x28c of logical maximum to 0x104d
 */
static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc,
		unsigned int *rsize)
{
	struct lg_drv_data *drv_data = hid_get_drvdata(hdev);
	struct usb_device_descriptor *udesc;
	__u16 bcdDevice, rev_maj, rev_min;

	if ((drv_data->quirks & LG_RDESC) && *rsize >= 90 && rdesc[83] == 0x26 &&
			rdesc[84] == 0x8c && rdesc[85] == 0x02) {
		hid_info(hdev,
			 "fixing up Logitech keyboard report descriptor\n");
		rdesc[84] = rdesc[89] = 0x4d;
		rdesc[85] = rdesc[90] = 0x10;
	}
	if ((drv_data->quirks & LG_RDESC_REL_ABS) && *rsize >= 50 &&
			rdesc[32] == 0x81 && rdesc[33] == 0x06 &&
			rdesc[49] == 0x81 && rdesc[50] == 0x06) {
		hid_info(hdev,
			 "fixing up rel/abs in Logitech report descriptor\n");
		rdesc[33] = rdesc[50] = 0x02;
	}

	switch (hdev->product) {

	/* Several wheels report as this id when operating in emulation mode. */
	case USB_DEVICE_ID_LOGITECH_WHEEL:
		udesc = &(hid_to_usb_dev(hdev)->descriptor);
		if (!udesc) {
			hid_err(hdev, "NULL USB device descriptor\n");
			break;
		}
		bcdDevice = le16_to_cpu(udesc->bcdDevice);
		rev_maj = bcdDevice >> 8;
		rev_min = bcdDevice & 0xff;

		/* Update the report descriptor for only the Driving Force wheel */
		if (rev_maj == 1 && rev_min == 2 &&
				*rsize == DF_RDESC_ORIG_SIZE) {
			hid_info(hdev,
				"fixing up Logitech Driving Force report descriptor\n");
			rdesc = df_rdesc_fixed;
			*rsize = sizeof(df_rdesc_fixed);
		}
		break;

	case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL:
		if (*rsize == MOMO_RDESC_ORIG_SIZE) {
			hid_info(hdev,
				"fixing up Logitech Momo Force (Red) report descriptor\n");
			rdesc = momo_rdesc_fixed;
			*rsize = sizeof(momo_rdesc_fixed);
		}
		break;

	case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2:
		if (*rsize == MOMO2_RDESC_ORIG_SIZE) {
			hid_info(hdev,
				"fixing up Logitech Momo Racing Force (Black) report descriptor\n");
			rdesc = momo2_rdesc_fixed;
			*rsize = sizeof(momo2_rdesc_fixed);
		}
		break;

	case USB_DEVICE_ID_LOGITECH_VIBRATION_WHEEL:
		if (*rsize == FV_RDESC_ORIG_SIZE) {
			hid_info(hdev,
				"fixing up Logitech Formula Vibration report descriptor\n");
			rdesc = fv_rdesc_fixed;
			*rsize = sizeof(fv_rdesc_fixed);
		}
		break;

	case USB_DEVICE_ID_LOGITECH_DFP_WHEEL:
		if (*rsize == DFP_RDESC_ORIG_SIZE) {
			hid_info(hdev,
				"fixing up Logitech Driving Force Pro report descriptor\n");
			rdesc = dfp_rdesc_fixed;
			*rsize = sizeof(dfp_rdesc_fixed);
		}
		break;

	case USB_DEVICE_ID_LOGITECH_WII_WHEEL:
		if (*rsize >= 101 && rdesc[41] == 0x95 && rdesc[42] == 0x0B &&
				rdesc[47] == 0x05 && rdesc[48] == 0x09) {
			hid_info(hdev, "fixing up Logitech Speed Force Wireless report descriptor\n");
			rdesc[41] = 0x05;
			rdesc[42] = 0x09;
			rdesc[47] = 0x95;
			rdesc[48] = 0x0B;
		}
		break;
	}

	return rdesc;
}