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
)
43 setObjectName( "LogitechMouse" );
45 cordlessNameLabel
->setText( i18n("Mouse type: %1", objectName() ) );
47 m_mouseCapabilityFlags
= mouseCapabilityFlags
;
49 m_usbDeviceHandle
= usb_open( usbDev
);
51 if ( !m_usbDeviceHandle
) {
52 kWarning() << "Error opening usbfs file: " << usb_strerror() ;
56 if ( mouseCapabilityFlags
& USE_CH2
) {
57 m_useSecondChannel
= 0x0100;
59 m_useSecondChannel
= 0x0000;
62 permissionProblemText
->hide();
64 if ( mouseCapabilityFlags
& HAS_RES
) {
66 resolutionSelector
->setEnabled( true );
68 connect( button400cpi
, SIGNAL( clicked() ), parent
, SLOT( changed() ) );
69 connect( button800cpi
, SIGNAL( clicked() ), parent
, SLOT( changed() ) );
71 if ( 4 == resolution() ) {
72 button800cpi
->setChecked( true );
73 } else if ( 3 == resolution() ) {
74 button400cpi
->setChecked( true );
76 // it must have failed, try to help out
77 resolutionSelector
->setEnabled(false);
78 permissionProblemText
->show();
82 if ( mouseCapabilityFlags
& HAS_CSR
) {
84 initCordlessStatusReporting();
87 cordlessNameLabel
->setText( i18n("Mouse type: %1", cordlessName() ) );
88 cordlessNameLabel
->setEnabled( true );
90 // Display the battery power level - the level gets updated in updateGUI()
91 batteryBox
->setEnabled( true );
94 channelSelector
->setEnabled( true );
95 // if the channel is changed, we need to turn off the timer, otherwise it
96 // just resets the button to reflect the current status. The timer is
97 // started again when we applyChanges()
98 connect( channel1
, SIGNAL( clicked() ), this, SLOT( stopTimerForNow() ) );
99 connect( channel1
, SIGNAL( clicked() ), parent
, SLOT( changed() ) );
100 if ( isDualChannelCapable() ) {
101 channel2
->setEnabled( true );
102 connect( channel2
, SIGNAL( clicked() ), this, SLOT( stopTimerForNow() ) );
103 connect( channel2
, SIGNAL( clicked() ), parent
, SLOT( changed() ) );
111 LogitechMouse::~LogitechMouse()
113 usb_close( m_usbDeviceHandle
);
116 void LogitechMouse::initCordlessStatusReporting()
118 updateCordlessStatus();
119 doUpdate
= new QTimer( this ); // will be automatically deleted
120 connect( doUpdate
, SIGNAL( timeout() ), this, SLOT( updateGUI() ) );
121 doUpdate
->start( 20000 );
124 void LogitechMouse::updateCordlessStatus()
126 QByteArray
status(8, '\0');
128 int result
= usb_control_msg( m_usbDeviceHandle
,
129 USB_TYPE_VENDOR
| USB_ENDPOINT_IN
,0x09,
130 (0x0003 | m_useSecondChannel
),
131 (0x0000 | m_useSecondChannel
),
137 // We probably have a permission problem
138 channelSelector
->setEnabled( false );
139 batteryBox
->setEnabled( false );
140 cordlessNameLabel
->hide();
141 permissionProblemText
->show();
143 // kDebug() << "P6 (connect status): " << (status[0] & 0xFF);
144 if ( status
[0] & 0x20 ) { // mouse is talking
145 m_connectStatus
= ( status
[0] & 0x80 );
146 m_mousePowerup
= ( status
[0] & 0x40 );
147 m_receiverUnlock
= ( status
[0] & 0x10 );
148 m_waitLock
= ( status
[0] & 0x08 );
151 // kDebug() << "P0 (receiver type): " << (status[1] & 0xFF);
161 m_cordlessNameIndex
= (status
[2] & 0xFF);
163 m_batteryLevel
= (status
[3] & 0x07 );
164 if ( status
[3] & 0x08 ) {
170 m_cordlessSecurity
= ( ( status
[4] ) & ( status
[5] << 8 ) );
172 m_caseShape
= ( status
[6] & 0x7F );
174 // kDebug() << "PB1 (device Capabilities): " << (status[7] & 0xFF);
175 m_numberOfButtons
= 2 + ( status
[7] & 0x07 ); // 9 means something more than 8
176 m_twoChannelCapable
= ( status
[7] & 0x40 );
177 m_verticalRoller
= ( status
[7] & 0x08 );
178 m_horizontalRoller
= ( status
[7] & 0x10 );
179 m_has800cpi
= ( status
[7] & 0x20 );
184 void LogitechMouse::updateGUI()
186 updateCordlessStatus();
188 batteryBar
->setValue( batteryLevel() );
190 if ( isDualChannelCapable() ) {
191 if ( 2 == channel() ) {
192 channel2
->setChecked( true );
193 } else if ( 1 == channel() ) {
194 channel1
->setChecked( true );
195 } // else it might have failed - we don't do anything
199 void LogitechMouse::stopTimerForNow()
204 void LogitechMouse::applyChanges()
206 if ( m_mouseCapabilityFlags
& HAS_RES
) {
207 if ( ( resolution() == 4 ) && ( button400cpi
->isChecked() ) ) {
208 // then we are in 800cpi mode, but want 400cpi
210 } else if ( ( resolution() == 3 ) && (button800cpi
->isChecked() ) ) {
211 // then we are in 400 cpi mode, but want 800 cpi
216 if ( isDualChannelCapable() ) {
217 if ( ( channel() == 2 ) && ( channel1
->isChecked() ) ) {
218 // we are on channel 2, but want channel 1
220 KMessageBox::information(this, i18n("RF channel 1 has been set. Please press Connect button on mouse to re-establish link"), i18n("Press Connect Button") );
221 } else if ( ( channel() == 1 ) && ( channel2
->isChecked() ) ) {
222 // we are on channel 1, but want channel 2
224 KMessageBox::information(this, i18n("RF channel 2 has been set. Please press Connect button on mouse to re-establish link"), i18n("Press Connect Button") );
227 initCordlessStatusReporting();
231 void LogitechMouse::save(KConfig
* /*config*/)
233 kDebug() << "Logitech mouse settings not saved - not implemented yet";
236 quint8
LogitechMouse::resolution()
238 // kDebug() << "resolution: " << m_resolution;
239 if ( 0 == m_resolution
) {
245 void LogitechMouse::updateResolution()
249 int result
= usb_control_msg( m_usbDeviceHandle
,
250 USB_TYPE_VENDOR
| USB_ENDPOINT_IN
,
258 // kDebug() << "resolution is: " << resolution;
260 kWarning() << "Error getting resolution from device : " << usb_strerror() ;
263 m_resolution
= resolution
;
267 void LogitechMouse::setLogitechTo800()
269 int result
= usb_control_msg( m_usbDeviceHandle
,
278 kWarning() << "Error setting resolution on device: " << usb_strerror() ;
282 void LogitechMouse::setLogitechTo400()
284 int result
= usb_control_msg( m_usbDeviceHandle
,
293 kWarning() << "Error setting resolution on device: " << usb_strerror() ;
297 quint8
LogitechMouse::batteryLevel()
299 return m_batteryLevel
;
303 quint8
LogitechMouse::channel()
308 bool LogitechMouse::isDualChannelCapable()
310 return m_twoChannelCapable
;
313 void LogitechMouse::setChannel1()
315 int result
= usb_control_msg( m_usbDeviceHandle
,
318 (0x0008 | m_useSecondChannel
),
319 (0x0000 | m_useSecondChannel
),
325 kWarning() << "Error setting mouse to channel 1 : " << usb_strerror() ;
330 void LogitechMouse::setChannel2()
332 int result
= usb_control_msg( m_usbDeviceHandle
,
335 (0x0008 | m_useSecondChannel
),
336 (0x0001 | m_useSecondChannel
),
342 kWarning() << "Error setting mouse to channel 2 : " << usb_strerror() ;
347 QString
LogitechMouse::cordlessName()
349 switch ( m_cordlessNameIndex
) {
351 return i18n( "none" );
354 return i18n( "Cordless Mouse" );
357 return i18n( "Cordless Wheel Mouse" );
360 return i18n( "Cordless MouseMan Wheel" );
363 return i18n( "Cordless Wheel Mouse" );
366 return i18n( "Cordless Wheel Mouse" );
369 return i18n( "Cordless TrackMan Wheel" );
372 return i18n( "TrackMan Live" );
375 return i18n( "Cordless TrackMan FX" );
378 return i18n( "Cordless MouseMan Optical" );
381 return i18n( "Cordless Optical Mouse" );
384 return i18n( "Cordless Mouse" );
387 return i18n( "Cordless MouseMan Optical (2ch)" );
390 return i18n( "Cordless Optical Mouse (2ch)" );
393 return i18n( "Cordless Mouse (2ch)" );
396 return i18n( "Cordless Optical TrackMan" );
399 return i18n( "MX700 Cordless Optical Mouse" );
402 return i18n( "MX700 Cordless Optical Mouse (2ch)" );
405 return i18n( "Unknown mouse");
409 #include "logitechmouse.moc"