Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
USSD (Unstructured Supplementary Service Data) é um protocolo de comunicação usado por dispositivos GSM (Global System for Mobile Communications) para se comunicar com operadores de rede móvel (normalmente conhecidos como MO).
Para entender o USSD, ajuda compará-lo a seu irmão mais próximo, o SMS. O USSD e o SMS são padrões GSM, ou seja, eles foram introduzidos como recursos na segunda geração de dispositivos móveis. No entanto, em comparação com o SMS, o USSD é uma conexão baseada em sessão. Enquanto o SMS é usado para mensagens curtas sem sessão, o USSD normalmente é usado para comando e controle de um dispositivo móvel. Por ser necessário manter uma sessão, o USSD não oferece suporte à capacidade de armazenamento e encaminhamento, como o SMS. As mensagens USSD e SMS são enviadas com caracteres compatíveis com GSM de 7 bits, mas o USSD atinge o máximo de 184 caracteres, em comparação com os 160 do SMS.
As mensagens USSD podem ser enviadas de um telefone celular abrindo o teclado numérico e digitando um código. Nem todos os códigos são aceitos por todos os telefones ou MO. Em alguns casos, o software do telefone ou o sistema operacional podem impedir o envio manual de códigos. Um código necessário que deve ser implementado é *#06#. Esse código retorna o IMEI (identificação internacional de equipamento móvel) do modem, mas alguns telefones não permitem discar esse código diretamente. Se você seguir os meios convencionais de localizar o IMEI do modem pelas configurações do telefone, esse número foi recuperado usando esse código.
Se o hardware do telefone conseguir processar o comando de um código diretamente, como o IMEI do exemplo, nenhuma sessão de rede será iniciada. Outros códigos que exigem comunicação de rede abrirão uma sessão e depois enviarão uma mensagem contendo um comando e os parâmetros necessários, se aplicável. Um exemplo disso é um código que verifica seu saldo atual e o status do plano da MO.
No Windows, o USSD é implementado como uma superfície da API WinRT. As classes de implementação dessa interface funcionam como a máquina de estado de sessões de USSD, mas, em última análise, dependem do Serviço WWAN para fazer o trabalho pesado. Essas APIs são implementadas com um padrão de fábrica.
Implementar a USSD
Um ponto importante a ser lembrado é que a API voltada para o público é definida pela IDL. A implementação pode ser confusa por causa disso, principalmente se você não conhecer bem o WinRT. Parte dessa confusão vem do uso aparentemente ambíguo da expressão "de fábrica". O termo "de fábrica" pode fazer referência a uma implementação de classe de uma interface estática ou a uma fábrica propriamente dita 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. Para saber mais, você sempre pode consultar a IDL.
Interfaces
As interfaces definem a ABI. Elas descrevem as funções que você pode chamar em qualquer classe que implementa a interface.
Classes de runtime
São as classes propriamente ditas. Elas representam, pelo nome, o que acaba sendo 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ção ativável, se necessário. Cada uma dessas interfaces é implementada em arquivos diferentes como diferentes classes "Impl", mas parecerão ser uma classe única e 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 classe de runtime propriamente dita.
Uma marcação ativável define a interface de fábrica que produzirá uma instância de uma classe de runtime. Ela fica completamente ofuscada para o cliente, aparecendo como construtor dessa classe de runtime.
Implementação do USSD
Fluxo: abrir, enviar, receber, fechar.
Abrir, enviar
O cliente usa uma das funções estáticas UssdSession.CreateFromNetworkAccountId ou UssdSession.CreateFromNetworkInterfaceId para criar o objeto UssdSession.
Independentemente da API chamada, uma ID de adaptador de rede é necessária para inicializar um 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, são criados um thread de trabalho e um identificador de eventos para disparar eventos para o thread. As etapas 3 e 4 também ocorrem durante Initialize() da instância.
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.
WwanWrapper abre um identificador para WwanService, enumera as interfaces e se inscreve para receber notificações de USSD fornecendo um ponteiro de função de retorno de chamada estática e "this" como contexto.
O objeto UssdSession é retornado para o cliente.
O cliente constrói um novo UssdMessage invocando o construtor com uma cadeia de caracteres de mensagem. O WinRT ofusca UssdMessageFactory nesse processo.
O cliente invoca SendMessageAndGetReplyAsync no objeto de sessão, passando a instância de UssdMessage.
Nesse momento, SendMessageAndGetReplyAsync cria um objeto de operação especial chamado UssdSendMessageAndGetReplyOperation. Pelo nome, parece que o objeto encapsula a lógica de uma única mensagem sendo encaminhada para a pilha (e aguardando resposta), mas não é esse 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);
É IUssdSendMessageAndGetReplyOperation, uma interface nomeada por meio de typedef, que atende a esse parâmetro, prometendo que essa operação inevitavelmente retornará UssdReply. Essa interface não é definida na IDL, mas é implementada pela classe UssdSendMessageAndGetReplyOperationImpl. 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 ofusque as complexidades dessa operação assíncrona e toda a compartimentalização e o proxy de memória que a acompanha. Para obter mais informações, consulte SendMessageAndGetReplyAsync.
Por enquanto, entenda que a operação assíncrona descrita acima simplesmente chama de volta o objeto UssdSession em que a lógica dessa operação está contida. Para simplificar, podemos visualizar que o próprio objeto UssdSession encapsula o trabalho aqui. Agora podemos afirmar que, apesar da natureza assíncrona, apenas um UssdMessage pode ser enviado de cada vez.
O que de fato a função SendMessageAndGetReplyAsync faz:
- O objeto UssdSession muda para um estado ocupado, armazena o conteúdo de UssdMessage e dispara a ação assíncrona.
- OnOperationStart() é o ponto de entrada da lógica assíncrona. Para esse cenário, vamos supor que não existe uma sessão ativa. Essa função cria um objeto WWAN_USSD_REQUEST com RequestType=WwanUssdRequestInitiate.
- As etapas 9 e 10 ocorrem como as ações executadas por essa função.
m_wwanWrapper.SendRequest é invocado para processar o trabalho de passar a mensagem para WwanService.
WwanWrapper usa o identificador WwanService para invocar APIs WwanService para executar a ação.
Receber
Após a etapa 10, ficamos em um estado em que uma solicitação foi enviada para WwanService para inicializar uma nova sessão de USSD e enviar uma mensagem USSD nessa sessão. Depois de algum tempo, a resposta estará disponível.
- WwanService invocará a função de retorno de chamada estática especificada na etapa 4 com o contexto que também foi anexado.
- O contexto será usado para recuperar a instância de WwanWrapper e invocar NotificationCallback().
- 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.
- Assim como na etapa 12, o contexto é usado para invocar o retorno de chamada em uma instância de UssdSession.
- UssdSession armazena WWAN_USSD_EVENT (em um bloqueio) e notifica o thread de trabalho para manipular o evento.
- HandleOperationReply() pega o objeto UssdSendMessageAndGetReplyOperationImpl existente e passa os dados do evento para o manipulador interno.
- A operação construirá e UssdReply e invocará FireCompletion() para marcar a ação assíncrona como concluída.
- O WinRT ofusca a conclusão da ação assíncrona para o cliente. (Eles podem ter aguardado a ação ou têm a lógica de retorno de chamada.)
Mais mensagens podem ser enviadas na mesma sessão. Se a sessão foi mantida, o próximo RequestType será WwanUssdRequestContinue.
Fechar
Após a etapa 18, o cliente recebeu a resposta para UssdMessage. Ele pode ou não ter continuado a usar o UssdSession ativo para enviar mais mensagens. Vamos supor que, em algum momento no futuro, o cliente invocará Close() manualmente em UssdSession. Se o cliente não invocar Close() explicitamente, ele será chamado durante o destruidor de UssdSession.
- O cliente invoca Close() na instância de UssdSession.
- Um objeto WWAN_USSD_REQUEST é criado com RequestType=WwanUssdRequestCancel.
- A solicitação é enviada para m_wwanWrapper, como na etapa 9.
- A solicitação é enviada para WwanService, como na etapa 10.
O resultado dessa solicitação não é importante. Para todos os efeitos, a sessão está encerrada. Mesmo no caso extremo em que a mensagem nunca é entregue, uma nova sessão de USSD sempre substituirá uma sessão existente.
Testes do kit de laboratório de hardware (HLK)
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 de USSD MB
Colete e decodifique os logs usando as instruções em Coleta de logs MB.
Palavras-chave para filtragem
- OID_WWAN_USSD
- NDIS_STATUS_WWAN_USSD
- WWAN_USSD_REQUEST
- WWAN_USSD_EVENT