1.1 GATT server Service
通过走读代码, GATT Server作为一个GATT service,我是没有发现其发挥了多大功能,其负责处理的消息GATT_SERVER_SERVICE_CHANGED_INDICATION_CFM,GATT_SERVER_READ_CLIENT_CONFIG_IND,GATT_SERVER_WRITE_CLIENT_CONFIG_IND都没有定义对应的handler。
1.2 GATT Service(Battery Service)
GATT Battery Servce是ADK4.0 sink例程中默认添加的一个比较简单和常用的服务,该服务只有一个设备电量(batteryLevel)的特征值。纵观GATT Battery Servce模块的接口可以大致看出该模块完成的主要功能有:
1.2.1 服务初始化
GattBatteryServerInit(GBASS *battery_server, Task app_task, init_params, start_h, end_h);
该接口主要用来初始化指定(#battery_server) GATT Battery Service实例,如lib_task和app_task。初始化实例之后,通过GattManagerRegisterServer()将其添加到GATT MGR模块。
1.2.2 回调函数
前面也提到过,这里涉及到两个回调函数,外部钩子函数主要用来接收application layer的数据,而内部钩子函数,则用来接收上级管理模块的信息。
内部钩子函数与外部钩子函数对应的函数名称以及处理的信号如下:
batteryServerMsgHandler(); /*内部钩子函数*/
--GATT_MANAGER_SERVER_ACCESS_IND
-- HANDLE_BATTERY_SERVICE
-- HANDLE_BATTERY_LEVEL à GATT_BATTERY_SERVER_READ_LEVEL_IND
-- HANDLE_BATTERY_LEVEL_CLIENT_CONFIG à GATT_BATTERY_SERVER_READ_CLIENT_CONFIG_IND / GATT_BATTERY_SERVER_WRITE_CLIENT_CONFIG_IND
-- HANDLE_BATTERY_LEVEL_PRESENTATIONà GATT_BATTERY_SERVER_READ_PRESENTATION_IND
-- GATT_MANAGER_REMOTE_CLIENT_NOTIFICATION_CFM
sinkGattBatteryServerMsgHandler(); /*外部钩子函数*/
-- GATT_BATTERY_SERVER_READ_LEVEL_IND
-- GATT_BATTERY_SERVER_READ_CLIENT_CONFIG_IND
-- GATT_BATTERY_SERVER_WRITE_CLIENT_CONFIG_IND
-- GATT_BATTERY_SERVER_READ_PRESENTATION_IND
从上面的分析可以看出,内部钩子函数在接收到的GATT请求,如果能够自己处理,则直接进行处理和应答,如HANDLE_BATTERY_SERVICE,其他大部分情况还需要application Layer的介入,因此将其映射为外部钩子函数对应的信号后转发给application Layer(通过app_task),application Layer通过直接调用外部钩子函数,进行请求转发,在外部钩子函数里面,实现大部分的GATT请求。
1.2.3 服务参数配置,特征值获取接口
实现内部钩子函数和外部钩子函数对GATT请求的处理接口。在Battery Service中主要有:
-- HANDLE_BATTERY_SERVICEà查询Battery Service,主要用于获取Battery Service句柄
-- HANDLE_BATTERY_LEVEL à获取电量特征值
--HANDLE_BATTERY_LEVEL_CLIENT_CONFIG à 获取电量特征值的客户端配置参数
-- HANDLE_BATTERY_LEVEL_PRESENTATIONà获取电量特征值的表示方式
1.3 初始化
The local database and the GATT Server libraries to manage the local GATT database must be registered. This section describes the procedure required to do this, a few points to note are:
§ The local GATT Database must be registered first.
§ Each required GATT Server library must be individually registered:
§ Only GATT Server Libraries that manage a section of the registered GATT database should be registered.
§ The handle range for each GATT Server library must not overlap.
§ When the local GATT database and all the required GATT Server libraries have been registered, the device can be registered with GATT (and the ATT firmware layer):
§ If a local GATT database is registered, but no GATT Server libraries have been registered, this request fails.
1.4 GATT Request Handle
当一个GATT客户设备与一个GATT服务设备建立连接后,就可以开始GATT操作。GATT MGR模块对每个到来的GATT请求,通过查询已注册的服务列表,经过一定的匹配算法寻找到合适GATT Service后将该请求分发给它。GATT Service模块对于到来的请求通常有两种不同的处理方式:
1.少数情况,GATT Service模块有能力可以立即对到来的GATT请求作出回应,例如,GATT请求时获取软件版本,确认某个服务等,这种情况无需Application Layer介入。
2.大多数情况下,GATT Service模块将到来的请求传递给Application Layer, Application Layer通过该模块的外部钩子函数API处理该请求,这也是为什么通常GATT Service模块需要提供外部钩子函数的原因(The GATT Server library should provide a downstream API for the application to respond to the request)。
下图分别展示上述两种不同的GATT请求的处理方式。上半部分展示了读取GATT Battery Service的电池电量的操作,在该GATT请求中,GATT Battery Service模块将该请求传递个Application Layer,后者通过GATT Battery Service模块提供的外部回调函数(downstream API) sinkGattBatteryServerMsgHandler()来处理请求。下半部分展示了一个简单的GATT请求,该请求无需Application Layer处理。
获取BatteryService的电量特征值的函数调用过程如下图:
gattMessageHandler(); (ATT_ACCESS_IND)->
gattHandleAttAccessInd((ATT_ACCESS_IND_T *) message);
MessageSend(gattGetCidMappedTask(ind->cid), GATT_ACCESS_IND, message);
gattManagerMessageHandler(); /* gatt_manager_data->gatt_manager_task.handler */
gattMessageHandler(); (GATT_ACCESS_IND)->
gattManagerServerAccessInd();
gattManagerDataResolveServerHandle(&discover);
serverAccessInd(ind, discover.task, discover.adjusted);
MessageSend(task, GATT_MANAGER_SERVER_ACCESS_IND, message);
batteryServerMsgHandler();->GATT_MANAGER_SERVER_ACCESS_IND
handleBatteryAccess()->HANDLE_BATTERY_LEVEL
batteryLevelAccess();->GATT_BATTERY_SERVER_READ_LEVEL_IND
MessageSend(battery_server->app_task, , message);-à
sinkBleMsgHandler()->GATT_BATTERY_SERVER_READ_LEVEL_IND
sinkGattBatteryServerMsgHandler()->
handleReadBatteryLevel();->
getBatteryLevelAsPercentage();
sendBatteryLevelAccessRsp(battery_server, cid, battery_level);->
sendBatteryLevelAccessRsp(); (HANDLE_BATTERY_LEVEL)
sendBatteryAccessRsp(&battery_server->lib_task, , , &battery_level);
GattAccessResponse(); (GATT_INTERNAL_ACCESS_RES)
MessageSend(&theGatt->task, GATT_INTERNAL_ACCESS_RES);
gattMessageHandler()->
gattHandleInternalAccessRes()->
VmSendAttPrim(prim);
1.5 Service Discovery
关于这一节,ADK提供的使用手册表诉的比较详细,这里就直接摘抄过来。
When a GATT Server device has been successfully connected, the Audio Sink application starts discovering which primary services are supported by the connected device. The procedure for discovering the GATT Primary Services of a remote GATT Server is:
§ The Audio Sink application discovers all primary services defined on the remote GATT Server:
§ Discovered primary services that are supported by the Audio Sink application is temporarily stored in a list.
§ Discovered primary services that are not supported by the Audio Sink application are ignored.
§ When all primary services have been discovered:
§ For each supported primary service that has been discovered, the Audio Sink application initialises the GATT client library used to manage the service. Library initialisation is done sequentially not simultaneously.
§ If no supported primary services have been discovered, the device is disconnected.
Description
§ The Audio Sink application discovers all primary services on the remote GATT Server.
§ The Audio Sink application discovers the remote GATT Server supports Service One and temporarily stores that information.
§ The Audio Sink application ignores the discovered primary service (Service Two) that is not supported.
§ When all primary services have been discovered, the Audio Sink application initialises the GATT Client library to manage Service One.