Udostępnij za pośrednictwem


Komunikacja ze sterownikiem RIL przy użyciu interfejsu IOemCellularModem

Ostrzeżenie

Interfejs API sieci komórkowej COM jest wycofany w systemie Windows 10. Ta zawartość jest dostarczana do obsługi konserwacji aplikacji OEM i operatora sieci komórkowej utworzonych w systemie Windows Phone 8.1.

Interfejs IOemCellularModem umożliwia komunikację ze sterownikiem OEM RIL. Jest to przypadek, w którym partnerzy mogą używać interfejsów API na liście dozwolonych platform ograniczonych (RPAL) do komunikowania się z modemem.

Aby uzyskać więcej informacji na temat interfejsów API COM dla sieci komórkowej, zobacz odniesienie do interfejsu API COM dla sieci komórkowej.

Korzystanie z interfejsów API COM w sieciach komórkowych

Aby użyć komórkowych interfejsów API modelu COM, pobierz wskaźnik do wystąpienia IOemCellular, wywołując metodę CoCreateInstanceFromApp. Aplikacja wywołująca potrzebuje tego wskaźnika do interfejsu IOemCellular, aby móc używać interfejsu IOemCellularModem.

Metoda IOemCellular::RegisterForOemModemExistenceChanges może służyć do wyświetlania listy modemów. Po wywołaniu metody, IOemCellularModemExistenceChange::OnOemModemAdded jest wywoływana z użyciem wskaźnika IOemCellularModem.

Ten kod przedstawia pobieranie wskaźnika IOemCellular za pomocą polecenia CoCreateInstanceFromApp. CoCreateInstanceFromApp może zwrócić jeden lub więcej wskaźników do określonych interfejsów. Żądany interfejs to IOemCellular, który jest określony przez zapytanie[0].pIID. OemCellular jest referencją do wspomagającej klasy COM; określa fabrykę aktywującą tę klasę.

    MULTI_QI query[1];
    query[0].pIID = &__uuidof(IOemCellular);
    query[0].pItf = nullptr;
    query[0].hr = S_OK;

    hr = CoCreateInstanceFromApp(__uuidof(OemCellular), nullptr, CLSCTX_INPROC_SERVER,
                                nullptr, _countof(query), query);
    ...

Ten kod przedstawia zarejestrowanie wskaźnika do IOemCellularModemExistenceChange za pomocą IOemCellular::RegisterForOemModemExistenceChanges. W poniższym kodzie jest to wskaźnik do CModems, który udostępnia interfejs IOemCellularModemExistenceChange.

    HRESULT hr;
    hr = m_spCellular->RegisterForOemModemExistenceChanges(this);

    ...

Ten kod pokazuje, jak zaimplementować metodę OnOemModemAdded i inne metody interfejsu IOemCellularModemExistenceChange .

class CModems : public IOemCellularModemExistenceChange, public CellBase
{
    ...

    // 
    // IOemCellularModemExistenceChange interface
    //
    IFACEMETHOD(OnOemModemAdded)(IOemCellularModem *pModem);
    IFACEMETHOD(OnOemModemRemoved)(IOemCellularModem *pModem);
    IFACEMETHOD(OnOemModemExistenceDone)();

    ...
};
IFACEMETHODIMP CModems::OnOemModemAdded(IOemCellularModem *pModem)
{
    ComPtr<IOemCellularModem> spModem(pModem);
    m_ModemList.push_back(spModem);
    return S_OK;
}

Wysyłanie nieprzezroczystych danych do RIL

Po otrzymaniu wskaźnika IOemCellularModem przez wywołanie OnOemModemAdded, można użyć IOemCellularModem::SendModemOpaqueCommand. Za kulisami, cellcore wywołuje funkcję RIL_DevSpecific z przekazanymi parametrami. Sterownik RIL obsługuje to żądanie i wysyła odpowiedź z powrotem do górnych warstw. Po dostarczeniu odpowiedzi wywołanie zwrotne do IModemOpaqueCommandCompletion::OnModemOpaqueCommandCompletion jest uruchamiane z wynikiem wywołania SendModemOpaqueCommand.

Ten kod pokazuje wysyłanie nieprzezroczystych danych za pomocą polecenia IOemCellularModem::SendModemOpaqueCommand.

    void CCellcoreComponent::CAgent::SetRadioPowerState(bool fPowerOn)
    {
        DWORD command[2];
        command[0] = CMD_SET_EQUIPMENTSTATE;
        command[1] = fPowerOn ? RIL_EQSTATE_FULL : RIL_EQSTATE_MINIMUM;
        m_spModem->SendModemOpaqueCommand(this, (BYTE*)command, sizeof(command), 
            (INT_PTR) CMD_SET_EQUIPMENTSTATE);
    ...

W poprzednim przykładzie kodu polecenie jest wysyłane do RIL w celu włączenia lub wyłączenia radia. Sterownik RIL powinien być zaprojektowany tak, aby obsługiwał dwa elementy danych DWORD po wywołaniu RIL_DevSpecific . Możesz zdefiniować własną strukturę i polecenia zgodnie z potrzebami. Po zakończeniu polecenia sterownik RIL wysyła odpowiedź, a następnie wywołanie zwrotne ukończenia (IModemOpaqueCommandCompletion::OnModemOpaqueCommandCompletion) zostaje wywołane.

Ten kod pokazuje obsługę zdarzenia zakończenia odbierania dla polecenia SendModemOpaqueCommand w poprzednim przykładzie.

IFACEMETHODIMP CCellcoreComponent::CAgent::OnModemOpaqueCommandCompletion (
            /* [in] */ HRESULT result,
            /* [size_is][in] */ BYTE *pOpaqueResponse,
            /* [in] */ DWORD cbSize,
            /* [in] */ INT_PTR context)
{
    if (SUCCEEDED(result))
    {
        if ((int)context == CMD_SET_EQUIPMENTSTATE)
        {
            //
            // add routine if it is necessary to handle completion.
            //
        }
    }

    return S_OK;
}

Uwaga

Maksymalny rozmiar żądania, odpowiedzi i powiadomienia — warstwa adaptacji RIL nakłada ograniczenie maksymalnego rozmiaru 0x2800 (10240) bajtów dla poleceń RIL, odpowiedzi i ładunków powiadomień. Ładunek przekraczający ten rozmiar spowoduje błąd krytyczny.

Otrzymywanie powiadomienia od RIL

Interfejs komórkowy udostępnia wiele powiadomień RIL, które zaczynają się od RIL_NOTIFY, takich jak RIL_NOTIFY_SIGNALQUALITY. Ale IOemCellularModem nie udostępnia domyślnej metody odbierania tych powiadomień RIL. Jedną z opcji jest użycie funkcji IOemCellularModem::RegisterForOpaqueModemNotifications dla tych powiadomień OEM RIL. Aby to zrobić, najpierw zdefiniuj własny komunikat powiadomienia RIL, który jest mniejszy niż RIL_NOTIFY_OEM_MAX, który jest zdefiniowany w RilAPITypes.h. Za każdym razem, gdy RIL wysyła powiadomienie OEM RIL, po zarejestrowaniu wskaźnika wywołania zwrotnego przez IOemCellularModem::RegisterForOpaqueModemNotifications zostaje wywołana funkcja IOpaqueModemNotifications::OnOpaqueModemNotifications.

Ten kod pokazuje, jak wywołać metodę IOemCellularModem::RegisterForOpaqueModemNotifications.

HRESULT CCellcoreComponent::CAgent::Initialize()
{
    ...
    IFFAILED_EXIT(m_spModem->RegisterForOpaqueModemNotifications(this));
    ...

Ten kod pokazuje, jak zaimplementować IOpaqueModemNotifications::OnOpaqueModemNotifications. Kod zawiera uchwyt wywołania zwrotnego powiadomień, który zwraca liczbę pasków sygnału. Zdefiniowane przez użytkownika powiadomienie RIL_NOTIFY_OEM_SIGNALSTRENGTH należy zaimplementować zarówno w aplikacji wywołującej, jak i w sterowniku RIL.

class CAgent : 
        public IOpaqueModemNotifications, 
        public IModemOpaqueCommandCompletion,
        public IPowerStateChange,
        public IPositionInfoCompletion,
        public IAgent
{
    ...

    //
    // IOpaqueModemNotifications
    //
    IFACEMETHOD(OnOpaqueModemNotifications)( 
    /* [in] */ DWORD dwCode,
    /* [in] */ BYTE *pOpaqueNotification,
    /* [in] */ DWORD cbSize);

                }
IFACEMETHODIMP CCellcoreComponent::CAgent::OnOpaqueModemNotifications( 
            /* [in] */ DWORD dwCode,
            /* [in] */ BYTE *pOpaqueNotification,
            /* [in] */ DWORD cbSize)
{
    wchar_t szResultString[STRING_BUF_LEN] = {0,};

    // check dwCode to fill notification result string.
    if (dwCode == RIL_NOTIFY_OEM_SIGNALSTRENGTH)
    {
        DWORD dwSignalBar;
        if (cbSize == sizeof(DWORD))
        {
            dwSignalBar = *((DWORD*)pOpaqueNotification);
        }
        else
        {
            dwSignalBar = -1;
        }

        swprintf_s(szResultString, STRING_BUF_LEN, L"Num of signal bars : %d", dwSignalBar );
    }
    else
    {
        swprintf_s(szResultString, STRING_BUF_LEN, L"Unknown Notification");
    }

    // send notification string.
    String ^ opaqueInfo = ref new String (szResultString);
    m_cellcore->OnOpaqueNotification(opaqueInfo);

    return S_OK;
}

Przewodnik projektowania interfejsu API COM sieci komórkowej

Referencja API COM dla komórek