blob: 613e5624050ee2207f6cf81c750f9c671b1210fc [file] [log] [blame]
// Copyright 2021 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 HERMES_MODEM_MBIM_H_
#define HERMES_MODEM_MBIM_H_
#include <deque>
#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include <glib-bridge/glib_bridge.h>
#include <glib-bridge/glib_logger.h>
#include <glib-bridge/glib_scopers.h>
#include <google-lpa/lpa/card/euicc_card.h>
#include <libmbim-glib/libmbim-glib.h>
#include <libmbim-glib/mbim-enums.h>
#include "hermes/euicc_interface.h"
#include "hermes/executor.h"
#include "hermes/logger.h"
#include "hermes/mbim_cmd.h"
#include "hermes/modem.h"
#include "hermes/modem_control_interface.h"
#include "hermes/socket_interface.h"
namespace hermes {
// Implementation of EuiccCard using MBIM
// messages.
class ModemMbim : public Modem<MbimCmd> {
public:
static std::unique_ptr<ModemMbim> Create(Logger* logger, Executor* executor);
virtual ~ModemMbim();
// EuiccInterface overrides
void Initialize(EuiccManagerInterface* euicc_manager,
ResultCallback cb) override;
void StoreAndSetActiveSlot(const uint32_t physical_slot,
ResultCallback cb) override;
void StartProfileOp(const uint32_t physical_slot, ResultCallback cb) override;
void FinishProfileOp(ResultCallback cb) override;
void RestoreActiveSlot(ResultCallback cb) override;
bool IsSimValidAfterEnable() override;
bool IsSimValidAfterDisable() override;
private:
ModemMbim(GFile* file, Logger* logger, Executor* executor);
void Shutdown() override;
void TransmitFromQueue() override;
std::unique_ptr<MbimCmd> GetTagForSendApdu() override;
void ProcessMbimResult(int err);
static void MbimCreateNewDeviceCb(GObject* source,
GAsyncResult* res,
ModemMbim* modem_mbim);
static void MbimDeviceOpenReadyCb(MbimDevice* dev,
GAsyncResult* res,
ModemMbim* modem_mbim);
void TransmitSubscriberReadyStatusQuery();
void TransmitMbimLoadCurrentCapabilities();
void TransmitMbimCloseChannel();
void TransmitMbimOpenLogicalChannel();
void TransmitMbimSendEidApdu();
void TransmitMbimSendApdu(TxElement* tx_element);
void QueryCurrentMbimCapabilities(ResultCallback cb);
void AcquireChannel(base::OnceCallback<void(int)> cb);
void ReacquireChannel(const uint32_t physical_slot, ResultCallback cb);
void GetEidFromSim(ResultCallback cb);
void GetEidStepCloseChannel(ResultCallback cb);
void GetEidStepOpenChannel(ResultCallback cb);
static void SubscriberReadyStatusRspCb(MbimDevice* device,
GAsyncResult* res,
ModemMbim* modem_mbim);
static void DeviceCapsQueryReady(MbimDevice* device,
GAsyncResult* res,
ModemMbim* modem_mbim);
static void UiccLowLevelAccessCloseChannelSetCb(MbimDevice* device,
GAsyncResult* res,
ModemMbim* modem_mbim);
static void UiccLowLevelAccessOpenChannelSetCb(MbimDevice* device,
GAsyncResult* res,
ModemMbim* modem_mbim);
static void UiccLowLevelAccessApduEidParse(MbimDevice* device,
GAsyncResult* res,
ModemMbim* modem_mbim);
static void UiccLowLevelAccessApduResponseParse(MbimDevice* device,
GAsyncResult* res,
ModemMbim* modem_mbim);
static void ClientIndicationCb(MbimDevice* device,
MbimMessage* notification,
ModemMbim* modem_mbim);
void CloseDevice();
///////////////////
// State Diagram //
///////////////////
//
// Uninitialized --------------------------------> InitializeStarted
// Initialize()
// InitializeStarted ----------------------------> MbimStarted
// GetEidFromSim()
class State {
public:
enum Value : uint8_t {
kMbimUninitialized,
kMbimInitializeStarted,
kMbimStarted,
};
State() : value_(kMbimUninitialized) {}
// Transitions to the indicated state. Returns whether or not the
// transition was successful.
bool Transition(Value value);
bool operator==(Value value) const { return value_ == value; }
bool operator!=(Value value) const { return value_ != value; }
friend std::ostream& operator<<(std::ostream& os, const State state) {
switch (state.value_) {
case kMbimUninitialized:
os << "Uninitialized";
break;
case kMbimInitializeStarted:
os << "InitializeStarted";
break;
case kMbimStarted:
os << "MbimStarted";
break;
}
return os;
}
private:
explicit State(Value value) : value_(value) {}
Value value_;
};
State current_state_;
ResultCallback init_done_cb_;
std::string eid_;
guint32 channel_;
glib_bridge::ScopedGObject<MbimDevice> device_;
uint8_t indication_id_;
bool pending_response_;
MbimSubscriberReadyState ready_state_;
GFile* file_ = NULL;
bool is_ready_state_valid;
base::WeakPtrFactory<ModemMbim> weak_factory_;
};
} // namespace hermes
#endif // HERMES_MODEM_MBIM_H_