]> sigrok.org Git - libserialport.git/blob - serialport.c
Fix building on OSX and Linux.
[libserialport.git] / serialport.c
1 /*
2  * This file is part of the libserialport project.
3  *
4  * Copyright (C) 2010-2012 Bert Vermeulen <bert@biot.com>
5  * Copyright (C) 2010-2012 Uwe Hermann <uwe@hermann-uwe.de>
6  * Copyright (C) 2013 Martin Ling <martin-libserialport@earth.li>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as
10  * published by the Free Software Foundation, either version 3 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
20  */
21
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <errno.h>
29 #ifdef _WIN32
30 #include <windows.h>
31 #include <tchar.h>
32 #else
33 #include <termios.h>
34 #include <sys/ioctl.h>
35 #endif
36 #ifdef __APPLE__
37 #include <IOKit/IOKitLib.h>
38 #include <IOKit/serial/IOSerialKeys.h>
39 #include <sys/syslimits.h>
40 #endif
41 #ifdef __linux__
42 #include "libudev.h"
43 #include "linux/serial.h"
44 #endif
45
46 #include "serialport.h"
47
48 static char **sp_list_new(void)
49 {
50         char **list;
51         if ((list = malloc(sizeof(char *))))
52                 list[0] = NULL;
53         return list;
54 }
55
56 static char **sp_list_append(char **list, void *data, size_t len)
57 {
58         void *tmp;
59         unsigned int count;
60         for (count = 0; list[count]; count++);
61         if (!(tmp = realloc(list, sizeof(char *) * (count + 2))))
62                 goto fail;
63         list = tmp;
64         if (!(list[count] = malloc(len)))
65                 goto fail;
66         memcpy(list[count], data, len);
67         list[count + 1] = NULL;
68         return list;
69 fail:
70         sp_free_port_list(list);
71         return NULL;
72 }
73
74 /**
75  * List the serial ports available on the system.
76  *
77  * @return A null-terminated array of port name strings.
78  */
79 char **sp_list_ports(void)
80 {
81         char **list = NULL;
82
83 #ifdef _WIN32
84         HKEY key;
85         TCHAR *value, *data;
86         DWORD max_value_len, max_data_size, max_data_len;
87         DWORD value_len, data_size, data_len;
88         DWORD type, index = 0;
89
90         if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"),
91                         0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
92                 return NULL;
93         if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
94                                 &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS)
95                 goto out_close;
96         max_data_len = max_data_size / sizeof(TCHAR);
97         if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR))))
98                 goto out_close;
99         if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR))))
100                 goto out_free_value;
101         if (!(list = sp_list_new()))
102                 goto out;
103         while (
104                 value_len = max_value_len,
105                 data_size = max_data_size,
106                 RegEnumValue(key, index, value, &value_len,
107                         NULL, &type, (LPBYTE)data, &data_size) == ERROR_SUCCESS)
108         {
109                 data_len = data_size / sizeof(TCHAR);
110                 data[data_len] = '\0';
111                 if (type == REG_SZ)
112                         if (!(list = sp_list_append(list,
113                                         data, (data_len + 1) * sizeof(TCHAR))))
114                                 goto out;
115                 index++;
116         }
117 out:
118         free(data);
119 out_free_value:
120         free(value);
121 out_close:
122         RegCloseKey(key);
123         return list;
124 #endif
125 #ifdef __APPLE__
126         mach_port_t master;
127         CFMutableDictionaryRef classes;
128         io_iterator_t iter;
129         char *path;
130         io_object_t port;
131         CFTypeRef cf_path;
132         Boolean result;
133
134         if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS)
135                 return NULL;
136
137         if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue)))
138                 return NULL;
139
140         CFDictionarySetValue(classes,
141                         CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes));
142
143         if (!(IOServiceGetMatchingServices(master, classes, &iter)))
144                 return NULL;
145
146         if (!(path = malloc(PATH_MAX)))
147                 goto out_release;
148
149         if (!(list = sp_list_new()))
150                 goto out;
151
152         while ((port = IOIteratorNext(iter))) {
153                 cf_path = IORegistryEntryCreateCFProperty(port,
154                                 CFSTR(kIOCalloutDeviceKey), kCFAllocatorDefault, 0);
155                 if (cf_path) {
156                         result = CFStringGetCString(cf_path,
157                                         path, PATH_MAX, kCFStringEncodingASCII);
158                         CFRelease(cf_path);
159                         if (result)
160                                 if (!(list = sp_list_append(list, path, strlen(path) + 1)))
161                                 {
162                                         IOObjectRelease(port);
163                                         goto out;
164                                 }
165                 }
166                 IOObjectRelease(port);
167         }
168
169 out:
170         free(path);
171 out_release:
172         IOObjectRelease(iter);
173         return list;
174 #endif
175 #ifdef __linux__
176         struct udev *ud;
177         struct udev_enumerate *ud_enumerate;
178         struct udev_list_entry *ud_list;
179         struct udev_list_entry *ud_entry;
180         const char *path;
181         struct udev_device *ud_dev, *ud_parent;
182         const char *name;
183         const char *driver;
184         int fd, ioctl_result;
185         struct serial_struct serial_info;
186
187         ud = udev_new();
188         ud_enumerate = udev_enumerate_new(ud);
189         udev_enumerate_add_match_subsystem(ud_enumerate, "tty");
190         udev_enumerate_scan_devices(ud_enumerate);
191         ud_list = udev_enumerate_get_list_entry(ud_enumerate);
192         if (!(list = sp_list_new()))
193                 goto out;
194         udev_list_entry_foreach(ud_entry, ud_list)
195         {
196                 path = udev_list_entry_get_name(ud_entry);
197                 ud_dev = udev_device_new_from_syspath(ud, path);
198                 /* If there is no parent device, this is a virtual tty. */
199                 ud_parent = udev_device_get_parent(ud_dev);
200                 if (ud_parent == NULL)
201                 {
202                         udev_device_unref(ud_dev);
203                         continue;
204                 }
205                 name = udev_device_get_devnode(ud_dev);
206                 /* The serial8250 driver has a hardcoded number of ports.
207                  * The only way to tell which actually exist on a given system
208                  * is to try to open them and make an ioctl call. */
209                 driver = udev_device_get_driver(ud_parent);
210                 if (driver && !strcmp(driver, "serial8250"))
211                 {
212                         if ((fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY)) < 0)
213                                 goto skip;
214                         ioctl_result = ioctl(fd, TIOCGSERIAL, &serial_info);
215                         close(fd);
216                         if (ioctl_result != 0)
217                                 goto skip;
218                         if (serial_info.type == PORT_UNKNOWN)
219                                 goto skip;
220                 }
221                 list = sp_list_append(list, (void *)name, strlen(name) + 1);
222 skip:
223                 udev_device_unref(ud_dev);
224                 if (!list)
225                         goto out;
226         }
227 out:
228         udev_enumerate_unref(ud_enumerate);
229         udev_unref(ud);
230         return list;
231 #endif
232 }
233
234 /**
235  * Free a port list returned by sp_list_ports.
236  */
237 void sp_free_port_list(char **list)
238 {
239         unsigned int i;
240         for (i = 0; list[i]; i++)
241                 free(list[i]);
242         free(list);
243 }
244
245 static int sp_validate_port(struct sp_port *port)
246 {
247         if (port == NULL)
248                 return 0;
249 #ifdef _WIN32
250         if (port->hdl == INVALID_HANDLE_VALUE)
251                 return 0;
252 #else
253         if (port->fd < 0)
254                 return 0;
255 #endif
256         return 1;
257 }
258
259 #define CHECK_PORT() do { if (!sp_validate_port(port)) return SP_ERR_ARG; } while (0)
260
261 /**
262  * Open the specified serial port.
263  *
264  * @param port Pointer to empty port structure allocated by caller.
265  * @param portname Name of port to open.
266  * @param flags Flags to use when opening the serial port. Possible flags
267  *              are: SP_MODE_RDWR, SP_MODE_RDONLY, SP_MODE_NONBLOCK.
268  *
269  * @return SP_OK on success, SP_ERR_FAIL on failure,
270  *         or SP_ERR_ARG if an invalid port or name is passed.
271  */
272 int sp_open(struct sp_port *port, char *portname, int flags)
273 {
274         if (!port)
275                 return SP_ERR_ARG;
276
277         if (!portname)
278                 return SP_ERR_ARG;
279
280         port->name = portname;
281
282 #ifdef _WIN32
283         DWORD desired_access = 0, flags_and_attributes = 0;
284         /* Map 'flags' to the OS-specific settings. */
285         desired_access |= GENERIC_READ;
286         flags_and_attributes = FILE_ATTRIBUTE_NORMAL;
287         if (flags & SP_MODE_RDWR)
288                 desired_access |= GENERIC_WRITE;
289         if (flags & SP_MODE_NONBLOCK)
290                 flags_and_attributes |= FILE_FLAG_OVERLAPPED;
291
292         port->hdl = CreateFile(port->name, desired_access, 0, 0,
293                          OPEN_EXISTING, flags_and_attributes, 0);
294         if (port->hdl == INVALID_HANDLE_VALUE)
295                 return SP_ERR_FAIL;
296 #else
297         int flags_local = 0;
298         /* Map 'flags' to the OS-specific settings. */
299         if (flags & SP_MODE_RDWR)
300                 flags_local |= O_RDWR;
301         if (flags & SP_MODE_RDONLY)
302                 flags_local |= O_RDONLY;
303         if (flags & SP_MODE_NONBLOCK)
304                 flags_local |= O_NONBLOCK;
305
306         if ((port->fd = open(port->name, flags_local)) < 0)
307                 return SP_ERR_FAIL;
308 #endif
309
310         return SP_OK;
311 }
312
313 /**
314  * Close the specified serial port.
315  *
316  * @param port Pointer to port structure.
317  *
318  * @return SP_OK on success, SP_ERR_FAIL on failure,
319  *         or SP_ERR_ARG if an invalid port is passed.
320  */
321 int sp_close(struct sp_port *port)
322 {
323         CHECK_PORT();
324
325 #ifdef _WIN32
326         /* Returns non-zero upon success, 0 upon failure. */
327         if (CloseHandle(port->hdl) == 0)
328                 return SP_ERR_FAIL;
329 #else
330         /* Returns 0 upon success, -1 upon failure. */
331         if (close(port->fd) == -1)
332                 return SP_ERR_FAIL;
333 #endif
334
335         return SP_OK;
336 }
337
338 /**
339  * Flush serial port buffers.
340  *
341  * @param port Pointer to port structure.
342  *
343  * @return SP_OK on success, SP_ERR_FAIL on failure,
344  *         or SP_ERR_ARG if an invalid port is passed.
345  */
346 int sp_flush(struct sp_port *port)
347 {
348         CHECK_PORT();
349
350 #ifdef _WIN32
351         /* Returns non-zero upon success, 0 upon failure. */
352         if (PurgeComm(port->hdl, PURGE_RXCLEAR | PURGE_TXCLEAR) == 0)
353                 return SP_ERR_FAIL;
354 #else
355         /* Returns 0 upon success, -1 upon failure. */
356         if (tcflush(port->fd, TCIOFLUSH) < 0)
357                 return SP_ERR_FAIL;
358 #endif
359         return SP_OK;
360 }
361
362 /**
363  * Write a number of bytes to the specified serial port.
364  *
365  * @param port Pointer to port structure.
366  * @param buf Buffer containing the bytes to write.
367  * @param count Number of bytes to write.
368  *
369  * @return The number of bytes written, SP_ERR_FAIL on failure,
370  *         or SP_ERR_ARG if an invalid port is passed.
371  */
372 int sp_write(struct sp_port *port, const void *buf, size_t count)
373 {
374         CHECK_PORT();
375
376         if (!buf)
377                 return SP_ERR_ARG;
378
379 #ifdef _WIN32
380         DWORD written = 0;
381         /* Returns non-zero upon success, 0 upon failure. */
382         if (WriteFile(port->hdl, buf, count, &written, NULL) == 0)
383                 return SP_ERR_FAIL;
384         return written;
385 #else
386         /* Returns the number of bytes written, or -1 upon failure. */
387         ssize_t written = write(port->fd, buf, count);
388         if (written < 0)
389                 return SP_ERR_FAIL;
390         else
391                 return written;;
392 #endif
393 }
394
395 /**
396  * Read a number of bytes from the specified serial port.
397  *
398  * @param port Pointer to port structure.
399  * @param buf Buffer where to store the bytes that are read.
400  * @param count The number of bytes to read.
401  *
402  * @return The number of bytes read, SP_ERR_FAIL on failure,
403  *         or SP_ERR_ARG if an invalid port is passed.
404  */
405 int sp_read(struct sp_port *port, void *buf, size_t count)
406 {
407         CHECK_PORT();
408
409         if (!buf)
410                 return SP_ERR_ARG;
411
412 #ifdef _WIN32
413         DWORD bytes_read = 0;
414         /* Returns non-zero upon success, 0 upon failure. */
415         if (ReadFile(port->hdl, buf, count, &bytes_read, NULL) == 0)
416                 return SP_ERR_FAIL;
417         return bytes_read;
418 #else
419         ssize_t bytes_read;
420         /* Returns the number of bytes read, or -1 upon failure. */
421         if ((bytes_read = read(port->fd, buf, count)) < 0)
422                 return SP_ERR_FAIL;
423         return bytes_read;
424 #endif
425 }
426
427 /**
428  * Set serial parameters for the specified serial port.
429  *
430  * @param port Pointer to port structure.
431  * @param baudrate The baudrate to set.
432  * @param bits The number of data bits to use.
433  * @param parity The parity setting to use (0 = none, 1 = even, 2 = odd).
434  * @param stopbits The number of stop bits to use (1 or 2).
435  * @param flowcontrol The flow control settings to use (0 = none, 1 = RTS/CTS,
436  *                    2 = XON/XOFF).
437  *
438  * @return The number of bytes read, SP_ERR_FAIL on failure,
439  *         or SP_ERR_ARG if an invalid argument is passed.
440  */
441 int sp_set_params(struct sp_port *port, int baudrate,
442                               int bits, int parity, int stopbits,
443                               int flowcontrol, int rts, int dtr)
444 {
445         CHECK_PORT();
446
447 #ifdef _WIN32
448         DCB dcb;
449
450         if (!GetCommState(port->hdl, &dcb))
451                 return SP_ERR_FAIL;
452
453         switch (baudrate) {
454         /*
455          * The baudrates 50/75/134/150/200/1800/230400/460800 do not seem to
456          * have documented CBR_* macros.
457          */
458         case 110:
459                 dcb.BaudRate = CBR_110;
460                 break;
461         case 300:
462                 dcb.BaudRate = CBR_300;
463                 break;
464         case 600:
465                 dcb.BaudRate = CBR_600;
466                 break;
467         case 1200:
468                 dcb.BaudRate = CBR_1200;
469                 break;
470         case 2400:
471                 dcb.BaudRate = CBR_2400;
472                 break;
473         case 4800:
474                 dcb.BaudRate = CBR_4800;
475                 break;
476         case 9600:
477                 dcb.BaudRate = CBR_9600;
478                 break;
479         case 14400:
480                 dcb.BaudRate = CBR_14400; /* Not available on Unix? */
481                 break;
482         case 19200:
483                 dcb.BaudRate = CBR_19200;
484                 break;
485         case 38400:
486                 dcb.BaudRate = CBR_38400;
487                 break;
488         case 57600:
489                 dcb.BaudRate = CBR_57600;
490                 break;
491         case 115200:
492                 dcb.BaudRate = CBR_115200;
493                 break;
494         case 128000:
495                 dcb.BaudRate = CBR_128000; /* Not available on Unix? */
496                 break;
497         case 256000:
498                 dcb.BaudRate = CBR_256000; /* Not available on Unix? */
499                 break;
500         default:
501                 return SP_ERR_ARG;
502         }
503
504         switch (stopbits) {
505         /* Note: There's also ONE5STOPBITS == 1.5 (unneeded so far). */
506         case 1:
507                 dcb.StopBits = ONESTOPBIT;
508                 break;
509         case 2:
510                 dcb.StopBits = TWOSTOPBITS;
511                 break;
512         default:
513                 return SP_ERR_ARG;
514         }
515
516         switch (parity) {
517         /* Note: There's also SPACEPARITY, MARKPARITY (unneeded so far). */
518         case SP_PARITY_NONE:
519                 dcb.Parity = NOPARITY;
520                 break;
521         case SP_PARITY_EVEN:
522                 dcb.Parity = EVENPARITY;
523                 break;
524         case SP_PARITY_ODD:
525                 dcb.Parity = ODDPARITY;
526                 break;
527         default:
528                 return SP_ERR_ARG;
529         }
530
531         if (rts != -1) {
532                 if (rts)
533                         dcb.fRtsControl = RTS_CONTROL_ENABLE;
534                 else
535                         dcb.fRtsControl = RTS_CONTROL_DISABLE;
536         }
537
538         if (dtr != -1) {
539                 if (dtr)
540                         dcb.fDtrControl = DTR_CONTROL_ENABLE;
541                 else
542                         dcb.fDtrControl = DTR_CONTROL_DISABLE;
543         }
544
545         if (!SetCommState(port->hdl, &dcb))
546                 return SP_ERR_FAIL;
547 #else
548         struct termios term;
549         speed_t baud;
550         int controlbits;
551
552         if (tcgetattr(port->fd, &term) < 0)
553                 return SP_ERR_FAIL;
554
555         switch (baudrate) {
556         case 50:
557                 baud = B50;
558                 break;
559         case 75:
560                 baud = B75;
561                 break;
562         case 110:
563                 baud = B110;
564                 break;
565         case 134:
566                 baud = B134;
567                 break;
568         case 150:
569                 baud = B150;
570                 break;
571         case 200:
572                 baud = B200;
573                 break;
574         case 300:
575                 baud = B300;
576                 break;
577         case 600:
578                 baud = B600;
579                 break;
580         case 1200:
581                 baud = B1200;
582                 break;
583         case 1800:
584                 baud = B1800;
585                 break;
586         case 2400:
587                 baud = B2400;
588                 break;
589         case 4800:
590                 baud = B4800;
591                 break;
592         case 9600:
593                 baud = B9600;
594                 break;
595         case 19200:
596                 baud = B19200;
597                 break;
598         case 38400:
599                 baud = B38400;
600                 break;
601         case 57600:
602                 baud = B57600;
603                 break;
604         case 115200:
605                 baud = B115200;
606                 break;
607         case 230400:
608                 baud = B230400;
609                 break;
610 #if !defined(__APPLE__) && !defined(__OpenBSD__)
611         case 460800:
612                 baud = B460800;
613                 break;
614 #endif
615         default:
616                 return SP_ERR_ARG;
617         }
618
619         if (cfsetospeed(&term, baud) < 0)
620                 return SP_ERR_FAIL;
621
622         if (cfsetispeed(&term, baud) < 0)
623                 return SP_ERR_FAIL;
624
625         term.c_cflag &= ~CSIZE;
626         switch (bits) {
627         case 8:
628                 term.c_cflag |= CS8;
629                 break;
630         case 7:
631                 term.c_cflag |= CS7;
632                 break;
633         default:
634                 return SP_ERR_ARG;
635         }
636
637         term.c_cflag &= ~CSTOPB;
638         switch (stopbits) {
639         case 1:
640                 term.c_cflag &= ~CSTOPB;
641                 break;
642         case 2:
643                 term.c_cflag |= CSTOPB;
644                 break;
645         default:
646                 return SP_ERR_ARG;
647         }
648
649         term.c_iflag &= ~(IXON | IXOFF | IXANY);
650         term.c_cflag &= ~CRTSCTS;
651         switch (flowcontrol) {
652         case 0:
653                 /* No flow control. */
654                 break;
655         case 1:
656                 term.c_cflag |= CRTSCTS;
657                 break;
658         case 2:
659                 term.c_iflag |= IXON | IXOFF | IXANY;
660                 break;
661         default:
662                 return SP_ERR_ARG;
663         }
664
665         term.c_iflag &= ~IGNPAR;
666         term.c_cflag &= ~(PARENB | PARODD);
667         switch (parity) {
668         case SP_PARITY_NONE:
669                 term.c_iflag |= IGNPAR;
670                 break;
671         case SP_PARITY_EVEN:
672                 term.c_cflag |= PARENB;
673                 break;
674         case SP_PARITY_ODD:
675                 term.c_cflag |= PARENB | PARODD;
676                 break;
677         default:
678                 return SP_ERR_ARG;
679         }
680
681         /* Turn off all serial port cooking. */
682         term.c_iflag &= ~(ISTRIP | INLCR | ICRNL);
683         term.c_oflag &= ~(ONLCR | OCRNL | ONOCR);
684 #if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)
685         term.c_oflag &= ~OFILL;
686 #endif
687
688         /* Disable canonical mode, and don't echo input characters. */
689         term.c_lflag &= ~(ICANON | ECHO);
690
691         /* Ignore modem status lines; enable receiver */
692         term.c_cflag |= (CLOCAL | CREAD);
693
694         /* Write the configured settings. */
695         if (tcsetattr(port->fd, TCSADRAIN, &term) < 0)
696                 return SP_ERR_FAIL;
697
698         if (rts != -1) {
699                 controlbits = TIOCM_RTS;
700                 if (ioctl(port->fd, rts ? TIOCMBIS : TIOCMBIC,
701                                 &controlbits) < 0)
702                         return SP_ERR_FAIL;
703         }
704
705         if (dtr != -1) {
706                 controlbits = TIOCM_DTR;
707                 if (ioctl(port->fd, dtr ? TIOCMBIS : TIOCMBIC,
708                                 &controlbits) < 0)
709                         return SP_ERR_FAIL;
710         }
711 #endif
712
713         return SP_OK;
714 }
715
716 /**
717  * Get error code for failed operation.
718  *
719  * In order to obtain the correct result, this function should be called
720  * straight after the failure, before executing any other system operations.
721  *
722  * @return The system's numeric code for the error that caused the last
723  *         operation to fail.
724  */
725 int sp_last_error_code(void)
726 {
727 #ifdef _WIN32
728         return GetLastError();
729 #else
730         return errno;
731 #endif
732 }
733
734 /**
735  * Get error message for failed operation.
736  *
737  * In order to obtain the correct result, this function should be called
738  * straight after the failure, before executing other system operations.
739  *
740  * @return The system's message for the error that caused the last
741  *         operation to fail. This string may be allocated by the function,
742  *         and can be freed after use by calling sp_free_error_message.
743  */
744 char *sp_last_error_message(void)
745 {
746 #ifdef _WIN32
747         LPVOID message;
748         DWORD error = GetLastError();
749
750         FormatMessage(
751                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
752                 FORMAT_MESSAGE_FROM_SYSTEM |
753                 FORMAT_MESSAGE_IGNORE_INSERTS,
754                 NULL,
755                 error,
756                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
757                 (LPTSTR) &message,
758                 0, NULL );
759
760         return message;
761 #else
762         return strerror(errno);
763 #endif
764 }
765
766 /**
767  * Free error message.
768  *
769  * This function can be used to free a string returned by the
770  * sp_last_error_message function.
771  */
772 void sp_free_error_message(char *message)
773 {
774 #ifdef _WIN32
775         LocalFree(message);
776 #else
777         (void)message;
778 #endif
779 }