Messages in this thread | | | From | Anton Chikin <> | Date | Thu, 18 Nov 2010 19:59:50 +0300 | Subject | RE: [PATCH] hid: usbhid: New hid quirks for Panasonic Elite Panaboard T-780 and T-880 |
| |
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@suse.cz] Sent: Wednesday, November 03, 2010 4:28 PM To: Anton Chikin Cc: chatty@enac.fr; spbnick@gmail.com; anisse@astier.eu; cascardo@holoscopio.com; linux-input@vger.kernel.org; linux-kernel@vger.kernel.org; linux-usb@vger.kernel.org; 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@enac.fr> * */
/* * 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@gmail.com>"); MODULE_DESCRIPTION("Panasonic UB-T780 driver"); MODULE_LICENSE("GPL"); [unhandled content-type:application/octet-stream] | |