Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
remote.c
Go to the documentation of this file.
1 /*
2  * IBM ASM Service Processor Device Driver
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  *
18  * Copyright (C) IBM Corporation, 2004
19  *
20  * Authors: Max Asböck <[email protected]>
21  * Vernon Mauery <[email protected]>
22  *
23  */
24 
25 /* Remote mouse and keyboard event handling functions */
26 
27 #include <linux/pci.h>
28 #include "ibmasm.h"
29 #include "remote.h"
30 
31 #define MOUSE_X_MAX 1600
32 #define MOUSE_Y_MAX 1200
33 
34 static const unsigned short xlate_high[XLATE_SIZE] = {
35  [KEY_SYM_ENTER & 0xff] = KEY_ENTER,
36  [KEY_SYM_KPSLASH & 0xff] = KEY_KPSLASH,
37  [KEY_SYM_KPSTAR & 0xff] = KEY_KPASTERISK,
38  [KEY_SYM_KPMINUS & 0xff] = KEY_KPMINUS,
39  [KEY_SYM_KPDOT & 0xff] = KEY_KPDOT,
40  [KEY_SYM_KPPLUS & 0xff] = KEY_KPPLUS,
41  [KEY_SYM_KP0 & 0xff] = KEY_KP0,
42  [KEY_SYM_KP1 & 0xff] = KEY_KP1,
43  [KEY_SYM_KP2 & 0xff] = KEY_KP2, [KEY_SYM_KPDOWN & 0xff] = KEY_KP2,
44  [KEY_SYM_KP3 & 0xff] = KEY_KP3,
45  [KEY_SYM_KP4 & 0xff] = KEY_KP4, [KEY_SYM_KPLEFT & 0xff] = KEY_KP4,
46  [KEY_SYM_KP5 & 0xff] = KEY_KP5,
47  [KEY_SYM_KP6 & 0xff] = KEY_KP6, [KEY_SYM_KPRIGHT & 0xff] = KEY_KP6,
48  [KEY_SYM_KP7 & 0xff] = KEY_KP7,
49  [KEY_SYM_KP8 & 0xff] = KEY_KP8, [KEY_SYM_KPUP & 0xff] = KEY_KP8,
50  [KEY_SYM_KP9 & 0xff] = KEY_KP9,
51  [KEY_SYM_BK_SPC & 0xff] = KEY_BACKSPACE,
52  [KEY_SYM_TAB & 0xff] = KEY_TAB,
53  [KEY_SYM_CTRL & 0xff] = KEY_LEFTCTRL,
54  [KEY_SYM_ALT & 0xff] = KEY_LEFTALT,
55  [KEY_SYM_INSERT & 0xff] = KEY_INSERT,
56  [KEY_SYM_DELETE & 0xff] = KEY_DELETE,
57  [KEY_SYM_SHIFT & 0xff] = KEY_LEFTSHIFT,
58  [KEY_SYM_UARROW & 0xff] = KEY_UP,
59  [KEY_SYM_DARROW & 0xff] = KEY_DOWN,
60  [KEY_SYM_LARROW & 0xff] = KEY_LEFT,
61  [KEY_SYM_RARROW & 0xff] = KEY_RIGHT,
62  [KEY_SYM_ESCAPE & 0xff] = KEY_ESC,
63  [KEY_SYM_PAGEUP & 0xff] = KEY_PAGEUP,
64  [KEY_SYM_PAGEDOWN & 0xff] = KEY_PAGEDOWN,
65  [KEY_SYM_HOME & 0xff] = KEY_HOME,
66  [KEY_SYM_END & 0xff] = KEY_END,
67  [KEY_SYM_F1 & 0xff] = KEY_F1,
68  [KEY_SYM_F2 & 0xff] = KEY_F2,
69  [KEY_SYM_F3 & 0xff] = KEY_F3,
70  [KEY_SYM_F4 & 0xff] = KEY_F4,
71  [KEY_SYM_F5 & 0xff] = KEY_F5,
72  [KEY_SYM_F6 & 0xff] = KEY_F6,
73  [KEY_SYM_F7 & 0xff] = KEY_F7,
74  [KEY_SYM_F8 & 0xff] = KEY_F8,
75  [KEY_SYM_F9 & 0xff] = KEY_F9,
76  [KEY_SYM_F10 & 0xff] = KEY_F10,
77  [KEY_SYM_F11 & 0xff] = KEY_F11,
78  [KEY_SYM_F12 & 0xff] = KEY_F12,
79  [KEY_SYM_CAP_LOCK & 0xff] = KEY_CAPSLOCK,
80  [KEY_SYM_NUM_LOCK & 0xff] = KEY_NUMLOCK,
82 };
83 
84 static const unsigned short xlate[XLATE_SIZE] = {
108  [KEY_SYM_A] = KEY_A, [KEY_SYM_a] = KEY_A,
109  [KEY_SYM_B] = KEY_B, [KEY_SYM_b] = KEY_B,
110  [KEY_SYM_C] = KEY_C, [KEY_SYM_c] = KEY_C,
111  [KEY_SYM_D] = KEY_D, [KEY_SYM_d] = KEY_D,
112  [KEY_SYM_E] = KEY_E, [KEY_SYM_e] = KEY_E,
113  [KEY_SYM_F] = KEY_F, [KEY_SYM_f] = KEY_F,
114  [KEY_SYM_G] = KEY_G, [KEY_SYM_g] = KEY_G,
115  [KEY_SYM_H] = KEY_H, [KEY_SYM_h] = KEY_H,
116  [KEY_SYM_I] = KEY_I, [KEY_SYM_i] = KEY_I,
117  [KEY_SYM_J] = KEY_J, [KEY_SYM_j] = KEY_J,
118  [KEY_SYM_K] = KEY_K, [KEY_SYM_k] = KEY_K,
119  [KEY_SYM_L] = KEY_L, [KEY_SYM_l] = KEY_L,
120  [KEY_SYM_M] = KEY_M, [KEY_SYM_m] = KEY_M,
121  [KEY_SYM_N] = KEY_N, [KEY_SYM_n] = KEY_N,
122  [KEY_SYM_O] = KEY_O, [KEY_SYM_o] = KEY_O,
123  [KEY_SYM_P] = KEY_P, [KEY_SYM_p] = KEY_P,
124  [KEY_SYM_Q] = KEY_Q, [KEY_SYM_q] = KEY_Q,
125  [KEY_SYM_R] = KEY_R, [KEY_SYM_r] = KEY_R,
126  [KEY_SYM_S] = KEY_S, [KEY_SYM_s] = KEY_S,
127  [KEY_SYM_T] = KEY_T, [KEY_SYM_t] = KEY_T,
128  [KEY_SYM_U] = KEY_U, [KEY_SYM_u] = KEY_U,
129  [KEY_SYM_V] = KEY_V, [KEY_SYM_v] = KEY_V,
130  [KEY_SYM_W] = KEY_W, [KEY_SYM_w] = KEY_W,
131  [KEY_SYM_X] = KEY_X, [KEY_SYM_x] = KEY_X,
132  [KEY_SYM_Y] = KEY_Y, [KEY_SYM_y] = KEY_Y,
133  [KEY_SYM_Z] = KEY_Z, [KEY_SYM_z] = KEY_Z,
134 };
135 
136 static void print_input(struct remote_input *input)
137 {
138  if (input->type == INPUT_TYPE_MOUSE) {
139  unsigned char buttons = input->mouse_buttons;
140  dbg("remote mouse movement: (x,y)=(%d,%d)%s%s%s%s\n",
141  input->data.mouse.x, input->data.mouse.y,
142  (buttons) ? " -- buttons:" : "",
143  (buttons & REMOTE_BUTTON_LEFT) ? "left " : "",
144  (buttons & REMOTE_BUTTON_MIDDLE) ? "middle " : "",
145  (buttons & REMOTE_BUTTON_RIGHT) ? "right" : ""
146  );
147  } else {
148  dbg("remote keypress (code, flag, down):"
149  "%d (0x%x) [0x%x] [0x%x]\n",
150  input->data.keyboard.key_code,
151  input->data.keyboard.key_code,
152  input->data.keyboard.key_flag,
153  input->data.keyboard.key_down
154  );
155  }
156 }
157 
158 static void send_mouse_event(struct input_dev *dev, struct remote_input *input)
159 {
160  unsigned char buttons = input->mouse_buttons;
161 
162  input_report_abs(dev, ABS_X, input->data.mouse.x);
163  input_report_abs(dev, ABS_Y, input->data.mouse.y);
164  input_report_key(dev, BTN_LEFT, buttons & REMOTE_BUTTON_LEFT);
165  input_report_key(dev, BTN_MIDDLE, buttons & REMOTE_BUTTON_MIDDLE);
166  input_report_key(dev, BTN_RIGHT, buttons & REMOTE_BUTTON_RIGHT);
167  input_sync(dev);
168 }
169 
170 static void send_keyboard_event(struct input_dev *dev,
171  struct remote_input *input)
172 {
173  unsigned int key;
174  unsigned short code = input->data.keyboard.key_code;
175 
176  if (code & 0xff00)
177  key = xlate_high[code & 0xff];
178  else
179  key = xlate[code];
180  input_report_key(dev, key, input->data.keyboard.key_down);
181  input_sync(dev);
182 }
183 
185 {
186  unsigned long reader;
187  unsigned long writer;
188  struct remote_input input;
189 
190  reader = get_queue_reader(sp);
191  writer = get_queue_writer(sp);
192 
193  while (reader != writer) {
194  memcpy_fromio(&input, get_queue_entry(sp, reader),
195  sizeof(struct remote_input));
196 
197  print_input(&input);
198  if (input.type == INPUT_TYPE_MOUSE) {
199  send_mouse_event(sp->remote.mouse_dev, &input);
200  } else if (input.type == INPUT_TYPE_KEYBOARD) {
201  send_keyboard_event(sp->remote.keybd_dev, &input);
202  } else
203  break;
204 
205  reader = advance_queue_reader(sp, reader);
206  writer = get_queue_writer(sp);
207  }
208 }
209 
211 {
212  /* set up the mouse input device */
213  struct input_dev *mouse_dev, *keybd_dev;
214  struct pci_dev *pdev = to_pci_dev(sp->dev);
215  int error = -ENOMEM;
216  int i;
217 
218  sp->remote.mouse_dev = mouse_dev = input_allocate_device();
219  sp->remote.keybd_dev = keybd_dev = input_allocate_device();
220 
221  if (!mouse_dev || !keybd_dev)
222  goto err_free_devices;
223 
224  mouse_dev->id.bustype = BUS_PCI;
225  mouse_dev->id.vendor = pdev->vendor;
226  mouse_dev->id.product = pdev->device;
227  mouse_dev->id.version = 1;
228  mouse_dev->dev.parent = sp->dev;
229  mouse_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
230  mouse_dev->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
232  set_bit(BTN_TOUCH, mouse_dev->keybit);
233  mouse_dev->name = "ibmasm RSA I remote mouse";
234  input_set_abs_params(mouse_dev, ABS_X, 0, MOUSE_X_MAX, 0, 0);
235  input_set_abs_params(mouse_dev, ABS_Y, 0, MOUSE_Y_MAX, 0, 0);
236 
237  keybd_dev->id.bustype = BUS_PCI;
238  keybd_dev->id.vendor = pdev->vendor;
239  keybd_dev->id.product = pdev->device;
240  keybd_dev->id.version = 2;
241  keybd_dev->dev.parent = sp->dev;
242  keybd_dev->evbit[0] = BIT_MASK(EV_KEY);
243  keybd_dev->name = "ibmasm RSA I remote keyboard";
244 
245  for (i = 0; i < XLATE_SIZE; i++) {
246  if (xlate_high[i])
247  set_bit(xlate_high[i], keybd_dev->keybit);
248  if (xlate[i])
249  set_bit(xlate[i], keybd_dev->keybit);
250  }
251 
252  error = input_register_device(mouse_dev);
253  if (error)
254  goto err_free_devices;
255 
256  error = input_register_device(keybd_dev);
257  if (error)
258  goto err_unregister_mouse_dev;
259 
261 
262  printk(KERN_INFO "ibmasm remote responding to events on RSA card %d\n", sp->number);
263 
264  return 0;
265 
266  err_unregister_mouse_dev:
267  input_unregister_device(mouse_dev);
268  mouse_dev = NULL; /* so we don't try to free it again below */
269  err_free_devices:
270  input_free_device(mouse_dev);
271  input_free_device(keybd_dev);
272 
273  return error;
274 }
275 
277 {
279  input_unregister_device(sp->remote.mouse_dev);
280  input_unregister_device(sp->remote.keybd_dev);
281 }
282