/* * HID driver for Cando dual-touch panels * * Copyright (c) 2010 Stephane Chatty * */ /* * 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 #include #include #include #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 "); MODULE_DESCRIPTION("Panasonic UB-T780 driver"); MODULE_LICENSE("GPL");