490 lines
9.7 KiB
C
490 lines
9.7 KiB
C
/**
|
||
******************************************************************************
|
||
* @file outprompts.c
|
||
* @author TMC Scan Team
|
||
* @version V1.0.0
|
||
* @date 09/07/2019
|
||
* @brief
|
||
******************************************************************************
|
||
*
|
||
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
||
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
||
* TIME. AS A RESULT, TMC SHALL NOT BE HELD LIABLE FOR ANY
|
||
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
||
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
||
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
||
*
|
||
* <h2><center>© COPYRIGHT 2016 TMC</center></h2>
|
||
******************************************************************************
|
||
**/
|
||
|
||
#include "global.h"
|
||
|
||
const uint8_t aliPayCodeType[6][2] = {{0x32, 0x35}, {0x32, 0x36}, {0x32, 0x37}, {0x032, 0x38}, {0x32, 0x39}, {0x33, 0x30}};
|
||
const uint8_t weiPayCodeType[6][2] = {{0x31, 0x30}, {0x31, 0x31}, {0x31, 0x32}, {0x31, 0x33}, {0x31, 0x34}, {0x31, 0x35}};
|
||
const uint8_t cloudPayCodeType[2] = {0x36, 0x32};
|
||
|
||
extern uint8_t gReceiveKey;
|
||
|
||
/**
|
||
* @function ScanCodeType
|
||
* @brief 区分支付码类型
|
||
* @param[in] pCode 扫码结果
|
||
* @return 支付码类型(微信、支付宝、云闪付、其它)
|
||
*/
|
||
uint8_t ScanCodeType(BarData *pCode)
|
||
{
|
||
uint8_t tmpBuf[2];
|
||
uint8_t i = 0;
|
||
memcpy(tmpBuf, pCode->bardata, 2);
|
||
|
||
if((Memcmp(tmpBuf, (uint8_t *)&cloudPayCodeType, 2) == TRUE) && (pCode->datalen == CLOUDPAY_LEN))
|
||
{
|
||
return CLOUDPAY;
|
||
}
|
||
|
||
for(i = 0; i < 6; i++)
|
||
{
|
||
if((Memcmp(tmpBuf, (uint8_t *)&weiPayCodeType[i][0], 2) == TRUE) && (pCode->datalen == WECHATPAY_LEN))
|
||
{
|
||
return WECHATPAY;
|
||
}
|
||
|
||
if(Memcmp(tmpBuf, (uint8_t *)&aliPayCodeType[i][0], 2) == TRUE)
|
||
{
|
||
if((pCode->datalen >= ALIPAY_LEN_MIN) && (pCode->datalen <= ALIPAY_LEN_MAX))
|
||
{
|
||
return ALIPAY;
|
||
}
|
||
}
|
||
}
|
||
|
||
return OTHERPAY;
|
||
}
|
||
|
||
/**
|
||
* @function InputCodeType
|
||
* @brief 判断输入数据的编码格式
|
||
* @param[in] pCode input data
|
||
* @return
|
||
*/
|
||
uint8_t InputCodeType(BarData *pCode)
|
||
{
|
||
uint8_t codeType = GBK;
|
||
uint8_t *ptr = pCode->bardata;
|
||
uint8_t gbkFlag = TRUE;
|
||
int utfByte, inputData = 0;;
|
||
char b2, b3, b4;
|
||
|
||
if(gConfgBuf.inputCodeType == UTF8)
|
||
{
|
||
codeType = UTF8;
|
||
}
|
||
else
|
||
{
|
||
if(gConfgBuf.inputCodeType == AUTO) // AUTO
|
||
{
|
||
//根据解码结果判断当前编码是gbk还是utf_8,如果都不是,按照gbk处理
|
||
while(inputData < pCode->datalen)
|
||
{
|
||
if(*(ptr + inputData) < 0x80)
|
||
{
|
||
inputData ++;
|
||
}
|
||
else
|
||
{
|
||
gbkFlag = FALSE;
|
||
//先按照utf-8解析
|
||
utfByte = enc_get_utf8_size(*(ptr + inputData));
|
||
|
||
switch(utfByte)
|
||
{
|
||
case 1:
|
||
inputData ++;
|
||
break;
|
||
|
||
case 2:
|
||
b2 = *(ptr + inputData + 1);
|
||
|
||
if((b2 >> 6) != 0x02)
|
||
{
|
||
codeType = GBK;
|
||
return codeType;
|
||
}
|
||
else
|
||
{
|
||
inputData += 2;
|
||
}
|
||
|
||
break;
|
||
|
||
case 3:
|
||
b2 = *(ptr + inputData + 1);
|
||
b3 = *(ptr + inputData + 2);
|
||
|
||
if(((b2 >> 6) != 0x02) || ((b3 >> 6) != 0x02))
|
||
{
|
||
codeType = GBK;
|
||
return codeType;
|
||
}
|
||
else
|
||
{
|
||
inputData += 3;
|
||
}
|
||
|
||
break;
|
||
|
||
case 4:
|
||
b2 = *(ptr + inputData + 1);
|
||
b3 = *(ptr + inputData + 2);
|
||
b4 = *(ptr + inputData + 3);
|
||
|
||
if(((b2 >> 6) != 0x02) || ((b3 >> 6) != 0x02) || ((b4 >> 6) != 0x02))
|
||
{
|
||
codeType = GBK;
|
||
return codeType;
|
||
}
|
||
else
|
||
{
|
||
inputData += 4;
|
||
}
|
||
|
||
break;
|
||
|
||
case 0:
|
||
codeType = GBK;
|
||
return codeType;
|
||
|
||
default:
|
||
codeType = GBK;
|
||
return codeType;
|
||
}
|
||
}
|
||
}
|
||
|
||
if(gbkFlag == TRUE)
|
||
{
|
||
codeType = GBK;
|
||
}
|
||
else
|
||
{
|
||
codeType = UTF8;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
codeType = GBK;
|
||
}
|
||
}
|
||
|
||
return codeType;
|
||
}
|
||
|
||
/**
|
||
* @function ECIModeCheck
|
||
* @brief 检测数据是否含有ECI模式,如果有,去掉ECI数据
|
||
* @param[in] pCode 扫码结果
|
||
* @return
|
||
*/
|
||
void ECIModeCheck(BarData *pCode)
|
||
{
|
||
uint8_t *pTmpData = (uint8_t *)MIDOUTBUF;
|
||
uint16_t codelen = pCode->datalen, i = 0, j, offset = 0;
|
||
if(!pCode->containECI)
|
||
{
|
||
return;
|
||
}
|
||
|
||
memcpy(pTmpData, pCode->bardata, codelen);
|
||
|
||
while(i < codelen)
|
||
{
|
||
if(i < (codelen - ECI_NUMBER_NUM))
|
||
{
|
||
if(pTmpData[i] == '\\')
|
||
{
|
||
for(j = 0; j < ECI_NUMBER_NUM;j++)
|
||
{
|
||
if((pTmpData[i + 1 + j] < '0') || (pTmpData[i + 1 + j] > '9'))
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
if(j == ECI_NUMBER_NUM)
|
||
{
|
||
i += (ECI_NUMBER_NUM + 1);
|
||
continue;
|
||
}
|
||
}
|
||
}
|
||
|
||
if((pTmpData[i] == '\\') && (pTmpData[i + 1] == '\\'))
|
||
{
|
||
i++;
|
||
continue;
|
||
}
|
||
|
||
pCode->bardata[offset++] = pTmpData[i++];
|
||
}
|
||
|
||
pCode->datalen = offset;
|
||
}
|
||
|
||
/**
|
||
* @function DataEdit
|
||
* @brief 数据编辑,按照特定的格式输出,默认格式 :[前缀]][data][后缀][结束符]
|
||
* @param[in] pCode 扫码结果
|
||
* @return 数据长度
|
||
*/
|
||
uint16_t DataEdit(BarData *pCode)
|
||
{
|
||
uint16_t dataLen = 0, tmpLen;
|
||
uint8_t *pData = (uint8_t *)PREOUTBUF;
|
||
uint8_t *pOut = (uint8_t *)POSOUTBUF;
|
||
uint8_t inputCodeType, outputCodeType;
|
||
int tmp = 0;
|
||
|
||
//判断输入数据的格式。
|
||
inputCodeType = InputCodeType(pCode);
|
||
outputCodeType = gConfgBuf.outputCodeType;
|
||
|
||
if(gConfgBuf.billModeStatus == ON)
|
||
{
|
||
//发票模式
|
||
tmp = BillMode(pCode);
|
||
|
||
if(tmp > 0)
|
||
{
|
||
inputCodeType = UTF8;
|
||
outputCodeType = gConfgBuf.outputCodeType;
|
||
}
|
||
}
|
||
|
||
//ECI模式
|
||
if(gConfgBuf.ECIMode)
|
||
{
|
||
ECIModeCheck(pCode);
|
||
}
|
||
|
||
//前缀
|
||
if(gConfgBuf.prefixLen)
|
||
{
|
||
Memcpy(&pData[dataLen], gConfgBuf.prefix, gConfgBuf.prefixLen);
|
||
dataLen += gConfgBuf.prefixLen;
|
||
}
|
||
|
||
Memcpy(&pData[dataLen], pCode->bardata, pCode->datalen);
|
||
dataLen += pCode->datalen;
|
||
|
||
//后缀
|
||
if(gConfgBuf.prefixLen)
|
||
{
|
||
Memcpy(&pData[dataLen], gConfgBuf.suffix, gConfgBuf.suffixLen);
|
||
dataLen += gConfgBuf.suffixLen;
|
||
}
|
||
|
||
/*根据输入和输出数据的格式进行转换*/
|
||
if(inputCodeType == GBK)
|
||
{
|
||
if(outputCodeType == UNICODE)
|
||
{
|
||
tmpLen = GbkToUnicode(pData, pOut, dataLen);
|
||
dataLen = tmpLen;
|
||
}
|
||
else if(outputCodeType == UTF8)
|
||
{
|
||
tmpLen = GbkToUnicode(pData, (uint8_t *) MIDOUTBUF, dataLen);
|
||
tmpLen = unicode_to_utf8((uint8_t *) MIDOUTBUF, pOut, tmpLen);
|
||
dataLen = tmpLen;
|
||
}
|
||
else
|
||
{
|
||
Memcpy(pOut, pData, dataLen);
|
||
}
|
||
}
|
||
|
||
if(inputCodeType == UTF8)
|
||
{
|
||
if(outputCodeType == UNICODE)
|
||
{
|
||
tmpLen = utf8_to_unicode(pData, pOut, dataLen);
|
||
dataLen = tmpLen;
|
||
}
|
||
else if(outputCodeType == GBK)
|
||
{
|
||
tmpLen = utf8_to_unicode(pData, (uint8_t *) MIDOUTBUF, dataLen);
|
||
tmpLen = UnicodeToGbk((uint8_t *) MIDOUTBUF, pOut, tmpLen);
|
||
dataLen = tmpLen;
|
||
}
|
||
else
|
||
{
|
||
Memcpy(pOut, pData, dataLen);
|
||
}
|
||
}
|
||
|
||
//结束符
|
||
switch(gConfgBuf.endCode){
|
||
case END_DOCE_CRLF://换行回车
|
||
pOut[dataLen++] = '\r';
|
||
pOut[dataLen++] = '\n';
|
||
break;
|
||
case END_DOCE_TAB://TAB键
|
||
pOut[dataLen++] = '\t';
|
||
break;
|
||
case END_DOCE_CR://回车
|
||
pOut[dataLen++] = '\r';
|
||
break;
|
||
case END_DOCE_LF://new line
|
||
pOut[dataLen++] = '\n';
|
||
break;
|
||
defalut:
|
||
pOut[dataLen++] = '\n';
|
||
break;
|
||
}
|
||
|
||
|
||
return dataLen;
|
||
}
|
||
|
||
/**
|
||
* @function PayCodeReport
|
||
* @brief 设置码以外的码输出提示
|
||
* @param[in] pCode 解码数据
|
||
* @return
|
||
*/
|
||
void PayCodeReport(BarData *pCode)
|
||
{
|
||
uint16_t dataLen;
|
||
uint8_t payCodeType;
|
||
|
||
//蜂鸣器声音
|
||
if(gConfgBuf.buzzerStatus)
|
||
{
|
||
BuzzerSelect(SCAN_CODE_SUCCESS);
|
||
}
|
||
|
||
//补光灯闪烁
|
||
if(gConfgBuf.ledStatus && gConfgBuf.ledFlash)
|
||
{
|
||
AppLEDControl(LED_WHITE_FLASH);
|
||
}
|
||
|
||
//输出数据编辑,【Prefix】【Data】【Suffix】【结束符】
|
||
dataLen = DataEdit(pCode);
|
||
payCodeType = ScanCodeType(pCode);
|
||
if(payCodeType == WECHATPAY||payCodeType == ALIPAY||payCodeType == CLOUDPAY)
|
||
{
|
||
if(!gConfgBuf.payCodeEnable)
|
||
{
|
||
SetPackType(PACK_TYPEA);
|
||
SetOutputData((uint8_t *)"PAYCODEDISABLE", 14);
|
||
ReportData(pCode->bartype);
|
||
} else {
|
||
if(!gReceiveKey)
|
||
{
|
||
SetPackType(PACK_TYPEA);
|
||
SetOutputData((uint8_t *)"NOKEY", 5);
|
||
ReportData(pCode->bartype);
|
||
} else {
|
||
SetOutputData((uint8_t *)"PAY", 3);
|
||
SetOutputData((uint8_t *)POSOUTBUF, dataLen);
|
||
ReportData(pCode->bartype);
|
||
}
|
||
}
|
||
|
||
} else {
|
||
//扫码数据输出
|
||
if(!gReceiveKey)
|
||
{
|
||
SetPackType(PACK_TYPEA);
|
||
SetOutputData((uint8_t *)"NOKEY", 5);
|
||
ReportData(pCode->bartype);
|
||
} else {
|
||
SetOutputData((uint8_t *)"SCAN", 4);
|
||
SetOutputData((uint8_t *)POSOUTBUF, dataLen);
|
||
ReportData(pCode->bartype);
|
||
}
|
||
}
|
||
|
||
#if(SUPPORT_VOICE)
|
||
|
||
//语音播放
|
||
if(gConfgBuf.voiceStatus == VOICE_PAY)
|
||
{
|
||
//按支付码类型,区分语音类型播放
|
||
payCodeType = ScanCodeType(pCode);
|
||
{
|
||
if(gConfgBuf.voiceScanFinish == VOICE_FINISH_PRINT)
|
||
{
|
||
}
|
||
else if(gConfgBuf.voiceScanFinish == VOICE_SCAN_SUCCESS)
|
||
{
|
||
addPlayList(VOICEDATA,(uint8_t *)scanSuccessFile, sizeof(scanSuccessFile));
|
||
}
|
||
else
|
||
{
|
||
//除支付宝、微信、云闪付外,播放叮咚
|
||
addPlayList(VOICEDATA,(uint8_t *)scanFinishFile, sizeof(scanFinishFile));
|
||
}
|
||
}
|
||
}
|
||
else if(gConfgBuf.voiceStatus == VOICE_NO_PAY)
|
||
{
|
||
if(gConfgBuf.voiceScanFinish == VOICE_FINISH_PRINT)
|
||
{
|
||
}
|
||
else if(gConfgBuf.voiceScanFinish == VOICE_SCAN_SUCCESS)
|
||
{
|
||
addPlayList(VOICEDATA,(uint8_t *)scanSuccessFile, sizeof(scanSuccessFile));
|
||
}
|
||
else
|
||
{
|
||
//除支付宝、微信、云闪付外,播放叮咚
|
||
addPlayList(VOICEDATA,(uint8_t *)scanFinishFile, sizeof(scanFinishFile));
|
||
}
|
||
}
|
||
|
||
#endif
|
||
}
|
||
|
||
/**
|
||
* @function PayCodeReport
|
||
* @brief 设置码输出提示
|
||
* @param[in] pCode 解码数据
|
||
* @return
|
||
*/
|
||
void SetCodeReport(uint8_t setstatus)
|
||
{
|
||
//声音
|
||
if(gConfgBuf.buzzerStatus)
|
||
{
|
||
if(setstatus == TMC_OK)
|
||
{
|
||
BuzzerSelect(SET_CODE_SUCEESS);
|
||
}
|
||
else
|
||
{
|
||
BuzzerSelect(SET_CODE_ERROR);
|
||
}
|
||
}
|
||
|
||
#if(SUPPORT_VOICE)
|
||
|
||
//语音播放
|
||
if(gConfgBuf.voiceStatus)
|
||
{
|
||
if(setstatus == TMC_OK)
|
||
{
|
||
AppVoiceSelect(SET_CODE_SUCEESS);
|
||
}
|
||
else
|
||
{
|
||
AppVoiceSelect(SET_CODE_ERROR);
|
||
}
|
||
}
|
||
|
||
#endif
|
||
}
|
||
|