diff --git a/src/calibre/devices/cybookg3/books.py b/src/calibre/devices/cybookg3/books.py deleted file mode 100644 index ed3df812db..0000000000 --- a/src/calibre/devices/cybookg3/books.py +++ /dev/null @@ -1,78 +0,0 @@ -__license__ = 'GPL v3' -__copyright__ = '2009, John Schember - - - - - - %(main_memory)s - %(deviceclass)s - - - - - - - - - - - - - %(storage_card)s - %(deviceclass)s - - - - - - -''' - - - def __init__(self, key='-1', log_packets=False, report_progress=None) : - self._main_prefix = self._card_prefix = None - - @classmethod - def get_fdi(cls): - return cls.FDI_TEMPLATE%dict( - app=__appname__, - deviceclass=cls.__name__, - vendor_id=hex(cls.VENDOR_ID), - product_id=hex(cls.PRODUCT_ID), - bcd=hex(cls.BCD), - main_memory=cls.MAIN_MEMORY_VOLUME_LABEL, - storage_card=cls.STORAGE_CARD_VOLUME_LABEL, - ) - - def set_progress_reporter(self, report_progress): - self.report_progress = report_progress - - def get_device_information(self, end_session=True): - """ - Ask device for device information. See L{DeviceInfoQuery}. - @return: (device name, device version, software version on device, mime type) - """ - return (self.__class__.__name__, '', '', '') - - def card_prefix(self, end_session=True): - return self._card_prefix - - @classmethod - def _windows_space(cls, prefix): - if prefix is None: - return 0, 0 - win32file = __import__('win32file', globals(), locals(), [], -1) - try: - sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters = \ - win32file.GetDiskFreeSpace(prefix[:-1]) - except Exception, err: - if getattr(err, 'args', [None])[0] == 21: # Disk not ready - time.sleep(3) - sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters = \ - win32file.GetDiskFreeSpace(prefix[:-1]) - else: raise - mult = sectors_per_cluster * bytes_per_sector - return total_clusters * mult, free_clusters * mult - - def total_space(self, end_session=True): - msz = csz = 0 - print self._main_prefix - if not iswindows: - if self._main_prefix is not None: - stats = os.statvfs(self._main_prefix) - msz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree) - if self._card_prefix is not None: - stats = os.statvfs(self._card_prefix) - csz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree) - else: - msz = self._windows_space(self._main_prefix)[0] - csz = self._windows_space(self._card_prefix)[0] - - return (msz, 0, csz) - - def free_space(self, end_session=True): - msz = csz = 0 - if not iswindows: - if self._main_prefix is not None: - stats = os.statvfs(self._main_prefix) - msz = stats.f_frsize * stats.f_bavail - if self._card_prefix is not None: - stats = os.statvfs(self._card_prefix) - csz = stats.f_frsize * stats.f_bavail - else: - msz = self._windows_space(self._main_prefix)[1] - csz = self._windows_space(self._card_prefix)[1] - - return (msz, 0, csz) - - def books(self, oncard=False, end_session=True): - if oncard and self._card_prefix is None: - return [] - prefix = self._card_prefix if oncard else self._main_prefix - bl = BookList(prefix) - return bl - - def upload_books(self, files, names, on_card=False, end_session=True): - if on_card and not self._card_prefix: - raise ValueError(_('The reader has no storage card connected.')) - - if not on_card: - path = os.path.join(self._main_prefix, EBOOK_DIR) - else: - path = os.path.join(self._card_prefix, EBOOK_DIR) - - sizes = map(os.path.getsize, files) - size = sum(sizes) - - if on_card and size > self.free_space()[2] - 1024*1024: - raise FreeSpaceError("There is insufficient free space "+\ - "on the storage card") - if not on_card and size > self.free_space()[0] - 2*1024*1024: - raise FreeSpaceError("There is insufficient free space " +\ - "in main memory") + EBOOK_DIR = "eBooks" - paths = [] - names = iter(names) - - for infile in files: - filepath = os.path.join(path, names.next()) - paths.append(filepath) - - shutil.copy2(infile, filepath) - - return zip(paths, cycle([on_card])) - - @classmethod - def add_books_to_metadata(cls, locations, metadata, booklists): - for location in locations: - path = location[0] - on_card = 1 if location[1] else 0 - booklists[on_card].add_book(path, os.path.basename(path)) - def delete_books(self, paths, end_session=True): for path in paths: if os.path.exists(path): - # Delete the ebook os.unlink(path) filepath, ext = os.path.splitext(path) @@ -194,132 +49,4 @@ class CYBOOKG3(Device): for p, d, files in os.walk(basepath): for filen in fnmatch.filter(files, filename + "*.t2b"): os.unlink(os.path.join(p, filen)) - - @classmethod - def remove_books_from_metadata(cls, paths, booklists): - for path in paths: - for bl in booklists: - bl.remove_book(path) - - def sync_booklists(self, booklists, end_session=True): - # There is no meta data on the device to update. The device is treated - # as a mass storage device and does not use a meta data xml file like - # the Sony Readers. - pass - - def get_file(self, path, outfile, end_session=True): - path = self.munge_path(path) - src = open(path, 'rb') - shutil.copyfileobj(src, outfile, 10*1024*1024) - - def munge_path(self, path): - if path.startswith('/') and not (path.startswith(self._main_prefix) or \ - (self._card_prefix and path.startswith(self._card_prefix))): - path = self._main_prefix + path[1:] - elif path.startswith('card:'): - path = path.replace('card:', self._card_prefix[:-1]) - return path - - - def _windows_match_device(self, device_id): - device_id = device_id.upper() - vid, pid = hex(cls.VENDOR_ID)[2:], hex(cls.PRODUCT_ID)[2:] - while len(vid) < 4: vid = '0' + vid - while len(pid) < 4: pid = '0' + pid - if 'VID_'+vid in device_id and 'PID_'+pid in device_id: - return True - return False - - # This only supports Windows >= 2000 - def open_windows(self): - drives = [] - wmi = __import__('wmi', globals(), locals(), [], -1) - c = wmi.WMI() - for drive in c.Win32_DiskDrive(): - if self._windows_match_device(str(drive.PNPDeviceID)): - if drive.Partitions == 0: - continue - try: - partition = drive.associators("Win32_DiskDriveToDiskPartition")[0] - logical_disk = partition.associators('Win32_LogicalDiskToPartition')[0] - prefix = logical_disk.DeviceID+os.sep - drives.append((drive.Index, prefix)) - except IndexError: - continue - - if not drives: - raise DeviceError(_('Unable to detect the %s disk drive. Try rebooting.')%self.__class__.__name__) - - drives.sort(cmp=lambda a, b: cmp(a[0], b[0])) - self._main_prefix = drives[0][1] - if len(drives) > 1: - self._card_prefix = drives[1][1] - - def open_osx(self): - raise NotImplementedError() - - def open_linux(self): - import dbus - bus = dbus.SystemBus() - hm = dbus.Interface(bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager"), "org.freedesktop.Hal.Manager") - - def conditional_mount(dev): - mmo = bus.get_object("org.freedesktop.Hal", dev) - label = mmo.GetPropertyString('volume.label', dbus_interface='org.freedesktop.Hal.Device') - is_mounted = mmo.GetPropertyString('volume.is_mounted', dbus_interface='org.freedesktop.Hal.Device') - mount_point = mmo.GetPropertyString('volume.mount_point', dbus_interface='org.freedesktop.Hal.Device') - fstype = mmo.GetPropertyString('volume.fstype', dbus_interface='org.freedesktop.Hal.Device') - if is_mounted: - return str(mount_point) - mmo.Mount(label, fstype, ['umask=077', 'uid='+str(os.getuid()), 'sync'], - dbus_interface='org.freedesktop.Hal.Device.Volume') - return os.path.normpath('/media/'+label)+'/' - - mm = hm.FindDeviceStringMatch(__appname__+'.mainvolume', self.__class__.__name__) - if not mm: - raise DeviceError(_('Unable to detect the %s disk drive. Try rebooting.')%(self.__class__.__name__,)) - self._main_prefix = None - for dev in mm: - try: - self._main_prefix = conditional_mount(dev)+os.sep - break - except dbus.exceptions.DBusException: - continue - - if not self._main_prefix: - raise DeviceError('Could not open device for reading. Try a reboot.') - - self._card_prefix = None - cards = hm.FindDeviceStringMatch(__appname__+'.cardvolume', self.__class__.__name__) - - for dev in cards: - try: - self._card_prefix = conditional_mount(dev)+os.sep - break - except: - import traceback - print traceback - continue - - def open(self): - time.sleep(5) - self._main_prefix = self._card_prefix = None - if islinux: - try: - self.open_linux() - except DeviceError: - time.sleep(3) - self.open_linux() - if iswindows: - try: - self.open_windows() - except DeviceError: - time.sleep(3) - self.open_windows() - if isosx: - try: - self.open_osx() - except DeviceError: - time.sleep(3) - self.open_osx() diff --git a/src/calibre/devices/kindle/books.py b/src/calibre/devices/kindle/books.py deleted file mode 100755 index 623b02fe20..0000000000 --- a/src/calibre/devices/kindle/books.py +++ /dev/null @@ -1,122 +0,0 @@ -__license__ = 'GPL v3' -__copyright__ = '2008, Kovid Goyal ' -''' -''' -import re, time, functools -import os - - -from calibre.devices.interface import BookList as _BookList -from calibre.devices import strftime as _strftime - -strftime = functools.partial(_strftime, zone=time.localtime) -MIME_MAP = { - "azw" : "application/azw", - "prc" : "application/prc", - "txt" : "text/plain", - 'mobi': 'application/mobi', - } - -def sortable_title(title): - return re.sub('^\s*A\s+|^\s*The\s+|^\s*An\s+', '', title).rstrip() - -class Book(object): - - @apply - def title_sorter(): - doc = '''String to sort the title. If absent, title is returned''' - def fget(self): - src = self.title - return src - def fset(self, val): - self.elem.setAttribute('titleSorter', sortable_title(unicode(val))) - return property(doc=doc, fget=fget, fset=fset) - - @apply - def thumbnail(): - return 0 - - - @apply - def path(): - doc = """ Absolute path to book on device. Setting not supported. """ - def fget(self): - return self.mountpath + self.rpath - return property(fget=fget, doc=doc) - - @apply - def db_id(): - doc = '''The database id in the application database that this file corresponds to''' - def fget(self): - match = re.search(r'_(\d+)$', self.rpath.rpartition('.')[0]) - if match: - return int(match.group(1)) - return property(fget=fget, doc=doc) - - def __init__(self, mountpath, title, authors ): - self.mountpath = mountpath - self.title = title - self.authors = authors - self.mime = "" - self.rpath = "documents//" + title - self.id = 0 - self.sourceid = 0 - self.size = 0 - self.datetime = time.gmtime() - self.tags = [] - - - def __str__(self): - """ Return a utf-8 encoded string with title author and path information """ - return self.title.encode('utf-8') + " by " + \ - self.authors.encode('utf-8') + " at " + self.path.encode('utf-8') - - -class BookList(_BookList): - _mountpath = "" - - def __init__(self, mountpath): - self._mountpath = mountpath - _BookList.__init__(self) - self.return_books(mountpath) - - def return_books(self,mountpath): - docs = mountpath + "documents" - for f in os.listdir(docs): - m = re.match(".*azw", f) - if m: - self.append_book(mountpath,f) - m = re.match(".*prc", f) - if m: - self.append_book(mountpath,f) - m = re.match(".*txt", f) - if m: - self.append_book(mountpath,f) - - def append_book(self,mountpath,f): - b = Book(mountpath,f,"") - b.size = os.stat(mountpath + "//documents//" + f)[6] - b.datetime = time.gmtime(os.stat(mountpath + "//documents//" + f)[8]) - b.rpath = "//documents//" + f - self.append(b) - - def supports_tags(self): - return False - - def add_book(self, name, size, ctime): - book = Book(self._mountpath, name, "") - book.datetime = time.gmtime(ctime) - book.size = size - '''remove book if already in db''' - self.remove_book(self._mountpath + "//documents//" + name) - self.append(book) - - - def remove_book(self, path): - for book in self: - if path.startswith(book.mountpath): - if path.endswith(book.rpath): - self.remove(book) - break - - diff --git a/src/calibre/devices/kindle/driver.py b/src/calibre/devices/kindle/driver.py index 93145432db..29152c4186 100755 --- a/src/calibre/devices/kindle/driver.py +++ b/src/calibre/devices/kindle/driver.py @@ -1,360 +1,33 @@ __license__ = 'GPL v3' -__copyright__ = '2008, Kovid Goyal ' -''' -Device driver for the Amazon Kindle -''' -import sys, os, shutil, time, subprocess, re -from itertools import cycle - -from calibre.devices.interface import Device -from calibre.devices.errors import DeviceError, FreeSpaceError -from calibre.devices.kindle.books import BookList -from calibre import iswindows, islinux, isosx -from calibre.devices.errors import PathError - -class File(object): - def __init__(self, path): - stats = os.stat(path) - self.is_dir = os.path.isdir(path) - self.is_readonly = not os.access(path, os.W_OK) - self.ctime = stats.st_ctime - self.wtime = stats.st_mtime - self.size = stats.st_size - if path.endswith(os.sep): - path = path[:-1] - self.path = path - self.name = os.path.basename(path) - - -class KINDLE(Device): - FORMATS = ["azw", "prc", "txt", 'mobi'] - VENDOR_ID = 0x1949 #: Amazon Vendor Id - PRODUCT_ID = 0x001 #: Product Id for the Kindle - INTERNAL_STORAGE = 'INTERNAL_STORAGE' - CARD_STORAGE = 'CARD_STORAGE' - PRODUCT_NAME = 'KINDLE' - VENDOR_NAME = 'AMAZON' - - - MAIN_MEMORY_VOLUME_LABEL = 'Kindle Internal Storage USB Device' - STORAGE_CARD_VOLUME_LABEL = 'Kindle Card Storage USB Device' - - #OSX_MAIN_NAME = 'Sony PRS-505/UC Media' - #OSX_SD_NAME = 'Sony PRS-505/UC:SD Media' - #OSX_MS_NAME = 'Sony PRS-505/UC:MS Media' - - FDI_TEMPLATE = \ -''' - - - - - - %(main_memory)s - %(deviceclass)s - - - - - - - - - - - %(storage_card)s - %(deviceclass)s - - - - - -''' - - - def __init__(self, log_packets=False): - self._main_prefix = self._card_prefix = None - - @classmethod - def get_fdi(cls): - return cls.FDI_TEMPLATE%dict( - deviceclass=cls.__name__, - vendor_id=hex(cls.VENDOR_ID), - product_id=hex(cls.PRODUCT_ID), - main_memory=cls.MAIN_MEMORY_VOLUME_LABEL, - storage_card=cls.STORAGE_CARD_VOLUME_LABEL, - ) - - @classmethod - def is_device(cls, device_id): - '''print "mimi in is device"''' - if not hasattr(device_id, 'upper'): - return False - - if 'VEN_'+cls.VENDOR_NAME in device_id.upper() and \ - 'PROD_'+cls.INTERNAL_STORAGE in device_id.upper(): - return True - if 'VEN_'+cls.VENDOR_NAME in device_id.upper() and \ - 'PROD_'+cls.CARD_STORAGE in device_id.upper(): - return True - - vid, pid = hex(cls.VENDOR_ID)[2:], hex(cls.PRODUCT_ID)[2:] - if len(vid) < 4: vid = '0'+vid - if len(pid) < 4: pid = '0'+pid - if len(pid) < 4: pid = '0'+pid - if 'VID_'+vid in device_id.upper() and \ - 'PID_'+pid in device_id.upper(): - return True - return False - - def open_osx(self): - mount = subprocess.Popen('mount', shell=True, - stdout=subprocess.PIPE).stdout.read() - src = subprocess.Popen('ioreg -n "%s"'%(self.OSX_MAIN_NAME,), - shell=True, stdout=subprocess.PIPE).stdout.read() - try: - devname = re.search(r'BSD Name.*=\s+"(\S+)"', src).group(1) - self._main_prefix = re.search('/dev/%s(\w*)\s+on\s+([^\(]+)\s+'%(devname,), mount).group(2) + os.sep - except: - raise DeviceError('Unable to find %s. Is it connected?'%(self.__class__.__name__,)) - try: - src = subprocess.Popen('ioreg -n "%s"'%(self.OSX_SD_NAME,), - shell=True, stdout=subprocess.PIPE).stdout.read() - devname = re.search(r'BSD Name.*=\s+"(\S+)"', src).group(1) - except: - try: - src = subprocess.Popen('ioreg -n "%s"'%(self.OSX_MS_NAME,), - shell=True, stdout=subprocess.PIPE).stdout.read() - devname = re.search(r'BSD Name.*=\s+"(\S+)"', src).group(1) - except: - devname = None - if devname is not None: - self._card_prefix = re.search('/dev/%s(\w*)\s+on\s+([^\(]+)\s+'%(devname,), mount).group(2) + os.sep - - - def open_windows(self): - raise NotImplementedError - - - def open_linux(self): - import dbus - bus = dbus.SystemBus() - hm = dbus.Interface(bus.get_object("org.freedesktop.Hal", "/org/freedesktop/Hal/Manager"), "org.freedesktop.Hal.Manager") - try: - mm = hm.FindDeviceStringMatch('kindle.mainvolume', self.__class__.__name__)[0] - except: - raise DeviceError('Unable to find %s. Is it connected?'%(self.__class__.__name__,)) - try: - sc = hm.FindDeviceStringMatch('kindle.cardvolume', self.__class__.__name__)[0] - except: - sc = None - - def conditional_mount(dev): - mmo = bus.get_object("org.freedesktop.Hal", dev) - label = mmo.GetPropertyString('volume.label', dbus_interface='org.freedesktop.Hal.Device') - is_mounted = mmo.GetPropertyString('volume.is_mounted', dbus_interface='org.freedesktop.Hal.Device') - mount_point = mmo.GetPropertyString('volume.mount_point', dbus_interface='org.freedesktop.Hal.Device') - fstype = mmo.GetPropertyString('volume.fstype', dbus_interface='org.freedesktop.Hal.Device') - if is_mounted: - return str(mount_point) - mmo.Mount(label, fstype, ['umask=077', 'uid='+str(os.getuid()), 'sync'], - dbus_interface='org.freedesktop.Hal.Device.Volume') - return os.path.normpath('/media/'+label)+'/' - - self._main_prefix = conditional_mount(mm)+os.sep - self._card_prefix = None - if sc is not None: - self._card_prefix = conditional_mount(sc)+os.sep - - def open(self): - time.sleep(5) - self._main_prefix = self._card_prefix = None - if islinux: - try: - self.open_linux() - except DeviceError: - time.sleep(3) - self.open_linux() - if iswindows: - try: - self.open_windows() - except DeviceError: - time.sleep(3) - self.open_windows() - if isosx: - try: - self.open_osx() - except DeviceError: - time.sleep(3) - self.open_osx() - - - def set_progress_reporter(self, pr): - self.report_progress = pr - - def get_device_information(self, end_session=True): - return ('Kindle', '', '', '') - - def card_prefix(self, end_session=True): - return self._card_prefix - - @classmethod - def _windows_space(cls, prefix): - if prefix is None: - return 0, 0 - import win32file - sectors_per_cluster, bytes_per_sector, free_clusters, total_clusters = \ - win32file.GetDiskFreeSpace(prefix[:-1]) - mult = sectors_per_cluster * bytes_per_sector - return total_clusters * mult, free_clusters * mult - - def total_space(self, end_session=True): - msz = csz = 0 - if not iswindows: - if self._main_prefix is not None: - stats = os.statvfs(self._main_prefix) - msz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree) - if self._card_prefix is not None: - stats = os.statvfs(self._card_prefix) - csz = stats.f_frsize * (stats.f_blocks + stats.f_bavail - stats.f_bfree) - else: - msz = self._windows_space(self._main_prefix)[0] - csz = self._windows_space(self._card_prefix)[0] - - return (msz, 0, csz) - - def free_space(self, end_session=True): - msz = csz = 0 - if not iswindows: - if self._main_prefix is not None: - stats = os.statvfs(self._main_prefix) - msz = stats.f_bsize * stats.f_bavail - if self._card_prefix is not None: - stats = os.statvfs(self._card_prefix) - csz = stats.f_bsize * stats.f_bavail - else: - msz = self._windows_space(self._main_prefix)[1] - csz = self._windows_space(self._card_prefix)[1] - - return (msz, 0, csz) - - def books(self, oncard=False, end_session=True): - if oncard and self._card_prefix is None: - return [] - prefix = self._card_prefix if oncard else self._main_prefix - bl = BookList(prefix) - return bl - - def munge_path(self, path): - if path.startswith('/') and not (path.startswith(self._main_prefix) or \ - (self._card_prefix and path.startswith(self._card_prefix))): - path = self._main_prefix + path[1:] - elif path.startswith('card:'): - path = path.replace('card:', self._card_prefix[:-1]) - return path - - def mkdir(self, path, end_session=True): - """ Make directory """ - path = self.munge_path(path) - os.mkdir(path) - - def list(self, path, recurse=False, end_session=True, munge=True): - if munge: - path = self.munge_path(path) - if os.path.isfile(path): - return [(os.path.dirname(path), [File(path)])] - entries = [File(os.path.join(path, f)) for f in os.listdir(path)] - dirs = [(path, entries)] - for _file in entries: - if recurse and _file.is_dir: - dirs[len(dirs):] = self.list(_file.path, recurse=True, munge=False) - return dirs - - def get_file(self, path, outfile, end_session=True): - path = self.munge_path(path) - src = open(path, 'rb') - shutil.copyfileobj(src, outfile, 10*1024*1024) - - def put_file(self, infile, path, replace_file=False, end_session=True): - path = self.munge_path(path) - if os.path.isdir(path): - path = os.path.join(path, infile.name) - if not replace_file and os.path.exists(path): - raise PathError('File already exists: '+path) - dest = open(path, 'wb') - shutil.copyfileobj(infile, dest, 10*1024*1024) - dest.flush() - dest.close() - - def rm(self, path, end_session=True): - path = self.munge_path(path) - os.unlink(path) - - def touch(self, path, end_session=True): - path = self.munge_path(path) - if not os.path.exists(path): - open(path, 'w').close() - if not os.path.isdir(path): - os.utime(path, None) - - def upload_books(self, files, names, on_card=False, end_session=True): - path = os.path.join(self._card_prefix, "documents") if on_card \ - else os.path.join(self._main_prefix, 'documents') - infiles = [file if hasattr(file, 'read') else open(file, 'rb') for file in files] - for f in infiles: f.seek(0, 2) - sizes = [f.tell() for f in infiles] - size = sum(sizes) - space = self.free_space() - mspace = space[0] - cspace = space[2] - if on_card and size > cspace - 1024*1024: - raise FreeSpaceError("There is insufficient free space "+\ - "on the storage card") - if not on_card and size > mspace - 2*1024*1024: - raise FreeSpaceError("There is insufficient free space " +\ - "in main memory") - - paths, ctimes = [], [] - - names = iter(names) - for infile in infiles: - infile.seek(0) - name = names.next() - paths.append(os.path.join(path, name)) - if on_card and not os.path.exists(os.path.dirname(paths[-1])): - os.mkdir(os.path.dirname(paths[-1])) - self.put_file(infile, paths[-1], replace_file=True) - ctimes.append(os.path.getctime(paths[-1])) - return zip(paths, sizes, ctimes, cycle([on_card])) - - @classmethod - def add_books_to_metadata(cls, locations, metadata, booklists): - metadata = iter(metadata) - for location in locations: - #info = metadata.next() - path = location[0] - on_card = 1 if location[3] else 0 - name = path.rpartition(os.sep)[2] - name = name.replace('//', '/') - booklists[on_card].add_book(name,*location[1:-1]) - - def delete_books(self, paths, end_session=True): - for path in paths: - os.unlink(path) - - @classmethod - def remove_books_from_metadata(cls, paths, booklists): - for path in paths: - for bl in booklists: - bl.remove_book(path) - - - def sync_booklists(self, booklists, end_session=True): - return 0; - - -def main(args=sys.argv): - return 0 - -if __name__ == '__main__': - sys.exit(main()) \ No newline at end of file +__copyright__ = '2009, John Schember ' +''' +Device driver for Amazon's Kindle +''' + +import os, fnmatch + +from calibre.devices.usbms.driver import USBMS +from calibre.devices.usbms.cli import CLI + +class KINDLE(USBMS, CLI): + MIME_MAP = { + 'azw' : 'application/azw', + 'mobi' : 'application/mobi', + 'prc' : 'application/prc', + 'txt' : 'text/plain', + } + # Ordered list of supported formats + FORMATS = MIME_MAP.keys() + + VENDOR_ID = 0x1949 + PRODUCT_ID = 0x0001 + BCD = 0x399 + + VENDOR_NAME = 'AMAZON' + PRODUCT_NAME = 'KINDLE' + + MAIN_MEMORY_VOLUME_LABEL = 'Kindle Main Memory' + STORAGE_CARD_VOLUME_LABEL = 'Kindle Storage Card' + + EBOOK_DIR = "documents" +