I want to use Ethernet port to send data with create socket.
How can I open the Ethernet port and set IP, NETMASK and GateWay? I can use these functions but I don't know how to open the Ethernet port or how to configure these functions.
ceSETNWParamValue();
ceGetNWParamValue();
ceSetDDParamValue();
Well, The "Verix eVo Volume II OS and Communication Programmers Guide" (esp. chapter 5) can help you out a bit, but before we get into that, there is one important thing to consider--if you are using this program that you are writing on a vx520, you will likely want it on another terminal type at some point in the future. To that end, you may consider using CommServer. CommServer is a program that helps abstract the various types of hardware out of your code so you can send the same commands to any terminal type and let it determine how to fulfill your requests based on what hardware it is using. It has been around for a while and has been ported to most of the VerFone terminal types. It is provided (and supported) by VeriFone for free. There are a few downsides to it:
However, once you get it working, it's really nice:
There is a good chance that at some point, you'll need to share your terminal with another 3rd party. If that's the case, you'll need to have your program running on top of VMAC, anyway, AND there is a good chance they'll be using CommServer, too. If this is ever the case, 2 of the "CON"s just disappeared and one of the "PRO"s was just emphasized.
So now you have to choose--CommServer, or no CommServer.
If you choose CommServer, you'll need to get very familiar with how FlexiRecords work so as a prerequisite, I suggest you read Chapter 7 of the "Verix eVo Multi-App Conductor Programmers Guide". Next, the program flow will go something like this:
1) Initialize the event buffer with
// 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) Connect
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) Verify you are connected
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) Send
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) Receive
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) Disconnect
vVarInitRecord(buffer, sizeof(buffer), 0);
ushInitStandardFlexi(buffer);
SendEvent(VCS_EVT_DISC_REQ)
ReadEvent(VCS_EVT_DISC_RESP);
There's going to be more to it than that, but that's the gist of it.
At this point, you are likely thinking to yourself, "That looks complicated--how can I do it WITHOUT CommServer?" Well, now we are venturing into a realm that I am less familiar with and I probably won't be that helpful, but I do have a code sample that makes the following calls (note that my code sample is over 1500 lines long, so I can't include it all here):
//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);
Where FillNWIF is defined as
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;
}
}
The actual connect and send is, in a nutshell, as follows:
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);
Other APIs you may find useful:
//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);
To address the make file comments below, your make file should have a line that is something like the following:
$(EVOSDK)\bin\vrxcc $(COptions) $(Includes) $(AppObjects) $(Libs) -o $(OutDir)\Project.out`.
Above that, each of COptions
, Includes
, AppObjects
, and Libs
need to be defined.
COptions
COptions
are the compiler options you want to use. Several possible options are in your "Verix eVo Volume III OS programming tools reference manual", but as an example, you might set it to:
COptions = -p -DLOGSYS_FLAG -DLOGSYS_NEW_API_STYLE
-p
indicates that it is for the ARM11 processor (i.e., this code is for the 520, not the 570)-DLOGSYS_FLAG
says that you want to enable LOG_PRINTF statements and-DLOGSYS_NEW_API_STYLE
indicates that you want to use the new macros (that don't require double parenthesis)Includes
Includes
is how you tell the compiler where to look for your header (.h) files. Any time you use a #include
statement, you need to make sure that the directory where that .h
file lives is represented in your Includes
list. For example, if you want to #include <ceif.h>
then you need to make sure you have -I$(EOSSDK)\include
as part of your includes path. An example of how you may set your Includes
might be:
Includes = -I.\include -I$(EVOSDK)\include -I$(EOSSDK)\include -I$(EVOACT)\include -I$(EVOVCS)include -I$(EVOVMAC)include
-I
in front of each. This tells the compiler that it is an Include
and not a library file..\include
points to my .h files that I made. Note that it uses a relative directory and so it assumes that my include folder is visible from the same place that my make file exists.EVOSDK
, EOSSDK
, and EVOACT
will probably be used in all your projectsEVOVCS
is if you are using commserverEVOVMAC
is if you are using VMAC (which you will be if you are using commserver)AppObjects
For each .c
file you have, you need to compile it into an object (.o
) file. You could technically roll this up with Libs
below as it is really the same thing. The only difference is that you made these; they aren't part of the SDK or anything.
Libs
Libs
might look something like this:
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
is the object file that you'll need to use the things that are defined in ceif.h.\
at the end of each line (except the last). That's just to tell nmake that this line continues. You could just as correctly remove each \
and put it all on 1 line. This is just for readability.The last part, -o $(OutDir)\Project.out
is just saying where you want to output the result of your compilation.