Warning, file /plasma/wacomtablet/src/kded/x11tabletfinder.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * This file is part of the KDE wacomtablet project. For copyright 0003 * information and license terms see the AUTHORS and COPYING files 0004 * in the top-level directory of this distribution. 0005 * 0006 * This program is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU General Public License as 0008 * published by the Free Software Foundation; either version 2 of 0009 * the License, or (at your option) any later version. 0010 * 0011 * This program is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0014 * GNU General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU General Public License 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "x11tabletfinder.h" 0021 0022 #include "deviceinformation.h" 0023 #include "logging.h" 0024 #include "x11input.h" 0025 0026 #include <xcb/xcb.h> 0027 0028 #include <QMap> 0029 #include <QString> 0030 0031 #include "private/qtx11extras_p.h" 0032 0033 using namespace Wacom; 0034 0035 /** 0036 * Class for private members. 0037 */ 0038 namespace Wacom 0039 { 0040 class X11TabletFinderPrivate 0041 { 0042 public: 0043 typedef QMap<long, TabletInformation> TabletMap; 0044 0045 TabletMap tabletMap; //!< A map which is used while visiting devices. 0046 QList<TabletInformation> scannedList; //!< A list which is build after scanning all devices. 0047 }; 0048 } 0049 0050 X11TabletFinder::X11TabletFinder() 0051 : d_ptr(new X11TabletFinderPrivate) 0052 { 0053 } 0054 0055 X11TabletFinder::~X11TabletFinder() 0056 { 0057 delete d_ptr; 0058 } 0059 0060 const QList<TabletInformation> &X11TabletFinder::getTablets() const 0061 { 0062 Q_D(const X11TabletFinder); 0063 0064 return d->scannedList; 0065 } 0066 0067 bool X11TabletFinder::scanDevices() 0068 { 0069 Q_D(X11TabletFinder); 0070 0071 d->tabletMap.clear(); 0072 d->scannedList.clear(); 0073 0074 X11Input::scanDevices(*this); 0075 0076 X11TabletFinderPrivate::TabletMap::ConstIterator iter; 0077 0078 for (iter = d->tabletMap.constBegin(); iter != d->tabletMap.constEnd(); ++iter) { 0079 d->scannedList.append(iter.value()); 0080 } 0081 0082 return (d->tabletMap.size() > 0); 0083 } 0084 0085 bool X11TabletFinder::visit(X11InputDevice &x11device) 0086 { 0087 if (!x11device.isTabletDevice()) { 0088 return false; 0089 } 0090 0091 // gather basic device information which we need to create a device information structure 0092 QString deviceName = x11device.getName(); 0093 const DeviceType *deviceType = getDeviceType(getToolType(x11device)); 0094 0095 if (deviceName.isEmpty() || deviceType == nullptr) { 0096 qCWarning(KDED) << QString::fromLatin1("Unsupported device '%1' detected!").arg(deviceName); 0097 return false; 0098 } 0099 0100 // create device information and gather all information we can 0101 DeviceInformation deviceInfo(*deviceType, x11device.getName()); 0102 0103 gatherDeviceInformation(x11device, deviceInfo); 0104 0105 // add device information to tablet map 0106 addDeviceInformation(deviceInfo); 0107 0108 // true is only returned if device visiting should be aborted by X11Input 0109 return false; 0110 } 0111 0112 void X11TabletFinder::addDeviceInformation(DeviceInformation &deviceInformation) 0113 { 0114 Q_D(X11TabletFinder); 0115 0116 long serial = deviceInformation.getTabletSerial(); 0117 0118 if (serial < 1) { 0119 qCDebug(KDED) << QString::fromLatin1("Device '%1' has an invalid serial number '%2'!").arg(deviceInformation.getName()).arg(serial); 0120 } 0121 0122 X11TabletFinderPrivate::TabletMap::iterator mapIter = d->tabletMap.find(serial); 0123 0124 if (mapIter == d->tabletMap.end()) { 0125 auto newTabletInformation = TabletInformation(serial); 0126 // LibWacom needs CompanyId so set it too 0127 newTabletInformation.set(TabletInfo::CompanyId, QString::fromLatin1("%1").arg(deviceInformation.getVendorId(), 4, 16, QLatin1Char('0')).toUpper()); 0128 mapIter = d->tabletMap.insert(serial, newTabletInformation); 0129 } 0130 0131 mapIter.value().setDevice(deviceInformation); 0132 } 0133 0134 void X11TabletFinder::gatherDeviceInformation(X11InputDevice &device, DeviceInformation &deviceInformation) const 0135 { 0136 // get X11 device id 0137 deviceInformation.setDeviceId(device.getDeviceId()); 0138 0139 // get tablet serial 0140 deviceInformation.setTabletSerial(getTabletSerial(device)); 0141 0142 // get product and vendor id if set 0143 long vendorId = 0, productId = 0; 0144 0145 if (getProductId(device, vendorId, productId)) { 0146 deviceInformation.setVendorId(vendorId); 0147 deviceInformation.setProductId(productId); 0148 } 0149 0150 // get the device node which is the full path to the input device 0151 deviceInformation.setDeviceNode(getDeviceNode(device)); 0152 } 0153 0154 const QString X11TabletFinder::getDeviceNode(X11InputDevice &device) const 0155 { 0156 QList<QString> values; 0157 0158 if (!device.getStringProperty(X11Input::PROPERTY_DEVICE_NODE, values, 1000) || values.size() == 0) { 0159 qCDebug(KDED) << QString::fromLatin1("Could not get device node from device '%1'!").arg(device.getName()); 0160 return QString(); 0161 } 0162 0163 return values.at(0); 0164 } 0165 0166 const DeviceType *X11TabletFinder::getDeviceType(const QString &toolType) const 0167 { 0168 if (toolType.contains(QLatin1String("pad"), Qt::CaseInsensitive)) { 0169 return &(DeviceType::Pad); 0170 0171 } else if (toolType.contains(QLatin1String("eraser"), Qt::CaseInsensitive)) { 0172 return &(DeviceType::Eraser); 0173 0174 } else if (toolType.contains(QLatin1String("cursor"), Qt::CaseInsensitive)) { 0175 return &(DeviceType::Cursor); 0176 0177 } else if (toolType.contains(QLatin1String("touch"), Qt::CaseInsensitive)) { 0178 return &(DeviceType::Touch); 0179 0180 } else if (toolType.contains(QLatin1String("stylus"), Qt::CaseInsensitive)) { 0181 return &(DeviceType::Stylus); 0182 } 0183 0184 return nullptr; 0185 } 0186 0187 bool X11TabletFinder::getProductId(X11InputDevice &device, long int &vendorId, long int &productId) const 0188 { 0189 QList<long> values; 0190 0191 if (!device.getLongProperty(X11Input::PROPERTY_DEVICE_PRODUCT_ID, values, 2)) { 0192 return false; 0193 } 0194 0195 if (values.size() != 2) { 0196 qCWarning(KDED) << QString::fromLatin1("Unexpected number of values when fetching XInput property '%1'!").arg(X11Input::PROPERTY_DEVICE_PRODUCT_ID); 0197 return false; 0198 } 0199 0200 long value; 0201 0202 if ((value = values.at(0)) > 0) { 0203 vendorId = value; 0204 } 0205 0206 if ((value = values.at(1)) > 0) { 0207 productId = value; 0208 } 0209 0210 return true; 0211 } 0212 0213 long int X11TabletFinder::getTabletSerial(X11InputDevice &device) const 0214 { 0215 long tabletId = 0; 0216 QList<long> serialIdValues; 0217 0218 if (!device.getLongProperty(X11Input::PROPERTY_WACOM_SERIAL_IDS, serialIdValues, 1000)) { 0219 return tabletId; 0220 } 0221 0222 // the offset for the tablet id is 0 see wacom-properties.h in the xf86-input-wacom driver for more information on this 0223 if (serialIdValues.size() > 0) { 0224 tabletId = serialIdValues.at(0); 0225 0226 if (tabletId > 0) { 0227 return tabletId; 0228 } 0229 } 0230 0231 return tabletId; 0232 } 0233 0234 const QString X11TabletFinder::getToolType(X11InputDevice &device) const 0235 { 0236 QList<long> toolTypeAtoms; 0237 0238 if (!device.getAtomProperty(X11Input::PROPERTY_WACOM_TOOL_TYPE, toolTypeAtoms)) { 0239 return QString(); 0240 } 0241 0242 QString toolTypeName; 0243 0244 if (toolTypeAtoms.size() == 1) { 0245 xcb_get_atom_name_cookie_t cookie = xcb_get_atom_name(QX11Info::connection(), toolTypeAtoms.at(0)); 0246 xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(QX11Info::connection(), cookie, nullptr); 0247 if (reply) { 0248 toolTypeName = QString::fromLatin1(QByteArray(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply))); 0249 free(reply); 0250 } 0251 } 0252 0253 return toolTypeName; 0254 }