mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Improved packet tracing output (added byte count and packet count)
Added support for the df command
This commit is contained in:
parent
1c8319a5a4
commit
df077ebfbe
@ -20,6 +20,6 @@ the following rule in C{/etc/udev/rules.d/90-local.rules} ::
|
||||
BUS=="usb", SYSFS{idProduct}=="029b", SYSFS{idVendor}=="054c", MODE="660", GROUP="plugdev"
|
||||
You may have to adjust the GROUP and the location of the rules file to suit your distribution.
|
||||
"""
|
||||
VERSION = "0.1"
|
||||
VERSION = "0.1.1"
|
||||
__docformat__ = "epytext"
|
||||
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"
|
||||
|
@ -47,13 +47,19 @@ The public interface of class L{PRS500Device} defines the methods for performing
|
||||
import usb, sys
|
||||
from array import array
|
||||
|
||||
from prstypes import AcknowledgeBulkRead, Answer, Command, DeviceInfo, DirOpen, DirRead, DirClose, \
|
||||
FileOpen, FileClose, FileRead, IdAnswer, ListAnswer, \
|
||||
ListResponse, LongCommand, FileProperties, PathQuery, Response, \
|
||||
ShortCommand, DeviceInfoQuery
|
||||
from prstypes import *
|
||||
from errors import *
|
||||
|
||||
MINIMUM_COL_WIDTH = 12 #: Minimum width of columns in ls output
|
||||
_packet_number = 0 #: Keep track of the packet number of packet tracing
|
||||
|
||||
def _log_packet(packet, header, stream=sys.stderr):
|
||||
""" Log C{packet} to stream C{stream}. Header should be a small word describing the type of packet. """
|
||||
global _packet_number
|
||||
_packet_number += 1
|
||||
print >>stream, header, "(Packet #", str(_packet_number) + ")\n"
|
||||
print >>stream, packet
|
||||
print >>stream, "--"
|
||||
|
||||
class File(object):
|
||||
""" Wrapper that allows easy access to all information about files/directories """
|
||||
@ -165,12 +171,12 @@ class PRS500Device(object):
|
||||
@param response_type: an object of type 'type'. The return packet from the device is returned as an object of type response_type.
|
||||
@param timeout: the time to wait for a response from the device, in milliseconds. If there is no response, a L{usb.USBError} is raised.
|
||||
"""
|
||||
if self._log_packets: print "Command\n%s\n--\n"%command
|
||||
if self._log_packets: _log_packet(command, "Command")
|
||||
bytes_sent = self.handle.controlMsg(0x40, 0x80, command)
|
||||
if bytes_sent != len(command):
|
||||
raise ControlError(desc="Could not send control request to device\n" + str(query.query))
|
||||
response = response_type(self.handle.controlMsg(0xc0, 0x81, Response.SIZE, timeout=timeout))
|
||||
if self._log_packets: print "Response\n%s\n--\n"%response
|
||||
if self._log_packets: _log_packet(response, "Response")
|
||||
return response
|
||||
|
||||
def _send_validated_command(self, command, cnumber=None, response_type=Response, timeout=100):
|
||||
@ -191,7 +197,7 @@ class PRS500Device(object):
|
||||
@param size: the expected size of the data packet.
|
||||
"""
|
||||
data = data_type(self.handle.bulkRead(PRS500Device.PRS500_BULK_IN_EP, size))
|
||||
if self._log_packets: print "Answer\n%s\n--\n"%data
|
||||
if self._log_packets: _log_packet(data, "Answer d->h")
|
||||
return data
|
||||
|
||||
def _bulk_read(self, bytes, command_number=0x00, packet_size=4096, data_type=Answer):
|
||||
@ -364,3 +370,25 @@ class PRS500Device(object):
|
||||
if recurse and file.is_dir and not file.path.startswith(("/dev","/proc")):
|
||||
dirs[len(dirs):] = self.list(file.path, recurse=True)
|
||||
return dirs
|
||||
|
||||
def available_space(self):
|
||||
"""
|
||||
Get free space available on the mountpoints:
|
||||
1. /Data/ Device memory
|
||||
2. a:/ Memory Stick
|
||||
3. b:/ SD Card
|
||||
|
||||
@return: A list of tuples. Each tuple has form ("location", free space, total space)
|
||||
"""
|
||||
return self._run_session(self._available_space)
|
||||
|
||||
def _available_space(self, args):
|
||||
""" L{available_space} """
|
||||
data = []
|
||||
for path in ("/Data/", "a:/", "b:/"):
|
||||
res = self._send_validated_command(FreeSpaceQuery(path),timeout=5000) # Timeout needs to be increased as it takes time to read card
|
||||
buffer_size = 16 + res.data[2]
|
||||
pkt = self._bulk_read(buffer_size, data_type=FreeSpaceAnswer, command_number=FreeSpaceQuery.NUMBER)[0]
|
||||
data.append( (path, pkt.free_space, pkt.total) )
|
||||
return data
|
||||
|
||||
|
@ -85,7 +85,7 @@ class TransferBuffer(list):
|
||||
0700 0100 0000 0000 0000 0000 0c00 0000 ................
|
||||
0200 0000 0400 0000 4461 7461 ........Data
|
||||
"""
|
||||
ans, ascii = "", ""
|
||||
ans, ascii = ": ".rjust(10,"0"), ""
|
||||
for i in range(0, len(self), 2):
|
||||
for b in range(2):
|
||||
try:
|
||||
@ -95,10 +95,10 @@ class TransferBuffer(list):
|
||||
ans = ans + " "
|
||||
if (i+2)%16 == 0:
|
||||
if i+2 < len(self):
|
||||
ans += " " + ascii + "\n"
|
||||
ans += " " + ascii + "\n" + (TransferBuffer.phex(i+2)+": ").rjust(10, "0")
|
||||
ascii = ""
|
||||
last_line = ans[ans.rfind("\n")+1:]
|
||||
padding = 40 - len(last_line)
|
||||
padding = 50 - len(last_line)
|
||||
ans += "".ljust(padding) + " " + ascii
|
||||
return ans.strip()
|
||||
|
||||
@ -271,6 +271,43 @@ class ShortCommand(Command):
|
||||
|
||||
return property(**locals())
|
||||
|
||||
class FreeSpaceQuery(Command):
|
||||
""" Query the free space available """
|
||||
NUMBER = 0x53 #; Command number
|
||||
def __init__(self, path):
|
||||
Command.__init__(self, 20 + len(path))
|
||||
self.number=FreeSpaceQuery.NUMBER
|
||||
self.type=0x01
|
||||
self.length = 4 + len(path)
|
||||
self.path_length = len(path)
|
||||
self.path = path
|
||||
|
||||
@apply
|
||||
def path_length():
|
||||
doc =\
|
||||
""" The length in bytes of the path to follow. C{unsigned int} stored at byte 16. """
|
||||
def fget(self):
|
||||
return self.unpack(start=16, fmt=DWORD)[0]
|
||||
|
||||
def fset(self, val):
|
||||
self.pack(val, start=16, fmt=DWORD)
|
||||
|
||||
return property(**locals())
|
||||
|
||||
@apply
|
||||
def path():
|
||||
doc =\
|
||||
""" The path. Stored as a string at byte 20. """
|
||||
|
||||
def fget(self):
|
||||
return self.unpack(start=20, fmt="<"+str(self.path_length)+"s")[0]
|
||||
|
||||
def fset(self, val):
|
||||
self.pack(val, start=20, fmt="<"+str(self.path_length)+"s")
|
||||
|
||||
return property(**locals())
|
||||
|
||||
|
||||
class DirOpen(Command):
|
||||
|
||||
""" Open a directory for reading its contents """
|
||||
@ -795,6 +832,31 @@ class DeviceInfo(Answer):
|
||||
return src[0:src.find('\x00')]
|
||||
return property(**locals())
|
||||
|
||||
class FreeSpaceAnswer(Answer):
|
||||
@apply
|
||||
def total():
|
||||
doc =\
|
||||
""" The total space in bytes. C{unsigned long long} stored in 8 bytes at byte 24 """
|
||||
def fget(self):
|
||||
return self.unpack(start=24, fmt=DDWORD)[0]
|
||||
|
||||
def fset(self, val):
|
||||
self.pack(val, start=24, fmt=DDWORD)
|
||||
|
||||
return property(**locals())
|
||||
|
||||
@apply
|
||||
def free_space():
|
||||
doc =\
|
||||
""" The free space in bytes. C{unsigned long long} stored in 8 bytes at byte 32 """
|
||||
def fget(self):
|
||||
return self.unpack(start=32, fmt=DDWORD)[0]
|
||||
|
||||
def fset(self, val):
|
||||
self.pack(val, start=32, fmt=DDWORD)
|
||||
|
||||
return property(**locals())
|
||||
|
||||
class ListAnswer(Answer):
|
||||
|
||||
""" Defines the structure of packets that contain items in a list. """
|
||||
|
40
prs-500.e3p
40
prs-500.e3p
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Project SYSTEM "Project-3.9.dtd">
|
||||
<!-- Project file for project pr5-500 -->
|
||||
<!-- Saved: 2006-10-31, 21:14:19 -->
|
||||
<!-- Project file for project prs-500 -->
|
||||
<!-- Saved: 2006-11-07, 00:09:05 -->
|
||||
<!-- Copyright (C) 2006 Kovid Goyal, kovid@kovidgoyal.net -->
|
||||
<Project version="3.9">
|
||||
<ProgLanguage mixed="0">Python</ProgLanguage>
|
||||
@ -12,16 +12,31 @@
|
||||
<Email>kovid@kovidgoyal.net</Email>
|
||||
<Sources>
|
||||
<Source>
|
||||
<Name>libprs500/communicate.py</Name>
|
||||
<Dir>libprs500</Dir>
|
||||
<Name>communicate.py</Name>
|
||||
</Source>
|
||||
<Source>
|
||||
<Name>libprs500/terminfo.py</Name>
|
||||
<Dir>libprs500</Dir>
|
||||
<Name>terminfo.py</Name>
|
||||
</Source>
|
||||
<Source>
|
||||
<Name>libprs500/prstypes.py</Name>
|
||||
<Dir>libprs500</Dir>
|
||||
<Name>prstypes.py</Name>
|
||||
</Source>
|
||||
<Source>
|
||||
<Name>libprs500/errors.py</Name>
|
||||
<Dir>libprs500</Dir>
|
||||
<Name>errors.py</Name>
|
||||
</Source>
|
||||
<Source>
|
||||
<Dir>libprs500</Dir>
|
||||
<Name>__init__.py</Name>
|
||||
</Source>
|
||||
<Source>
|
||||
<Name>setup.py</Name>
|
||||
</Source>
|
||||
<Source>
|
||||
<Dir>scripts</Dir>
|
||||
<Name>prs500.py</Name>
|
||||
</Source>
|
||||
</Sources>
|
||||
<Forms>
|
||||
@ -31,9 +46,16 @@
|
||||
<Interfaces>
|
||||
</Interfaces>
|
||||
<Others>
|
||||
<Other>
|
||||
<Name>epydoc.conf</Name>
|
||||
</Other>
|
||||
<Other>
|
||||
<Name>epydoc-pdf.conf</Name>
|
||||
</Other>
|
||||
</Others>
|
||||
<MainScript>
|
||||
<Name>libprs500/communicate.py</Name>
|
||||
<Dir>scripts</Dir>
|
||||
<Name>prs500.py</Name>
|
||||
</MainScript>
|
||||
<Vcs>
|
||||
<VcsType>Subversion</VcsType>
|
||||
@ -96,9 +118,9 @@ s.</VcsOtherData>
|
||||
</Vcs>
|
||||
<FiletypeAssociations>
|
||||
<FiletypeAssociation pattern="*.ui.h" type="FORMS" />
|
||||
<FiletypeAssociation pattern="*.ptl" type="SOURCES" />
|
||||
<FiletypeAssociation pattern="*.idl" type="INTERFACES" />
|
||||
<FiletypeAssociation pattern="*.ui" type="FORMS" />
|
||||
<FiletypeAssociation pattern="*.idl" type="INTERFACES" />
|
||||
<FiletypeAssociation pattern="*.ptl" type="SOURCES" />
|
||||
<FiletypeAssociation pattern="*.py" type="SOURCES" />
|
||||
</FiletypeAssociations>
|
||||
</Project>
|
||||
|
@ -16,6 +16,16 @@ from libprs500.errors import ArgumentError
|
||||
|
||||
MINIMUM_COL_WIDTH = 12 #: Minimum width of columns in ls output
|
||||
|
||||
def human_readable(size):
|
||||
""" Convert a size in bytes into a human readle form """
|
||||
if size < 1024: divisor, suffix = 1, ""
|
||||
elif size < 1024*1024: divisor, suffix = 1024., "K"
|
||||
elif size < 1024*1024*1024: divisor, suffix = 1024*1024, "M"
|
||||
elif size < 1024*1024*1024*1024: divisor, suffix = 1024*1024, "G"
|
||||
size = str(size/divisor)
|
||||
if size.find(".") > -1: size = size[:size.find(".")+2]
|
||||
return size + suffix
|
||||
|
||||
class FileFormatter(object):
|
||||
def __init__(self, file, term):
|
||||
self.term = term
|
||||
@ -56,13 +66,7 @@ class FileFormatter(object):
|
||||
def human_readable_size():
|
||||
doc=""" File size in human readable form """
|
||||
def fget(self):
|
||||
if self.size < 1024: divisor, suffix = 1, ""
|
||||
elif self.size < 1024*1024: divisor, suffix = 1024., "K"
|
||||
elif self.size < 1024*1024*1024: divisor, suffix = 1024*1024, "M"
|
||||
elif self.size < 1024*1024*1024*1024: divisor, suffix = 1024*1024, "G"
|
||||
size = str(self.size/divisor)
|
||||
if size.find(".") > -1: size = size[:size.find(".")+2]
|
||||
return size + suffix
|
||||
human_readable(self.size)
|
||||
return property(**locals())
|
||||
|
||||
@apply
|
||||
@ -161,7 +165,7 @@ def main():
|
||||
term = TerminalController()
|
||||
cols = term.COLS
|
||||
|
||||
parser = OptionParser(usage="usage: %prog command [options] args\n\ncommand is one of: info, ls, cp, cat or rm\n\n"+
|
||||
parser = OptionParser(usage="usage: %prog [options] command args\n\ncommand is one of: info, df, ls, cp, cat or rm\n\n"+
|
||||
"For help on a particular command: %prog command", version="libprs500 version: " + VERSION)
|
||||
parser.add_option("--log-packets", help="print out packet stream to stdout", dest="log_packets", action="store_true", default=False)
|
||||
parser.remove_option("-h")
|
||||
@ -174,7 +178,16 @@ def main():
|
||||
command = args[0]
|
||||
args = args[1:]
|
||||
dev = PRS500Device(log_packets=options.log_packets)
|
||||
if command == "ls":
|
||||
if command == "df":
|
||||
dev.open()
|
||||
data = dev.available_space()
|
||||
dev.close()
|
||||
print "Filesystem\tSize \tUsed \tAvail \tUse%"
|
||||
for datum in data:
|
||||
total, free, used, percent = human_readable(datum[2]), human_readable(datum[1]), human_readable(datum[2]-datum[1]), \
|
||||
str(0 if datum[2]==0 else int(100*(datum[2]-datum[1])/(datum[2]*1.)))+"%"
|
||||
print "%-10s\t%s\t%s\t%s\t%s"%(datum[0], total, used, free, percent)
|
||||
elif command == "ls":
|
||||
parser = OptionParser(usage="usage: %prog ls [options] path\n\npath must begin with /,a:/ or b:/")
|
||||
parser.add_option("--color", help="show ls output in color", dest="color", action="store_true", default=False)
|
||||
parser.add_option("-l", help="In addition to the name of each file, print the file type, permissions, and timestamp (the modification time unless other times are selected)", dest="ll", action="store_true", default=False)
|
||||
|
Loading…
x
Reference in New Issue
Block a user