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