4
* Copyright (C) 2004 Brad Hards <bradh@frogmouth.net>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
#include <QPushButton>
24
#include <QtGui/QProgressBar>
30
#include <kmessagebox.h>
32
#include <config-workspace.h>
33
#include <config-kcontrol-input.h>
37
#include "logitechmouse.h"
39
LogitechMouse::LogitechMouse( struct usb_device *usbDev, int mouseCapabilityFlags, QWidget* parent, const char* name )
40
: LogitechMouseBase( parent )
44
setObjectName( "LogitechMouse" );
46
cordlessNameLabel->setText( i18n("Mouse type: %1", objectName() ) );
48
m_mouseCapabilityFlags = mouseCapabilityFlags;
50
m_usbDeviceHandle = usb_open( usbDev );
52
if ( !m_usbDeviceHandle ) {
53
kWarning() << "Error opening usbfs file: " << usb_strerror() ;
57
if ( mouseCapabilityFlags & USE_CH2 ) {
58
m_useSecondChannel = 0x0100;
60
m_useSecondChannel = 0x0000;
63
permissionProblemText->hide();
65
if ( mouseCapabilityFlags & HAS_RES ) {
67
resolutionSelector->setEnabled( true );
69
connect( button400cpi, SIGNAL( clicked() ), parent, SLOT( changed() ) );
70
connect( button800cpi, SIGNAL( clicked() ), parent, SLOT( changed() ) );
72
if ( 4 == resolution() ) {
73
button800cpi->setChecked( true );
74
} else if ( 3 == resolution() ) {
75
button400cpi->setChecked( true );
77
// it must have failed, try to help out
78
resolutionSelector->setEnabled(false);
79
permissionProblemText->show();
83
if ( mouseCapabilityFlags & HAS_CSR ) {
85
initCordlessStatusReporting();
88
cordlessNameLabel->setText( i18n("Mouse type: %1", cordlessName() ) );
89
cordlessNameLabel->setEnabled( true );
91
// Display the battery power level - the level gets updated in updateGUI()
92
batteryBox->setEnabled( true );
95
channelSelector->setEnabled( true );
96
// if the channel is changed, we need to turn off the timer, otherwise it
97
// just resets the button to reflect the current status. The timer is
98
// started again when we applyChanges()
99
connect( channel1, SIGNAL( clicked() ), this, SLOT( stopTimerForNow() ) );
100
connect( channel1, SIGNAL( clicked() ), parent, SLOT( changed() ) );
101
if ( isDualChannelCapable() ) {
102
channel2->setEnabled( true );
103
connect( channel2, SIGNAL( clicked() ), this, SLOT( stopTimerForNow() ) );
104
connect( channel2, SIGNAL( clicked() ), parent, SLOT( changed() ) );
112
LogitechMouse::~LogitechMouse()
114
if ( m_usbDeviceHandle )
115
usb_close( m_usbDeviceHandle );
118
void LogitechMouse::initCordlessStatusReporting()
120
updateCordlessStatus();
121
doUpdate = new QTimer( this ); // will be automatically deleted
122
connect( doUpdate, SIGNAL( timeout() ), this, SLOT( updateGUI() ) );
123
doUpdate->start( 20000 );
126
void LogitechMouse::updateCordlessStatus()
128
QByteArray status(8, '\0');
132
if ( m_usbDeviceHandle )
133
result = usb_control_msg( m_usbDeviceHandle,
134
USB_TYPE_VENDOR | USB_ENDPOINT_IN,0x09,
135
(0x0003 | m_useSecondChannel),
136
(0x0000 | m_useSecondChannel),
142
// We probably have a permission problem
144
channelSelector->setEnabled( false );
145
batteryBox->setEnabled( false );
146
cordlessNameLabel->hide();
147
permissionProblemText->show();
149
// kDebug() << "P6 (connect status): " << (status[0] & 0xFF);
150
if ( status[0] & 0x20 ) { // mouse is talking
151
m_connectStatus = ( status[0] & 0x80 );
152
m_mousePowerup = ( status[0] & 0x40 );
153
m_receiverUnlock = ( status[0] & 0x10 );
154
m_waitLock = ( status[0] & 0x08 );
157
// kDebug() << "P0 (receiver type): " << (status[1] & 0xFF);
167
m_cordlessNameIndex = (status[2] & 0xFF);
169
m_batteryLevel = (status[3] & 0x07 );
170
if ( status[3] & 0x08 ) {
176
m_cordlessSecurity = ( ( status[4] ) & ( status[5] << 8 ) );
178
m_caseShape = ( status[6] & 0x7F );
180
// kDebug() << "PB1 (device Capabilities): " << (status[7] & 0xFF);
181
m_numberOfButtons = 2 + ( status[7] & 0x07 ); // 9 means something more than 8
182
m_twoChannelCapable = ( status[7] & 0x40 );
183
m_verticalRoller = ( status[7] & 0x08 );
184
m_horizontalRoller = ( status[7] & 0x10 );
185
m_has800cpi = ( status[7] & 0x20 );
190
void LogitechMouse::updateGUI()
192
updateCordlessStatus();
194
batteryBar->setValue( batteryLevel() );
196
if ( isDualChannelCapable() ) {
197
if ( 2 == channel() ) {
198
channel2->setChecked( true );
199
} else if ( 1 == channel() ) {
200
channel1->setChecked( true );
201
} // else it might have failed - we don't do anything
205
void LogitechMouse::stopTimerForNow()
210
void LogitechMouse::applyChanges()
212
if ( m_mouseCapabilityFlags & HAS_RES ) {
213
if ( ( resolution() == 4 ) && ( button400cpi->isChecked() ) ) {
214
// then we are in 800cpi mode, but want 400cpi
216
} else if ( ( resolution() == 3 ) && (button800cpi->isChecked() ) ) {
217
// then we are in 400 cpi mode, but want 800 cpi
222
if ( isDualChannelCapable() ) {
223
if ( ( channel() == 2 ) && ( channel1->isChecked() ) ) {
224
// we are on channel 2, but want channel 1
226
KMessageBox::information(this, i18n("RF channel 1 has been set. Please press Connect button on mouse to re-establish link"), i18n("Press Connect Button") );
227
} else if ( ( channel() == 1 ) && ( channel2->isChecked() ) ) {
228
// we are on channel 1, but want channel 2
230
KMessageBox::information(this, i18n("RF channel 2 has been set. Please press Connect button on mouse to re-establish link"), i18n("Press Connect Button") );
233
initCordlessStatusReporting();
237
void LogitechMouse::save(KConfig * /*config*/)
239
kDebug() << "Logitech mouse settings not saved - not implemented yet";
242
quint8 LogitechMouse::resolution()
244
// kDebug() << "resolution: " << m_resolution;
245
if ( 0 == m_resolution ) {
251
void LogitechMouse::updateResolution()
257
if ( m_usbDeviceHandle )
258
result = usb_control_msg( m_usbDeviceHandle,
259
USB_TYPE_VENDOR | USB_ENDPOINT_IN,
267
// kDebug() << "resolution is: " << resolution;
269
kWarning() << "Error getting resolution from device : " << usb_strerror() ;
272
m_resolution = resolution;
276
void LogitechMouse::setLogitechTo800()
278
int result = usb_control_msg( m_usbDeviceHandle,
287
kWarning() << "Error setting resolution on device: " << usb_strerror() ;
291
void LogitechMouse::setLogitechTo400()
293
int result = usb_control_msg( m_usbDeviceHandle,
302
kWarning() << "Error setting resolution on device: " << usb_strerror() ;
306
quint8 LogitechMouse::batteryLevel() const
308
return m_batteryLevel;
312
quint8 LogitechMouse::channel() const
317
bool LogitechMouse::isDualChannelCapable() const
319
return m_twoChannelCapable;
322
void LogitechMouse::setChannel1()
324
int result = usb_control_msg( m_usbDeviceHandle,
327
(0x0008 | m_useSecondChannel),
328
(0x0000 | m_useSecondChannel),
334
kWarning() << "Error setting mouse to channel 1 : " << usb_strerror() ;
339
void LogitechMouse::setChannel2()
341
int result = usb_control_msg( m_usbDeviceHandle,
344
(0x0008 | m_useSecondChannel),
345
(0x0001 | m_useSecondChannel),
351
kWarning() << "Error setting mouse to channel 2 : " << usb_strerror() ;
356
QString LogitechMouse::cordlessName() const
358
switch ( m_cordlessNameIndex ) {
360
return i18nc( "no cordless mouse", "none" );
363
return i18n( "Cordless Mouse" );
366
return i18n( "Cordless Wheel Mouse" );
369
return i18n( "Cordless MouseMan Wheel" );
372
return i18n( "Cordless Wheel Mouse" );
375
return i18n( "Cordless Wheel Mouse" );
378
return i18n( "Cordless TrackMan Wheel" );
381
return i18n( "TrackMan Live" );
384
return i18n( "Cordless TrackMan FX" );
387
return i18n( "Cordless MouseMan Optical" );
390
return i18n( "Cordless Optical Mouse" );
393
return i18n( "Cordless Mouse" );
396
return i18n( "Cordless MouseMan Optical (2ch)" );
399
return i18n( "Cordless Optical Mouse (2ch)" );
402
return i18n( "Cordless Mouse (2ch)" );
405
return i18n( "Cordless Optical TrackMan" );
408
return i18n( "MX700 Cordless Optical Mouse" );
411
return i18n( "MX700 Cordless Optical Mouse (2ch)" );
414
return i18n( "Unknown mouse");
418
#include "logitechmouse.moc"