Amaury Pouly | ba91ff1 | 2016-10-19 17:03:52 +0200 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2016 Amaury Pouly |
| 11 | * |
| 12 | * This program is free software; you can redistribute it and/or |
| 13 | * modify it under the terms of the GNU General Public License |
| 14 | * as published by the Free Software Foundation; either version 2 |
| 15 | * of the License, or (at your option) any later version. |
| 16 | * |
| 17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 18 | * KIND, either express or implied. |
| 19 | * |
| 20 | ****************************************************************************/ |
| 21 | #include "nwz_lib.h" |
Amaury Pouly | c95e30b | 2016-11-11 16:01:14 +0100 | [diff] [blame] | 22 | #include "nwz_db.h" |
Amaury Pouly | 3097239 | 2016-10-28 23:27:29 +0200 | [diff] [blame] | 23 | |
Amaury Pouly | d492f25 | 2016-11-01 17:04:26 +0100 | [diff] [blame] | 24 | int nwz_run(const char *file, const char *args[], bool wait) |
Amaury Pouly | ba91ff1 | 2016-10-19 17:03:52 +0200 | [diff] [blame] | 25 | { |
| 26 | pid_t child_pid = fork(); |
| 27 | if(child_pid != 0) |
| 28 | { |
| 29 | if(wait) |
| 30 | { |
| 31 | int status; |
| 32 | waitpid(child_pid, &status, 0); |
Amaury Pouly | d492f25 | 2016-11-01 17:04:26 +0100 | [diff] [blame] | 33 | return status; |
Amaury Pouly | ba91ff1 | 2016-10-19 17:03:52 +0200 | [diff] [blame] | 34 | } |
Amaury Pouly | d492f25 | 2016-11-01 17:04:26 +0100 | [diff] [blame] | 35 | else |
| 36 | return 0; |
Amaury Pouly | ba91ff1 | 2016-10-19 17:03:52 +0200 | [diff] [blame] | 37 | } |
| 38 | else |
| 39 | { |
| 40 | execvp(file, (char * const *)args); |
| 41 | _exit(1); |
| 42 | } |
| 43 | } |
| 44 | |
Amaury Pouly | d492f25 | 2016-11-01 17:04:26 +0100 | [diff] [blame] | 45 | char *nwz_run_pipe(const char *file, const char *args[], int *status) |
| 46 | { |
| 47 | int pipe_fds[2]; |
| 48 | pipe(pipe_fds); |
| 49 | pid_t child_pid = fork(); |
| 50 | if(child_pid == 0) |
| 51 | { |
| 52 | dup2(pipe_fds[1], 1); /* redirect stdout */ |
| 53 | dup2(pipe_fds[1], 2); /* redirect stderr */ |
| 54 | close(pipe_fds[0]); /* close reading */ |
| 55 | close(pipe_fds[1]); /* close writing */ |
| 56 | execvp(file, (char * const *)args); |
| 57 | _exit(1); |
| 58 | } |
| 59 | else |
| 60 | { |
| 61 | close(pipe_fds[1]); /* close writing */ |
| 62 | char buffer[1024]; |
| 63 | char *output = malloc(1); |
| 64 | ssize_t count; |
| 65 | size_t size = 0; |
| 66 | while((count = read(pipe_fds[0], buffer, sizeof(buffer))) > 0) |
| 67 | { |
| 68 | output = realloc(output, size + count + 1); |
| 69 | memcpy(output + size, buffer, count); |
| 70 | size += count; |
| 71 | } |
| 72 | close(pipe_fds[0]); |
| 73 | output[size] = 0; |
| 74 | waitpid(child_pid, status, 0); |
| 75 | return output; |
| 76 | } |
| 77 | } |
| 78 | |
Amaury Pouly | ba91ff1 | 2016-10-19 17:03:52 +0200 | [diff] [blame] | 79 | void nwz_lcdmsg(bool clear, int x, int y, const char *msg) |
| 80 | { |
| 81 | const char *path_lcdmsg = "/usr/local/bin/lcdmsg"; |
| 82 | const char *args[16]; |
| 83 | int index = 0; |
| 84 | char locate[32]; |
Amaury Pouly | c95e30b | 2016-11-11 16:01:14 +0100 | [diff] [blame] | 85 | args[index++] = "lcdmsg"; |
Amaury Pouly | ba91ff1 | 2016-10-19 17:03:52 +0200 | [diff] [blame] | 86 | if(clear) |
| 87 | args[index++] = "-c"; |
| 88 | args[index++] = "-f"; |
| 89 | args[index++] = "/usr/local/bin/font_08x12.bmp"; |
| 90 | args[index++] = "-l"; |
| 91 | sprintf(locate, "%d,%d", x, y); |
| 92 | args[index++] = locate; |
| 93 | args[index++] = msg; |
| 94 | args[index++] = NULL; |
| 95 | /* wait for lcdmsg to finish to avoid any race conditions in framebuffer |
| 96 | * accesses */ |
| 97 | nwz_run(path_lcdmsg, args, true); |
| 98 | } |
| 99 | |
| 100 | void nwz_lcdmsgf(bool clear, int x, int y, const char *format, ...) |
| 101 | { |
| 102 | char buffer[1024]; |
| 103 | va_list args; |
| 104 | va_start(args, format); |
| 105 | vsprintf(buffer, format, args); |
| 106 | va_end(args); |
| 107 | nwz_lcdmsg(clear, x, y, buffer); |
| 108 | } |
| 109 | |
Amaury Pouly | c95e30b | 2016-11-11 16:01:14 +0100 | [diff] [blame] | 110 | #define NWZ_COLOR_RGB(col) \ |
| 111 | NWZ_COLOR_RED(col), NWZ_COLOR_GREEN(col), NWZ_COLOR_BLUE(col) |
| 112 | |
| 113 | void nwz_display_clear(nwz_color_t color) |
| 114 | { |
| 115 | const char *path_display = "/usr/local/bin/display"; |
| 116 | const char *args[16]; |
| 117 | int index = 0; |
| 118 | char col[32]; |
| 119 | args[index++] = "display"; |
| 120 | args[index++] = "lcd"; |
| 121 | args[index++] = "clear"; |
| 122 | sprintf(col, "%d,%d,%d", NWZ_COLOR_RGB(color)); |
| 123 | args[index++] = col; |
| 124 | args[index++] = NULL; |
| 125 | /* wait for lcdmsg to finish to avoid any race conditions in framebuffer |
| 126 | * accesses */ |
| 127 | nwz_run(path_display, args, true); |
| 128 | } |
| 129 | |
| 130 | void nwz_display_text(int x, int y, bool big_font, nwz_color_t foreground_col, |
| 131 | nwz_color_t background_col, int alpha, const char *text) |
| 132 | { |
| 133 | const char *path_display = "/usr/local/bin/display"; |
| 134 | const char *args[16]; |
| 135 | int index = 0; |
| 136 | char fg[32],bg[32], pos[32], transp[16]; |
| 137 | args[index++] = "display"; |
| 138 | args[index++] = "lcd"; |
| 139 | args[index++] = "text"; |
| 140 | sprintf(pos, "%d,%d", x, y); |
| 141 | args[index++] = pos; |
| 142 | if(big_font) |
| 143 | args[index++] = "/usr/local/bin/font_14x24.bmp"; |
| 144 | else |
| 145 | args[index++] = "/usr/local/bin/font_08x12.bmp"; |
| 146 | sprintf(fg, "%d,%d,%d", NWZ_COLOR_RGB(foreground_col)); |
| 147 | args[index++] = fg; |
| 148 | sprintf(bg, "%d,%d,%d", NWZ_COLOR_RGB(background_col)); |
| 149 | args[index++] = bg; |
| 150 | sprintf(transp, "%d", alpha); |
| 151 | args[index++] = transp; |
| 152 | args[index++] = text; |
| 153 | args[index++] = NULL; |
| 154 | /* wait for lcdmsg to finish to avoid any race conditions in framebuffer |
| 155 | * accesses */ |
| 156 | nwz_run(path_display, args, true); |
| 157 | } |
| 158 | |
Amaury Pouly | 0c1a961 | 2016-11-12 22:16:48 +0100 | [diff] [blame] | 159 | void nwz_display_text_center(int width, int y, bool big_font, nwz_color_t fg, |
| 160 | nwz_color_t bg, int alpha, const char *text) |
| 161 | { |
| 162 | int txt_w = NWZ_FONT_W(big_font) * strlen(text); |
| 163 | nwz_display_text((width - txt_w) / 2, y, big_font, fg, bg, alpha, text); |
| 164 | } |
| 165 | |
Amaury Pouly | c95e30b | 2016-11-11 16:01:14 +0100 | [diff] [blame] | 166 | void nwz_display_textf(int x, int y, bool big_font, nwz_color_t foreground_col, |
| 167 | nwz_color_t background_col, int alpha, const char *fmt, ...) |
| 168 | { |
| 169 | char buffer[1024]; |
| 170 | va_list args; |
| 171 | va_start(args, fmt); |
| 172 | vsprintf(buffer, fmt, args); |
| 173 | va_end(args); |
| 174 | nwz_display_text(x, y, big_font, foreground_col, background_col, alpha, buffer); |
| 175 | } |
| 176 | |
Amaury Pouly | 0c1a961 | 2016-11-12 22:16:48 +0100 | [diff] [blame] | 177 | void nwz_display_textf_center(int width, int y, bool big_font, nwz_color_t fg, |
| 178 | nwz_color_t bg, int alpha, const char *fmt, ...) |
| 179 | { |
| 180 | char buffer[1024]; |
| 181 | va_list args; |
| 182 | va_start(args, fmt); |
| 183 | vsprintf(buffer, fmt, args); |
| 184 | va_end(args); |
| 185 | nwz_display_text_center(width, y, big_font, fg, bg, alpha, buffer); |
| 186 | } |
| 187 | |
Amaury Pouly | c95e30b | 2016-11-11 16:01:14 +0100 | [diff] [blame] | 188 | void nwz_display_bitmap(int x, int y, const char *file, int left, int top, |
| 189 | int width, int height, nwz_color_t key_col, int bmp_alpha) |
| 190 | { |
| 191 | const char *path_display = "/usr/local/bin/display"; |
| 192 | const char *args[16]; |
| 193 | int index = 0; |
| 194 | char pos[32], topleft[32], dim[32], key[32], transp[16]; |
| 195 | args[index++] = "display"; |
| 196 | args[index++] = "lcd"; |
| 197 | args[index++] = "bitmap"; |
| 198 | sprintf(pos, "%d,%d", x, y); |
| 199 | args[index++] = pos; |
| 200 | args[index++] = file; |
| 201 | sprintf(topleft, "%d,%d", left, top); |
| 202 | args[index++] = topleft; |
| 203 | sprintf(dim, "%d,%d", width, height); |
| 204 | args[index++] = dim; |
| 205 | if(key_col == NWZ_COLOR_NO_KEY) |
| 206 | sprintf(key, "no"); |
| 207 | else |
| 208 | sprintf(key, "%d,%d,%d", NWZ_COLOR_RGB(key_col)); |
| 209 | args[index++] = key; |
| 210 | sprintf(transp, "%d", bmp_alpha); |
| 211 | args[index++] = transp; |
| 212 | args[index++] = NULL; |
| 213 | /* wait for lcdmsg to finish to avoid any race conditions in framebuffer |
| 214 | * accesses */ |
| 215 | nwz_run(path_display, args, true); |
| 216 | } |
| 217 | |
Amaury Pouly | d42b43c | 2016-10-20 18:21:00 +0200 | [diff] [blame] | 218 | int nwz_input_open(const char *requested_name) |
| 219 | { |
| 220 | /* try all /dev/input/eventX, there can't a lot of them */ |
| 221 | for(int index = 0; index < 8; index++) |
| 222 | { |
| 223 | char buffer[32]; |
| 224 | sprintf(buffer, "/dev/input/event%d", index); |
| 225 | int fd = open(buffer, O_RDWR); |
| 226 | if(fd < 0) |
| 227 | continue; /* try next one */ |
| 228 | /* query name */ |
| 229 | char name[256]; |
| 230 | if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) >= 0 && |
| 231 | strcmp(name, requested_name) == 0) |
| 232 | return fd; |
| 233 | close(fd); |
| 234 | } |
| 235 | return -1; |
| 236 | } |
| 237 | |
Amaury Pouly | ba91ff1 | 2016-10-19 17:03:52 +0200 | [diff] [blame] | 238 | int nwz_key_open(void) |
| 239 | { |
Amaury Pouly | d42b43c | 2016-10-20 18:21:00 +0200 | [diff] [blame] | 240 | return nwz_input_open(NWZ_KEY_NAME); |
Amaury Pouly | ba91ff1 | 2016-10-19 17:03:52 +0200 | [diff] [blame] | 241 | } |
| 242 | |
| 243 | void nwz_key_close(int fd) |
| 244 | { |
| 245 | close(fd); |
| 246 | } |
| 247 | |
| 248 | int nwz_key_get_hold_status(int fd) |
| 249 | { |
| 250 | unsigned long led_hold = 0; |
| 251 | if(ioctl(fd, EVIOCGLED(sizeof(led_hold)), &led_hold) < 0) |
| 252 | return -1; |
| 253 | return led_hold; |
| 254 | } |
| 255 | |
| 256 | int nwz_key_wait_event(int fd, long tmo_us) |
| 257 | { |
Amaury Pouly | d42b43c | 2016-10-20 18:21:00 +0200 | [diff] [blame] | 258 | return nwz_wait_fds(&fd, 1, tmo_us); |
Amaury Pouly | ba91ff1 | 2016-10-19 17:03:52 +0200 | [diff] [blame] | 259 | } |
| 260 | |
| 261 | int nwz_key_read_event(int fd, struct input_event *evt) |
| 262 | { |
| 263 | int ret = read(fd, evt, sizeof(struct input_event)); |
| 264 | if(ret != sizeof(struct input_event)) |
| 265 | return -1; |
| 266 | return 1; |
| 267 | } |
| 268 | |
| 269 | int nwz_key_event_get_keycode(struct input_event *evt) |
| 270 | { |
| 271 | return evt->code & NWZ_KEY_MASK; |
| 272 | } |
| 273 | |
| 274 | bool nwz_key_event_is_press(struct input_event *evt) |
| 275 | { |
| 276 | return evt->value == 0; |
| 277 | } |
| 278 | |
| 279 | bool nwz_key_event_get_hold_status(struct input_event *evt) |
| 280 | { |
| 281 | return !!(evt->code & NWZ_KEY_HOLD_MASK); |
| 282 | } |
| 283 | |
| 284 | static const char *nwz_keyname[NWZ_KEY_MASK + 1] = |
| 285 | { |
| 286 | [0 ... NWZ_KEY_MASK] = "unknown", |
| 287 | [NWZ_KEY_PLAY] = "PLAY", |
| 288 | [NWZ_KEY_RIGHT] = "RIGHT", |
| 289 | [NWZ_KEY_LEFT] = "LEFT", |
| 290 | [NWZ_KEY_UP] = "UP", |
| 291 | [NWZ_KEY_DOWN] = "DOWN", |
| 292 | [NWZ_KEY_ZAPPIN] = "ZAPPIN", |
| 293 | [NWZ_KEY_AD0_6] = "AD0_6", |
| 294 | [NWZ_KEY_AD0_7] = "AD0_7", |
| 295 | [NWZ_KEY_NONE] = "NONE", |
| 296 | [NWZ_KEY_VOL_DOWN] = "VOL DOWN", |
| 297 | [NWZ_KEY_VOL_UP] = "VOL UP", |
| 298 | [NWZ_KEY_BACK] = "BACK", |
| 299 | [NWZ_KEY_OPTION] = "OPTION", |
| 300 | [NWZ_KEY_BT] = "BT", |
| 301 | [NWZ_KEY_AD1_5] = "AD1_5", |
| 302 | [NWZ_KEY_AD1_6] = "AD1_6", |
| 303 | [NWZ_KEY_AD1_7] = "AD1_7", |
| 304 | }; |
| 305 | |
| 306 | const char *nwz_key_get_name(int keycode) |
| 307 | { |
| 308 | if(keycode <0 || keycode > NWZ_KEY_MASK) |
| 309 | return "invalid"; |
| 310 | else |
| 311 | return nwz_keyname[keycode]; |
| 312 | } |
Amaury Pouly | 8d24b62 | 2016-10-19 17:58:40 +0200 | [diff] [blame] | 313 | |
| 314 | int nwz_fb_open(bool lcd) |
| 315 | { |
Amaury Pouly | 0b01ca6 | 2016-10-19 18:19:57 +0200 | [diff] [blame] | 316 | return open(lcd ? NWZ_FB_LCD_DEV : NWZ_FB_TV_DEV, O_RDWR); |
Amaury Pouly | 8d24b62 | 2016-10-19 17:58:40 +0200 | [diff] [blame] | 317 | } |
| 318 | |
| 319 | void nwz_fb_close(int fd) |
| 320 | { |
| 321 | close(fd); |
| 322 | } |
| 323 | |
| 324 | int nwz_fb_get_brightness(int fd, struct nwz_fb_brightness *bl) |
| 325 | { |
| 326 | if(ioctl(fd, NWZ_FB_GET_BRIGHTNESS, bl) < 0) |
| 327 | return -1; |
| 328 | else |
| 329 | return 1; |
| 330 | } |
| 331 | |
| 332 | int nwz_fb_set_brightness(int fd, struct nwz_fb_brightness *bl) |
| 333 | { |
| 334 | if(ioctl(fd, NWZ_FB_SET_BRIGHTNESS, bl) < 0) |
| 335 | return -1; |
| 336 | else |
| 337 | return 1; |
| 338 | } |
Amaury Pouly | 0b01ca6 | 2016-10-19 18:19:57 +0200 | [diff] [blame] | 339 | |
Amaury Pouly | 0c1a961 | 2016-11-12 22:16:48 +0100 | [diff] [blame] | 340 | int nwz_fb_set_page(int fd, int page) |
| 341 | { |
| 342 | /* set page mode to no transparency and no rotation */ |
| 343 | struct nwz_fb_image_info mode_info; |
| 344 | mode_info.tc_enable = 0; |
| 345 | mode_info.t_color = 0; |
| 346 | mode_info.alpha = 0; |
| 347 | mode_info.rot = 0; |
| 348 | mode_info.page = page; |
| 349 | mode_info.update = NWZ_FB_ONLY_2D_MODE; |
| 350 | if(ioctl(fd, NWZ_FB_UPDATE, &mode_info) < 0) |
| 351 | return -2; |
| 352 | return 0; |
| 353 | } |
| 354 | |
Amaury Pouly | 5017bab | 2016-11-06 00:12:04 +0100 | [diff] [blame] | 355 | int nwz_fb_set_standard_mode(int fd) |
| 356 | { |
| 357 | /* disable timer (apparently useless with LCD) */ |
| 358 | struct nwz_fb_update_timer update_timer; |
| 359 | update_timer.timerflag = NWZ_FB_TIMER_OFF; |
| 360 | update_timer.timeout = NWZ_FB_DEFAULT_TIMEOUT; |
| 361 | if(ioctl(fd, NWZ_FB_UPDATE_TIMER, &update_timer) < 0) |
| 362 | return -1; |
Amaury Pouly | 0c1a961 | 2016-11-12 22:16:48 +0100 | [diff] [blame] | 363 | return nwz_fb_set_page(fd, 0); |
Amaury Pouly | 5017bab | 2016-11-06 00:12:04 +0100 | [diff] [blame] | 364 | } |
| 365 | |
Amaury Pouly | c95e30b | 2016-11-11 16:01:14 +0100 | [diff] [blame] | 366 | int nwz_fb_get_resolution(int fd, int *x, int *y, int *bpp) |
| 367 | { |
| 368 | struct fb_var_screeninfo vinfo; |
| 369 | if(ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) |
| 370 | return -1; |
| 371 | if(x) |
| 372 | *x = vinfo.xres; |
| 373 | if(y) |
| 374 | *y = vinfo.yres; |
| 375 | if(bpp) |
| 376 | *bpp = vinfo.bits_per_pixel; |
| 377 | return 0; |
| 378 | } |
| 379 | |
Amaury Pouly | 0c1a961 | 2016-11-12 22:16:48 +0100 | [diff] [blame] | 380 | void *nwz_fb_mmap(int fd, int offset, int size) |
| 381 | { |
| 382 | return mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)offset); |
| 383 | } |
| 384 | |
Amaury Pouly | 0b01ca6 | 2016-10-19 18:19:57 +0200 | [diff] [blame] | 385 | int nwz_adc_open(void) |
| 386 | { |
| 387 | return open(NWZ_ADC_DEV, O_RDONLY); |
| 388 | } |
| 389 | |
| 390 | void nwz_adc_close(int fd) |
| 391 | { |
| 392 | close(fd); |
| 393 | } |
| 394 | |
| 395 | static const char *nwz_adc_name[] = |
| 396 | { |
| 397 | [NWZ_ADC_VCCBAT] = "VCCBAT", |
| 398 | [NWZ_ADC_VCCVBUS] = "VCCVBUS", |
| 399 | [NWZ_ADC_ADIN3] = "ADIN3", |
| 400 | [NWZ_ADC_ADIN4] = "ADIN4", |
| 401 | [NWZ_ADC_ADIN5] = "ADIN5", |
| 402 | [NWZ_ADC_ADIN6] = "ADIN6", |
| 403 | [NWZ_ADC_ADIN7] = "ADIN7", |
| 404 | [NWZ_ADC_ADIN8] = "ADIN8", |
| 405 | }; |
| 406 | |
| 407 | const char *nwz_adc_get_name(int ch) |
| 408 | { |
| 409 | return nwz_adc_name[ch]; |
| 410 | } |
| 411 | |
| 412 | int nwz_adc_get_val(int fd, int ch) |
| 413 | { |
| 414 | unsigned char val; |
| 415 | if(ioctl(fd, NWZ_ADC_GET_VAL(ch), &val) < 0) |
| 416 | return -1; |
| 417 | else |
| 418 | return val; |
| 419 | } |
Amaury Pouly | d42b43c | 2016-10-20 18:21:00 +0200 | [diff] [blame] | 420 | |
| 421 | int nwz_ts_open(void) |
| 422 | { |
| 423 | return nwz_input_open(NWZ_TS_NAME); |
| 424 | } |
| 425 | |
| 426 | void nwz_ts_close(int fd) |
| 427 | { |
| 428 | close(fd); |
| 429 | } |
| 430 | |
| 431 | int nwz_ts_state_init(int fd, struct nwz_ts_state_t *state) |
| 432 | { |
| 433 | memset(state, 0, sizeof(struct nwz_ts_state_t)); |
| 434 | struct input_absinfo info; |
| 435 | if(ioctl(fd, EVIOCGABS(ABS_X), &info) < 0) |
| 436 | return -1; |
| 437 | state->max_x = info.maximum; |
| 438 | if(ioctl(fd, EVIOCGABS(ABS_Y), &info) < 0) |
| 439 | return -1; |
| 440 | state->max_y = info.maximum; |
| 441 | if(ioctl(fd, EVIOCGABS(ABS_PRESSURE), &info) < 0) |
| 442 | return -1; |
| 443 | state->max_pressure = info.maximum; |
| 444 | if(ioctl(fd, EVIOCGABS(ABS_TOOL_WIDTH), &info) < 0) |
| 445 | return -1; |
| 446 | state->max_tool_width = info.maximum; |
| 447 | return 1; |
| 448 | } |
| 449 | |
| 450 | int nwz_ts_state_update(struct nwz_ts_state_t *state, struct input_event *evt) |
| 451 | { |
| 452 | switch(evt->type) |
| 453 | { |
| 454 | case EV_SYN: |
| 455 | return 1; |
| 456 | case EV_REL: |
| 457 | if(evt->code == REL_RX) |
| 458 | state->flick_x = evt->value; |
| 459 | else if(evt->code == REL_RY) |
| 460 | state->flick_y = evt->value; |
| 461 | else |
| 462 | return -1; |
| 463 | state->flick = true; |
| 464 | break; |
| 465 | case EV_ABS: |
| 466 | if(evt->code == ABS_X) |
| 467 | state->x = evt->value; |
| 468 | else if(evt->code == ABS_Y) |
| 469 | state->y = evt->value; |
| 470 | else if(evt->code == ABS_PRESSURE) |
| 471 | state->pressure = evt->value; |
| 472 | else if(evt->code == ABS_TOOL_WIDTH) |
| 473 | state->tool_width = evt->value; |
| 474 | else |
| 475 | return -1; |
| 476 | break; |
| 477 | case EV_KEY: |
| 478 | if(evt->code == BTN_TOUCH) |
| 479 | state->touch = evt->value; |
| 480 | else |
| 481 | return -1; |
| 482 | break; |
| 483 | default: |
| 484 | return -1; |
| 485 | } |
| 486 | return 0; |
| 487 | } |
| 488 | |
| 489 | int nwz_ts_state_post_syn(struct nwz_ts_state_t *state) |
| 490 | { |
| 491 | state->flick = false; |
| 492 | return 1; |
| 493 | } |
| 494 | |
| 495 | int nwz_ts_read_events(int fd, struct input_event *evts, int nr_evts) |
| 496 | { |
| 497 | int ret = read(fd, evts, nr_evts * sizeof(struct input_event)); |
| 498 | if(ret < 0) |
| 499 | return -1; |
| 500 | return ret / sizeof(struct input_event); |
| 501 | } |
| 502 | |
| 503 | long nwz_wait_fds(int *fds, int nr_fds, long tmo_us) |
| 504 | { |
| 505 | fd_set rfds; |
| 506 | struct timeval tv; |
| 507 | struct timeval *tv_ptr = NULL; |
| 508 | /* watch the input device */ |
| 509 | FD_ZERO(&rfds); |
| 510 | int max_fd = 0; |
| 511 | for(int i = 0; i < nr_fds; i++) |
| 512 | { |
| 513 | FD_SET(fds[i], &rfds); |
| 514 | if(fds[i] > max_fd) |
| 515 | max_fd = fds[i]; |
| 516 | } |
| 517 | /* setup timeout */ |
| 518 | if(tmo_us >= 0) |
| 519 | { |
| 520 | tv.tv_sec = 0; |
| 521 | tv.tv_usec = tmo_us; |
| 522 | tv_ptr = &tv; |
| 523 | } |
| 524 | int ret = select(max_fd + 1, &rfds, NULL, NULL, tv_ptr); |
| 525 | if(ret <= 0) |
| 526 | return ret; |
| 527 | long bitmap = 0; |
| 528 | for(int i = 0; i < nr_fds; i++) |
| 529 | if(FD_ISSET(fds[i], &rfds)) |
| 530 | bitmap |= 1 << i; |
| 531 | return bitmap; |
| 532 | } |
| 533 | |
| 534 | int nwz_power_open(void) |
| 535 | { |
| 536 | return open(NWZ_POWER_DEV, O_RDWR); |
| 537 | } |
| 538 | |
| 539 | void nwz_power_close(int fd) |
| 540 | { |
| 541 | close(fd); |
| 542 | } |
| 543 | |
| 544 | int nwz_power_get_status(int fd) |
| 545 | { |
| 546 | int status; |
| 547 | if(ioctl(fd, NWZ_POWER_GET_STATUS, &status) < 0) |
| 548 | return -1; |
| 549 | return status; |
| 550 | } |
| 551 | |
| 552 | static int nwz_power_adval_to_mv(int adval, int ad_base) |
| 553 | { |
| 554 | if(adval == -1) |
| 555 | return -1; |
| 556 | /* the AD base corresponds to the millivolt value if adval was 255 */ |
| 557 | return (adval * ad_base) / 255; |
| 558 | } |
| 559 | |
| 560 | int nwz_power_get_vbus_adval(int fd) |
| 561 | { |
| 562 | int status; |
| 563 | if(ioctl(fd, NWZ_POWER_GET_VBUS_ADVAL, &status) < 0) |
| 564 | return -1; |
| 565 | return status; |
| 566 | } |
| 567 | |
| 568 | int nwz_power_get_vbus_voltage(int fd) |
| 569 | { |
| 570 | return nwz_power_adval_to_mv(nwz_power_get_vbus_adval(fd), NWZ_POWER_AD_BASE_VBUS); |
| 571 | } |
| 572 | |
| 573 | int nwz_power_get_vbus_limit(int fd) |
| 574 | { |
| 575 | int status; |
| 576 | if(ioctl(fd, NWZ_POWER_GET_VBUS_LIMIT, &status) < 0) |
| 577 | return -1; |
| 578 | return status; |
| 579 | } |
| 580 | |
| 581 | int nwz_power_get_charge_switch(int fd) |
| 582 | { |
| 583 | int status; |
| 584 | if(ioctl(fd, NWZ_POWER_GET_CHARGE_SWITCH, &status) < 0) |
| 585 | return -1; |
| 586 | return status; |
| 587 | } |
| 588 | |
| 589 | int nwz_power_get_charge_current(int fd) |
| 590 | { |
| 591 | int status; |
| 592 | if(ioctl(fd, NWZ_POWER_GET_CHARGE_CURRENT, &status) < 0) |
| 593 | return -1; |
| 594 | return status; |
| 595 | } |
| 596 | |
| 597 | int nwz_power_get_battery_gauge(int fd) |
| 598 | { |
| 599 | int status; |
| 600 | if(ioctl(fd, NWZ_POWER_GET_BAT_GAUGE, &status) < 0) |
| 601 | return -1; |
| 602 | return status; |
| 603 | } |
| 604 | |
| 605 | int nwz_power_get_battery_adval(int fd) |
| 606 | { |
| 607 | int status; |
| 608 | if(ioctl(fd, NWZ_POWER_GET_BAT_ADVAL, &status) < 0) |
| 609 | return -1; |
| 610 | return status; |
| 611 | } |
| 612 | |
| 613 | int nwz_power_get_battery_voltage(int fd) |
| 614 | { |
| 615 | return nwz_power_adval_to_mv(nwz_power_get_battery_adval(fd), NWZ_POWER_AD_BASE_VBAT); |
| 616 | } |
| 617 | |
| 618 | int nwz_power_get_vbat_adval(int fd) |
| 619 | { |
| 620 | int status; |
| 621 | if(ioctl(fd, NWZ_POWER_GET_VBAT_ADVAL, &status) < 0) |
| 622 | return -1; |
| 623 | return status; |
| 624 | } |
| 625 | |
| 626 | int nwz_power_get_vbat_voltage(int fd) |
| 627 | { |
| 628 | return nwz_power_adval_to_mv(nwz_power_get_vbat_adval(fd), NWZ_POWER_AD_BASE_VBAT); |
| 629 | } |
| 630 | |
| 631 | int nwz_power_get_sample_count(int fd) |
| 632 | { |
| 633 | int status; |
| 634 | if(ioctl(fd, NWZ_POWER_GET_SAMPLE_COUNT, &status) < 0) |
| 635 | return -1; |
| 636 | return status; |
| 637 | } |
| 638 | |
| 639 | int nwz_power_get_vsys_adval(int fd) |
| 640 | { |
| 641 | int status; |
| 642 | if(ioctl(fd, NWZ_POWER_GET_VSYS_ADVAL, &status) < 0) |
| 643 | return -1; |
| 644 | return status; |
| 645 | } |
| 646 | |
| 647 | int nwz_power_get_vsys_voltage(int fd) |
| 648 | { |
| 649 | return nwz_power_adval_to_mv(nwz_power_get_vsys_adval(fd), NWZ_POWER_AD_BASE_VSYS); |
| 650 | } |
| 651 | |
| 652 | int nwz_power_get_acc_charge_mode(int fd) |
| 653 | { |
| 654 | int status; |
| 655 | if(ioctl(fd, NWZ_POWER_GET_ACCESSARY_CHARGE_MODE, &status) < 0) |
| 656 | return -1; |
| 657 | return status; |
| 658 | } |
| 659 | |
| 660 | int nwz_power_is_fully_charged(int fd) |
| 661 | { |
| 662 | int status; |
| 663 | if(ioctl(fd, NWZ_POWER_IS_FULLY_CHARGED, &status) < 0) |
| 664 | return -1; |
| 665 | return status; |
| 666 | } |
Amaury Pouly | 0a22906 | 2016-10-31 17:50:16 +0100 | [diff] [blame] | 667 | |
| 668 | int nwz_pminfo_open(void) |
| 669 | { |
| 670 | return open(NWZ_PMINFO_DEV, O_RDONLY); |
| 671 | } |
| 672 | |
| 673 | void nwz_pminfo_close(int fd) |
| 674 | { |
| 675 | close(fd); |
| 676 | } |
| 677 | |
| 678 | unsigned int nwz_pminfo_get_factor(int fd) |
| 679 | { |
| 680 | unsigned int val; |
| 681 | if(ioctl(fd, NWZ_PMINFO_GET_FACTOR, &val) < 0) |
| 682 | return 0; |
| 683 | else |
| 684 | return val; |
| 685 | } |
Amaury Pouly | c95e30b | 2016-11-11 16:01:14 +0100 | [diff] [blame] | 686 | |
| 687 | static unsigned long find_model_id(void) |
| 688 | { |
| 689 | /* try with the environment variable */ |
| 690 | const char *mid = getenv("ICX_MODEL_ID"); |
| 691 | if(mid == NULL) |
| 692 | return 0; |
| 693 | char *end; |
| 694 | unsigned long v = strtoul(mid, &end, 0); |
| 695 | if(*end) |
| 696 | return 0; |
| 697 | else |
| 698 | return v; |
| 699 | } |
| 700 | |
| 701 | unsigned long nwz_get_model_id(void) |
| 702 | { |
| 703 | static unsigned long model_id = 0xffffffff; |
| 704 | if(model_id == 0xffffffff) |
| 705 | model_id = find_model_id(); |
| 706 | return model_id; |
| 707 | } |
| 708 | |
| 709 | const char *nwz_get_model_name() |
| 710 | { |
| 711 | for(int i = 0; i < NWZ_MODEL_COUNT; i++) |
| 712 | if(nwz_model[i].mid == nwz_get_model_id()) |
| 713 | return nwz_model[i].name; |
| 714 | return NULL; |
| 715 | } |
| 716 | |
| 717 | static int find_series(void) |
| 718 | { |
| 719 | for(int i = 0; i < NWZ_SERIES_COUNT; i++) |
| 720 | for(int j = 0; j < nwz_series[i].mid_count; j++) |
| 721 | if(nwz_series[i].mid[j] == nwz_get_model_id()) |
| 722 | return i; |
| 723 | return -1; |
| 724 | } |
| 725 | |
| 726 | int nwz_get_series(void) |
| 727 | { |
| 728 | static int series = -2; |
| 729 | if(series == -2) |
| 730 | series = find_series(); |
| 731 | return series; |
| 732 | } |
| 733 | |
| 734 | static nwz_nvp_index_t *get_nvp_index(void) |
| 735 | { |
| 736 | static nwz_nvp_index_t *index = 0; |
| 737 | if(index == 0) |
| 738 | { |
| 739 | int series = nwz_get_series(); |
| 740 | index = series < 0 ? 0 : nwz_series[series].nvp_index; |
| 741 | } |
| 742 | return index; |
| 743 | } |
| 744 | |
| 745 | int nwz_nvp_read(enum nwz_nvp_node_t node, void *data) |
| 746 | { |
| 747 | int size = nwz_nvp[node].size; |
| 748 | if(data == 0) |
| 749 | return size; |
| 750 | nwz_nvp_index_t *index = get_nvp_index(); |
| 751 | if(index == 0 || (*index)[node] == NWZ_NVP_INVALID) |
| 752 | return -1; |
| 753 | char nvp_path[32]; |
| 754 | snprintf(nvp_path, sizeof(nvp_path), "/dev/icx_nvp/%03d", (*index)[node]); |
| 755 | int fd = open(nvp_path, O_RDONLY); |
| 756 | if(fd < 0) |
| 757 | return -1; |
| 758 | int cnt = read(fd, data, size); |
| 759 | close(fd); |
| 760 | return cnt == size ? size : -1; |
| 761 | } |
| 762 | |
| 763 | int nwz_nvp_write(enum nwz_nvp_node_t node, void *data) |
| 764 | { |
| 765 | int size = nwz_nvp[node].size; |
| 766 | nwz_nvp_index_t *index = get_nvp_index(); |
| 767 | if(index == 0 || (*index)[node] == NWZ_NVP_INVALID) |
| 768 | return -1; |
| 769 | char nvp_path[32]; |
| 770 | snprintf(nvp_path, sizeof(nvp_path), "/dev/icx_nvp/%03d", (*index)[node]); |
| 771 | int fd = open(nvp_path, O_WRONLY); |
| 772 | if(fd < 0) |
| 773 | return -1; |
| 774 | int cnt = write(fd, data, size); |
| 775 | close(fd); |
| 776 | return cnt == size ? 0 : -1; |
| 777 | } |