%PDF- %PDF-
Direktori : /usr/lib/calibre/calibre/devices/usbms/ |
Current File : //usr/lib/calibre/calibre/devices/usbms/hal.py |
#!/usr/bin/env python3 # License: GPL v3 Copyright: 2021, Kovid Goyal <kovid at kovidgoyal.net> import time from jeepney import ( DBusAddress, DBusErrorResponse, MessageType, Properties, new_method_call ) from jeepney.io.blocking import open_dbus_connection from calibre.constants import DEBUG class HAL: def __init__(self): self.bus = open_dbus_connection('SYSTEM') def send(self, msg): reply = self.bus.send_and_get_reply(msg) if reply.header.message_type is MessageType.error: raise DBusErrorResponse(reply) return reply.body[0] def call(self, addr, method, sig='', *args): if sig: return self.send(new_method_call(addr, method, sig, args)) return self.send(new_method_call(addr, method)) def prop(self, addr, name): return self.send(Properties(addr).get(name)) def addr(self, path, interface): return DBusAddress(path, bus_name='org.freedesktop.Hal', interface=f'org.freedesktop.Hal.{interface}') def get_volume(self, vpath): vdevif = self.addr(vpath, 'Device') if not self.prop(vdevif, 'block.is_volume') or self.prop(vdevif, 'volume.fsusage') != 'filesystem': return volif = self.addr(vpath, 'Volume') pdevif = self.addr(self.prop(volif, 'info.parent'), 'Device') return {'node': self.prop(pdevif, 'block.device'), 'dev': vdevif, 'vol': volif, 'label': self.prop(vdevif, 'volume.label')} def get_volumes(self, d): vols = [] manager = self.addr('/org/freedesktop/Hal/Manager', 'Manager') paths = self.call(manager, 'FindDeviceStringMatch', 'ss', 'usb.serial', d.serial) for path in paths: objif = self.addr(path, 'Device') # Extra paranoia... try: if d.idVendor == self.prop(objif, 'usb.vendor_id') and \ d.idProduct == self.prop(objif, 'usb.product_id') and \ d.manufacturer == self.prop(objif, 'usb.vendor') and \ d.product == self.prop(objif, 'usb.product') and \ d.serial == self.prop(objif, 'usb.serial'): midpath = self.call(manager, 'FindDeviceStringMatch', 'ss', 'info.parent', path) dpaths = self.call(manager, 'FindDeviceStringMatch', 'ss', 'storage.originating_device', path ) + self.call(manager, 'FindDeviceStringMatch', 'ss', 'storage.originating_device', midpath[0]) for dpath in dpaths: try: vpaths = self.call(manager, 'FindDeviceStringMatch', 'block.storage_device', dpath) for vpath in vpaths: try: vol = self.get_volume(vpath) if vol is not None: vols.append(vol) except DBusErrorResponse as e: print(e) continue except DBusErrorResponse as e: print(e) continue except DBusErrorResponse: continue vols.sort(key=lambda x: x['node']) return vols def get_mount_point(self, vol): if not self.prop(vol['dev'], 'volume.is_mounted'): fstype = self.prop(vol['dev'], 'volume.fstype') self.call(vol['vol'], 'Mount', 'ssas', 'Calibre-'+vol['label'], fstype, []) loops = 0 while not self.prop(vol['dev'], 'volume.is_mounted'): time.sleep(1) loops += 1 if loops > 100: raise Exception("ERROR: Timeout waiting for mount to complete") return self.prop(vol['dev'], 'volume.mount_point') def mount_volumes(self, volumes): mtd=0 ans = { '_main_prefix': None, '_main_vol': None, '_card_a_prefix': None, '_card_a_vol': None, '_card_b_prefix': None, '_card_b_vol': None, } for vol in volumes: try: mp = self.get_mount_point(vol) except Exception as e: print("Failed to mount: {vol['label']}", e) continue # Mount Point becomes Mount Path mp += '/' if DEBUG: print("FBSD: mounted", vol['label'], "on", mp) if mtd == 0: ans['_main_prefix'], ans['_main_vol'] = mp, vol['vol'] if DEBUG: print("FBSD: main = ", mp) elif mtd == 1: ans['_card_a_prefix'], ans['_card_a_vol'] = mp, vol['vol'] if DEBUG: print("FBSD: card a = ", mp) elif mtd == 2: ans['_card_b_prefix'], ans['_card_b_vol'] = mp, vol['vol'] if DEBUG: print("FBSD: card b = ", mp) break mtd += 1 return mtd > 0, ans def unmount(self, vol): try: self.call(vol, 'Unmount', 'as', []) except DBusErrorResponse as e: print('Unable to eject ', e) def get_hal(): if not hasattr(get_hal, 'ans'): get_hal.ans = HAL() return get_hal.ans