/* * scribiu -- read notebooks and voice memos from Livescribe pens * Copyright (C) 2015 Javier S. Pedro * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include "smartpenmanager.h" SmartpenManager::SmartpenManager(QObject *parent) : QObject(parent), _udev(udev_new()), _monitor(udev_monitor_new_from_netlink(_udev, "udev")), _notifier(new QSocketNotifier(udev_monitor_get_fd(_monitor), QSocketNotifier::Read)) { udev_monitor_filter_add_match_tag(_monitor, "livescribe-pen"); connect(_notifier, SIGNAL(activated(int)), SLOT(handleMonitorActivity())); udev_monitor_enable_receiving(_monitor); udev_enumerate *scan = udev_enumerate_new(_udev); udev_enumerate_add_match_tag(scan, "livescribe-pen"); if (udev_enumerate_scan_devices(scan) == 0) { udev_list_entry *l = udev_enumerate_get_list_entry(scan), *i; udev_list_entry_foreach(i, l) { const char *path = udev_list_entry_get_name(i); udev_device *dev = udev_device_new_from_syspath(_udev, path); processDevice(dev); udev_device_unref(dev); } } else { qWarning() << "Failed to scan for devices"; } udev_enumerate_unref(scan); } SmartpenManager::~SmartpenManager() { delete _notifier; udev_monitor_unref(_monitor); udev_unref(_udev); } QStringList SmartpenManager::pensBeingSynchronized() const { QStringList pens; pens.reserve(_syncers.size()); for (QMap::const_iterator it = _syncers.begin(); it != _syncers.end(); ++it) { QString name = it.value()->penName(); if (name.isEmpty()) { Smartpen::Address addr = it.value()->penAddress(); name = QString("%1-%2").arg(addr.first).arg(addr.second); } pens.append(name); } return pens; } void SmartpenManager::handleMonitorActivity() { qDebug() << "udev activity"; udev_device *dev = udev_monitor_receive_device(_monitor); if (dev) { const char *action = udev_device_get_action(dev); if (action && strcmp(action, "add") == 0) { processDevice(dev); } udev_device_unref(dev); } } void SmartpenManager::handleSyncerFinished() { SmartpenSyncer *syncer = static_cast(sender()); Smartpen::Address addr = syncer->penAddress(); qDebug() << "Finished synchronization with pen with address:" << addr; _syncers.remove(addr); emit pensBeingSynchronizedChanged(); if (syncer->hasErrors()) { qWarning() << "Synchronization with address" << addr << "failed"; emit syncFailed(syncer->penName()); } else { emit syncComplete(syncer->penName()); } syncer->deleteLater(); } void SmartpenManager::processDevice(udev_device *dev) { uint busnum = atol(udev_device_get_sysattr_value(dev, "busnum")); uint devnum = atol(udev_device_get_sysattr_value(dev, "devnum")); Smartpen::Address addr(busnum, devnum); if (!_syncers.contains(addr)) { SmartpenSyncer *syncer = new SmartpenSyncer(addr, this); _syncers.insert(addr, syncer); connect(syncer, SIGNAL(finished()), SLOT(handleSyncerFinished())); connect(syncer, SIGNAL(penNameChanged()), SIGNAL(pensBeingSynchronizedChanged())); syncer->start(); emit pensBeingSynchronizedChanged(); } }