コード例 #1
0
ファイル: rmi_hid.c プロジェクト: thypon/bowser-kernel
static int rmi_hid_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
	struct rmi_transport_device *xport = NULL;
	struct rmi_hid_data *data = NULL;
	unsigned int connect_mask = HID_CONNECT_HIDRAW | HID_CONNECT_HIDDEV;
	int ret;

	dev_dbg(&hdev->dev, "%s\n", __func__);

	xport = devm_kzalloc(&hdev->dev, sizeof(struct rmi_transport_device),
				GFP_KERNEL);
	if (!xport) {
		ret = -ENOMEM;
		goto err;
	}

	data = devm_kzalloc(&hdev->dev, sizeof(struct rmi_hid_data),
				GFP_KERNEL);
	if (!data) {
		ret =-ENOMEM;
		goto err;
	}

	data->xport = xport;

	xport->data = data;
	xport->dev = &hdev->dev;

	xport->write_block = rmi_hid_write_block;
	xport->read_block = rmi_hid_read_block;
	xport->info.proto_type = RMI_PROTOCOL_HID;
	xport->info.proto = transport_proto_name;
	xport->post_reset = rmi_hid_post_reset;
	hid_set_drvdata(hdev, xport);

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

	data->input_report_size =
		(hdev->report_enum[HID_INPUT_REPORT]
		.report_id_hash[RMI_ATTN_REPORT_ID]->size >> 3)
		+ 1 /* report id */;
	data->output_report_size =
		(hdev->report_enum[HID_OUTPUT_REPORT]
		.report_id_hash[RMI_WRITE_REPORT_ID]->size >> 3)
		+ 1 /* report id */;
	data->feature_report_size =
		(hdev->report_enum[HID_FEATURE_REPORT]
		.report_id_hash[RMI_SET_RMI_MODE_REPORT_ID]->size >> 3)
		+ 1 /* report id */;

	dev_dbg(&hdev->dev, "input report size %d\n", data->input_report_size);
	dev_dbg(&hdev->dev, "output report size %d\n",
		data->output_report_size);
	dev_dbg(&hdev->dev, "feature report size %d\n",
		data->feature_report_size);

	data->input_queue = devm_kzalloc(&hdev->dev, data->input_report_size
				* RMI_HID_INPUT_REPORT_QUEUE_LEN, GFP_KERNEL);
	if (!data->input_queue) {
		ret = -ENOMEM;
		goto err;
	}

	data->writeReport = devm_kzalloc(&hdev->dev, data->output_report_size,
				GFP_KERNEL);
	if (!data->writeReport) {
		ret = -ENOMEM;
		goto err;
	}

	data->readReport = devm_kzalloc(&hdev->dev, data->input_report_size,
				GFP_KERNEL);
	if (!data->readReport) {
		ret = -ENOMEM;
		goto err;
	}

	data->attnReport = devm_kzalloc(&hdev->dev, data->input_report_size,
				GFP_KERNEL);
	if (!data->attnReport) {
		ret = -ENOMEM;
		goto err;
	}

	tp_platformdata.pm_data = hdev;
	xport->dev->platform_data = &tp_platformdata;

#ifdef TOUCHPAD_WAKE_SYSTEM
	if (tp_platformdata.f11_sensor_data[0].sensor_type == rmi_sensor_touchpad) {
		device_init_wakeup(hdev->dev.parent, 1);
	}
#endif

	spin_lock_init(&data->input_queue_consumer_lock);
	spin_lock_init(&data->input_queue_producer_lock);
	data->input_queue_head = 0;
	data->input_queue_tail = 0;
	INIT_WORK(&data->attn_report_work, rmi_hid_attn_report_work);
	INIT_WORK(&data->reset_work, rmi_hid_reset_work);
	init_waitqueue_head(&data->wait);

	mutex_init(&data->page_mutex);

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

	dev_dbg(&hdev->dev, "Opening low level driver\n");
	hdev->ll_driver->open(hdev);

	/* Allow incoming hid reports */
	hid_device_io_start(hdev);

	ret = rmi_hid_set_mode(hdev, RMI_HID_MODE_ATTN_REPORTS);
	if (ret < 0) {
		dev_err(&hdev->dev, "failed to set rmi mode\n");
		goto rmi_read_failed;
	}

	ret = rmi_set_page(xport, 0);
	if (ret < 0) {
		dev_err(&hdev->dev, "failed to set page select to 0.\n");
		goto rmi_read_failed;
	}

	ret = rmi_register_transport_device(xport);
	if (ret) {
		dev_err(&hdev->dev, "failed to register transport device at %s\n",
			hdev->phys);
		goto rmi_read_failed;
	}

	if (!xport->probe_succeeded) {
		dev_err(&hdev->dev, "Probe failed in rmi_driver\n");
		ret = -ENODEV;
		goto rmi_driver_probe_failed;
	}

	set_bit(RMI_HID_STARTED, &data->flags);

	if (IS_ENABLED(CONFIG_RMI4_DEBUG))
		ret = setup_debugfs(xport->rmi_dev, data);

	dev_info(&hdev->dev, "registered rmi hid driver at %s\n", hdev->phys);

	return 0;

rmi_driver_probe_failed:
	rmi_unregister_transport_device(xport);

rmi_read_failed:
	hdev->ll_driver->close(hdev);
	hid_hw_stop(hdev);

err:
	return ret;
}
コード例 #2
0
static int logi_dj_probe(struct hid_device *hdev,
			 const struct hid_device_id *id)
{
	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
	struct dj_receiver_dev *djrcv_dev;
	int retval;

	if (is_dj_device((struct dj_device *)hdev->driver_data))
		return -ENODEV;

	dbg_hid("%s called for ifnum %d\n", __func__,
		intf->cur_altsetting->desc.bInterfaceNumber);

	/* Ignore interfaces 0 and 1, they will not carry any data, dont create
	 * any hid_device for them */
	if (intf->cur_altsetting->desc.bInterfaceNumber !=
	    LOGITECH_DJ_INTERFACE_NUMBER) {
		dbg_hid("%s: ignoring ifnum %d\n", __func__,
			intf->cur_altsetting->desc.bInterfaceNumber);
		return -ENODEV;
	}

	/* Treat interface 2 */

	djrcv_dev = kzalloc(sizeof(struct dj_receiver_dev), GFP_KERNEL);
	if (!djrcv_dev) {
		dev_err(&hdev->dev,
			"%s:failed allocating dj_receiver_dev\n", __func__);
		return -ENOMEM;
	}
	djrcv_dev->hdev = hdev;
	INIT_WORK(&djrcv_dev->work, delayedwork_callback);
	spin_lock_init(&djrcv_dev->lock);
	if (kfifo_alloc(&djrcv_dev->notif_fifo,
			DJ_MAX_NUMBER_NOTIFICATIONS * sizeof(struct dj_report),
			GFP_KERNEL)) {
		dev_err(&hdev->dev,
			"%s:failed allocating notif_fifo\n", __func__);
		kfree(djrcv_dev);
		return -ENOMEM;
	}
	hid_set_drvdata(hdev, djrcv_dev);

	/* Call  to usbhid to fetch the HID descriptors of interface 2 and
	 * subsequently call to the hid/hid-core to parse the fetched
	 * descriptors, this will in turn create the hidraw and hiddev nodes
	 * for interface 2 of the receiver */
	retval = hid_parse(hdev);
	if (retval) {
		dev_err(&hdev->dev,
			"%s:parse of interface 2 failed\n", __func__);
		goto hid_parse_fail;
	}

	if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, REPORT_ID_DJ_SHORT,
				 0, DJREPORT_SHORT_LENGTH - 1)) {
		retval = -ENODEV;
		goto hid_parse_fail;
	}

	/* Starts the usb device and connects to upper interfaces hiddev and
	 * hidraw */
	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
	if (retval) {
		dev_err(&hdev->dev,
			"%s:hid_hw_start returned error\n", __func__);
		goto hid_hw_start_fail;
	}

	retval = logi_dj_recv_switch_to_dj_mode(djrcv_dev, 0);
	if (retval < 0) {
		dev_err(&hdev->dev,
			"%s:logi_dj_recv_switch_to_dj_mode returned error:%d\n",
			__func__, retval);
		goto switch_to_dj_mode_fail;
	}

	/* This is enabling the polling urb on the IN endpoint */
	retval = hdev->ll_driver->open(hdev);
	if (retval < 0) {
		dev_err(&hdev->dev, "%s:hdev->ll_driver->open returned "
			"error:%d\n", __func__, retval);
		goto llopen_failed;
	}

	/* Allow incoming packets to arrive: */
	hid_device_io_start(hdev);

	retval = logi_dj_recv_query_paired_devices(djrcv_dev);
	if (retval < 0) {
		dev_err(&hdev->dev, "%s:logi_dj_recv_query_paired_devices "
			"error:%d\n", __func__, retval);
		goto logi_dj_recv_query_paired_devices_failed;
	}

	return retval;

logi_dj_recv_query_paired_devices_failed:
	hdev->ll_driver->close(hdev);

llopen_failed:
switch_to_dj_mode_fail:
	hid_hw_stop(hdev);

hid_hw_start_fail:
hid_parse_fail:
	kfifo_free(&djrcv_dev->notif_fifo);
	kfree(djrcv_dev);
	hid_set_drvdata(hdev, NULL);
	return retval;

}
コード例 #3
0
ファイル: rtc-hid-sensor-time.c プロジェクト: 020gzh/linux
static int hid_time_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
	struct hid_time_state *time_state = devm_kzalloc(&pdev->dev,
		sizeof(struct hid_time_state), GFP_KERNEL);

	if (time_state == NULL)
		return -ENOMEM;

	platform_set_drvdata(pdev, time_state);

	spin_lock_init(&time_state->lock_last_time);
	init_completion(&time_state->comp_last_time);
	time_state->common_attributes.hsdev = hsdev;
	time_state->common_attributes.pdev = pdev;

	ret = hid_sensor_parse_common_attributes(hsdev,
				HID_USAGE_SENSOR_TIME,
				&time_state->common_attributes);
	if (ret) {
		dev_err(&pdev->dev, "failed to setup common attributes!\n");
		return ret;
	}

	ret = hid_time_parse_report(pdev, hsdev, HID_USAGE_SENSOR_TIME,
					time_state);
	if (ret) {
		dev_err(&pdev->dev, "failed to setup attributes!\n");
		return ret;
	}

	time_state->callbacks.send_event = hid_time_proc_event;
	time_state->callbacks.capture_sample = hid_time_capture_sample;
	time_state->callbacks.pdev = pdev;
	ret = sensor_hub_register_callback(hsdev, HID_USAGE_SENSOR_TIME,
					&time_state->callbacks);
	if (ret < 0) {
		dev_err(&pdev->dev, "register callback failed!\n");
		return ret;
	}

	ret = sensor_hub_device_open(hsdev);
	if (ret) {
		dev_err(&pdev->dev, "failed to open sensor hub device!\n");
		goto err_open;
	}

	/*
	 * Enable HID input processing early in order to be able to read the
	 * clock already in devm_rtc_device_register().
	 */
	hid_device_io_start(hsdev->hdev);

	time_state->rtc = devm_rtc_device_register(&pdev->dev,
					"hid-sensor-time", &hid_time_rtc_ops,
					THIS_MODULE);

	if (IS_ERR_OR_NULL(time_state->rtc)) {
		hid_device_io_stop(hsdev->hdev);
		ret = time_state->rtc ? PTR_ERR(time_state->rtc) : -ENODEV;
		time_state->rtc = NULL;
		dev_err(&pdev->dev, "rtc device register failed!\n");
		goto err_rtc;
	}

	return ret;

err_rtc:
	sensor_hub_device_close(hsdev);
err_open:
	sensor_hub_remove_callback(hsdev, HID_USAGE_SENSOR_TIME);
	return ret;
}