UsbMouse.Mod 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. MODULE UsbMouse; (** AUTHOR "staubesv"; PURPOSE "USB Mouse Driver"; *)
  2. (**
  3. * Bluebottle USB Mouse Driver (HID boot protocol)
  4. *
  5. * Usage:
  6. * UsbMouse.Install ~ loads this driver
  7. * SystemTools.Free UsbMouse ~ unloads this driver
  8. *
  9. * The HID boot protocol for USB mice supports 3 buttons and 2 axes.
  10. *
  11. * References:
  12. * Device Class Definition for Human Interface Devices (HID), Version 1.11, 27.06.2001, www.usb.org
  13. *
  14. * History:
  15. * 01.12.2005 Added MouseSpeed & MouseAcceleration (staubesv)
  16. * 10.10.2006 Adapted to UsbHid (staubesv)
  17. * 28.02.2007 Removed mouse wheel hack since new HID driver can correctly handle it (staubesv)
  18. *)
  19. IMPORT SYSTEM, KernelLog, Modules, Inputs, Usbdi, UsbHid;
  20. CONST
  21. Name = "UsbMouse";
  22. Description = "HID boot protocol mouse driver";
  23. (* Mouse Configuration *)
  24. MouseSpeed = 50;
  25. MouseAcceleration = 0;
  26. Debug = TRUE;
  27. TYPE
  28. MouseDriver= OBJECT (UsbHid.HidDriver);
  29. VAR
  30. buffer : Usbdi.BufferPtr;
  31. pipe : Usbdi.Pipe;
  32. lastDx, lastDy : LONGINT;
  33. accelX, accelY : REAL;
  34. PROCEDURE HandleEvent(status : Usbdi.Status; actLen : LONGINT);
  35. VAR mm : Inputs.MouseMsg; dx, dy : LONGINT;
  36. BEGIN
  37. IF (status = Usbdi.Ok) OR ((status = Usbdi.ShortPacket) & (actLen >= 3)) THEN
  38. dx := SYSTEM.VAL(SHORTINT, buffer[1]);
  39. dy := SYSTEM.VAL(SHORTINT, buffer[2]);
  40. accelX := 1.0 + ABS(dx - lastDx) / 128 * MouseAcceleration;
  41. accelY := 1.0 + ABS(dy - lastDy) / 128 * MouseAcceleration;
  42. lastDx := dx;
  43. lastDy := dy;
  44. mm.dx :=ENTIER(MouseSpeed / 50.0 * dx * accelX);
  45. mm.dy := ENTIER(MouseSpeed / 50.0 * dy * accelY);
  46. IF (SYSTEM.VAL(SET, buffer[0]) * {0}) # {} THEN mm.keys := mm.keys + {0}; END;
  47. IF (SYSTEM.VAL(SET, buffer[0]) * {1}) # {} THEN mm.keys := mm.keys + {2}; END;
  48. IF (SYSTEM.VAL(SET, buffer[0]) * {2}) # {} THEN mm.keys := mm.keys + {1}; END;
  49. Inputs.mouse.Handle(mm);
  50. status := pipe.Transfer(pipe.maxPacketSize, 0, buffer);
  51. ELSE
  52. IF status = Usbdi.Stalled THEN
  53. IF pipe.ClearHalt() THEN
  54. IF Debug THEN KernelLog.String("UsbMouse: Stall on Interrupt Pipe cleared."); KernelLog.Ln; END;
  55. status := pipe.Transfer(pipe.maxPacketSize, 0, buffer); (* ignore status *)
  56. ELSE
  57. IF Debug THEN KernelLog.String("UsbMouse: Couldn't clear stall on interrupt pipe. Abort."); KernelLog.Ln; END;
  58. device.FreePipe(pipe);
  59. END;
  60. END;
  61. END;
  62. END HandleEvent;
  63. PROCEDURE Connect() : BOOLEAN;
  64. VAR endpoint, i : LONGINT; status : Usbdi.Status;
  65. BEGIN
  66. (* Set the HID boot protocol *)
  67. IF SetProtocol(UsbHid.BootProtocol) = FALSE THEN
  68. IF Debug THEN KernelLog.String("UsbMouse: Error: Cannot set boot protocol."); KernelLog.Ln; END;
  69. RETURN FALSE
  70. END;
  71. (* Look for the first interrupt IN endpoint of this device *)
  72. LOOP
  73. IF i >= LEN(interface.endpoints) THEN EXIT; END;
  74. IF interface.endpoints[i].type = Usbdi.InterruptIn THEN
  75. endpoint := interface.endpoints[i].bEndpointAddress;
  76. EXIT;
  77. END;
  78. INC(i);
  79. END;
  80. IF endpoint = 0 THEN
  81. IF Debug THEN KernelLog.String("UsbMouse: No interrupt IN endpoint found."); KernelLog.Ln; END;
  82. RETURN FALSE;
  83. END;
  84. pipe := device.GetPipe(endpoint);
  85. IF pipe = NIL THEN RETURN FALSE END;
  86. NEW(buffer, pipe.maxPacketSize);
  87. pipe.SetTimeout(0);
  88. pipe.SetCompletionHandler(HandleEvent);
  89. status := pipe.Transfer(pipe.maxPacketSize, 0, buffer); (* ignore res *)
  90. RETURN TRUE;
  91. END Connect;
  92. PROCEDURE Disconnect;
  93. BEGIN
  94. KernelLog.String("USB mouse disconnected."); KernelLog.Ln;
  95. END Disconnect;
  96. END MouseDriver;
  97. PROCEDURE Probe(dev : Usbdi.UsbDevice; id : Usbdi.InterfaceDescriptor) : Usbdi.Driver;
  98. VAR driver : MouseDriver;
  99. BEGIN
  100. IF id.bInterfaceClass # 3 THEN RETURN NIL END; (* HID class *)
  101. IF id.bInterfaceSubClass # 1 THEN RETURN NIL END; (* Boot protocol subclass *)
  102. IF id.bInterfaceProtocol # 2 THEN RETURN NIL END; (* Mouse *)
  103. NEW(driver); RETURN driver;
  104. END Probe;
  105. PROCEDURE Install*;
  106. END Install;
  107. PROCEDURE Cleanup;
  108. BEGIN
  109. Usbdi.drivers.Remove(Name);
  110. END Cleanup;
  111. BEGIN
  112. Modules.InstallTermHandler(Cleanup);
  113. Usbdi.drivers.Add(Probe, Name, Description, 10)
  114. END UsbMouse.
  115. UsbMouse.Install ~ SystemTools.Free UsbMouse ~