Removed mouse polling, there seem to exist way too many broken mice for this to work relyable.
Reworked interrupt handler calling, and added a data history. Hotplug support will later be implemented using interrupt data. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17097 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
7d550b53a0
commit
f9ff1193f7
@ -58,7 +58,4 @@ extern status_t ps2_command(uint8 cmd, const uint8 *out, int out_count, uint8 *i
|
|||||||
// prototypes from keyboard.c & mouse.c
|
// prototypes from keyboard.c & mouse.c
|
||||||
extern status_t probe_keyboard(void);
|
extern status_t probe_keyboard(void);
|
||||||
|
|
||||||
extern int32 mouse_handle_int(ps2_dev *dev, uint8 data);
|
|
||||||
extern int32 keyboard_handle_int(uint8 data);
|
|
||||||
|
|
||||||
#endif /* __PS2_COMMON_H */
|
#endif /* __PS2_COMMON_H */
|
||||||
|
@ -142,8 +142,6 @@ ps2_dev_handle_int(ps2_dev *dev, uint8 data)
|
|||||||
|
|
||||||
pass_to_handler:
|
pass_to_handler:
|
||||||
|
|
||||||
dev->last_data = system_time();
|
|
||||||
|
|
||||||
if (!dev->active) {
|
if (!dev->active) {
|
||||||
ps2_service_notify_device_added(dev);
|
ps2_service_notify_device_added(dev);
|
||||||
dprintf("ps2: %s not active, data 0x%02x dropped\n", dev->name, data);
|
dprintf("ps2: %s not active, data 0x%02x dropped\n", dev->name, data);
|
||||||
@ -159,11 +157,14 @@ pass_to_handler:
|
|||||||
return B_HANDLED_INTERRUPT;
|
return B_HANDLED_INTERRUPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// temporary hack...
|
dev->history[4] = dev->history[3];
|
||||||
if (flags & PS2_FLAG_KEYB)
|
dev->history[3] = dev->history[2];
|
||||||
return keyboard_handle_int(data);
|
dev->history[2] = dev->history[1];
|
||||||
else
|
dev->history[1] = dev->history[0];
|
||||||
return mouse_handle_int(dev, data);
|
dev->history[0].time = system_time();
|
||||||
|
dev->history[0].data = data;
|
||||||
|
|
||||||
|
return dev->handle_int(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,6 +15,11 @@ typedef struct ps2_dev ps2_dev;
|
|||||||
|
|
||||||
#include "ps2_common.h"
|
#include "ps2_common.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
bigtime_t time;
|
||||||
|
uint8 data;
|
||||||
|
} data_history;
|
||||||
|
|
||||||
struct ps2_dev
|
struct ps2_dev
|
||||||
{
|
{
|
||||||
@ -27,10 +32,11 @@ struct ps2_dev
|
|||||||
int result_buf_idx;
|
int result_buf_idx;
|
||||||
int result_buf_cnt;
|
int result_buf_cnt;
|
||||||
void * cookie;
|
void * cookie;
|
||||||
bigtime_t last_data;
|
data_history history[5];
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
void (*disconnect)(ps2_dev *);
|
void (*disconnect)(ps2_dev *);
|
||||||
|
int32 (*handle_int)(ps2_dev *);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PS2_DEVICE_COUNT 5
|
#define PS2_DEVICE_COUNT 5
|
||||||
|
@ -89,24 +89,23 @@ set_typematic(int32 rate, bigtime_t delay)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int32 keyboard_handle_int(uint8 data)
|
static int32
|
||||||
|
keyboard_handle_int(ps2_dev *dev)
|
||||||
{
|
{
|
||||||
at_kbd_io keyInfo;
|
at_kbd_io keyInfo;
|
||||||
uint8 scancode;
|
uint8 scancode = dev->history[0].data;
|
||||||
|
|
||||||
if (atomic_and(&sKeyboardOpenMask, 1) == 0)
|
if (atomic_and(&sKeyboardOpenMask, 1) == 0)
|
||||||
return B_HANDLED_INTERRUPT;
|
return B_HANDLED_INTERRUPT;
|
||||||
|
|
||||||
// TODO: Handle braindead "pause" key special case
|
// TODO: Handle braindead "pause" key special case
|
||||||
|
|
||||||
if (data == EXTENDED_KEY) {
|
if (scancode == EXTENDED_KEY) {
|
||||||
sIsExtended = true;
|
sIsExtended = true;
|
||||||
TRACE(("Extended key\n"));
|
TRACE(("Extended key\n"));
|
||||||
return B_HANDLED_INTERRUPT;
|
return B_HANDLED_INTERRUPT;
|
||||||
}
|
}
|
||||||
|
|
||||||
scancode = data;
|
|
||||||
|
|
||||||
TRACE(("scancode: %x\n", scancode));
|
TRACE(("scancode: %x\n", scancode));
|
||||||
|
|
||||||
// For now, F12 enters the kernel debugger
|
// For now, F12 enters the kernel debugger
|
||||||
@ -125,7 +124,7 @@ int32 keyboard_handle_int(uint8 data)
|
|||||||
sIsExtended = false;
|
sIsExtended = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
keyInfo.timestamp = system_time();
|
keyInfo.timestamp = dev->history[0].time;
|
||||||
keyInfo.scancode = scancode;
|
keyInfo.scancode = scancode;
|
||||||
|
|
||||||
if (packet_buffer_write(sKeyBuffer, (uint8 *)&keyInfo, sizeof(keyInfo)) == 0) {
|
if (packet_buffer_write(sKeyBuffer, (uint8 *)&keyInfo, sizeof(keyInfo)) == 0) {
|
||||||
@ -250,6 +249,7 @@ keyboard_open(const char *name, uint32 flags, void **_cookie)
|
|||||||
|
|
||||||
*_cookie = NULL;
|
*_cookie = NULL;
|
||||||
ps2_device[PS2_DEVICE_KEYB].disconnect = &ps2_keyboard_disconnect;
|
ps2_device[PS2_DEVICE_KEYB].disconnect = &ps2_keyboard_disconnect;
|
||||||
|
ps2_device[PS2_DEVICE_KEYB].handle_int = &keyboard_handle_int;
|
||||||
|
|
||||||
dprintf("ps2: keyboard_open %s success\n", name);
|
dprintf("ps2: keyboard_open %s success\n", name);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
@ -218,10 +218,11 @@ ps2_mouse_disconnect(ps2_dev *dev)
|
|||||||
* by read() operations. The full data is obtained using 3 consecutive
|
* by read() operations. The full data is obtained using 3 consecutive
|
||||||
* calls to the handler, each holds a different byte on the data port.
|
* calls to the handler, each holds a different byte on the data port.
|
||||||
*/
|
*/
|
||||||
int32
|
static int32
|
||||||
mouse_handle_int(ps2_dev *dev, uint8 data)
|
mouse_handle_int(ps2_dev *dev)
|
||||||
{
|
{
|
||||||
mouse_cookie *cookie = dev->cookie;
|
mouse_cookie *cookie = dev->cookie;
|
||||||
|
uint8 data = dev->history[0].data;
|
||||||
|
|
||||||
if (cookie->packet_index == 0 && !(data & 8)) {
|
if (cookie->packet_index == 0 && !(data & 8)) {
|
||||||
TRACE(("bad mouse data, trying resync\n"));
|
TRACE(("bad mouse data, trying resync\n"));
|
||||||
@ -339,6 +340,7 @@ mouse_open(const char *name, uint32 flags, void **_cookie)
|
|||||||
cookie->dev = dev;
|
cookie->dev = dev;
|
||||||
dev->cookie = cookie;
|
dev->cookie = cookie;
|
||||||
dev->disconnect = &ps2_mouse_disconnect;
|
dev->disconnect = &ps2_mouse_disconnect;
|
||||||
|
dev->handle_int = &mouse_handle_int;
|
||||||
|
|
||||||
status = probe_mouse(cookie, &cookie->packet_size);
|
status = probe_mouse(cookie, &cookie->packet_size);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
|
@ -16,16 +16,6 @@ static thread_id sServiceThread;
|
|||||||
static volatile bool sServiceTerminate;
|
static volatile bool sServiceTerminate;
|
||||||
static packet_buffer * sServiceCmdBuffer;
|
static packet_buffer * sServiceCmdBuffer;
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#define PS2_SERVICE_INTERVAL 10000000
|
|
||||||
#else
|
|
||||||
#define PS2_SERVICE_INTERVAL 1000000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#define PS2_PERIODIC_SERVICE
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
uint32 id;
|
uint32 id;
|
||||||
@ -72,72 +62,6 @@ ps2_service_notify_device_removed(ps2_dev *dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
|
||||||
ps2_service_probe_device(ps2_dev *dev)
|
|
||||||
{
|
|
||||||
status_t res;
|
|
||||||
uint8 data[2];
|
|
||||||
|
|
||||||
TRACE(("ps2_service_probe_device %s\n", dev->name));
|
|
||||||
|
|
||||||
// assume device still exists if it sent data during last 500 ms
|
|
||||||
if (dev->active && (system_time() - dev->last_data) < 500000)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
if (dev->flags & PS2_FLAG_KEYB) {
|
|
||||||
|
|
||||||
// res = ps2_dev_command(dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0);
|
|
||||||
// if (res == B_OK)
|
|
||||||
// return B_OK;
|
|
||||||
|
|
||||||
// snooze(25000);
|
|
||||||
// res = ps2_dev_command(dev, 0xee, NULL, 0, NULL, 0); // echo
|
|
||||||
// if (res == B_OK)
|
|
||||||
// return B_OK;
|
|
||||||
|
|
||||||
// snooze(25000);
|
|
||||||
res = ps2_dev_command(dev, PS2_CMD_GET_DEVICE_ID, NULL, 0, data, 2);
|
|
||||||
if (res == B_OK)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
// if (!dev->active) {
|
|
||||||
// snooze(25000);
|
|
||||||
// // 0xFA (Set All Keys Typematic/Make/Break) - Keyboard responds with "ack" (0xFA).
|
|
||||||
// res = ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], 0xfa, NULL, 0, NULL, 0);
|
|
||||||
// if (res == B_OK)
|
|
||||||
// return B_OK;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!dev->active) {
|
|
||||||
snooze(25000);
|
|
||||||
// 0xF3 (Set Typematic Rate/Delay)
|
|
||||||
data[0] = 0x0b;
|
|
||||||
res = ps2_dev_command(dev, PS2_CMD_KEYBOARD_SET_TYPEMATIC, data, 1, NULL, 0);
|
|
||||||
if (res == B_OK)
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
res = ps2_dev_command(dev, PS2_CMD_GET_DEVICE_ID, NULL, 0, data, 1);
|
|
||||||
if (res == B_OK)
|
|
||||||
return B_OK;
|
|
||||||
|
|
||||||
if (!dev->active) {
|
|
||||||
snooze(25000);
|
|
||||||
res = ps2_dev_command(dev, PS2_CMD_ENABLE, NULL, 0, NULL, 0);
|
|
||||||
if (res == B_OK) {
|
|
||||||
ps2_dev_command(dev, PS2_CMD_DISABLE, NULL, 0, NULL, 0);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
ps2_service_thread(void *arg)
|
ps2_service_thread(void *arg)
|
||||||
{
|
{
|
||||||
@ -145,11 +69,7 @@ ps2_service_thread(void *arg)
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
status_t status;
|
status_t status;
|
||||||
#ifdef PS2_PERIODIC_SERVICE
|
status = acquire_sem_etc(sServiceSem, 1, B_CAN_INTERRUPT, 0);
|
||||||
status = acquire_sem_etc(sServiceSem, 1, B_CAN_INTERRUPT | B_RELATIVE_TIMEOUT, PS2_SERVICE_INTERVAL);
|
|
||||||
#else
|
|
||||||
status = acquire_sem_etc(sServiceSem, 1, B_CAN_INTERRUPT, 0);
|
|
||||||
#endif
|
|
||||||
if (sServiceTerminate)
|
if (sServiceTerminate)
|
||||||
break;
|
break;
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
@ -172,21 +92,6 @@ ps2_service_thread(void *arg)
|
|||||||
TRACE(("PS2_SERVICE: unknown id %lu\n", cmd.id));
|
TRACE(("PS2_SERVICE: unknown id %lu\n", cmd.id));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (status == B_TIMED_OUT) {
|
|
||||||
|
|
||||||
// do periodic processing
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < (gActiveMultiplexingEnabled ? PS2_DEVICE_COUNT : 2); i++) {
|
|
||||||
ps2_dev *dev = &ps2_device[i];
|
|
||||||
status_t status = ps2_service_probe_device(dev);
|
|
||||||
if (dev->active && status != B_OK)
|
|
||||||
ps2_dev_unpublish(dev);
|
|
||||||
else if (!dev->active && status == B_OK)
|
|
||||||
ps2_dev_publish(dev);
|
|
||||||
snooze(50000);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dprintf("ps2_service_thread: Error, status 0x%08lx, terminating\n", status);
|
dprintf("ps2_service_thread: Error, status 0x%08lx, terminating\n", status);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user