diff options
Diffstat (limited to 'drivers/hid/hid-ntrig.c')
-rw-r--r-- | drivers/hid/hid-ntrig.c | 69 |
1 files changed, 60 insertions, 9 deletions
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index fb69b8c4953..69169efa1e1 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -90,6 +90,55 @@ struct ntrig_data { }; +/* + * This function converts the 4 byte raw firmware code into + * a string containing 5 comma separated numbers. + */ +static int ntrig_version_string(unsigned char *raw, char *buf) +{ + __u8 a = (raw[1] & 0x0e) >> 1; + __u8 b = (raw[0] & 0x3c) >> 2; + __u8 c = ((raw[0] & 0x03) << 3) | ((raw[3] & 0xe0) >> 5); + __u8 d = ((raw[3] & 0x07) << 3) | ((raw[2] & 0xe0) >> 5); + __u8 e = raw[2] & 0x07; + + /* + * As yet unmapped bits: + * 0b11000000 0b11110001 0b00011000 0b00011000 + */ + + return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e); +} + +static void ntrig_report_version(struct hid_device *hdev) +{ + int ret; + char buf[20]; + struct usb_device *usb_dev = hid_to_usb_dev(hdev); + unsigned char *data = kmalloc(8, GFP_KERNEL); + + if (!data) + goto err_free; + + ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), + USB_REQ_CLEAR_FEATURE, + USB_TYPE_CLASS | USB_RECIP_INTERFACE | + USB_DIR_IN, + 0x30c, 1, data, 8, + USB_CTRL_SET_TIMEOUT); + + if (ret == 8) { + ret = ntrig_version_string(&data[2], buf); + + dev_info(&hdev->dev, + "Firmware version: %s (%02x%02x %02x%02x)\n", + buf, data[2], data[3], data[4], data[5]); + } + +err_free: + kfree(data); +} + static ssize_t show_phys_width(struct device *dev, struct device_attribute *attr, char *buf) @@ -377,8 +426,8 @@ static struct attribute_group ntrig_attribute_group = { */ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) { struct ntrig_data *nd = hid_get_drvdata(hdev); @@ -448,13 +497,13 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, /* width/height mapped on TouchMajor/TouchMinor/Orientation */ case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MAJOR); + EV_ABS, ABS_MT_TOUCH_MAJOR); return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, - EV_ABS, ABS_MT_TOUCH_MINOR); + EV_ABS, ABS_MT_TOUCH_MINOR); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, - 0, 1, 0, 0); + 0, 1, 0, 0); return 1; } return 0; @@ -468,8 +517,8 @@ static int ntrig_input_mapping(struct hid_device *hdev, struct hid_input *hi, } static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, - struct hid_field *field, struct hid_usage *usage, - unsigned long **bit, int *max) + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) { /* No special mappings needed for the pen and single touch */ if (field->physical) @@ -489,7 +538,7 @@ static int ntrig_input_mapped(struct hid_device *hdev, struct hid_input *hi, * and call input_mt_sync after each point if necessary */ static int ntrig_event (struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value) + struct hid_usage *usage, __s32 value) { struct input_dev *input = field->hidinput->input; struct ntrig_data *nd = hid_get_drvdata(hid); @@ -848,6 +897,8 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) if (report) usbhid_submit_report(hdev, report, USB_DIR_OUT); + ntrig_report_version(hdev); + ret = sysfs_create_group(&hdev->dev.kobj, &ntrig_attribute_group); @@ -860,7 +911,7 @@ err_free: static void ntrig_remove(struct hid_device *hdev) { sysfs_remove_group(&hdev->dev.kobj, - &ntrig_attribute_group); + &ntrig_attribute_group); hid_hw_stop(hdev); kfree(hid_get_drvdata(hdev)); } |