通过以太网端口发送数据(verifone vx520)

时间:2015-08-13 05:58:08

标签: point-of-sale verifone

我想使用以太网端口通过create socket发送数据。

如何打开以太网端口并设置IP,NETMASK和GateWay? 我可以使用这些功能,但我不知道如何打开以太网端口或如何配置这些功能。

ceSETNWParamValue();
ceGetNWParamValue();
ceSetDDParamValue();

1 个答案:

答案 0 :(得分:2)

嗯," Verix eVo第二卷操作系统和通信程序员指南" (尤其是第5章)可以帮助你一点点,但在我们开始之前,有一件重要的事情需要考虑 - 如果你使用的是你在vx520上编写的程序,你可能会想要在另一个终端类型在未来的某个时刻。为此,您可以考虑使用CommServer。 CommServer是一个程序,可帮助从代码中抽象出各种类型的硬件,因此您可以将相同的命令发送到任何终端类型,并让它根据所使用的硬件确定如何完成请求。它已经存在了一段时间,并已被移植到大多数VerFone终端类型。它由VeriFone免费提供(并支持)。它有一些缺点:

  • 它只增加了一个你必须下载的程序(而且它很大)
  • 它要求您通过Flexi Records发送请求,这可能会让您首先设置起来有点混乱。
  • 它增加了1层可能使调试复杂化的移动部件
  • 如果您之前没有使用过VMAC,那么您现在就需要使用它(这是另一个程序,而且更复杂)。

然而,一旦你开始工作,它真的很棒:

  • 对所有硬件使用相同的代码
  • 如果终端上运行的多个应用程序都需要使用IP通信,则在任何应用程序中都不需要TCP / IP库,这通常会导致整体尺寸变小。

很有可能在某些时候,您需要与另一个第三方共享您的终端。如果是这种情况,那么无论如何,您都需要让您的程序在VMAC上运行,而且他们很可能也会使用CommServer。如果情况确实如此,那么" CON"中的2个刚刚消失,其中一个" PRO" s刚刚被强调。

所以现在你必须选择 - CommServer,或者没有CommServer。

如果您选择CommServer,您需要非常熟悉FlexiRecords的工作方式,因此作为先决条件,我建议您阅读" Verix eVo Multi-App Conductor Programmers Guide" 。接下来,程序流程将如下所示:

1)用

初始化事件缓冲区
// Initializes the buffer provided to store a new flexi-record structure. 
// This is a flexirecord public interface function.
vVarInitRecord(buffer, sizeof(buffer), 0);

// Assigns the buffer passed as a parameter to the global space of the Extended 
// Flexi-record API.This is a mandatory function call for the rest of the Extended 
// Flexi-record APIs.The buffer should be initialized using vVarInitRecord()
// function before calling this API.
ushInitStandardFlexi(buffer);

//send the event (you'll need some other boiler plate code)
// you'll probably want to turn this into a "SendEvent" method
EESL_send_event("COMMSVR", VCS_EVT_INIT_REQ, buffer, bufferSize);

// read the response from CommSever (again, this is a skeletal sample)
// This will become a "ReadEvent" method
while(strcmp(sendername, "COMMSVR") || eventID != VCS_EVT_INIT_RESP)
    eventID = EESL_read_cust_evt(buffer, sizeof(buffer), &bufferSize, sendername);

2)连接

vVarInitRecord(eco->Buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);

// shVarAddData will add an un-typed field to a variable record
// The field VCS_FLD_CONN_URL is defined as a URL or an IP address to connect to. 
// All syntax validation of URL or IP address is performed by the TCP/IP library.
shVarAddData(VCS_FLD_CONN_URL, hostip, strlen(hostip));

// shVarAddUnsignedInt adds (unsurprisingly) an unsigned int to the Flexi-record.
// The constant VCS_FLD_CONN_PORT defines the TCP/IP port number
shVarAddUnsignedInt(VCS_FLD_CONN_PORT, port);

// The value VCS_FLD_CONN_HOSTSSL represents a flag that indicates whether SSL
// is supported or not: (1 - SSL supported, 0 - SSL not supported)
shVarAddUnsignedInt(VCS_FLD_CONN_HOSTSSL, useSSL);
// (if you are going to use SSL, you'll need to add some other values, too)

//Honestly, I don't know what this is, but I don't think it works without it
shVarAddUnsignedInt(VCS_FLD_CONN_HOSTCTX, (unsigned short)0);

//send the event (you'll need some other boiler plate code)
EESL_send_event("COMMSVR", VCS_EVT_CONN_REQ, buffer, bufferSize);

// read the response from CommSever (use the same "receive" code from above, 
// but you are looking for the response "VCS_EVT_CONN_RESP"
EESL_read_cust_evt(buffer, sizeof(buffer), &bufferSize, sendername);

3)确认您已连接

vVarInitRecord(buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);
// Add Status ID buffer to the parameter list
shVarAddData(VCS_FLD_STATUS_IDS, (unsigned char*)statusIDs, (sizeof(int) * 2));

// do your "sendEvent" from above with the event VCS_EVT_STATUS_REQ
SendEvent(VCS_EVT_STATUS_REQ);

// do your "ReceiveEvent" from above, looking for VCS_EVT_STATUS_RESP
ReadEvent(VCS_EVT_STATUS_RESP);

// Extract data from event buffer
ushInitStandardFlexi(buffer);

//This is the eVo (520) version:
shVarGetUnsignedInt(VCS_FLD_CONN_STATUS, (unsigned short*)&connStatus);
//This is the Verix/Vx version
//shVarGetData(VCS_FLD_CONN_STATUS, (unsigned char*)&connStatus, 
               sizeof(unsigned short), &dataLength);

if (connStatus == 1) {/* you are connected */}

4)发送

vVarInitRecord(eco->Buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);

//Add length parameter to the data stack.
shVarAddUnsignedInt(VCS_FLD_SEND_BUFSIZE, p_size);

// Send Event to server. Note that this doesn't actually send the data, it simply
// tells CommServer that data will be coming shortly. It also advises the length
// of the data to be sent
SendEvent(VCS_EVT_SEND_REQ); // this is your function, remember?


/* Send the raw data to the host via Comm Server */
EESL_send_event("COMMSVR", VCS_EVT_DATA_RAW, buffer, sendLength);


// Read Comm Server's response message. Note that this isn't yet the host response
// message. We're simply checking to make sure that our data was delivered correctly
// to Comm Server. We'll get the actual response later...
ReadEvent(VCS_EVT_SEND_RESP); // your function

5)收到

vVarInitRecord(buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);

/* Add parameters to send to server */
shVarAddUnsignedInt(VCS_FLD_RECV_BUFSIZE, p_size);
shVarAddUnsignedInt(VCS_FLD_RECV_TIMEOUT, p_timeout);


// Send Event to server. Again, note that this doesn't actually receive any data,
// it simply prepares comm server for sending us the raw data and will
// tell us how many bytes we should be expecting
SendEvent(VCS_EVT_RECV_REQ);

// Read event from server
ReadEvent(VCS_EVT_RECV_RESP);

// Extract data from event buffer. We're particularly interested in the number
// total of bytes available to read. Note that we haven't actually read anything
// at this point. We simply got the number of bytes AVAILABLE to read
ushInitStandardFlexi(eco->Buffer);

//Now do the actual read
EESL_send_event("COMMSVR", VCS_EVT_DATA_RAW, (unsigned char *)buffer, readSize);

5)断开连接

vVarInitRecord(buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);
SendEvent(VCS_EVT_DISC_REQ)
ReadEvent(VCS_EVT_DISC_RESP);

除此之外,还有更多的东西,但这是它的要点。

此时,您可能会想到自己,"这看起来很复杂 - 我怎么能在没有CommServer的情况下做到这一点?"好吧,现在我们冒险进入一个我不太熟悉的领域,我可能不会那么有用,但我确实有一个代码示例可以进行以下调用(注意我的代码示例超过1500行) ,所以我不能在这里包括所有内容):

//important includes:
#include <ctype.h>
#include <svc_net.h>
#include <ceif.h>
#include <vos_ddi_ini.h>

// Init Comm Engine
ceRegister();

// Subscribe to notification events from CommEngine
ceEnableEventNotification();


// Check how many network interfaces (NWIF) are available and store in stNIInfo
g_NICount=ceGetNWIFCount();
g_NIInfo = (unsigned char*) malloc (g_NICount * sizeof (stNIInfo));
ceGetNWIFInfo((stNIInfo*)g_NIInfo, g_NICount, &nwInfoCount);
FillNWIF ((stNIInfo*)g_NIInfo, g_NICount);

// Check the link speed
ceGetDDParamValue (g_currMediaInfo.niHandle, "GET_LINK_SPEED",
            sizeof (szLinkSpeed), szLinkSpeed, &linkValueLen);

FillNWIF被定义为

void FillNWIF (stNIInfo stArray[], int arrayCount)
{
  int cntr = 0;
  for (cntr = 0; cntr < arrayCount; cntr++)
  {
    if (strcmp (stArray [cntr].niCommTech, CE_COMM_TECH_ETH) == 0) 
      g_Devices.devEthernet.iDevHandle = stArray [cntr].niHandle;
    else if (strcmp (stArray [cntr].niCommTech, CE_COMM_TECH_PPPDIAL) == 0)
      g_Devices.devDialPPP.iDevHandle = stArray [cntr].niHandle;
    else if (strcmp (stArray [cntr].niCommTech, CE_COMM_TECH_DIALONLY) == 0)
      g_Devices.devDial.iDevHandle = stArray [cntr].niHandle;
  }
}

简而言之,实际的连接和发送如下:

struct sockaddr_in  sockHost;

memset (&sockHost, 0, sizeof (struct sockaddr_in));
memset (&timeout, 0, sizeof (struct timeval));

sockHost.sin_family = AF_INET;
sockHost.sin_addr.s_addr = htonl (inet_addr (g_AppConfig.szHostIP));
sockHost.sin_port = htons (g_AppConfig.iPort);

sockType = SOCK_STREAM;
sockHandle = socket (AF_INET, sockType, 0);

connect (sockHandle, (struct sockaddr*)&sockHost, sizeof (struct sockaddr_in));

send (iSockHandle, szSendBuff, uiSendSize, 0);
recv (iSockHandle, szRecvBuff, sizeof (szRecvBuff), 0);

您可能会觉得有用的其他API:

//get network interface start mode
ceGetNWIFStartMode (g_currMediaInfo.niHandle);

// Get the total number of network interface from this terminal
g_NICount=ceGetNWIFCount();

//Get network interfaces
ceGetNWIFInfo((stNIInfo*)g_NIInfo, g_NICount, &nwInfoCount);

// only open the NWIF
ceStartNWIF (g_currMediaInfo.niHandle, CE_OPEN);

//close NWIF
ceStopNWIF (g_currMediaInfo.niHandle, CE_CLOSE);

// connect
ceStartNWIF (g_currMediaInfo.niHandle, CE_CONNECT);

//get connection status
ceGetNWParamValue (iNWIFHandle, IP_CONFIG, &ipConfig, sizeof (stNI_IPConfig), &pLen);

//link up
ceStartNWIF (g_currMediaInfo.niHandle, CE_LINK)

//network up
ceStartNWIF (g_currMediaInfo.niHandle, CE_NETWORK);

//network down
ceStopNWIF (g_currMediaInfo.niHandle, CE_NETWORK);

//link down
ceStopNWIF (g_currMediaInfo.niHandle, CE_LINK);

//Disconnect
ceStopNWIF (g_currMediaInfo.niHandle, CE_DISCONNECT);

// Get the version;
ceGetVersion (CE_VER_VXCE, sizeof (g_szVXCEVersion), g_szVXCEVersion);
ceGetVersion (CE_VER_CEIF, sizeof (g_szCEIFVersion), g_szCEIFVersion);

要解决下面的make文件注释,您的make文件应该有一行如下所示:

$(EVOSDK)\bin\vrxcc $(COptions) $(Includes) $(AppObjects) $(Libs) -o $(OutDir)\Project.out`. 

在此之上,需要定义COptionsIncludesAppObjectsLibs中的每一个。

<强> COptions

COptions是您要使用的编译器选项。您的&#34; Verix eVo第三卷OS编程工具参考手册&#34;中有几个可能的选项,但作为示例,您可以将其设置为:

COptions = -p -DLOGSYS_FLAG -DLOGSYS_NEW_API_STYLE
  • -p表示它适用于ARM11处理器(即此代码适用于520而不是570)
  • -DLOGSYS_FLAG表示您要启用LOG_PRINTF语句和
  • -DLOGSYS_NEW_API_STYLE表示您要使用新的宏(不需要双括号)

<强>含

Includes是告诉编译器在哪里查找标题(.h)文件的方法。每次使用#include语句时,都需要确保.h列表中包含Includes文件所在的目录。例如,如果您想要#include <ceif.h>,则需要确保将-I$(EOSSDK)\include作为包含路径的一部分。您可以设置Includes的示例如下:

Includes = -I.\include -I$(EVOSDK)\include -I$(EOSSDK)\include -I$(EVOACT)\include -I$(EVOVCS)include -I$(EVOVMAC)include
  • 请注意,每个前面都有-I。这告诉编译器它是Include而不是库文件。
  • .\include指向我制作的.h文件。请注意,它使用相对目录,因此它假定我的 include 文件夹在我的make文件所在的同一位置可见。
  • EVOSDKEOSSDKEVOACT中的每一个都可能会在您的所有项目中使用
  • EVOVCS如果您使用的是commserver
  • EVOVMAC如果您使用的是VMAC(如果您使用的是commserver,则会是这样)
  • 如果您没有使用VMAC或CommServer,请将最后2个关闭。

<强>应用对象

对于您拥有的每个.c文件,您需要将其编译为对象(.o)文件。你可以在技术上用下面的Libs来推动它,因为它实际上是一样的。唯一的区别是你做了这些;他们不是SDK或其他任何东西的一部分。

<强>利布斯

Libs可能看起来像这样:

Libs =  $(EOSSDK)\lib\svc_net.o \
        $(EOSSDK)\lib\ssl.o \
        $(EOSSDK)\lib\ceif.o \
        $(EOSSDK)\lib\elog.o \
        $(EVOACT)\Output\RV\Files\Static\Release\act2000.a
  • ceif.o是您需要使用ceif.h中定义的内容的目标文件。
  • 请注意,每行末尾都有\(除了最后一行)。这只是告诉nmake这条线路还在继续。您可以正确删除每个\并将其全部放在一行上。这只是为了便于阅读。

最后一部分,-o $(OutDir)\Project.out只是说你要输出编译结果的位置。