mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Linux MTP driver: Detect devices that have MTP interfaces even if their USB ids are not known
This commit is contained in:
parent
4c09d25062
commit
251a057a53
@ -13,7 +13,7 @@ from collections import namedtuple
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from calibre import prints, as_unicode
|
from calibre import prints, as_unicode
|
||||||
from calibre.constants import plugins
|
from calibre.constants import plugins, islinux
|
||||||
from calibre.ptempfile import SpooledTemporaryFile
|
from calibre.ptempfile import SpooledTemporaryFile
|
||||||
from calibre.devices.errors import OpenFailed, DeviceError, BlacklistedDevice
|
from calibre.devices.errors import OpenFailed, DeviceError, BlacklistedDevice
|
||||||
from calibre.devices.mtp.base import MTPDeviceBase, synchronous, debug
|
from calibre.devices.mtp.base import MTPDeviceBase, synchronous, debug
|
||||||
@ -44,6 +44,17 @@ class MTP_DEVICE(MTPDeviceBase):
|
|||||||
self.blacklisted_devices = set()
|
self.blacklisted_devices = set()
|
||||||
self.ejected_devices = set()
|
self.ejected_devices = set()
|
||||||
self.currently_connected_dev = None
|
self.currently_connected_dev = None
|
||||||
|
self._is_device_mtp = None
|
||||||
|
if islinux:
|
||||||
|
from calibre.devices.mtp.unix.sysfs import MTPDetect
|
||||||
|
self._is_device_mtp = MTPDetect()
|
||||||
|
|
||||||
|
def is_device_mtp(self, d, debug=None):
|
||||||
|
''' Returns True iff the _is_device_mtp check returns True and libmtp
|
||||||
|
is able to probe the device successfully. '''
|
||||||
|
if self._is_device_mtp is None: return False
|
||||||
|
return (self._is_device_mtp(d, debug=debug) and
|
||||||
|
self.libmtp.is_mtp_device(d.busnum, d.devnum))
|
||||||
|
|
||||||
def set_debug_level(self, lvl):
|
def set_debug_level(self, lvl):
|
||||||
self.libmtp.set_debug_level(lvl)
|
self.libmtp.set_debug_level(lvl)
|
||||||
@ -77,7 +88,9 @@ class MTP_DEVICE(MTPDeviceBase):
|
|||||||
for d in devs:
|
for d in devs:
|
||||||
ans = cache.get(d, None)
|
ans = cache.get(d, None)
|
||||||
if ans is None:
|
if ans is None:
|
||||||
ans = (d.vendor_id, d.product_id) in self.known_devices
|
ans = (
|
||||||
|
(d.vendor_id, d.product_id) in self.known_devices or
|
||||||
|
self.is_device_mtp(d))
|
||||||
cache[d] = ans
|
cache[d] = ans
|
||||||
if ans:
|
if ans:
|
||||||
return d
|
return d
|
||||||
@ -95,12 +108,13 @@ class MTP_DEVICE(MTPDeviceBase):
|
|||||||
err = 'startup() not called on this device driver'
|
err = 'startup() not called on this device driver'
|
||||||
p(err)
|
p(err)
|
||||||
return False
|
return False
|
||||||
devs = [d for d in devices_on_system if (d.vendor_id, d.product_id)
|
devs = [d for d in devices_on_system if
|
||||||
in self.known_devices and d.vendor_id != APPLE]
|
( (d.vendor_id, d.product_id) in self.known_devices or
|
||||||
|
self.is_device_mtp(d, debug=p)) and d.vendor_id != APPLE]
|
||||||
if not devs:
|
if not devs:
|
||||||
p('No known MTP devices connected to system')
|
p('No MTP devices connected to system')
|
||||||
return False
|
return False
|
||||||
p('Known MTP devices connected:')
|
p('MTP devices connected:')
|
||||||
for d in devs: p(d)
|
for d in devs: p(d)
|
||||||
|
|
||||||
for d in devs:
|
for d in devs:
|
||||||
|
@ -662,13 +662,6 @@ is_mtp_device(PyObject *self, PyObject *args) {
|
|||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "ii", &busnum, &devnum)) return NULL;
|
if (!PyArg_ParseTuple(args, "ii", &busnum, &devnum)) return NULL;
|
||||||
|
|
||||||
/*
|
|
||||||
* LIBMTP_Check_Specific_Device does not seem to work at least on my linux
|
|
||||||
* system. Need to investigate why later. Most devices are in the device
|
|
||||||
* table so this is not terribly important.
|
|
||||||
*/
|
|
||||||
/* LIBMTP_Set_Debug(LIBMTP_DEBUG_ALL); */
|
|
||||||
/* printf("Calling check: %d %d\n", busnum, devnum); */
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
ans = LIBMTP_Check_Specific_Device(busnum, devnum);
|
ans = LIBMTP_Check_Specific_Device(busnum, devnum);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
|
53
src/calibre/devices/mtp/unix/sysfs.py
Normal file
53
src/calibre/devices/mtp/unix/sysfs.py
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai
|
||||||
|
from __future__ import (unicode_literals, division, absolute_import,
|
||||||
|
print_function)
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2013, Kovid Goyal <kovid at kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
import os, glob
|
||||||
|
|
||||||
|
class MTPDetect(object):
|
||||||
|
|
||||||
|
SYSFS_PATH = os.environ.get('SYSFS_PATH', '/sys')
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.base = os.path.join(self.SYSFS_PATH, 'subsystem', 'usb', 'devices')
|
||||||
|
if not os.path.exists(self.base):
|
||||||
|
self.base = os.path.join(self.SYSFS_PATH, 'bus', 'usb', 'devices')
|
||||||
|
self.ok = os.path.exists(self.base)
|
||||||
|
|
||||||
|
def __call__(self, dev, debug=None):
|
||||||
|
'''
|
||||||
|
Check if the device has an interface named "MTP" using sysfs, which
|
||||||
|
avoids probing the device.
|
||||||
|
'''
|
||||||
|
if not self.ok: return False
|
||||||
|
|
||||||
|
def read(x):
|
||||||
|
try:
|
||||||
|
with open(x, 'rb') as f:
|
||||||
|
return f.read()
|
||||||
|
except EnvironmentError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
ipath = os.path.join(self.base, '{0}-*/{0}-*/interface'.format(dev.busnum))
|
||||||
|
for x in glob.glob(ipath):
|
||||||
|
raw = read(x)
|
||||||
|
if not raw or raw.strip() != b'MTP': continue
|
||||||
|
raw = read(os.path.join(os.path.dirname(os.path.dirname(x)),
|
||||||
|
'devnum'))
|
||||||
|
try:
|
||||||
|
if raw and int(raw) == dev.devnum:
|
||||||
|
if debug is not None:
|
||||||
|
debug('Unknown device {0} claims to be an MTP device'
|
||||||
|
.format(dev))
|
||||||
|
return True
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
continue
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user