/* * Copyright (C) 2007-2010 Michael Buesch * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "util.h" #include "razer_private.h" #include #include #include #include void razer_free(void *ptr, size_t size) { if (ptr) { memset(ptr, 0, size); free(ptr); } } char * razer_strsplit(char *str, char sep) { char c; if (!str) return NULL; for (c = *str; c != '\0' && c != sep; c = *str) str++; if (c == sep) { *str = '\0'; return str + 1; } return NULL; } int razer_split_tuple(const char *str, char sep, size_t elems_max_len, ...) { char *elem; va_list ap; int err = 0; if (!elems_max_len) return -EINVAL; if (strlen(str) >= elems_max_len) return -EINVAL; va_start(ap, elems_max_len); while (1) { elem = va_arg(ap, char *); if (!elem) break; elem[0] = '\0'; if (!str) { err = -ENODATA; continue; } razer_strlcpy(elem, str, elems_max_len); str = razer_strsplit(elem, sep); } va_end(ap); return err; } int razer_string_to_int(const char *string, int *i) { char *tailptr; long retval; retval = strtol(string, &tailptr, 0); if (tailptr == string || tailptr[0] != '\0') return -EINVAL; *i = retval; return 0; } int razer_string_to_bool(const char *string, bool *b) { int i; if (strcasecmp(string, "yes") == 0 || strcasecmp(string, "true") == 0 || strcasecmp(string, "on") == 0) { *b = 1; return 0; } if (strcasecmp(string, "no") == 0 || strcasecmp(string, "false") == 0 || strcasecmp(string, "off") == 0) { *b = 0; return 0; } if (!razer_string_to_int(string, &i)) { *b = !!i; return 0; } return -EINVAL; } int razer_string_to_mode(const char *string, enum razer_led_mode *mode) { if (strcasecmp(string, "static") == 0) { *mode = RAZER_LED_MODE_STATIC; return 0; } if (strcasecmp(string, "spectrum") == 0) { *mode = RAZER_LED_MODE_SPECTRUM; return 0; } if (strcasecmp(string, "breathing") == 0) { *mode = RAZER_LED_MODE_BREATHING; return 0; } if (strcasecmp(string, "wave") == 0) { *mode = RAZER_LED_MODE_WAVE; return 0; } if (strcasecmp(string, "reaction") == 0) { *mode = RAZER_LED_MODE_REACTION; return 0; } return -EINVAL; } int razer_string_to_color(const char *string, struct razer_rgb_color *color) { uint32_t temp = (uint32_t)strtol(string, NULL, 16); color->r = (uint8_t)((temp >> 16) & 0xFF); color->g = (uint8_t)((temp >> 8) & 0xFF); color->b = (uint8_t)(temp & 0xFF); color->valid = 1; return 0; } char * razer_string_strip(char *str) { char *start = str; size_t len; if (!str) return NULL; while (*start != '\0' && isspace(*start)) start++; len = strlen(start); while (len && isspace(start[len - 1])) { start[len - 1] = '\0'; len--; } return start; } void razer_strlcpy(char *dst, const char *src, size_t dst_size) { size_t len; if (!dst_size) return; len = strlen(src); if (len >= dst_size) len = dst_size - 1; memcpy(dst, src, len); dst[len] = 0; } void razer_timeval_add_msec(struct timeval *tv, unsigned int msec) { unsigned int seconds, usec; seconds = msec / 1000; msec = msec % 1000; usec = msec * 1000; tv->tv_usec += usec; while (tv->tv_usec >= 1000000) { tv->tv_sec++; tv->tv_usec -= 1000000; } tv->tv_sec += seconds; } /* Returns true, if a is after b. */ bool razer_timeval_after(const struct timeval *a, const struct timeval *b) { if (a->tv_sec > b->tv_sec) return 1; if ((a->tv_sec == b->tv_sec) && (a->tv_usec > b->tv_usec)) return 1; return 0; } /* Return a-b in milliseconds */ int razer_timeval_msec_diff(const struct timeval *a, const struct timeval *b) { int64_t usec_a, usec_b, usec_diff; usec_a = (int64_t)a->tv_sec * 1000000; usec_a += (int64_t)a->tv_usec; usec_b = (int64_t)b->tv_sec * 1000000; usec_b += (int64_t)b->tv_usec; usec_diff = usec_a - usec_b; return usec_diff / 1000; } void razer_msleep(unsigned int msecs) { int err; struct timespec time; time.tv_sec = 0; while (msecs >= 1000) { time.tv_sec++; msecs -= 1000; } time.tv_nsec = msecs; time.tv_nsec *= 1000000; do { err = nanosleep(&time, &time); } while (err && errno == EINTR); if (err) { razer_error("nanosleep() failed with: %s\n", strerror(errno)); } } le16_t razer_xor16_checksum(const void *_buffer, size_t size) { const uint8_t *buffer = _buffer; uint16_t sum = 0; size_t i; for (i = 0; i < size; i += 2) { sum ^= buffer[i]; if (i < size - 1) sum ^= ((uint16_t)(buffer[i + 1])) << 8; } return cpu_to_le16(sum); } be16_t razer_xor16_checksum_be(const void *_buffer, size_t size) { return (be16_t)bswap_16((uint16_t)razer_xor16_checksum(_buffer, size)); } uint8_t razer_xor8_checksum(const void *_buffer, size_t size) { const uint8_t *buffer = _buffer; uint8_t sum = 0; size_t i; for (i = 0; i < size; i++) sum ^= buffer[i]; return sum; } static char razer_char_to_ascii(char c) { if (c >= 32 && c <= 126) return c; return '.'; } void razer_dump(const char *prefix, const void *_buf, size_t size) { const unsigned char *buf = _buf; size_t i; char ascii[17] = { 0, }; unsigned int ascii_idx = 0; for (i = 0; i < size; i++) { if (i % 16 == 0) { if (i != 0) { printf(" |%s|\n", ascii); memset(ascii, 0, sizeof(ascii)); ascii_idx = 0; } printf("%s-[%04X]: ", prefix, (unsigned int)i); } printf("%02X%s", buf[i], (i % 2) ? " " : ""); ascii[ascii_idx++] = razer_char_to_ascii(buf[i]); } if (ascii[0]) { for (; i % 16; i++) printf((i % 2) ? " " : " "); printf(" |%s|", ascii); } printf("\n\n"); } void razer_ascii_to_utf16(razer_utf16_t *dest, size_t dest_max_chars, const char *src) { size_t count = 0; if (!dest_max_chars) return; /* FIXME: This code is wrong. * But it works for most strings in the current setup. * So it probably won't blow up too often. */ while (count < dest_max_chars - 1) { if (!*src) break; *dest++ = *src++; count++; } *dest = 0; } int razer_utf16_cpy(razer_utf16_t *dest, const razer_utf16_t *src, size_t max_chars) { size_t i; for (i = 0; i < max_chars; i++, dest++, src++) { *dest = *src; if (!(*src)) return 0; } return -ENOSPC; } size_t razer_utf16_strlen(const razer_utf16_t *str) { size_t count = 0; while (*str) { str++; count++; } return count; }