nodehid.js 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. var os = require('os')
  2. var EventEmitter = require("events").EventEmitter,
  3. util = require("util");
  4. var driverType = null;
  5. function setDriverType(type) {
  6. driverType = type;
  7. }
  8. // lazy load the C++ binding
  9. var binding = null;
  10. function loadBinding() {
  11. if( !binding ) {
  12. if( os.platform() === 'linux' ) {
  13. // Linux defaults to hidraw
  14. if( !driverType || driverType === 'hidraw' ) {
  15. binding = require('bindings')('HID-hidraw.node');
  16. } else {
  17. binding = require('bindings')('HID.node');
  18. }
  19. }
  20. else {
  21. binding = require('bindings')('HID.node');
  22. }
  23. }
  24. }
  25. //This class is a wrapper for `binding.HID` class
  26. function HID() {
  27. //Inherit from EventEmitter
  28. EventEmitter.call(this);
  29. loadBinding();
  30. /* We also want to inherit from `binding.HID`, but unfortunately,
  31. it's not so easy for native Objects. For example, the
  32. following won't work since `new` keyword isn't used:
  33. `binding.HID.apply(this, arguments);`
  34. So... we do this craziness instead...
  35. */
  36. var thisPlusArgs = new Array(arguments.length + 1);
  37. thisPlusArgs[0] = null;
  38. for(var i = 0; i < arguments.length; i++)
  39. thisPlusArgs[i + 1] = arguments[i];
  40. this._raw = new (Function.prototype.bind.apply(binding.HID,
  41. thisPlusArgs) )();
  42. /* Now we have `this._raw` Object from which we need to
  43. inherit. So, one solution is to simply copy all
  44. prototype methods over to `this` and binding them to
  45. `this._raw`
  46. */
  47. for(var i in binding.HID.prototype)
  48. if(i != "close" && i != "read")
  49. this[i] = binding.HID.prototype[i].bind(this._raw);
  50. /* We are now done inheriting from `binding.HID` and EventEmitter.
  51. Now upon adding a new listener for "data" events, we start
  52. polling the HID device using `read(...)`
  53. See `resume()` for more details. */
  54. this._paused = true;
  55. var self = this;
  56. self.on("newListener", function(eventName, listener) {
  57. if(eventName == "data")
  58. process.nextTick(self.resume.bind(self) );
  59. });
  60. }
  61. //Inherit prototype methods
  62. util.inherits(HID, EventEmitter);
  63. //Don't inherit from `binding.HID`; that's done above already!
  64. HID.prototype.close = function close() {
  65. this._closing = true;
  66. this.removeAllListeners();
  67. this._raw.close();
  68. this._closed = true;
  69. };
  70. //Pauses the reader, which stops "data" events from being emitted
  71. HID.prototype.pause = function pause() {
  72. this._paused = true;
  73. };
  74. HID.prototype.read = function read(callback) {
  75. if (this._closed) {
  76. throw new Error('Unable to read from a closed HID device');
  77. } else {
  78. return this._raw.read(callback);
  79. }
  80. };
  81. HID.prototype.resume = function resume() {
  82. var self = this;
  83. if(self._paused && self.listeners("data").length > 0)
  84. {
  85. //Start polling & reading loop
  86. self._paused = false;
  87. self.read(function readFunc(err, data) {
  88. if(err)
  89. {
  90. //Emit error and pause reading
  91. self._paused = true;
  92. if(!self._closing)
  93. self.emit("error", err);
  94. //else ignore any errors if I'm closing the device
  95. }
  96. else
  97. {
  98. //If there are no "data" listeners, we pause
  99. if(self.listeners("data").length <= 0)
  100. self._paused = true;
  101. //Keep reading if we aren't paused
  102. if(!self._paused)
  103. self.read(readFunc);
  104. //Now emit the event
  105. self.emit("data", data);
  106. }
  107. });
  108. }
  109. };
  110. function showdevices() {
  111. loadBinding();
  112. return binding.devices.apply(HID,arguments);
  113. }
  114. //Expose API
  115. exports.HID = HID;
  116. exports.devices = showdevices;
  117. exports.setDriverType = setDriverType;
  118. // exports.devices = binding.devices;