-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathusb_modem_switch_operation.h
189 lines (154 loc) · 7.73 KB
/
usb_modem_switch_operation.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
// 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/callback.h>
#include <base/cancelable_callback.h>
#include <base/macros.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 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:
using CompletionCallback =
base::Callback<void(UsbModemSwitchOperation* operation, bool success)>;
// 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:
using Task = void (UsbModemSwitchOperation::*)();
using UsbTransferCompletionHandler =
void (UsbModemSwitchOperation::*)(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();
// Starts waiting for the device to reconnect to the USB bus.
void StartWaitingForDeviceToReconnect();
// 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 a specified period time since
// StartWaitingForDeviceToReconnect() is invoked.
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_