Escrever um driver de cliente MBBCx

Aviso

Os diagramas de sequência neste tópico são apenas para fins ilustrativos. Eles não são contratos públicos e estão sujeitos a mudanças no futuro.

Arquivos INF para drivers de cliente MBBCx

Os arquivos INF para drivers de cliente MBBCx são os mesmos que outros drivers de cliente NetAdapterCx. Para obter mais informações, consulte Arquivos INF para drivers de cliente NetAdapterCx.

Siga as diretrizes universais para garantir que os arquivos INF atendam aos requisitos universais.

Inicializar o dispositivo

Além das tarefas exigidas pela inicialização do dispositivo NetAdapterCx para NetAdapter, um driver de cliente MBB também deve executar as seguintes tarefas em sua função de retorno de chamada EvtDriverDeviceAdd :

  1. Chame MBB_DEVICE_CONFIG_INIT depois de chamar NetDeviceInitConfig , mas antes de chamar WdfDeviceCreate, referenciando o mesmo objeto WDFDEVICE_INIT passado pela estrutura.

  2. Chame MbbDeviceInitialize para registrar funções de retorno de chamada específicas do dispositivo MBB usando uma estrutura de MBB_DEVICE_CONFIG inicializada e o objeto WDFDEVICE obtido de WdfDeviceCreate.

O exemplo a seguir demonstra como inicializar o dispositivo MBB. O tratamento de erros foi deixado de fora para maior clareza.

    status = NetDeviceInitConfig(deviceInit);
    status = MbbDeviceInitConfig(deviceInit);

    // Set up other callbacks such as Pnp and Power policy

    status = WdfDeviceCreate(&deviceInit, &deviceAttributes, &wdfDevice);

    MBB_DEVICE_CONFIG mbbDeviceConfig;
    MBB_DEVICE_CONFIG_INIT(&mbbDeviceConfig,
                           EvtMbbDeviceSendMbimFragment,
                           EvtMbbDeviceReceiveMbimFragment,
                           EvtMbbDeviceSendServiceSessionData,
                           EvtMbbDeviceCreateAdapter);

    status = MbbDeviceInitialize(wdfDevice, &mbbDeviceConfig);

Ao contrário de outros tipos de drivers NetAdapterCx, os drivers de cliente MBB não devem criar o objeto NETADAPTER de dentro da função de retorno de chamada EvtDriverDeviceAdd . Em vez disso, ele será instruído pelo MBBCx a fazê-lo mais tarde.

Em seguida, o driver cliente deve chamar MbbDeviceSetMbimParameters, normalmente na função de retorno de chamada EvtDevicePrepareHardware a seguir.

Este diagrama de fluxo de mensagens ilustra o processo de inicialização.

Diagrama que mostra o processo de inicialização do driver de cliente MBBCx.

Este diagrama de fluxo de mensagens ilustra o processo de inicialização.

Diagrama que mostra o processo de inicialização do driver de cliente MBBCx.

Manipulando mensagens de controle do MBIM

O MBBCx usa os comandos de controle MBIM padrão definidos na especificação do MBIM Rev 1.0, seções 8, 9 e 10, para o painel de controle. Comandos e respostas são trocados por meio de um conjunto de funções de retorno de chamada fornecidas pelo driver cliente e apIs fornecidas pelo MBBCx. O MBBCx imita o modelo operacional de um dispositivo MBIM, conforme definido na especificação do MBIM Rev 1.0, seção 5.3, usando estas chamadas de função:

  • O MBBCx envia uma mensagem de comando MBIM para o driver cliente invocando sua função de retorno de chamada EvtMbbDeviceSendMbimFragment . O driver cliente conclui de forma assíncrona essa solicitação de envio chamando MbbRequestComplete.
  • O driver cliente sinaliza a disponibilidade do resultado chamando MbbDeviceResponseAvailable.
  • O MBBCx busca a mensagem de resposta do MBIM do driver cliente invocando sua função de retorno de chamada EvtMbbDeviceReceiveMbimFragment . O driver do cliente conclui de forma assíncrona essa solicitação get-response chamando MbbRequestCompleteWithInformation.
  • O driver do cliente MBB pode notificar o MBBCx de um evento de dispositivo não solicitado chamando MbbDeviceResponseAvailable. Em seguida, o MBBCx recupera as informações do driver cliente de maneira semelhante à maneira como ele busca mensagens de resposta do MBIM.

O diagrama a seguir ilustra o fluxo de troca de mensagens do driver MBBCx-client.

Diagrama que mostra a troca de mensagens do MBIM entre o MBBCx e o driver do cliente.

Sincronização de mensagens de controle do MBIM

A estrutura MBBCx sempre serializa chamadas para as funções de retorno de chamada EvtMbbDeviceSendMbimFragment e EvtMbbDeviceReceiveMbimFragment do driver cliente. Nenhuma nova chamada será feita pela estrutura até que o driver cliente chame MbbRequestComplete ou MbbRequestCompleteWithInformation.

Embora seja garantido que um driver cliente não receba retornos de chamada EvtMbbDeviceSendMbimFragment ou EvtMbbDeviceReceiveMbimFragment sobrepostos, ele pode receber várias chamadas para eles em sucessão antes que a resposta de um comando anterior esteja disponível no dispositivo.

Se o dispositivo não estiver no estado D0 , a estrutura MBBCx primeiro levará o dispositivo para D0 (em outras palavras, ele chama EvtDeviceD0Entry) antes de chamar EvtMbbDeviceSendMbimFragment ou EvtMbbDeviceReceiveMbimFragment. A estrutura MBBCx também garante que manterá o dispositivo no estado D0, o que significa que ele não chamará EvtDeviceD0Exit até que o cliente chame MbbRequestComplete ou MbbRequestCompleteWithInformation.

Criando a interface NetAdapter para o portador de contexto/EPS PDP

Antes de estabelecer uma sessão de dados, o MBBCx instruirá o driver cliente a criar um objeto NETADAPTER e ele será usado pelo MBBCx para representar o adaptador de rede para a sessão de dados ativada. Isso é feito pela chamada MBBCx para a função de retorno de chamada EvtMbbDeviceCreateAdapter do driver cliente.

Na implementação da função de retorno de chamada EvtMbbDeviceCreateAdapter , o driver cliente MBBCx deve primeiro executar as mesmas tarefas necessárias para criar um objeto NETADAPTER que qualquer driver cliente NetAdapterCx. Além disso, ele também deve executar as seguintes tarefas adicionais:

  1. Chame MbbAdapterInitialize no objeto NETADAPTER criado por NetAdapterCreate.

  2. Depois de chamar MbbAdapterinitialize, chame MbbAdapterGetSessionId para recuperar a ID da sessão de dados para a qual o MBBCx pretende usar esse objeto NETADAPTER. Por exemplo, se o valor retornado for 0, isso significa que o MBBCx usará essa interface NETADAPTER para a sessão de dados estabelecida pelo portador de EPS padrão/contexto PDP primário.

  3. Recomendamos que os drivers de cliente MBBCx mantenham um mapeamento interno entre o objeto NETADAPTER criado e o SessionId retornado. Isso ajuda a acompanhar a relação de objeto de sessão de dados para NETADAPTER, que é especialmente útil quando vários contextos PDP/portadores de EPS foram ativados.

  4. Antes de retornar de EvtMbbDeviceCreateAdapter, os drivers de cliente devem iniciar o adaptador chamando NetAdapterStart. Opcionalmente, eles também podem definir os recursos do adaptador chamando uma ou mais dessas funções antes da chamada para NetAdapterStart:

O MBBCx invoca essa função de retorno de chamada pelo menos uma vez, portanto, sempre há um objeto NETADPATER para o contexto PDP primário/portador padrão do EPS. Se vários contextos PDP/portadores de EPS forem ativados, o MBBCx poderá invocar essa função de retorno de chamada mais vezes, uma vez para que cada sessão de dados seja estabelecida. Deve haver uma relação um-para-um entre o adaptador de rede representado pelo objeto NETADAPTER e uma sessão de dados, conforme mostrado no diagrama a seguir.

Diagrama que mostra vários objetos NETADAPTER para sessões de dados diferentes.

O exemplo a seguir mostra como criar um objeto NETADAPTER para uma sessão de dados. Observe que o tratamento de erros e o código necessários para configurar os recursos do adaptador são deixados de fora para fins de brevidade e clareza.

    NTSTATUS
    EvtMbbDeviceCreateAdapter(
        WDFDEVICE  Device,
        PNETADAPTER_INIT AdapterInit
    )
    {
        // Get the client driver defined per-device context
        PMY_DEVICE_CONTEXT deviceContext = MyGetDeviceContext(Device);

        // Set up the client driver defined per-adapter context
        WDF_OBJECT_ATTRIBUTES adapterAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&adapterAttributes,
                                                MY_NETADAPTER_CONTEXT);


        // Create the NETADAPTER object
        NETADAPTER netAdapter;
        NTSTATUS status = NetAdapterCreate(AdapterInit,
                                           &adapterAttributes,
                                           &netAdapter);

        // Initialize the adapter for MBB
        status = MbbAdapterInitialize(netAdapter);

        // Retrieve the Session ID and use an array to store
        // the session <-> NETADAPTER object mapping
        ULONG sessionId;
        PMY_NETADAPTER_CONTEXT netAdapterContext = MyGetNetAdapterContext(netAdapter);

        netAdapterContext->NetAdapter = netAdapter;

        sessionId = MbbAdapterGetSessionId(netAdapter);

        netAdapterContext->SessionId = sessionId;

        deviceContext->Sessions[sessionId].NetAdapterContext = netAdapterContext;

        //
        // Optional: set adapter capabilities
        //
        ...
        NetAdapterSetDatapathCapabilities(netAdapter,
                                          &txCapabilities,
                                          &rxCapabilities);

        ...
        NetAdapterSetLinkLayerCapabilities(netAdapter,
                                           &linkLayerCapabilities);

        ...
        NetAdapterSetLinkLayerMtuSize(netAdapter,
                                      MY_MAX_PACKET_SIZE - ETHERNET_HEADER_LENGTH);

        //
        // Required: start the adapter
        //
        status = NetAdapterStart(netAdapter);

        return status;
    }

Para obter um exemplo de código de configuração de recursos de caminho de dados, consulte Gerenciamento de buffer de dados de rede.

O MBBCx garante que ele chame EvtMbbDeviceCreateAdapter antes de solicitar MBIM_CID_CONNECT com a mesma ID de sessão. O diagrama de fluxo a seguir mostra as interações entre o driver cliente e a extensão de classe na criação do objeto NETADAPTER.

Diagrama que mostra a criação e a ativação do NETADAPTER para um driver de cliente MBB.

O fluxo para criar o objeto NETADAPTER para o contexto PDP primário/portador padrão do EPS é iniciado pelo MBBCx quando EvtDevicePrepareHardware foi concluído com êxito.

O fluxo para criar o objeto NETADAPTER para o contexto PDP secundário/portador de EPS dedicado é disparado pelo WwanSvc sempre que as conexões sob demanda são solicitadas por aplicativos.

Tempo de vida do objeto NETADAPTER

O objeto NETADAPTER criado pelo driver cliente será destruído automaticamente pelo MBBCx quando ele não estiver mais em uso. Por exemplo, isso acontece depois que outros portadores de EPS/contexto PDP são desativados. Os drivers de cliente MBBCx não devem chamar WdfObjectDelete nos objetos NETADAPTER que eles criam.

Se um driver de cliente precisar limpo dados de contexto vinculados a um objeto NETADAPTER, ele deverá fornecer uma função EvtDestroyCallback na estrutura de atributos de objeto ao chamar NetAdapterCreate.

Gerenciamento de energia do dispositivo MBB

Para o gerenciamento de energia, os drivers cliente devem usar o objeto NETPOWERSETTINGS como outros tipos de drivers de cliente NetAdapterCx.

Manipulando sessões de serviço de dispositivo

Quando um aplicativo envia dados DSS para o dispositivo modem, o MBBCx invoca a função de retorno de chamada EvtMbbDeviceSendServiceSessionData do driver cliente. Em seguida, o driver cliente deve enviar os dados de forma assíncrona para o dispositivo e chamar MbbDeviceSendDeviceServiceSessionDataComplete depois que o envio for concluído, para que o MBBCx possa liberar a memória alocada para os dados.

Por outro lado, o driver cliente chama MbbDeviceReceiveDeviceServiceSessionData para passar todos os dados para o aplicativo por meio do MBBCx.

Requisitos de conformidade com drivers do Windows