util.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. /*
  2. * Copyright (C) 2007-2010 Michael Buesch <m@bues.ch>
  3. *
  4. * This program is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU General Public License
  6. * as published by the Free Software Foundation; either version 2
  7. * of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. */
  14. #include "util.h"
  15. #include "razer_private.h"
  16. #include <unistd.h>
  17. #include <errno.h>
  18. #include <ctype.h>
  19. #include <stdarg.h>
  20. void razer_free(void *ptr, size_t size)
  21. {
  22. if (ptr) {
  23. memset(ptr, 0, size);
  24. free(ptr);
  25. }
  26. }
  27. char * razer_strsplit(char *str, char sep)
  28. {
  29. char c;
  30. if (!str)
  31. return NULL;
  32. for (c = *str; c != '\0' && c != sep; c = *str)
  33. str++;
  34. if (c == sep) {
  35. *str = '\0';
  36. return str + 1;
  37. }
  38. return NULL;
  39. }
  40. int razer_split_tuple(const char *str, char sep,
  41. size_t elems_max_len, ...)
  42. {
  43. char *elem;
  44. va_list ap;
  45. int err = 0;
  46. if (!elems_max_len)
  47. return -EINVAL;
  48. if (strlen(str) >= elems_max_len)
  49. return -EINVAL;
  50. va_start(ap, elems_max_len);
  51. while (1) {
  52. elem = va_arg(ap, char *);
  53. if (!elem)
  54. break;
  55. elem[0] = '\0';
  56. if (!str) {
  57. err = -ENODATA;
  58. continue;
  59. }
  60. razer_strlcpy(elem, str, elems_max_len);
  61. str = razer_strsplit(elem, sep);
  62. }
  63. va_end(ap);
  64. return err;
  65. }
  66. int razer_string_to_int(const char *string, int *i)
  67. {
  68. char *tailptr;
  69. long retval;
  70. retval = strtol(string, &tailptr, 0);
  71. if (tailptr == string || tailptr[0] != '\0')
  72. return -EINVAL;
  73. *i = retval;
  74. return 0;
  75. }
  76. int razer_string_to_bool(const char *string, bool *b)
  77. {
  78. int i;
  79. if (strcasecmp(string, "yes") == 0 ||
  80. strcasecmp(string, "true") == 0 ||
  81. strcasecmp(string, "on") == 0) {
  82. *b = 1;
  83. return 0;
  84. }
  85. if (strcasecmp(string, "no") == 0 ||
  86. strcasecmp(string, "false") == 0 ||
  87. strcasecmp(string, "off") == 0) {
  88. *b = 0;
  89. return 0;
  90. }
  91. if (!razer_string_to_int(string, &i)) {
  92. *b = !!i;
  93. return 0;
  94. }
  95. return -EINVAL;
  96. }
  97. int razer_string_to_mode(const char *string, enum razer_led_mode *mode)
  98. {
  99. if (strcasecmp(string, "static") == 0) {
  100. *mode = RAZER_LED_MODE_STATIC;
  101. return 0;
  102. }
  103. if (strcasecmp(string, "spectrum") == 0) {
  104. *mode = RAZER_LED_MODE_SPECTRUM;
  105. return 0;
  106. }
  107. if (strcasecmp(string, "breathing") == 0) {
  108. *mode = RAZER_LED_MODE_BREATHING;
  109. return 0;
  110. }
  111. if (strcasecmp(string, "wave") == 0) {
  112. *mode = RAZER_LED_MODE_WAVE;
  113. return 0;
  114. }
  115. if (strcasecmp(string, "reaction") == 0) {
  116. *mode = RAZER_LED_MODE_REACTION;
  117. return 0;
  118. }
  119. return -EINVAL;
  120. }
  121. int razer_string_to_color(const char *string, struct razer_rgb_color *color)
  122. {
  123. uint32_t temp = (uint32_t)strtol(string, NULL, 16);
  124. color->r = (uint8_t)((temp >> 16) & 0xFF);
  125. color->g = (uint8_t)((temp >> 8) & 0xFF);
  126. color->b = (uint8_t)(temp & 0xFF);
  127. color->valid = 1;
  128. return 0;
  129. }
  130. char * razer_string_strip(char *str)
  131. {
  132. char *start = str;
  133. size_t len;
  134. if (!str)
  135. return NULL;
  136. while (*start != '\0' && isspace(*start))
  137. start++;
  138. len = strlen(start);
  139. while (len && isspace(start[len - 1])) {
  140. start[len - 1] = '\0';
  141. len--;
  142. }
  143. return start;
  144. }
  145. void razer_strlcpy(char *dst, const char *src, size_t dst_size)
  146. {
  147. size_t len;
  148. if (!dst_size)
  149. return;
  150. len = strlen(src);
  151. if (len >= dst_size)
  152. len = dst_size - 1;
  153. memcpy(dst, src, len);
  154. dst[len] = 0;
  155. }
  156. void razer_timeval_add_msec(struct timeval *tv, unsigned int msec)
  157. {
  158. unsigned int seconds, usec;
  159. seconds = msec / 1000;
  160. msec = msec % 1000;
  161. usec = msec * 1000;
  162. tv->tv_usec += usec;
  163. while (tv->tv_usec >= 1000000) {
  164. tv->tv_sec++;
  165. tv->tv_usec -= 1000000;
  166. }
  167. tv->tv_sec += seconds;
  168. }
  169. /* Returns true, if a is after b. */
  170. bool razer_timeval_after(const struct timeval *a, const struct timeval *b)
  171. {
  172. if (a->tv_sec > b->tv_sec)
  173. return 1;
  174. if ((a->tv_sec == b->tv_sec) && (a->tv_usec > b->tv_usec))
  175. return 1;
  176. return 0;
  177. }
  178. /* Return a-b in milliseconds */
  179. int razer_timeval_msec_diff(const struct timeval *a, const struct timeval *b)
  180. {
  181. int64_t usec_a, usec_b, usec_diff;
  182. usec_a = (int64_t)a->tv_sec * 1000000;
  183. usec_a += (int64_t)a->tv_usec;
  184. usec_b = (int64_t)b->tv_sec * 1000000;
  185. usec_b += (int64_t)b->tv_usec;
  186. usec_diff = usec_a - usec_b;
  187. return usec_diff / 1000;
  188. }
  189. void razer_msleep(unsigned int msecs)
  190. {
  191. int err;
  192. struct timespec time;
  193. time.tv_sec = 0;
  194. while (msecs >= 1000) {
  195. time.tv_sec++;
  196. msecs -= 1000;
  197. }
  198. time.tv_nsec = msecs;
  199. time.tv_nsec *= 1000000;
  200. do {
  201. err = nanosleep(&time, &time);
  202. } while (err && errno == EINTR);
  203. if (err) {
  204. razer_error("nanosleep() failed with: %s\n",
  205. strerror(errno));
  206. }
  207. }
  208. le16_t razer_xor16_checksum(const void *_buffer, size_t size)
  209. {
  210. const uint8_t *buffer = _buffer;
  211. uint16_t sum = 0;
  212. size_t i;
  213. for (i = 0; i < size; i += 2) {
  214. sum ^= buffer[i];
  215. if (i < size - 1)
  216. sum ^= ((uint16_t)(buffer[i + 1])) << 8;
  217. }
  218. return cpu_to_le16(sum);
  219. }
  220. be16_t razer_xor16_checksum_be(const void *_buffer, size_t size)
  221. {
  222. return (be16_t)bswap_16((uint16_t)razer_xor16_checksum(_buffer, size));
  223. }
  224. uint8_t razer_xor8_checksum(const void *_buffer, size_t size)
  225. {
  226. const uint8_t *buffer = _buffer;
  227. uint8_t sum = 0;
  228. size_t i;
  229. for (i = 0; i < size; i++)
  230. sum ^= buffer[i];
  231. return sum;
  232. }
  233. static char razer_char_to_ascii(char c)
  234. {
  235. if (c >= 32 && c <= 126)
  236. return c;
  237. return '.';
  238. }
  239. void razer_dump(const char *prefix, const void *_buf, size_t size)
  240. {
  241. const unsigned char *buf = _buf;
  242. size_t i;
  243. char ascii[17] = { 0, };
  244. unsigned int ascii_idx = 0;
  245. for (i = 0; i < size; i++) {
  246. if (i % 16 == 0) {
  247. if (i != 0) {
  248. printf(" |%s|\n", ascii);
  249. memset(ascii, 0, sizeof(ascii));
  250. ascii_idx = 0;
  251. }
  252. printf("%s-[%04X]: ", prefix, (unsigned int)i);
  253. }
  254. printf("%02X%s", buf[i], (i % 2) ? " " : "");
  255. ascii[ascii_idx++] = razer_char_to_ascii(buf[i]);
  256. }
  257. if (ascii[0]) {
  258. for (; i % 16; i++)
  259. printf((i % 2) ? " " : " ");
  260. printf(" |%s|", ascii);
  261. }
  262. printf("\n\n");
  263. }
  264. void razer_ascii_to_utf16(razer_utf16_t *dest, size_t dest_max_chars,
  265. const char *src)
  266. {
  267. size_t count = 0;
  268. if (!dest_max_chars)
  269. return;
  270. /* FIXME: This code is wrong.
  271. * But it works for most strings in the current setup.
  272. * So it probably won't blow up too often.
  273. */
  274. while (count < dest_max_chars - 1) {
  275. if (!*src)
  276. break;
  277. *dest++ = *src++;
  278. count++;
  279. }
  280. *dest = 0;
  281. }
  282. int razer_utf16_cpy(razer_utf16_t *dest, const razer_utf16_t *src,
  283. size_t max_chars)
  284. {
  285. size_t i;
  286. for (i = 0; i < max_chars; i++, dest++, src++) {
  287. *dest = *src;
  288. if (!(*src))
  289. return 0;
  290. }
  291. return -ENOSPC;
  292. }
  293. size_t razer_utf16_strlen(const razer_utf16_t *str)
  294. {
  295. size_t count = 0;
  296. while (*str) {
  297. str++;
  298. count++;
  299. }
  300. return count;
  301. }