Visão geral do USSD

USSD (Dados de Serviço Suplementar Não Estruturados) é um protocolo de comunicação usado por dispositivos GSM (Sistema Global de Comunicações Móveis) para se comunicar com as operadoras de rede móvel (normalmente conhecidas como simplesmente "MO").

Para entender o USSD, é útil compará-lo com seu irmão mais próximo: SMS (serviço de mensagens curtas). USSD e SMS são ambos padrões de GSM, o que significa que eles foram introduzidos como recursos na segunda geração de dispositivos móveis. No entanto, em contraste com o SMS, o USSD é uma conexão baseada em sessão. Embora o SMS seja usado para mensagens curtas sem sessão, o USSD normalmente é usado para comando e controle de um dispositivo móvel. Como é necessário manter uma sessão, o USSD não dá suporte à funcionalidade de armazenamento e encaminhamento, como o SMS faz. As mensagens USSD e SMS são enviadas com caracteres compatíveis com GSM de 7 bits, mas o USSD é máximo em 184 caracteres, em contraste com 160 para SMS.

Mensagens USSD podem ser enviadas de um telefone celular abrindo o discador e digitando um código. Nem todos os códigos são compatíveis com todos os telefones ou MO. Em alguns casos, o software ou sistema operacional do telefone pode impedir o envio manual de códigos. Um código necessário que deve ser implementado é *#06#. Esse código retorna o IMEI (International Mobile Equipment Identifier) do modem, mas alguns telefones impedirão que você disce isso diretamente. Se você seguir os meios convencionais de localizar o IMEI do modem por meio das configurações do telefone, esse número foi recuperado usando esse código.

Se o hardware do telefone puder lidar diretamente com o comando de um código, como no exemplo IMEI, nenhuma sessão de rede será iniciada. Outros códigos que exigem comunicação de rede abrirão uma sessão e enviarão uma mensagem que consiste em um comando e quaisquer parâmetros necessários, se aplicável. Um exemplo disso é um código que verifica o saldo atual e o plano status com o MO.

O USSD no Windows é implementado como uma superfície de API do WinRT. As classes de implementação dessa interface servem como a máquina de estado para sessões USSD, mas, por fim, dependem do Serviço WWAN para fazer o trabalho pesado. Essas APIs são implementadas com um padrão de fábrica.

Implementando USSD

Um ponto importante a ser lembrado é que a API voltada para o público é definida pela IDL. A implementação pode ser confusa devido a isso, especialmente se você não estiver familiarizado com o WinRT. Parte da confusão vem do uso aparentemente ambíguo da palavra "fábrica". Uma fábrica pode se referir a uma implementação de classe de uma interface estática ou a uma fábrica verdadeira que fornece uma interface ativável para uma classe de runtime.

Este tópico analisa os conceitos do WinRT e descreve a implementação com base nesses conceitos. Você sempre pode consultar a IDL para obter mais esclarecimentos.

Interfaces

As interfaces definem a ABI (Interface Binária do Aplicativo). Eles descrevem as funções que você pode chamar em qualquer classe que implemente a interface .

Runtime Classes

Essas são as classes reais. Eles representam, por nome, o que é, em última análise, exposto como nomes de classe para a ABI. Cada classe de runtime pode ter zero ou mais interfaces (mas deve declarar pelo menos uma interface padrão se tiver uma ou mais interfaces), zero ou mais interfaces estáticas e uma marca ativável, se necessário. Cada uma dessas interfaces é implementada em arquivos diferentes como classes "Impl" diferentes, mas elas parecerão ser uma única classe unificada para a ABI.

Uma interface típica aparece como métodos de instância em um objeto existente.

Uma interface estática aparece para o cliente como métodos estáticos na própria classe de runtime.

Uma marca ativável define a interface de fábrica que produzirá uma instância de uma classe de runtime. Isso é completamente ofuscado para o cliente, aparecendo como um construtor para essa classe de runtime.

Implementação de USSD

Diagrama mostrando a implementação de USSD.

Fluxo: Abrir, Enviar, Receber, Fechar.

Abrir, Enviar

Diagrama de fluxo mostrando a solicitação USSD com o processo de resposta.

  1. O cliente usa uma das funções estáticas UssdSession.CreateFromNetworkAccountId ou UssdSession.CreateFromNetworkInterfaceId para criar o objeto UssdSession.

  2. Independentemente da API chamada, uma ID de interface de rede é necessária para inicializar uma UssdSession. No caso de *NetworkAccountID, são executadas etapas para recuperar a ID do adaptador de rede da ID da Conta. CreateInternal() é chamado para criar uma instância de UssdSession e invocar Initialize() na instância recém-criada. Durante as etapas de inicialização, um thread de trabalho é ativado e um identificador de evento para disparar eventos para o thread é criado. As etapas 3 e 4 também ocorrem durante o Initialize() da instância.

  3. Initialize() é chamado no objeto membro WwanWrapper. Essa função aceita uma função de retorno de chamada estática, bem como um contexto para permitir que a função estática mapeie o retorno de chamada para um contexto de objeto.

  4. O WwanWrapper abre um identificador para wwanService, enumera interfaces e assina notificações de USSD fornecendo um ponteiro de função de retorno de chamada estático e "isso" como contexto.

  5. O objeto UssdSession é retornado ao cliente.

  6. O cliente constrói um novo UssdMessage invocando o construtor com uma cadeia de caracteres de mensagem. O WinRT ofusca o UssdMessageFactory nesse processo.

  7. O cliente invoca SendMessageAndGetReplyAsync no objeto de sessão, passando a instância ussdMessage.

  8. Neste momento, SendMessageAndGetReplyAsync cria um objeto de operação especial chamado UssdSendMessageAndGetReplyOperation. A partir do nome, parece que o objeto encapsula a lógica de uma única mensagem sendo enviada para baixo da pilha (e aguardando resposta), mas esse não é o caso. O WinRT requer um parâmetro de saída especial para operações assíncronas, que podemos ver como o segundo parâmetro na definição dessa função.

    HRESULT SendMessageAndGetReplyAsync(
                [in] UssdMessage* message,
                [out, retval] Windows.Foundation.IAsyncOperation<UssdReply>** asyncInfo);
    

    É a IUssdSendMessageAndGetReplyOperation, uma interface nomeada por meio de typedef, que satisfaz esse parâmetro prometendo que essa operação inevitavelmente retornará ussdReply. Essa interface não é definida na IDL, mas é implementada pela classe UssdSendMessageAndGetReplyOperationImpl. Observe que o cabeçalho dessa classe tem uma extensão especial:

    class UssdSendMessageAndGetReplyOperationImpl :
        public Microsoft::WRL::RuntimeClass<
            Windows::Networking::NetworkOperators::IUssdSendMessageAndGetReplyOperation,
            Windows::Internal::AsyncBaseFTM<IUssdSendMessageAndGetReplyCompletedHandler, Microsoft::WRL::SingleResult>>
    

    O objeto UssdSendMessageAndGetReplyOperation permite que o WinRT ofuscar as complexidades dessa operação assíncrona e toda a compartimentalização e proxy de memória que acompanha isso. Para obter mais informações, consulte SendMessageAndGetReplyAsync.

    Por enquanto, entenda que a operação assíncrona descrita acima simplesmente chama de volta para o objeto UssdSession em que a lógica dessa operação está realmente contida. Podemos visualizar para simplificar que o próprio UssdSession encapsula o trabalho aqui. Agora podemos afirmar que, apesar da natureza assíncrona, apenas um UssdMessage pode ser enviado por vez.

    O que a função SendMessageAndGetReplyAsync realmente faz:

    • O objeto UssdSession muda para um estado ocupado, armazena o conteúdo do UssdMessage e dispara a ação assíncrona.
    • OnOperationStart() é o ponto de entrada para a lógica assíncrona. Suponha que, para esse cenário, não haja nenhuma sessão ativa. Essa função cria um objeto WWAN_USSD_REQUEST com RequestType=WwanUssdRequestInitiate.
    • As etapas 9 e 10 ocorrem como ações executadas por essa função.
  9. m_wwanWrapper.SendRequest é invocado para lidar com o trabalho de passar a mensagem para WwanService.

  10. O WwanWrapper usa o identificador WwanService para invocar APIs WwanService para executar a ação.

Receber

Diagrama de fluxo ilustrando o processo de recebimento de USSD.

Após a etapa 10, ficamos em um estado em que uma solicitação foi enviada ao WwanService para inicializar uma nova sessão de USSD e enviar uma mensagem USSD nessa sessão. Após algum tempo, a resposta estará disponível.

  1. O WwanService invocará a função de retorno de chamada estática fornecida na etapa 4 com o contexto que também foi anexado.
  2. O contexto será usado para recuperar a instância do WwanWrapper e invocar NotificationCallback().
  3. O WwanWrapper seguirá o mesmo padrão da etapa 11, invocando um retorno de chamada estático para UssdSession, fornecendo o contexto armazenado na etapa 3.
  4. Semelhante à etapa 12, o contexto é usado para invocar o retorno de chamada em uma instância de UssdSession.
  5. A UssdSession armazena o WWAN_USSD_EVENT (em um bloqueio) e notifica o thread de trabalho para manipular o evento.
  6. HandleOperationReply() usa o objeto UssdSendMessageAndGetReplyOperationImpl existente e passa os dados do evento para seu manipulador interno.
  7. A operação construirá e UssdReply e invocará FireCompletion() para marcar a ação assíncrona como concluída.
  8. O WinRT ofusca a conclusão da ação assíncrona para o cliente. (Eles aguardaram a ação ou têm lógica de retorno de chamada.)

Mais mensagens podem ser enviadas na mesma sessão. Se a sessão tiver sido mantida, o RequestType futuro será WwanUssdRequestContinue.

Fechar

Diagrama de fluxo mostrando o processo de fechamento do USSD.

Após a etapa 18, o cliente recebeu a resposta para seu UssdMessage. Eles podem ou não ter continuado a usar a UssdSession ativa para enviar mensagens adicionais. Vamos supor que, em algum momento no futuro, o cliente invocará Close() manualmente na UssdSession. Se o cliente não invocar Close(explicitamente), ele será chamado durante o destruidor de UssdSession.

  1. O cliente invoca Close() na instância ussdSession.
  2. Um WWAN_USSD_REQUEST é criado com RequestType=WwanUssdRequestCancel.
  3. A solicitação é enviada para m_wwanWrapper como na etapa 9.
  4. A solicitação é enviada ao WwanService como na etapa 10.

O resultado dessa solicitação não é importante. Para todas as intenções e finalidades, a sessão é fechada. Mesmo no caso de borda extrema em que a mensagem nunca é entregue, uma nova sessão de USSD sempre substituirá uma sessão existente.

Testes do HLK (Hardware Lab Kit)

Consulte Etapas para instalar o HLK.

No HLK Studio, conecte-se ao driver de modem celular do dispositivo e execute o teste: Win6_4.MB. GSM. Data.TestUssd.

Guia de solução de problemas do MB USSD

  • Colete e decodize os logs usando as instruções em MB Coletando logs.

  • Palavras-chave para filtragem

    1. OID_WWAN_USSD
    2. NDIS_STATUS_WWAN_USSD
    3. WWAN_USSD_REQUEST
    4. WWAN_USSD_EVENT

Consulte Também

Operações de USSD do MB