blob: 9ede70d61ddfcd69c7c8e84a727c7223399fcafa [file] [log] [blame]
# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""The control interface of USB printer exposed to chameleond user."""
import logging
import os
import tempfile
from chameleond.devices import chameleon_device
from chameleond.utils import system_tools
from chameleond.utils import usb_printer_control
class USBPrinterError(Exception):
"""Exception raised when any error occurs in USBPrinter."""
pass
class USBPrinter(object):
"""The control interface of USB printer module driver."""
def __init__(self, usb_ctrl):
"""Initializes a USBPrinter object.
Args:
usb_ctrl: A USBPrinterController object that USBPrinter keep
reference to.
"""
self._usb_ctrl = usb_ctrl
self._subprocess = None
def IsDetected(self):
"""Returns if the device can be detected."""
return self._usb_ctrl.DetectDriver()
def InitDevice(self):
"""Enables USB port controller.
Enables USB port device mode controller so USB host on the other side will
not get confused when trying to enumerate this USB device.
"""
self._usb_ctrl.EnableUSBOTGDriver()
logging.info('Initialized USB device mode for printer')
@property
def _subprocess_is_running(self):
"""The subprocess spawned for running a command is running.
Returns:
True if subprocess has yet to return a result.
False if there is no subprocess spawned yet, or if the subprocess has
returned a value.
"""
if self._subprocess is None:
return False
elif self._subprocess.poll() is None:
return True
else:
return False
@property
def is_capturing_printer_data(self):
"""USBPrinter is capturing printer data from USB Host.
Returns:
True if USBPrinter is capturing printer data.
"""
return self._subprocess_is_running
def StartCapturingPrinterData(self):
"""Starts capturing printer data.
Raises:
USBPrinterError: If printer is not plugged.
"""
if not self.IsPlugged():
raise USBPrinterError('Should start capturing printer data after plug.')
recorded_file = tempfile.NamedTemporaryFile(prefix='printer_',
suffix='.raw',
delete=False)
self._file_path = recorded_file.name
self._file_handle = open(self._file_path, 'w')
self._subprocess = system_tools.SystemTools.RunInSubprocessOutputToFile(
'printer', self._file_handle, '-read_data')
logging.info('Started capturing printer data to %s', self._file_path)
def StopCapturingPrinterData(self):
"""Stops capturing printer data.
Returns:
The path to the captured printer data.
Raises:
USBPrinterError if this is called before StartCapturingPrinterData()
is called.
"""
if self._subprocess is None:
raise USBPrinterError('Stop capturing printer data before start.')
elif self._subprocess.poll() is None:
self._subprocess.terminate()
logging.info('Stopped capturing printer data.')
else:
raise USBPrinterError('Printer capturing process stopped unexpectedly')
self._subprocess = None
self._file_handle.close()
return self._file_path
def Reset(self):
"""Resets USBPrinter.
Stops capturing. Set printer model to the default model.
Then, unplug printer.
"""
if self.is_capturing_printer_data:
self.StopCapturingPrinterData()
self._usb_ctrl.ResetPrinterModel()
self.Unplug()
def IsPlugged(self):
"""Returns a Boolean value reflecting the status of USB printer driver.
Returns:
True if USB printer gadget driver is enabled. False otherwise.
"""
return self._usb_ctrl.DriverIsEnabled()
def Plug(self):
"""Emulates plug for USB printer by enabling printer gadget driver."""
self._usb_ctrl.EnableDriver()
def Unplug(self):
"""Emulates unplug for USB printer by disabling printer gadget driver."""
self._usb_ctrl.DisableDriver()
def SetPrinterModel(self, vendor_id, product_id, name):
"""Sets printer model with vendor_id, product_id, and name.
Args:
vendor_id: A number for vendor_id.
product_id: A number for product_id.
name: A name for printer product name.
Raises:
USBPrinterError if it is capturing printer data.
"""
if self.is_capturing_printer_data:
raise USBPrinterError('Can not set printer model while capturing')
printer_model = usb_printer_control.PrinterModel(vendor_id, product_id, name)
self._usb_ctrl.SetPrinterModel(printer_model)