DeviceVirtualization Engine(简称DV Engine)是华为提供的多设备虚拟化平台,通过该平台,将周边的设备或设备器件转换为手机的虚拟器件,能够将周边设备能力作为手机系统通用能力来提供和使用,同时能够实现多虚拟设备能力同步协同使用。
应用开发者通过集成DV Kit,可以便捷使用外部的设备,包括但不限于摄像头、扬声器、显示器、麦克风、穿戴等外部设备能力以及相关器件的能力,并可以支持灵活的控制和切换,充分使用外部设备的资源优势,致力为消费者打造更佳的协同体验。
在这个Codelab中,你将创建Demo Project,并将DeviceVirtualization Engine集成到Demo Project中,以及完成DeviceVirtualization Engine服务的整体流程搭建,并在设备上实现启动,停止以及发现设备。
集成DeviceVirtualization Engine能力,需要完成以下准备工作:
具体操作,请按照《DeviceVirtualization Engine 接入准备》中详细说明来完成。
1. 集成DeviceVirtualization Engine。
请依照《DeviceVirtualization Engine 接入准备》中第二步获取到DeviceVirtualization Engine的SDK软件包。
2. 北向DVAgentListener注册接口适配:
// 以下为DVAgentListener需要注册的回调函数
void DVKIT_DataReceive(DV_AGENT_HANDLE handle, int dataType, char *data, uint32_t dataLen)
{
return;
}
void DVKIT_DeviceChange(DV_AGENT_HANDLE handle, const char *deviceId, uint32_t idLen, int state)
{
// 接收到状态106断开,异步线程进行删除调用DVAgentDestroyServiceHandle进行删除
return;
}
void DVKIT_DeviceServiceChange(DV_AGENT_HANDLE handle, const char *serviceId, uint32_t idLen, int state)
{
return;
}
void DVKIT_PinCode(const char *pinCode, uint32_t codeLen)
{
// 显示Pin码
return;
}
int32_t DVKIT_GetSecureFileSize(const char *filename)
{
// 获取存储认证信息的文件大小
return size;
}
int32_t DVKIT_ReadSecureFile(const char *filename, uint32_t offset, uint8_t *buf, uint32_t len)
{
// 读取存储认证信息的文件
return size;
}
int32_t DVKIT_WriteSecureFile(const char *filename, uint32_t offset, uint8_t *buf, uint32_t len)
{
// 往存储认证信息的文件写入内容,认证信息建议存储在安全存储区
return 0;
}
int32_t DVKIT_RemoveSecureFile(const char *filename)
{
// 删除存储认证信息的文件
return 0;
}
3. 北向初始化DV Kit:
DV_AGENT_HANDLE g_dvagentHandle = NULL;
// 初始化DvKit
void DVKIT_Init()
{
DVAgentConfig dvAgentConfig = {0};
dvAgentConfig.deviceInfo.connectAllowType = 0x1;
dvAgentConfig.deviceInfo.vendorID = 0x1;
// 获取BLE MAC,为6字节二进制,且此处MAC不可变,如果变了需要清除认证信息文件
GetMac((char*)dvAgentConfig.deviceInfo.brMac);
memcpy_s(dvAgentConfig.deviceInfo.deviceId, strlen(DV_AGENT_DEVICE_ID) + 1, DV_AGENT_DEVICE_ID, strlen(DV_AGENT_DEVICE_ID));
dvAgentConfig.deviceInfo.idLen = strlen(DV_AGENT_DEVICE_ID);
memcpy_s(dvAgentConfig.deviceInfo.deviceName, strlen(DV_AGENT_DEVICE_NAME) + 1, DV_AGENT_DEVICE_NAME, strlen(DV_AGENT_DEVICE_NAME));
dvAgentConfig.deviceInfo.nameLen = strlen(DV_AGENT_DEVICE_NAME);
int32_t ret= DVAgentInit(&dvAgentConfig);
if(ret != 0) {
return;
}
DVAgentListener listener = {0};
listener.DataReceive = DVKIT_DataReceive;
listener.DeviceChange = DVKIT_DeviceChange;
listener.DeviceServiceChange = DVKIT_DeviceServiceChange;
listener.GetSecureFileSize = DVKIT_GetSecureFileSize;
listener.PinCode = DVKIT_PinCode;
listener.ReadSecureFile = DVKIT_ReadSecureFile;
listener.RemoveSecureFile = DVKIT_RemoveSecureFile;
listener.WriteSecureFile = DVKIT_WriteSecureFile;
ret = DVAgentRegisterListener(&listener);
if(ret != 0) {
return;
}
g_dvagentHandle = DVAgentCreateServiceHandle();
while (1) {
sleep(1);
}
return;
}
4. 南向智能设备信息采集适配,DV Engine采集智能设备的设备类型、设备支持的服务能力及设备能力的状态,智能设备厂商需实现对应libdmsdpdevice.so,完成获取设备类型、设备服务能力及设备能力状态等接口,供DV Engine调用。
int32_t DMSDPGetState(uint32_t *state)
{
if (state == NULL) {
return DMSDP_ERR_NULLPTR;
}
/* if support DMSDP set AVAILABLE */
*state = DMSDP_AVAILABLE;
return DMSDP_OK;
}
int32_t DMSDPGetDeviceType(uint32_t *type)
{
if (type == NULL) {
return DMSDP_ERR_NULLPTR;
}
/* set the device type */
*type = DEVICE_TYPE_CAMERA;
return DMSDP_OK;
}
int32_t DMSDPGetDeviceServiceCapability(uint32_t *serviceMask, uint32_t *stateMask)
{
if (serviceMask == NULL || stateMask == NULL) {
return DMSDP_ERR_NULLPTR;
}
/*
* get dmsdp deivce service capability
* serviceMask: DMSDPServiceType mask, each bit specify a service type
* for example : if support MIC and Speaker, mask will be SERVICE_TYPE_MIC | SERVICE_TYPE_SPEAKER
*
* stateMask: DMSDPServiceState mask, each 2bit specify a service state match to the service type mask
* for example : if support MIC and Speaker, mask will be SERVICE_TYPE_MIC | SERVICE_TYPE_SPEAKER,
* if MIC state is AVAILABLE and speaker is AVAILABLE, the the state mask will be
* 0000 0000 0000 0000 0000 0000 0001 0100 : 0x00000014
*/
*serviceMask = SERVICE_TYPE_CAMERA | SERVICE_TYPE_SPEAKER | SERVICE_TYPE_MIC;
*stateMask = 0x00000015;
return DMSDP_OK;
}
int32_t DMSDPDeviceRegisterListener(const DMSDPListener *listener)
{
/* regist service state/action listener */
(void)listener;
return DMSDP_OK;
}
int32_t DMSDPGetDeviceCustomProps(DMSDPProps* props)
{
if (props == NULL || props->SetProp == NULL) {
return DMSDP_ERR_NULLPTR;
}
props->nums = 1;
props->SetProp(0, "10036", "xxxxx", props);
return 0;
}
5. 南向设备Camera虚拟化接口适配,此类接口用于定义DV Engine对智能设备Camera硬件的调用接口,智能设备厂商需实现对应的libdmsdpcamerahandler.so。如果智能设备厂商不具备Camera硬件或者不需要将Camera硬件虚拟化,不需要关注该接口,默认不实现此so即可。
int32_t CameraRegisterSendDataCallback(const char *id, uint32_t idLen, const DMSDPSendBackDataCB cb)
{
/* regist callback for send data */
(void)id;
(void)idLen;
(void)cb;
return DMSDP_OK;
}
int32_t OpenCamera(const DMSDPCameraParam *param)
{
/* open camera */
(void)param;
return DMSDP_OK;
}
int32_t CloseCamera(const char *id, uint32_t idLen)
{
/* close camera, unregist senddata callback */
(void)id;
(void)idLen;
return DMSDP_OK;
}
int32_t CameraUpdateConfig(const char *id, uint32_t idLen, int32_t key, char *value, uint32_t valLen)
{
/* update camera config: fps */
(void)id;
(void)idLen;
(void)key;
(void)value;
(void)valLen;
return DMSDP_OK;
}
void CameraRelease(int32_t type, void *ptr, uint32_t num)
{
/* release resource if any */
(void)type;
(void)ptr;
(void)num;
return;
}
int32_t GetCameraCapability(DMSDPCameraCapabilities **capabilities, uint32_t *num)
{
/*
* collect the camera capabilities,
* CameraRelease will be called after the function to release the resource allocated
*/
(void)capabilities;
(void)num;
return DMSDP_OK;
}
const char *GetCameraCapabilityString(uint32_t *len)
{
/* reserved for ide automatic no need to impl */
(void)len;
return NULL;
}
int32_t CameraRegisterListener(const DMSDPListener *listener)
{
/* regist service state/action listener */
(void)listener;
return DMSDP_OK;
}
int32_t CameraBusinessControl(uint32_t cmd, void *inputPara, uint32_t inLen, void *outputPara, uint32_t outLen)
{
/* reserved */
(void)cmd;
(void)inputPara;
(void)inLen;
(void)outputPara;
(void)outLen;
return DMSDP_OK;
}
int32_t DMSDPGetCameraHandler(DMSDPCameraHandler *cameraHandler)
{
if (cameraHandler == NULL) {
return DMSDP_ERR_NULLPTR;
}
cameraHandler->RegisterSendDataCallback = CameraRegisterSendDataCallback;
cameraHandler->OpenCamera = OpenCamera;
cameraHandler->CloseCamera = CloseCamera;
cameraHandler->UpdateConfig = CameraUpdateConfig;
cameraHandler->GetCameraCapability = GetCameraCapability;
cameraHandler->GetCameraCapabilityString = GetCameraCapabilityString;
cameraHandler->Release = CameraRelease;
cameraHandler->RegisterListener = CameraRegisterListener;
cameraHandler->BusinessControl = CameraBusinessControl;
return DMSDP_OK;
}
6. 发南向WiFi适配,智能设备厂商需根据自己驱动实现对应的能力。
static ChannelCallback *g_wifiCallback;
static int InitWifi(constvoid *context, constchar *ifName)
{
/* 初始化WiFi信息 */
return RESULT_RET_OK;
}
static int DeinitWifi(constvoid *context)
{
/* 去初始化WiFi信息,移除GO */
return RESULT_RET_OK;
}
static int WifiGetParam(GetParamsType paramType, void *result)
{
if (paramType == GET_DEV_MAC) {
/* 获取本地MAC地址 */
} else if (paramType == GET_WIFI_ABILITY) {
/* 获取设备WiFi能力,支持2.4G/5G */
} else {
printf("unknown paramtype\r\n");
return RESULT_RET_ERROR;
}
return RESULT_RET_OK;
}
static int WifiSetParam(SetParamsType paramType, constvoid *context)
{
if (paramType == SET_WIFI_LOCAL_IP) {
/* 设置本地IP信息 */
/* 设置IP信息成功,上报EVENT_CONFIG_IP_SUCCESS事件 */
g_wifiCallback->ChannelStateChange(CHANNEL_P2P, EVENT_CONFIG_IP_SUCCESS, NULL, 0);
}
return RESULT_RET_OK;
}
static int WifiRegisterCallBack(const ChannelCallback *callback)
{
/* 注册WiFi回调 */
g_wifiCallback = (ChannelCallback *)callback;
return RESULT_RET_OK;
}
static int WifiCreateAP(constvoid *priv, constvoid *wifiInfo)
{
/* 根据下发的频率启对应的GO*/
/* GO创建成功,上报EVENT_CREATE_WIFI_SUCCESS事件*/
if (g_wifiCallback != NULL) {
g_wifiCallback->ChannelStateChange(CHANNEL_P2P, EVENT_CREATE_WIFI_SUCCESS, &apParams, sizeof(WifiParams));
}
return RESULT_RET_OK;
}
const struct FcDriverAdaptOps g_fcDriverWifiOps = {
.name = WIFI_DRIVER_NAME,
.desc = "wifi driver",
.Init = InitWifi,
.Deinit = DeinitWifi,
.SetParam = WifiSetParam,
.GetParam = WifiGetParam,
.RegisterChannelCallback = WifiRegisterCallBack,
.CreateWifiChannel = WifiCreateAP,
};
7. 南向BLE适配,智能设备厂商需根据自己驱动实现对应的能力。
static ChannelCallback *g_bleCallback;
static int BleDriverInit(const void *context, const char *ifName)
{
/*初始化BLE信息 */
/* 启蓝牙GATT服务 */
return 0;
}
static int BleDriverDeinit(const void *context)
{
/* 去初始化BLE信息 */
/* 停止蓝牙GATT服务 */
return 0;
}
static int BleSetParam(SetParamsType paramType, const void *paramValue)
{
return 0;
}
static int BleGetParam(GetParamsType paramType, void *result)
{
/* 获取设备名称 */
if (paramType == GET_DEV_NAME) {
*name = "drives name";
}
return 0;
}
static int BleStartAdv(const void *priv)
{
/* 设置广播参数,开始广播 */
return 0;
}
static int BleSetAdvData(const void *priv)
{
/* 设置广播数据 */
/* 设置扫描回复数据 */
return 0;
}
static int BleStopAdv(const void *priv)
{
/* 停止广播 */
return 0;
}
static int BleStartScan(const void *priv)
{
/* 开始BLE扫描 */
return 0;
}
static int BleStopScan(const void *priv)
{
/* 停止BLE扫描 */
return 0;
}
static int BleDisconnect(const void *priv)
{
/* BLE连接断开 */
return 0;
}
static int BleRegisterChannelCallback(const ChannelCallback *channelCallback)
{
/* 注册BLE回调 */
if (channelCallback) {
g_bleCallback = channelCallback;
return 0;
}
return -1;
}
static int BleNotifyData(const unsigned char *data, int dataLen, const void *priv)
{
/* server向client发送数据 */
return 0;
}
const struct FcDriverAdaptOps g_fcAdaptBleOps = {
.name = "ble",
.desc = "ble driver",
.Init = BleDriverInit,
.Deinit = BleDriverDeinit,
.SetParam = BleSetParam,
.GetParam = BleGetParam,
.StartAdv = BleStartAdv,
.StopAdv = BleStopAdv,
.SetAdvData = BleSetAdvData,
.StartScan = BleStartScan,
.StopScan = BleStopScan,
.Connect = BleConnect,
.Disconnect = BleDisconnect,
.SendData = BleSendData,
.NotifyData = BleNotifyData,
.RegisterChannelCallback = BleRegisterChannelCallback,
};
干得好,你已经成功完成了Codelab并学到了:
您可以阅读下面链接,了解更多相关的信息。
相关文档
您可以点击下方按钮下载源码。