Error Trace

[Home]

Bug # 60

Show/hide error trace
Error trace
Function bodies
Blocks
  • Others...
    Function bodies without model function calls
    Initialization function calls
    Initialization function bodies
    Entry point
    Entry point body
    Function calls
    Skipped function calls
    Formal parameter names
    Declarations
    Assumes
    Assume conditions
    Returns
    Return values
    DEG initialization
    DEG function calls
    Model function calls
    Model function bodies
    Model asserts
    Model state changes
    Model function function calls
    Model function function bodies
    Model returns
    Model others
    Identation
    Line numbers
    Expand signs
-__BLAST_initialize_/work/ldvuser/ref_launch/work/current--X--drivers--X--defaultlinux-4.0-rc1.tar.xz--X--151_1a/linux-4.0-rc1.tar.xz/csd_deg_dscv/564/dscv_tempdir/dscv/rcv/151_1a/main-ldv_main0_sequence_infinite_withcheck_stateful/preprocess/1-cpp/drivers/hid/hid-lenovo.o.i()
{
15 -LDV_SYSFS_GROUPS = 0;
dev_attr_fn_lock_cptkbd.attr.name = "fn_lock";
dev_attr_fn_lock_cptkbd.attr.mode = 420;
dev_attr_fn_lock_cptkbd.attr.ignore_lockdep = 0;
dev_attr_fn_lock_cptkbd.attr.key = 0;
dev_attr_fn_lock_cptkbd.attr.skey.subkeys[ 0 ].__one_byte = 0;
dev_attr_fn_lock_cptkbd.attr.skey.subkeys[ 1 ].__one_byte = 0;
dev_attr_fn_lock_cptkbd.attr.skey.subkeys[ 2 ].__one_byte = 0;
dev_attr_fn_lock_cptkbd.attr.skey.subkeys[ 3 ].__one_byte = 0;
dev_attr_fn_lock_cptkbd.attr.skey.subkeys[ 4 ].__one_byte = 0;
dev_attr_fn_lock_cptkbd.attr.skey.subkeys[ 5 ].__one_byte = 0;
dev_attr_fn_lock_cptkbd.attr.skey.subkeys[ 6 ].__one_byte = 0;
dev_attr_fn_lock_cptkbd.attr.skey.subkeys[ 7 ].__one_byte = 0;
dev_attr_fn_lock_cptkbd.show = &(attr_fn_lock_show_cptkbd);
dev_attr_fn_lock_cptkbd.store = &(attr_fn_lock_store_cptkbd);
dev_attr_sensitivity_cptkbd.attr.name = "sensitivity";
dev_attr_sensitivity_cptkbd.attr.mode = 420;
dev_attr_sensitivity_cptkbd.attr.ignore_lockdep = 0;
dev_attr_sensitivity_cptkbd.attr.key = 0;
dev_attr_sensitivity_cptkbd.attr.skey.subkeys[ 0 ].__one_byte = 0;
dev_attr_sensitivity_cptkbd.attr.skey.subkeys[ 1 ].__one_byte = 0;
dev_attr_sensitivity_cptkbd.attr.skey.subkeys[ 2 ].__one_byte = 0;
dev_attr_sensitivity_cptkbd.attr.skey.subkeys[ 3 ].__one_byte = 0;
dev_attr_sensitivity_cptkbd.attr.skey.subkeys[ 4 ].__one_byte = 0;
dev_attr_sensitivity_cptkbd.attr.skey.subkeys[ 5 ].__one_byte = 0;
dev_attr_sensitivity_cptkbd.attr.skey.subkeys[ 6 ].__one_byte = 0;
dev_attr_sensitivity_cptkbd.attr.skey.subkeys[ 7 ].__one_byte = 0;
dev_attr_sensitivity_cptkbd.show = &(attr_sensitivity_show_cptkbd);
dev_attr_sensitivity_cptkbd.store = &(attr_sensitivity_store_cptkbd);
lenovo_attributes_cptkbd[ 0 ] = &(&(dev_attr_fn_lock_cptkbd))->attr;
lenovo_attributes_cptkbd[ 1 ] = &(&(dev_attr_sensitivity_cptkbd))->attr;
lenovo_attributes_cptkbd[ 2 ] = 0;
lenovo_attr_group_cptkbd.name = 0;
lenovo_attr_group_cptkbd.is_visible = 0;
lenovo_attr_group_cptkbd.attrs = &(lenovo_attributes_cptkbd);
lenovo_attr_group_cptkbd.bin_attrs = 0;
dev_attr_press_to_select_tpkbd.attr.name = "press_to_select";
dev_attr_press_to_select_tpkbd.attr.mode = 420;
dev_attr_press_to_select_tpkbd.attr.ignore_lockdep = 0;
dev_attr_press_to_select_tpkbd.attr.key = 0;
dev_attr_press_to_select_tpkbd.attr.skey.subkeys[ 0 ].__one_byte = 0;
dev_attr_press_to_select_tpkbd.attr.skey.subkeys[ 1 ].__one_byte = 0;
dev_attr_press_to_select_tpkbd.attr.skey.subkeys[ 2 ].__one_byte = 0;
dev_attr_press_to_select_tpkbd.attr.skey.subkeys[ 3 ].__one_byte = 0;
dev_attr_press_to_select_tpkbd.attr.skey.subkeys[ 4 ].__one_byte = 0;
dev_attr_press_to_select_tpkbd.attr.skey.subkeys[ 5 ].__one_byte = 0;
dev_attr_press_to_select_tpkbd.attr.skey.subkeys[ 6 ].__one_byte = 0;
dev_attr_press_to_select_tpkbd.attr.skey.subkeys[ 7 ].__one_byte = 0;
dev_attr_press_to_select_tpkbd.show = &(attr_press_to_select_show_tpkbd);
dev_attr_press_to_select_tpkbd.store = &(attr_press_to_select_store_tpkbd);
dev_attr_dragging_tpkbd.attr.name = "dragging";
dev_attr_dragging_tpkbd.attr.mode = 420;
dev_attr_dragging_tpkbd.attr.ignore_lockdep = 0;
dev_attr_dragging_tpkbd.attr.key = 0;
dev_attr_dragging_tpkbd.attr.skey.subkeys[ 0 ].__one_byte = 0;
dev_attr_dragging_tpkbd.attr.skey.subkeys[ 1 ].__one_byte = 0;
dev_attr_dragging_tpkbd.attr.skey.subkeys[ 2 ].__one_byte = 0;
dev_attr_dragging_tpkbd.attr.skey.subkeys[ 3 ].__one_byte = 0;
dev_attr_dragging_tpkbd.attr.skey.subkeys[ 4 ].__one_byte = 0;
dev_attr_dragging_tpkbd.attr.skey.subkeys[ 5 ].__one_byte = 0;
dev_attr_dragging_tpkbd.attr.skey.subkeys[ 6 ].__one_byte = 0;
dev_attr_dragging_tpkbd.attr.skey.subkeys[ 7 ].__one_byte = 0;
dev_attr_dragging_tpkbd.show = &(attr_dragging_show_tpkbd);
dev_attr_dragging_tpkbd.store = &(attr_dragging_store_tpkbd);
dev_attr_release_to_select_tpkbd.attr.name = "release_to_select";
dev_attr_release_to_select_tpkbd.attr.mode = 420;
dev_attr_release_to_select_tpkbd.attr.ignore_lockdep = 0;
dev_attr_release_to_select_tpkbd.attr.key = 0;
dev_attr_release_to_select_tpkbd.attr.skey.subkeys[ 0 ].__one_byte = 0;
dev_attr_release_to_select_tpkbd.attr.skey.subkeys[ 1 ].__one_byte = 0;
dev_attr_release_to_select_tpkbd.attr.skey.subkeys[ 2 ].__one_byte = 0;
dev_attr_release_to_select_tpkbd.attr.skey.subkeys[ 3 ].__one_byte = 0;
dev_attr_release_to_select_tpkbd.attr.skey.subkeys[ 4 ].__one_byte = 0;
dev_attr_release_to_select_tpkbd.attr.skey.subkeys[ 5 ].__one_byte = 0;
dev_attr_release_to_select_tpkbd.attr.skey.subkeys[ 6 ].__one_byte = 0;
dev_attr_release_to_select_tpkbd.attr.skey.subkeys[ 7 ].__one_byte = 0;
dev_attr_release_to_select_tpkbd.show = &(attr_release_to_select_show_tpkbd);
dev_attr_release_to_select_tpkbd.store = &(attr_release_to_select_store_tpkbd);
dev_attr_select_right_tpkbd.attr.name = "select_right";
dev_attr_select_right_tpkbd.attr.mode = 420;
dev_attr_select_right_tpkbd.attr.ignore_lockdep = 0;
dev_attr_select_right_tpkbd.attr.key = 0;
dev_attr_select_right_tpkbd.attr.skey.subkeys[ 0 ].__one_byte = 0;
dev_attr_select_right_tpkbd.attr.skey.subkeys[ 1 ].__one_byte = 0;
dev_attr_select_right_tpkbd.attr.skey.subkeys[ 2 ].__one_byte = 0;
dev_attr_select_right_tpkbd.attr.skey.subkeys[ 3 ].__one_byte = 0;
dev_attr_select_right_tpkbd.attr.skey.subkeys[ 4 ].__one_byte = 0;
dev_attr_select_right_tpkbd.attr.skey.subkeys[ 5 ].__one_byte = 0;
dev_attr_select_right_tpkbd.attr.skey.subkeys[ 6 ].__one_byte = 0;
dev_attr_select_right_tpkbd.attr.skey.subkeys[ 7 ].__one_byte = 0;
dev_attr_select_right_tpkbd.show = &(attr_select_right_show_tpkbd);
dev_attr_select_right_tpkbd.store = &(attr_select_right_store_tpkbd);
dev_attr_sensitivity_tpkbd.attr.name = "sensitivity";
dev_attr_sensitivity_tpkbd.attr.mode = 420;
dev_attr_sensitivity_tpkbd.attr.ignore_lockdep = 0;
dev_attr_sensitivity_tpkbd.attr.key = 0;
dev_attr_sensitivity_tpkbd.attr.skey.subkeys[ 0 ].__one_byte = 0;
dev_attr_sensitivity_tpkbd.attr.skey.subkeys[ 1 ].__one_byte = 0;
dev_attr_sensitivity_tpkbd.attr.skey.subkeys[ 2 ].__one_byte = 0;
dev_attr_sensitivity_tpkbd.attr.skey.subkeys[ 3 ].__one_byte = 0;
dev_attr_sensitivity_tpkbd.attr.skey.subkeys[ 4 ].__one_byte = 0;
dev_attr_sensitivity_tpkbd.attr.skey.subkeys[ 5 ].__one_byte = 0;
dev_attr_sensitivity_tpkbd.attr.skey.subkeys[ 6 ].__one_byte = 0;
dev_attr_sensitivity_tpkbd.attr.skey.subkeys[ 7 ].__one_byte = 0;
dev_attr_sensitivity_tpkbd.show = &(attr_sensitivity_show_tpkbd);
dev_attr_sensitivity_tpkbd.store = &(attr_sensitivity_store_tpkbd);
dev_attr_press_speed_tpkbd.attr.name = "press_speed";
dev_attr_press_speed_tpkbd.attr.mode = 420;
dev_attr_press_speed_tpkbd.attr.ignore_lockdep = 0;
dev_attr_press_speed_tpkbd.attr.key = 0;
dev_attr_press_speed_tpkbd.attr.skey.subkeys[ 0 ].__one_byte = 0;
dev_attr_press_speed_tpkbd.attr.skey.subkeys[ 1 ].__one_byte = 0;
dev_attr_press_speed_tpkbd.attr.skey.subkeys[ 2 ].__one_byte = 0;
dev_attr_press_speed_tpkbd.attr.skey.subkeys[ 3 ].__one_byte = 0;
dev_attr_press_speed_tpkbd.attr.skey.subkeys[ 4 ].__one_byte = 0;
dev_attr_press_speed_tpkbd.attr.skey.subkeys[ 5 ].__one_byte = 0;
dev_attr_press_speed_tpkbd.attr.skey.subkeys[ 6 ].__one_byte = 0;
dev_attr_press_speed_tpkbd.attr.skey.subkeys[ 7 ].__one_byte = 0;
dev_attr_press_speed_tpkbd.show = &(attr_press_speed_show_tpkbd);
dev_attr_press_speed_tpkbd.store = &(attr_press_speed_store_tpkbd);
lenovo_attributes_tpkbd[ 0 ] = &(&(dev_attr_press_to_select_tpkbd))->attr;
lenovo_attributes_tpkbd[ 1 ] = &(&(dev_attr_dragging_tpkbd))->attr;
lenovo_attributes_tpkbd[ 2 ] = &(&(dev_attr_release_to_select_tpkbd))->attr;
lenovo_attributes_tpkbd[ 3 ] = &(&(dev_attr_select_right_tpkbd))->attr;
lenovo_attributes_tpkbd[ 4 ] = &(&(dev_attr_sensitivity_tpkbd))->attr;
lenovo_attributes_tpkbd[ 5 ] = &(&(dev_attr_press_speed_tpkbd))->attr;
lenovo_attributes_tpkbd[ 6 ] = 0;
lenovo_attr_group_tpkbd.name = 0;
lenovo_attr_group_tpkbd.is_visible = 0;
lenovo_attr_group_tpkbd.attrs = &(lenovo_attributes_tpkbd);
lenovo_attr_group_tpkbd.bin_attrs = 0;
return ;
}
-__BLAST_initialize_/work/ldvuser/ref_launch/work/current--X--drivers--X--defaultlinux-4.0-rc1.tar.xz--X--151_1a/linux-4.0-rc1.tar.xz/csd_deg_dscv/564/dscv_tempdir/dscv/rcv/151_1a/main-ldv_main0_sequence_infinite_withcheck_stateful/preprocess/1-cpp//work/ldvuser/ref_launch/work/current--X--drivers--X--defaultlinux-4.0-rc1.tar.xz--X--151_1a/linux-4.0-rc1.tar.xz/csd_deg_dscv/564/dscv_tempdir/rule-instrumentor/151_1a/common-model/ldv_common_model.o.i()
{
return ;
}
-entry_point
{
892 -ldv_s_lenovo_driver_hid_driver = 0;
LDV_IN_INTERRUPT = 1;
891 ldv_initialize() { /* Function call is skipped due to function is undefined */}
896 tmp___0 = nondet_int() { /* Function call is skipped due to function is undefined */}
896 assume(tmp___0 != 0);
900 tmp = nondet_int() { /* Function call is skipped due to function is undefined */}
902 assume(tmp == 0);
905 assume(ldv_s_lenovo_driver_hid_driver == 0);
913 -res_lenovo_probe_27 = lenovo_probe(var_group1 /* hdev */, var_lenovo_probe_27_p1 /* id */)
{
691 -ret = hid_parse(hdev /* hdev */)
{
919 tmp = hid_open_report(hdev) { /* Function call is skipped due to function is undefined */}
919 return tmp;
}
692 assume(ret == 0);
697 -ret = hid_hw_start(hdev /* hdev */, 45 /* connect_mask */)
{
935 cil_6 = *(*(hdev).ll_driver).start;
935 tmp = *(cil_6)(hdev) { /* Function call is skipped due to function is undefined */}
935 ret = tmp;
936 assume(ret == 0);
936 assume(connect_mask != 0);
938 ret = hid_connect(hdev, connect_mask) { /* Function call is skipped due to function is undefined */}
939 assume(ret == 0);
941 __retres9 = ret;
932 return __retres9;
}
698 assume(ret == 0);
704 assume(*(hdev).product != 24585);
707 assume(*(hdev).product == 24647);
709 -ret = lenovo_probe_cptkbd(hdev /* hdev */)
{
646 assume(*(hdev).product == 24647);
646 assume(*(hdev).type != 1);
648 -descriptor.modname = "hid_lenovo";
descriptor.function = "lenovo_probe_cptkbd";
descriptor.filename = "/work/ldvuser/ref_launch/work/current--X--drivers--X--defaultlinux-4.0-rc1.tar.xz--X--151_1a/linux-4.0-rc1.tar.xz/csd_deg_dscv/564/dscv_tempdir/dscv/ri/151_1a/drivers/hid/hid-lenovo.c";
descriptor.format = "Ignoring keyboard half of device\n";
descriptor.lineno = 648;
descriptor.flags = 0;
648 -tmp = __builtin_expect(descriptor.flags & 1 /* exp */, 0 /* c */)
{
52 return exp;
}
648 assume(tmp == 0);
649 __retres7 = 0;
640 return __retres7;
}
715 assume(ret == 0);
718 __retres4 = 0;
686 return __retres4;
}
914 ldv_check_return_value(res_lenovo_probe_27) { /* Function call is skipped due to function is undefined */}
915 ldv_check_return_value_probe(res_lenovo_probe_27) { /* Function call is skipped due to function is undefined */}
916 assume(res_lenovo_probe_27 == 0);
918 ldv_s_lenovo_driver_hid_driver = ldv_s_lenovo_driver_hid_driver + 1;
896 tmp___0 = nondet_int() { /* Function call is skipped due to function is undefined */}
896 assume(tmp___0 != 0);
900 tmp = nondet_int() { /* Function call is skipped due to function is undefined */}
902 assume(tmp != 0);
925 assume(tmp == 1);
928 assume(ldv_s_lenovo_driver_hid_driver == 1);
936 ldv_handler_precall() { /* Function call is skipped due to function is undefined */}
937 -lenovo_remove(var_group1 /* hdev */)
{
754 assume(*(hdev).product != 24585);
757 assume(*(hdev).product == 24647);
759 -lenovo_remove_cptkbd(hdev /* hdev */)
{
747 -ldv_sysfs_remove_group_8(&(&(hdev)->dev)->kobj /* ldv_func_arg1 */, &(lenovo_attr_group_cptkbd) /* ldv_func_arg2 */)
{
117 -ldv_sysfs_remove_group(ldv_func_arg1 /* kobj */, ldv_func_arg2 /* grp */)
{
30 LDV_SYSFS_GROUPS = LDV_SYSFS_GROUPS + -1;
29 return ;
}
114 return ;
}
745 return ;
}
763 -hid_hw_stop(hdev /* hdev */)
{
954 hid_disconnect(hdev) { /* Function call is skipped due to function is undefined */}
955 cil_3 = *(*(hdev).ll_driver).stop;
955 *(cil_3)(hdev) { /* Function call is skipped due to function is undefined */}
952 return ;
}
751 return ;
}
938 ldv_s_lenovo_driver_hid_driver = 0;
896 tmp___0 = nondet_int() { /* Function call is skipped due to function is undefined */}
896 assume(tmp___0 == 0);
896 assume(ldv_s_lenovo_driver_hid_driver == 0);
996 -ldv_check_final_state()
{
34 assume(LDV_SYSFS_GROUPS != 0);
34 -ldv_error()
{
}
}
}
Source code
1 2 /* 3 * HID driver for Lenovo: 4 * - ThinkPad USB Keyboard with TrackPoint (tpkbd) 5 * - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd) 6 * - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd) 7 * 8 * Copyright (c) 2012 Bernhard Seibold 9 * Copyright (c) 2014 Jamie Lentin <jm@lentin.co.uk> 10 */ 11 12 /* 13 * This program is free software; you can redistribute it and/or modify it 14 * under the terms of the GNU General Public License as published by the Free 15 * Software Foundation; either version 2 of the License, or (at your option) 16 * any later version. 17 */ 18 19 #include <linux/module.h> 20 #include <linux/sysfs.h> 21 #include <linux/device.h> 22 #include <linux/hid.h> 23 #include <linux/input.h> 24 #include <linux/leds.h> 25 26 #include "hid-ids.h" 27 28 struct lenovo_drvdata_tpkbd { 29 int led_state; 30 struct led_classdev led_mute; 31 struct led_classdev led_micmute; 32 int press_to_select; 33 int dragging; 34 int release_to_select; 35 int select_right; 36 int sensitivity; 37 int press_speed; 38 }; 39 40 struct lenovo_drvdata_cptkbd { 41 bool fn_lock; 42 int sensitivity; 43 }; 44 45 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 46 47 static int lenovo_input_mapping_tpkbd(struct hid_device *hdev, 48 struct hid_input *hi, struct hid_field *field, 49 struct hid_usage *usage, unsigned long **bit, int *max) 50 { 51 if (usage->hid == (HID_UP_BUTTON | 0x0010)) { 52 /* This sub-device contains trackpoint, mark it */ 53 hid_set_drvdata(hdev, (void *)1); 54 map_key_clear(KEY_MICMUTE); 55 return 1; 56 } 57 return 0; 58 } 59 60 static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, 61 struct hid_input *hi, struct hid_field *field, 62 struct hid_usage *usage, unsigned long **bit, int *max) 63 { 64 /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */ 65 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR || 66 (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) { 67 switch (usage->hid & HID_USAGE) { 68 case 0x00f1: /* Fn-F4: Mic mute */ 69 map_key_clear(KEY_MICMUTE); 70 return 1; 71 case 0x00f2: /* Fn-F5: Brightness down */ 72 map_key_clear(KEY_BRIGHTNESSDOWN); 73 return 1; 74 case 0x00f3: /* Fn-F6: Brightness up */ 75 map_key_clear(KEY_BRIGHTNESSUP); 76 return 1; 77 case 0x00f4: /* Fn-F7: External display (projector) */ 78 map_key_clear(KEY_SWITCHVIDEOMODE); 79 return 1; 80 case 0x00f5: /* Fn-F8: Wireless */ 81 map_key_clear(KEY_WLAN); 82 return 1; 83 case 0x00f6: /* Fn-F9: Control panel */ 84 map_key_clear(KEY_CONFIG); 85 return 1; 86 case 0x00f8: /* Fn-F11: View open applications (3 boxes) */ 87 map_key_clear(KEY_SCALE); 88 return 1; 89 case 0x00f9: /* Fn-F12: Open My computer (6 boxes) USB-only */ 90 /* NB: This mapping is invented in raw_event below */ 91 map_key_clear(KEY_FILE); 92 return 1; 93 case 0x00fa: /* Fn-Esc: Fn-lock toggle */ 94 map_key_clear(KEY_FN_ESC); 95 return 1; 96 case 0x00fb: /* Middle mouse button (in native mode) */ 97 map_key_clear(BTN_MIDDLE); 98 return 1; 99 } 100 } 101 102 /* Compatibility middle/wheel mappings should be ignored */ 103 if (usage->hid == HID_GD_WHEEL) 104 return -1; 105 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON && 106 (usage->hid & HID_USAGE) == 0x003) 107 return -1; 108 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER && 109 (usage->hid & HID_USAGE) == 0x238) 110 return -1; 111 112 /* Map wheel emulation reports: 0xffa1 = USB, 0xff10 = BT */ 113 if ((usage->hid & HID_USAGE_PAGE) == 0xff100000 || 114 (usage->hid & HID_USAGE_PAGE) == 0xffa10000) { 115 field->flags |= HID_MAIN_ITEM_RELATIVE | HID_MAIN_ITEM_VARIABLE; 116 field->logical_minimum = -127; 117 field->logical_maximum = 127; 118 119 switch (usage->hid & HID_USAGE) { 120 case 0x0000: 121 hid_map_usage(hi, usage, bit, max, EV_REL, 0x06); 122 return 1; 123 case 0x0001: 124 hid_map_usage(hi, usage, bit, max, EV_REL, 0x08); 125 return 1; 126 default: 127 return -1; 128 } 129 } 130 131 return 0; 132 } 133 134 static int lenovo_input_mapping(struct hid_device *hdev, 135 struct hid_input *hi, struct hid_field *field, 136 struct hid_usage *usage, unsigned long **bit, int *max) 137 { 138 switch (hdev->product) { 139 case USB_DEVICE_ID_LENOVO_TPKBD: 140 return lenovo_input_mapping_tpkbd(hdev, hi, field, 141 usage, bit, max); 142 case USB_DEVICE_ID_LENOVO_CUSBKBD: 143 case USB_DEVICE_ID_LENOVO_CBTKBD: 144 return lenovo_input_mapping_cptkbd(hdev, hi, field, 145 usage, bit, max); 146 default: 147 return 0; 148 } 149 } 150 151 #undef map_key_clear 152 153 /* Send a config command to the keyboard */ 154 static int lenovo_send_cmd_cptkbd(struct hid_device *hdev, 155 unsigned char byte2, unsigned char byte3) 156 { 157 int ret; 158 unsigned char buf[] = {0x18, byte2, byte3}; 159 160 switch (hdev->product) { 161 case USB_DEVICE_ID_LENOVO_CUSBKBD: 162 ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf), 163 HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 164 break; 165 case USB_DEVICE_ID_LENOVO_CBTKBD: 166 ret = hid_hw_output_report(hdev, buf, sizeof(buf)); 167 break; 168 default: 169 ret = -EINVAL; 170 break; 171 } 172 173 return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */ 174 } 175 176 static void lenovo_features_set_cptkbd(struct hid_device *hdev) 177 { 178 int ret; 179 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 180 181 ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock); 182 ret = lenovo_send_cmd_cptkbd(hdev, 0x02, cptkbd_data->sensitivity); 183 if (ret) 184 hid_err(hdev, "Fn-lock setting failed: %d\n", ret); 185 } 186 187 static ssize_t attr_fn_lock_show_cptkbd(struct device *dev, 188 struct device_attribute *attr, 189 char *buf) 190 { 191 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 192 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 193 194 return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock); 195 } 196 197 static ssize_t attr_fn_lock_store_cptkbd(struct device *dev, 198 struct device_attribute *attr, 199 const char *buf, 200 size_t count) 201 { 202 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 203 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 204 int value; 205 206 if (kstrtoint(buf, 10, &value)) 207 return -EINVAL; 208 if (value < 0 || value > 1) 209 return -EINVAL; 210 211 cptkbd_data->fn_lock = !!value; 212 lenovo_features_set_cptkbd(hdev); 213 214 return count; 215 } 216 217 static ssize_t attr_sensitivity_show_cptkbd(struct device *dev, 218 struct device_attribute *attr, 219 char *buf) 220 { 221 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 222 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 223 224 return snprintf(buf, PAGE_SIZE, "%u\n", 225 cptkbd_data->sensitivity); 226 } 227 228 static ssize_t attr_sensitivity_store_cptkbd(struct device *dev, 229 struct device_attribute *attr, 230 const char *buf, 231 size_t count) 232 { 233 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 234 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 235 int value; 236 237 if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 238 return -EINVAL; 239 240 cptkbd_data->sensitivity = value; 241 lenovo_features_set_cptkbd(hdev); 242 243 return count; 244 } 245 246 247 static struct device_attribute dev_attr_fn_lock_cptkbd = 248 __ATTR(fn_lock, S_IWUSR | S_IRUGO, 249 attr_fn_lock_show_cptkbd, 250 attr_fn_lock_store_cptkbd); 251 252 static struct device_attribute dev_attr_sensitivity_cptkbd = 253 __ATTR(sensitivity, S_IWUSR | S_IRUGO, 254 attr_sensitivity_show_cptkbd, 255 attr_sensitivity_store_cptkbd); 256 257 258 static struct attribute *lenovo_attributes_cptkbd[] = { 259 &dev_attr_fn_lock_cptkbd.attr, 260 &dev_attr_sensitivity_cptkbd.attr, 261 NULL 262 }; 263 264 static const struct attribute_group lenovo_attr_group_cptkbd = { 265 .attrs = lenovo_attributes_cptkbd, 266 }; 267 268 static int lenovo_raw_event(struct hid_device *hdev, 269 struct hid_report *report, u8 *data, int size) 270 { 271 /* 272 * Compact USB keyboard's Fn-F12 report holds down many other keys, and 273 * its own key is outside the usage page range. Remove extra 274 * keypresses and remap to inside usage page. 275 */ 276 if (unlikely(hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD 277 && size == 3 278 && data[0] == 0x15 279 && data[1] == 0x94 280 && data[2] == 0x01)) { 281 data[1] = 0x00; 282 data[2] = 0x01; 283 } 284 285 return 0; 286 } 287 288 static int lenovo_features_set_tpkbd(struct hid_device *hdev) 289 { 290 struct hid_report *report; 291 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 292 293 report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4]; 294 295 report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02; 296 report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08; 297 report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20; 298 report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40; 299 report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver 300 report->field[2]->value[0] = data_pointer->sensitivity; 301 report->field[3]->value[0] = data_pointer->press_speed; 302 303 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 304 return 0; 305 } 306 307 static ssize_t attr_press_to_select_show_tpkbd(struct device *dev, 308 struct device_attribute *attr, 309 char *buf) 310 { 311 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 312 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 313 314 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select); 315 } 316 317 static ssize_t attr_press_to_select_store_tpkbd(struct device *dev, 318 struct device_attribute *attr, 319 const char *buf, 320 size_t count) 321 { 322 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 323 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 324 int value; 325 326 if (kstrtoint(buf, 10, &value)) 327 return -EINVAL; 328 if (value < 0 || value > 1) 329 return -EINVAL; 330 331 data_pointer->press_to_select = value; 332 lenovo_features_set_tpkbd(hdev); 333 334 return count; 335 } 336 337 static ssize_t attr_dragging_show_tpkbd(struct device *dev, 338 struct device_attribute *attr, 339 char *buf) 340 { 341 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 342 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 343 344 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging); 345 } 346 347 static ssize_t attr_dragging_store_tpkbd(struct device *dev, 348 struct device_attribute *attr, 349 const char *buf, 350 size_t count) 351 { 352 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 353 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 354 int value; 355 356 if (kstrtoint(buf, 10, &value)) 357 return -EINVAL; 358 if (value < 0 || value > 1) 359 return -EINVAL; 360 361 data_pointer->dragging = value; 362 lenovo_features_set_tpkbd(hdev); 363 364 return count; 365 } 366 367 static ssize_t attr_release_to_select_show_tpkbd(struct device *dev, 368 struct device_attribute *attr, 369 char *buf) 370 { 371 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 372 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 373 374 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select); 375 } 376 377 static ssize_t attr_release_to_select_store_tpkbd(struct device *dev, 378 struct device_attribute *attr, 379 const char *buf, 380 size_t count) 381 { 382 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 383 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 384 int value; 385 386 if (kstrtoint(buf, 10, &value)) 387 return -EINVAL; 388 if (value < 0 || value > 1) 389 return -EINVAL; 390 391 data_pointer->release_to_select = value; 392 lenovo_features_set_tpkbd(hdev); 393 394 return count; 395 } 396 397 static ssize_t attr_select_right_show_tpkbd(struct device *dev, 398 struct device_attribute *attr, 399 char *buf) 400 { 401 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 402 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 403 404 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right); 405 } 406 407 static ssize_t attr_select_right_store_tpkbd(struct device *dev, 408 struct device_attribute *attr, 409 const char *buf, 410 size_t count) 411 { 412 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 413 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 414 int value; 415 416 if (kstrtoint(buf, 10, &value)) 417 return -EINVAL; 418 if (value < 0 || value > 1) 419 return -EINVAL; 420 421 data_pointer->select_right = value; 422 lenovo_features_set_tpkbd(hdev); 423 424 return count; 425 } 426 427 static ssize_t attr_sensitivity_show_tpkbd(struct device *dev, 428 struct device_attribute *attr, 429 char *buf) 430 { 431 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 432 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 433 434 return snprintf(buf, PAGE_SIZE, "%u\n", 435 data_pointer->sensitivity); 436 } 437 438 static ssize_t attr_sensitivity_store_tpkbd(struct device *dev, 439 struct device_attribute *attr, 440 const char *buf, 441 size_t count) 442 { 443 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 444 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 445 int value; 446 447 if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 448 return -EINVAL; 449 450 data_pointer->sensitivity = value; 451 lenovo_features_set_tpkbd(hdev); 452 453 return count; 454 } 455 456 static ssize_t attr_press_speed_show_tpkbd(struct device *dev, 457 struct device_attribute *attr, 458 char *buf) 459 { 460 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 461 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 462 463 return snprintf(buf, PAGE_SIZE, "%u\n", 464 data_pointer->press_speed); 465 } 466 467 static ssize_t attr_press_speed_store_tpkbd(struct device *dev, 468 struct device_attribute *attr, 469 const char *buf, 470 size_t count) 471 { 472 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 473 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 474 int value; 475 476 if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 477 return -EINVAL; 478 479 data_pointer->press_speed = value; 480 lenovo_features_set_tpkbd(hdev); 481 482 return count; 483 } 484 485 static struct device_attribute dev_attr_press_to_select_tpkbd = 486 __ATTR(press_to_select, S_IWUSR | S_IRUGO, 487 attr_press_to_select_show_tpkbd, 488 attr_press_to_select_store_tpkbd); 489 490 static struct device_attribute dev_attr_dragging_tpkbd = 491 __ATTR(dragging, S_IWUSR | S_IRUGO, 492 attr_dragging_show_tpkbd, 493 attr_dragging_store_tpkbd); 494 495 static struct device_attribute dev_attr_release_to_select_tpkbd = 496 __ATTR(release_to_select, S_IWUSR | S_IRUGO, 497 attr_release_to_select_show_tpkbd, 498 attr_release_to_select_store_tpkbd); 499 500 static struct device_attribute dev_attr_select_right_tpkbd = 501 __ATTR(select_right, S_IWUSR | S_IRUGO, 502 attr_select_right_show_tpkbd, 503 attr_select_right_store_tpkbd); 504 505 static struct device_attribute dev_attr_sensitivity_tpkbd = 506 __ATTR(sensitivity, S_IWUSR | S_IRUGO, 507 attr_sensitivity_show_tpkbd, 508 attr_sensitivity_store_tpkbd); 509 510 static struct device_attribute dev_attr_press_speed_tpkbd = 511 __ATTR(press_speed, S_IWUSR | S_IRUGO, 512 attr_press_speed_show_tpkbd, 513 attr_press_speed_store_tpkbd); 514 515 static struct attribute *lenovo_attributes_tpkbd[] = { 516 &dev_attr_press_to_select_tpkbd.attr, 517 &dev_attr_dragging_tpkbd.attr, 518 &dev_attr_release_to_select_tpkbd.attr, 519 &dev_attr_select_right_tpkbd.attr, 520 &dev_attr_sensitivity_tpkbd.attr, 521 &dev_attr_press_speed_tpkbd.attr, 522 NULL 523 }; 524 525 static const struct attribute_group lenovo_attr_group_tpkbd = { 526 .attrs = lenovo_attributes_tpkbd, 527 }; 528 529 static enum led_brightness lenovo_led_brightness_get_tpkbd( 530 struct led_classdev *led_cdev) 531 { 532 struct device *dev = led_cdev->dev->parent; 533 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 534 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 535 int led_nr = 0; 536 537 if (led_cdev == &data_pointer->led_micmute) 538 led_nr = 1; 539 540 return data_pointer->led_state & (1 << led_nr) 541 ? LED_FULL 542 : LED_OFF; 543 } 544 545 static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev, 546 enum led_brightness value) 547 { 548 struct device *dev = led_cdev->dev->parent; 549 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 550 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 551 struct hid_report *report; 552 int led_nr = 0; 553 554 if (led_cdev == &data_pointer->led_micmute) 555 led_nr = 1; 556 557 if (value == LED_OFF) 558 data_pointer->led_state &= ~(1 << led_nr); 559 else 560 data_pointer->led_state |= 1 << led_nr; 561 562 report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3]; 563 report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1; 564 report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1; 565 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 566 } 567 568 static int lenovo_probe_tpkbd(struct hid_device *hdev) 569 { 570 struct device *dev = &hdev->dev; 571 struct lenovo_drvdata_tpkbd *data_pointer; 572 size_t name_sz = strlen(dev_name(dev)) + 16; 573 char *name_mute, *name_micmute; 574 int i; 575 int ret; 576 577 /* 578 * Only register extra settings against subdevice where input_mapping 579 * set drvdata to 1, i.e. the trackpoint. 580 */ 581 if (!hid_get_drvdata(hdev)) 582 return 0; 583 584 hid_set_drvdata(hdev, NULL); 585 586 /* Validate required reports. */ 587 for (i = 0; i < 4; i++) { 588 if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1)) 589 return -ENODEV; 590 } 591 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2)) 592 return -ENODEV; 593 594 ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd); 595 if (ret) 596 hid_warn(hdev, "Could not create sysfs group: %d\n", ret); 597 598 data_pointer = devm_kzalloc(&hdev->dev, 599 sizeof(struct lenovo_drvdata_tpkbd), 600 GFP_KERNEL); 601 if (data_pointer == NULL) { 602 hid_err(hdev, "Could not allocate memory for driver data\n"); 603 return -ENOMEM; 604 } 605 606 // set same default values as windows driver 607 data_pointer->sensitivity = 0xa0; 608 data_pointer->press_speed = 0x38; 609 610 name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); 611 name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); 612 if (name_mute == NULL || name_micmute == NULL) { 613 hid_err(hdev, "Could not allocate memory for led data\n"); 614 return -ENOMEM; 615 } 616 snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev)); 617 snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev)); 618 619 hid_set_drvdata(hdev, data_pointer); 620 621 data_pointer->led_mute.name = name_mute; 622 data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd; 623 data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd; 624 data_pointer->led_mute.dev = dev; 625 led_classdev_register(dev, &data_pointer->led_mute); 626 627 data_pointer->led_micmute.name = name_micmute; 628 data_pointer->led_micmute.brightness_get = 629 lenovo_led_brightness_get_tpkbd; 630 data_pointer->led_micmute.brightness_set = 631 lenovo_led_brightness_set_tpkbd; 632 data_pointer->led_micmute.dev = dev; 633 led_classdev_register(dev, &data_pointer->led_micmute); 634 635 lenovo_features_set_tpkbd(hdev); 636 637 return 0; 638 } 639 640 static int lenovo_probe_cptkbd(struct hid_device *hdev) 641 { 642 int ret; 643 struct lenovo_drvdata_cptkbd *cptkbd_data; 644 645 /* All the custom action happens on the USBMOUSE device for USB */ 646 if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD 647 && hdev->type != HID_TYPE_USBMOUSE) { 648 hid_dbg(hdev, "Ignoring keyboard half of device\n"); 649 return 0; 650 } 651 652 cptkbd_data = devm_kzalloc(&hdev->dev, 653 sizeof(*cptkbd_data), 654 GFP_KERNEL); 655 if (cptkbd_data == NULL) { 656 hid_err(hdev, "can't alloc keyboard descriptor\n"); 657 return -ENOMEM; 658 } 659 hid_set_drvdata(hdev, cptkbd_data); 660 661 /* 662 * Tell the keyboard a driver understands it, and turn F7, F9, F11 into 663 * regular keys 664 */ 665 ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03); 666 if (ret) 667 hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret); 668 669 /* Switch middle button to native mode */ 670 ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01); 671 if (ret) 672 hid_warn(hdev, "Failed to switch middle button: %d\n", ret); 673 674 /* Set keyboard settings to known state */ 675 cptkbd_data->fn_lock = true; 676 cptkbd_data->sensitivity = 0x05; 677 lenovo_features_set_cptkbd(hdev); 678 679 ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd); 680 if (ret) 681 hid_warn(hdev, "Could not create sysfs group: %d\n", ret); 682 683 return 0; 684 } 685 686 static int lenovo_probe(struct hid_device *hdev, 687 const struct hid_device_id *id) 688 { 689 int ret; 690 691 ret = hid_parse(hdev); 692 if (ret) { 693 hid_err(hdev, "hid_parse failed\n"); 694 goto err; 695 } 696 697 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 698 if (ret) { 699 hid_err(hdev, "hid_hw_start failed\n"); 700 goto err; 701 } 702 703 switch (hdev->product) { 704 case USB_DEVICE_ID_LENOVO_TPKBD: 705 ret = lenovo_probe_tpkbd(hdev); 706 break; 707 case USB_DEVICE_ID_LENOVO_CUSBKBD: 708 case USB_DEVICE_ID_LENOVO_CBTKBD: 709 ret = lenovo_probe_cptkbd(hdev); 710 break; 711 default: 712 ret = 0; 713 break; 714 } 715 if (ret) 716 goto err_hid; 717 718 return 0; 719 err_hid: 720 hid_hw_stop(hdev); 721 err: 722 return ret; 723 } 724 725 static void lenovo_remove_tpkbd(struct hid_device *hdev) 726 { 727 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 728 729 /* 730 * Only the trackpoint half of the keyboard has drvdata and stuff that 731 * needs unregistering. 732 */ 733 if (data_pointer == NULL) 734 return; 735 736 sysfs_remove_group(&hdev->dev.kobj, 737 &lenovo_attr_group_tpkbd); 738 739 led_classdev_unregister(&data_pointer->led_micmute); 740 led_classdev_unregister(&data_pointer->led_mute); 741 742 hid_set_drvdata(hdev, NULL); 743 } 744 745 static void lenovo_remove_cptkbd(struct hid_device *hdev) 746 { 747 sysfs_remove_group(&hdev->dev.kobj, 748 &lenovo_attr_group_cptkbd); 749 } 750 751 static void lenovo_remove(struct hid_device *hdev) 752 { 753 switch (hdev->product) { 754 case USB_DEVICE_ID_LENOVO_TPKBD: 755 lenovo_remove_tpkbd(hdev); 756 break; 757 case USB_DEVICE_ID_LENOVO_CUSBKBD: 758 case USB_DEVICE_ID_LENOVO_CBTKBD: 759 lenovo_remove_cptkbd(hdev); 760 break; 761 } 762 763 hid_hw_stop(hdev); 764 } 765 766 static const struct hid_device_id lenovo_devices[] = { 767 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, 768 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, 769 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, 770 { } 771 }; 772 773 MODULE_DEVICE_TABLE(hid, lenovo_devices); 774 775 static struct hid_driver lenovo_driver = { 776 .name = "lenovo", 777 .id_table = lenovo_devices, 778 .input_mapping = lenovo_input_mapping, 779 .probe = lenovo_probe, 780 .remove = lenovo_remove, 781 .raw_event = lenovo_raw_event, 782 }; 783 module_hid_driver(lenovo_driver); 784 785 MODULE_LICENSE("GPL"); 786 787 788 789 790 791 /* LDV_COMMENT_BEGIN_MAIN */ 792 #ifdef LDV_MAIN0_sequence_infinite_withcheck_stateful 793 794 /*###########################################################################*/ 795 796 /*############## Driver Environment Generator 0.2 output ####################*/ 797 798 /*###########################################################################*/ 799 800 801 802 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Test if all kernel resources are correctly released by driver before driver will be unloaded. */ 803 void ldv_check_final_state(void); 804 805 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Test correct return result. */ 806 void ldv_check_return_value(int res); 807 808 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Test correct return result of probe() function. */ 809 void ldv_check_return_value_probe(int res); 810 811 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Initializes the model. */ 812 void ldv_initialize(void); 813 814 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Reinitializes the model between distinct model function calls. */ 815 void ldv_handler_precall(void); 816 817 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Returns arbitrary interger value. */ 818 int nondet_int(void); 819 820 /* LDV_COMMENT_VAR_DECLARE_LDV Special variable for LDV verifier. */ 821 int LDV_IN_INTERRUPT; 822 823 /* LDV_COMMENT_FUNCTION_MAIN Main function for LDV verifier. */ 824 void ldv_main0_sequence_infinite_withcheck_stateful(void) { 825 826 827 828 /* LDV_COMMENT_BEGIN_VARIABLE_DECLARATION_PART */ 829 /*============================= VARIABLE DECLARATION PART =============================*/ 830 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 831 /* content: static int lenovo_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max)*/ 832 /* LDV_COMMENT_BEGIN_PREP */ 833 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 834 /* LDV_COMMENT_END_PREP */ 835 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 836 struct hid_device * var_group1; 837 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 838 struct hid_input * var_group2; 839 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 840 struct hid_field * var_lenovo_input_mapping_2_p2; 841 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 842 struct hid_usage * var_lenovo_input_mapping_2_p3; 843 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 844 unsigned long ** var_lenovo_input_mapping_2_p4; 845 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 846 int * var_lenovo_input_mapping_2_p5; 847 /* LDV_COMMENT_BEGIN_PREP */ 848 #undef map_key_clear 849 /* LDV_COMMENT_END_PREP */ 850 /* content: static int lenovo_probe(struct hid_device *hdev, const struct hid_device_id *id)*/ 851 /* LDV_COMMENT_BEGIN_PREP */ 852 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 853 #undef map_key_clear 854 /* LDV_COMMENT_END_PREP */ 855 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_probe" */ 856 const struct hid_device_id * var_lenovo_probe_27_p1; 857 /* LDV_COMMENT_VAR_DECLARE Variable declaration for test return result from function call "lenovo_probe" */ 858 static int res_lenovo_probe_27; 859 /* content: static void lenovo_remove(struct hid_device *hdev)*/ 860 /* LDV_COMMENT_BEGIN_PREP */ 861 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 862 #undef map_key_clear 863 /* LDV_COMMENT_END_PREP */ 864 /* content: static int lenovo_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size)*/ 865 /* LDV_COMMENT_BEGIN_PREP */ 866 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 867 #undef map_key_clear 868 /* LDV_COMMENT_END_PREP */ 869 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_raw_event" */ 870 struct hid_report * var_group3; 871 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_raw_event" */ 872 u8 * var_lenovo_raw_event_9_p2; 873 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_raw_event" */ 874 int var_lenovo_raw_event_9_p3; 875 876 877 878 879 /* LDV_COMMENT_END_VARIABLE_DECLARATION_PART */ 880 /* LDV_COMMENT_BEGIN_VARIABLE_INITIALIZING_PART */ 881 /*============================= VARIABLE INITIALIZING PART =============================*/ 882 LDV_IN_INTERRUPT=1; 883 884 885 886 887 /* LDV_COMMENT_END_VARIABLE_INITIALIZING_PART */ 888 /* LDV_COMMENT_BEGIN_FUNCTION_CALL_SECTION */ 889 /*============================= FUNCTION CALL SECTION =============================*/ 890 /* LDV_COMMENT_FUNCTION_CALL Initialize LDV model. */ 891 ldv_initialize(); 892 int ldv_s_lenovo_driver_hid_driver = 0; 893 894 895 896 while( nondet_int() 897 || !(ldv_s_lenovo_driver_hid_driver == 0) 898 ) { 899 900 switch(nondet_int()) { 901 902 case 0: { 903 904 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 905 if(ldv_s_lenovo_driver_hid_driver==0) { 906 907 /* content: static int lenovo_probe(struct hid_device *hdev, const struct hid_device_id *id)*/ 908 /* LDV_COMMENT_BEGIN_PREP */ 909 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 910 #undef map_key_clear 911 /* LDV_COMMENT_END_PREP */ 912 /* LDV_COMMENT_FUNCTION_CALL Function from field "probe" from driver structure with callbacks "lenovo_driver". Standart function test for correct return result. */ 913 res_lenovo_probe_27 = lenovo_probe( var_group1, var_lenovo_probe_27_p1); 914 ldv_check_return_value(res_lenovo_probe_27); 915 ldv_check_return_value_probe(res_lenovo_probe_27); 916 if(res_lenovo_probe_27) 917 goto ldv_module_exit; 918 ldv_s_lenovo_driver_hid_driver++; 919 920 } 921 922 } 923 924 break; 925 case 1: { 926 927 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 928 if(ldv_s_lenovo_driver_hid_driver==1) { 929 930 /* content: static void lenovo_remove(struct hid_device *hdev)*/ 931 /* LDV_COMMENT_BEGIN_PREP */ 932 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 933 #undef map_key_clear 934 /* LDV_COMMENT_END_PREP */ 935 /* LDV_COMMENT_FUNCTION_CALL Function from field "remove" from driver structure with callbacks "lenovo_driver" */ 936 ldv_handler_precall(); 937 lenovo_remove( var_group1); 938 ldv_s_lenovo_driver_hid_driver=0; 939 940 } 941 942 } 943 944 break; 945 case 2: { 946 947 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 948 949 950 /* content: static int lenovo_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max)*/ 951 /* LDV_COMMENT_BEGIN_PREP */ 952 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 953 /* LDV_COMMENT_END_PREP */ 954 /* LDV_COMMENT_FUNCTION_CALL Function from field "input_mapping" from driver structure with callbacks "lenovo_driver" */ 955 ldv_handler_precall(); 956 lenovo_input_mapping( var_group1, var_group2, var_lenovo_input_mapping_2_p2, var_lenovo_input_mapping_2_p3, var_lenovo_input_mapping_2_p4, var_lenovo_input_mapping_2_p5); 957 /* LDV_COMMENT_BEGIN_PREP */ 958 #undef map_key_clear 959 /* LDV_COMMENT_END_PREP */ 960 961 962 963 964 } 965 966 break; 967 case 3: { 968 969 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 970 971 972 /* content: static int lenovo_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size)*/ 973 /* LDV_COMMENT_BEGIN_PREP */ 974 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 975 #undef map_key_clear 976 /* LDV_COMMENT_END_PREP */ 977 /* LDV_COMMENT_FUNCTION_CALL Function from field "raw_event" from driver structure with callbacks "lenovo_driver" */ 978 ldv_handler_precall(); 979 lenovo_raw_event( var_group1, var_group3, var_lenovo_raw_event_9_p2, var_lenovo_raw_event_9_p3); 980 981 982 983 984 } 985 986 break; 987 default: break; 988 989 } 990 991 } 992 993 ldv_module_exit: 994 995 /* LDV_COMMENT_FUNCTION_CALL Checks that all resources and locks are correctly released before the driver will be unloaded. */ 996 ldv_final: ldv_check_final_state(); 997 998 /* LDV_COMMENT_END_FUNCTION_CALL_SECTION */ 999 return; 1000 1001 } 1002 #endif 1003 1004 /* LDV_COMMENT_END_MAIN */
1 2 #include <linux/kernel.h> 3 bool ldv_is_err(const void *ptr); 4 bool ldv_is_err_or_null(const void *ptr); 5 void* ldv_err_ptr(long error); 6 long ldv_ptr_err(const void *ptr); 7 8 9 #include <linux/sysfs.h> 10 #include <verifier/rcv.h> 11 #include <verifier/multimap.h> 12 13 # 1 "/home/ldvuser/ldv/inst/kernel-rules/kernel-model/ERR.inc" 1 14 #ifndef _LDV_ERR_ 15 #define _LDV_ERR_ 16 17 #include <linux/kernel.h> 18 19 /* LDV_COMMENT_MODEL_FUNCTION_DEFENITION(name='ldv_is_err') This function return result of checking if pointer is impossible. */ 20 bool ldv_is_err(const void *ptr) 21 { 22 /*LDV_COMMENT_RETURN Return value of function ldv_is_err_val().*/ 23 return ((unsigned long)ptr > LDV_PTR_MAX); 24 } 25 26 /* LDV_COMMENT_MODEL_FUNCTION_DEFENITION(name='ldv_err_ptr') This function return pointer. */ 27 void* ldv_err_ptr(long error) 28 { 29 /*LDV_COMMENT_RETURN Return error pointer.*/ 30 return (void *)(LDV_PTR_MAX - error); 31 } 32 33 /* LDV_COMMENT_MODEL_FUNCTION_DEFENITION(name='ldv_ptr_err') This function return error if pointer is impossible. */ 34 long ldv_ptr_err(const void *ptr) 35 { 36 /*LDV_COMMENT_RETURN Return error code.*/ 37 return (long)(LDV_PTR_MAX - (unsigned long)ptr); 38 } 39 40 /* LDV_COMMENT_MODEL_FUNCTION_DEFENITION(name='ldv_is_err_or_null') This function check if pointer is impossible or null. */ 41 bool ldv_is_err_or_null(const void *ptr) 42 { 43 /*LDV_COMMENT_RETURN Return 0 if pointer is possible and not zero, and 1 in other cases*/ 44 return !ptr || ldv_is_err((unsigned long)ptr); 45 } 46 47 #endif /* _LDV_ERR_ */ 48 # 11 "/home/ldvuser/ldv/inst/kernel-rules/models/0151.aspect" 2 49 50 MultiMap LDV_SYSFS_GROUPS = ldv_multimap_init(LDV_SYSFS_GROUPS); 51 52 53 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='ldv_sysfs_create_group') Create some sysfs group for specified kernel object */ 54 int ldv_sysfs_create_group(struct kobject *kobj, const struct attribute_group *grp) { 55 ldv_assert(ldv_multimap_not_contains_key_value(LDV_SYSFS_GROUPS, kobj, grp)); 56 if (ldv_undef_int()) { 57 ldv_multimap_put(LDV_SYSFS_GROUPS, kobj, grp); 58 return 0; 59 } 60 return ldv_undef_int_negative(); 61 } 62 63 /* LDV_COMMENT_MODEL_FUNCTION_DEFINITION(name='ldv_sysfs_remove_group') Remove some sysfs group from specified kernel object */ 64 void ldv_sysfs_remove_group(struct kobject *kobj, const struct attribute_group *grp) { 65 ldv_multimap_remove_value(LDV_SYSFS_GROUPS, kobj, grp); 66 } 67 68 void ldv_check_final_state(void) { 69 ldv_assert(ldv_multimap_is_empty(LDV_SYSFS_GROUPS)); 70 } 71 #line 1 "/work/ldvuser/ref_launch/work/current--X--drivers--X--defaultlinux-4.0-rc1.tar.xz--X--151_1a/linux-4.0-rc1.tar.xz/csd_deg_dscv/564/dscv_tempdir/dscv/ri/151_1a/drivers/hid/hid-lenovo.c" 72 73 /* 74 * HID driver for Lenovo: 75 * - ThinkPad USB Keyboard with TrackPoint (tpkbd) 76 * - ThinkPad Compact Bluetooth Keyboard with TrackPoint (cptkbd) 77 * - ThinkPad Compact USB Keyboard with TrackPoint (cptkbd) 78 * 79 * Copyright (c) 2012 Bernhard Seibold 80 * Copyright (c) 2014 Jamie Lentin <jm@lentin.co.uk> 81 */ 82 83 /* 84 * This program is free software; you can redistribute it and/or modify it 85 * under the terms of the GNU General Public License as published by the Free 86 * Software Foundation; either version 2 of the License, or (at your option) 87 * any later version. 88 */ 89 90 #include <linux/module.h> 91 #include <linux/sysfs.h> 92 #include <linux/device.h> 93 #include <linux/hid.h> 94 #include <linux/input.h> 95 #include <linux/leds.h> 96 97 #include "hid-ids.h" 98 99 struct lenovo_drvdata_tpkbd { 100 int led_state; 101 struct led_classdev led_mute; 102 struct led_classdev led_micmute; 103 int press_to_select; 104 int dragging; 105 int release_to_select; 106 int select_right; 107 int sensitivity; 108 int press_speed; 109 }; 110 111 struct lenovo_drvdata_cptkbd { 112 bool fn_lock; 113 int sensitivity; 114 }; 115 116 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 117 118 static int lenovo_input_mapping_tpkbd(struct hid_device *hdev, 119 struct hid_input *hi, struct hid_field *field, 120 struct hid_usage *usage, unsigned long **bit, int *max) 121 { 122 if (usage->hid == (HID_UP_BUTTON | 0x0010)) { 123 /* This sub-device contains trackpoint, mark it */ 124 hid_set_drvdata(hdev, (void *)1); 125 map_key_clear(KEY_MICMUTE); 126 return 1; 127 } 128 return 0; 129 } 130 131 static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, 132 struct hid_input *hi, struct hid_field *field, 133 struct hid_usage *usage, unsigned long **bit, int *max) 134 { 135 /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */ 136 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR || 137 (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) { 138 switch (usage->hid & HID_USAGE) { 139 case 0x00f1: /* Fn-F4: Mic mute */ 140 map_key_clear(KEY_MICMUTE); 141 return 1; 142 case 0x00f2: /* Fn-F5: Brightness down */ 143 map_key_clear(KEY_BRIGHTNESSDOWN); 144 return 1; 145 case 0x00f3: /* Fn-F6: Brightness up */ 146 map_key_clear(KEY_BRIGHTNESSUP); 147 return 1; 148 case 0x00f4: /* Fn-F7: External display (projector) */ 149 map_key_clear(KEY_SWITCHVIDEOMODE); 150 return 1; 151 case 0x00f5: /* Fn-F8: Wireless */ 152 map_key_clear(KEY_WLAN); 153 return 1; 154 case 0x00f6: /* Fn-F9: Control panel */ 155 map_key_clear(KEY_CONFIG); 156 return 1; 157 case 0x00f8: /* Fn-F11: View open applications (3 boxes) */ 158 map_key_clear(KEY_SCALE); 159 return 1; 160 case 0x00f9: /* Fn-F12: Open My computer (6 boxes) USB-only */ 161 /* NB: This mapping is invented in raw_event below */ 162 map_key_clear(KEY_FILE); 163 return 1; 164 case 0x00fa: /* Fn-Esc: Fn-lock toggle */ 165 map_key_clear(KEY_FN_ESC); 166 return 1; 167 case 0x00fb: /* Middle mouse button (in native mode) */ 168 map_key_clear(BTN_MIDDLE); 169 return 1; 170 } 171 } 172 173 /* Compatibility middle/wheel mappings should be ignored */ 174 if (usage->hid == HID_GD_WHEEL) 175 return -1; 176 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON && 177 (usage->hid & HID_USAGE) == 0x003) 178 return -1; 179 if ((usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER && 180 (usage->hid & HID_USAGE) == 0x238) 181 return -1; 182 183 /* Map wheel emulation reports: 0xffa1 = USB, 0xff10 = BT */ 184 if ((usage->hid & HID_USAGE_PAGE) == 0xff100000 || 185 (usage->hid & HID_USAGE_PAGE) == 0xffa10000) { 186 field->flags |= HID_MAIN_ITEM_RELATIVE | HID_MAIN_ITEM_VARIABLE; 187 field->logical_minimum = -127; 188 field->logical_maximum = 127; 189 190 switch (usage->hid & HID_USAGE) { 191 case 0x0000: 192 hid_map_usage(hi, usage, bit, max, EV_REL, 0x06); 193 return 1; 194 case 0x0001: 195 hid_map_usage(hi, usage, bit, max, EV_REL, 0x08); 196 return 1; 197 default: 198 return -1; 199 } 200 } 201 202 return 0; 203 } 204 205 static int lenovo_input_mapping(struct hid_device *hdev, 206 struct hid_input *hi, struct hid_field *field, 207 struct hid_usage *usage, unsigned long **bit, int *max) 208 { 209 switch (hdev->product) { 210 case USB_DEVICE_ID_LENOVO_TPKBD: 211 return lenovo_input_mapping_tpkbd(hdev, hi, field, 212 usage, bit, max); 213 case USB_DEVICE_ID_LENOVO_CUSBKBD: 214 case USB_DEVICE_ID_LENOVO_CBTKBD: 215 return lenovo_input_mapping_cptkbd(hdev, hi, field, 216 usage, bit, max); 217 default: 218 return 0; 219 } 220 } 221 222 #undef map_key_clear 223 224 /* Send a config command to the keyboard */ 225 static int lenovo_send_cmd_cptkbd(struct hid_device *hdev, 226 unsigned char byte2, unsigned char byte3) 227 { 228 int ret; 229 unsigned char buf[] = {0x18, byte2, byte3}; 230 231 switch (hdev->product) { 232 case USB_DEVICE_ID_LENOVO_CUSBKBD: 233 ret = hid_hw_raw_request(hdev, 0x13, buf, sizeof(buf), 234 HID_FEATURE_REPORT, HID_REQ_SET_REPORT); 235 break; 236 case USB_DEVICE_ID_LENOVO_CBTKBD: 237 ret = hid_hw_output_report(hdev, buf, sizeof(buf)); 238 break; 239 default: 240 ret = -EINVAL; 241 break; 242 } 243 244 return ret < 0 ? ret : 0; /* BT returns 0, USB returns sizeof(buf) */ 245 } 246 247 static void lenovo_features_set_cptkbd(struct hid_device *hdev) 248 { 249 int ret; 250 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 251 252 ret = lenovo_send_cmd_cptkbd(hdev, 0x05, cptkbd_data->fn_lock); 253 ret = lenovo_send_cmd_cptkbd(hdev, 0x02, cptkbd_data->sensitivity); 254 if (ret) 255 hid_err(hdev, "Fn-lock setting failed: %d\n", ret); 256 } 257 258 static ssize_t attr_fn_lock_show_cptkbd(struct device *dev, 259 struct device_attribute *attr, 260 char *buf) 261 { 262 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 263 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 264 265 return snprintf(buf, PAGE_SIZE, "%u\n", cptkbd_data->fn_lock); 266 } 267 268 static ssize_t attr_fn_lock_store_cptkbd(struct device *dev, 269 struct device_attribute *attr, 270 const char *buf, 271 size_t count) 272 { 273 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 274 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 275 int value; 276 277 if (kstrtoint(buf, 10, &value)) 278 return -EINVAL; 279 if (value < 0 || value > 1) 280 return -EINVAL; 281 282 cptkbd_data->fn_lock = !!value; 283 lenovo_features_set_cptkbd(hdev); 284 285 return count; 286 } 287 288 static ssize_t attr_sensitivity_show_cptkbd(struct device *dev, 289 struct device_attribute *attr, 290 char *buf) 291 { 292 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 293 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 294 295 return snprintf(buf, PAGE_SIZE, "%u\n", 296 cptkbd_data->sensitivity); 297 } 298 299 static ssize_t attr_sensitivity_store_cptkbd(struct device *dev, 300 struct device_attribute *attr, 301 const char *buf, 302 size_t count) 303 { 304 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 305 struct lenovo_drvdata_cptkbd *cptkbd_data = hid_get_drvdata(hdev); 306 int value; 307 308 if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 309 return -EINVAL; 310 311 cptkbd_data->sensitivity = value; 312 lenovo_features_set_cptkbd(hdev); 313 314 return count; 315 } 316 317 318 static struct device_attribute dev_attr_fn_lock_cptkbd = 319 __ATTR(fn_lock, S_IWUSR | S_IRUGO, 320 attr_fn_lock_show_cptkbd, 321 attr_fn_lock_store_cptkbd); 322 323 static struct device_attribute dev_attr_sensitivity_cptkbd = 324 __ATTR(sensitivity, S_IWUSR | S_IRUGO, 325 attr_sensitivity_show_cptkbd, 326 attr_sensitivity_store_cptkbd); 327 328 329 static struct attribute *lenovo_attributes_cptkbd[] = { 330 &dev_attr_fn_lock_cptkbd.attr, 331 &dev_attr_sensitivity_cptkbd.attr, 332 NULL 333 }; 334 335 static const struct attribute_group lenovo_attr_group_cptkbd = { 336 .attrs = lenovo_attributes_cptkbd, 337 }; 338 339 static int lenovo_raw_event(struct hid_device *hdev, 340 struct hid_report *report, u8 *data, int size) 341 { 342 /* 343 * Compact USB keyboard's Fn-F12 report holds down many other keys, and 344 * its own key is outside the usage page range. Remove extra 345 * keypresses and remap to inside usage page. 346 */ 347 if (unlikely(hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD 348 && size == 3 349 && data[0] == 0x15 350 && data[1] == 0x94 351 && data[2] == 0x01)) { 352 data[1] = 0x00; 353 data[2] = 0x01; 354 } 355 356 return 0; 357 } 358 359 static int lenovo_features_set_tpkbd(struct hid_device *hdev) 360 { 361 struct hid_report *report; 362 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 363 364 report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[4]; 365 366 report->field[0]->value[0] = data_pointer->press_to_select ? 0x01 : 0x02; 367 report->field[0]->value[0] |= data_pointer->dragging ? 0x04 : 0x08; 368 report->field[0]->value[0] |= data_pointer->release_to_select ? 0x10 : 0x20; 369 report->field[0]->value[0] |= data_pointer->select_right ? 0x80 : 0x40; 370 report->field[1]->value[0] = 0x03; // unknown setting, imitate windows driver 371 report->field[2]->value[0] = data_pointer->sensitivity; 372 report->field[3]->value[0] = data_pointer->press_speed; 373 374 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 375 return 0; 376 } 377 378 static ssize_t attr_press_to_select_show_tpkbd(struct device *dev, 379 struct device_attribute *attr, 380 char *buf) 381 { 382 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 383 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 384 385 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->press_to_select); 386 } 387 388 static ssize_t attr_press_to_select_store_tpkbd(struct device *dev, 389 struct device_attribute *attr, 390 const char *buf, 391 size_t count) 392 { 393 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 394 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 395 int value; 396 397 if (kstrtoint(buf, 10, &value)) 398 return -EINVAL; 399 if (value < 0 || value > 1) 400 return -EINVAL; 401 402 data_pointer->press_to_select = value; 403 lenovo_features_set_tpkbd(hdev); 404 405 return count; 406 } 407 408 static ssize_t attr_dragging_show_tpkbd(struct device *dev, 409 struct device_attribute *attr, 410 char *buf) 411 { 412 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 413 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 414 415 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->dragging); 416 } 417 418 static ssize_t attr_dragging_store_tpkbd(struct device *dev, 419 struct device_attribute *attr, 420 const char *buf, 421 size_t count) 422 { 423 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 424 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 425 int value; 426 427 if (kstrtoint(buf, 10, &value)) 428 return -EINVAL; 429 if (value < 0 || value > 1) 430 return -EINVAL; 431 432 data_pointer->dragging = value; 433 lenovo_features_set_tpkbd(hdev); 434 435 return count; 436 } 437 438 static ssize_t attr_release_to_select_show_tpkbd(struct device *dev, 439 struct device_attribute *attr, 440 char *buf) 441 { 442 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 443 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 444 445 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->release_to_select); 446 } 447 448 static ssize_t attr_release_to_select_store_tpkbd(struct device *dev, 449 struct device_attribute *attr, 450 const char *buf, 451 size_t count) 452 { 453 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 454 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 455 int value; 456 457 if (kstrtoint(buf, 10, &value)) 458 return -EINVAL; 459 if (value < 0 || value > 1) 460 return -EINVAL; 461 462 data_pointer->release_to_select = value; 463 lenovo_features_set_tpkbd(hdev); 464 465 return count; 466 } 467 468 static ssize_t attr_select_right_show_tpkbd(struct device *dev, 469 struct device_attribute *attr, 470 char *buf) 471 { 472 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 473 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 474 475 return snprintf(buf, PAGE_SIZE, "%u\n", data_pointer->select_right); 476 } 477 478 static ssize_t attr_select_right_store_tpkbd(struct device *dev, 479 struct device_attribute *attr, 480 const char *buf, 481 size_t count) 482 { 483 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 484 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 485 int value; 486 487 if (kstrtoint(buf, 10, &value)) 488 return -EINVAL; 489 if (value < 0 || value > 1) 490 return -EINVAL; 491 492 data_pointer->select_right = value; 493 lenovo_features_set_tpkbd(hdev); 494 495 return count; 496 } 497 498 static ssize_t attr_sensitivity_show_tpkbd(struct device *dev, 499 struct device_attribute *attr, 500 char *buf) 501 { 502 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 503 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 504 505 return snprintf(buf, PAGE_SIZE, "%u\n", 506 data_pointer->sensitivity); 507 } 508 509 static ssize_t attr_sensitivity_store_tpkbd(struct device *dev, 510 struct device_attribute *attr, 511 const char *buf, 512 size_t count) 513 { 514 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 515 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 516 int value; 517 518 if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 519 return -EINVAL; 520 521 data_pointer->sensitivity = value; 522 lenovo_features_set_tpkbd(hdev); 523 524 return count; 525 } 526 527 static ssize_t attr_press_speed_show_tpkbd(struct device *dev, 528 struct device_attribute *attr, 529 char *buf) 530 { 531 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 532 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 533 534 return snprintf(buf, PAGE_SIZE, "%u\n", 535 data_pointer->press_speed); 536 } 537 538 static ssize_t attr_press_speed_store_tpkbd(struct device *dev, 539 struct device_attribute *attr, 540 const char *buf, 541 size_t count) 542 { 543 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 544 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 545 int value; 546 547 if (kstrtoint(buf, 10, &value) || value < 1 || value > 255) 548 return -EINVAL; 549 550 data_pointer->press_speed = value; 551 lenovo_features_set_tpkbd(hdev); 552 553 return count; 554 } 555 556 static struct device_attribute dev_attr_press_to_select_tpkbd = 557 __ATTR(press_to_select, S_IWUSR | S_IRUGO, 558 attr_press_to_select_show_tpkbd, 559 attr_press_to_select_store_tpkbd); 560 561 static struct device_attribute dev_attr_dragging_tpkbd = 562 __ATTR(dragging, S_IWUSR | S_IRUGO, 563 attr_dragging_show_tpkbd, 564 attr_dragging_store_tpkbd); 565 566 static struct device_attribute dev_attr_release_to_select_tpkbd = 567 __ATTR(release_to_select, S_IWUSR | S_IRUGO, 568 attr_release_to_select_show_tpkbd, 569 attr_release_to_select_store_tpkbd); 570 571 static struct device_attribute dev_attr_select_right_tpkbd = 572 __ATTR(select_right, S_IWUSR | S_IRUGO, 573 attr_select_right_show_tpkbd, 574 attr_select_right_store_tpkbd); 575 576 static struct device_attribute dev_attr_sensitivity_tpkbd = 577 __ATTR(sensitivity, S_IWUSR | S_IRUGO, 578 attr_sensitivity_show_tpkbd, 579 attr_sensitivity_store_tpkbd); 580 581 static struct device_attribute dev_attr_press_speed_tpkbd = 582 __ATTR(press_speed, S_IWUSR | S_IRUGO, 583 attr_press_speed_show_tpkbd, 584 attr_press_speed_store_tpkbd); 585 586 static struct attribute *lenovo_attributes_tpkbd[] = { 587 &dev_attr_press_to_select_tpkbd.attr, 588 &dev_attr_dragging_tpkbd.attr, 589 &dev_attr_release_to_select_tpkbd.attr, 590 &dev_attr_select_right_tpkbd.attr, 591 &dev_attr_sensitivity_tpkbd.attr, 592 &dev_attr_press_speed_tpkbd.attr, 593 NULL 594 }; 595 596 static const struct attribute_group lenovo_attr_group_tpkbd = { 597 .attrs = lenovo_attributes_tpkbd, 598 }; 599 600 static enum led_brightness lenovo_led_brightness_get_tpkbd( 601 struct led_classdev *led_cdev) 602 { 603 struct device *dev = led_cdev->dev->parent; 604 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 605 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 606 int led_nr = 0; 607 608 if (led_cdev == &data_pointer->led_micmute) 609 led_nr = 1; 610 611 return data_pointer->led_state & (1 << led_nr) 612 ? LED_FULL 613 : LED_OFF; 614 } 615 616 static void lenovo_led_brightness_set_tpkbd(struct led_classdev *led_cdev, 617 enum led_brightness value) 618 { 619 struct device *dev = led_cdev->dev->parent; 620 struct hid_device *hdev = container_of(dev, struct hid_device, dev); 621 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 622 struct hid_report *report; 623 int led_nr = 0; 624 625 if (led_cdev == &data_pointer->led_micmute) 626 led_nr = 1; 627 628 if (value == LED_OFF) 629 data_pointer->led_state &= ~(1 << led_nr); 630 else 631 data_pointer->led_state |= 1 << led_nr; 632 633 report = hdev->report_enum[HID_OUTPUT_REPORT].report_id_hash[3]; 634 report->field[0]->value[0] = (data_pointer->led_state >> 0) & 1; 635 report->field[0]->value[1] = (data_pointer->led_state >> 1) & 1; 636 hid_hw_request(hdev, report, HID_REQ_SET_REPORT); 637 } 638 639 static int lenovo_probe_tpkbd(struct hid_device *hdev) 640 { 641 struct device *dev = &hdev->dev; 642 struct lenovo_drvdata_tpkbd *data_pointer; 643 size_t name_sz = strlen(dev_name(dev)) + 16; 644 char *name_mute, *name_micmute; 645 int i; 646 int ret; 647 648 /* 649 * Only register extra settings against subdevice where input_mapping 650 * set drvdata to 1, i.e. the trackpoint. 651 */ 652 if (!hid_get_drvdata(hdev)) 653 return 0; 654 655 hid_set_drvdata(hdev, NULL); 656 657 /* Validate required reports. */ 658 for (i = 0; i < 4; i++) { 659 if (!hid_validate_values(hdev, HID_FEATURE_REPORT, 4, i, 1)) 660 return -ENODEV; 661 } 662 if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 3, 0, 2)) 663 return -ENODEV; 664 665 ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd); 666 if (ret) 667 hid_warn(hdev, "Could not create sysfs group: %d\n", ret); 668 669 data_pointer = devm_kzalloc(&hdev->dev, 670 sizeof(struct lenovo_drvdata_tpkbd), 671 GFP_KERNEL); 672 if (data_pointer == NULL) { 673 hid_err(hdev, "Could not allocate memory for driver data\n"); 674 return -ENOMEM; 675 } 676 677 // set same default values as windows driver 678 data_pointer->sensitivity = 0xa0; 679 data_pointer->press_speed = 0x38; 680 681 name_mute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); 682 name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); 683 if (name_mute == NULL || name_micmute == NULL) { 684 hid_err(hdev, "Could not allocate memory for led data\n"); 685 return -ENOMEM; 686 } 687 snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev)); 688 snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev)); 689 690 hid_set_drvdata(hdev, data_pointer); 691 692 data_pointer->led_mute.name = name_mute; 693 data_pointer->led_mute.brightness_get = lenovo_led_brightness_get_tpkbd; 694 data_pointer->led_mute.brightness_set = lenovo_led_brightness_set_tpkbd; 695 data_pointer->led_mute.dev = dev; 696 led_classdev_register(dev, &data_pointer->led_mute); 697 698 data_pointer->led_micmute.name = name_micmute; 699 data_pointer->led_micmute.brightness_get = 700 lenovo_led_brightness_get_tpkbd; 701 data_pointer->led_micmute.brightness_set = 702 lenovo_led_brightness_set_tpkbd; 703 data_pointer->led_micmute.dev = dev; 704 led_classdev_register(dev, &data_pointer->led_micmute); 705 706 lenovo_features_set_tpkbd(hdev); 707 708 return 0; 709 } 710 711 static int lenovo_probe_cptkbd(struct hid_device *hdev) 712 { 713 int ret; 714 struct lenovo_drvdata_cptkbd *cptkbd_data; 715 716 /* All the custom action happens on the USBMOUSE device for USB */ 717 if (hdev->product == USB_DEVICE_ID_LENOVO_CUSBKBD 718 && hdev->type != HID_TYPE_USBMOUSE) { 719 hid_dbg(hdev, "Ignoring keyboard half of device\n"); 720 return 0; 721 } 722 723 cptkbd_data = devm_kzalloc(&hdev->dev, 724 sizeof(*cptkbd_data), 725 GFP_KERNEL); 726 if (cptkbd_data == NULL) { 727 hid_err(hdev, "can't alloc keyboard descriptor\n"); 728 return -ENOMEM; 729 } 730 hid_set_drvdata(hdev, cptkbd_data); 731 732 /* 733 * Tell the keyboard a driver understands it, and turn F7, F9, F11 into 734 * regular keys 735 */ 736 ret = lenovo_send_cmd_cptkbd(hdev, 0x01, 0x03); 737 if (ret) 738 hid_warn(hdev, "Failed to switch F7/9/11 mode: %d\n", ret); 739 740 /* Switch middle button to native mode */ 741 ret = lenovo_send_cmd_cptkbd(hdev, 0x09, 0x01); 742 if (ret) 743 hid_warn(hdev, "Failed to switch middle button: %d\n", ret); 744 745 /* Set keyboard settings to known state */ 746 cptkbd_data->fn_lock = true; 747 cptkbd_data->sensitivity = 0x05; 748 lenovo_features_set_cptkbd(hdev); 749 750 ret = sysfs_create_group(&hdev->dev.kobj, &lenovo_attr_group_cptkbd); 751 if (ret) 752 hid_warn(hdev, "Could not create sysfs group: %d\n", ret); 753 754 return 0; 755 } 756 757 static int lenovo_probe(struct hid_device *hdev, 758 const struct hid_device_id *id) 759 { 760 int ret; 761 762 ret = hid_parse(hdev); 763 if (ret) { 764 hid_err(hdev, "hid_parse failed\n"); 765 goto err; 766 } 767 768 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 769 if (ret) { 770 hid_err(hdev, "hid_hw_start failed\n"); 771 goto err; 772 } 773 774 switch (hdev->product) { 775 case USB_DEVICE_ID_LENOVO_TPKBD: 776 ret = lenovo_probe_tpkbd(hdev); 777 break; 778 case USB_DEVICE_ID_LENOVO_CUSBKBD: 779 case USB_DEVICE_ID_LENOVO_CBTKBD: 780 ret = lenovo_probe_cptkbd(hdev); 781 break; 782 default: 783 ret = 0; 784 break; 785 } 786 if (ret) 787 goto err_hid; 788 789 return 0; 790 err_hid: 791 hid_hw_stop(hdev); 792 err: 793 return ret; 794 } 795 796 static void lenovo_remove_tpkbd(struct hid_device *hdev) 797 { 798 struct lenovo_drvdata_tpkbd *data_pointer = hid_get_drvdata(hdev); 799 800 /* 801 * Only the trackpoint half of the keyboard has drvdata and stuff that 802 * needs unregistering. 803 */ 804 if (data_pointer == NULL) 805 return; 806 807 sysfs_remove_group(&hdev->dev.kobj, 808 &lenovo_attr_group_tpkbd); 809 810 led_classdev_unregister(&data_pointer->led_micmute); 811 led_classdev_unregister(&data_pointer->led_mute); 812 813 hid_set_drvdata(hdev, NULL); 814 } 815 816 static void lenovo_remove_cptkbd(struct hid_device *hdev) 817 { 818 sysfs_remove_group(&hdev->dev.kobj, 819 &lenovo_attr_group_cptkbd); 820 } 821 822 static void lenovo_remove(struct hid_device *hdev) 823 { 824 switch (hdev->product) { 825 case USB_DEVICE_ID_LENOVO_TPKBD: 826 lenovo_remove_tpkbd(hdev); 827 break; 828 case USB_DEVICE_ID_LENOVO_CUSBKBD: 829 case USB_DEVICE_ID_LENOVO_CBTKBD: 830 lenovo_remove_cptkbd(hdev); 831 break; 832 } 833 834 hid_hw_stop(hdev); 835 } 836 837 static const struct hid_device_id lenovo_devices[] = { 838 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, 839 { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, 840 { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, 841 { } 842 }; 843 844 MODULE_DEVICE_TABLE(hid, lenovo_devices); 845 846 static struct hid_driver lenovo_driver = { 847 .name = "lenovo", 848 .id_table = lenovo_devices, 849 .input_mapping = lenovo_input_mapping, 850 .probe = lenovo_probe, 851 .remove = lenovo_remove, 852 .raw_event = lenovo_raw_event, 853 }; 854 module_hid_driver(lenovo_driver); 855 856 MODULE_LICENSE("GPL"); 857 858 859 860 861 862 /* LDV_COMMENT_BEGIN_MAIN */ 863 #ifdef LDV_MAIN0_sequence_infinite_withcheck_stateful 864 865 /*###########################################################################*/ 866 867 /*############## Driver Environment Generator 0.2 output ####################*/ 868 869 /*###########################################################################*/ 870 871 872 873 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Test if all kernel resources are correctly released by driver before driver will be unloaded. */ 874 void ldv_check_final_state(void); 875 876 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Test correct return result. */ 877 void ldv_check_return_value(int res); 878 879 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Test correct return result of probe() function. */ 880 void ldv_check_return_value_probe(int res); 881 882 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Initializes the model. */ 883 void ldv_initialize(void); 884 885 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Reinitializes the model between distinct model function calls. */ 886 void ldv_handler_precall(void); 887 888 /* LDV_COMMENT_FUNCTION_DECLARE_LDV Special function for LDV verifier. Returns arbitrary interger value. */ 889 int nondet_int(void); 890 891 /* LDV_COMMENT_VAR_DECLARE_LDV Special variable for LDV verifier. */ 892 int LDV_IN_INTERRUPT; 893 894 /* LDV_COMMENT_FUNCTION_MAIN Main function for LDV verifier. */ 895 void ldv_main0_sequence_infinite_withcheck_stateful(void) { 896 897 898 899 /* LDV_COMMENT_BEGIN_VARIABLE_DECLARATION_PART */ 900 /*============================= VARIABLE DECLARATION PART =============================*/ 901 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 902 /* content: static int lenovo_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max)*/ 903 /* LDV_COMMENT_BEGIN_PREP */ 904 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 905 /* LDV_COMMENT_END_PREP */ 906 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 907 struct hid_device * var_group1; 908 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 909 struct hid_input * var_group2; 910 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 911 struct hid_field * var_lenovo_input_mapping_2_p2; 912 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 913 struct hid_usage * var_lenovo_input_mapping_2_p3; 914 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 915 unsigned long ** var_lenovo_input_mapping_2_p4; 916 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_input_mapping" */ 917 int * var_lenovo_input_mapping_2_p5; 918 /* LDV_COMMENT_BEGIN_PREP */ 919 #undef map_key_clear 920 /* LDV_COMMENT_END_PREP */ 921 /* content: static int lenovo_probe(struct hid_device *hdev, const struct hid_device_id *id)*/ 922 /* LDV_COMMENT_BEGIN_PREP */ 923 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 924 #undef map_key_clear 925 /* LDV_COMMENT_END_PREP */ 926 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_probe" */ 927 const struct hid_device_id * var_lenovo_probe_27_p1; 928 /* LDV_COMMENT_VAR_DECLARE Variable declaration for test return result from function call "lenovo_probe" */ 929 static int res_lenovo_probe_27; 930 /* content: static void lenovo_remove(struct hid_device *hdev)*/ 931 /* LDV_COMMENT_BEGIN_PREP */ 932 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 933 #undef map_key_clear 934 /* LDV_COMMENT_END_PREP */ 935 /* content: static int lenovo_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size)*/ 936 /* LDV_COMMENT_BEGIN_PREP */ 937 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 938 #undef map_key_clear 939 /* LDV_COMMENT_END_PREP */ 940 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_raw_event" */ 941 struct hid_report * var_group3; 942 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_raw_event" */ 943 u8 * var_lenovo_raw_event_9_p2; 944 /* LDV_COMMENT_VAR_DECLARE Variable declaration for function "lenovo_raw_event" */ 945 int var_lenovo_raw_event_9_p3; 946 947 948 949 950 /* LDV_COMMENT_END_VARIABLE_DECLARATION_PART */ 951 /* LDV_COMMENT_BEGIN_VARIABLE_INITIALIZING_PART */ 952 /*============================= VARIABLE INITIALIZING PART =============================*/ 953 LDV_IN_INTERRUPT=1; 954 955 956 957 958 /* LDV_COMMENT_END_VARIABLE_INITIALIZING_PART */ 959 /* LDV_COMMENT_BEGIN_FUNCTION_CALL_SECTION */ 960 /*============================= FUNCTION CALL SECTION =============================*/ 961 /* LDV_COMMENT_FUNCTION_CALL Initialize LDV model. */ 962 ldv_initialize(); 963 int ldv_s_lenovo_driver_hid_driver = 0; 964 965 966 967 while( nondet_int() 968 || !(ldv_s_lenovo_driver_hid_driver == 0) 969 ) { 970 971 switch(nondet_int()) { 972 973 case 0: { 974 975 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 976 if(ldv_s_lenovo_driver_hid_driver==0) { 977 978 /* content: static int lenovo_probe(struct hid_device *hdev, const struct hid_device_id *id)*/ 979 /* LDV_COMMENT_BEGIN_PREP */ 980 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 981 #undef map_key_clear 982 /* LDV_COMMENT_END_PREP */ 983 /* LDV_COMMENT_FUNCTION_CALL Function from field "probe" from driver structure with callbacks "lenovo_driver". Standart function test for correct return result. */ 984 res_lenovo_probe_27 = lenovo_probe( var_group1, var_lenovo_probe_27_p1); 985 ldv_check_return_value(res_lenovo_probe_27); 986 ldv_check_return_value_probe(res_lenovo_probe_27); 987 if(res_lenovo_probe_27) 988 goto ldv_module_exit; 989 ldv_s_lenovo_driver_hid_driver++; 990 991 } 992 993 } 994 995 break; 996 case 1: { 997 998 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 999 if(ldv_s_lenovo_driver_hid_driver==1) { 1000 1001 /* content: static void lenovo_remove(struct hid_device *hdev)*/ 1002 /* LDV_COMMENT_BEGIN_PREP */ 1003 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 1004 #undef map_key_clear 1005 /* LDV_COMMENT_END_PREP */ 1006 /* LDV_COMMENT_FUNCTION_CALL Function from field "remove" from driver structure with callbacks "lenovo_driver" */ 1007 ldv_handler_precall(); 1008 lenovo_remove( var_group1); 1009 ldv_s_lenovo_driver_hid_driver=0; 1010 1011 } 1012 1013 } 1014 1015 break; 1016 case 2: { 1017 1018 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 1019 1020 1021 /* content: static int lenovo_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max)*/ 1022 /* LDV_COMMENT_BEGIN_PREP */ 1023 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 1024 /* LDV_COMMENT_END_PREP */ 1025 /* LDV_COMMENT_FUNCTION_CALL Function from field "input_mapping" from driver structure with callbacks "lenovo_driver" */ 1026 ldv_handler_precall(); 1027 lenovo_input_mapping( var_group1, var_group2, var_lenovo_input_mapping_2_p2, var_lenovo_input_mapping_2_p3, var_lenovo_input_mapping_2_p4, var_lenovo_input_mapping_2_p5); 1028 /* LDV_COMMENT_BEGIN_PREP */ 1029 #undef map_key_clear 1030 /* LDV_COMMENT_END_PREP */ 1031 1032 1033 1034 1035 } 1036 1037 break; 1038 case 3: { 1039 1040 /** STRUCT: struct type: hid_driver, struct name: lenovo_driver **/ 1041 1042 1043 /* content: static int lenovo_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *data, int size)*/ 1044 /* LDV_COMMENT_BEGIN_PREP */ 1045 #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) 1046 #undef map_key_clear 1047 /* LDV_COMMENT_END_PREP */ 1048 /* LDV_COMMENT_FUNCTION_CALL Function from field "raw_event" from driver structure with callbacks "lenovo_driver" */ 1049 ldv_handler_precall(); 1050 lenovo_raw_event( var_group1, var_group3, var_lenovo_raw_event_9_p2, var_lenovo_raw_event_9_p3); 1051 1052 1053 1054 1055 } 1056 1057 break; 1058 default: break; 1059 1060 } 1061 1062 } 1063 1064 ldv_module_exit: 1065 1066 /* LDV_COMMENT_FUNCTION_CALL Checks that all resources and locks are correctly released before the driver will be unloaded. */ 1067 ldv_final: ldv_check_final_state(); 1068 1069 /* LDV_COMMENT_END_FUNCTION_CALL_SECTION */ 1070 return; 1071 1072 } 1073 #endif 1074 1075 /* LDV_COMMENT_END_MAIN */ 1076 1077 #line 71 "/work/ldvuser/ref_launch/work/current--X--drivers--X--defaultlinux-4.0-rc1.tar.xz--X--151_1a/linux-4.0-rc1.tar.xz/csd_deg_dscv/564/dscv_tempdir/dscv/ri/151_1a/drivers/hid/hid-lenovo.o.c.prepared"
1 #ifndef _LDV_RCV_H_ 2 #define _LDV_RCV_H_ 3 4 /* If expr evaluates to zero, ldv_assert() causes a program to reach the error 5 label like the standard assert(). */ 6 #define ldv_assert(expr) ((expr) ? 0 : ldv_error()) 7 8 /* The error label wrapper. It is used because of some static verifiers (like 9 BLAST) don't accept multiple error labels through a program. */ 10 static inline void ldv_error(void) 11 { 12 LDV_ERROR: goto LDV_ERROR; 13 } 14 15 /* If expr evaluates to zero, ldv_assume() causes an infinite loop that is 16 avoided by verifiers. */ 17 #define ldv_assume(expr) ((expr) ? 0 : ldv_stop()) 18 19 /* Infinite loop, that causes verifiers to skip such paths. */ 20 static inline void ldv_stop(void) { 21 LDV_STOP: goto LDV_STOP; 22 } 23 24 /* Special nondeterministic functions. */ 25 int ldv_undef_int(void); 26 void *ldv_undef_ptr(void); 27 unsigned long ldv_undef_ulong(void); 28 long ldv_undef_long(void); 29 /* Return nondeterministic negative integer number. */ 30 static inline int ldv_undef_int_negative(void) 31 { 32 int ret = ldv_undef_int(); 33 34 ldv_assume(ret < 0); 35 36 return ret; 37 } 38 /* Return nondeterministic nonpositive integer number. */ 39 static inline int ldv_undef_int_nonpositive(void) 40 { 41 int ret = ldv_undef_int(); 42 43 ldv_assume(ret <= 0); 44 45 return ret; 46 } 47 48 /* Add explicit model for __builin_expect GCC function. Without the model a 49 return value will be treated as nondetermined by verifiers. */ 50 long __builtin_expect(long exp, long c) 51 { 52 return exp; 53 } 54 55 /* This function causes the program to exit abnormally. GCC implements this 56 function by using a target-dependent mechanism (such as intentionally executing 57 an illegal instruction) or by calling abort. The mechanism used may vary from 58 release to release so you should not rely on any particular implementation. 59 http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html */ 60 void __builtin_trap(void) 61 { 62 ldv_assert(0); 63 } 64 65 /* The constant is for simulating an error of ldv_undef_ptr() function. */ 66 #define LDV_PTR_MAX 2012 67 68 #endif /* _LDV_RCV_H_ */
1 /* 2 * Copyright (c) 1999 Andreas Gal 3 * Copyright (c) 2000-2001 Vojtech Pavlik 4 * Copyright (c) 2006-2007 Jiri Kosina 5 */ 6 /* 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 * 21 * Should you need to contact me, the author, you can do so either by 22 * e-mail - mail your message to <vojtech@ucw.cz>, or by paper mail: 23 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic 24 */ 25 #ifndef __HID_H 26 #define __HID_H 27 28 29 #include <linux/types.h> 30 #include <linux/slab.h> 31 #include <linux/list.h> 32 #include <linux/mod_devicetable.h> /* hid_device_id */ 33 #include <linux/timer.h> 34 #include <linux/workqueue.h> 35 #include <linux/input.h> 36 #include <linux/semaphore.h> 37 #include <linux/power_supply.h> 38 #include <uapi/linux/hid.h> 39 40 /* 41 * We parse each description item into this structure. Short items data 42 * values are expanded to 32-bit signed int, long items contain a pointer 43 * into the data area. 44 */ 45 46 struct hid_item { 47 unsigned format; 48 __u8 size; 49 __u8 type; 50 __u8 tag; 51 union { 52 __u8 u8; 53 __s8 s8; 54 __u16 u16; 55 __s16 s16; 56 __u32 u32; 57 __s32 s32; 58 __u8 *longdata; 59 } data; 60 }; 61 62 /* 63 * HID report item format 64 */ 65 66 #define HID_ITEM_FORMAT_SHORT 0 67 #define HID_ITEM_FORMAT_LONG 1 68 69 /* 70 * Special tag indicating long items 71 */ 72 73 #define HID_ITEM_TAG_LONG 15 74 75 /* 76 * HID report descriptor item type (prefix bit 2,3) 77 */ 78 79 #define HID_ITEM_TYPE_MAIN 0 80 #define HID_ITEM_TYPE_GLOBAL 1 81 #define HID_ITEM_TYPE_LOCAL 2 82 #define HID_ITEM_TYPE_RESERVED 3 83 84 /* 85 * HID report descriptor main item tags 86 */ 87 88 #define HID_MAIN_ITEM_TAG_INPUT 8 89 #define HID_MAIN_ITEM_TAG_OUTPUT 9 90 #define HID_MAIN_ITEM_TAG_FEATURE 11 91 #define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10 92 #define HID_MAIN_ITEM_TAG_END_COLLECTION 12 93 94 /* 95 * HID report descriptor main item contents 96 */ 97 98 #define HID_MAIN_ITEM_CONSTANT 0x001 99 #define HID_MAIN_ITEM_VARIABLE 0x002 100 #define HID_MAIN_ITEM_RELATIVE 0x004 101 #define HID_MAIN_ITEM_WRAP 0x008 102 #define HID_MAIN_ITEM_NONLINEAR 0x010 103 #define HID_MAIN_ITEM_NO_PREFERRED 0x020 104 #define HID_MAIN_ITEM_NULL_STATE 0x040 105 #define HID_MAIN_ITEM_VOLATILE 0x080 106 #define HID_MAIN_ITEM_BUFFERED_BYTE 0x100 107 108 /* 109 * HID report descriptor collection item types 110 */ 111 112 #define HID_COLLECTION_PHYSICAL 0 113 #define HID_COLLECTION_APPLICATION 1 114 #define HID_COLLECTION_LOGICAL 2 115 116 /* 117 * HID report descriptor global item tags 118 */ 119 120 #define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0 121 #define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1 122 #define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2 123 #define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3 124 #define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4 125 #define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5 126 #define HID_GLOBAL_ITEM_TAG_UNIT 6 127 #define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7 128 #define HID_GLOBAL_ITEM_TAG_REPORT_ID 8 129 #define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9 130 #define HID_GLOBAL_ITEM_TAG_PUSH 10 131 #define HID_GLOBAL_ITEM_TAG_POP 11 132 133 /* 134 * HID report descriptor local item tags 135 */ 136 137 #define HID_LOCAL_ITEM_TAG_USAGE 0 138 #define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1 139 #define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2 140 #define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3 141 #define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4 142 #define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5 143 #define HID_LOCAL_ITEM_TAG_STRING_INDEX 7 144 #define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8 145 #define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9 146 #define HID_LOCAL_ITEM_TAG_DELIMITER 10 147 148 /* 149 * HID usage tables 150 */ 151 152 #define HID_USAGE_PAGE 0xffff0000 153 154 #define HID_UP_UNDEFINED 0x00000000 155 #define HID_UP_GENDESK 0x00010000 156 #define HID_UP_SIMULATION 0x00020000 157 #define HID_UP_GENDEVCTRLS 0x00060000 158 #define HID_UP_KEYBOARD 0x00070000 159 #define HID_UP_LED 0x00080000 160 #define HID_UP_BUTTON 0x00090000 161 #define HID_UP_ORDINAL 0x000a0000 162 #define HID_UP_CONSUMER 0x000c0000 163 #define HID_UP_DIGITIZER 0x000d0000 164 #define HID_UP_PID 0x000f0000 165 #define HID_UP_HPVENDOR 0xff7f0000 166 #define HID_UP_HPVENDOR2 0xff010000 167 #define HID_UP_MSVENDOR 0xff000000 168 #define HID_UP_CUSTOM 0x00ff0000 169 #define HID_UP_LOGIVENDOR 0xffbc0000 170 #define HID_UP_LNVENDOR 0xffa00000 171 #define HID_UP_SENSOR 0x00200000 172 173 #define HID_USAGE 0x0000ffff 174 175 #define HID_GD_POINTER 0x00010001 176 #define HID_GD_MOUSE 0x00010002 177 #define HID_GD_JOYSTICK 0x00010004 178 #define HID_GD_GAMEPAD 0x00010005 179 #define HID_GD_KEYBOARD 0x00010006 180 #define HID_GD_KEYPAD 0x00010007 181 #define HID_GD_MULTIAXIS 0x00010008 182 #define HID_GD_X 0x00010030 183 #define HID_GD_Y 0x00010031 184 #define HID_GD_Z 0x00010032 185 #define HID_GD_RX 0x00010033 186 #define HID_GD_RY 0x00010034 187 #define HID_GD_RZ 0x00010035 188 #define HID_GD_SLIDER 0x00010036 189 #define HID_GD_DIAL 0x00010037 190 #define HID_GD_WHEEL 0x00010038 191 #define HID_GD_HATSWITCH 0x00010039 192 #define HID_GD_BUFFER 0x0001003a 193 #define HID_GD_BYTECOUNT 0x0001003b 194 #define HID_GD_MOTION 0x0001003c 195 #define HID_GD_START 0x0001003d 196 #define HID_GD_SELECT 0x0001003e 197 #define HID_GD_VX 0x00010040 198 #define HID_GD_VY 0x00010041 199 #define HID_GD_VZ 0x00010042 200 #define HID_GD_VBRX 0x00010043 201 #define HID_GD_VBRY 0x00010044 202 #define HID_GD_VBRZ 0x00010045 203 #define HID_GD_VNO 0x00010046 204 #define HID_GD_FEATURE 0x00010047 205 #define HID_GD_SYSTEM_CONTROL 0x00010080 206 #define HID_GD_UP 0x00010090 207 #define HID_GD_DOWN 0x00010091 208 #define HID_GD_RIGHT 0x00010092 209 #define HID_GD_LEFT 0x00010093 210 211 #define HID_DC_BATTERYSTRENGTH 0x00060020 212 213 #define HID_CP_CONSUMER_CONTROL 0x000c0001 214 215 #define HID_DG_DIGITIZER 0x000d0001 216 #define HID_DG_PEN 0x000d0002 217 #define HID_DG_LIGHTPEN 0x000d0003 218 #define HID_DG_TOUCHSCREEN 0x000d0004 219 #define HID_DG_TOUCHPAD 0x000d0005 220 #define HID_DG_STYLUS 0x000d0020 221 #define HID_DG_PUCK 0x000d0021 222 #define HID_DG_FINGER 0x000d0022 223 #define HID_DG_TIPPRESSURE 0x000d0030 224 #define HID_DG_BARRELPRESSURE 0x000d0031 225 #define HID_DG_INRANGE 0x000d0032 226 #define HID_DG_TOUCH 0x000d0033 227 #define HID_DG_UNTOUCH 0x000d0034 228 #define HID_DG_TAP 0x000d0035 229 #define HID_DG_TABLETFUNCTIONKEY 0x000d0039 230 #define HID_DG_PROGRAMCHANGEKEY 0x000d003a 231 #define HID_DG_INVERT 0x000d003c 232 #define HID_DG_TIPSWITCH 0x000d0042 233 #define HID_DG_TIPSWITCH2 0x000d0043 234 #define HID_DG_BARRELSWITCH 0x000d0044 235 #define HID_DG_ERASER 0x000d0045 236 #define HID_DG_TABLETPICK 0x000d0046 237 238 #define HID_CP_CONSUMERCONTROL 0x000c0001 239 #define HID_CP_NUMERICKEYPAD 0x000c0002 240 #define HID_CP_PROGRAMMABLEBUTTONS 0x000c0003 241 #define HID_CP_MICROPHONE 0x000c0004 242 #define HID_CP_HEADPHONE 0x000c0005 243 #define HID_CP_GRAPHICEQUALIZER 0x000c0006 244 #define HID_CP_FUNCTIONBUTTONS 0x000c0036 245 #define HID_CP_SELECTION 0x000c0080 246 #define HID_CP_MEDIASELECTION 0x000c0087 247 #define HID_CP_SELECTDISC 0x000c00ba 248 #define HID_CP_PLAYBACKSPEED 0x000c00f1 249 #define HID_CP_PROXIMITY 0x000c0109 250 #define HID_CP_SPEAKERSYSTEM 0x000c0160 251 #define HID_CP_CHANNELLEFT 0x000c0161 252 #define HID_CP_CHANNELRIGHT 0x000c0162 253 #define HID_CP_CHANNELCENTER 0x000c0163 254 #define HID_CP_CHANNELFRONT 0x000c0164 255 #define HID_CP_CHANNELCENTERFRONT 0x000c0165 256 #define HID_CP_CHANNELSIDE 0x000c0166 257 #define HID_CP_CHANNELSURROUND 0x000c0167 258 #define HID_CP_CHANNELLOWFREQUENCYENHANCEMENT 0x000c0168 259 #define HID_CP_CHANNELTOP 0x000c0169 260 #define HID_CP_CHANNELUNKNOWN 0x000c016a 261 #define HID_CP_APPLICATIONLAUNCHBUTTONS 0x000c0180 262 #define HID_CP_GENERICGUIAPPLICATIONCONTROLS 0x000c0200 263 264 #define HID_DG_CONFIDENCE 0x000d0047 265 #define HID_DG_WIDTH 0x000d0048 266 #define HID_DG_HEIGHT 0x000d0049 267 #define HID_DG_CONTACTID 0x000d0051 268 #define HID_DG_INPUTMODE 0x000d0052 269 #define HID_DG_DEVICEINDEX 0x000d0053 270 #define HID_DG_CONTACTCOUNT 0x000d0054 271 #define HID_DG_CONTACTMAX 0x000d0055 272 #define HID_DG_BARRELSWITCH2 0x000d005a 273 #define HID_DG_TOOLSERIALNUMBER 0x000d005b 274 275 /* 276 * HID report types --- Ouch! HID spec says 1 2 3! 277 */ 278 279 #define HID_INPUT_REPORT 0 280 #define HID_OUTPUT_REPORT 1 281 #define HID_FEATURE_REPORT 2 282 283 #define HID_REPORT_TYPES 3 284 285 /* 286 * HID connect requests 287 */ 288 289 #define HID_CONNECT_HIDINPUT 0x01 290 #define HID_CONNECT_HIDINPUT_FORCE 0x02 291 #define HID_CONNECT_HIDRAW 0x04 292 #define HID_CONNECT_HIDDEV 0x08 293 #define HID_CONNECT_HIDDEV_FORCE 0x10 294 #define HID_CONNECT_FF 0x20 295 #define HID_CONNECT_DRIVER 0x40 296 #define HID_CONNECT_DEFAULT (HID_CONNECT_HIDINPUT|HID_CONNECT_HIDRAW| \ 297 HID_CONNECT_HIDDEV|HID_CONNECT_FF) 298 299 /* 300 * HID device quirks. 301 */ 302 303 /* 304 * Increase this if you need to configure more HID quirks at module load time 305 */ 306 #define MAX_USBHID_BOOT_QUIRKS 4 307 308 #define HID_QUIRK_INVERT 0x00000001 309 #define HID_QUIRK_NOTOUCH 0x00000002 310 #define HID_QUIRK_IGNORE 0x00000004 311 #define HID_QUIRK_NOGET 0x00000008 312 #define HID_QUIRK_HIDDEV_FORCE 0x00000010 313 #define HID_QUIRK_BADPAD 0x00000020 314 #define HID_QUIRK_MULTI_INPUT 0x00000040 315 #define HID_QUIRK_HIDINPUT_FORCE 0x00000080 316 #define HID_QUIRK_NO_EMPTY_INPUT 0x00000100 317 #define HID_QUIRK_NO_INIT_INPUT_REPORTS 0x00000200 318 #define HID_QUIRK_ALWAYS_POLL 0x00000400 319 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 320 #define HID_QUIRK_SKIP_OUTPUT_REPORT_ID 0x00020000 321 #define HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP 0x00040000 322 #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 323 #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 324 #define HID_QUIRK_NO_IGNORE 0x40000000 325 #define HID_QUIRK_NO_INPUT_SYNC 0x80000000 326 327 /* 328 * HID device groups 329 * 330 * Note: HID_GROUP_ANY is declared in linux/mod_devicetable.h 331 * and has a value of 0x0000 332 */ 333 #define HID_GROUP_GENERIC 0x0001 334 #define HID_GROUP_MULTITOUCH 0x0002 335 #define HID_GROUP_SENSOR_HUB 0x0003 336 #define HID_GROUP_MULTITOUCH_WIN_8 0x0004 337 338 /* 339 * Vendor specific HID device groups 340 */ 341 #define HID_GROUP_RMI 0x0100 342 #define HID_GROUP_WACOM 0x0101 343 #define HID_GROUP_LOGITECH_DJ_DEVICE 0x0102 344 345 /* 346 * This is the global environment of the parser. This information is 347 * persistent for main-items. The global environment can be saved and 348 * restored with PUSH/POP statements. 349 */ 350 351 struct hid_global { 352 unsigned usage_page; 353 __s32 logical_minimum; 354 __s32 logical_maximum; 355 __s32 physical_minimum; 356 __s32 physical_maximum; 357 __s32 unit_exponent; 358 unsigned unit; 359 unsigned report_id; 360 unsigned report_size; 361 unsigned report_count; 362 }; 363 364 /* 365 * This is the local environment. It is persistent up the next main-item. 366 */ 367 368 #define HID_MAX_USAGES 12288 369 #define HID_DEFAULT_NUM_COLLECTIONS 16 370 371 struct hid_local { 372 unsigned usage[HID_MAX_USAGES]; /* usage array */ 373 unsigned collection_index[HID_MAX_USAGES]; /* collection index array */ 374 unsigned usage_index; 375 unsigned usage_minimum; 376 unsigned delimiter_depth; 377 unsigned delimiter_branch; 378 }; 379 380 /* 381 * This is the collection stack. We climb up the stack to determine 382 * application and function of each field. 383 */ 384 385 struct hid_collection { 386 unsigned type; 387 unsigned usage; 388 unsigned level; 389 }; 390 391 struct hid_usage { 392 unsigned hid; /* hid usage code */ 393 unsigned collection_index; /* index into collection array */ 394 unsigned usage_index; /* index into usage array */ 395 /* hidinput data */ 396 __u16 code; /* input driver code */ 397 __u8 type; /* input driver type */ 398 __s8 hat_min; /* hat switch fun */ 399 __s8 hat_max; /* ditto */ 400 __s8 hat_dir; /* ditto */ 401 }; 402 403 struct hid_input; 404 405 struct hid_field { 406 unsigned physical; /* physical usage for this field */ 407 unsigned logical; /* logical usage for this field */ 408 unsigned application; /* application usage for this field */ 409 struct hid_usage *usage; /* usage table for this function */ 410 unsigned maxusage; /* maximum usage index */ 411 unsigned flags; /* main-item flags (i.e. volatile,array,constant) */ 412 unsigned report_offset; /* bit offset in the report */ 413 unsigned report_size; /* size of this field in the report */ 414 unsigned report_count; /* number of this field in the report */ 415 unsigned report_type; /* (input,output,feature) */ 416 __s32 *value; /* last known value(s) */ 417 __s32 logical_minimum; 418 __s32 logical_maximum; 419 __s32 physical_minimum; 420 __s32 physical_maximum; 421 __s32 unit_exponent; 422 unsigned unit; 423 struct hid_report *report; /* associated report */ 424 unsigned index; /* index into report->field[] */ 425 /* hidinput data */ 426 struct hid_input *hidinput; /* associated input structure */ 427 __u16 dpad; /* dpad input code */ 428 }; 429 430 #define HID_MAX_FIELDS 256 431 432 struct hid_report { 433 struct list_head list; 434 unsigned id; /* id of this report */ 435 unsigned type; /* report type */ 436 struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */ 437 unsigned maxfield; /* maximum valid field index */ 438 unsigned size; /* size of the report (bits) */ 439 struct hid_device *device; /* associated device */ 440 }; 441 442 #define HID_MAX_IDS 256 443 444 struct hid_report_enum { 445 unsigned numbered; 446 struct list_head report_list; 447 struct hid_report *report_id_hash[HID_MAX_IDS]; 448 }; 449 450 #define HID_MIN_BUFFER_SIZE 64 /* make sure there is at least a packet size of space */ 451 #define HID_MAX_BUFFER_SIZE 4096 /* 4kb */ 452 #define HID_CONTROL_FIFO_SIZE 256 /* to init devices with >100 reports */ 453 #define HID_OUTPUT_FIFO_SIZE 64 454 455 struct hid_control_fifo { 456 unsigned char dir; 457 struct hid_report *report; 458 char *raw_report; 459 }; 460 461 struct hid_output_fifo { 462 struct hid_report *report; 463 char *raw_report; 464 }; 465 466 #define HID_CLAIMED_INPUT 1 467 #define HID_CLAIMED_HIDDEV 2 468 #define HID_CLAIMED_HIDRAW 4 469 #define HID_CLAIMED_DRIVER 8 470 471 #define HID_STAT_ADDED 1 472 #define HID_STAT_PARSED 2 473 474 struct hid_input { 475 struct list_head list; 476 struct hid_report *report; 477 struct input_dev *input; 478 }; 479 480 enum hid_type { 481 HID_TYPE_OTHER = 0, 482 HID_TYPE_USBMOUSE, 483 HID_TYPE_USBNONE 484 }; 485 486 struct hid_driver; 487 struct hid_ll_driver; 488 489 struct hid_device { /* device report descriptor */ 490 __u8 *dev_rdesc; 491 unsigned dev_rsize; 492 __u8 *rdesc; 493 unsigned rsize; 494 struct hid_collection *collection; /* List of HID collections */ 495 unsigned collection_size; /* Number of allocated hid_collections */ 496 unsigned maxcollection; /* Number of parsed collections */ 497 unsigned maxapplication; /* Number of applications */ 498 __u16 bus; /* BUS ID */ 499 __u16 group; /* Report group */ 500 __u32 vendor; /* Vendor ID */ 501 __u32 product; /* Product ID */ 502 __u32 version; /* HID version */ 503 enum hid_type type; /* device type (mouse, kbd, ...) */ 504 unsigned country; /* HID country */ 505 struct hid_report_enum report_enum[HID_REPORT_TYPES]; 506 struct work_struct led_work; /* delayed LED worker */ 507 508 struct semaphore driver_lock; /* protects the current driver, except during input */ 509 struct semaphore driver_input_lock; /* protects the current driver */ 510 struct device dev; /* device */ 511 struct hid_driver *driver; 512 struct hid_ll_driver *ll_driver; 513 514 #ifdef CONFIG_HID_BATTERY_STRENGTH 515 /* 516 * Power supply information for HID devices which report 517 * battery strength. power_supply is registered iff 518 * battery.name is non-NULL. 519 */ 520 struct power_supply battery; 521 __s32 battery_min; 522 __s32 battery_max; 523 __s32 battery_report_type; 524 __s32 battery_report_id; 525 #endif 526 527 unsigned int status; /* see STAT flags above */ 528 unsigned claimed; /* Claimed by hidinput, hiddev? */ 529 unsigned quirks; /* Various quirks the device can pull on us */ 530 bool io_started; /* Protected by driver_lock. If IO has started */ 531 532 struct list_head inputs; /* The list of inputs */ 533 void *hiddev; /* The hiddev structure */ 534 void *hidraw; 535 int minor; /* Hiddev minor number */ 536 537 int open; /* is the device open by anyone? */ 538 char name[128]; /* Device name */ 539 char phys[64]; /* Device physical location */ 540 char uniq[64]; /* Device unique identifier (serial #) */ 541 542 void *driver_data; 543 544 /* temporary hid_ff handling (until moved to the drivers) */ 545 int (*ff_init)(struct hid_device *); 546 547 /* hiddev event handler */ 548 int (*hiddev_connect)(struct hid_device *, unsigned int); 549 void (*hiddev_disconnect)(struct hid_device *); 550 void (*hiddev_hid_event) (struct hid_device *, struct hid_field *field, 551 struct hid_usage *, __s32); 552 void (*hiddev_report_event) (struct hid_device *, struct hid_report *); 553 554 /* debugging support via debugfs */ 555 unsigned short debug; 556 struct dentry *debug_dir; 557 struct dentry *debug_rdesc; 558 struct dentry *debug_events; 559 struct list_head debug_list; 560 spinlock_t debug_list_lock; 561 wait_queue_head_t debug_wait; 562 }; 563 564 static inline void *hid_get_drvdata(struct hid_device *hdev) 565 { 566 return dev_get_drvdata(&hdev->dev); 567 } 568 569 static inline void hid_set_drvdata(struct hid_device *hdev, void *data) 570 { 571 dev_set_drvdata(&hdev->dev, data); 572 } 573 574 #define HID_GLOBAL_STACK_SIZE 4 575 #define HID_COLLECTION_STACK_SIZE 4 576 577 #define HID_SCAN_FLAG_MT_WIN_8 BIT(0) 578 #define HID_SCAN_FLAG_VENDOR_SPECIFIC BIT(1) 579 #define HID_SCAN_FLAG_GD_POINTER BIT(2) 580 581 struct hid_parser { 582 struct hid_global global; 583 struct hid_global global_stack[HID_GLOBAL_STACK_SIZE]; 584 unsigned global_stack_ptr; 585 struct hid_local local; 586 unsigned collection_stack[HID_COLLECTION_STACK_SIZE]; 587 unsigned collection_stack_ptr; 588 struct hid_device *device; 589 unsigned scan_flags; 590 }; 591 592 struct hid_class_descriptor { 593 __u8 bDescriptorType; 594 __le16 wDescriptorLength; 595 } __attribute__ ((packed)); 596 597 struct hid_descriptor { 598 __u8 bLength; 599 __u8 bDescriptorType; 600 __le16 bcdHID; 601 __u8 bCountryCode; 602 __u8 bNumDescriptors; 603 604 struct hid_class_descriptor desc[1]; 605 } __attribute__ ((packed)); 606 607 #define HID_DEVICE(b, g, ven, prod) \ 608 .bus = (b), .group = (g), .vendor = (ven), .product = (prod) 609 #define HID_USB_DEVICE(ven, prod) \ 610 .bus = BUS_USB, .vendor = (ven), .product = (prod) 611 #define HID_BLUETOOTH_DEVICE(ven, prod) \ 612 .bus = BUS_BLUETOOTH, .vendor = (ven), .product = (prod) 613 #define HID_I2C_DEVICE(ven, prod) \ 614 .bus = BUS_I2C, .vendor = (ven), .product = (prod) 615 616 #define HID_REPORT_ID(rep) \ 617 .report_type = (rep) 618 #define HID_USAGE_ID(uhid, utype, ucode) \ 619 .usage_hid = (uhid), .usage_type = (utype), .usage_code = (ucode) 620 /* we don't want to catch types and codes equal to 0 */ 621 #define HID_TERMINATOR (HID_ANY_ID - 1) 622 623 struct hid_report_id { 624 __u32 report_type; 625 }; 626 struct hid_usage_id { 627 __u32 usage_hid; 628 __u32 usage_type; 629 __u32 usage_code; 630 }; 631 632 /** 633 * struct hid_driver 634 * @name: driver name (e.g. "Footech_bar-wheel") 635 * @id_table: which devices is this driver for (must be non-NULL for probe 636 * to be called) 637 * @dyn_list: list of dynamically added device ids 638 * @dyn_lock: lock protecting @dyn_list 639 * @probe: new device inserted 640 * @remove: device removed (NULL if not a hot-plug capable driver) 641 * @report_table: on which reports to call raw_event (NULL means all) 642 * @raw_event: if report in report_table, this hook is called (NULL means nop) 643 * @usage_table: on which events to call event (NULL means all) 644 * @event: if usage in usage_table, this hook is called (NULL means nop) 645 * @report: this hook is called after parsing a report (NULL means nop) 646 * @report_fixup: called before report descriptor parsing (NULL means nop) 647 * @input_mapping: invoked on input registering before mapping an usage 648 * @input_mapped: invoked on input registering after mapping an usage 649 * @input_configured: invoked just before the device is registered 650 * @feature_mapping: invoked on feature registering 651 * @suspend: invoked on suspend (NULL means nop) 652 * @resume: invoked on resume if device was not reset (NULL means nop) 653 * @reset_resume: invoked on resume if device was reset (NULL means nop) 654 * 655 * probe should return -errno on error, or 0 on success. During probe, 656 * input will not be passed to raw_event unless hid_device_io_start is 657 * called. 658 * 659 * raw_event and event should return 0 on no action performed, 1 when no 660 * further processing should be done and negative on error 661 * 662 * input_mapping shall return a negative value to completely ignore this usage 663 * (e.g. doubled or invalid usage), zero to continue with parsing of this 664 * usage by generic code (no special handling needed) or positive to skip 665 * generic parsing (needed special handling which was done in the hook already) 666 * input_mapped shall return negative to inform the layer that this usage 667 * should not be considered for further processing or zero to notify that 668 * no processing was performed and should be done in a generic manner 669 * Both these functions may be NULL which means the same behavior as returning 670 * zero from them. 671 */ 672 struct hid_driver { 673 char *name; 674 const struct hid_device_id *id_table; 675 676 struct list_head dyn_list; 677 spinlock_t dyn_lock; 678 679 int (*probe)(struct hid_device *dev, const struct hid_device_id *id); 680 void (*remove)(struct hid_device *dev); 681 682 const struct hid_report_id *report_table; 683 int (*raw_event)(struct hid_device *hdev, struct hid_report *report, 684 u8 *data, int size); 685 const struct hid_usage_id *usage_table; 686 int (*event)(struct hid_device *hdev, struct hid_field *field, 687 struct hid_usage *usage, __s32 value); 688 void (*report)(struct hid_device *hdev, struct hid_report *report); 689 690 __u8 *(*report_fixup)(struct hid_device *hdev, __u8 *buf, 691 unsigned int *size); 692 693 int (*input_mapping)(struct hid_device *hdev, 694 struct hid_input *hidinput, struct hid_field *field, 695 struct hid_usage *usage, unsigned long **bit, int *max); 696 int (*input_mapped)(struct hid_device *hdev, 697 struct hid_input *hidinput, struct hid_field *field, 698 struct hid_usage *usage, unsigned long **bit, int *max); 699 void (*input_configured)(struct hid_device *hdev, 700 struct hid_input *hidinput); 701 void (*feature_mapping)(struct hid_device *hdev, 702 struct hid_field *field, 703 struct hid_usage *usage); 704 #ifdef CONFIG_PM 705 int (*suspend)(struct hid_device *hdev, pm_message_t message); 706 int (*resume)(struct hid_device *hdev); 707 int (*reset_resume)(struct hid_device *hdev); 708 #endif 709 /* private: */ 710 struct device_driver driver; 711 }; 712 713 /** 714 * hid_ll_driver - low level driver callbacks 715 * @start: called on probe to start the device 716 * @stop: called on remove 717 * @open: called by input layer on open 718 * @close: called by input layer on close 719 * @parse: this method is called only once to parse the device data, 720 * shouldn't allocate anything to not leak memory 721 * @request: send report request to device (e.g. feature report) 722 * @wait: wait for buffered io to complete (send/recv reports) 723 * @raw_request: send raw report request to device (e.g. feature report) 724 * @output_report: send output report to device 725 * @idle: send idle request to device 726 */ 727 struct hid_ll_driver { 728 int (*start)(struct hid_device *hdev); 729 void (*stop)(struct hid_device *hdev); 730 731 int (*open)(struct hid_device *hdev); 732 void (*close)(struct hid_device *hdev); 733 734 int (*power)(struct hid_device *hdev, int level); 735 736 int (*parse)(struct hid_device *hdev); 737 738 void (*request)(struct hid_device *hdev, 739 struct hid_report *report, int reqtype); 740 741 int (*wait)(struct hid_device *hdev); 742 743 int (*raw_request) (struct hid_device *hdev, unsigned char reportnum, 744 __u8 *buf, size_t len, unsigned char rtype, 745 int reqtype); 746 747 int (*output_report) (struct hid_device *hdev, __u8 *buf, size_t len); 748 749 int (*idle)(struct hid_device *hdev, int report, int idle, int reqtype); 750 }; 751 752 #define PM_HINT_FULLON 1<<5 753 #define PM_HINT_NORMAL 1<<1 754 755 /* Applications from HID Usage Tables 4/8/99 Version 1.1 */ 756 /* We ignore a few input applications that are not widely used */ 757 #define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || (a == 0x00010080) || (a == 0x000c0001) || ((a >= 0x000d0002) && (a <= 0x000d0006))) 758 759 /* HID core API */ 760 761 extern int hid_debug; 762 763 extern bool hid_ignore(struct hid_device *); 764 extern int hid_add_device(struct hid_device *); 765 extern void hid_destroy_device(struct hid_device *); 766 767 extern int __must_check __hid_register_driver(struct hid_driver *, 768 struct module *, const char *mod_name); 769 770 /* use a define to avoid include chaining to get THIS_MODULE & friends */ 771 #define hid_register_driver(driver) \ 772 __hid_register_driver(driver, THIS_MODULE, KBUILD_MODNAME) 773 774 extern void hid_unregister_driver(struct hid_driver *); 775 776 /** 777 * module_hid_driver() - Helper macro for registering a HID driver 778 * @__hid_driver: hid_driver struct 779 * 780 * Helper macro for HID drivers which do not do anything special in module 781 * init/exit. This eliminates a lot of boilerplate. Each module may only 782 * use this macro once, and calling it replaces module_init() and module_exit() 783 */ 784 #define module_hid_driver(__hid_driver) \ 785 module_driver(__hid_driver, hid_register_driver, \ 786 hid_unregister_driver) 787 788 extern void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32); 789 extern void hidinput_report_event(struct hid_device *hid, struct hid_report *report); 790 extern int hidinput_connect(struct hid_device *hid, unsigned int force); 791 extern void hidinput_disconnect(struct hid_device *); 792 793 int hid_set_field(struct hid_field *, unsigned, __s32); 794 int hid_input_report(struct hid_device *, int type, u8 *, int, int); 795 int hidinput_find_field(struct hid_device *hid, unsigned int type, unsigned int code, struct hid_field **field); 796 struct hid_field *hidinput_get_led_field(struct hid_device *hid); 797 unsigned int hidinput_count_leds(struct hid_device *hid); 798 __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code); 799 void hid_output_report(struct hid_report *report, __u8 *data); 800 void __hid_request(struct hid_device *hid, struct hid_report *rep, int reqtype); 801 u8 *hid_alloc_report_buf(struct hid_report *report, gfp_t flags); 802 struct hid_device *hid_allocate_device(void); 803 struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); 804 int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); 805 struct hid_report *hid_validate_values(struct hid_device *hid, 806 unsigned int type, unsigned int id, 807 unsigned int field_index, 808 unsigned int report_counts); 809 int hid_open_report(struct hid_device *device); 810 int hid_check_keys_pressed(struct hid_device *hid); 811 int hid_connect(struct hid_device *hid, unsigned int connect_mask); 812 void hid_disconnect(struct hid_device *hid); 813 const struct hid_device_id *hid_match_id(struct hid_device *hdev, 814 const struct hid_device_id *id); 815 s32 hid_snto32(__u32 value, unsigned n); 816 817 /** 818 * hid_device_io_start - enable HID input during probe, remove 819 * 820 * @hid - the device 821 * 822 * This should only be called during probe or remove and only be 823 * called by the thread calling probe or remove. It will allow 824 * incoming packets to be delivered to the driver. 825 */ 826 static inline void hid_device_io_start(struct hid_device *hid) { 827 if (hid->io_started) { 828 dev_warn(&hid->dev, "io already started"); 829 return; 830 } 831 hid->io_started = true; 832 up(&hid->driver_input_lock); 833 } 834 835 /** 836 * hid_device_io_stop - disable HID input during probe, remove 837 * 838 * @hid - the device 839 * 840 * Should only be called after hid_device_io_start. It will prevent 841 * incoming packets from going to the driver for the duration of 842 * probe, remove. If called during probe, packets will still go to the 843 * driver after probe is complete. This function should only be called 844 * by the thread calling probe or remove. 845 */ 846 static inline void hid_device_io_stop(struct hid_device *hid) { 847 if (!hid->io_started) { 848 dev_warn(&hid->dev, "io already stopped"); 849 return; 850 } 851 hid->io_started = false; 852 down(&hid->driver_input_lock); 853 } 854 855 /** 856 * hid_map_usage - map usage input bits 857 * 858 * @hidinput: hidinput which we are interested in 859 * @usage: usage to fill in 860 * @bit: pointer to input->{}bit (out parameter) 861 * @max: maximal valid usage->code to consider later (out parameter) 862 * @type: input event type (EV_KEY, EV_REL, ...) 863 * @c: code which corresponds to this usage and type 864 */ 865 static inline void hid_map_usage(struct hid_input *hidinput, 866 struct hid_usage *usage, unsigned long **bit, int *max, 867 __u8 type, __u16 c) 868 { 869 struct input_dev *input = hidinput->input; 870 871 usage->type = type; 872 usage->code = c; 873 874 switch (type) { 875 case EV_ABS: 876 *bit = input->absbit; 877 *max = ABS_MAX; 878 break; 879 case EV_REL: 880 *bit = input->relbit; 881 *max = REL_MAX; 882 break; 883 case EV_KEY: 884 *bit = input->keybit; 885 *max = KEY_MAX; 886 break; 887 case EV_LED: 888 *bit = input->ledbit; 889 *max = LED_MAX; 890 break; 891 } 892 } 893 894 /** 895 * hid_map_usage_clear - map usage input bits and clear the input bit 896 * 897 * The same as hid_map_usage, except the @c bit is also cleared in supported 898 * bits (@bit). 899 */ 900 static inline void hid_map_usage_clear(struct hid_input *hidinput, 901 struct hid_usage *usage, unsigned long **bit, int *max, 902 __u8 type, __u16 c) 903 { 904 hid_map_usage(hidinput, usage, bit, max, type, c); 905 clear_bit(c, *bit); 906 } 907 908 /** 909 * hid_parse - parse HW reports 910 * 911 * @hdev: hid device 912 * 913 * Call this from probe after you set up the device (if needed). Your 914 * report_fixup will be called (if non-NULL) after reading raw report from 915 * device before passing it to hid layer for real parsing. 916 */ 917 static inline int __must_check hid_parse(struct hid_device *hdev) 918 { 919 return hid_open_report(hdev); 920 } 921 922 /** 923 * hid_hw_start - start underlaying HW 924 * 925 * @hdev: hid device 926 * @connect_mask: which outputs to connect, see HID_CONNECT_* 927 * 928 * Call this in probe function *after* hid_parse. This will setup HW buffers 929 * and start the device (if not deffered to device open). hid_hw_stop must be 930 * called if this was successful. 931 */ 932 static inline int __must_check hid_hw_start(struct hid_device *hdev, 933 unsigned int connect_mask) 934 { 935 int ret = hdev->ll_driver->start(hdev); 936 if (ret || !connect_mask) 937 return ret; 938 ret = hid_connect(hdev, connect_mask); 939 if (ret) 940 hdev->ll_driver->stop(hdev); 941 return ret; 942 } 943 944 /** 945 * hid_hw_stop - stop underlaying HW 946 * 947 * @hdev: hid device 948 * 949 * This is usually called from remove function or from probe when something 950 * failed and hid_hw_start was called already. 951 */ 952 static inline void hid_hw_stop(struct hid_device *hdev) 953 { 954 hid_disconnect(hdev); 955 hdev->ll_driver->stop(hdev); 956 } 957 958 /** 959 * hid_hw_open - signal underlaying HW to start delivering events 960 * 961 * @hdev: hid device 962 * 963 * Tell underlying HW to start delivering events from the device. 964 * This function should be called sometime after successful call 965 * to hid_hiw_start(). 966 */ 967 static inline int __must_check hid_hw_open(struct hid_device *hdev) 968 { 969 return hdev->ll_driver->open(hdev); 970 } 971 972 /** 973 * hid_hw_close - signal underlaying HW to stop delivering events 974 * 975 * @hdev: hid device 976 * 977 * This function indicates that we are not interested in the events 978 * from this device anymore. Delivery of events may or may not stop, 979 * depending on the number of users still outstanding. 980 */ 981 static inline void hid_hw_close(struct hid_device *hdev) 982 { 983 hdev->ll_driver->close(hdev); 984 } 985 986 /** 987 * hid_hw_power - requests underlying HW to go into given power mode 988 * 989 * @hdev: hid device 990 * @level: requested power level (one of %PM_HINT_* defines) 991 * 992 * This function requests underlying hardware to enter requested power 993 * mode. 994 */ 995 996 static inline int hid_hw_power(struct hid_device *hdev, int level) 997 { 998 return hdev->ll_driver->power ? hdev->ll_driver->power(hdev, level) : 0; 999 } 1000 1001 1002 /** 1003 * hid_hw_request - send report request to device 1004 * 1005 * @hdev: hid device 1006 * @report: report to send 1007 * @reqtype: hid request type 1008 */ 1009 static inline void hid_hw_request(struct hid_device *hdev, 1010 struct hid_report *report, int reqtype) 1011 { 1012 if (hdev->ll_driver->request) 1013 return hdev->ll_driver->request(hdev, report, reqtype); 1014 1015 __hid_request(hdev, report, reqtype); 1016 } 1017 1018 /** 1019 * hid_hw_raw_request - send report request to device 1020 * 1021 * @hdev: hid device 1022 * @reportnum: report ID 1023 * @buf: in/out data to transfer 1024 * @len: length of buf 1025 * @rtype: HID report type 1026 * @reqtype: HID_REQ_GET_REPORT or HID_REQ_SET_REPORT 1027 * 1028 * @return: count of data transfered, negative if error 1029 * 1030 * Same behavior as hid_hw_request, but with raw buffers instead. 1031 */ 1032 static inline int hid_hw_raw_request(struct hid_device *hdev, 1033 unsigned char reportnum, __u8 *buf, 1034 size_t len, unsigned char rtype, int reqtype) 1035 { 1036 if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf) 1037 return -EINVAL; 1038 1039 return hdev->ll_driver->raw_request(hdev, reportnum, buf, len, 1040 rtype, reqtype); 1041 } 1042 1043 /** 1044 * hid_hw_output_report - send output report to device 1045 * 1046 * @hdev: hid device 1047 * @buf: raw data to transfer 1048 * @len: length of buf 1049 * 1050 * @return: count of data transfered, negative if error 1051 */ 1052 static inline int hid_hw_output_report(struct hid_device *hdev, __u8 *buf, 1053 size_t len) 1054 { 1055 if (len < 1 || len > HID_MAX_BUFFER_SIZE || !buf) 1056 return -EINVAL; 1057 1058 if (hdev->ll_driver->output_report) 1059 return hdev->ll_driver->output_report(hdev, buf, len); 1060 1061 return -ENOSYS; 1062 } 1063 1064 /** 1065 * hid_hw_idle - send idle request to device 1066 * 1067 * @hdev: hid device 1068 * @report: report to control 1069 * @idle: idle state 1070 * @reqtype: hid request type 1071 */ 1072 static inline int hid_hw_idle(struct hid_device *hdev, int report, int idle, 1073 int reqtype) 1074 { 1075 if (hdev->ll_driver->idle) 1076 return hdev->ll_driver->idle(hdev, report, idle, reqtype); 1077 1078 return 0; 1079 } 1080 1081 /** 1082 * hid_hw_wait - wait for buffered io to complete 1083 * 1084 * @hdev: hid device 1085 */ 1086 static inline void hid_hw_wait(struct hid_device *hdev) 1087 { 1088 if (hdev->ll_driver->wait) 1089 hdev->ll_driver->wait(hdev); 1090 } 1091 1092 /** 1093 * hid_report_len - calculate the report length 1094 * 1095 * @report: the report we want to know the length 1096 */ 1097 static inline int hid_report_len(struct hid_report *report) 1098 { 1099 /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */ 1100 return ((report->size - 1) >> 3) + 1 + (report->id > 0); 1101 } 1102 1103 int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, 1104 int interrupt); 1105 1106 /* HID quirks API */ 1107 u32 usbhid_lookup_quirk(const u16 idVendor, const u16 idProduct); 1108 int usbhid_quirks_init(char **quirks_param); 1109 void usbhid_quirks_exit(void); 1110 1111 #ifdef CONFIG_HID_PID 1112 int hid_pidff_init(struct hid_device *hid); 1113 #else 1114 #define hid_pidff_init NULL 1115 #endif 1116 1117 #define dbg_hid(format, arg...) \ 1118 do { \ 1119 if (hid_debug) \ 1120 printk(KERN_DEBUG "%s: " format, __FILE__, ##arg); \ 1121 } while (0) 1122 1123 #define hid_printk(level, hid, fmt, arg...) \ 1124 dev_printk(level, &(hid)->dev, fmt, ##arg) 1125 #define hid_emerg(hid, fmt, arg...) \ 1126 dev_emerg(&(hid)->dev, fmt, ##arg) 1127 #define hid_crit(hid, fmt, arg...) \ 1128 dev_crit(&(hid)->dev, fmt, ##arg) 1129 #define hid_alert(hid, fmt, arg...) \ 1130 dev_alert(&(hid)->dev, fmt, ##arg) 1131 #define hid_err(hid, fmt, arg...) \ 1132 dev_err(&(hid)->dev, fmt, ##arg) 1133 #define hid_notice(hid, fmt, arg...) \ 1134 dev_notice(&(hid)->dev, fmt, ##arg) 1135 #define hid_warn(hid, fmt, arg...) \ 1136 dev_warn(&(hid)->dev, fmt, ##arg) 1137 #define hid_info(hid, fmt, arg...) \ 1138 dev_info(&(hid)->dev, fmt, ##arg) 1139 #define hid_dbg(hid, fmt, arg...) \ 1140 dev_dbg(&(hid)->dev, fmt, ##arg) 1141 1142 #endif

Here is an explanation of a rule violation arisen while checking your driver against a corresponding kernel.

Note that it may be false positive, i.e. there isn't a real error indeed. Please analyze a given error trace and related source code to understand whether there is an error in your driver.

Error trace column contains a path on which the given rule is violated. You can expand/collapse some entity classes by clicking on corresponding checkboxes in a main menu or in an advanced Others menu. Also you can expand/collapse each particular entity by clicking on +/-. In hovering on some entities you can see some tips. Also the error trace is bound with related source code. Line numbers may be shown as links on the left. You can click on them to open corresponding lines in source code.

Source code column contains a content of files related with the error trace. There is source code of your driver (note that there are some LDV modifications at the end), kernel headers and rule model. Tabs show a currently opened file and other available files. In hovering on them you can see full file names. On clicking a corresponding file content will be shown.

Kernel Module Rule Verifier Verdict Status Timestamp Bug report
linux-4.0-rc1.tar.xz drivers/hid/hid-lenovo.ko 151_1a BLAST Bug Fixed 2015-05-13 13:33:18 L0196

Comment

Описание ошибки по старой трассе. В функции lenovo_probe_tpkbd в случае, если группа lenovo_attr_group_tpkbd (строка 594) создана, а затем вызов devm_kzalloc на строке 598 выполнился с ошибкой, группа не удаляется.

[Home]