1 /* 2 * Author: Thomas Ingleby <thomas.c.ingleby (at) intel.com> 3 * Author: Brendan Le Foll <brendan.le.foll (at) intel.com> 4 * Copyright (c) 2014, 2015 Intel Corporation. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining 7 * a copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sublicense, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be 15 * included in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 #include "gpio.h" 26 #include "mraa_internal.h" 27 28 #include <stdlib.h> 29 #include <fcntl.h> 30 #include <string.h> 31 #include <unistd.h> 32 #include <poll.h> 33 #include <pthread.h> 34 #include <signal.h> 35 #include <sys/stat.h> 36 #include <sys/mman.h> 37 38 #define SYSFS_CLASS_GPIO "/sys/class/gpio" 39 #define MAX_SIZE 64 40 #define POLL_TIMEOUT 41 42 static mraa_result_t 43 mraa_gpio_get_valfp(mraa_gpio_context dev) 44 { 45 char bu[MAX_SIZE]; 46 sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin); 47 dev->value_fp = open(bu, O_RDWR); 48 if (dev->value_fp == -1) { 49 return MRAA_ERROR_INVALID_RESOURCE; 50 } 51 52 return MRAA_SUCCESS; 53 } 54 55 static mraa_gpio_context 56 mraa_gpio_init_internal(mraa_adv_func_t* func_table, int pin) 57 { 58 if (pin < 0) 59 return NULL; 60 61 mraa_result_t status = MRAA_SUCCESS; 62 char bu[MAX_SIZE]; 63 int length; 64 65 mraa_gpio_context dev = (mraa_gpio_context) calloc(1, sizeof(struct _gpio)); 66 if (dev == NULL) { 67 syslog(LOG_CRIT, "gpio: Failed to allocate memory for context"); 68 return NULL; 69 } 70 71 dev->advance_func = func_table; 72 dev->pin = pin; 73 74 if (IS_FUNC_DEFINED(dev, gpio_init_internal_replace)) { 75 status = dev->advance_func->gpio_init_internal_replace(dev, pin); 76 if (status == MRAA_SUCCESS) 77 return dev; 78 else 79 goto init_internal_cleanup; 80 } 81 82 if (IS_FUNC_DEFINED(dev, gpio_init_pre)) { 83 status = dev->advance_func->gpio_init_pre(pin); 84 if (status != MRAA_SUCCESS) 85 goto init_internal_cleanup; 86 } 87 88 dev->value_fp = -1; 89 dev->isr_value_fp = -1; 90 #ifndef HAVE_PTHREAD_CANCEL 91 dev->isr_control_pipe[0] = dev->isr_control_pipe[1] = -1; 92 #endif 93 dev->isr_thread_terminating = 0; 94 dev->phy_pin = -1; 95 96 // then check to make sure the pin is exported. 97 char directory[MAX_SIZE]; 98 snprintf(directory, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/", dev->pin); 99 struct stat dir; 100 if (stat(directory, &dir) == 0 && S_ISDIR(dir.st_mode)) { 101 dev->owner = 0; // Not Owner 102 } else { 103 int export = open(SYSFS_CLASS_GPIO "/export", O_WRONLY); 104 if (export == -1) { 105 syslog(LOG_ERR, "gpio: Failed to open export for writing"); 106 status = MRAA_ERROR_NO_RESOURCES; 107 goto init_internal_cleanup; 108 } 109 length = snprintf(bu, sizeof(bu), "%d", dev->pin); 110 if (write(export, bu, length * sizeof(char)) == -1) { 111 syslog(LOG_ERR, "gpio: Failed to write %d to export", dev->pin); 112 close(export); 113 status = MRAA_ERROR_NO_RESOURCES; 114 goto init_internal_cleanup; 115 } 116 dev->owner = 1; 117 close(export); 118 } 119 120 init_internal_cleanup: 121 if (status != MRAA_SUCCESS) { 122 if (dev != NULL) 123 free(dev); 124 return NULL; 125 } 126 return dev; 127 } 128 129 mraa_gpio_context 130 mraa_gpio_init(int pin) 131 { 132 mraa_board_t* board = plat; 133 if (board == NULL) { 134 syslog(LOG_ERR, "gpio: platform not initialised"); 135 return NULL; 136 } 137 138 if (mraa_is_sub_platform_id(pin)) { 139 syslog(LOG_NOTICE, "gpio: Using sub platform"); 140 board = board->sub_platform; 141 if (board == NULL) { 142 syslog(LOG_ERR, "gpio: Sub platform Not Initialised"); 143 return NULL; 144 } 145 pin = mraa_get_sub_platform_index(pin); 146 } 147 148 if (pin < 0 || pin > board->phy_pin_count) { 149 syslog(LOG_ERR, "gpio: pin %i beyond platform definition", pin); 150 return NULL; 151 } 152 if (board->pins[pin].capabilites.gpio != 1) { 153 syslog(LOG_ERR, "gpio: pin %i not capable of gpio", pin); 154 return NULL; 155 } 156 if (board->pins[pin].gpio.mux_total > 0) { 157 if (mraa_setup_mux_mapped(board->pins[pin].gpio) != MRAA_SUCCESS) { 158 syslog(LOG_ERR, "gpio: unable to setup muxes"); 159 return NULL; 160 } 161 } 162 163 mraa_gpio_context r = mraa_gpio_init_internal(board->adv_func, board->pins[pin].gpio.pinmap); 164 if (r == NULL) { 165 syslog(LOG_CRIT, "gpio: mraa_gpio_init_raw(%d) returned error", pin); 166 return NULL; 167 } 168 if (r->phy_pin == -1) 169 r->phy_pin = pin; 170 171 if (IS_FUNC_DEFINED(r, gpio_init_post)) { 172 mraa_result_t ret = r->advance_func->gpio_init_post(r); 173 if (ret != MRAA_SUCCESS) { 174 free(r); 175 return NULL; 176 } 177 } 178 return r; 179 } 180 181 mraa_gpio_context 182 mraa_gpio_init_raw(int pin) 183 { 184 return mraa_gpio_init_internal(plat == NULL ? NULL : plat->adv_func , pin); 185 } 186 187 188 static mraa_result_t 189 mraa_gpio_wait_interrupt(int fd 190 #ifndef HAVE_PTHREAD_CANCEL 191 , int control_fd 192 #endif 193 ) 194 { 195 unsigned char c; 196 #ifdef HAVE_PTHREAD_CANCEL 197 struct pollfd pfd[1]; 198 #else 199 struct pollfd pfd[2]; 200 201 if (control_fd < 0) { 202 return MRAA_ERROR_INVALID_RESOURCE; 203 } 204 #endif 205 206 if (fd < 0) { 207 return MRAA_ERROR_INVALID_RESOURCE; 208 } 209 210 // setup poll on POLLPRI 211 pfd[0].fd = fd; 212 pfd[0].events = POLLPRI; 213 214 // do an initial read to clear interrupt 215 lseek(fd, 0, SEEK_SET); 216 read(fd, &c, 1); 217 218 #ifdef HAVE_PTHREAD_CANCEL 219 // Wait for it forever or until pthread_cancel 220 // poll is a cancelable point like sleep() 221 int x = poll(pfd, 1, -1); 222 #else 223 // setup poll on the controling fd 224 pfd[1].fd = control_fd; 225 pfd[1].events = 0; // POLLHUP, POLLERR, and POLLNVAL 226 227 // Wait for it forever or until control fd is closed 228 int x = poll(pfd, 2, -1); 229 #endif 230 231 // do a final read to clear interrupt 232 read(fd, &c, 1); 233 234 return MRAA_SUCCESS; 235 } 236 237 #if defined(SWIGJAVA) || defined(JAVACALLBACK) 238 pthread_key_t env_key; 239 240 extern JavaVM *globVM; 241 static pthread_once_t env_key_init = PTHREAD_ONCE_INIT; 242 243 jmethodID runGlobal; 244 245 static void make_env_key(void) 246 { 247 248 JNIEnv *jenv; 249 (*globVM)->GetEnv(globVM, (void **)&jenv, JNI_VERSION_1_8); 250 251 jclass rcls = (*jenv)->FindClass(jenv, "java/lang/Runnable"); 252 jmethodID runm = (*jenv)->GetMethodID(jenv, rcls, "run", "()V"); 253 254 runGlobal = (jmethodID)(*jenv)->NewGlobalRef(jenv, (jobject)runm); 255 256 pthread_key_create(&env_key, NULL); 257 } 258 259 void mraa_java_isr_callback(void* data) 260 { 261 JNIEnv *jenv = (JNIEnv *) pthread_getspecific(env_key); 262 (*jenv)->CallVoidMethod(jenv, (jobject)data, runGlobal); 263 } 264 265 #endif 266 267 static void* 268 mraa_gpio_interrupt_handler(void* arg) 269 { 270 mraa_gpio_context dev = (mraa_gpio_context) arg; 271 if (IS_FUNC_DEFINED(dev, gpio_interrupt_handler_replace)) 272 return dev->advance_func->gpio_interrupt_handler_replace(dev); 273 274 mraa_result_t ret; 275 276 // open gpio value with open(3) 277 char bu[MAX_SIZE]; 278 sprintf(bu, SYSFS_CLASS_GPIO "/gpio%d/value", dev->pin); 279 int fp = open(bu, O_RDONLY); 280 if (fp < 0) { 281 syslog(LOG_ERR, "gpio: failed to open gpio%d/value", dev->pin); 282 return NULL; 283 } 284 285 #ifndef HAVE_PTHREAD_CANCEL 286 if (pipe(dev->isr_control_pipe)) { 287 syslog(LOG_ERR, "gpio: failed to create isr control pipe"); 288 close(fp); 289 return NULL; 290 } 291 #endif 292 293 dev->isr_value_fp = fp; 294 295 #if defined(SWIGJAVA) || defined(JAVACALLBACK) 296 JNIEnv *jenv; 297 if(dev->isr == mraa_java_isr_callback) { 298 jint err = (*globVM)->AttachCurrentThreadAsDaemon(globVM, (void **)&jenv, NULL); 299 300 if (err != JNI_OK) { 301 close(dev->isr_value_fp); 302 dev->isr_value_fp = -1; 303 return NULL; 304 } 305 306 pthread_once(&env_key_init, make_env_key); 307 pthread_setspecific(env_key, jenv); 308 } 309 #endif 310 311 for (;;) { 312 ret = mraa_gpio_wait_interrupt(dev->isr_value_fp 313 #ifndef HAVE_PTHREAD_CANCEL 314 , dev->isr_control_pipe[0] 315 #endif 316 ); 317 if (ret == MRAA_SUCCESS && !dev->isr_thread_terminating) { 318 #ifdef HAVE_PTHREAD_CANCEL 319 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 320 #endif 321 #ifdef SWIGPYTHON 322 // In order to call a python object (all python functions are objects) we 323 // need to aquire the GIL (Global Interpreter Lock). This may not always be 324 // necessary but especially if doing IO (like print()) python will segfault 325 // if we do not hold a lock on the GIL 326 PyGILState_STATE gilstate = PyGILState_Ensure(); 327 PyObject* arglist; 328 PyObject* ret; 329 arglist = Py_BuildValue("(O)", dev->isr_args); 330 if (arglist == NULL) { 331 syslog(LOG_ERR, "gpio: Py_BuildValue NULL"); 332 } else { 333 ret = PyEval_CallObject((PyObject*) dev->isr, arglist); 334 if (ret == NULL) { 335 syslog(LOG_ERR, "gpio: PyEval_CallObject failed"); 336 PyObject *pvalue, *ptype, *ptraceback; 337 PyObject *pvalue_pystr, *ptype_pystr, *ptraceback_pystr; 338 char *pvalue_cstr, *ptype_cstr, *ptraceback_cstr; 339 PyErr_Fetch(&pvalue, &ptype, &ptraceback); 340 pvalue_pystr = PyObject_Str(pvalue); 341 ptype_pystr = PyObject_Str(ptype); 342 ptraceback_pystr = PyObject_Str(ptraceback); 343 // Python2 344 #if PY_VERSION_HEX < 0x03000000 345 pvalue_cstr = PyString_AsString(pvalue_pystr); 346 ptype_cstr = PyString_AsString(ptype_pystr); 347 ptraceback_cstr = PyString_AsString(ptraceback_pystr); 348 // Python 3 and up 349 #elif PY_VERSION_HEX >= 0x03000000 350 // In Python 3 we need one extra conversion 351 PyObject *pvalue_ustr, *ptype_ustr, *ptraceback_ustr; 352 pvalue_ustr = PyUnicode_AsUTF8String(pvalue_pystr); 353 pvalue_cstr = PyBytes_AsString(pvalue_ustr); 354 ptype_ustr = PyUnicode_AsUTF8String(ptype_pystr); 355 ptype_cstr = PyBytes_AsString(ptype_ustr); 356 ptraceback_ustr = PyUnicode_AsUTF8String(ptraceback_pystr); 357 ptraceback_cstr = PyBytes_AsString(ptraceback_ustr); 358 #endif // PY_VERSION_HEX 359 syslog(LOG_ERR, "gpio: the error was %s:%s:%s", 360 pvalue_cstr, 361 ptype_cstr, 362 ptraceback_cstr 363 ); 364 Py_XDECREF(pvalue); 365 Py_XDECREF(ptype); 366 Py_XDECREF(ptraceback); 367 Py_XDECREF(pvalue_pystr); 368 Py_XDECREF(ptype_pystr); 369 Py_XDECREF(ptraceback_pystr); 370 // Python 3 and up 371 #if PY_VERSION_HEX >= 0x03000000 372 Py_XDECREF(pvalue_ustr); 373 Py_XDECREF(ptype_ustr); 374 Py_XDECREF(ptraceback_ustr); 375 #endif // PY_VERSION_HEX 376 } else { 377 Py_DECREF(ret); 378 } 379 Py_DECREF(arglist); 380 } 381 382 PyGILState_Release(gilstate); 383 #else 384 dev->isr(dev->isr_args); 385 #endif 386 #ifdef HAVE_PTHREAD_CANCEL 387 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 388 #endif 389 } else { 390 // we must have got an error code or exit request so die nicely 391 #ifdef HAVE_PTHREAD_CANCEL 392 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 393 #endif 394 close(dev->isr_value_fp); 395 dev->isr_value_fp = -1; 396 #if defined(SWIGJAVA) || defined(JAVACALLBACK) 397 398 if(dev->isr == mraa_java_isr_callback) { 399 (*jenv)->DeleteGlobalRef(jenv, (jobject)dev->isr_args); 400 (*globVM)->DetachCurrentThread(globVM); 401 } 402 #endif 403 return NULL; 404 } 405 } 406 } 407 408 mraa_result_t 409 mraa_gpio_edge_mode(mraa_gpio_context dev, mraa_gpio_edge_t mode) 410 { 411 if (IS_FUNC_DEFINED(dev, gpio_edge_mode_replace)) 412 return dev->advance_func->gpio_edge_mode_replace(dev, mode); 413 414 if (dev->value_fp != -1) { 415 close(dev->value_fp); 416 dev->value_fp = -1; 417 } 418 419 char filepath[MAX_SIZE]; 420 snprintf(filepath, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/edge", dev->pin); 421 422 int edge = open(filepath, O_RDWR); 423 if (edge == -1) { 424 syslog(LOG_ERR, "gpio: Failed to open edge for writing"); 425 return MRAA_ERROR_INVALID_RESOURCE; 426 } 427 428 char bu[MAX_SIZE]; 429 int length; 430 switch (mode) { 431 case MRAA_GPIO_EDGE_NONE: 432 length = snprintf(bu, sizeof(bu), "none"); 433 break; 434 case MRAA_GPIO_EDGE_BOTH: 435 length = snprintf(bu, sizeof(bu), "both"); 436 break; 437 case MRAA_GPIO_EDGE_RISING: 438 length = snprintf(bu, sizeof(bu), "rising"); 439 break; 440 case MRAA_GPIO_EDGE_FALLING: 441 length = snprintf(bu, sizeof(bu), "falling"); 442 break; 443 default: 444 close(edge); 445 return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; 446 } 447 if (write(edge, bu, length * sizeof(char)) == -1) { 448 syslog(LOG_ERR, "gpio: Failed to write to edge"); 449 close(edge); 450 return MRAA_ERROR_INVALID_RESOURCE; 451 } 452 453 close(edge); 454 return MRAA_SUCCESS; 455 } 456 457 mraa_result_t 458 mraa_gpio_isr(mraa_gpio_context dev, mraa_gpio_edge_t mode, void (*fptr)(void*), void* args) 459 { 460 // we only allow one isr per mraa_gpio_context 461 if (dev->thread_id != 0) { 462 return MRAA_ERROR_NO_RESOURCES; 463 } 464 465 if (MRAA_SUCCESS != mraa_gpio_edge_mode(dev, mode)) { 466 return MRAA_ERROR_UNSPECIFIED; 467 } 468 469 dev->isr = fptr; 470 #if defined(SWIGJAVA) || defined(JAVACALLBACK) 471 JNIEnv *jenv; 472 /* Most UPM sensors use the C API, the global ref must be created here. */ 473 /* The reason for checking the callback function is internal callbacks. */ 474 if (fptr == mraa_java_isr_callback) { 475 (*globVM)->GetEnv(globVM, (void **)&jenv, JNI_VERSION_1_8); 476 jobject grunnable = (*jenv)->NewGlobalRef(jenv, (jobject) args); 477 args = (void *) grunnable; 478 } 479 #endif 480 dev->isr_args = args; 481 pthread_create(&dev->thread_id, NULL, mraa_gpio_interrupt_handler, (void*) dev); 482 483 return MRAA_SUCCESS; 484 } 485 486 mraa_result_t 487 mraa_gpio_isr_exit(mraa_gpio_context dev) 488 { 489 mraa_result_t ret = MRAA_SUCCESS; 490 491 // wasting our time, there is no isr to exit from 492 if (dev->thread_id == 0 && dev->isr_value_fp == -1) { 493 return ret; 494 } 495 // mark the beginning of the thread termination process for interested parties 496 dev->isr_thread_terminating = 1; 497 498 // stop isr being useful 499 ret = mraa_gpio_edge_mode(dev, MRAA_GPIO_EDGE_NONE); 500 501 if ((dev->thread_id != 0)) { 502 #ifdef HAVE_PTHREAD_CANCEL 503 if ((pthread_cancel(dev->thread_id) != 0) || (pthread_join(dev->thread_id, NULL) != 0)) { 504 ret = MRAA_ERROR_INVALID_HANDLE; 505 } 506 #else 507 close(dev->isr_control_pipe[1]); 508 if (pthread_join(dev->thread_id, NULL) != 0) 509 ret = MRAA_ERROR_INVALID_HANDLE; 510 511 close(dev->isr_control_pipe[0]); 512 dev->isr_control_pipe[0] = dev->isr_control_pipe[1] = -1; 513 #endif 514 } 515 516 // close the filehandle in case it's still open 517 if (dev->isr_value_fp != -1) { 518 if (close(dev->isr_value_fp) != 0) { 519 ret = MRAA_ERROR_INVALID_PARAMETER; 520 } 521 } 522 523 // assume our thread will exit either way we just lost it's handle 524 dev->thread_id = 0; 525 dev->isr_value_fp = -1; 526 dev->isr_thread_terminating = 0; 527 return ret; 528 } 529 530 mraa_result_t 531 mraa_gpio_mode(mraa_gpio_context dev, mraa_gpio_mode_t mode) 532 { 533 if (IS_FUNC_DEFINED(dev, gpio_mode_replace)) 534 return dev->advance_func->gpio_mode_replace(dev, mode); 535 536 if (IS_FUNC_DEFINED(dev, gpio_mode_pre)) { 537 mraa_result_t pre_ret = (dev->advance_func->gpio_mode_pre(dev, mode)); 538 if (pre_ret != MRAA_SUCCESS) 539 return pre_ret; 540 } 541 542 if (dev->value_fp != -1) { 543 close(dev->value_fp); 544 dev->value_fp = -1; 545 } 546 547 char filepath[MAX_SIZE]; 548 snprintf(filepath, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/drive", dev->pin); 549 550 int drive = open(filepath, O_WRONLY); 551 if (drive == -1) { 552 syslog(LOG_ERR, "gpio: Failed to open drive for writing"); 553 return MRAA_ERROR_INVALID_RESOURCE; 554 } 555 556 char bu[MAX_SIZE]; 557 int length; 558 switch (mode) { 559 case MRAA_GPIO_STRONG: 560 length = snprintf(bu, sizeof(bu), "strong"); 561 break; 562 case MRAA_GPIO_PULLUP: 563 length = snprintf(bu, sizeof(bu), "pullup"); 564 break; 565 case MRAA_GPIO_PULLDOWN: 566 length = snprintf(bu, sizeof(bu), "pulldown"); 567 break; 568 case MRAA_GPIO_HIZ: 569 length = snprintf(bu, sizeof(bu), "hiz"); 570 break; 571 default: 572 close(drive); 573 return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; 574 } 575 if (write(drive, bu, length * sizeof(char)) == -1) { 576 syslog(LOG_ERR, "gpio: Failed to write to drive mode"); 577 close(drive); 578 return MRAA_ERROR_INVALID_RESOURCE; 579 } 580 581 close(drive); 582 if (IS_FUNC_DEFINED(dev, gpio_mode_post)) 583 return dev->advance_func->gpio_mode_post(dev, mode); 584 return MRAA_SUCCESS; 585 } 586 587 mraa_result_t 588 mraa_gpio_dir(mraa_gpio_context dev, mraa_gpio_dir_t dir) 589 { 590 if (IS_FUNC_DEFINED(dev, gpio_dir_replace)) { 591 return dev->advance_func->gpio_dir_replace(dev, dir); 592 } 593 594 if (IS_FUNC_DEFINED(dev, gpio_dir_pre)) { 595 mraa_result_t pre_ret = (dev->advance_func->gpio_dir_pre(dev, dir)); 596 if (pre_ret != MRAA_SUCCESS) { 597 return pre_ret; 598 } 599 } 600 601 if (dev == NULL) { 602 return MRAA_ERROR_INVALID_HANDLE; 603 } 604 if (dev->value_fp != -1) { 605 close(dev->value_fp); 606 dev->value_fp = -1; 607 } 608 char filepath[MAX_SIZE]; 609 snprintf(filepath, MAX_SIZE, SYSFS_CLASS_GPIO "/gpio%d/direction", dev->pin); 610 611 int direction = open(filepath, O_RDWR); 612 613 if (direction == -1) { 614 // Direction Failed to Open. If HIGH or LOW was passed will try and set 615 // If not fail as usual. 616 switch (dir) { 617 case MRAA_GPIO_OUT_HIGH: 618 return mraa_gpio_write(dev, 1); 619 case MRAA_GPIO_OUT_LOW: 620 return mraa_gpio_write(dev, 0); 621 default: 622 return MRAA_ERROR_INVALID_RESOURCE; 623 } 624 } 625 626 char bu[MAX_SIZE]; 627 int length; 628 switch (dir) { 629 case MRAA_GPIO_OUT: 630 length = snprintf(bu, sizeof(bu), "out"); 631 break; 632 case MRAA_GPIO_IN: 633 length = snprintf(bu, sizeof(bu), "in"); 634 break; 635 case MRAA_GPIO_OUT_HIGH: 636 length = snprintf(bu, sizeof(bu), "high"); 637 break; 638 case MRAA_GPIO_OUT_LOW: 639 length = snprintf(bu, sizeof(bu), "low"); 640 break; 641 default: 642 close(direction); 643 return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; 644 } 645 646 if (write(direction, bu, length * sizeof(char)) == -1) { 647 close(direction); 648 return MRAA_ERROR_INVALID_RESOURCE; 649 } 650 651 close(direction); 652 if (IS_FUNC_DEFINED(dev, gpio_dir_post)) 653 return dev->advance_func->gpio_dir_post(dev, dir); 654 return MRAA_SUCCESS; 655 } 656 657 int 658 mraa_gpio_read(mraa_gpio_context dev) 659 { 660 if (dev == NULL) 661 return -1; 662 663 if (IS_FUNC_DEFINED(dev, gpio_read_replace)) 664 return dev->advance_func->gpio_read_replace(dev); 665 666 if (dev->mmap_read != NULL) 667 return dev->mmap_read(dev); 668 669 if (dev->value_fp == -1) { 670 if (mraa_gpio_get_valfp(dev) != MRAA_SUCCESS) { 671 syslog(LOG_ERR, "gpio: Failed to get value file pointer"); 672 return -1; 673 } 674 } else { 675 // if value_fp is new this is pointless 676 lseek(dev->value_fp, 0, SEEK_SET); 677 } 678 char bu[2]; 679 if (read(dev->value_fp, bu, 2 * sizeof(char)) != 2) { 680 syslog(LOG_ERR, "gpio: Failed to read a sensible value from sysfs"); 681 return -1; 682 } 683 lseek(dev->value_fp, 0, SEEK_SET); 684 685 return (int) strtol(bu, NULL, 10); 686 } 687 688 mraa_result_t 689 mraa_gpio_write(mraa_gpio_context dev, int value) 690 { 691 if (dev == NULL) 692 return MRAA_ERROR_INVALID_HANDLE; 693 694 if (dev->mmap_write != NULL) 695 return dev->mmap_write(dev, value); 696 697 if (IS_FUNC_DEFINED(dev, gpio_write_pre)) { 698 mraa_result_t pre_ret = (dev->advance_func->gpio_write_pre(dev, value)); 699 if (pre_ret != MRAA_SUCCESS) 700 return pre_ret; 701 } 702 703 if (IS_FUNC_DEFINED(dev, gpio_write_replace)) { 704 return dev->advance_func->gpio_write_replace(dev, value); 705 } 706 707 if (dev->value_fp == -1) { 708 if (mraa_gpio_get_valfp(dev) != MRAA_SUCCESS) { 709 return MRAA_ERROR_INVALID_RESOURCE; 710 } 711 } 712 713 if (lseek(dev->value_fp, 0, SEEK_SET) == -1) { 714 return MRAA_ERROR_INVALID_RESOURCE; 715 } 716 717 char bu[MAX_SIZE]; 718 int length = snprintf(bu, sizeof(bu), "%d", value); 719 if (write(dev->value_fp, bu, length * sizeof(char)) == -1) { 720 return MRAA_ERROR_INVALID_HANDLE; 721 } 722 723 if (IS_FUNC_DEFINED(dev, gpio_write_post)) 724 return dev->advance_func->gpio_write_post(dev, value); 725 return MRAA_SUCCESS; 726 } 727 728 static mraa_result_t 729 mraa_gpio_unexport_force(mraa_gpio_context dev) 730 { 731 int unexport = open(SYSFS_CLASS_GPIO "/unexport", O_WRONLY); 732 if (unexport == -1) { 733 syslog(LOG_ERR, "gpio: Failed to open unexport for writing"); 734 return MRAA_ERROR_INVALID_RESOURCE; 735 } 736 737 char bu[MAX_SIZE]; 738 int length = snprintf(bu, sizeof(bu), "%d", dev->pin); 739 if (write(unexport, bu, length * sizeof(char)) == -1) { 740 syslog(LOG_ERR, "gpio: Failed to write to unexport"); 741 close(unexport); 742 return MRAA_ERROR_INVALID_RESOURCE; 743 } 744 745 close(unexport); 746 mraa_gpio_isr_exit(dev); 747 return MRAA_SUCCESS; 748 } 749 static mraa_result_t 750 mraa_gpio_unexport(mraa_gpio_context dev) 751 { 752 if (dev->owner) { 753 return mraa_gpio_unexport_force(dev); 754 } 755 return MRAA_ERROR_INVALID_RESOURCE; 756 } 757 758 mraa_result_t 759 mraa_gpio_close(mraa_gpio_context dev) 760 { 761 mraa_result_t result = MRAA_SUCCESS; 762 763 if (IS_FUNC_DEFINED(dev, gpio_close_pre)) { 764 result = dev->advance_func->gpio_close_pre(dev); 765 } 766 767 if (dev->value_fp != -1) { 768 close(dev->value_fp); 769 } 770 mraa_gpio_unexport(dev); 771 free(dev); 772 return result; 773 } 774 775 mraa_result_t 776 mraa_gpio_owner(mraa_gpio_context dev, mraa_boolean_t own) 777 { 778 if (dev == NULL) { 779 return MRAA_ERROR_INVALID_RESOURCE; 780 } 781 syslog(LOG_DEBUG, "gpio: Set owner to %d", (int) own); 782 dev->owner = own; 783 return MRAA_SUCCESS; 784 } 785 786 mraa_result_t 787 mraa_gpio_use_mmaped(mraa_gpio_context dev, mraa_boolean_t mmap_en) 788 { 789 if (IS_FUNC_DEFINED(dev, gpio_mmap_setup)) { 790 return dev->advance_func->gpio_mmap_setup(dev, mmap_en); 791 } 792 793 syslog(LOG_ERR, "gpio: mmap not implemented on this platform"); 794 return MRAA_ERROR_FEATURE_NOT_IMPLEMENTED; 795 } 796 797 int 798 mraa_gpio_get_pin(mraa_gpio_context dev) 799 { 800 if (dev == NULL) { 801 syslog(LOG_ERR, "gpio: context is invalid"); 802 return -1; 803 } 804 return dev->phy_pin; 805 } 806 807 int 808 mraa_gpio_get_pin_raw(mraa_gpio_context dev) 809 { 810 if (dev == NULL) { 811 syslog(LOG_ERR, "gpio: context is invalid"); 812 return -1; 813 } 814 return dev->pin; 815 } 816