Ejemplo n.º 1
0
static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
	unsigned long quirks = id->driver_data;
	unsigned int connect_mask = HID_CONNECT_DEFAULT;
	int ret;

	hid_set_drvdata(hdev, (void *)quirks);

	if (quirks & LG_NOGET)
		hdev->quirks |= HID_QUIRK_NOGET;

	ret = hid_parse(hdev);
	if (ret) {
		hid_err(hdev, "parse failed\n");
		goto err_free;
	}

	if (quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
		connect_mask &= ~HID_CONNECT_FF;

	ret = hid_hw_start(hdev, connect_mask);
	if (ret) {
		hid_err(hdev, "hw start failed\n");
		goto err_free;
	}

	/* Setup wireless link with Logitech Wii wheel */
	if(hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

		ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);

		if (ret >= 0) {
			/* insert a little delay of 10 jiffies ~ 40ms */
			wait_queue_head_t wait;
			init_waitqueue_head (&wait);
			wait_event_interruptible_timeout(wait, 0, 10);

			/* Select random Address */
			buf[1] = 0xB2;
			get_random_bytes(&buf[2], 2);

			ret = hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT);
		}
	}

	if (quirks & LG_FF)
		lgff_init(hdev);
	if (quirks & LG_FF2)
		lg2ff_init(hdev);
	if (quirks & LG_FF3)
		lg3ff_init(hdev);
	if (quirks & LG_FF4)
		lg4ff_init(hdev);

	return 0;
err_free:
	return ret;
}
Ejemplo n.º 2
0
static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
	struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
	__u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
	unsigned int connect_mask = HID_CONNECT_DEFAULT;
	struct lg_drv_data *drv_data;
	int ret;

	/* G29 only work with the 1st interface */
	if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
	    (iface_num != 0)) {
		dbg_hid("%s: ignoring ifnum %d\n", __func__, iface_num);
		return -ENODEV;
	}

	drv_data = kzalloc(sizeof(struct lg_drv_data), GFP_KERNEL);
	if (!drv_data) {
		hid_err(hdev, "Insufficient memory, cannot allocate driver data\n");
		return -ENOMEM;
	}
	drv_data->quirks = id->driver_data;

	hid_set_drvdata(hdev, (void *)drv_data);

	if (drv_data->quirks & LG_NOGET)
		hdev->quirks |= HID_QUIRK_NOGET;

	ret = hid_parse(hdev);
	if (ret) {
		hid_err(hdev, "parse failed\n");
		goto err_free;
	}

	if (drv_data->quirks & (LG_FF | LG_FF2 | LG_FF3 | LG_FF4))
		connect_mask &= ~HID_CONNECT_FF;

	ret = hid_hw_start(hdev, connect_mask);
	if (ret) {
		hid_err(hdev, "hw start failed\n");
		goto err_free;
	}

	/* Setup wireless link with Logitech Wii wheel */
	if (hdev->product == USB_DEVICE_ID_LOGITECH_WII_WHEEL) {
		unsigned char buf[] = { 0x00, 0xAF,  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

		ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);

		if (ret >= 0) {
			/* insert a little delay of 10 jiffies ~ 40ms */
			wait_queue_head_t wait;
			init_waitqueue_head (&wait);
			wait_event_interruptible_timeout(wait, 0,
							 msecs_to_jiffies(40));

			/* Select random Address */
			buf[1] = 0xB2;
			get_random_bytes(&buf[2], 2);

			ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf),
					HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
		}
	}

	if (drv_data->quirks & LG_FF)
		ret = lgff_init(hdev);
	else if (drv_data->quirks & LG_FF2)
		ret = lg2ff_init(hdev);
	else if (drv_data->quirks & LG_FF3)
		ret = lg3ff_init(hdev);
	else if (drv_data->quirks & LG_FF4)
		ret = lg4ff_init(hdev);

	if (ret)
		goto err_free;

	return 0;
err_free:
	kfree(drv_data);
	return ret;
}