MBBCx 클라이언트 드라이버 작성

경고

이 항목의 시퀀스 다이어그램은 설명 용도로만 사용됩니다. 그들은 공공 계약이 아니며 미래에 변경 될 수 있습니다.

MBBCx 클라이언트 드라이버용 INF 파일

MBBCx 클라이언트 드라이버용 INF 파일은 다른 NetAdapterCx 클라이언트 드라이버와 동일합니다. 자세한 내용은 NetAdapterCx 클라이언트 드라이버용 INF 파일을 참조하세요.

유니버설 지침에 따라 INF 파일이 유니버설 요구 사항을 충족하는지 확인합니다.

디바이스 초기화

NetAdapter 디바이스 초기화를 위해 NetAdapterCx에 필요한 작업 외에도 MBB 클라이언트 드라이버는 EvtDriverDeviceAdd 콜백 함수에서 다음 작업을 수행해야 합니다.

  1. NetDeviceInitConfig를 호출한 후,WdfDeviceCreate를 호출하기 전에 프레임워크에서 전달한 것과 동일한 WDFDEVICE_INIT 개체를 참조하여 MBB_DEVICE_CONFIG_INIT 호출합니다.

  2. MbbDeviceInitialize를 호출하여 초기화된 MBB_DEVICE_CONFIG 구조체 및 WdfDeviceCreate에서 가져온 WDFDEVICE 개체를 사용하여 MBB 디바이스별 콜백 함수를 등록합니다.

다음 예제에서는 MBB 디바이스를 초기화하는 방법을 보여 줍니다. 명확성을 위해 오류 처리가 제외되었습니다.

    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);

다른 유형의 NetAdapterCx 드라이버와 달리 MBB 클라이언트 드라이버는 EvtDriverDeviceAdd 콜백 함수 내에서 NETADAPTER 개체를 만들면 안됩니다. 대신 MBBCx에서 나중에 수행하도록 지시합니다.

다음으로 클라이언트 드라이버는 MbbDeviceSetMbimParameters를 호출해야 하며, 일반적으로 다음에 오는 EvtDevicePrepareHardware 콜백 함수에서 호출해야 합니다.

이 메시지 흐름 다이어그램은 초기화 프로세스를 보여 줍니다.

MBBCx 클라이언트 드라이버 초기화 프로세스를 보여 주는 다이어그램

이 메시지 흐름 다이어그램은 초기화 프로세스를 보여 줍니다.

MBBCx 클라이언트 드라이버 초기화 프로세스를 보여 주는 다이어그램

MBIM 제어 메시지 처리

MBBCx는 컨트롤 플레인에 대해 MBIM 사양 Rev 1.0, 섹션 8, 9 및 10에 정의된 표준 MBIM 컨트롤 명령을 사용합니다. 명령 및 응답은 MBBCx에서 제공하는 클라이언트 드라이버 및 API에서 제공하는 콜백 함수 집합을 통해 교환됩니다. MBBCx는 다음 함수 호출을 사용하여 MBIM 사양 Rev 1.0, 섹션 5.3에 정의된 MBIM 디바이스의 작동 모델을 모방합니다.

  • MBBCx는 EvtMbbDeviceSendMbimFragment 콜백 함수를 호출하여 클라이언트 드라이버에 MBIM 명령 메시지를 보냅니다. 클라이언트 드라이버는 MbbRequestComplete를 호출하여 이 보내기 요청을 비동기적으로 완료합니다.
  • 클라이언트 드라이버는 MbbDeviceResponseAvailable을 호출하여 결과의 가용성을 신호로 보냅니다.
  • MBBCx는 EvtMbbDeviceReceiveMbimFragment 콜백 함수를 호출하여 클라이언트 드라이버에서 MBIM 응답 메시지를 가져옵니다. 클라이언트 드라이버는 MbbRequestCompleteWithInformation을 호출하여 이 get-response 요청을 비동기적으로 완료합니다.
  • MBB 클라이언트 드라이버는 MbbDeviceResponseAvailable을 호출하여 MBBCx에 원치 않는 디바이스 이벤트를 알릴 수 있습니다. 그런 다음 MBBCx는 MBIM 응답 메시지를 가져오는 방법과 유사하게 클라이언트 드라이버에서 정보를 검색합니다.

다음 다이어그램에서는 MBBCx-client 드라이버 메시지 교환 흐름을 보여 줍니다.

MBBCx와 클라이언트 드라이버 간의 MBIM 메시지 교환을 보여 주는 다이어그램

MBIM 제어 메시지 동기화

MBBCx 프레임워크는 항상 클라이언트 드라이버의 EvtMbbDeviceSendMbimFragmentEvtMbbDeviceReceiveMbimFragment 콜백 함수로 호출을 직렬화합니다. 클라이언트 드라이버가 MbbRequestComplete 또는 MbbRequestCompleteWithInformation을 호출할 때까지 프레임워크에서 새 호출을 수행하지 않습니다.

클라이언트 드라이버가 겹치는 EvtMbbDeviceSendMbimFragment 또는 EvtMbbDeviceReceiveMbimFragment 콜백을 수신하지 않도록 보장되지만 디바이스에서 이전 명령에 대한 응답을 사용할 수 있기 전에 여러 호출을 연속으로 수신할 수 있습니다.

디바이스가 D0 상태가 아닌 경우 MBBCx 프레임워크는 EvtMbbDeviceSendMbimFragment 또는 EvtMbbDeviceReceiveMbimFragment를 호출하기 전에 먼저 디바이스를 D0(즉, EvtDeviceD0Entry 호출)로 가져옵니다. 또한 MBBCx 프레임워크는 디바이스를 D0 상태로 유지하도록 보장합니다. 즉, 클라이언트가 MbbRequestComplete 또는 MbbRequestCompleteWithInformation을 호출할 때까지 EvtDeviceD0Exit를 호출하지 않습니다.

PDP 컨텍스트/EPS 전달자에 대한 NetAdapter 인터페이스 만들기

데이터 세션을 설정하기 전에 MBBCx는 클라이언트 드라이버에 NETADAPTER 개체를 만들도록 지시하고 MBBCx에서 활성화된 데이터 세션에 대한 네트워크 인터페이스를 나타내는 데 사용됩니다. 이 작업은 클라이언트 드라이버의 EvtMbbDeviceCreateAdapter 콜백 함수를 호출하는 MBBCx를 통해 수행됩니다.

EvtMbbDeviceCreateAdapter 콜백 함수 구현에서 MBBCx 클라이언트 드라이버는 먼저 NetAdapterCx 클라이언트 드라이버와 NETADAPTER 개체를 만드는 데 필요한 동일한 작업을 수행해야 합니다. 또한 다음과 같은 추가 작업도 수행해야 합니다.

  1. NetAdapterCreate에서 만든 NETADAPTER 개체에서 MbbAdapterInitialize를 호출합니다.

  2. MbbAdapterinitialize를 호출한 후 MbbAdapterGetSessionId를 호출하여 MBBCx가 이 NETADAPTER 개체를 사용하려는 데이터 세션 ID를 다시 처리합니다. 예를 들어 반환된 값이 0인 경우 MBBCx는 기본 PDP 컨텍스트/기본 EPS 전달자가 설정한 데이터 세션에 이 NETADAPTER 인터페이스를 사용합니다.

  3. MBBCx 클라이언트 드라이버는 생성된 NETADAPTER 개체와 반환된 SessionId 간에 내부 매핑을 유지하는 것이 좋습니다. 이렇게 하면 데이터 세션-NETADAPTER 개체 관계를 추적하는 데 도움이 되며, 이는 여러 PDP 컨텍스트/EPS 전달자가 활성화된 경우에 특히 유용합니다.

  4. EvtMbbDeviceCreateAdapter에서 반환하기 전에 클라이언트 드라이버는 NetAdapterStart를 호출하여 어댑터를 시작해야 합니다. 필요에 따라 NetAdapterStart를 호출하기 전에 이러한 함수 중 하나 이상을 호출하여 어댑터의 기능을 설정할 수도 있습니다.

MBBCx는 이 콜백 함수를 한 번 이상 호출하므로 기본 PDP 컨텍스트/기본 EPS 전달자에 대해 항상 하나의 NETADPATER 개체가 있습니다. 여러 PDP 컨텍스트/EPS 전달자가 활성화되면 MBBCx는 모든 데이터 세션이 설정될 때마다 이 콜백 함수를 한 번 더 호출할 수 있습니다. 다음 다이어그램과 같이 NETADAPTER 개체가 나타내는 네트워크 인터페이스와 데이터 세션 간에 일대일 관계가 있어야 합니다.

여러 데이터 세션에 대한 여러 NETADAPTER 개체를 보여 주는 다이어그램

다음 예제에서는 데이터 세션에 대한 NETADAPTER 개체를 만드는 방법을 보여줍니다. 어댑터 기능을 설정하는 데 필요한 오류 처리 및 코드는 간결하고 명확하게 하기 위해 제외됩니다.

    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;
    }

데이터 경로 기능을 설정하는 코드 예제는 네트워크 데이터 버퍼 관리를 참조하세요.

MBBCx는 동일한 세션 ID로 MBIM_CID_CONNECT 요청하기 전에 EvtMbbDeviceCreateAdapter를 호출할 수 있도록 보장합니다. 다음 흐름 다이어그램은 NETADAPTER 개체를 만들 때 클라이언트 드라이버와 클래스 확장 간의 상호 작용을 보여 줍니다.

MBB 클라이언트 드라이버에 대한 NETADAPTER 만들기 및 활성화를 보여 주는 다이어그램

기본 PDP 컨텍스트/기본 EPS 전달자에 대한 NETADAPTER 개체를 만드는 흐름은 EvtDevicePrepareHardware 가 성공적으로 완료되면 MBBCx에서 시작됩니다.

애플리케이션에서 주문형 연결을 요청할 때마다 보조 PDP 컨텍스트/전용 EPS 전달자에 대한 NETADAPTER 개체를 만드는 흐름은 WwanSvc 에 의해 트리거됩니다.

NETADAPTER 개체의 수명

클라이언트 드라이버에서 만든 NETADAPTER 개체는 MBBCx가 더 이상 사용하지 않을 때 자동으로 제거됩니다. 예를 들어 이 문제는 추가 PDP 컨텍스트/EPS 전달자가 비활성화된 후에 발생합니다. MBBCx 클라이언트 드라이버는 만든 NETADAPTER 개체에서 WdfObjectDelete 를 호출해서는 안됩니다.

클라이언트 드라이버가 NETADAPTER 개체에 연결된 컨텍스트 데이터를 클린 경우 NetAdapterCreate를 호출할 때 개체 특성 구조에 EvtDestroyCallback 함수를 제공해야 합니다.

MBB 디바이스의 전원 관리

전원 관리의 경우 클라이언트 드라이버는 다른 유형의 NetAdapterCx 클라이언트 드라이버와 같은 NETPOWERSETTINGS 개체를 사용해야 합니다.

디바이스 서비스 세션 처리

애플리케이션이 DSS 데이터를 모뎀 디바이스로 보내면 MBBCx는 클라이언트 드라이버의 EvtMbbDeviceSendServiceSessionData 콜백 함수를 호출합니다. 그런 다음 클라이언트 드라이버는 디바이스에 데이터를 비동기적으로 보내고 보내기가 완료되면 MbbDeviceSendDeviceServiceSessionDataComplete 를 호출하므로 MBBCx는 데이터에 할당된 메모리를 해제할 수 있습니다.

반대로 클라이언트 드라이버는 MbbDeviceReceiveDeviceServiceSessionData 를 호출하여 MBBCx를 통해 애플리케이션에 데이터를 전달합니다.

Windows 드라이버 규격 요구 사항