-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathseriallib.c
284 lines (219 loc) · 12.5 KB
/
seriallib.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
#if defined(_WIN32) || defined(_WIN64)
#include <windows.h>
#endif
#include "seriallib.h"
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
char* formatSerialPortName(int num) {
#if defined(_WIN32) || defined(_WIN64)
char *data = malloc (sizeof (char) * 15); // Allocates memory to handle all possible argument numbers between 1 and 256
char *str = malloc (sizeof (char) * 4); // Allocates memory just to cast the given argument number into a char
sprintf(str, "%d", num); // Casts the int to char
strcpy(data, "\\\\.\\COM"); // Copies the port base name into the previously allocated space
strcat(data, str); // Concatenates the newly casted char with the port base name
return data;
#elif defined(__linux__) || defined(__linux)
// No code yet
#endif
}
int getSerialPortAvailability(char *portName) {
#if defined(_WIN32) || defined(_WIN64)
HANDLE hComm;
/*----------------------------------- Opening the Serial Port --------------------------------------------*/
hComm = CreateFile(portName, // Port name
GENERIC_READ | GENERIC_WRITE, // Read/Write
0, // No Sharing
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE) {
printf("Error! CreateFile() %s\n", portName);
return 0;
}
CloseHandle(hComm); //Closing the Serial Port
return 1;
#elif defined(__linux__) || defined(__linux)
// No code yet
#endif
}
void updateAvailablePortsInfo(AVAILABLE_PORTS *ports) {
#if defined(_WIN32) || defined(_WIN64)
ports->openQuantity = 0; // Struct initialization
// int array[S_PORTS] = { 0 }; // As the memory was already allocated/initialized for the array, it can only be updated by whole copying a new one over the existant one
// memcpy(ports->statusList, array, sizeof array); // These two lines are just for good practices, they are not actually needed
int i, status; // These two variables are just for loop actions control
for (i = 0; i < S_PORTS; ++i) {
status = getSerialPortAvailability(formatSerialPortName(i));
if (status != 0) { // Zero status means that the port is not available
ports->openQuantity++; // Updates the number of open ports
ports->statusList[i] = status; // Records which port got its status different from zero on its proper position of number array
status = 0; // Clear the status value for the next iteration
}
}
#elif defined(__linux__) || defined(__linux)
// No code yet
#endif
}
void writeSerialPort(char *portName, int baudRate, DATA_BUFFER *buffer) {
#if defined(_WIN32) || defined(_WIN64)
HANDLE hComm; // Handle to the Serial port
BOOL Status;
buffer->code = 0; // Default code is zero
*buffer->message = 0; // Straightest way to erase all pointer content
/*----------------------------------- Opening the Serial Port --------------------------------------------*/
hComm = CreateFile(portName, // Name of the Port to be Opened
GENERIC_READ | GENERIC_WRITE, // Read/Write Access
0, // No Sharing, ports cant be shared
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE) {
strcpy(buffer->message, "Error! CreateFile() ");
strcat(buffer->message, portName);
return;
}
/*------------------------------- Setting the Parameters for the SerialPort ------------------------------*/
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Status = GetCommState(hComm, &dcbSerialParams); //retreives the current settings
if (Status == FALSE) {
strcpy(buffer->message, "Error! GetCommState() ");
strcat(buffer->message, portName);
return;
}
dcbSerialParams.BaudRate = baudRate; // Setting BaudRate = CBR_<baud_rate_number>
dcbSerialParams.ByteSize = 8; // Setting ByteSize = 8
dcbSerialParams.StopBits = ONESTOPBIT; // Setting StopBits = 1
dcbSerialParams.Parity = NOPARITY; // Setting Parity = None
Status = SetCommState(hComm, &dcbSerialParams); //Configuring the port according to settings in DCB
if (Status == FALSE) {
strcpy(buffer->message, "Error! GetCommState() ");
strcat(buffer->message, portName);
return;
}
/*------------------------------------ Setting Timeouts --------------------------------------------------*/
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (SetCommTimeouts(hComm, &timeouts) == FALSE) {
strcpy(buffer->message, "Error! SetCommState() ");
strcat(buffer->message, portName);
return;
}
/*----------------------------- Writing a Character to Serial Port----------------------------------------*/
DWORD dNoOFBytestoWrite; // No of bytes to write into the port
DWORD dNoOfBytesWritten = 0; // No of bytes written to the port
dNoOFBytestoWrite = sizeof(buffer->message); // Calculating the no of bytes to write into the port
Status = WriteFile(hComm, // Handle to the Serialport
buffer->message, // Data to be written to the port (should be char or byte array, otherwise write will fail)
dNoOFBytestoWrite, // No of bytes to write into the port
&dNoOfBytesWritten, // No of bytes written to the port
NULL);
if (Status != TRUE) {
strcpy(buffer->message, "Error ");
char *str = malloc (sizeof (char) * 4); // Allocates memory just to cast the given argument number into a char
sprintf(str, "%d", GetLastError()); // Casts the int to char
strcat(buffer->message, str);
strcat(buffer->message, " WriteFile() ");
strcat(buffer->message, portName);
return;
}
buffer->code = 1;
CloseHandle(hComm); // Closing the Serial Port
return;
#elif defined(__linux__) || defined(__linux)
// No code yet
#endif
}
void listenSerialPort(char *portName, int baudRate, DATA_BUFFER *buffer) {
#if defined(_WIN32) || defined(_WIN64)
HANDLE hComm; // Handle to the Serial port
BOOL Status; // Status of the various operations
DWORD dwEventMask; // Event mask to trigger
char TempChar; // Temperory Character
DWORD NoBytesRead; // Bytes read by ReadFile()
int i = 0;
buffer->code = 0; // Default code is zero
*buffer->message = 0; // Straightest way to erase all pointer content
/*----------------------------------- Opening the Serial Port --------------------------------------------*/
hComm = CreateFile(portName, // Name of the Port to be Opened
GENERIC_READ | GENERIC_WRITE, // Read/Write Access
0, // No Sharing, ports cant be shared
NULL, // No Security
OPEN_EXISTING, // Open existing port only
0, // Non Overlapped I/O
NULL); // Null for Comm Devices
if (hComm == INVALID_HANDLE_VALUE) {
strcpy(buffer->message, "Error! CreateFile() ");
strcat(buffer->message, portName);
return;
}
/*------------------------------- Setting the Parameters for the SerialPort ------------------------------*/
DCB dcbSerialParams = { 0 }; // Initializing DCB structure
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
Status = GetCommState(hComm, &dcbSerialParams); //retreives the current settings
if (Status == FALSE) {
strcpy(buffer->message, "Error! GetCommState() ");
strcat(buffer->message, portName);
return;
}
dcbSerialParams.BaudRate = baudRate; // Setting BaudRate = CBR_<baud_rate_number>
dcbSerialParams.ByteSize = 8; // Setting ByteSize = 8
dcbSerialParams.StopBits = ONESTOPBIT; // Setting StopBits = 1
dcbSerialParams.Parity = NOPARITY; // Setting Parity = None
Status = SetCommState(hComm, &dcbSerialParams); //Configuring the port according to settings in DCB
if (Status == FALSE) {
strcpy(buffer->message, "Error! SetCommState() ");
strcat(buffer->message, portName);
return;
}
/*------------------------------------ Setting Timeouts --------------------------------------------------*/
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (SetCommTimeouts(hComm, &timeouts) == FALSE) {
strcpy(buffer->message, "Error! SetCommTimeouts() ");
strcat(buffer->message, portName);
return;
}
/*------------------------------------ Setting Receive Mask ----------------------------------------------*/
Status = SetCommMask(hComm, EV_RXCHAR); //Configure Windows to Monitor the serial device for Character Reception
if (Status == FALSE) {
strcpy(buffer->message, "Error! SetCommMask() ");
strcat(buffer->message, portName);
return;
}
/*------------------------------------ Setting WaitComm() Event ----------------------------------------*/
Status = WaitCommEvent(hComm, &dwEventMask, NULL); //Wait for the character to be received
/*-------------------------- Program will Wait here till a Character is received ------------------------*/
if (Status == FALSE) {
strcpy(buffer->message, "Error! WaitCommEvent() ");
strcat(buffer->message, portName);
return;
}
else { //If WaitCommEvent() == True, read the RXed data using ReadFile();
buffer->code = 1;
do {
Status = ReadFile(hComm, &TempChar, sizeof(TempChar), &NoBytesRead, NULL);
// SerialBuffer[i] = TempChar;
buffer->data[i] = TempChar;
i++;
}
// while (NoBytesRead > 0 && i < S_BUFFER); // Need improvement in logic
while (i < S_BUFFER);
}
CloseHandle(hComm); //Closing the Serial Port
return;
#elif defined(__linux__) || defined(__linux)
// No code yet
#endif
}