diff --git a/src/libprs500/__init__.py b/src/libprs500/__init__.py
index 187426819f..c30761f556 100644
--- a/src/libprs500/__init__.py
+++ b/src/libprs500/__init__.py
@@ -29,7 +29,6 @@ The packet structure used by the SONY Reader USB protocol is defined
in the module L{prstypes}. The communication logic
is defined in the module L{communicate}.
-This package requires U{PyUSB}.
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} ::
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
suit your distribution.
"""
-__version__ = "0.3.0"
+__version__ = "0.3.1"
__docformat__ = "epytext"
__author__ = "Kovid Goyal "
diff --git a/src/libprs500/communicate.py b/src/libprs500/communicate.py
index 7d94f89661..40131902b2 100755
--- a/src/libprs500/communicate.py
+++ b/src/libprs500/communicate.py
@@ -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
methods for performing various tasks.
"""
-import usb
import sys
import os
import time
from tempfile import TemporaryFile
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.errors import *
from libprs500.books import BookList, fix_ids
@@ -115,34 +116,6 @@ class File(object):
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}
- """
-
- 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):
"""
@@ -154,11 +127,11 @@ class PRS500Device(Device):
2. Listing of directories. See the C{list} method.
"""
- SONY_VENDOR_ID = 0x054c #: SONY Vendor Id
- PRS500_PRODUCT_ID = 0x029b #: Product Id for the PRS-500
- PRS500_INTERFACE_ID = 0 #: The interface we use to talk to the device
- PRS500_BULK_IN_EP = 0x81 #: Endpoint for Bulk reads
- PRS500_BULK_OUT_EP = 0x02 #: Endpoint for Bulk writes
+ VENDOR_ID = 0x054c #: SONY Vendor Id
+ PRODUCT_ID = 0x029b #: Product Id for the PRS-500
+ INTERFACE_ID = 0 #: The interface we use to talk to the device
+ BULK_IN_EP = 0x81 #: Endpoint for Bulk reads
+ BULK_OUT_EP = 0x02 #: Endpoint for Bulk writes
# Location of media.xml file on device
MEDIA_XML = "/Data/database/cache/media.xml"
# 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
THUMBNAIL_HEIGHT = 68
- device_descriptor = DeviceDescriptor(SONY_VENDOR_ID, \
- PRS500_PRODUCT_ID, PRS500_INTERFACE_ID)
-
@classmethod
def signature(cls):
""" 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):
"""
@@ -202,7 +172,7 @@ class PRS500Device(Device):
if not kwargs.has_key("end_session") or kwargs["end_session"]:
dev.send_validated_command(EndSession())
raise
- except usb.USBError, err:
+ except USBError, err:
if "No such device" in str(err):
raise DeviceError()
elif "Connection timed out" in str(err):
@@ -229,8 +199,7 @@ class PRS500Device(Device):
task does not have any progress information
"""
Device.__init__(self)
- # The actual device (PyUSB object)
- self.device = self.device_descriptor.get_device()
+ self.device = get_device_by_id(self.VENDOR_ID, self.PRODUCT_ID)
# Handle that is used to communicate with device. Setup in L{open}
self.handle = None
self.log_packets = log_packets
@@ -238,7 +207,7 @@ class PRS500Device(Device):
def reconnect(self):
""" 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
@classmethod
@@ -249,7 +218,7 @@ class PRS500Device(Device):
software connection. You may need to call L{reconnect} if you keep
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) :
@@ -261,13 +230,13 @@ class PRS500Device(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:
raise DeviceError()
try:
self.handle = self.device.open()
- self.handle.claimInterface(self.device_descriptor.interface_id)
- except usb.USBError, err:
+ self.handle.claim_interface(self.INTERFACE_ID)
+ except USBError, err:
print >> sys.stderr, err
raise DeviceBusy()
# Large timeout as device may still be initializing
@@ -292,7 +261,7 @@ class PRS500Device(Device):
""" Release device interface """
try:
self.handle.reset()
- self.handle.releaseInterface()
+ self.handle.release_interface()
except Exception, err:
print >> sys.stderr, err
self.handle, self.device = None, None
@@ -309,11 +278,11 @@ class PRS500Device(Device):
"""
if self.log_packets:
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):
raise ControlError(desc="Could not send control request to device\n"\
+ str(command))
- response = response_type(self.handle.controlMsg(0xc0, 0x81, \
+ response = response_type(self.handle.control_msg(0xc0, 0x81, \
Response.SIZE, timeout=timeout))
if self.log_packets:
self.log_packet(response, "Response")
@@ -342,7 +311,7 @@ class PRS500Device(Device):
C{data} is broken up into packets to be sent to device.
"""
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:
self.log_packet(Answer(packet), "Answer h->d")
@@ -366,7 +335,7 @@ class PRS500Device(Device):
bulk_write_packet(data[pos:endpos])
bytes_left -= endpos - pos
pos = endpos
- res = Response(self.handle.controlMsg(0xc0, 0x81, Response.SIZE, \
+ res = Response(self.handle.control_msg(0xc0, 0x81, Response.SIZE, \
timeout=5000))
if self.log_packets:
self.log_packet(res, "Response")
@@ -390,8 +359,7 @@ class PRS500Device(Device):
Each packet is of type data_type
"""
def bulk_read_packet(data_type=Answer, size=0x1000):
- data = data_type(self.handle.bulkRead(PRS500Device.PRS500_BULK_IN_EP, \
- size))
+ data = data_type(self.handle.bulk_read(self.BULK_IN_EP, size))
if self.log_packets:
self.log_packet(data, "Answer d->h")
return data
@@ -844,4 +812,4 @@ class PRS500Device(Device):
f.seek(0)
self.put_file(f, path, replace_file=True, end_session=False)
f.close()
-
+
\ No newline at end of file
diff --git a/src/libprs500/libusb.py b/src/libprs500/libusb.py
index 4568158b3e..17f50bc535 100644
--- a/src/libprs500/libusb.py
+++ b/src/libprs500/libusb.py
@@ -1,11 +1,15 @@
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
iswindows = 'win32' in sys.platform.lower()
+isosx = 'darwin' in sys.platform.lower()
_libusb_name = 'libusb.so'
if iswindows:
_libusb_name = 'libusb0'
+elif isosx:
+ _libusb_name = 'libusb.dylib'
_libusb = cdll.LoadLibrary(_libusb_name)
# TODO: Need to set this in a platform dependednt way (limits.h in linux)
@@ -96,7 +100,11 @@ class Device(Structure):
class Bus(Structure):
@apply
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):
if _libusb.usb_find_devices() < 0:
raise Error('Unable to search for USB devices')
@@ -162,7 +170,7 @@ class DeviceHandle(Structure):
if rsize < size:
raise Error('Could not read ' + str(size) + ' bytes on the '\
'control bus. Read: ' + str(rsize) + ' bytes.')
- return list(arr)
+ return tuple(arr)
else:
ArrayType = c_byte * size
_libusb.usb_control_msg.argtypes = [POINTER(DeviceHandle), c_int, \
@@ -185,7 +193,7 @@ class DeviceHandle(Structure):
if rsize < size:
raise Error('Could not read ' + str(size) + ' bytes on the '\
'bulk bus. Read: ' + str(rsize) + ' bytes.')
- return list(arr)
+ return tuple(arr)
def bulk_write(self, endpoint, bytes, timeout=100):
size = len(bytes)
@@ -268,17 +276,3 @@ def get_device_by_id(idVendor, idProduct):
if dev.device_descriptor.idVendor == idVendor and \
dev.device_descriptor.idProduct == idProduct:
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()
\ No newline at end of file
diff --git a/src/libprs500/prstypes.py b/src/libprs500/prstypes.py
index fbb2645d18..3dd4b22193 100755
--- a/src/libprs500/prstypes.py
+++ b/src/libprs500/prstypes.py
@@ -63,7 +63,7 @@ class TransferBuffer(list):
"""
Represents raw (unstructured) data packets sent over the usb bus.
- C{TransferBuffer} is a wrapper around the tuples used by L{PyUSB} 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
L{TransferBuffer.pack} and L{TransferBuffer.unpack}.
"""