| # 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) |