sunmouse.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:14k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* sunmouse.c: Sun mouse driver for the Sparc
  2.  *
  3.  * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu)
  4.  * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
  5.  *
  6.  * Parts based on the psaux.c driver written by:
  7.  * Johan Myreen.
  8.  *
  9.  * Dec/19/95 Added SunOS mouse ioctls - miguel.
  10.  * Jan/5/96  Added VUID support, sigio support - miguel.
  11.  * Mar/5/96  Added proper mouse stream support - miguel.
  12.  * Sep/96    Allow more than one reader -miguel.
  13.  * Aug/97    Added PCI 8042 controller support -DaveM
  14.  */
  15. /* The mouse is run off of one of the Zilog serial ports.  On
  16.  * that port is the mouse and the keyboard, each gets a zs channel.
  17.  * The mouse itself is mouse-systems in nature.  So the protocol is:
  18.  *
  19.  * Byte 1) Button state which is bit-encoded as
  20.  *            0x4 == left-button down, else up
  21.  *            0x2 == middle-button down, else up
  22.  *            0x1 == right-button down, else up
  23.  *
  24.  * Byte 2) Delta-x
  25.  * Byte 3) Delta-y
  26.  * Byte 4) Delta-x again
  27.  * Byte 5) Delta-y again
  28.  *
  29.  * One day this driver will have to support more than one mouse in the system.
  30.  *
  31.  * This driver has two modes of operation: the default VUID_NATIVE is
  32.  * set when the device is opened and allows the application to see the
  33.  * mouse character stream as we get it from the serial (for gpm for
  34.  * example).  The second method, VUID_FIRM_EVENT will provide cooked
  35.  * events in Firm_event records as expected by SunOS/Solaris applications.
  36.  *
  37.  * FIXME: We need to support more than one mouse.
  38.  * */
  39. #include <linux/config.h>
  40. #include <linux/kernel.h>
  41. #include <linux/sched.h>
  42. #include <linux/fcntl.h>
  43. #include <linux/signal.h>
  44. #include <linux/timer.h>
  45. #include <linux/errno.h>
  46. #include <linux/miscdevice.h>
  47. #include <linux/mm.h>
  48. #include <linux/poll.h>
  49. #include <linux/spinlock.h>
  50. #include <linux/smp_lock.h>
  51. #include <linux/init.h>
  52. #include <asm/uaccess.h>
  53. #include <asm/system.h>
  54. #include <asm/vuid_event.h>
  55. #include <linux/random.h>
  56. /* The following keeps track of software state for the Sun
  57.  * mouse.
  58.  */
  59. #define STREAM_SIZE   2048
  60. #define EV_SIZE       (STREAM_SIZE/sizeof (Firm_event))
  61. #define BUTTON_LEFT   4
  62. #define BUTTON_MIDDLE 2
  63. #define BUTTON_RIGHT  1
  64. struct sun_mouse {
  65. unsigned char transaction[5];  /* Each protocol transaction */
  66. unsigned char byte;            /* Counter, starts at 0 */
  67. unsigned char button_state;    /* Current button state */
  68. unsigned char prev_state;      /* Previous button state */
  69. int delta_x;                   /* Current delta-x */
  70. int delta_y;                   /* Current delta-y */
  71. int active;        /* set if device is open */
  72.         int vuid_mode;                /* VUID_NATIVE or VUID_FIRM_EVENT */
  73. wait_queue_head_t proc_list;
  74. struct fasync_struct *fasync;
  75. /* The event/stream queue */
  76. spinlock_t lock;
  77. unsigned int head;
  78. unsigned int tail;
  79. union {
  80. char stream [STREAM_SIZE];
  81. Firm_event ev [EV_SIZE];
  82. } queue;
  83. };
  84. static struct sun_mouse sunmouse;
  85. #define gen_events (sunmouse.vuid_mode != VUID_NATIVE)
  86. #define bstate sunmouse.button_state
  87. #define pstate sunmouse.prev_state
  88. extern void mouse_put_char(char ch);
  89. #undef SMOUSE_DEBUG
  90. static int
  91. push_event (Firm_event *ev)
  92. {
  93. unsigned long flags;
  94. int next, ret;
  95. spin_lock_irqsave(&sunmouse.lock, flags);
  96. next = (sunmouse.head + 1) % EV_SIZE;
  97. ret = 0;
  98. if (next != sunmouse.tail) {
  99. sunmouse.queue.ev [sunmouse.head] = *ev;
  100. sunmouse.head = next;
  101. ret = 1;
  102. }
  103. spin_unlock_irqrestore(&sunmouse.lock, flags);
  104. return ret;
  105. }
  106. static int
  107. queue_empty (void)
  108. {
  109. return sunmouse.head == sunmouse.tail;
  110. }
  111. /* Must be invoked under the sunmouse.lock */
  112. static void get_from_queue (Firm_event *p)
  113. {
  114. *p = sunmouse.queue.ev [sunmouse.tail];
  115. sunmouse.tail = (sunmouse.tail + 1) % EV_SIZE;
  116. }
  117. static void
  118. push_char (char c)
  119. {
  120. unsigned long flags;
  121. int next;
  122. spin_lock_irqsave(&sunmouse.lock, flags);
  123. next = (sunmouse.head + 1) % STREAM_SIZE;
  124. if (next != sunmouse.tail) {
  125. #ifdef SMOUSE_DEBUG
  126. printk("P<%02x>n", (unsigned char)c);
  127. #endif
  128. sunmouse.queue.stream [sunmouse.head] = c;
  129. sunmouse.head = next;
  130. }
  131. spin_unlock_irqrestore(&sunmouse.lock, flags);
  132. kill_fasync (&sunmouse.fasync, SIGIO, POLL_IN);
  133. wake_up_interruptible (&sunmouse.proc_list);
  134. }
  135. /* Auto baud rate "detection".  ;-) */
  136. static int mouse_baud = 4800; /* Initial rate set by zilog driver. */
  137. /* Change the baud rate after receiving too many "bogon bytes". */
  138. void sun_mouse_change_baud(void)
  139. {
  140. extern void rs_change_mouse_baud(int newbaud);
  141. if(mouse_baud == 1200)
  142. mouse_baud = 2400;
  143. else if(mouse_baud == 2400)
  144. mouse_baud = 4800;
  145. else if(mouse_baud == 4800)
  146. mouse_baud = 9600;
  147. else
  148. mouse_baud = 1200;
  149. rs_change_mouse_baud(mouse_baud);
  150. }
  151. /* This tries to monitor the mouse state so that it
  152.  * can automatically adjust to the correct baud rate.
  153.  * The mouse spits out BRKs when the baud rate is
  154.  * incorrect.
  155.  *
  156.  * It returns non-zero if we should ignore this byte.
  157.  */
  158. int mouse_baud_detection(unsigned char c, int is_break)
  159. {
  160. static int mouse_got_break = 0;
  161. static int ctr = 0;
  162. if (is_break) {
  163. /* Let a few normal bytes go by before
  164.  * we jump the gun and say we need to
  165.  * try another baud rate.
  166.  */
  167. if (mouse_got_break && ctr < 8)
  168. return 1;
  169. /* OK, we need to try another baud rate. */
  170. sun_mouse_change_baud();
  171. ctr = 0;
  172. mouse_got_break = 1;
  173. return 1;
  174. }
  175. if (mouse_got_break) {
  176. ctr++;
  177. if (c == 0x87) {
  178. printk(KERN_INFO "sunmouse: Successfully "
  179.        "adjusted to %d baud.n", mouse_baud);
  180. mouse_got_break = 0;
  181. }
  182. return 1;
  183. }
  184. return 0;
  185. }
  186. /* You ask me, why does this cap the lower bound at -127 and not
  187.  * -128?  Because the xf86 mouse code is crap and treats -128
  188.  * as an illegal value and resets it's protocol state machine
  189.  * when it sees this value.
  190.  */
  191. #define CLIP(__X) (((__X) > 127) ? 127 : (((__X) < -127) ? -127 : (__X)))
  192. /* The following is called from the serial driver when bytes/breaks
  193.  * are received on the Mouse line.
  194.  */
  195. void
  196. sun_mouse_inbyte(unsigned char byte, int is_break)
  197. {
  198. signed char mvalue;
  199. int d, pushed = 0;
  200. Firm_event ev;
  201. add_mouse_randomness (byte);
  202. #if 0
  203. {
  204. static int xxx = 0;
  205. printk("mouse(%02x:%d) ",
  206.        byte, is_break);
  207. if (byte == 0x87) {
  208. xxx = 0;
  209. printk("n");
  210. }
  211. }
  212. #endif
  213. if (mouse_baud_detection(byte, is_break))
  214. return;
  215. if(!sunmouse.active)
  216. return;
  217. /* Ignore this if it is garbage. */
  218. if (sunmouse.byte == 69) {
  219. if (byte != 0x87)
  220. return;
  221. /* Ok, we've begun the state machine. */
  222. sunmouse.byte = 0;
  223. }
  224. #if 0
  225. /* If the mouse sends us a byte from 0x80 to 0x87
  226.  * we are starting at byte zero in the transaction
  227.  * protocol.
  228.  */
  229. if((byte & ~0x0f) == 0x80) 
  230. sunmouse.byte = 0;
  231. #endif
  232. mvalue = (signed char) byte;
  233. switch(sunmouse.byte) {
  234. case 0:
  235. /* If we get a bogus button byte, just skip it.
  236.  * When we get here the baud detection code has
  237.  * passed, so the only other things which can
  238.  * cause this are dropped serial characters and
  239.  * confused mouse.  We check this because otherwise
  240.  * begin posting erroneous mouse events.
  241.  */
  242. if ((byte & 0xf0) != 0x80)
  243. return;
  244. /* Button state */
  245. sunmouse.button_state = (~byte) & 0x7;
  246. #ifdef SMOUSE_DEBUG
  247. printk("B<Left %s, Middle %s, Right %s>",
  248.        ((sunmouse.button_state & 0x4) ? "DOWN" : "UP"),
  249.        ((sunmouse.button_state & 0x2) ? "DOWN" : "UP"),
  250.        ((sunmouse.button_state & 0x1) ? "DOWN" : "UP"));
  251. #endif
  252. /* To deal with the Sparcbook 3 */
  253. if (byte & 0x8) {
  254. sunmouse.byte += 2;
  255. sunmouse.delta_y = 0;
  256. sunmouse.delta_x = 0;
  257. }
  258. sunmouse.byte++;
  259. return;
  260. case 1:
  261. /* Delta-x 1 */
  262. #ifdef SMOUSE_DEBUG
  263. printk("DX1<%d>", mvalue);
  264. #endif
  265. sunmouse.delta_x = mvalue;
  266. sunmouse.byte++;
  267. return;
  268. case 2:
  269. /* Delta-y 1 */
  270. #ifdef SMOUSE_DEBUG
  271. printk("DY1<%d>", mvalue);
  272. #endif
  273. sunmouse.delta_y = mvalue;
  274. sunmouse.byte++;
  275. return;
  276. case 3:
  277. /* Delta-x 2 */
  278. #ifdef SMOUSE_DEBUG
  279. printk("DX2<%d>", mvalue);
  280. #endif
  281. sunmouse.delta_x += mvalue;
  282. sunmouse.delta_x = CLIP(sunmouse.delta_x);
  283. sunmouse.byte++;
  284. return;
  285. case 4:
  286. /* Last byte, Delta-y 2 */
  287. #ifdef SMOUSE_DEBUG
  288. printk("DY2<%d>", mvalue);
  289. #endif
  290. sunmouse.delta_y += mvalue;
  291. sunmouse.delta_y = CLIP(sunmouse.delta_y);
  292. sunmouse.byte = 0;  /* Back to button state */
  293. break;
  294. case 69:
  295. /* Until we get the (0x80 -> 0x87) value we aren't
  296.  * in the middle of a real transaction, so just
  297.  * return.
  298.  */
  299. return;
  300. default:
  301. printk("sunmouse: bogon transaction staten");
  302. sunmouse.byte = 69;  /* What could cause this? */
  303. return;
  304. };
  305. if (!gen_events) {
  306. push_char (~sunmouse.button_state & 0x87);
  307. push_char (sunmouse.delta_x);
  308. push_char (sunmouse.delta_y);
  309. return;
  310. }
  311. d = bstate ^ pstate;
  312. pstate = bstate;
  313. if (d) {
  314. if (d & BUTTON_LEFT) {
  315. ev.id = MS_LEFT;
  316. ev.value = bstate & BUTTON_LEFT;
  317. }
  318. if (d & BUTTON_RIGHT) {
  319. ev.id = MS_RIGHT;
  320. ev.value = bstate & BUTTON_RIGHT;
  321. }
  322. if (d & BUTTON_MIDDLE) {
  323. ev.id = MS_MIDDLE;
  324. ev.value = bstate & BUTTON_MIDDLE;
  325. }
  326. ev.time = xtime;
  327. ev.value = ev.value ? VKEY_DOWN : VKEY_UP;
  328. pushed += push_event (&ev);
  329. }
  330. if (sunmouse.delta_x) {
  331. ev.id = LOC_X_DELTA;
  332. ev.time = xtime;
  333. ev.value = sunmouse.delta_x;
  334. pushed += push_event (&ev);
  335. sunmouse.delta_x = 0;
  336. }
  337. if (sunmouse.delta_y) {
  338. ev.id = LOC_Y_DELTA;
  339. ev.time = xtime;
  340. ev.value = sunmouse.delta_y;
  341. pushed += push_event (&ev);
  342. }
  343. if (pushed != 0) {
  344. /* We just completed a transaction, wake up whoever is awaiting
  345.  * this event.
  346.  */
  347. kill_fasync (&sunmouse.fasync, SIGIO, POLL_IN);
  348. wake_up_interruptible(&sunmouse.proc_list);
  349. }
  350. return;
  351. }
  352. static int
  353. sun_mouse_open(struct inode * inode, struct file * file)
  354. {
  355. spin_lock_irq(&sunmouse.lock);
  356. if (sunmouse.active++)
  357. goto out;
  358. sunmouse.delta_x = sunmouse.delta_y = 0;
  359. sunmouse.button_state = 0x80;
  360. sunmouse.vuid_mode = VUID_NATIVE;
  361. out:
  362. spin_unlock_irq(&sunmouse.lock);
  363. return 0;
  364. }
  365. static int sun_mouse_fasync (int fd, struct file *filp, int on)
  366. {
  367. int retval;
  368. retval = fasync_helper (fd, filp, on, &sunmouse.fasync);
  369. if (retval < 0)
  370. return retval;
  371. return 0;
  372. }
  373. static int
  374. sun_mouse_close(struct inode *inode, struct file *file)
  375. {
  376. sun_mouse_fasync (-1, file, 0);
  377. spin_lock_irq(&sunmouse.lock);
  378. sunmouse.active--;
  379. spin_unlock_irq(&sunmouse.lock);
  380. return 0;
  381. }
  382. static ssize_t
  383. sun_mouse_write(struct file *file, const char *buffer,
  384. size_t count, loff_t *ppos)
  385. {
  386. return -EINVAL;  /* foo on you */
  387. }
  388. static ssize_t
  389. sun_mouse_read(struct file *file, char *buffer,
  390.        size_t count, loff_t *ppos)
  391. {
  392. DECLARE_WAITQUEUE(wait, current);
  393. unsigned long flags;
  394. if (queue_empty ()) {
  395. if (file->f_flags & O_NONBLOCK)
  396. return -EWOULDBLOCK;
  397. add_wait_queue (&sunmouse.proc_list, &wait);
  398. repeat:
  399. set_current_state(TASK_INTERRUPTIBLE);
  400. if (queue_empty() && !signal_pending(current)) {
  401. schedule();
  402. goto repeat;
  403. }
  404. current->state = TASK_RUNNING;
  405. remove_wait_queue (&sunmouse.proc_list, &wait);
  406. }
  407. if (gen_events) {
  408. char *p = buffer, *end = buffer+count;
  409. spin_lock_irqsave(&sunmouse.lock, flags);
  410. while (p < end && !queue_empty ()){
  411. Firm_event this_event;
  412. get_from_queue(&this_event);
  413. spin_unlock_irqrestore(&sunmouse.lock, flags);
  414. #ifdef CONFIG_SPARC32_COMPAT
  415. if (current->thread.flags & SPARC_FLAG_32BIT) {
  416. if ((end - p) <
  417.     ((sizeof(Firm_event) - sizeof(struct timeval) +
  418.       (sizeof(u32) * 2))))
  419. break;
  420. if (copy_to_user((Firm_event *)p, &this_event,
  421.  sizeof(Firm_event)-sizeof(struct timeval)))
  422. return -EFAULT;
  423. p += sizeof(Firm_event)-sizeof(struct timeval);
  424. if (__put_user(this_event.time.tv_sec, (u32 *)p))
  425. return -EFAULT;
  426. p += sizeof(u32);
  427. if (__put_user(this_event.time.tv_usec, (u32 *)p))
  428. return -EFAULT;
  429. p += sizeof(u32);
  430. } else
  431. #endif
  432. {
  433. if ((end - p) < sizeof(Firm_event))
  434. break;
  435. if (copy_to_user((Firm_event *)p, &this_event,
  436.        sizeof(Firm_event)))
  437. return -EFAULT;
  438. p += sizeof (Firm_event);
  439. }
  440. spin_lock_irqsave(&sunmouse.lock, flags);
  441. }
  442. spin_unlock_irqrestore(&sunmouse.lock, flags);
  443. file->f_dentry->d_inode->i_atime = CURRENT_TIME;
  444. return p-buffer;
  445. } else {
  446. int c, limit = 3;
  447. if (count < limit)
  448. limit = count;
  449. for (c = 0; c < limit; c++) {
  450. unsigned char val;
  451. int empty = 0;
  452. spin_lock_irqsave(&sunmouse.lock, flags);
  453. if (queue_empty()) {
  454. empty = 1;
  455. val = 0;
  456. } else {
  457. val = sunmouse.queue.stream[sunmouse.tail];
  458. sunmouse.tail = (sunmouse.tail + 1) % STREAM_SIZE;
  459. }
  460. spin_unlock_irqrestore(&sunmouse.lock, flags);
  461. if (empty)
  462. break;
  463. put_user(val, buffer);
  464. buffer++;
  465. }
  466. while (c < count) {
  467. if (c >= 5)
  468. break;
  469. put_user(0, buffer);
  470. buffer++;
  471. c++;
  472. }
  473. file->f_dentry->d_inode->i_atime = CURRENT_TIME;
  474. return c;
  475. }
  476. /* Only called if nothing was sent */
  477. if (signal_pending(current))
  478. return -ERESTARTSYS;
  479. return 0;
  480. }
  481. static unsigned int sun_mouse_poll(struct file *file, poll_table *wait)
  482. {
  483. poll_wait(file, &sunmouse.proc_list, wait);
  484. if(!queue_empty())
  485. return POLLIN | POLLRDNORM;
  486. return 0;
  487. }
  488. int
  489. sun_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
  490. {
  491. int i;
  492. switch (cmd){
  493. /* VUIDGFORMAT - Get input device byte stream format */
  494. case _IOR('v', 2, int):
  495. if (put_user(sunmouse.vuid_mode, (int *) arg))
  496. return -EFAULT;
  497. break;
  498. /* VUIDSFORMAT - Set input device byte stream format*/
  499. case _IOW('v', 1, int):
  500. if (get_user(i, (int *) arg))
  501. return -EFAULT;
  502. if (i == VUID_NATIVE || i == VUID_FIRM_EVENT){
  503. int value;
  504. if (get_user(value, (int *)arg))
  505. return -EFAULT;
  506. spin_lock_irq(&sunmouse.lock);
  507. sunmouse.vuid_mode = value;
  508. sunmouse.head = sunmouse.tail = 0;
  509. spin_unlock_irq(&sunmouse.lock);
  510. } else
  511. return -EINVAL;
  512. break;
  513. case 0x8024540b:
  514. case 0x40245408:
  515. /* This is a buggy application doing termios on the mouse driver */
  516. /* we ignore it.  I keep this check here so that we will notice   */
  517. /* future mouse vuid ioctls */
  518. return -ENOTTY;
  519. default:
  520. #ifdef DEBUG
  521. printk ("[MOUSE-ioctl: %8.8x]n", cmd);
  522. #endif
  523. return -EINVAL;
  524. }
  525. return 0;
  526. }
  527. struct file_operations sun_mouse_fops = {
  528. read: sun_mouse_read,
  529. write: sun_mouse_write,
  530. poll: sun_mouse_poll,
  531. ioctl: sun_mouse_ioctl,
  532. open: sun_mouse_open,
  533. release: sun_mouse_close,
  534. fasync: sun_mouse_fasync,
  535. };
  536. static struct miscdevice sun_mouse_mouse = {
  537. SUN_MOUSE_MINOR, "sunmouse", &sun_mouse_fops
  538. };
  539. void sun_mouse_zsinit(void)
  540. {
  541. printk("Sun Mouse-Systems mouse driver version 1.00n");
  542. sunmouse.active = 0;
  543. misc_register (&sun_mouse_mouse);
  544. sunmouse.delta_x = sunmouse.delta_y = 0;
  545. sunmouse.button_state = 0x80;
  546. init_waitqueue_head(&sunmouse.proc_list);
  547. spin_lock_init(&sunmouse.lock);
  548. sunmouse.byte = 69;
  549. }