Partager via


Comment obtenir les paramètres de connexion d’un appareil

Si votre pilote de contrôleur SPB inscrit une fonction de rappel EvtSpbTargetConnect , l’extension de l’infrastructure SPB (SpbCx) appelle cette fonction lorsqu’un client (pilote périphérique) du contrôleur envoie une IRP_MJ_CREATE demande d’ouverture d’une connexion logique à un appareil cible sur le bus. En réponse au rappel EvtSpbTargetConnect , le pilote du contrôleur SPB doit appeler la méthode SpbTargetGetConnectionParameters pour obtenir les paramètres de connexion de l’appareil cible. Le pilote du contrôleur SPB stocke ces paramètres et les utilise ultérieurement pour accéder à l’appareil en réponse aux demandes d’E/S du client.

Par exemple, les paramètres de connexion d’un appareil cible sur un bus I2C incluent l’adresse du bus de l’appareil, la largeur d’adresse (7 ou 10 bits) et la fréquence d’horloge du bus à utiliser pendant les accès de l’appareil. Le pilote de contrôleur I2C utilise ces paramètres pour configurer le contrôleur afin qu’il accède à l’appareil via le bus I2C.

Un pilote de contrôleur SPB appelle SpbTargetGetConnectionParameters pour obtenir un pointeur vers un descripteur de connexion de bus série qui décrit la connexion d’un appareil cible à un bus série de type I2C ou SPI. Ce descripteur contient des informations de connexion communes aux deux types de bus série et est suivi d’informations spécifiques au bus série auquel l’appareil est connecté. Pour plus d’informations sur le format de ce descripteur, consultez la spécification ACPI 5.0.

Dans l’exemple de code suivant, un pilote de contrôleur I2C définit une structure PNP_I2C_SERIAL_BUS_DESCRIPTOR . Cette structure représente un descripteur de connexion de bus série I2C, qui est le terme utilisé par la spécification ACPI 5.0 pour décrire un descripteur de connexion de bus série suivi de paramètres de connexion spécifiques au bus I2C. Le premier membre de la structure PNP_I2C_SERIAL_BUS_DESCRIPTOR , SerialBusDescriptor, est une structure PNP_SERIAL_BUS_DESCRIPTOR qui représente le descripteur de connexion de bus série. Les membres ConnectionSpeed et SlaveAddress contiennent des paramètres de connexion spécifiques à I2C.

#include <reshub.h>
#include <pshpack1.h>  

//
// See the ACPI 5.0 spec, section 6.4.3.8.2.1 (I2C Serial Bus Connection Descriptor).  
//
typedef struct _PNP_I2C_SERIAL_BUS_DESCRIPTOR {  
    PNP_SERIAL_BUS_DESCRIPTOR SerialBusDescriptor;  
    ULONG ConnectionSpeed;  
    USHORT SlaveAddress;  
    // Followed by optional vendor-specific data.
    // Followed by name of serial bus controller.
} PNP_I2C_SERIAL_BUS_DESCRIPTOR, *PPNP_I2C_SERIAL_BUS_DESCRIPTOR;  
  
#include <poppack.h>

Le fichier d’en-tête reshub.h définit la structure PNP_SERIAL_BUS_DESCRIPTOR . Les fichiers d’en-tête pshpack1.h et poppack.h contrôlent le mode d’alignement de structure utilisé par le compilateur.

Un descripteur de connexion de bus série I2C est une structure de données empaquetée dans laquelle les champs adjacents sont alignés sur les limites d’octet les plus proches, sans interstices. Par conséquent, une valeur entière de 16 bits dans ce descripteur peut démarrer sur une limite d’octet impaire. Dans l’exemple de code précédent, pshpack1.h est inclus pour indiquer au compilateur de packer des membres de structure adjacents, et poppack.h indique au compilateur de reprendre l’alignement de structure par défaut.

Le membre ConnectionSpeed de la structure PNP_I2C_SERIAL_BUS_DESCRIPTOR spécifie la fréquence, en Hertz, à laquelle l’horloge du bus I2C lors des accès de l’appareil cible. Le membre SlaveAddress est l’adresse de bus de l’appareil cible. Pour certains pilotes de contrôleur I2C, le membre SlaveAddress peut être suivi de données facultatives spécifiques au fournisseur, mais ces données ne sont pas utilisées par le pilote dans cet exemple de code et ne font donc pas partie de la définition de structure.

Dans l’exemple de code suivant, le pilote de contrôleur I2C de l’exemple précédent implémente une GetTargetSettings routine qui appelle SpbTargetGetConnectionParameters pour obtenir les paramètres de connexion d’un appareil cible sur le bus I2C. Le paramètre d’entrée cible de cette routine est un handle pour l’appareil cible. Le paramètre de sortie Settings est un pointeur vers une structure de SPB_CONNECTION_PARAMETERS allouée au pilote dans laquelle la routine écrit un ensemble de paramètres de connexion. Ces paramètres incluent un pointeur vers les paramètres de connexion demandés.

#define I2C_SERIAL_BUS_TYPE 0x01
#define I2C_SERIAL_BUS_SPECIFIC_FLAG_10BIT_ADDRESS 0x0001

typedef enum _I2C_ADDRESS_MODE
{
    AddressMode7Bit,
    AddressMode10Bit
} I2C_ADDRESS_MODE, *PI2C_ADDRESS_MODE;
  
typedef struct _I2C_TARGET_SETTINGS
{
    ULONG  ClockFrequency;
    ULONG  Address;
    I2C_ADDRESS_MODE  AddressMode;
} I2C_TARGET_SETTINGS, *PI2C_TARGET_SETTINGS;

NTSTATUS
GetTargetSettings(_In_ SPBTARGET Target, _Out_ PI2C_TARGET_SETTINGS Settings)
{
    PRH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER Connection = NULL;
    SPB_CONNECTION_PARAMETERS Params;

    SPB_CONNECTION_PARAMETERS_INIT(&Params);
    SpbTargetGetConnectionParameters(Target, &Params);
    Connection = (PRH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER)Params.ConnectionParameters;
    if (Connection->PropertiesLength < sizeof(PNP_SERIAL_BUS_DESCRIPTOR))
    {
        return STATUS_INVALID_PARAMETER;
    }

    PPNP_SERIAL_BUS_DESCRIPTOR Descriptor;

    Descriptor = (PPNP_SERIAL_BUS_DESCRIPTOR)Connection->ConnectionProperties;
    if (Descriptor->Tag != SERIAL_BUS_DESCRIPTOR ||
        Descriptor->SerialBusType != I2C_SERIAL_BUS_TYPE)
    {
        return STATUS_INVALID_PARAMETER;
    }

    PPNP_I2C_SERIAL_BUS_DESCRIPTOR I2CDescriptor;
    USHORT I2CFlags;

    I2CDescriptor = (PPNP_I2C_SERIAL_BUS_DESCRIPTOR)Connection->ConnectionProperties;
    Settings->Address = (ULONG)I2CDescriptor->SlaveAddress;
    I2CFlags = I2CDescriptor->SerialBusDescriptor.TypeSpecificFlags;
    Settings->AddressMode = 
                ((I2CFlags & I2C_SERIAL_BUS_SPECIFIC_FLAG_10BIT_ADDRESS) == 0) ? AddressMode7Bit : AddressMode10Bit;

    Settings->ClockFrequency = I2CDescriptor->ConnectionSpeed;

    return STATUS_SUCCESS;
}

Dans l’exemple de code précédent, SpbTargetGetConnectionParameters écrit les paramètres de connexion dans la structure allouée par Params le pilote. Le membre ConnectionParameters de Params pointe vers une structure RH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER (définie dans reshub.h), dont le membre ConnectionProperties est le premier octet du descripteur de connexion de bus série ; les octets restants de ce descripteur suivent immédiatement le membre ConnectionProperties . La mémoire tampon pointée par le membre ConnectionParameters de Params est suffisamment grande pour contenir la structure RH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER plus les octets de descripteur qui suivent cette structure.

La routine implémentée par GetTargetSettings le pilote dans l’exemple de code précédent effectue les vérifications de paramètres suivantes sur les paramètres de connexion reçus de SpbTargetGetConnectionParameters :

  • Vérifie que la taille du descripteur de connexion de bus série contenu dans la structure RH_QUERY_CONNECTION_PROPERTIES_OUTPUT_BUFFER est au moins sizeof(PNP_SERIAL_BUS_DESCRIPTOR).
  • Vérifie que le premier octet du descripteur de connexion de bus série est défini sur SERIAL_BUS_DESCRIPTOR (valeur constante 0x8e), comme requis par la spécification ACPI 5.0.
  • Vérifie que le type de bus série dans le descripteur de connexion de bus série est défini sur I2C_SERIAL_BUS_TYPE (valeur constante 0x01), ce qui identifie le type de bus série comme I2C.

À la fin de l’exemple de code précédent, la structure *Settings contient les paramètres de connexion (adresse du bus, largeur d’adresse et fréquence d’horloge du bus) pour l’appareil cible. Le pilote de contrôleur I2C utilise ces paramètres de connexion pour configurer le contrôleur pour accéder à l’appareil.