1 /* This file is part of Clementine. 2 Copyright 2010, David Sansome <me@davidsansome.com> 3 4 Clementine is free software: you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 Clementine is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with Clementine. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #include "mtpconnection.h" 19 #include "core/logging.h" 20 21 #include <QRegExp> 22 #include <QtDebug> 23 #include <QUrlQuery> 24 MtpConnection(const QUrl & url)25MtpConnection::MtpConnection(const QUrl& url) : device_(nullptr) { 26 QString hostname = url.host(); 27 // Parse the URL 28 QRegExp host_re("^usb-(\\d+)-(\\d+)$"); 29 30 unsigned int bus_location; 31 unsigned int device_num; 32 33 QUrlQuery url_query(url); 34 35 if (host_re.indexIn(hostname) >= 0) { 36 bus_location = host_re.cap(1).toUInt(); 37 device_num = host_re.cap(2).toUInt(); 38 } else if (url_query.hasQueryItem("busnum")) { 39 bus_location = url_query.queryItemValue("busnum").toUInt(); 40 device_num = url_query.queryItemValue("devnum").toUInt(); 41 } else { 42 qLog(Warning) << "Invalid MTP device:" << hostname; 43 return; 44 } 45 46 if (url_query.hasQueryItem("vendor")) { 47 LIBMTP_raw_device_t* raw_device = 48 (LIBMTP_raw_device_t*)malloc(sizeof(LIBMTP_raw_device_t)); 49 raw_device->device_entry.vendor = 50 url_query.queryItemValue("vendor").toLatin1().data(); 51 raw_device->device_entry.product = 52 url_query.queryItemValue("product").toLatin1().data(); 53 raw_device->device_entry.vendor_id = 54 url_query.queryItemValue("vendor_id").toUShort(); 55 raw_device->device_entry.product_id = 56 url_query.queryItemValue("product_id").toUShort(); 57 raw_device->device_entry.device_flags = 58 url_query.queryItemValue("quirks").toUInt(); 59 60 raw_device->bus_location = bus_location; 61 raw_device->devnum = device_num; 62 63 device_ = LIBMTP_Open_Raw_Device(raw_device); 64 return; 65 } 66 67 // Get a list of devices from libmtp and figure out which one is ours 68 int count = 0; 69 LIBMTP_raw_device_t* raw_devices = nullptr; 70 LIBMTP_error_number_t err = LIBMTP_Detect_Raw_Devices(&raw_devices, &count); 71 if (err != LIBMTP_ERROR_NONE) { 72 qLog(Warning) << "MTP error:" << err; 73 return; 74 } 75 76 LIBMTP_raw_device_t* raw_device = nullptr; 77 for (int i = 0; i < count; ++i) { 78 if (raw_devices[i].bus_location == bus_location && 79 raw_devices[i].devnum == device_num) { 80 raw_device = &raw_devices[i]; 81 break; 82 } 83 } 84 85 if (!raw_device) { 86 qLog(Warning) << "MTP device not found"; 87 free(raw_devices); 88 return; 89 } 90 91 // Connect to the device 92 device_ = LIBMTP_Open_Raw_Device(raw_device); 93 94 free(raw_devices); 95 } 96 ~MtpConnection()97MtpConnection::~MtpConnection() { 98 if (device_) LIBMTP_Release_Device(device_); 99 } 100