mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Drop dependency on PyUSB. Version bump.
This commit is contained in:
parent
fbdb293ac0
commit
234750d487
@ -29,7 +29,6 @@ The packet structure used by the SONY Reader USB protocol is defined
|
|||||||
in the module L{prstypes}. The communication logic
|
in the module L{prstypes}. The communication logic
|
||||||
is defined in the module L{communicate}.
|
is defined in the module L{communicate}.
|
||||||
|
|
||||||
This package requires U{PyUSB<http://pyusb.berlios.de/>}.
|
|
||||||
In order to use it as a non-root user on Linux, you should have
|
In order to use it as a non-root user on Linux, you should have
|
||||||
the following rule in C{/etc/udev/rules.d/90-local.rules} ::
|
the following rule in C{/etc/udev/rules.d/90-local.rules} ::
|
||||||
BUS=="usb", SYSFS{idProduct}=="029b", SYSFS{idVendor}=="054c",
|
BUS=="usb", SYSFS{idProduct}=="029b", SYSFS{idVendor}=="054c",
|
||||||
@ -37,6 +36,6 @@ the following rule in C{/etc/udev/rules.d/90-local.rules} ::
|
|||||||
You may have to adjust the GROUP and the location of the rules file to
|
You may have to adjust the GROUP and the location of the rules file to
|
||||||
suit your distribution.
|
suit your distribution.
|
||||||
"""
|
"""
|
||||||
__version__ = "0.3.0"
|
__version__ = "0.3.1"
|
||||||
__docformat__ = "epytext"
|
__docformat__ = "epytext"
|
||||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||||
|
@ -46,13 +46,14 @@ Contains the logic for communication with the device (a SONY PRS-500).
|
|||||||
The public interface of class L{PRS500Device} defines the
|
The public interface of class L{PRS500Device} defines the
|
||||||
methods for performing various tasks.
|
methods for performing various tasks.
|
||||||
"""
|
"""
|
||||||
import usb
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from tempfile import TemporaryFile
|
from tempfile import TemporaryFile
|
||||||
from array import array
|
from array import array
|
||||||
|
|
||||||
|
from libprs500.libusb import Error as USBError
|
||||||
|
from libprs500.libusb import get_device_by_id
|
||||||
from libprs500.prstypes import *
|
from libprs500.prstypes import *
|
||||||
from libprs500.errors import *
|
from libprs500.errors import *
|
||||||
from libprs500.books import BookList, fix_ids
|
from libprs500.books import BookList, fix_ids
|
||||||
@ -115,34 +116,6 @@ class File(object):
|
|||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
class DeviceDescriptor:
|
|
||||||
"""
|
|
||||||
Describes a USB device.
|
|
||||||
|
|
||||||
A description is composed of the Vendor Id, Product Id and Interface Id.
|
|
||||||
See the U{USB spec<http://www.usb.org/developers/docs/usb_20_05122006.zip>}
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, vendor_id, product_id, interface_id) :
|
|
||||||
self.vendor_id = vendor_id
|
|
||||||
self.product_id = product_id
|
|
||||||
self.interface_id = interface_id
|
|
||||||
|
|
||||||
def get_device(self) :
|
|
||||||
"""
|
|
||||||
Return the device corresponding to the device descriptor if it is
|
|
||||||
available on a USB bus. Otherwise, return None. Note that the
|
|
||||||
returned device has yet to be claimed or opened.
|
|
||||||
"""
|
|
||||||
buses = usb.busses()
|
|
||||||
for bus in buses :
|
|
||||||
for device in bus.devices :
|
|
||||||
if device.idVendor == self.vendor_id :
|
|
||||||
if device.idProduct == self.product_id :
|
|
||||||
return device
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class PRS500Device(Device):
|
class PRS500Device(Device):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -154,11 +127,11 @@ class PRS500Device(Device):
|
|||||||
2. Listing of directories. See the C{list} method.
|
2. Listing of directories. See the C{list} method.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
SONY_VENDOR_ID = 0x054c #: SONY Vendor Id
|
VENDOR_ID = 0x054c #: SONY Vendor Id
|
||||||
PRS500_PRODUCT_ID = 0x029b #: Product Id for the PRS-500
|
PRODUCT_ID = 0x029b #: Product Id for the PRS-500
|
||||||
PRS500_INTERFACE_ID = 0 #: The interface we use to talk to the device
|
INTERFACE_ID = 0 #: The interface we use to talk to the device
|
||||||
PRS500_BULK_IN_EP = 0x81 #: Endpoint for Bulk reads
|
BULK_IN_EP = 0x81 #: Endpoint for Bulk reads
|
||||||
PRS500_BULK_OUT_EP = 0x02 #: Endpoint for Bulk writes
|
BULK_OUT_EP = 0x02 #: Endpoint for Bulk writes
|
||||||
# Location of media.xml file on device
|
# Location of media.xml file on device
|
||||||
MEDIA_XML = "/Data/database/cache/media.xml"
|
MEDIA_XML = "/Data/database/cache/media.xml"
|
||||||
# Location of cache.xml on storage card in device
|
# Location of cache.xml on storage card in device
|
||||||
@ -168,13 +141,10 @@ class PRS500Device(Device):
|
|||||||
# Height for thumbnails of books/images on the device
|
# Height for thumbnails of books/images on the device
|
||||||
THUMBNAIL_HEIGHT = 68
|
THUMBNAIL_HEIGHT = 68
|
||||||
|
|
||||||
device_descriptor = DeviceDescriptor(SONY_VENDOR_ID, \
|
|
||||||
PRS500_PRODUCT_ID, PRS500_INTERFACE_ID)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def signature(cls):
|
def signature(cls):
|
||||||
""" Return a two element tuple (vendor id, product id) """
|
""" Return a two element tuple (vendor id, product id) """
|
||||||
return (cls.SONY_VENDOR_ID, cls.PRS500_PRODUCT_ID )
|
return (cls.VENDOR_ID, cls.PRODUCT_ID )
|
||||||
|
|
||||||
def safe(func):
|
def safe(func):
|
||||||
"""
|
"""
|
||||||
@ -202,7 +172,7 @@ class PRS500Device(Device):
|
|||||||
if not kwargs.has_key("end_session") or kwargs["end_session"]:
|
if not kwargs.has_key("end_session") or kwargs["end_session"]:
|
||||||
dev.send_validated_command(EndSession())
|
dev.send_validated_command(EndSession())
|
||||||
raise
|
raise
|
||||||
except usb.USBError, err:
|
except USBError, err:
|
||||||
if "No such device" in str(err):
|
if "No such device" in str(err):
|
||||||
raise DeviceError()
|
raise DeviceError()
|
||||||
elif "Connection timed out" in str(err):
|
elif "Connection timed out" in str(err):
|
||||||
@ -229,8 +199,7 @@ class PRS500Device(Device):
|
|||||||
task does not have any progress information
|
task does not have any progress information
|
||||||
"""
|
"""
|
||||||
Device.__init__(self)
|
Device.__init__(self)
|
||||||
# The actual device (PyUSB object)
|
self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
|
||||||
self.device = self.device_descriptor.get_device()
|
|
||||||
# Handle that is used to communicate with device. Setup in L{open}
|
# Handle that is used to communicate with device. Setup in L{open}
|
||||||
self.handle = None
|
self.handle = None
|
||||||
self.log_packets = log_packets
|
self.log_packets = log_packets
|
||||||
@ -238,7 +207,7 @@ class PRS500Device(Device):
|
|||||||
|
|
||||||
def reconnect(self):
|
def reconnect(self):
|
||||||
""" Only recreates the device node and deleted the connection handle """
|
""" Only recreates the device node and deleted the connection handle """
|
||||||
self.device = self.device_descriptor.get_device()
|
self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
|
||||||
self.handle = None
|
self.handle = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -249,7 +218,7 @@ class PRS500Device(Device):
|
|||||||
software connection. You may need to call L{reconnect} if you keep
|
software connection. You may need to call L{reconnect} if you keep
|
||||||
getting L{DeviceError}.
|
getting L{DeviceError}.
|
||||||
"""
|
"""
|
||||||
return cls.device_descriptor.get_device() != None
|
return get_device_by_id(cls.VENDOR_ID, cls.PRODUCT_ID) != None
|
||||||
|
|
||||||
|
|
||||||
def open(self) :
|
def open(self) :
|
||||||
@ -261,13 +230,13 @@ class PRS500Device(Device):
|
|||||||
|
|
||||||
@todo: Implement unlocking of the device
|
@todo: Implement unlocking of the device
|
||||||
"""
|
"""
|
||||||
self.device = self.device_descriptor.get_device()
|
self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
|
||||||
if not self.device:
|
if not self.device:
|
||||||
raise DeviceError()
|
raise DeviceError()
|
||||||
try:
|
try:
|
||||||
self.handle = self.device.open()
|
self.handle = self.device.open()
|
||||||
self.handle.claimInterface(self.device_descriptor.interface_id)
|
self.handle.claim_interface(self.INTERFACE_ID)
|
||||||
except usb.USBError, err:
|
except USBError, err:
|
||||||
print >> sys.stderr, err
|
print >> sys.stderr, err
|
||||||
raise DeviceBusy()
|
raise DeviceBusy()
|
||||||
# Large timeout as device may still be initializing
|
# Large timeout as device may still be initializing
|
||||||
@ -292,7 +261,7 @@ class PRS500Device(Device):
|
|||||||
""" Release device interface """
|
""" Release device interface """
|
||||||
try:
|
try:
|
||||||
self.handle.reset()
|
self.handle.reset()
|
||||||
self.handle.releaseInterface()
|
self.handle.release_interface()
|
||||||
except Exception, err:
|
except Exception, err:
|
||||||
print >> sys.stderr, err
|
print >> sys.stderr, err
|
||||||
self.handle, self.device = None, None
|
self.handle, self.device = None, None
|
||||||
@ -309,11 +278,11 @@ class PRS500Device(Device):
|
|||||||
"""
|
"""
|
||||||
if self.log_packets:
|
if self.log_packets:
|
||||||
self.log_packet(command, "Command")
|
self.log_packet(command, "Command")
|
||||||
bytes_sent = self.handle.controlMsg(0x40, 0x80, command)
|
bytes_sent = self.handle.control_msg(0x40, 0x80, command)
|
||||||
if bytes_sent != len(command):
|
if bytes_sent != len(command):
|
||||||
raise ControlError(desc="Could not send control request to device\n"\
|
raise ControlError(desc="Could not send control request to device\n"\
|
||||||
+ str(command))
|
+ str(command))
|
||||||
response = response_type(self.handle.controlMsg(0xc0, 0x81, \
|
response = response_type(self.handle.control_msg(0xc0, 0x81, \
|
||||||
Response.SIZE, timeout=timeout))
|
Response.SIZE, timeout=timeout))
|
||||||
if self.log_packets:
|
if self.log_packets:
|
||||||
self.log_packet(response, "Response")
|
self.log_packet(response, "Response")
|
||||||
@ -342,7 +311,7 @@ class PRS500Device(Device):
|
|||||||
C{data} is broken up into packets to be sent to device.
|
C{data} is broken up into packets to be sent to device.
|
||||||
"""
|
"""
|
||||||
def bulk_write_packet(packet):
|
def bulk_write_packet(packet):
|
||||||
self.handle.bulkWrite(PRS500Device.PRS500_BULK_OUT_EP, packet)
|
self.handle.bulk_write(self.BULK_OUT_EP, packet)
|
||||||
if self.log_packets:
|
if self.log_packets:
|
||||||
self.log_packet(Answer(packet), "Answer h->d")
|
self.log_packet(Answer(packet), "Answer h->d")
|
||||||
|
|
||||||
@ -366,7 +335,7 @@ class PRS500Device(Device):
|
|||||||
bulk_write_packet(data[pos:endpos])
|
bulk_write_packet(data[pos:endpos])
|
||||||
bytes_left -= endpos - pos
|
bytes_left -= endpos - pos
|
||||||
pos = endpos
|
pos = endpos
|
||||||
res = Response(self.handle.controlMsg(0xc0, 0x81, Response.SIZE, \
|
res = Response(self.handle.control_msg(0xc0, 0x81, Response.SIZE, \
|
||||||
timeout=5000))
|
timeout=5000))
|
||||||
if self.log_packets:
|
if self.log_packets:
|
||||||
self.log_packet(res, "Response")
|
self.log_packet(res, "Response")
|
||||||
@ -390,8 +359,7 @@ class PRS500Device(Device):
|
|||||||
Each packet is of type data_type
|
Each packet is of type data_type
|
||||||
"""
|
"""
|
||||||
def bulk_read_packet(data_type=Answer, size=0x1000):
|
def bulk_read_packet(data_type=Answer, size=0x1000):
|
||||||
data = data_type(self.handle.bulkRead(PRS500Device.PRS500_BULK_IN_EP, \
|
data = data_type(self.handle.bulk_read(self.BULK_IN_EP, size))
|
||||||
size))
|
|
||||||
if self.log_packets:
|
if self.log_packets:
|
||||||
self.log_packet(data, "Answer d->h")
|
self.log_packet(data, "Answer d->h")
|
||||||
return data
|
return data
|
||||||
@ -844,4 +812,4 @@ class PRS500Device(Device):
|
|||||||
f.seek(0)
|
f.seek(0)
|
||||||
self.put_file(f, path, replace_file=True, end_session=False)
|
self.put_file(f, path, replace_file=True, end_session=False)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
@ -1,11 +1,15 @@
|
|||||||
import sys
|
import sys
|
||||||
from ctypes import *
|
from ctypes import cdll, POINTER, byref, pointer, Structure, \
|
||||||
|
c_ubyte, c_ushort, c_int, c_char, c_void_p, c_byte
|
||||||
from errno import EBUSY, ENOMEM
|
from errno import EBUSY, ENOMEM
|
||||||
|
|
||||||
iswindows = 'win32' in sys.platform.lower()
|
iswindows = 'win32' in sys.platform.lower()
|
||||||
|
isosx = 'darwin' in sys.platform.lower()
|
||||||
_libusb_name = 'libusb.so'
|
_libusb_name = 'libusb.so'
|
||||||
if iswindows:
|
if iswindows:
|
||||||
_libusb_name = 'libusb0'
|
_libusb_name = 'libusb0'
|
||||||
|
elif isosx:
|
||||||
|
_libusb_name = 'libusb.dylib'
|
||||||
_libusb = cdll.LoadLibrary(_libusb_name)
|
_libusb = cdll.LoadLibrary(_libusb_name)
|
||||||
|
|
||||||
# TODO: Need to set this in a platform dependednt way (limits.h in linux)
|
# TODO: Need to set this in a platform dependednt way (limits.h in linux)
|
||||||
@ -96,7 +100,11 @@ class Device(Structure):
|
|||||||
class Bus(Structure):
|
class Bus(Structure):
|
||||||
@apply
|
@apply
|
||||||
def device_list():
|
def device_list():
|
||||||
doc = """ Flat list of devices on this bus. Note: children are not explored """
|
doc = """
|
||||||
|
Flat list of devices on this bus.
|
||||||
|
Note: children are not explored
|
||||||
|
TODO: Check if exploring children is neccessary (e.g. with an external hub)
|
||||||
|
"""
|
||||||
def fget(self):
|
def fget(self):
|
||||||
if _libusb.usb_find_devices() < 0:
|
if _libusb.usb_find_devices() < 0:
|
||||||
raise Error('Unable to search for USB devices')
|
raise Error('Unable to search for USB devices')
|
||||||
@ -162,7 +170,7 @@ class DeviceHandle(Structure):
|
|||||||
if rsize < size:
|
if rsize < size:
|
||||||
raise Error('Could not read ' + str(size) + ' bytes on the '\
|
raise Error('Could not read ' + str(size) + ' bytes on the '\
|
||||||
'control bus. Read: ' + str(rsize) + ' bytes.')
|
'control bus. Read: ' + str(rsize) + ' bytes.')
|
||||||
return list(arr)
|
return tuple(arr)
|
||||||
else:
|
else:
|
||||||
ArrayType = c_byte * size
|
ArrayType = c_byte * size
|
||||||
_libusb.usb_control_msg.argtypes = [POINTER(DeviceHandle), c_int, \
|
_libusb.usb_control_msg.argtypes = [POINTER(DeviceHandle), c_int, \
|
||||||
@ -185,7 +193,7 @@ class DeviceHandle(Structure):
|
|||||||
if rsize < size:
|
if rsize < size:
|
||||||
raise Error('Could not read ' + str(size) + ' bytes on the '\
|
raise Error('Could not read ' + str(size) + ' bytes on the '\
|
||||||
'bulk bus. Read: ' + str(rsize) + ' bytes.')
|
'bulk bus. Read: ' + str(rsize) + ' bytes.')
|
||||||
return list(arr)
|
return tuple(arr)
|
||||||
|
|
||||||
def bulk_write(self, endpoint, bytes, timeout=100):
|
def bulk_write(self, endpoint, bytes, timeout=100):
|
||||||
size = len(bytes)
|
size = len(bytes)
|
||||||
@ -268,17 +276,3 @@ def get_device_by_id(idVendor, idProduct):
|
|||||||
if dev.device_descriptor.idVendor == idVendor and \
|
if dev.device_descriptor.idVendor == idVendor and \
|
||||||
dev.device_descriptor.idProduct == idProduct:
|
dev.device_descriptor.idProduct == idProduct:
|
||||||
return dev
|
return dev
|
||||||
|
|
||||||
#dev = get_device_by_id(0x054c,0x029b)
|
|
||||||
#handle = dev.open()
|
|
||||||
#handle.claim_interface(0)
|
|
||||||
#from libprs500.prstypes import *
|
|
||||||
#comm = GetUSBProtocolVersion()
|
|
||||||
#handle.control_msg(0x40, 0x80, comm)
|
|
||||||
#ret = handle.control_msg(0xc0, 0x81, 32)
|
|
||||||
#print ret
|
|
||||||
#ret = handle.bulk_read(0x81, 24)
|
|
||||||
#print ret
|
|
||||||
#
|
|
||||||
#handle.release_interface(0)
|
|
||||||
#handle.close()
|
|
@ -63,7 +63,7 @@ class TransferBuffer(list):
|
|||||||
"""
|
"""
|
||||||
Represents raw (unstructured) data packets sent over the usb bus.
|
Represents raw (unstructured) data packets sent over the usb bus.
|
||||||
|
|
||||||
C{TransferBuffer} is a wrapper around the tuples used by L{PyUSB<usb>} for communication.
|
C{TransferBuffer} is a wrapper around the tuples used by libusb for communication.
|
||||||
It has convenience methods to read and write data from the underlying buffer. See
|
It has convenience methods to read and write data from the underlying buffer. See
|
||||||
L{TransferBuffer.pack} and L{TransferBuffer.unpack}.
|
L{TransferBuffer.pack} and L{TransferBuffer.unpack}.
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user