implemented basic support for multiple mouse devices, seems to work

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16022 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2006-01-21 15:45:22 +00:00
parent 098b042978
commit dfd5628d64
6 changed files with 173 additions and 117 deletions

View File

@ -173,13 +173,6 @@ ps2_keyboard_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int
return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], cmd, out, out_count, in, in_count); return ps2_dev_command(&ps2_device[PS2_DEVICE_KEYB], cmd, out, out_count, in, in_count);
} }
status_t
ps2_mouse_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count)
{
return ps2_dev_command(&ps2_device[PS2_DEVICE_MOUSE], cmd, out, out_count, in, in_count);
}
// #pragma mark - // #pragma mark -
inline status_t inline status_t

View File

@ -19,6 +19,7 @@
#include <OS.h> #include <OS.h>
#include "ps2_defs.h" #include "ps2_defs.h"
#include "ps2_dev.h"
// debug defines // debug defines
@ -50,7 +51,6 @@ extern void ps2_flush();
extern status_t ps2_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count); extern status_t ps2_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count);
extern status_t ps2_keyboard_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count); extern status_t ps2_keyboard_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count);
extern status_t ps2_mouse_command(uint8 cmd, const uint8 *out, int out_count, uint8 *in, int in_count);
extern status_t ps2_get_command_byte(uint8 *byte); extern status_t ps2_get_command_byte(uint8 *byte);
extern status_t ps2_set_command_byte(uint8 byte); extern status_t ps2_set_command_byte(uint8 byte);
@ -60,14 +60,11 @@ extern void ps2_unclaim_result(void);
extern status_t ps2_wait_for_result(void); extern status_t ps2_wait_for_result(void);
extern bool ps2_handle_result(uint8 data); extern bool ps2_handle_result(uint8 data);
extern void ps2_common_uninitialize(void);
extern status_t ps2_common_initialize(void);
// 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 status_t probe_mouse(size_t *probed_packet_size);
extern int32 mouse_handle_int(uint8 data); extern int32 mouse_handle_int(ps2_dev *dev, uint8 data);
extern int32 keyboard_handle_int(uint8 data); extern int32 keyboard_handle_int(uint8 data);

View File

@ -89,30 +89,43 @@ ps2_dev_unpublish(ps2_dev *dev)
int32 int32
ps2_dev_handle_int(ps2_dev *dev, uint8 data) ps2_dev_handle_int(ps2_dev *dev, uint8 data)
{ {
if (!dev->active) { uint32 flags;
ps2_service_handle_device_added(dev);
} flags = atomic_get(&dev->flags);
if (dev->result_buf_cnt) { if (flags & PS2_FLAG_CMD) {
dev->result_buf[dev->result_buf_idx] = data; if ((flags & (PS2_FLAG_ACK | PS2_FLAG_NACK)) == 0) {
dev->result_buf_idx++; atomic_or(&dev->flags, data == 0xfa ? PS2_FLAG_ACK : PS2_FLAG_NACK);
dev->result_buf_cnt--; } else if (dev->result_buf_cnt) {
if (dev->result_buf_cnt == 0) { dev->result_buf[dev->result_buf_idx] = data;
release_sem_etc(dev->result_sem, 1, B_DO_NOT_RESCHEDULE); dev->result_buf_idx++;
return B_INVOKE_SCHEDULER; dev->result_buf_cnt--;
if (dev->result_buf_cnt == 0) {
release_sem_etc(dev->result_sem, 1, B_DO_NOT_RESCHEDULE);
return B_INVOKE_SCHEDULER;
}
} else {
dprintf("ps2_dev_handle_int can't handle\n");
} }
return B_HANDLED_INTERRUPT; return B_HANDLED_INTERRUPT;
} }
if (!dev->active) { if (!dev->active) {
ps2_service_handle_device_added(dev);
dprintf("not active, data dropped\n");
return B_HANDLED_INTERRUPT; return B_HANDLED_INTERRUPT;
} }
if ((flags & PS2_FLAG_ENABLED) == 0) {
dprintf("not enabled, data dropped\n");
return B_HANDLED_INTERRUPT;
}
// temporary hack... // temporary hack...
if (dev->flags & PS2_FLAG_KEYB) if (flags & PS2_FLAG_KEYB)
return keyboard_handle_int(data); return keyboard_handle_int(data);
else else
return mouse_handle_int(data); return mouse_handle_int(dev, data);
} }
@ -124,6 +137,8 @@ ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int out_count, uint8
dprintf("ps2_dev_command %02x, %d out, in %d, dev %s\n", cmd, out_count, in_count, dev->name); dprintf("ps2_dev_command %02x, %d out, in %d, dev %s\n", cmd, out_count, in_count, dev->name);
dev->flags |= PS2_FLAG_CMD;
dev->flags &= ~(PS2_FLAG_ACK | PS2_FLAG_NACK);
dev->result_buf_cnt = in_count; dev->result_buf_cnt = in_count;
dev->result_buf_idx = 0; dev->result_buf_idx = 0;
@ -147,6 +162,16 @@ ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int out_count, uint8
ps2_write_data(i == -1 ? cmd : out[i]); ps2_write_data(i == -1 ? cmd : out[i]);
} }
} }
if (dev->flags & PS2_FLAG_ACK) {
dprintf("ps2_dev_command got ACK\n");
}
if (dev->flags & PS2_FLAG_NACK) {
dev->flags &= ~PS2_FLAG_CMD;
dprintf("ps2_dev_command got NACK\n");
return B_ERROR;
}
if (res != B_OK) { if (res != B_OK) {
dprintf("ps2_dev_command send failed\n"); dprintf("ps2_dev_command send failed\n");
@ -166,6 +191,8 @@ ps2_dev_command(ps2_dev *dev, uint8 cmd, const uint8 *out, int out_count, uint8
dprintf("ps2_dev_command data %02x\n", in[i]); dprintf("ps2_dev_command data %02x\n", in[i]);
} }
dev->flags &= ~PS2_FLAG_CMD;
return res; return res;
} }

View File

@ -10,9 +10,13 @@
#ifndef __PS2_DEV_H #ifndef __PS2_DEV_H
#define __PS2_DEV_H #define __PS2_DEV_H
struct ps2_dev;
typedef struct ps2_dev ps2_dev;
#include "ps2_common.h" #include "ps2_common.h"
typedef struct
struct ps2_dev
{ {
const char * name; const char * name;
bool active; bool active;
@ -22,14 +26,20 @@ typedef struct
uint8 * result_buf; uint8 * result_buf;
int result_buf_idx; int result_buf_idx;
int result_buf_cnt; int result_buf_cnt;
} ps2_dev; void * cookie;
};
extern ps2_dev ps2_device[5]; extern ps2_dev ps2_device[5];
#define PS2_DEVICE_MOUSE 0 #define PS2_DEVICE_MOUSE 0
#define PS2_DEVICE_KEYB 4 #define PS2_DEVICE_KEYB 4
#define PS2_FLAG_KEYB 1 #define PS2_FLAG_KEYB (1<<0)
#define PS2_FLAG_OPEN (1<<1)
#define PS2_FLAG_ENABLED (1<<2)
#define PS2_FLAG_CMD (1<<3)
#define PS2_FLAG_ACK (1<<4)
#define PS2_FLAG_NACK (1<<5)
status_t ps2_dev_init(void); status_t ps2_dev_init(void);
void ps2_dev_exit(void); void ps2_dev_exit(void);

View File

@ -225,6 +225,7 @@ keyboard_open(const char *name, uint32 flags, void **_cookie)
goto err3; goto err3;
} }
atomic_or(&ps2_device[PS2_DEVICE_KEYB].flags, PS2_FLAG_ENABLED);
release_sem(gDeviceOpenSemaphore); release_sem(gDeviceOpenSemaphore);

View File

@ -60,39 +60,44 @@
#include <Drivers.h> #include <Drivers.h>
#include <string.h> #include <string.h>
#include <malloc.h>
#include "kb_mouse_driver.h" #include "kb_mouse_driver.h"
#include "ps2_common.h"
#include "packet_buffer.h" #include "packet_buffer.h"
#include "ps2_common.h"
#include "ps2_dev.h"
#define MOUSE_HISTORY_SIZE 256 #define MOUSE_HISTORY_SIZE 256
// we record that many mouse packets before we start to drop them // we record that many mouse packets before we start to drop them
static sem_id sMouseSem; typedef struct
static struct packet_buffer *sMouseBuffer; {
static int32 sOpenMask; ps2_dev * dev;
static bigtime_t sLastClickTime; sem_id mouse_sem;
static bigtime_t sClickSpeed; packet_buffer * mouse_buffer;
static int32 sClickCount; bigtime_t click_last_time;
static int sButtonsState; bigtime_t click_speed;
int click_count;
static size_t sPacketSize; int buttons_state;
static size_t sPacketIndex;
static uint8 sPacketBuffer[PS2_MAX_PACKET_SIZE]; size_t packet_size;
size_t packet_index;
uint8 packet_buffer[PS2_MAX_PACKET_SIZE];
} mouse_cookie;
static status_t static status_t
ps2_reset_mouse() ps2_reset_mouse(mouse_cookie *cookie)
{ {
uint8 read; uint8 read;
status_t status; status_t status;
TRACE(("ps2_reset_mouse()\n")); TRACE(("ps2_reset_mouse()\n"));
status = ps2_mouse_command(PS2_CMD_RESET_MOUSE, NULL, 0, &read, 1); status = ps2_dev_command(cookie->dev, PS2_CMD_RESET_MOUSE, NULL, 0, &read, 1);
TRACE(("reset mouse: status 0x%08x, data 0x%02x\n", status, read)); TRACE(("reset mouse: status 0x%08x, data 0x%02x\n", status, read));
@ -105,12 +110,12 @@ ps2_reset_mouse()
*/ */
static status_t static status_t
ps2_set_sample_rate(uint8 rate) ps2_set_sample_rate(mouse_cookie *cookie, uint8 rate)
{ {
int32 tries = 5; int32 tries = 5;
while (--tries > 0) { while (--tries > 0) {
status_t status = ps2_mouse_command(PS2_CMD_SET_SAMPLE_RATE, &rate, 1, NULL, 0); status_t status = ps2_dev_command(cookie->dev, PS2_CMD_SET_SAMPLE_RATE, &rate, 1, NULL, 0);
if (status == B_OK) if (status == B_OK)
return B_OK; return B_OK;
@ -124,7 +129,7 @@ ps2_set_sample_rate(uint8 rate)
*/ */
static void static void
ps2_packet_to_movement(uint8 packet[], mouse_movement *pos) ps2_packet_to_movement(mouse_cookie *cookie, uint8 packet[], mouse_movement *pos)
{ {
int buttons = packet[0] & 7; int buttons = packet[0] & 7;
int xDelta = ((packet[0] & 0x10) ? 0xFFFFFF00 : 0) | packet[1]; int xDelta = ((packet[0] & 0x10) ? 0xFFFFFF00 : 0) | packet[1];
@ -133,17 +138,17 @@ ps2_packet_to_movement(uint8 packet[], mouse_movement *pos)
int8 wheel_ydelta = 0; int8 wheel_ydelta = 0;
int8 wheel_xdelta = 0; int8 wheel_xdelta = 0;
if (buttons != 0 && sButtonsState == 0) { if (buttons != 0 && cookie->buttons_state == 0) {
if (sLastClickTime + sClickSpeed > currentTime) if (cookie->click_last_time + cookie->click_speed > currentTime)
sClickCount++; cookie->click_count++;
else else
sClickCount = 1; cookie->click_count = 1;
} }
sLastClickTime = currentTime; cookie->click_last_time = currentTime;
sButtonsState = buttons; cookie->buttons_state = buttons;
if (sPacketSize == PS2_PACKET_INTELLIMOUSE) { if (cookie->packet_size == PS2_PACKET_INTELLIMOUSE) {
switch (packet[3] & 0x0F) { switch (packet[3] & 0x0F) {
case 0x01: wheel_ydelta = +1; break; // wheel 1 down case 0x01: wheel_ydelta = +1; break; // wheel 1 down
case 0x0F: wheel_ydelta = -1; break; // wheel 1 up case 0x0F: wheel_ydelta = -1; break; // wheel 1 up
@ -154,20 +159,20 @@ ps2_packet_to_movement(uint8 packet[], mouse_movement *pos)
// dprintf("packet: %02x %02x %02x %02x: xd %d, yd %d, 0x%x (%d), w-xd %d, w-yd %d\n", // dprintf("packet: %02x %02x %02x %02x: xd %d, yd %d, 0x%x (%d), w-xd %d, w-yd %d\n",
// packet[0], packet[1], packet[2], packet[3], // packet[0], packet[1], packet[2], packet[3],
// xDelta, yDelta, buttons, sClickCount, wheel_xdelta, wheel_ydelta); // xDelta, yDelta, buttons, cookie->click_count, wheel_xdelta, wheel_ydelta);
if (pos) { if (pos) {
pos->xdelta = xDelta; pos->xdelta = xDelta;
pos->ydelta = yDelta; pos->ydelta = yDelta;
pos->buttons = buttons; pos->buttons = buttons;
pos->clicks = sClickCount; pos->clicks = cookie->click_count;
pos->modifiers = 0; pos->modifiers = 0;
pos->timestamp = currentTime; pos->timestamp = currentTime;
pos->wheel_ydelta = (int)wheel_ydelta; pos->wheel_ydelta = (int)wheel_ydelta;
pos->wheel_xdelta = (int)wheel_xdelta; pos->wheel_xdelta = (int)wheel_xdelta;
TRACE(("xdelta: %d, ydelta: %d, buttons %x, clicks: %ld, timestamp %Ld\n", TRACE(("xdelta: %d, ydelta: %d, buttons %x, clicks: %ld, timestamp %Ld\n",
xDelta, yDelta, buttons, sClickCount, currentTime)); xDelta, yDelta, buttons, cookie->click_count, currentTime));
} }
} }
@ -176,18 +181,18 @@ ps2_packet_to_movement(uint8 packet[], mouse_movement *pos)
*/ */
static status_t static status_t
mouse_read_event(mouse_movement *userMovement) mouse_read_event(mouse_cookie *cookie, mouse_movement *userMovement)
{ {
uint8 packet[PS2_MAX_PACKET_SIZE]; uint8 packet[PS2_MAX_PACKET_SIZE];
mouse_movement movement; mouse_movement movement;
status_t status; status_t status;
TRACE(("mouse_read_event()\n")); TRACE(("mouse_read_event()\n"));
status = acquire_sem_etc(sMouseSem, 1, B_CAN_INTERRUPT, 0); status = acquire_sem_etc(cookie->mouse_sem, 1, B_CAN_INTERRUPT, 0);
if (status < B_OK) if (status < B_OK)
return status; return status;
if (packet_buffer_read(sMouseBuffer, packet, sPacketSize) != sPacketSize) { if (packet_buffer_read(cookie->mouse_buffer, packet, cookie->packet_size) != cookie->packet_size) {
TRACE(("error copying buffer\n")); TRACE(("error copying buffer\n"));
return B_ERROR; return B_ERROR;
} }
@ -195,7 +200,7 @@ mouse_read_event(mouse_movement *userMovement)
if (!(packet[0] & 8)) if (!(packet[0] & 8))
panic("ps2_hid: got broken data from packet_buffer_read\n"); panic("ps2_hid: got broken data from packet_buffer_read\n");
ps2_packet_to_movement(packet, &movement); ps2_packet_to_movement(cookie, packet, &movement);
return user_memcpy(userMovement, &movement, sizeof(mouse_movement)); return user_memcpy(userMovement, &movement, sizeof(mouse_movement));
} }
@ -205,12 +210,12 @@ mouse_read_event(mouse_movement *userMovement)
*/ */
static status_t static status_t
set_mouse_enabled(bool enable) set_mouse_enabled(mouse_cookie *cookie, bool enable)
{ {
int32 tries = 5; int32 tries = 5;
while (true) { while (true) {
if (ps2_mouse_command(enable ? PS2_CMD_ENABLE_MOUSE : PS2_CMD_DISABLE_MOUSE, NULL, 0, NULL, 0) == B_OK) if (ps2_dev_command(cookie->dev, enable ? PS2_CMD_ENABLE_MOUSE : PS2_CMD_DISABLE_MOUSE, NULL, 0, NULL, 0) == B_OK)
return B_OK; return B_OK;
if (--tries <= 0) if (--tries <= 0)
@ -228,33 +233,32 @@ set_mouse_enabled(bool enable)
* 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 mouse_handle_int(uint8 data) int32 mouse_handle_int(ps2_dev *dev, uint8 data)
{ {
if (atomic_and(&sOpenMask, 1) == 0) mouse_cookie *cookie = dev->cookie;
return B_HANDLED_INTERRUPT;
if (cookie->packet_index == 0 && !(data & 8)) {
if (sPacketIndex == 0 && !(data & 8)) {
TRACE(("bad mouse data, trying resync\n")); TRACE(("bad mouse data, trying resync\n"));
return B_HANDLED_INTERRUPT; return B_HANDLED_INTERRUPT;
} }
sPacketBuffer[sPacketIndex++] = data; cookie->packet_buffer[cookie->packet_index++] = data;
if (sPacketIndex != sPacketSize) { if (cookie->packet_index != cookie->packet_size) {
// packet not yet complete // packet not yet complete
return B_HANDLED_INTERRUPT; return B_HANDLED_INTERRUPT;
} }
// complete packet is assembled // complete packet is assembled
sPacketIndex = 0; cookie->packet_index = 0;
if (packet_buffer_write(sMouseBuffer, sPacketBuffer, sPacketSize) != sPacketSize) { if (packet_buffer_write(cookie->mouse_buffer, cookie->packet_buffer, cookie->packet_size) != cookie->packet_size) {
// buffer is full, drop new data // buffer is full, drop new data
return B_HANDLED_INTERRUPT; return B_HANDLED_INTERRUPT;
} }
release_sem_etc(sMouseSem, 1, B_DO_NOT_RESCHEDULE); release_sem_etc(cookie->mouse_sem, 1, B_DO_NOT_RESCHEDULE);
return B_INVOKE_SCHEDULER; return B_INVOKE_SCHEDULER;
} }
@ -263,12 +267,12 @@ int32 mouse_handle_int(uint8 data)
status_t status_t
probe_mouse(size_t *probed_packet_size) probe_mouse(mouse_cookie *cookie, size_t *probed_packet_size)
{ {
uint8 deviceId = 0; uint8 deviceId = 0;
// get device id // get device id
ps2_mouse_command(PS2_CMD_GET_DEVICE_ID, NULL, 0, &deviceId, 1); ps2_dev_command(cookie->dev, PS2_CMD_GET_DEVICE_ID, NULL, 0, &deviceId, 1);
TRACE(("probe_mouse(): device id: %2x\n", deviceId)); TRACE(("probe_mouse(): device id: %2x\n", deviceId));
@ -277,11 +281,11 @@ probe_mouse(size_t *probed_packet_size)
while (--tries > 0) { while (--tries > 0) {
// try to switch to intellimouse mode // try to switch to intellimouse mode
if (ps2_set_sample_rate(200) == B_OK if (ps2_set_sample_rate(cookie, 200) == B_OK
&& ps2_set_sample_rate(100) == B_OK && ps2_set_sample_rate(cookie, 100) == B_OK
&& ps2_set_sample_rate(80) == B_OK) { && ps2_set_sample_rate(cookie, 80) == B_OK) {
// get device id, again // get device id, again
ps2_mouse_command(PS2_CMD_GET_DEVICE_ID, NULL, 0, &deviceId, 1); ps2_dev_command(cookie->dev, PS2_CMD_GET_DEVICE_ID, NULL, 0, &deviceId, 1);
TRACE(("probe_mouse(): device id: %2x\n", deviceId)); TRACE(("probe_mouse(): device id: %2x\n", deviceId));
break; break;
} }
@ -312,83 +316,105 @@ probe_mouse(size_t *probed_packet_size)
status_t status_t
mouse_open(const char *name, uint32 flags, void **_cookie) mouse_open(const char *name, uint32 flags, void **_cookie)
{ {
status_t status; mouse_cookie *cookie;
int8 commandByte; ps2_dev *dev;
status_t status;
int i;
TRACE(("mouse_open() %s\n", name));
TRACE(("mouse_open()\n")); for (dev = NULL, i = 0; i < 5; i++) {
if (0 == strcmp(ps2_device[i].name, name)) {
if (atomic_or(&sOpenMask, 1) != 0) dev = &ps2_device[i];
break;
}
}
if (dev == NULL) {
TRACE(("dev = NULL\n"));
return B_ERROR;
}
if (atomic_or(&dev->flags, PS2_FLAG_OPEN) & PS2_FLAG_OPEN)
return B_BUSY; return B_BUSY;
acquire_sem(gDeviceOpenSemaphore); cookie = malloc(sizeof(mouse_cookie));
if (cookie == NULL)
status = probe_mouse(&sPacketSize);
if (status != B_OK)
goto err1; goto err1;
sPacketIndex = 0; *_cookie = cookie;
memset(cookie, 0, sizeof(*cookie));
sMouseBuffer = create_packet_buffer(MOUSE_HISTORY_SIZE * sPacketSize); cookie->dev = dev;
if (sMouseBuffer == NULL) { dev->cookie = cookie;
status = probe_mouse(cookie, &cookie->packet_size);
if (status != B_OK) {
TRACE(("can't probe mouse\n"));
goto err1;
}
cookie->mouse_buffer = create_packet_buffer(MOUSE_HISTORY_SIZE * cookie->packet_size);
if (cookie->mouse_buffer == NULL) {
TRACE(("can't allocate mouse actions buffer\n")); TRACE(("can't allocate mouse actions buffer\n"));
status = B_NO_MEMORY;
goto err2; goto err2;
} }
// create the mouse semaphore, used for synchronization between // create the mouse semaphore, used for synchronization between
// the interrupt handler and the read operation // the interrupt handler and the read operation
sMouseSem = create_sem(0, "ps2_mouse_sem"); cookie->mouse_sem = create_sem(0, "ps2_mouse_sem");
if (sMouseSem < 0) { if (cookie->mouse_sem < 0) {
TRACE(("failed creating PS/2 mouse semaphore!\n")); TRACE(("failed creating PS/2 mouse semaphore!\n"));
status = sMouseSem;
goto err3; goto err3;
} }
*_cookie = NULL; status = set_mouse_enabled(cookie, true);
status = set_mouse_enabled(true);
if (status < B_OK) { if (status < B_OK) {
TRACE(("mouse_open(): cannot enable PS/2 mouse\n")); TRACE(("mouse_open(): cannot enable PS/2 mouse\n"));
goto err4; goto err4;
} }
release_sem(gDeviceOpenSemaphore); atomic_or(&dev->flags, PS2_FLAG_ENABLED);
TRACE(("mouse_open(): mouse succesfully enabled\n")); TRACE(("mouse_open(): mouse succesfully enabled\n"));
return B_OK; return B_OK;
err4: err4:
delete_sem(sMouseSem); delete_sem(cookie->mouse_sem);
err3: err3:
delete_packet_buffer(sMouseBuffer); delete_packet_buffer(cookie->mouse_buffer);
err2: err2:
free(cookie);
err1: err1:
atomic_and(&sOpenMask, 0); atomic_and(&dev->flags, ~PS2_FLAG_OPEN);
release_sem(gDeviceOpenSemaphore); return B_ERROR;
return status;
} }
status_t status_t
mouse_close(void *cookie) mouse_close(void *_cookie)
{ {
mouse_cookie *cookie = _cookie;
TRACE(("mouse_close()\n")); TRACE(("mouse_close()\n"));
set_mouse_enabled(false); set_mouse_enabled(cookie, false);
delete_packet_buffer(sMouseBuffer); delete_packet_buffer(cookie->mouse_buffer);
delete_sem(sMouseSem); delete_sem(cookie->mouse_sem);
atomic_and(&sOpenMask, 0); atomic_and(&cookie->dev->flags, ~PS2_FLAG_OPEN);
atomic_and(&cookie->dev->flags, ~PS2_FLAG_ENABLED);
return B_OK; return B_OK;
} }
status_t status_t
mouse_freecookie(void *cookie) mouse_freecookie(void *_cookie)
{ {
mouse_cookie *cookie = _cookie;
free(cookie);
return B_OK; return B_OK;
} }
@ -410,20 +436,22 @@ mouse_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
status_t status_t
mouse_ioctl(void *cookie, uint32 op, void *buffer, size_t length) mouse_ioctl(void *_cookie, uint32 op, void *buffer, size_t length)
{ {
mouse_cookie *cookie = _cookie;
switch (op) { switch (op) {
case MS_NUM_EVENTS: case MS_NUM_EVENTS:
{ {
int32 count; int32 count;
TRACE(("MS_NUM_EVENTS\n")); TRACE(("MS_NUM_EVENTS\n"));
get_sem_count(sMouseSem, &count); get_sem_count(cookie->mouse_sem, &count);
return count; return count;
} }
case MS_READ: case MS_READ:
TRACE(("MS_READ\n")); TRACE(("MS_READ\n"));
return mouse_read_event((mouse_movement *)buffer); return mouse_read_event(cookie, (mouse_movement *)buffer);
case MS_SET_TYPE: case MS_SET_TYPE:
TRACE(("MS_SET_TYPE not implemented\n")); TRACE(("MS_SET_TYPE not implemented\n"));
@ -443,7 +471,7 @@ mouse_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
case MS_SET_CLICKSPEED: case MS_SET_CLICKSPEED:
TRACE(("MS_SETCLICK (set click speed)\n")); TRACE(("MS_SETCLICK (set click speed)\n"));
return user_memcpy(&sClickSpeed, buffer, sizeof(bigtime_t)); return user_memcpy(&cookie->click_speed, buffer, sizeof(bigtime_t));
default: default:
TRACE(("unknown opcode: %ld\n", op)); TRACE(("unknown opcode: %ld\n", op));