驱动消息机制管理

About 4 min

驱动消息机制管理

使用场景

当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。

接口说明

消息机制的功能主要有以下两种:

  1. 用户态应用发送消息到驱动。
  2. 用户态应用接收驱动主动上报事件。

表 1 消息机制接口

方法

描述

struct HdfIoService *HdfIoServiceBind(const char *serviceName)

用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。

void HdfIoServiceRecycle(struct HdfIoService *service);

释放驱动服务。

int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);

用户态程序注册接收驱动上报事件的操作方法。

int HdfDeviceSendEvent(struct HdfDeviceObject *deviceObject, uint32_t id, struct HdfSBuf *data);

驱动主动上报事件接口。

开发步骤

  1. 将驱动配置信息中服务策略policy字段设置为2(SERVICE_POLICY_CAPACITY,参考policy定义)。

    device_sample :: Device {
        policy = 2;
        ...
    }
    
    1
    2
    3
    4
  2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。

  3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。

    // Dispatch是用来处理用户态发下来的消息
    int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
    {
        HDF_LOGE("sample driver lite A dispatch");
        return 0;
    }
    int32_t SampleDriverBind(struct HdfDeviceObject *device)
    {
        HDF_LOGE("test for lite os sample driver A Open!");
        if (device == NULL) {
            HDF_LOGE("test for lite os sample driver A Open failed!");
            return -1;
        }
        static struct ISampleDriverService sampleDriverA = {
            .ioService.Dispatch = SampleDriverDispatch,
            .ServiceA = SampleDriverServiceA,
            .ServiceB = SampleDriverServiceB,
        };
        device->service = (struct IDeviceIoService *)(&sampleDriverA);
        return 0;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
  4. 驱动定义消息处理函数中的cmd类型。

    #define SAMPLE_WRITE_READ 1    // 读写操作码1
    
    1
  5. 用户态获取服务接口并发送消息到驱动。

    int SendMsg(const char *testMsg)
    {
        if (testMsg == NULL) {
            HDF_LOGE("test msg is null");
            return -1;
        }
        struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
        if (serv == NULL) {
            HDF_LOGE("fail to get service");
            return -1;
        }
        struct HdfSBuf *data = HdfSBufObtainDefaultSize();
        if (data == NULL) {
            HDF_LOGE("fail to obtain sbuf data");
            return -1;
        }
        struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
        if (reply == NULL) {
            HDF_LOGE("fail to obtain sbuf reply");
            ret = HDF_DEV_ERR_NO_MEMORY;
            goto out;
        }
        if (!HdfSbufWriteString(data, testMsg)) {
            HDF_LOGE("fail to write sbuf");
            ret = HDF_FAILURE;
            goto out;
        }
        int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
        if (ret != HDF_SUCCESS) {
            HDF_LOGE("fail to send service call");
            goto out;
        }
    out:
        HdfSBufRecycle(data);
        HdfSBufRecycle(reply);
        HdfIoServiceRecycle(serv);
        return ret;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
  6. 用户态接收该驱动上报的消息。

    1. 用户态编写驱动上报消息的处理函数。

      static int OnDevEventReceived(void *priv,  uint32_t id, struct HdfSBuf *data)
      {
          OsalTimespec time;
          OsalGetTime(&time);
          HDF_LOGE("%s received event at %llu.%llu", (char *)priv, time.sec, time.usec);
      
          const char *string = HdfSbufReadString(data);
          if (string == NULL) {
              HDF_LOGE("fail to read string in event data");
              return -1;
          }
          HDF_LOGE("%s: dev event received: %d %s",  (char *)priv, id, string);
          return 0;
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
    2. 用户态注册接收驱动上报消息的操作方法。

      int RegisterListen()
      {
          struct HdfIoService *serv = HdfIoServiceBind("sample_driver");
          if (serv == NULL) {
              HDF_LOGE("fail to get service");
              return -1;
          }
          static struct HdfDevEventlistener listener = {
              .callBack = OnDevEventReceived,
              .priv ="Service0"
          };
          if (HdfDeviceRegisterEventListener(serv, &listener) != 0) {
              HDF_LOGE("fail to register event listener");
              return -1;
          }
          ......
          HdfDeviceUnregisterEventListener(serv, &listener);
          HdfIoServiceRecycle(serv);
          return 0;
      }
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
    3. 驱动上报事件。

      int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
      {
          ... // process api call here
          return HdfDeviceSendEvent(deviceObject, cmdCode, data);
      }
      
      1
      2
      3
      4
      5