Check in the serial mouse addon before I forget about it (hmmm holidays...).
Should be cleaned up a bit and maybe merged with the "other" mouse addon. Courtesy of Oscar Lesta aka BiPolar git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10246 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
e7a9dbff59
commit
4e8891d152
@ -0,0 +1,390 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
// Mouse input server device addon
|
||||||
|
// Written by Stefano Ceccherini
|
||||||
|
// Adapted for serial mice by Oscar Lesta
|
||||||
|
//
|
||||||
|
// MouseInputDevice.cpp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 Haiku Project
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included
|
||||||
|
// in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#include "MouseInputDevice.h"
|
||||||
|
#include "kb_mouse_settings.h"
|
||||||
|
#include "kb_mouse_driver.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <Debug.h>
|
||||||
|
#include <Directory.h>
|
||||||
|
#include <Entry.h>
|
||||||
|
#include <NodeMonitor.h>
|
||||||
|
#include <Path.h>
|
||||||
|
#include <String.h>
|
||||||
|
|
||||||
|
#include "SerialMouse.h"
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
inline void LOG(const char *fmt, ...) { char buf[1024]; va_list ap; va_start(ap, fmt); vsprintf(buf, fmt, ap); va_end(ap); \
|
||||||
|
fputs(buf, MouseInputDevice::sLogFile); fflush(MouseInputDevice::sLogFile); }
|
||||||
|
#define LOG_ERR(text...) LOG(text)
|
||||||
|
FILE *MouseInputDevice::sLogFile = NULL;
|
||||||
|
#else
|
||||||
|
#define LOG(text...)
|
||||||
|
#define LOG_ERR(text...) fprintf(stderr, text)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CALLED() LOG("%s\n", __PRETTY_FUNCTION__)
|
||||||
|
|
||||||
|
static MouseInputDevice *sSingletonMouseDevice = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
const static uint32 kMouseThreadPriority = B_FIRST_REAL_TIME_PRIORITY + 4;
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
struct mouse_device {
|
||||||
|
mouse_device();
|
||||||
|
~mouse_device();
|
||||||
|
|
||||||
|
status_t init_check(); // > 0 if a mouse was detected.
|
||||||
|
|
||||||
|
input_device_ref device_ref;
|
||||||
|
SerialMouse* sm;
|
||||||
|
thread_id device_watcher;
|
||||||
|
mouse_settings settings;
|
||||||
|
bool active;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
BInputServerDevice* instantiate_input_device()
|
||||||
|
{
|
||||||
|
return new MouseInputDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
MouseInputDevice::MouseInputDevice()
|
||||||
|
{
|
||||||
|
ASSERT(sSingletonMouseDevice == NULL);
|
||||||
|
sSingletonMouseDevice = this;
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
sLogFile = fopen("/var/log/serial_mouse.log", "w");
|
||||||
|
#endif
|
||||||
|
CALLED();
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseInputDevice::~MouseInputDevice()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
for (int32 i = 0; i < fDevices.CountItems(); i++)
|
||||||
|
delete (mouse_device*) fDevices.ItemAt(i);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
fclose(sLogFile);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// SerialMouse does not know anything about mouse_settings, I choose to let
|
||||||
|
// mouse_device hold that instead (bercause mice type, button mapping,
|
||||||
|
// speed/accel, etc., are all handled here, not in SerialMouse).
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MouseInputDevice::InitFromSettings(void* cookie, uint32 opcode)
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
mouse_device* device = (mouse_device*) cookie;
|
||||||
|
|
||||||
|
// retrieve current values.
|
||||||
|
// TODO: shouldn't we use sane values if we get errors here?
|
||||||
|
|
||||||
|
if (get_mouse_map(&device->settings.map) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_map\n");
|
||||||
|
|
||||||
|
if (get_click_speed(&device->settings.click_speed) != B_OK)
|
||||||
|
LOG_ERR("error when get_click_speed\n");
|
||||||
|
|
||||||
|
if (get_mouse_speed(&device->settings.accel.speed) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_speed\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (get_mouse_acceleration(&device->settings.accel.accel_factor) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_acceleration\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (get_mouse_type(&device->settings.type) != B_OK)
|
||||||
|
LOG_ERR("error when get_mouse_type\n");
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MouseInputDevice::InitCheck()
|
||||||
|
{
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
// TODO: We should iterate here to support more than just one mouse.
|
||||||
|
// (I've tried, but kept entering and endless loop or crashing
|
||||||
|
// the input_server :-( ).
|
||||||
|
|
||||||
|
mouse_device* device = new mouse_device();
|
||||||
|
if (!device)
|
||||||
|
{
|
||||||
|
LOG("No memory\n");
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (device->init_check() <= B_OK)
|
||||||
|
{
|
||||||
|
LOG("The mouse was eaten by a rabid cat.\n");
|
||||||
|
delete device;
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
input_device_ref* devices[2];
|
||||||
|
devices[0] = &device->device_ref;
|
||||||
|
devices[1] = NULL;
|
||||||
|
|
||||||
|
fDevices.AddItem(device);
|
||||||
|
|
||||||
|
return RegisterDevices(devices);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MouseInputDevice::Start(const char* name, void* cookie)
|
||||||
|
{
|
||||||
|
mouse_device* device = (mouse_device*) cookie;
|
||||||
|
|
||||||
|
LOG("%s(%s)\n", __PRETTY_FUNCTION__, name);
|
||||||
|
|
||||||
|
InitFromSettings(device);
|
||||||
|
|
||||||
|
char threadName[B_OS_NAME_LENGTH];
|
||||||
|
// "Microsoft watcher" sounded even more akward than this...
|
||||||
|
snprintf(threadName, B_OS_NAME_LENGTH, "%s Mouse", name);
|
||||||
|
|
||||||
|
device->active = true;
|
||||||
|
device->device_watcher = spawn_thread(DeviceWatcher, threadName,
|
||||||
|
kMouseThreadPriority, device);
|
||||||
|
|
||||||
|
resume_thread(device->device_watcher);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MouseInputDevice::Stop(const char* name, void* cookie)
|
||||||
|
{
|
||||||
|
mouse_device* device = (mouse_device*) cookie;
|
||||||
|
|
||||||
|
LOG("%s(%s)\n", __PRETTY_FUNCTION__, name);
|
||||||
|
|
||||||
|
device->active = false;
|
||||||
|
|
||||||
|
if (device->device_watcher >= 0)
|
||||||
|
{
|
||||||
|
suspend_thread(device->device_watcher);
|
||||||
|
resume_thread(device->device_watcher);
|
||||||
|
status_t dummy;
|
||||||
|
wait_for_thread(device->device_watcher, &dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
MouseInputDevice::Control(const char* name, void* cookie,
|
||||||
|
uint32 command, BMessage* message)
|
||||||
|
{
|
||||||
|
LOG("%s(%s, code: %lu)\n", __PRETTY_FUNCTION__, name, command);
|
||||||
|
|
||||||
|
if (command >= B_MOUSE_TYPE_CHANGED &&
|
||||||
|
command <= B_MOUSE_ACCELERATION_CHANGED)
|
||||||
|
{
|
||||||
|
InitFromSettings(cookie, command);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
MouseInputDevice::DeviceWatcher(void* arg)
|
||||||
|
{
|
||||||
|
mouse_device* dev = (mouse_device*) arg;
|
||||||
|
|
||||||
|
mouse_movement movements;
|
||||||
|
uint32 buttons_state = 0;
|
||||||
|
uint8 clicks_count = 0;
|
||||||
|
bigtime_t last_click_time = 0;
|
||||||
|
BMessage* message;
|
||||||
|
|
||||||
|
CALLED();
|
||||||
|
|
||||||
|
while (dev->active)
|
||||||
|
{
|
||||||
|
memset(&movements, 0, sizeof(movements));
|
||||||
|
|
||||||
|
if (dev->sm->GetMouseEvent(&movements) < B_OK)
|
||||||
|
continue;
|
||||||
|
/*
|
||||||
|
LOG("%s: buttons: 0x%lx, x: %ld, y: %ld, clicks:%ld, wheel_x:%ld, \
|
||||||
|
wheel_y:%ld\n", dev->device_ref.name, movements.buttons,
|
||||||
|
movements.xdelta, movements.ydelta, movements.clicks,
|
||||||
|
movements.wheel_xdelta, movements.wheel_ydelta);
|
||||||
|
*/
|
||||||
|
// TODO: Apply buttons mapping here.
|
||||||
|
uint32 buttons = buttons_state ^ movements.buttons;
|
||||||
|
|
||||||
|
if (movements.buttons) {
|
||||||
|
|
||||||
|
if ((movements.timestamp - last_click_time) <= dev->settings.click_speed)
|
||||||
|
clicks_count = (clicks_count % 3) + 1;
|
||||||
|
else
|
||||||
|
clicks_count = 1;
|
||||||
|
|
||||||
|
last_click_time = movements.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttons != 0) {
|
||||||
|
message = new BMessage(B_MOUSE_UP);
|
||||||
|
|
||||||
|
message->AddInt64("when", movements.timestamp);
|
||||||
|
message->AddInt32("buttons", movements.buttons);
|
||||||
|
|
||||||
|
if ((buttons & movements.buttons) > 0) {
|
||||||
|
message->what = B_MOUSE_DOWN;
|
||||||
|
message->AddInt32("clicks", clicks_count);
|
||||||
|
LOG("B_MOUSE_DOWN\n");
|
||||||
|
} else {
|
||||||
|
LOG("B_MOUSE_UP\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
message->AddInt32("x", movements.xdelta);
|
||||||
|
message->AddInt32("y", movements.ydelta);
|
||||||
|
|
||||||
|
sSingletonMouseDevice->EnqueueMessage(message);
|
||||||
|
buttons_state = movements.buttons;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movements.xdelta != 0 || movements.ydelta != 0) {
|
||||||
|
int32 xdelta = movements.xdelta;
|
||||||
|
int32 ydelta = movements.ydelta;
|
||||||
|
|
||||||
|
// TODO: properly scale these values.
|
||||||
|
// (s >> 14, a >> 8) or (s >> 15, a >> 11) feels more or less OK
|
||||||
|
// with the default values: yields to speed = 2; accel_factor = 32
|
||||||
|
// Maybe we should use floats and then round to nearest integer?
|
||||||
|
uint32 speed = (dev->settings.accel.speed >> 15);
|
||||||
|
uint32 accel_factor = (dev->settings.accel.accel_factor >> 11);
|
||||||
|
|
||||||
|
// LOG("accel.enabled? = %s\n", (dev->settings.accel.enabled) ? "Yes" : "No");
|
||||||
|
// LOG("speed = %ld; accel_factor = %ld\n", speed, accel_factor);
|
||||||
|
|
||||||
|
if (speed && accel_factor) {
|
||||||
|
xdelta *= speed;
|
||||||
|
ydelta *= speed;
|
||||||
|
|
||||||
|
// preserve the sign.
|
||||||
|
bool xneg = (xdelta < 0);
|
||||||
|
bool yneg = (ydelta < 0);
|
||||||
|
|
||||||
|
if (movements.xdelta != 0) {
|
||||||
|
xdelta = (xdelta * xdelta) / accel_factor;
|
||||||
|
(xdelta) ? : (xdelta = 1);
|
||||||
|
if (xneg) xdelta *= -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (movements.ydelta != 0) {
|
||||||
|
ydelta = (ydelta * ydelta) / accel_factor;
|
||||||
|
(ydelta) ? : (ydelta = 1);
|
||||||
|
if (yneg) ydelta *= -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LOG("%s: x: %ld, y: %ld\n", dev->device_ref.name, xdelta, ydelta);
|
||||||
|
|
||||||
|
message = new BMessage(B_MOUSE_MOVED);
|
||||||
|
if (message) {
|
||||||
|
message->AddInt64("when", movements.timestamp);
|
||||||
|
message->AddInt32("buttons", movements.buttons);
|
||||||
|
message->AddInt32("x", xdelta);
|
||||||
|
message->AddInt32("y", ydelta);
|
||||||
|
|
||||||
|
sSingletonMouseDevice->EnqueueMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((movements.wheel_ydelta != 0) || (movements.wheel_xdelta != 0)) {
|
||||||
|
message = new BMessage(B_MOUSE_WHEEL_CHANGED);
|
||||||
|
if (message) {
|
||||||
|
message->AddInt64("when", movements.timestamp);
|
||||||
|
message->AddFloat("be:wheel_delta_x", movements.wheel_xdelta);
|
||||||
|
message->AddFloat("be:wheel_delta_y", movements.wheel_ydelta);
|
||||||
|
|
||||||
|
sSingletonMouseDevice->EnqueueMessage(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// mouse_device
|
||||||
|
mouse_device::mouse_device()
|
||||||
|
{
|
||||||
|
device_watcher = -1;
|
||||||
|
active = false;
|
||||||
|
sm = new SerialMouse();
|
||||||
|
device_ref.type = B_POINTING_DEVICE;
|
||||||
|
device_ref.cookie = this;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
mouse_device::init_check()
|
||||||
|
{
|
||||||
|
status_t result = sm->IsMousePresent();
|
||||||
|
|
||||||
|
if (result > 0) // Positive values indicate a mouse present.
|
||||||
|
device_ref.name = (char *)sm->MouseDescription();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mouse_device::~mouse_device()
|
||||||
|
{
|
||||||
|
delete sm;
|
||||||
|
free(device_ref.name);
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
// Mouse input server device addon
|
||||||
|
// Written by Stefano Ceccherini and Jerome Duval
|
||||||
|
// Adapted for serial mice by Oscar Lesta
|
||||||
|
//
|
||||||
|
// MouseInputDevice.h
|
||||||
|
//
|
||||||
|
// Copyright (c) 2004 Haiku Project
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included
|
||||||
|
// in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||||
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __MOUSEINPUTDEVICE_H
|
||||||
|
#define __MOUSEINPUTDEVICE_H
|
||||||
|
|
||||||
|
#include <InputServerDevice.h>
|
||||||
|
#include <InterfaceDefs.h>
|
||||||
|
#include <List.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
class MouseInputDevice : public BInputServerDevice {
|
||||||
|
public:
|
||||||
|
MouseInputDevice();
|
||||||
|
~MouseInputDevice();
|
||||||
|
|
||||||
|
virtual status_t InitCheck();
|
||||||
|
|
||||||
|
virtual status_t Start(const char* name, void* cookie);
|
||||||
|
virtual status_t Stop(const char* name, void* cookie);
|
||||||
|
|
||||||
|
virtual status_t Control(const char *name, void* cookie,
|
||||||
|
uint32 command, BMessage* message);
|
||||||
|
private:
|
||||||
|
status_t InitFromSettings(void* cookie, uint32 opcode = 0);
|
||||||
|
|
||||||
|
static int32 DeviceWatcher(void* arg);
|
||||||
|
|
||||||
|
BList fDevices;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
public:
|
||||||
|
static FILE *sLogFile;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
extern "C" BInputServerDevice *instantiate_input_device();
|
||||||
|
|
||||||
|
#endif
|
486
src/add-ons/input_server/devices/serial_mouse/SerialMouse.cpp
Normal file
486
src/add-ons/input_server/devices/serial_mouse/SerialMouse.cpp
Normal file
@ -0,0 +1,486 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2004, Haiku, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
// File Name: SerialMouse.cpp
|
||||||
|
// Author(s): Oscar Lesta (bipolar@softhome.net)
|
||||||
|
// Description: SerialMouse detects and manages serial mice, duh!.
|
||||||
|
// References: - http://www.hut.fi/~then/mytexts/mouse.html
|
||||||
|
// - Be's (binary) serial_mouse addon.
|
||||||
|
// - Haiku's CVS.
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <SerialPort.h>
|
||||||
|
|
||||||
|
#include "SerialMouse.h"
|
||||||
|
|
||||||
|
//#define DEBUG_SERIAL_MOUSE
|
||||||
|
#ifdef DEBUG_SERIAL_MOUSE
|
||||||
|
#include <stdio.h>
|
||||||
|
#define LOG(x) printf x // TODO: log to "MouseInputDevice::sLogFile"
|
||||||
|
// I used this in my console tests.
|
||||||
|
#else
|
||||||
|
#define LOG(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const static bigtime_t kSerialTimeOut = 200000; // 200 ms
|
||||||
|
const static uint8 kMaxBytesToRead = 255; // Serial PnP data can be this long.
|
||||||
|
|
||||||
|
// The protocols we know how to handle. Indexed by mouse_protocol_id.
|
||||||
|
/*
|
||||||
|
the sync[] is a protocol-identification/sync thingy:
|
||||||
|
|
||||||
|
if ((read_byte[0] & sync[0]) == sync[1]) then we are at the beggining of the
|
||||||
|
a packet. Next data bytes are OK... if ((read_byte[i] & sync[2]) == 0))
|
||||||
|
*/
|
||||||
|
struct mouse_protocol {
|
||||||
|
const char* name;
|
||||||
|
uint8 num_bytes;
|
||||||
|
uint8 sync[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const static
|
||||||
|
struct mouse_protocol mp[] = {
|
||||||
|
{ "UNKNOWN", 0, { 0x00, 0x00, 0x00 } },
|
||||||
|
{ "Microsoft", 3, { 0x40, 0x40, 0x40,} },
|
||||||
|
{ "Logitech", 3, { 0x40, 0x40, 0x40 } }, // 3/4 bytes. FIX: only 3 are used now.
|
||||||
|
{ "MouseSystems", 5, { 0xF8, 0x80, 0x00 } },
|
||||||
|
{ "IntelliMouse", 4, { 0x40, 0x40, 0x00 } },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
SerialMouse::SerialMouse()
|
||||||
|
: fSerialPort(NULL),
|
||||||
|
fPortsCount(0),
|
||||||
|
fPortNumber(0),
|
||||||
|
fMouseID(kNotSet),
|
||||||
|
fButtonsState(0)
|
||||||
|
{
|
||||||
|
fSerialPort = new BSerialPort();
|
||||||
|
fPortsCount = fSerialPort->CountDevices() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SerialMouse::~SerialMouse()
|
||||||
|
{
|
||||||
|
if (fSerialPort != NULL) {
|
||||||
|
fSerialPort->SetRTS(false); // Put the mouse to sleep.
|
||||||
|
fSerialPort->Close();
|
||||||
|
delete fSerialPort;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
const char *
|
||||||
|
SerialMouse::MouseDescription()
|
||||||
|
{
|
||||||
|
// TODO: If we'll support more than just one mouse, this should be changed.
|
||||||
|
// Maybe we should also add the port number as suffix.
|
||||||
|
|
||||||
|
return mp[fMouseID].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Find first usable serial port, try to detect a mouse there.
|
||||||
|
// Returns:
|
||||||
|
// - B_NO_INIT: all available ports were tested (no mouse present there).
|
||||||
|
// - A positive value indicating in which serial port a mouse was found.
|
||||||
|
|
||||||
|
status_t
|
||||||
|
SerialMouse::IsMousePresent()
|
||||||
|
{
|
||||||
|
for (uint8 i = 1; i <= fPortsCount; i++) {
|
||||||
|
char dev_name[B_PATH_NAME_LENGTH];
|
||||||
|
|
||||||
|
fSerialPort->GetDeviceName(i, dev_name);
|
||||||
|
|
||||||
|
// Skip internal modem (pctel, lucent or trimodem drivers).
|
||||||
|
// previously I checked only for != "pctel", now for == "serial#"
|
||||||
|
if (strncmp(dev_name, "serial", 5) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (fSerialPort->Open(dev_name) <= 0) {
|
||||||
|
LOG(("SerialMouse: Failed to open %s.\n", dev_name));
|
||||||
|
continue; // try next port.
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(("SerialMouse : Opened %s.\n", dev_name));
|
||||||
|
|
||||||
|
// This 4x retries helps, a little, to detect one of my mouse (buggy?).
|
||||||
|
// Not perfect, but catchs it more often than before.
|
||||||
|
uint8 retries = 4;
|
||||||
|
do {
|
||||||
|
fMouseID = DetectMouse();
|
||||||
|
if (fMouseID > kNotSet) {
|
||||||
|
// We found a mouse, just break the loop.
|
||||||
|
LOG(("SerialMouse: Found a %s Mouse.\n", MouseDescription()));
|
||||||
|
fSerialPort->SetBlocking(true);
|
||||||
|
fPortNumber = i;
|
||||||
|
return fPortNumber; // Return the port # in use.
|
||||||
|
}
|
||||||
|
} while ((fMouseID == kUnknown) && (retries--));
|
||||||
|
|
||||||
|
LOG(("SerialMouse: Mouse not detected.\n"));
|
||||||
|
fSerialPort->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here its because we didn't found a mouse in any of the
|
||||||
|
// available serial ports.
|
||||||
|
// (Caller can do: "while (sm->IsMousePresent() > 0)").
|
||||||
|
|
||||||
|
return B_NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mouse_id
|
||||||
|
SerialMouse::DetectMouse()
|
||||||
|
{
|
||||||
|
int bytes_read = 0;
|
||||||
|
char c;
|
||||||
|
char id_buffer[20]; // If the mouse sends an ID, we store it here.
|
||||||
|
char buffer[kMaxBytesToRead];
|
||||||
|
uint8 id_length = 0;
|
||||||
|
|
||||||
|
fSerialPort->SetBlocking(false);
|
||||||
|
fSerialPort->SetTimeout(kSerialTimeOut);
|
||||||
|
|
||||||
|
SetPortOptions();
|
||||||
|
|
||||||
|
snooze(10000);
|
||||||
|
|
||||||
|
// Toggle RTS line in order to 'wake up' the mouse
|
||||||
|
fSerialPort->SetRTS(false);
|
||||||
|
snooze(120000); // RTS low pulse width must be at least 100ms.
|
||||||
|
fSerialPort->ClearInput();
|
||||||
|
fSerialPort->SetRTS(true);
|
||||||
|
|
||||||
|
// wait upto kSerialTimeOut ms while trying to read mouse ID string.
|
||||||
|
if (fSerialPort->WaitForInput() == 0)
|
||||||
|
return kNoDevice; // nothing there, quit.
|
||||||
|
|
||||||
|
// we make sure to 'eat' everything the mouse sends at init time, albeit
|
||||||
|
// we are interested only on the few first bytes, not doing it so will
|
||||||
|
// confuse things later.
|
||||||
|
while ((fSerialPort->Read(&c, 1) == 1) && (bytes_read < kMaxBytesToRead)) {
|
||||||
|
LOG(("read = %c (%d d - %x h)\n", c, c, c));
|
||||||
|
|
||||||
|
// Collect the bytes we care about.
|
||||||
|
if (c == 'M' || c == 'H' || c == '3' || c == 'Z' || c == '@') {
|
||||||
|
if (id_length < 4) {
|
||||||
|
id_buffer[id_length] = c;
|
||||||
|
id_length++;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
buffer[bytes_read] = c; // store the garbage for futher processing.
|
||||||
|
|
||||||
|
bytes_read++;
|
||||||
|
|
||||||
|
// is there something else waiting to be read?
|
||||||
|
if (fSerialPort->WaitForInput() == 0)
|
||||||
|
break; // no, break the loop.
|
||||||
|
}
|
||||||
|
|
||||||
|
// This can't happen, but... if we didn't get any data, just quit.
|
||||||
|
if (bytes_read == 0)
|
||||||
|
return kNoDevice;
|
||||||
|
|
||||||
|
fSerialPort->ClearInput(); // Toldya, I have a very noisy mouse.
|
||||||
|
|
||||||
|
if (id_length) {
|
||||||
|
fMouseID = ParseID(id_buffer, id_length);
|
||||||
|
SetPortOptions(); // Set new options according to MouseID.
|
||||||
|
return fMouseID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Below this line is work in progress (ie. temporal hacks until I,
|
||||||
|
// or someone else, get something better).
|
||||||
|
|
||||||
|
// Ok, last resort... try to identify the beast according to its packets.
|
||||||
|
|
||||||
|
if (bytes_read < 3) // not enough data to even start... quit.
|
||||||
|
return kUnknown;
|
||||||
|
|
||||||
|
// First attempt to identify a MouseSystems mouse, because some (most?) of
|
||||||
|
// them either send: nothing, an standard packet or just garbage.
|
||||||
|
if (bytes_read == 5) {
|
||||||
|
// TODO: validate the packet!
|
||||||
|
fMouseID = kMouseSystems;
|
||||||
|
SetPortOptions();
|
||||||
|
return fMouseID;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// See if we recognize the mouse ID (first bytes mice usually send after
|
||||||
|
// toggling the DTR/RTS lines on the serial port). Usual values:
|
||||||
|
//
|
||||||
|
// Microsoft mode = 'M'
|
||||||
|
// Microsoft mode = 'M3'
|
||||||
|
// IntelliMouse mode = 'MZ' and a valid 4-bytes null packet (0x40,0,0,0)
|
||||||
|
// MouseSystems mode = 'HH', nothing at all, 5-bytes packet, or just garbage.
|
||||||
|
|
||||||
|
mouse_id
|
||||||
|
SerialMouse::ParseID(char buffer[], uint8 length)
|
||||||
|
{
|
||||||
|
LOG(("data length = $d\n", length));
|
||||||
|
|
||||||
|
if ((length == 1) && (buffer[0] == 'M'))
|
||||||
|
return kMicrosoft;
|
||||||
|
|
||||||
|
if (length == 2) {
|
||||||
|
if (buffer[0] == 'M' && buffer[1] == '3')
|
||||||
|
return kLogitech;
|
||||||
|
else if (buffer[0] == 'H' && buffer[1] == 'H')
|
||||||
|
return kMouseSystems;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((length == 4) &&
|
||||||
|
(buffer[0] == 'M' && buffer[1] == 'Z') && (buffer[2] == '@'))
|
||||||
|
return kIntelliMouse;
|
||||||
|
|
||||||
|
return kUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Set serial port options according to our different needs.
|
||||||
|
status_t
|
||||||
|
SerialMouse::SetPortOptions()
|
||||||
|
{
|
||||||
|
switch (fMouseID) {
|
||||||
|
case kLogitech:
|
||||||
|
fSerialPort->SetDataRate(B_1200_BPS);
|
||||||
|
fSerialPort->Write("*q", 2);
|
||||||
|
fSerialPort->SetDataRate(B_9600_BPS);
|
||||||
|
fSerialPort->SetDataBits(B_DATA_BITS_7);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMouseSystems:
|
||||||
|
fSerialPort->SetDataRate(B_1200_BPS);
|
||||||
|
fSerialPort->SetDataBits(B_DATA_BITS_8);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kNotSet:
|
||||||
|
default:
|
||||||
|
// other defaults values are ok for us: no parity, 1 stop bit.
|
||||||
|
fSerialPort->SetDataRate(B_1200_BPS);
|
||||||
|
fSerialPort->SetDataBits(B_DATA_BITS_7);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
status_t
|
||||||
|
SerialMouse::GetMouseEvent(mouse_movement* mm)
|
||||||
|
{
|
||||||
|
char data[5];
|
||||||
|
|
||||||
|
if (fMouseID <= kNotSet)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
|
if (GetPacket(data) != B_OK)
|
||||||
|
return B_ERROR; // not enough, or out-of-sync, data.
|
||||||
|
|
||||||
|
if (PacketToMM(data, mm) != B_OK) {
|
||||||
|
// Something went wrong, clean up.
|
||||||
|
memset(mm, 0, sizeof(mouse_movement));
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG_SERIAL_MOUSE
|
||||||
|
DumpData(mm);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
// Block until we read enough bytes for the current protocol. See if we're in
|
||||||
|
// sync with data stream, if not, just skip data until we regain sync.
|
||||||
|
|
||||||
|
// TODO: syncronization needs a re-write. We should keep track of what byte we
|
||||||
|
// are currently working on, validate it against mice's protocol, and if valid,
|
||||||
|
// increment a "current_packet_byte" counter.
|
||||||
|
// Also: I'm currently skipping the optional 4th byte in the Logitech protocol.
|
||||||
|
// (may work, but 3th button will not).
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
SerialMouse::GetPacket(char data[])
|
||||||
|
{
|
||||||
|
status_t result = B_ERROR;
|
||||||
|
uchar c = 0;
|
||||||
|
uint8 bytes_read;
|
||||||
|
size_t mpsize = mp[fMouseID].num_bytes;
|
||||||
|
|
||||||
|
for (bytes_read = 0; bytes_read < mpsize; bytes_read++) {
|
||||||
|
// TODO: Shall we block here instead of leaving after a timeout?
|
||||||
|
// Yes, if we get called it's because there IS a mouse out there.
|
||||||
|
|
||||||
|
if (fSerialPort->Read(&c, 1) != 1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (bytes_read == 0) {
|
||||||
|
if ((c & mp[fMouseID].sync[0]) != mp[fMouseID].sync[1]) {
|
||||||
|
LOG(("Out of sync: skipping byte = %x\n", c));
|
||||||
|
continue; // skip bytes until we get a "header" byte.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data[bytes_read] = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bytes_read == mpsize) {
|
||||||
|
result = B_OK;
|
||||||
|
|
||||||
|
// validate data...
|
||||||
|
for (uint8 i = 1; i <= mpsize; i++) {
|
||||||
|
if ((data[i] & mp[fMouseID].sync[2]) != 0) {
|
||||||
|
LOG(("Out of sync: wrong data byte = %x\n", data[i]));
|
||||||
|
result = B_ERROR;
|
||||||
|
break; // skip the packet.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// kMicroSoft, kMouseSystem, kIntelliMouse: working OK.
|
||||||
|
// kLogitech: untested by lack of such devices. 3th button probably won't work.
|
||||||
|
status_t
|
||||||
|
SerialMouse::PacketToMM(char data[], mouse_movement* mm)
|
||||||
|
{
|
||||||
|
const uint8 kPrimaryButton = 1;
|
||||||
|
const uint8 kSecondaryButton = 2;
|
||||||
|
const uint8 kTertiaryButton = 4;
|
||||||
|
|
||||||
|
static uint8 previous_buttons = 0; // only meaningful for kMicrosoft.
|
||||||
|
|
||||||
|
mm->timestamp = system_time();
|
||||||
|
|
||||||
|
switch (fMouseID) {
|
||||||
|
case kMicrosoft:
|
||||||
|
mm->buttons = ((data[0] & 0x20) ? kPrimaryButton : 0) +
|
||||||
|
((data[0] & 0x10) ? kSecondaryButton : 0);
|
||||||
|
|
||||||
|
// Higher 2 bits Lower 6 bits
|
||||||
|
mm->xdelta = (int8) (((data[0] & 0x03) << 6) + (data[1] & 0x3F));
|
||||||
|
mm->ydelta = - (int8) (((data[0] & 0x0C) << 4) + (data[2] & 0x3F));
|
||||||
|
|
||||||
|
// up to here we've handled "ye olde" 2-buttons MS packet.
|
||||||
|
// There's a 3-buttons extension to it, consisting in sending a
|
||||||
|
// "null packet" (no changes in x/y nor in standard buttons)
|
||||||
|
// whenever the third button is pressed/released (how clever!! :-P).
|
||||||
|
|
||||||
|
if ((mm->xdelta == 0) && (mm->ydelta == 0) &&
|
||||||
|
((uint8) mm->buttons == (previous_buttons & ~kTertiaryButton))) {
|
||||||
|
// no movement, nor button change: toggle middle
|
||||||
|
mm->buttons = previous_buttons ^ kTertiaryButton;
|
||||||
|
} else {
|
||||||
|
// change: preserve middle
|
||||||
|
mm->buttons |= previous_buttons & kTertiaryButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
previous_buttons = mm->buttons;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kIntelliMouse:
|
||||||
|
// TODO: add support for 4th and 5th buttons?
|
||||||
|
mm->buttons = ((data[0] & 0x20) ? kPrimaryButton : 0) +
|
||||||
|
((data[0] & 0x10) ? kSecondaryButton : 0) +
|
||||||
|
((data[3] & 0x10) ? kTertiaryButton : 0);
|
||||||
|
|
||||||
|
mm->xdelta = ((int8) ((data[0] & 0x03) << 6) + (int8) (data[1] & 0x3F));
|
||||||
|
mm->ydelta = - ((int8) ((data[0] & 0x0C) << 4) + (int8) (data[2] & 0x3F));
|
||||||
|
|
||||||
|
switch (data[3] & 0x0F) {
|
||||||
|
case 0x1: mm->wheel_ydelta = +1; break; // wheel 1 down
|
||||||
|
case 0xF: mm->wheel_ydelta = -1; break; // wheel 1 up
|
||||||
|
case 0x2: mm->wheel_xdelta = +1; break; // wheel 2 down
|
||||||
|
case 0xE: mm->wheel_xdelta = -1; break; // wheel 2 up
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kMouseSystems:
|
||||||
|
{
|
||||||
|
uint8 tmp = (~data[0] & 0x07);
|
||||||
|
|
||||||
|
mm->buttons = ((tmp & 0x4) ? kPrimaryButton : 0) +
|
||||||
|
((tmp & 0x1) ? kSecondaryButton : 0) +
|
||||||
|
((tmp & 0x2) ? kTertiaryButton : 0);
|
||||||
|
|
||||||
|
mm->xdelta = ((int8) data[1] + (int8) data[3]);
|
||||||
|
mm->ydelta = ((int8) data[2] + (int8) data[4]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case kLogitech:
|
||||||
|
{
|
||||||
|
// uint8 tmp = (data[3] & 0x20); // 3th button bit.
|
||||||
|
|
||||||
|
mm->buttons = ((data[0] & 0x20) ? kPrimaryButton : 0) +
|
||||||
|
((data[0] & 0x10) ? kSecondaryButton : 0);
|
||||||
|
// + ((tmp) ? kTertiaryButton : 0);
|
||||||
|
|
||||||
|
// Higher 2 bits Lower 6 bits
|
||||||
|
mm->xdelta = (int8) (((data[0] & 0x03) << 6) + (data[1] & 0x3F));
|
||||||
|
mm->ydelta = - (int8) (((data[0] & 0x0C) << 4) + (data[2] & 0x3F));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
LOG(("Unhandled protocol. Should not happen.\n"));
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
SerialMouse::DumpData(mouse_movement* mm)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_SERIAL_MOUSE
|
||||||
|
if (mm->buttons ^ fButtonsState)
|
||||||
|
LOG(("Buttons = %ld\n", mm->buttons));
|
||||||
|
|
||||||
|
if (mm->xdelta || mm->ydelta)
|
||||||
|
LOG(("xdelta = %ld; ydelta = %ld\n", mm->xdelta, mm->ydelta));
|
||||||
|
|
||||||
|
if (fMouseID == kIntelliMouse && (mm->wheel_xdelta || mm->wheel_xdelta)) {
|
||||||
|
LOG(("wheel_xdelta = %ld; wheel_ydelta = %ld\n", mm->wheel_xdelta,
|
||||||
|
mm->wheel_ydelta));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
46
src/add-ons/input_server/devices/serial_mouse/SerialMouse.h
Normal file
46
src/add-ons/input_server/devices/serial_mouse/SerialMouse.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#ifndef _SERIAL_MOUSE_
|
||||||
|
#define _SERIAL_MOUSE_
|
||||||
|
|
||||||
|
#include <kb_mouse_driver.h>
|
||||||
|
|
||||||
|
typedef enum mouse_id {
|
||||||
|
kNoDevice = -2,
|
||||||
|
kUnknown = -1, // Something there, but can't recognize it yet.
|
||||||
|
kNotSet = 0,
|
||||||
|
kMicrosoft, // 3-bytes, 2 and 3 buttons.
|
||||||
|
kLogitech, // (3+1)-bytes, 3-buttons.
|
||||||
|
kMouseSystems, // 5-bytes, 3-buttons.
|
||||||
|
kIntelliMouse // 4-bytes, up to 5 buttons, 1 or 2 wheels.
|
||||||
|
};
|
||||||
|
|
||||||
|
class BSerialPort;
|
||||||
|
class SerialMouse {
|
||||||
|
public:
|
||||||
|
SerialMouse();
|
||||||
|
virtual ~SerialMouse();
|
||||||
|
|
||||||
|
status_t IsMousePresent();
|
||||||
|
mouse_id MouseID() { return fMouseID; };
|
||||||
|
const char* MouseDescription();
|
||||||
|
|
||||||
|
status_t GetMouseEvent(mouse_movement* mm);
|
||||||
|
|
||||||
|
private:
|
||||||
|
mouse_id DetectMouse();
|
||||||
|
mouse_id ParseID(char buffer[], uint8 length);
|
||||||
|
status_t SetPortOptions();
|
||||||
|
|
||||||
|
status_t GetPacket(char data[]);
|
||||||
|
status_t PacketToMM(char data[], mouse_movement* mm);
|
||||||
|
|
||||||
|
void DumpData(mouse_movement* mm);
|
||||||
|
|
||||||
|
BSerialPort* fSerialPort;
|
||||||
|
uint8 fPortsCount;
|
||||||
|
uint8 fPortNumber; // The port in use.
|
||||||
|
mouse_id fMouseID;
|
||||||
|
|
||||||
|
uint8 fButtonsState;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _SERIAL_MOUSE_
|
Loading…
Reference in New Issue
Block a user