WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content
This repository was archived by the owner on Jul 3, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ rules:
- 2
-
props: false
no-shadow: 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess a good rule, why disable?


parserOptions:
ecmaVersion: 6
Expand Down
2 changes: 2 additions & 0 deletions js/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require('./polyfill');

const random = require('./random');
const keyboard = require('./keyboard');
const mouse = require('./mouse');
const ps2 = require('./ps2');
const pci = require('./pci');
const net = require('./net');
Expand All @@ -29,6 +30,7 @@ class Runtime {
Object.assign(this, {
random,
keyboard,
mouse,
pci,
ps2,
allocator,
Expand Down
20 changes: 20 additions & 0 deletions js/core/mouse/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2016-present runtime.js project authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

'use strict';

const EventController = require('event-controller');
exports.onMousedown = new EventController();
exports.onMouseup = new EventController();
exports.onMousemove = new EventController();
10 changes: 10 additions & 0 deletions js/core/ps2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,13 @@ exports.setKeyboardDriver = (driver) => {
ioPort: driverUtils.ioPort(0x60),
});
};

exports.setMouseDriver = (driver) => {
assert(typeutils.isFunction(driver.init));
assert(typeutils.isFunction(driver.reset));

driver.init({
irq: driverUtils.irq(12),
ioPorts: [driverUtils.ioPort(0x60), driverUtils.ioPort(0x64)],
});
};
1 change: 1 addition & 0 deletions js/driver/ps2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@

'use strict';
require('./keyboard');
require('./mouse');
196 changes: 196 additions & 0 deletions js/driver/ps2/mouse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// Copyright 2016-present runtime.js project authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Some code modified and adapted for use by runtime.js from http://forum.osdev.org/viewtopic.php?t=10247

'use strict';

const runtime = require('../../core');

const flags = {
middle: false,
right: false,
left: false,
};

function splitByte(byte) {
const ret = [];
for (let i = 7; i >= 0; i--) ret.push(byte & (1 << i) ? 1 : 0);
return ret;
}

function processPacket(packet) {
const split = splitByte(packet[0]);
const info = {
yOverflow: split[0],
xOverflow: split[1],
ySign: split[2],
xSign: split[3],
alwaysOne: split[4],
buttons: {
middle: split[5],
right: split[6],
left: split[7],
},
xOffset: packet[1],
yOffset: packet[2],
};

// just a sanity check:
if (info.alwaysOne !== 1) return; // something's wrong with this packet

if (flags.middle && info.buttons.middle === 0) {
flags.middle = false;
setImmediate(() => {
runtime.mouse.onMouseup.dispatch(1);
});
} else if (!flags.middle && info.buttons.middle === 1) {
flags.middle = true;
setImmediate(() => {
runtime.mouse.onMousedown.dispatch(1);
});
} else if (flags.right && info.buttons.right === 0) {
flags.right = false;
setImmediate(() => {
runtime.mouse.onMouseup.dispatch(2);
});
} else if (!flags.right && info.buttons.right === 1) {
flags.right = true;
setImmediate(() => {
runtime.mouse.onMousedown.dispatch(2);
});
} else if (flags.left && info.buttons.left === 0) {
flags.left = false;
setImmediate(() => {
runtime.mouse.onMouseup.dispatch(0);
});
} else if (!flags.left && info.buttons.left === 1) {
flags.left = true;
setImmediate(() => {
runtime.mouse.onMousedown.dispatch(0);
});
}

if (info.xOffset !== 0 || info.yOffset !== 0) {
setImmediate(() => {
runtime.mouse.onMousemove.dispatch({
x: (info.xSign) ? (info.xOffset | 0xffffff00) : info.xOffset,
y: (info.ySign) ? (info.yOffset | 0xffffff00) : info.yOffset,
});
});
}
}

const driver = {
init(device) {
const irq = device.irq;
const [mainPort, port64] = device.ioPorts;

function mouseWait(type) {
return new Promise((resolve, reject) => {
let maxIter = 1500;
function loop() {
return new Promise((resolve, reject) => {
if (maxIter === 0) return resolve();
if (type === 0) {
if ((port64.read8() & 1) === 1) {
return resolve();
}
} else {
if ((port64.read8() & 2) === 0) {
return resolve();
}
}
maxIter--;
setImmediate(() => {
loop().then(resolve).catch(reject);
});
});
}
setImmediate(() => {
loop().then(resolve).catch(reject);
});
});
}

function mouseWrite(data) {
return new Promise((resolve, reject) => {
mouseWait(1).then(() => {
port64.write8(0xd4);
return mouseWait(1);
}).then(() => {
mainPort.write8(data);
resolve();
}).catch(reject);
});
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can avoid new Promise?

return mouseWait(1).then(() => {
          port64.write8(0xd4);
          return mouseWait(1);
        }).then(() => {
          mainPort.write8(data);
        })


function mouseRead() {
return new Promise((resolve, reject) => {
mouseWait(0).then(() => {
resolve(mainPort.read8());
}).catch(reject);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be the same?

return mouseWait(0).then(() => mainPort.read8());

Copy link
Contributor Author

@facekapow facekapow Aug 19, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, ok. I didn't even know that could be done, cool!

}

let status;

/* eslint-disable newline-per-chained-call */
mouseWait(1).then(() => {
port64.write8(0xa8); // enable the aux mouse device
return mouseWait(1);
}).then(() => {
port64.write8(0x20); // use interupts
return mouseWait(0);
}).then(() => {
status = (mainPort.read8() | 2);
return mouseWait(1);
}).then(() => {
port64.write8(0x60);
return mouseWait(1); // end use interupts
}).then(() => {
mainPort.write8(status);
return mouseWrite(0xf6); // use defaults
})
.then(() => mouseRead()) // ACK
.then(() => mouseWrite(0xf4)) // enable the mouse
.then(() => mouseRead()) // ACK
.then(() => {
let cycle = 0;
let packet = [];
irq.on(() => {
if (cycle === 0) {
packet = [];
packet[0] = mainPort.read8();
cycle++;
} else if (cycle === 1) {
packet[1] = mainPort.read8();
cycle++;
} else if (cycle === 2) {
packet[2] = mainPort.read8();
cycle = 0;
((packet) => {
setImmediate(() => {
processPacket(packet);
});
})(packet);
}
});
});
/* eslint-enable newline-per-chained-call */
},
reset() {},
};

runtime.ps2.setMouseDriver(driver);