RE: [PATCH] hid: usbhid: New hid quirks for Panasonic Elite Panaboard T-780 and T-880

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Jiri,

Actually our driver is implemented as the fork of usbhid driver. I'm now trying to move to HID bus. I think I need some help with this. 
I've copied /drivers/hid/hid-cando.c source code, changed device IDs in hid_driver structure, added my device IDs to /drivers/hid/hid-core.c hid_blacklist[] array, but my probe() method still never get called. Could you please help me with this?

My driver code and Makefile are in attachment.

Thank you.

-----Original Message-----
From: Jiri Kosina [mailto:jkosina@xxxxxxx] 
Sent: Wednesday, November 03, 2010 4:28 PM
To: Anton Chikin
Cc: chatty@xxxxxxx; spbnick@xxxxxxxxx; anisse@xxxxxxxxx; cascardo@xxxxxxxxxxxxxx; linux-input@xxxxxxxxxxxxxxx; linux-kernel@xxxxxxxxxxxxxxx; linux-usb@xxxxxxxxxxxxxxx; Gregory Burmistrov; Paul Osborn
Subject: RE: [PATCH] hid: usbhid: New hid quirks for Panasonic Elite Panaboard T-780 and T-880

On Tue, 2 Nov 2010, Anton Chikin wrote:

> Thank you for your feedback.
> 
> With the generic hid driver device is working in mouse-mode, turning 
> it into the huge touchscreen, which is completely useless for the end-user.

Still, at least some very basic and limited/crippled functionality is there. So my preferred mode of operation now would be having the device being claimed by generic driver and wait for your proper full-fledged driver.

> On some Linux systems hid driver is loaded from init.rd image, so we 
> can't feed our quirks to it while boot process and we can't rebuild 
> init.rd image on the user's machine because some Linux distributives 
> doesn't have special tools preinstalled.
> 
> We are going to submit our driver to the Linux kernel quickly, so 
> everyone can improve it.

That would be great, I'll be happy to review and merge it. Are you planning to have it as a driver on HID bus, or completely separate USB driver?

Thanks,

--
Jiri Kosina
SUSE Labs, Novell Inc.
/*
 *  HID driver for Cando dual-touch panels
 *
 *  Copyright (c) 2010 Stephane Chatty <chatty@xxxxxxx>
 *
 */

/*
 * 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/device.h>
#include <linux/hid.h>
#include <linux/module.h>
#include <linux/slab.h>


#include "hid-ids.h"
#include "usbubt.h"
#define UBT780_DEBUG

#ifdef UBT780_DEBUG
#define UBT_DUMMY_DEBUG if(ubt_debug) printk(KERN_DEBUG "ubt780: %s:%s line %i\n", __FILE__,__FUNCTION__ , __LINE__);
#else
#define UBT_DUMMY_DEBUG
#endif

static int ubt_debug=0;
module_param_named(debug_enabled, ubt_debug, int, 0600);
MODULE_PARM_DESC(debug_enabled, "toggle UBT debugging messages");

struct ubt780_data {
	struct ubt780_calib calib;
	struct ubt780_dgtzr ubt_packet;
};

static int ubt780_input_mapping(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
{
	UBT_DUMMY_DEBUG
	switch (usage->hid & HID_USAGE_PAGE) {

	case HID_UP_GENDESK:
		switch (usage->hid) {
		case HID_GD_X:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_X);
			/* touchscreen emulation */
			input_set_abs_params(hi->input, ABS_X,
						field->logical_minimum,
						field->logical_maximum, 0, 0);
			return 1;
		case HID_GD_Y:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_POSITION_Y);
			/* touchscreen emulation */
			input_set_abs_params(hi->input, ABS_Y,
						field->logical_minimum,
						field->logical_maximum, 0, 0);
			return 1;
		}
		return 0;

	case HID_UP_DIGITIZER:
		switch (usage->hid) {
		case HID_DG_TIPSWITCH:
		case HID_DG_CONTACTMAX:
			return -1;
		case HID_DG_INRANGE:
			/* touchscreen emulation */
			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
			return 1;
		case HID_DG_CONTACTID:
			hid_map_usage(hi, usage, bit, max,
					EV_ABS, ABS_MT_TRACKING_ID);
			return 1;
		}
		return 0;
	}

	return 0;
}

static int ubt780_input_mapped(struct hid_device *hdev, struct hid_input *hi,
		struct hid_field *field, struct hid_usage *usage,
		unsigned long **bit, int *max)
{
	UBT_DUMMY_DEBUG
	if (usage->type == EV_KEY || usage->type == EV_ABS)
		clear_bit(usage->code, *bit);

	return 0;
}

/*
 * this function is called when a whole finger has been parsed,
 * so that it can decide what to send to the input layer.
 */
static void ubt780_filter_event(struct ubt780_data *td, struct input_dev *input)
{
	//td->first = !td->first; /* touchscreen emulation */

	//if (!td->valid) {
	//	/*
	//	 * touchscreen emulation: if this is the second finger and
	//	 * the first was valid, the first was the oldest; if the
	//	 * first was not valid and there was a valid finger in the
	//	 * previous frame, this is a release.
	//	 */
	//	if (td->first) {
	//		td->firstid = -1;
	//	} else if (td->firstid >= 0) {
	//		input_event(input, EV_ABS, ABS_X, td->firstx);
	//		input_event(input, EV_ABS, ABS_Y, td->firsty);
	//		td->oldest = td->firstid;
	//	} else if (td->oldest >= 0) {
	//		input_event(input, EV_KEY, BTN_TOUCH, 0);
	//		td->oldest = -1;
	//	}

	//	return;
	//}
	//
	//input_event(input, EV_ABS, ABS_MT_TRACKING_ID, td->id);
	//input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
	//input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);

	//input_mt_sync(input);

	///*
	// * touchscreen emulation: if there was no touching finger previously,
	// * emit touch event
	// */
	//if (td->oldest < 0) {
	//	input_event(input, EV_KEY, BTN_TOUCH, 1);
	//	td->oldest = td->id;
	//}

	///*
	// * touchscreen emulation: if this is the first finger, wait for the
	// * second; the oldest is then the second if it was the oldest already
	// * or if there was no first, the first otherwise.
	// */
	//if (td->first) {
	//	td->firstx = td->x;
	//	td->firsty = td->y;
	//	td->firstid = td->id;
	//} else {
	//	int x, y, oldest;
	//	if (td->id == td->oldest || td->firstid < 0) {
	//		x = td->x;
	//		y = td->y;
	//		oldest = td->id;
	//	} else {
	//		x = td->firstx;
	//		y = td->firsty;
	//		oldest = td->firstid;
	//	}
	//	input_event(input, EV_ABS, ABS_X, x);
	//	input_event(input, EV_ABS, ABS_Y, y);
	//	td->oldest = oldest;
	//}
}


static int ubt780_event(struct hid_device *hid, struct hid_field *field,
				struct hid_usage *usage, __s32 value)
{
	struct ubt780_data *td = hid_get_drvdata(hid);

	UBT_DUMMY_DEBUG

	if (hid->claimed & HID_CLAIMED_INPUT) {
		struct input_dev *input = field->hidinput->input;

		switch (usage->hid) {
		case HID_DG_INRANGE:
			//td->valid = value;
	   		 UBT_DUMMY_DEBUG
			break;
		case HID_DG_CONTACTID:
			//td->id = value;
			UBT_DUMMY_DEBUG
			break;
		case HID_GD_X:
			//td->x = value;
			UBT_DUMMY_DEBUG
			break;
		case HID_GD_Y:
			//td->y = value;
			UBT_DUMMY_DEBUG
			//ubt780_filter_event(td, input);
			break;
		case HID_DG_TIPSWITCH:
			/* avoid interference from generic hidinput handling */
			UBT_DUMMY_DEBUG
			break;

		default:
			/* fallback to the generic hidinput handling */
			return 0;
		}
	}

	/* we have handled the hidinput part, now remains hiddev */
	if (hid->claimed & HID_CLAIMED_HIDDEV && hid->hiddev_hid_event)
		hid->hiddev_hid_event(hid, field, usage, value);

	return 1;
}

static int ubt780_probe(struct hid_device *hdev, const struct hid_device_id *id)
{
	int ret;
	struct ubt780_data *td;

	UBT_DUMMY_DEBUG

	td = kmalloc(sizeof(struct ubt780_data), GFP_KERNEL);
	if (!td) {
		dev_err(&hdev->dev, "cannot allocate UB-T780 data\n");
		return -ENOMEM;
	}


	hid_set_drvdata(hdev, td);
	/*td->first = false;
	td->oldest = -1;
	td->valid = false;*/

	ret = hid_parse(hdev);
	if (!ret)
		ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);

	if (ret)
		kfree(td);

	return ret;
}

static void ubt780_remove(struct hid_device *hdev)
{
	UBT_DUMMY_DEBUG
	hid_hw_stop(hdev);
	kfree(hid_get_drvdata(hdev));
	hid_set_drvdata(hdev, NULL);
}

static struct hid_device_id ubt780_devices[] = {
	{ HID_USB_DEVICE(0x04da, 0x1044) }, 
	{ }
};
MODULE_DEVICE_TABLE(hid, ubt780_devices);

static const struct hid_usage_id ubt780_grabbed_usages[] = {
	{ HID_ANY_ID, HID_ANY_ID, HID_ANY_ID },
	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1}
};

static struct hid_driver ubt780_driver = {
	.name = "ubt780",
	.id_table = ubt780_devices,
	.probe = ubt780_probe,
//	.remove = ubt780_remove,
//	.input_mapping = ubt780_input_mapping,
//	.input_mapped = ubt780_input_mapped,
//	.usage_table = ubt780_grabbed_usages,
//	.event = ubt780_event,
};

static int __init ubt780_init(void)
{
	UBT_DUMMY_DEBUG
	int retval = hid_register_driver(&ubt780_driver);

	if(retval)
		UBT_DUMMY_DEBUG

	return 0; 
}

static void __exit ubt780_exit(void)
{
	UBT_DUMMY_DEBUG
	hid_unregister_driver(&ubt780_driver);
}

module_init(ubt780_init);
module_exit(ubt780_exit);

MODULE_AUTHOR("Anton Chikin <kverloin@xxxxxxxxx>");
MODULE_DESCRIPTION("Panasonic UB-T780 driver");
MODULE_LICENSE("GPL");

Attachment: Makefile
Description: Makefile


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux