|
| 1 | +/* |
| 2 | + * xpadneo mouse driver |
| 3 | + * |
| 4 | + * Copyright (c) 2021 Kai Krakow <[email protected]> |
| 5 | + */ |
| 6 | + |
| 7 | +#include "../xpadneo.h" |
| 8 | + |
| 9 | +extern void xpadneo_toggle_mouse(struct xpadneo_devdata *xdata) |
| 10 | +{ |
| 11 | + if (!xdata->mouse) { |
| 12 | + xdata->mouse_mode = false; |
| 13 | + hid_info(xdata->hdev, "mouse not available\n"); |
| 14 | + } else if (xdata->mouse_mode) { |
| 15 | + xdata->mouse_mode = false; |
| 16 | + hid_info(xdata->hdev, "mouse mode disabled\n"); |
| 17 | + } else { |
| 18 | + xdata->mouse_mode = true; |
| 19 | + hid_info(xdata->hdev, "mouse mode enabled\n"); |
| 20 | + } |
| 21 | + |
| 22 | + /* Indicate that a request was made */ |
| 23 | + xdata->profile_switched = true; |
| 24 | +} |
| 25 | + |
| 26 | +#define mouse_report_rel(a,v) if((v)!=0)input_report_rel(mouse,a,v) |
| 27 | +extern void xpadneo_mouse_report(struct timer_list *t) |
| 28 | +{ |
| 29 | + struct xpadneo_devdata *xdata = from_timer(xdata, t, mouse_timer); |
| 30 | + struct input_dev *mouse = xdata->mouse; |
| 31 | + |
| 32 | + mod_timer(&xdata->mouse_timer, jiffies + msecs_to_jiffies(10)); |
| 33 | + |
| 34 | + if (xdata->mouse_mode) { |
| 35 | + mouse_report_rel(REL_X, xdata->mouse_state.rel_x); |
| 36 | + mouse_report_rel(REL_Y, xdata->mouse_state.rel_y); |
| 37 | + mouse_report_rel(REL_HWHEEL, xdata->mouse_state.wheel_x); |
| 38 | + mouse_report_rel(REL_WHEEL, xdata->mouse_state.wheel_y); |
| 39 | + input_sync(xdata->mouse); |
| 40 | + } |
| 41 | + |
| 42 | +} |
| 43 | + |
| 44 | +#define rescale_axis(v,d) (((v)<(d)&&(v)>-(d))?0:(32768*((v)>0?(v)-(d):(v)+(d))/(32768-(d)))) |
| 45 | +extern int xpadneo_mouse_event(struct xpadneo_devdata *xdata, struct hid_usage *usage, __s32 value) |
| 46 | +{ |
| 47 | + if (!xdata->mouse_mode) |
| 48 | + return 0; |
| 49 | + |
| 50 | + if (usage->type == EV_ABS) { |
| 51 | + switch (usage->code) { |
| 52 | + case ABS_X: |
| 53 | + xdata->mouse_state.rel_x = rescale_axis(value - 32768, 3072) / 2048; |
| 54 | + return 1; |
| 55 | + case ABS_Y: |
| 56 | + xdata->mouse_state.rel_y = rescale_axis(value - 32768, 3072) / 2048; |
| 57 | + return 1; |
| 58 | + case ABS_RX: |
| 59 | + xdata->mouse_state.wheel_x = rescale_axis(value - 32768, 3072) / 8192; |
| 60 | + return 1; |
| 61 | + case ABS_RY: |
| 62 | + xdata->mouse_state.wheel_y = rescale_axis(value - 32768, 3072) / 8192; |
| 63 | + return 1; |
| 64 | + case ABS_Z: |
| 65 | + if (xdata->mouse_state.analog_button.left && value < 384) { |
| 66 | + xdata->mouse_state.analog_button.left = false; |
| 67 | + input_report_key(xdata->mouse, BTN_LEFT, 0); |
| 68 | + input_sync(xdata->mouse); |
| 69 | + } else if (!xdata->mouse_state.analog_button.left && value > 640) { |
| 70 | + xdata->mouse_state.analog_button.left = true; |
| 71 | + input_report_key(xdata->mouse, BTN_LEFT, 1); |
| 72 | + input_sync(xdata->mouse); |
| 73 | + } |
| 74 | + return 1; |
| 75 | + case ABS_RZ: |
| 76 | + if (xdata->mouse_state.analog_button.right && value < 384) { |
| 77 | + xdata->mouse_state.analog_button.right = false; |
| 78 | + input_report_key(xdata->mouse, BTN_RIGHT, 0); |
| 79 | + input_sync(xdata->mouse); |
| 80 | + } else if (!xdata->mouse_state.analog_button.right && value > 640) { |
| 81 | + xdata->mouse_state.analog_button.right = true; |
| 82 | + input_report_key(xdata->mouse, BTN_RIGHT, 1); |
| 83 | + input_sync(xdata->mouse); |
| 84 | + } |
| 85 | + return 1; |
| 86 | + } |
| 87 | + } else if (usage->type == EV_KEY) { |
| 88 | + switch (usage->code) { |
| 89 | + case BTN_TL: |
| 90 | + input_report_key(xdata->mouse, BTN_SIDE, value); |
| 91 | + input_sync(xdata->mouse); |
| 92 | + return 1; |
| 93 | + case BTN_TR: |
| 94 | + input_report_key(xdata->mouse, BTN_EXTRA, value); |
| 95 | + input_sync(xdata->mouse); |
| 96 | + return 1; |
| 97 | + case BTN_START: |
| 98 | + if (xdata->consumer) { |
| 99 | + input_report_key(xdata->consumer, KEY_KEYBOARD, value); |
| 100 | + input_sync(xdata->consumer); |
| 101 | + } |
| 102 | + return 1; |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + return 0; |
| 107 | +} |
| 108 | + |
| 109 | +extern int xpadneo_init_mouse(struct xpadneo_devdata *xdata) |
| 110 | +{ |
| 111 | + struct hid_device *hdev = xdata->hdev; |
| 112 | + int ret, synth = 0; |
| 113 | + |
| 114 | + if (!xdata->mouse) { |
| 115 | + synth = 1; |
| 116 | + ret = xpadneo_init_synthetic(xdata, "Mouse", &xdata->mouse); |
| 117 | + if (ret || !xdata->mouse) |
| 118 | + return ret; |
| 119 | + } |
| 120 | + |
| 121 | + /* enable relative events for mouse emulation */ |
| 122 | + __set_bit(EV_REL, xdata->mouse->evbit); |
| 123 | + __set_bit(REL_X, xdata->mouse->relbit); |
| 124 | + __set_bit(REL_Y, xdata->mouse->relbit); |
| 125 | + __set_bit(REL_HWHEEL, xdata->mouse->relbit); |
| 126 | + __set_bit(REL_WHEEL, xdata->mouse->relbit); |
| 127 | + |
| 128 | + /* enable button events for mouse emulation */ |
| 129 | + __set_bit(EV_KEY, xdata->mouse->evbit); |
| 130 | + __set_bit(BTN_LEFT, xdata->mouse->keybit); |
| 131 | + __set_bit(BTN_RIGHT, xdata->mouse->keybit); |
| 132 | + __set_bit(BTN_MIDDLE, xdata->mouse->keybit); |
| 133 | + __set_bit(BTN_SIDE, xdata->mouse->keybit); |
| 134 | + __set_bit(BTN_EXTRA, xdata->mouse->keybit); |
| 135 | + __set_bit(BTN_FORWARD, xdata->mouse->keybit); |
| 136 | + __set_bit(BTN_BACK, xdata->mouse->keybit); |
| 137 | + __set_bit(BTN_TASK, xdata->mouse->keybit); |
| 138 | + |
| 139 | + if (synth) { |
| 140 | + ret = input_register_device(xdata->mouse); |
| 141 | + if (ret) { |
| 142 | + hid_err(hdev, "failed to register mouse\n"); |
| 143 | + return ret; |
| 144 | + } |
| 145 | + |
| 146 | + hid_info(hdev, "mouse added\n"); |
| 147 | + } |
| 148 | + |
| 149 | + return 0; |
| 150 | +} |
0 commit comments