21,597
社区成员
发帖
与我相关
我的任务
分享
struct partial_pkt
{
uint8_t tag;//TAG_END
uint8_t partial_order;
};
const pkt_header_t *pack(const char *buf, unsigned long length)
{
const pkt_header_t *head = (const pkt_header_t *)buf;
struct link_package {
int partial_order;
char link_buffer[512];
int total_pkg_len;
int offset;
};
static struct link_package linker = {-1};//init partial_order to -1 to aviod lost first pkt
//try to judge which pkt it is
if ((TAG_BEGIN <= head->tag && head->tag < TAG_END) && (head->length < MAX_PKT_LENGTH)) {
linker.total_pkg_len = head->length + OFFSET_OF_END_MEM(pkt_header_t, length);
if (linker.total_pkg_len > (int)length) {//need link other partial packages
linker.partial_order = 0;//init partial_order
if (length <= sizeof(linker.link_buffer)) {
memcpy(linker.link_buffer, buf, length);//save first partial package
linker.offset = length;
} else {
goto error;
}
goto receive_next;//receive next partial package
} else {
return head;//full pkt
}
} else if (TAG_END == head->tag) {//check if partial_order effective
struct partial_pkt *partial = (struct partial_pkt *)buf;
if (partial->partial_order == (linker.partial_order + 1)) {
if (linker.offset + length <= sizeof(linker.link_buffer)) {
++linker.partial_order;
memcpy(linker.link_buffer + linker.offset, buf + sizeof(struct partial_pkt), length - sizeof(struct partial_pkt));
linker.offset += length;
if (linker.offset >= linker.total_pkg_len) {//link finished
return (pkt_header_t *)linker.link_buffer;
} else {
goto receive_next;//receive next partial package
}
}
}
}
error://clear linker info when error
linker.partial_order = -1;
linker.total_pkg_len = 0;
linker.offset = 0;
receive_next:
return NULL;
}
#define MAX_SEND_LEN (32)//size rely on mailbox
int unpack(const void *buf, unsigned long length)
{
int ret = 0;
if (length <= MAX_SEND_LEN) {
//return inputhub_mcu_send((const char *)buf, length);
} else {
int partial_order = 0;
char send_partial_buf[MAX_SEND_LEN];
int send_cnt = 0;
//send head
//ret = inputhub_mcu_send(send_begin, MAX_SEND_LEN);
((struct partial_pkt *)send_partial_buf)->tag = TAG_END;
for (send_cnt = MAX_SEND_LEN; send_cnt < (int)length; send_cnt += (MAX_SEND_LEN - sizeof(struct partial_pkt))) {
++((struct partial_pkt *)send_partial_buf)->partial_order;
memcpy(send_partial_buf + sizeof(struct partial_pkt), (const char *)buf + send_cnt, MAX_SEND_LEN - sizeof(struct partial_pkt));
//ret = inputhub_mcu_send(send_partial_buf, MAX_SEND_LEN);
}
}
return ret;
}
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
//#include<stdint.h>
#include"protocol.h"
#define LINK_PACKAGE
#define OFFSET(struct_t, member) ((int)&(((struct_t *)0)->member))
#define OFFSET_OF_END_MEM(struct_t, member) (OFFSET(struct_t, member) + sizeof((((struct_t *)0)->member)))
#define OFFSET_INTERVAL(struct_t, member1, member2) (OFFSET_OF_END_MEM(struct_t, member2) - OFFSET_OF_END_MEM(struct_t, member1))
#ifdef LINK_PACKAGE
int generate_crc(const void *buf, unsigned long length)
{
return 0;
}
struct partial_pkt
{
uint8_t tag;//TAG_END
uint8_t partial_order;
};
/*
typedef struct
{
uint8_t tag;
uint8_t cmd;
uint8_t resp;//value CMD_RESP means need resp, CMD_NO_RESP means need not resp
uint8_t reserve;
uint16_t tranid;
uint16_t length;
}pkt_header_t;
typedef struct
{
uint8_t tag;
uint8_t cmd;
uint8_t resp;
uint8_t reserve;
uint16_t tranid;
uint16_t length;
uint32_t errno;
}pkt_header_resp_t;
*/
const pkt_header_t *pack(const char *buf, unsigned long length)
{
const pkt_header_t *head = (const pkt_header_t *)buf;
struct link_package {
bool full_pkg;
char link_buffer[512];
int offset;
int total_pkg_len;
int partial_order;
};
static struct link_package linker = {true};
begin:
if (linker.full_pkg) {
head = (const pkt_header_t *)buf;
linker.total_pkg_len = head->length + OFFSET_OF_END_MEM(pkt_header_t, length);
if (linker.total_pkg_len > (int)length) {//need link other partial packages
linker.full_pkg = false;
linker.partial_order = 0;
if (length <= sizeof(linker.link_buffer)) {
memcpy(linker.link_buffer, buf, length);//save first partial package
} else {
//printf("data length error from mcu in %s!\n", __func__);
}
linker.offset = length;
return NULL;//receive next partial package.
}
} else {
if (linker.offset + length <= sizeof(linker.link_buffer)) {
struct partial_pkt *partial = (struct partial_pkt *)buf;
if (TAG_END == partial->tag) {//partial pkt
if (partial->partial_order != (linker.partial_order + 1)) {
++linker.partial_order;
memcpy(linker.link_buffer + linker.offset, buf + sizeof(struct partial_pkt), length - sizeof(struct partial_pkt));
} else {//lost one partial pkt, so we will drop all partial pkt belongs
;
}
} else if (TAG_BEGIN <= head->tag && head->tag < TAG_END && head->length < MAX_PKT_LENGTH) {//may be next full pkt
linker.full_pkg = true;
linker.offset = 0;
linker.partial_order = 0;
goto begin;
} else {//error
;
}
} else {
//printf("data length error from mcu in %s!\n", __func__);
}
linker.offset += length;
if (linker.offset >= linker.total_pkg_len) {//link finished
head = (pkt_header_t *)linker.link_buffer;
linker.full_pkg = true;
} else {
return NULL;//receive next partial package.
}
}
return head;
}
#define MAX_SEND_LEN (32)//size rely on mailbox
int unpack(const void *buf, unsigned long length, int *crc)
{
int ret = 0;
const char *send_begin = (const char *)buf;
const char *send_end = send_begin + length;
*crc = generate_crc(buf, length);
do {
//ret = inputhub_mcu_send(send_begin, MAX_SEND_LEN);
if (ret) {
//printf("send data failed in %s\n", __func__);
break;
}
send_begin += MAX_SEND_LEN;
} while (send_begin < send_end);
return ret;
}
#endif
int main()
{
system("pause");
return 0;
}
int write_customize_cmd(const struct write_info *wr, struct read_info *rd)
{
char buf[MAX_PKT_LENGTH];
int ret = 0;
if (NULL == wr) {
hwlog_err("NULL pointer in %s\n", __func__);
return -EINVAL;
}
//[TAG_BEGIN, TAG_END)
if (wr->tag < TAG_BEGIN || wr->tag >= TAG_END) {
hwlog_err("tag = %d error in %s\n", wr->tag, __func__);
return -EINVAL;
}
if (wr->wr_len + sizeof(pkt_header_t) > MAX_PKT_LENGTH) {
hwlog_err("-----------> wr_len = %d is too large in %s\n", wr->wr_len, __func__);
return -EINVAL;
}
//转换成MCU需要的协议格式
((pkt_header_t *)buf)->tag = wr->tag;
((pkt_header_t *)buf)->cmd = wr->cmd;
((pkt_header_t *)buf)->resp = ((rd != NULL) ? (RESP) : (NO_RESP));
((pkt_header_t *)buf)->length = wr->wr_len;
if (wr->wr_buf != NULL) {
memcpy(buf + sizeof(pkt_header_t), wr->wr_buf, wr->wr_len);
}
if (NULL == rd) {//tag cmd need not resp
return inputhub_mcu_write_cmd(buf, sizeof(pkt_header_t) + wr->wr_len);
} else {//tag cmd need resp
unsigned long flags = 0;
mutex_lock(&type_record.lock_mutex);
spin_lock_irqsave(&type_record.lock_spin, flags);
type_record.pkt_info = ((pkt_header_t *)buf);
type_record.rd = rd;
spin_unlock_irqrestore(&type_record.lock_spin, flags);
//send data to mcu
if ((ret = inputhub_mcu_write_cmd(buf, sizeof(pkt_header_t) + wr->wr_len)) != 0) {
hwlog_err("send cmd to mcu failed in %s\n", __func__);
goto clear_info;
}
//wait for resp or timeout
hwlog_info("down ------------------------------------------------------> in %s\n", __func__);
if ((ret = down_timeout(&type_record.sem, HZ * 2)) != 0) {
hwlog_err("------->timeout in %s\n", __func__);//timeout
}
clear_info:
//clear infor
spin_lock_irqsave(&type_record.lock_spin, flags);
type_record.pkt_info = NULL;
type_record.rd = NULL;
spin_unlock_irqrestore(&type_record.lock_spin, flags);
mutex_unlock(&type_record.lock_mutex);
}
return ret;
}
static int report_resp_data(const pkt_header_resp_t *head)
{
int ret = 0;
unsigned long flags = 0;
spin_lock_irqsave(&type_record.lock_spin, flags);
if (type_record.rd != NULL && type_record.pkt_info != NULL//check record info
&& (cmd_match(type_record.pkt_info->cmd, head->cmd))
&& (type_record.pkt_info->tranid == head->tranid)) {//rcv resp from mcu
if (head->length <= (MAX_PKT_LENGTH + sizeof(head->errno))) {//data length ok
type_record.rd->errno = head->errno;//fill errno to app
type_record.rd->data_length = (head->length - sizeof(head->errno));//fill data_length to app, data_length means data lenght below
memcpy(type_record.rd->data, (char *)head + sizeof(pkt_header_resp_t), type_record.rd->data_length);//fill resp data to app
} else {//resp data too large
type_record.rd->errno = -EINVAL;
type_record.rd->data_length = 0;
hwlog_err("data too large from mcu in %s\n", __func__);
}
up(&type_record.sem);
hwlog_info("up ------------------------------------------------------> in %s\n", __func__);
}
spin_unlock_irqrestore(&type_record.lock_spin, flags);
return ret;
}