Drop dependency on PyUSB. Version bump.

This commit is contained in:
Kovid Goyal 2007-01-13 04:15:25 +00:00
parent fbdb293ac0
commit 234750d487
4 changed files with 36 additions and 75 deletions

View File

@ -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<http://pyusb.berlios.de/>}.
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 <kovid@kovidgoyal.net>"

View File

@ -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<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):
"""
@ -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

View File

@ -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()

View File

@ -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<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
L{TransferBuffer.pack} and L{TransferBuffer.unpack}.
"""