// Copyright (c) 2013 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.

#ifndef MIST_USB_MODEM_SWITCH_OPERATION_H_
#define MIST_USB_MODEM_SWITCH_OPERATION_H_

#include <stdint.h>

#include <memory>
#include <string>

#include <base/basictypes.h>
#include <base/callback.h>
#include <base/cancelable_callback.h>
#include <base/compiler_specific.h>
#include <base/memory/weak_ptr.h>
#include <base/time/time.h>

#include "mist/usb_device_event_observer.h"

namespace mist {

class Context;
class UsbBulkTransfer;
class UsbDevice;
class UsbModemInfo;
class UsbModemSwitchContext;
class UsbTransfer;

// A USB modem switch operation for switching a USB modem into the modem mode.
// The whole operation involves the following tasks:
// 1. Open the USB modem device. If the modem has a USB configuration that
//    exposes a MBIM interface, select that configuration and complete the
//    switch operation. Otherwise, find and claim the mass storage interface of
//    the mdoem.
// 2. Initiate a bulk output transfer of a (or multiple) special USB message(s)
//    to the mass storage endpoint of the modem.
// 3. On some modems, a bulk input transfer from the mass storage endpoint of
//    the modem is expected after completing each bulk output transfer.
// 4. Once the transfer of the last message completes, the modem is expected to
//    disconnect from the USB bus and then reconnect to the bus after it has
//    been switched to the modem mode.
//
// As mist may run multiple modem switch operations concurrently, in order to
// maximize the overall concurrency, the modem switch operation is broken up
// into the aforementioned tasks and each task is scheduled to execute in the
// message loop via EventDispatcher.
class UsbModemSwitchOperation
    : public base::SupportsWeakPtr<UsbModemSwitchOperation>,
      public UsbDeviceEventObserver {
 public:
  typedef base::Callback<void(UsbModemSwitchOperation* operation, bool success)>
      CompletionCallback;

  // Constructs a UsbModemSwitchOperation object by taking a raw pointer to a
  // Context object as |context| and a raw pointer to a UsbModemSwitchContext
  // object as |switch_context| that contains information about the device to
  // be switched to the modem mode. The ownership of |context| is not
  // transferred, and thus it should outlive this object. The ownership of
  // |switch_context| is transferred.
  UsbModemSwitchOperation(Context* context,
                          UsbModemSwitchContext* switch_context);

  ~UsbModemSwitchOperation();

  // Starts the modem switch operation. Upon the completion of the operation,
  // the completion callback |completion_callback| is invoked with the status
  // of the operation.
  void Start(const CompletionCallback& completion_callback);

  // Cancels the modem switch operation and closes any open device. It is a
  // no-op if the operation has not been started by Start().
  void Cancel();

 private:
  typedef void (UsbModemSwitchOperation::*Task)();
  typedef void (UsbModemSwitchOperation::*UsbTransferCompletionHandler)(
      UsbTransfer* transfer);

  // Schedules the specified |task| in the message loop for execution. At most
  // one pending task is allowed, so any pending task previously scheduled by
  // ScheduleTask() or ScheduleDelayedTask() is cancelled before |task| is
  // scheduled.
  void ScheduleTask(Task task);

  // Schedules the specified |task| in the message loop for execution after the
  // specified |delay|. At most one pending task is allowed, so any pending
  // task previously scheduled by ScheduleTask() or ScheduleDelayedTask() is
  // cancelled before |task| is scheduled.
  void ScheduleDelayedTask(Task task, const base::TimeDelta& delay);

  // Completes the operation, which invokes the completion callback with the
  // status of the operation as |success|. The completion callback may delete
  // this object, so this object should not be accessed after this method
  // returns.
  void Complete(bool success);

  // Detaches all the kernel drivers associated with the interfaces of the
  // currently active USB configuration. Continues to detach other kernel
  // drivers if it fails to detach any driver.
  void DetachAllKernelDrivers();

  // Returns the value of the USB configuration at which the device exposes a
  // MBIM interface, or kUsbConfigurationValueInvalid if no MBIM interface is
  // found.
  int GetMBIMConfigurationValue();

  // Sets the USB configuration of the device to |configuration|. Returns true
  // on success.
  bool SetConfiguration(int configuration);

  // Closes the device.
  void CloseDevice();

  // Opens the device. If the device has a USB configuration that exposes a MBIM
  // interface, selects that configuration and completes the switch operation.
  // Otherwise, finds and claims the mass storage interface on the device.
  void OpenDeviceAndSelectInterface();

  // Clears the halt condition on the endpoint at |endpoint_address|. Returns
  // true on success.
  bool ClearHalt(uint8_t endpoint_address);

  // Sends a special USB message to the mass storage endpoint of the device.
  void SendMessageToMassStorageEndpoint();

  // Receives a USB message from the mass storage endpoint of the device.
  void ReceiveMessageFromMassStorageEndpoint();

  // Creates and submits a USB bulk transfer to the specified |endpoint_address|
  // on the device. |length| specifies the size of the transfer in bytes. For a
  // host-to-device transfer, |data| should point to a buffer containing
  // |length| bytes of data to be transferred. For a device-to-host transfer,
  // |data| is not used and thus ignored. |completion_handler| will be invoked
  // upon the completion of the transfer.
  void InitiateUsbBulkTransfer(uint8_t endpoint_address,
                               const uint8_t* data,
                               int length,
                               UsbTransferCompletionHandler completion_handler);

  // Schedules the invocation of SendMessageToMassStorageEndpoint() on the next
  // USB message to be sent to the mass storage endpoint of the device, or when
  // there is no more message to send, schedule the wait for the device to
  // reconnect.
  void ScheduleNextMessageToMassStorageEndpoint();

  // Invoked upon the completion of the last USB bulk transfer submitted by
  // SendMessageToMassStorageEndpoint().
  void OnSendMessageCompleted(UsbTransfer* transfer);

  // Invoked upon the completion of the last USB bulk transfer submitted by
  // ReceiveMessageFromMassStorageEndpoint().
  void OnReceiveMessageCompleted(UsbTransfer* transfer);

  // Invoked when this switcher times out waiting for the device to reconnect to
  // the bus, after the special USB message(s) is sent to the mass storage
  // endpoint by SendMessageToMassStorageEndpoint().
  void OnReconnectTimeout();

  // Implements UsbDeviceEventObserver.
  void OnUsbDeviceAdded(const std::string& sys_path,
                        uint8_t bus_number,
                        uint8_t device_address,
                        uint16_t vendor_id,
                        uint16_t product_id) override;
  void OnUsbDeviceRemoved(const std::string& sys_path) override;

  Context* const context_;
  std::unique_ptr<UsbModemSwitchContext> switch_context_;
  std::unique_ptr<UsbDevice> device_;
  CompletionCallback completion_callback_;
  bool interface_claimed_;
  uint8_t interface_number_;
  uint8_t in_endpoint_address_;
  uint8_t out_endpoint_address_;
  int message_index_;
  int num_usb_messages_;
  std::unique_ptr<UsbBulkTransfer> bulk_transfer_;
  base::CancelableClosure pending_task_;
  base::CancelableClosure reconnect_timeout_callback_;

  DISALLOW_COPY_AND_ASSIGN(UsbModemSwitchOperation);
};

}  // namespace mist

#endif  // MIST_USB_MODEM_SWITCH_OPERATION_H_
