X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=serialport.c;h=c2a1a0cc606d7bda66527c275ffdd875ebc94973;hb=77f262c4f93264bf48b0832399528a557314eb5e;hp=ce306fdffa08a29e2d4026da54c7a4bbb6658f97;hpb=24c1a4bb053e517a55eb0f6355b8f362659d4caf;p=libserialport.git diff --git a/serialport.c b/serialport.c index ce306fd..c2a1a0c 100644 --- a/serialport.c +++ b/serialport.c @@ -45,17 +45,44 @@ #include "serialport.h" -static char **sp_list_append(char **list, void *data, size_t len) +int sp_get_port_by_name(const char *portname, struct sp_port **port_ptr) +{ + struct sp_port *port; + int len; + + *port_ptr = NULL; + + if (!portname) + return SP_ERR_ARG; + + if (!(port = malloc(sizeof(struct sp_port)))) + return SP_ERR_MEM; + + len = strlen(portname) + 1; + + if (!(port->name = malloc(len))) + { + free(port); + return SP_ERR_MEM; + } + + memcpy(port->name, portname, len); + + *port_ptr = port; + + return SP_OK; +} + +static struct sp_port **sp_list_append(struct sp_port **list, const char *portname) { void *tmp; unsigned int count; for (count = 0; list[count]; count++); - if (!(tmp = realloc(list, sizeof(char *) * (count + 2)))) + if (!(tmp = realloc(list, sizeof(struct sp_port *) * (count + 2)))) goto fail; list = tmp; - if (!(list[count] = malloc(len))) + if (sp_get_port_by_name(portname, &list[count]) != SP_OK) goto fail; - memcpy(list[count], data, len); list[count + 1] = NULL; return list; fail: @@ -68,12 +95,13 @@ fail: * * @return A null-terminated array of port name strings. */ -char **sp_list_ports(void) +int sp_list_ports(struct sp_port ***list_ptr) { - char **list; + struct sp_port **list; + int ret = SP_OK; - if (!(list = malloc(sizeof(char *)))) - return NULL; + if (!(list = malloc(sizeof(struct sp_port **)))) + return SP_ERR_MEM;; list[0] = NULL; @@ -83,18 +111,32 @@ char **sp_list_ports(void) DWORD max_value_len, max_data_size, max_data_len; DWORD value_len, data_size, data_len; DWORD type, index = 0; + char *name; + int name_len; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS) - return NULL; + { + ret = SP_ERR_FAIL; + goto out_done; + } if (RegQueryInfoKey(key, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &max_value_len, &max_data_size, NULL, NULL) != ERROR_SUCCESS) + { + ret = SP_ERR_FAIL; goto out_close; + } max_data_len = max_data_size / sizeof(TCHAR); if (!(value = malloc((max_value_len + 1) * sizeof(TCHAR)))) + { + ret = SP_ERR_MEM; goto out_close; + } if (!(data = malloc((max_data_len + 1) * sizeof(TCHAR)))) + { + ret = SP_ERR_MEM; goto out_free_value; + } while ( value_len = max_value_len, data_size = max_data_size, @@ -103,10 +145,26 @@ char **sp_list_ports(void) { data_len = data_size / sizeof(TCHAR); data[data_len] = '\0'; - if (type == REG_SZ) - if (!(list = sp_list_append(list, - data, (data_len + 1) * sizeof(TCHAR)))) - goto out; +#ifdef UNICODE + name_len = WideCharToMultiByte(CP_ACP, 0, data, -1, NULL, 0, NULL, NULL) +#else + name_len = data_len + 1; +#endif + if (!(name = malloc(name_len))) + { + ret = SP_ERR_MEM; + goto out; + } +#ifdef UNICODE + WideCharToMultiByte(CP_ACP, 0, data, -1, name, name_len, NULL, NULL); +#else + strcpy(name, data); +#endif + if (type == REG_SZ && !(list = sp_list_append(list, name))) + { + ret = SP_ERR_MEM; + goto out; + } index++; } out: @@ -115,7 +173,7 @@ out_free_value: free(value); out_close: RegCloseKey(key); - return list; +out_done: #endif #ifdef __APPLE__ mach_port_t master; @@ -127,19 +185,31 @@ out_close: Boolean result; if (IOMasterPort(MACH_PORT_NULL, &master) != KERN_SUCCESS) - return NULL; + { + ret = SP_ERR_FAIL; + goto out_done; + } if (!(classes = IOServiceMatching(kIOSerialBSDServiceValue))) - return NULL; + { + ret = SP_ERR_FAIL; + goto out_done; + } CFDictionarySetValue(classes, CFSTR(kIOSerialBSDTypeKey), CFSTR(kIOSerialBSDAllTypes)); if (!(IOServiceGetMatchingServices(master, classes, &iter))) - return NULL; + { + ret = SP_ERR_FAIL; + goto out_done; + } if (!(path = malloc(PATH_MAX))) + { + ret = SP_ERR_MEM; goto out_release; + } while ((port = IOIteratorNext(iter))) { cf_path = IORegistryEntryCreateCFProperty(port, @@ -148,21 +218,20 @@ out_close: result = CFStringGetCString(cf_path, path, PATH_MAX, kCFStringEncodingASCII); CFRelease(cf_path); - if (result) - if (!(list = sp_list_append(list, path, strlen(path) + 1))) - { - IOObjectRelease(port); - goto out; - } + if (result && !(list = sp_list_append(list, path))) + { + ret = SP_ERR_MEM; + IOObjectRelease(port); + goto out; + } } IOObjectRelease(port); } - out: free(path); out_release: IOObjectRelease(iter); - return list; +out_done: #endif #ifdef __linux__ struct udev *ud; @@ -208,23 +277,39 @@ out_release: if (serial_info.type == PORT_UNKNOWN) goto skip; } - list = sp_list_append(list, (void *)name, strlen(name) + 1); + list = sp_list_append(list, name); skip: udev_device_unref(ud_dev); if (!list) + { + ret = SP_ERR_MEM; goto out; + } } out: udev_enumerate_unref(ud_enumerate); udev_unref(ud); - return list; #endif + + if (ret == SP_OK) + { + *list_ptr = list; + } + else + { + if (list) + sp_free_port_list(list); + + *list_ptr = NULL; + } + + return ret; } /** * Free a port list returned by sp_list_ports. */ -void sp_free_port_list(char **list) +void sp_free_port_list(struct sp_port **list) { unsigned int i; for (i = 0; list[i]; i++) @@ -259,16 +344,11 @@ static int sp_validate_port(struct sp_port *port) * @return SP_OK on success, SP_ERR_FAIL on failure, * or SP_ERR_ARG if an invalid port or name is passed. */ -int sp_open(struct sp_port *port, char *portname, int flags) +int sp_open(struct sp_port *port, int flags) { if (!port) return SP_ERR_ARG; - if (!portname) - return SP_ERR_ARG; - - port->name = portname; - #ifdef _WIN32 DWORD desired_access = 0, flags_and_attributes = 0; /* Map 'flags' to the OS-specific settings. */