1. 任务需求
在BLE扫描过程中,由于Privacy地址的加入,TIFS的时隙不能满足解析耗时的时间处理,这里将解析和时序ACK分为两个步骤,比如scan_req的ScanA解析和回复SCAN_RSP 两个步骤。
2. 方案设计
这就需要一种链表数据结构记录这两个步骤的动作,不同的设备使用地址和地址类型这两个变量来进行判断,链表作用是可以缓存多个设备并且可以实现有序性。收到设备后该需要进行以下流程:
(1)检查该设备的地址和地址类型是否已经存在,不存在就添加到链表中,(当然前提还需判断该设备是为Privacy地址,进行解析,但是解析失败或者解析成功);
(2)如果该设备已经存在该链表中,就不需要重复上述动作,就直接执行协议动作回复SCAN_RSP;
3. 环形链表设计
构造一个环形双向结构的链表,当有数据添加时,该链表的头指针顺时针旋转,当需要查询当前列表的选项时需要逆时针旋转查询。将扫描请求按照时间顺序添加到链表中。
对环形链表的操作有三种:
(1) 初始化,这里使用数组;
(2) 添加或者更新链表项;
(3) 环形链表的遍历;
头文件代码:
#define DEVICE_RESOLVED_LIST_ITEM_NUM (6)
#define DEVICE_RESOLVED_LIST_INVALID_INDEX 0xff
typedef enum
{
RESOLVED_FAILED_LEGACY_ADV_LIST = 0,
RESOLVED_FAILED_LEGACY_SCAN_LIST = 1,
RESOLVED_FAILED_LEGACY_INIT_LIST = 2,
RESOLVED_FAILED_EXTEND_ADV_LIST = 3,
RESOLVED_FAILED_EXTEND_SCAN_LIST = 4, //unused
RESOLVED_FAILED_EXTEND_INIT_LIST = 5, //unused
RESOLVED_FAILED_LIST_NUM = 6,
}resolved_failed_list_index;
typedef struct resolved_failed_info {
u_int8 device_type;
u_int8 device_addr[BD_ADDR_LEN];
struct resolved_failed_info * p_next;
struct resolved_failed_info * p_prev;
}Reloved_Failed_Device_Info;
源文件代码
W1_BT_DATA_PATCH Reloved_Failed_Device_Info g_resolved_failed_list[DEVICE_RESOLVED_LIST_ITEM_NUM * RESOLVED_FAILED_LIST_NUM] = { 0 };
W1_BT_DATA_PATCH Reloved_Failed_Device_Info *g_resolved_failed_list_head_arr[RESOLVED_FAILED_LIST_NUM] = { 0 };
Reloved_Failed_Device_Info *aml_device_resolved_failed_list_check_item_exist(resolved_failed_list_index list_index, u_int8 device_type, u_int8 *p_addr)
{
if (device_type != RANDOM_DEVICE_ADDRESS_TYPE)
return NULL;
if (p_addr == NULL)
{
return NULL;
}
if (list_index >= RESOLVED_FAILED_LIST_NUM)
return NULL;
Reloved_Failed_Device_Info *p_list_head = g_resolved_failed_list_head_arr[list_index];
if (p_list_head == NULL)
{
return NULL;
}
Reloved_Failed_Device_Info *p_temp = p_list_head;
for (; (p_temp != NULL); p_temp = p_temp->p_next)
{
if ((aml_addr_is_equal(p_temp->device_addr, p_addr))
&& (p_temp->device_type == device_type))
{
return p_temp;
}
if (p_temp == p_list_head->p_prev)
{
break;
}
}
return NULL;
}
Reloved_Failed_Device_Info *aml_device_resolved_failed_list_get_idle_item(resolved_failed_list_index list_index)
{
if (list_index >= RESOLVED_FAILED_LIST_NUM)
return NULL;
Reloved_Failed_Device_Info *p_list_head = g_resolved_failed_list_head_arr[list_index];
if (p_list_head == NULL)
{
//init the buffer
p_list_head = &g_resolved_failed_list[list_index * DEVICE_RESOLVED_LIST_ITEM_NUM];
for (u_int8 index = 0; index < DEVICE_RESOLVED_LIST_ITEM_NUM; index++)
{
Reloved_Failed_Device_Info *p_temp = p_list_head + index;
p_temp->p_next = &p_list_head[(index + 1) % DEVICE_RESOLVED_LIST_ITEM_NUM];
p_temp->p_prev = &p_list_head[(index + DEVICE_RESOLVED_LIST_ITEM_NUM - 1) % DEVICE_RESOLVED_LIST_ITEM_NUM];
}
g_resolved_failed_list_head_arr[list_index] = p_list_head;
return p_list_head;
}
return p_list_head->p_prev;
}
Reloved_Failed_Device_Info *aml_device_resolved_failed_list_add_item(resolved_failed_list_index list_index, u_int8 device_type, u_int8 *p_addr)
{
Reloved_Failed_Device_Info *p_idle_item = NULL;
if (device_type != RANDOM_DEVICE_ADDRESS_TYPE)
return NULL;
if (p_addr == NULL)
{
return NULL;
}
if (list_index >= RESOLVED_FAILED_LIST_NUM)
{
return NULL;
}
p_idle_item = aml_device_resolved_failed_list_get_idle_item(list_index);//aml_device_resolved_failed_list_check_item_exist(device_type, p_addr);
if (p_idle_item == NULL)
{
return NULL;
}
{
p_idle_item->device_type = device_type;
aml_copy_array(BD_ADDR_LEN, p_idle_item->device_addr, p_addr);
}
g_resolved_failed_list_head_arr[list_index] = p_idle_item;
//p_resolved_failed_list_head = p_idle_item;
return p_idle_item;
}
Reloved_Failed_Device_Info *aml_device_resolved_failed_list_update_item(resolved_failed_list_index list_index, Reloved_Failed_Device_Info *p_new_item)
{
if (p_new_item == NULL)
{
return NULL;
}
if (list_index >= RESOLVED_FAILED_LIST_NUM)
{
return NULL;
}
Reloved_Failed_Device_Info *p_list_head = g_resolved_failed_list_head_arr[list_index];
if (p_list_head == p_new_item)
{
//nothing to be done
}
else if (p_list_head == p_new_item->p_prev)
{
//p_head_item just move to next item
p_list_head = p_new_item;
}
else
{
//update the list
//pick up out the list
p_new_item->p_next->p_prev = p_new_item->p_prev;
p_new_item->p_prev->p_next = p_new_item->p_next;
//insert the item into the list
p_new_item->p_prev = p_list_head->p_prev;
p_new_item->p_next = p_list_head;
p_list_head->p_prev->p_next = p_new_item;
p_list_head->p_prev = p_new_item;
}
g_resolved_failed_list_head_arr[list_index] = p_new_item;
//p_resolved_failed_list_head = p_idle_item;
return p_new_item;
}