diff options
Diffstat (limited to 'drivers/hid/hid-input.c')
| -rw-r--r-- | drivers/hid/hid-input.c | 101 | 
1 files changed, 96 insertions, 5 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index a19b65ed311..7f817897b17 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -240,11 +240,94 @@ static inline void hidinput_pb_setup(struct input_dev *input)  }  #endif +static inline int match_scancode(int code, int scancode) +{ +	if (scancode == 0) +		return 1; +	return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode); +} + +static inline int match_keycode(int code, int keycode) +{ +	if (keycode == 0) +		return 1; +	return (code == keycode); +} + +static struct hid_usage *hidinput_find_key(struct hid_device *hid, +		int scancode, int keycode) +{ +	int i, j, k; +	struct hid_report *report; +	struct hid_usage *usage; + +	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { +		list_for_each_entry(report, &hid->report_enum[k].report_list, list) { +			for (i = 0; i < report->maxfield; i++) { +				for ( j = 0; j < report->field[i]->maxusage; j++) { +					usage = report->field[i]->usage + j; +					if (usage->type == EV_KEY && +						match_scancode(usage->hid, scancode) && +						match_keycode(usage->code, keycode)) +						return usage; +				} +			} +		} +	} +	return NULL; +} + +static int hidinput_getkeycode(struct input_dev *dev, int scancode, +				int *keycode) +{ +	struct hid_device *hid = dev->private; +	struct hid_usage *usage; +	 +	usage = hidinput_find_key(hid, scancode, 0); +	if (usage) { +		*keycode = usage->code; +		return 0; +	} +	return -EINVAL; +} + +static int hidinput_setkeycode(struct input_dev *dev, int scancode, +				int keycode) +{ +	struct hid_device *hid = dev->private; +	struct hid_usage *usage; +	int old_keycode; +	 +	if (keycode < 0 || keycode > KEY_MAX) +		return -EINVAL; +	 +	usage = hidinput_find_key(hid, scancode, 0); +	if (usage) { +		old_keycode = usage->code; +		usage->code = keycode; +		 +		clear_bit(old_keycode, dev->keybit); +		set_bit(usage->code, dev->keybit); +#ifdef CONFIG_HID_DEBUG +		printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); +#endif +		/* Set the keybit for the old keycode if the old keycode is used +		 * by another key */ +		if (hidinput_find_key (hid, 0, old_keycode)) +			set_bit(old_keycode, dev->keybit); +		 +		return 0; +	} +	 +	return -EINVAL; +} + +  static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,  				     struct hid_usage *usage)  {  	struct input_dev *input = hidinput->input; -	struct hid_device *device = input->private; +	struct hid_device *device = input_get_drvdata(input);  	int max = 0, code;  	unsigned long *bit = NULL; @@ -553,6 +636,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel  				case 0x1015: map_key_clear(KEY_RECORD);		break;  				case 0x1016: map_key_clear(KEY_PLAYER);		break;  				case 0x1017: map_key_clear(KEY_EJECTCD);	break; +				case 0x1018: map_key_clear(KEY_MEDIA);          break;  				case 0x1019: map_key_clear(KEY_PROG1);		break;  				case 0x101a: map_key_clear(KEY_PROG2);		break;  				case 0x101b: map_key_clear(KEY_PROG3);		break; @@ -560,9 +644,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel  				case 0x1020: map_key_clear(KEY_ZOOMOUT);	break;  				case 0x1021: map_key_clear(KEY_ZOOMRESET);	break;  				case 0x1023: map_key_clear(KEY_CLOSE);		break; +				case 0x1027: map_key_clear(KEY_MENU);           break;  				/* this one is marked as 'Rotate' */  				case 0x1028: map_key_clear(KEY_ANGLE);		break;  				case 0x1029: map_key_clear(KEY_SHUFFLE);	break; +				case 0x102a: map_key_clear(KEY_BACK);           break; +				case 0x102b: map_key_clear(KEY_CYCLEWINDOWS);   break;  				case 0x1041: map_key_clear(KEY_BATTERY);	break;  				case 0x1042: map_key_clear(KEY_WORDPROCESSOR);	break;  				case 0x1043: map_key_clear(KEY_SPREADSHEET);	break; @@ -855,13 +942,15 @@ EXPORT_SYMBOL_GPL(hidinput_find_field);  static int hidinput_open(struct input_dev *dev)  { -	struct hid_device *hid = dev->private; +	struct hid_device *hid = input_get_drvdata(dev); +  	return hid->hid_open(hid);  }  static void hidinput_close(struct input_dev *dev)  { -	struct hid_device *hid = dev->private; +	struct hid_device *hid = input_get_drvdata(dev); +  	hid->hid_close(hid);  } @@ -909,10 +998,12 @@ int hidinput_connect(struct hid_device *hid)  					return -1;  				} -				input_dev->private = hid; +				input_set_drvdata(input_dev, hid);  				input_dev->event = hid->hidinput_input_event;  				input_dev->open = hidinput_open;  				input_dev->close = hidinput_close; +				input_dev->setkeycode = hidinput_setkeycode; +				input_dev->getkeycode = hidinput_getkeycode;  				input_dev->name = hid->name;  				input_dev->phys = hid->phys; @@ -921,7 +1012,7 @@ int hidinput_connect(struct hid_device *hid)  				input_dev->id.vendor  = hid->vendor;  				input_dev->id.product = hid->product;  				input_dev->id.version = hid->version; -				input_dev->cdev.dev = hid->dev; +				input_dev->dev.parent = hid->dev;  				hidinput->input = input_dev;  				list_add_tail(&hidinput->list, &hid->inputs);  			}  | 
