diff -Nru rpi.gpio-0.6.3/CHANGELOG.txt rpi.gpio-0.6.5/CHANGELOG.txt --- rpi.gpio-0.6.3/CHANGELOG.txt 2016-10-30 21:42:16.000000000 +0000 +++ rpi.gpio-0.6.5/CHANGELOG.txt 2018-11-16 10:05:26.000000000 +0000 @@ -1,8 +1,21 @@ Change Log ========== +0.6.5 +----- +- Fix exception on re-export of /sys/class/gpio/gpioNN + +0.6.4 +----- +- Event cleanup bug (issue 145) +- Raise exception for duplicate PWM objects (issue 54 - Thijs Schreijer ) +- Fix build warnings (Issue 146 - Dominik George) +- test.py runs unchanged for both python 2+3 +- Soft PWM stops running fix (Issues 94, 111, 154) +- Soft PWM segfault fix (Luke Allen pull request) + 0.6.3 -------- +----- - Fix code so it builds under PyPy (Gasper Zejn) - os.system breaks event detection - Matt Kimball (issue 127) diff -Nru rpi.gpio-0.6.3/PKG-INFO rpi.gpio-0.6.5/PKG-INFO --- rpi.gpio-0.6.3/PKG-INFO 2016-10-30 21:48:33.000000000 +0000 +++ rpi.gpio-0.6.5/PKG-INFO 2018-11-16 10:14:50.000000000 +0000 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: RPi.GPIO -Version: 0.6.3 +Version: 0.6.5 Summary: A module to control Raspberry Pi GPIO channels Home-page: http://sourceforge.net/projects/raspberry-gpio-python/ Author: Ben Croston @@ -24,8 +24,21 @@ Change Log ========== + 0.6.5 + ----- + - Fix exception on re-export of /sys/class/gpio/gpioNN + + 0.6.4 + ----- + - Event cleanup bug (issue 145) + - Raise exception for duplicate PWM objects (issue 54 - Thijs Schreijer ) + - Fix build warnings (Issue 146 - Dominik George) + - test.py runs unchanged for both python 2+3 + - Soft PWM stops running fix (Issues 94, 111, 154) + - Soft PWM segfault fix (Luke Allen pull request) + 0.6.3 - ------- + ----- - Fix code so it builds under PyPy (Gasper Zejn) - os.system breaks event detection - Matt Kimball (issue 127) diff -Nru rpi.gpio-0.6.3/RPi/GPIO/__init__.py rpi.gpio-0.6.5/RPi/GPIO/__init__.py --- rpi.gpio-0.6.3/RPi/GPIO/__init__.py 2016-10-30 21:43:19.000000000 +0000 +++ rpi.gpio-0.6.5/RPi/GPIO/__init__.py 2018-11-16 10:06:38.000000000 +0000 @@ -1,5 +1,5 @@ """ -Copyright (c) 2012-2016 Ben Croston +Copyright (c) 2012-2018 Ben Croston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -22,4 +22,4 @@ from RPi._GPIO import * -VERSION = '0.6.3' +VERSION = '0.6.5' diff -Nru rpi.gpio-0.6.3/debian/changelog rpi.gpio-0.6.5/debian/changelog --- rpi.gpio-0.6.3/debian/changelog 2017-08-04 06:57:33.000000000 +0000 +++ rpi.gpio-0.6.5/debian/changelog 2019-01-22 15:26:28.000000000 +0000 @@ -1,26 +1,25 @@ -rpi.gpio (0.6.3-1ubuntu4) artful; urgency=medium +rpi.gpio (0.6.5-1ubuntu1) disco; urgency=medium - * No change rebuild to drop Python 3.5 support. + * Added d/p/fix-revision-on-aarch64.patch to permit usage of the module + on aarch64 based distros. + * Fix filename on d/rpi.gpio-common.docs - -- Michael Hudson-Doyle Fri, 04 Aug 2017 18:57:33 +1200 + -- Dave Jones Tue, 22 Jan 2019 15:26:28 +0000 -rpi.gpio (0.6.3-1ubuntu3) artful; urgency=medium +rpi.gpio (0.6.5-1) unstable; urgency=medium - * No change rebuild to add Python 3.6 support. + * New upstream version. + * Vump Standards-Version and ocmpat level, no changes needed. - -- Michael Hudson-Doyle Fri, 12 May 2017 14:54:11 +1200 + -- Dominik George Sun, 13 Jan 2019 14:50:43 +0100 -rpi.gpio (0.6.3-1ubuntu2) artful; urgency=medium +rpi.gpio (0.6.4-1) unstable; urgency=medium - * Revert PIE changes now as ubuntu has got latest dpkg. + * Update to Salsa and update my maintainer address. + * New upstream version. + + Remove patches as they were applied upstream. - -- Bhavani Shankar Mon, 24 Apr 2017 08:15:15 +0530 - -rpi.gpio (0.6.3-1ubuntu1) zesty; urgency=medium - - * Disable PIE during build so that linkage happens in the correct manner. - - -- Bhavani Shankar Thu, 30 Mar 2017 10:12:40 +0530 + -- Dominik George Fri, 26 Oct 2018 19:46:05 +0200 rpi.gpio (0.6.3-1) unstable; urgency=low diff -Nru rpi.gpio-0.6.3/debian/compat rpi.gpio-0.6.5/debian/compat --- rpi.gpio-0.6.3/debian/compat 2017-01-31 18:50:14.000000000 +0000 +++ rpi.gpio-0.6.5/debian/compat 2019-01-13 13:50:43.000000000 +0000 @@ -1 +1 @@ -10 +11 diff -Nru rpi.gpio-0.6.3/debian/control rpi.gpio-0.6.5/debian/control --- rpi.gpio-0.6.3/debian/control 2017-03-30 04:43:38.000000000 +0000 +++ rpi.gpio-0.6.5/debian/control 2019-01-22 15:26:28.000000000 +0000 @@ -2,11 +2,11 @@ Maintainer: Ubuntu Developers XSBC-Original-Maintainer: Debian Raspberry Pi Maintainers Uploaders: - Dominik George , + Dominik George , Section: python Priority: optional Build-Depends: - debhelper (>= 10), + debhelper (>= 11~), dh-python, python-all (>= 2.6.6-3), python-all-dev, @@ -14,13 +14,14 @@ python3-all, python3-all-dev, python3-setuptools, -Standards-Version: 3.9.8 +Standards-Version: 4.3.1 Homepage: http://sourceforge.net/projects/raspberry-gpio-python/ -Vcs-Git: https://anonscm.debian.org/git/pkg-raspi/rpi.gpio.git -Vcs-Browser: https://anonscm.debian.org/git/pkg-raspi/rpi.gpio.git +Vcs-Git: https://salsa.debian.org/raspi-team/rpi.gpio.git +Vcs-Browser: https://salsa.debian.org/raspi-team/rpi.gpio Package: rpi.gpio-common Architecture: arm64 armel armhf +Multi-Arch: same Depends: ${misc:Depends}, Description: Module to control Raspberry Pi GPIO channels (common files) diff -Nru rpi.gpio-0.6.3/debian/patches/c-is-not-python.patch rpi.gpio-0.6.5/debian/patches/c-is-not-python.patch --- rpi.gpio-0.6.3/debian/patches/c-is-not-python.patch 2017-01-31 20:27:00.000000000 +0000 +++ rpi.gpio-0.6.5/debian/patches/c-is-not-python.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -From: mirabilos -Subject: Fix missing curly braces for blocks in C -Forwarded: https://sourceforge.net/p/raspberry-gpio-python/tickets/145/ ---- a/source/event_gpio.c -+++ b/source/event_gpio.c -@@ -414,19 +414,23 @@ void event_cleanup(unsigned int gpio) - struct gpios *temp = NULL; - - while (g != NULL) { -- if ((gpio == -666) || (g->gpio == gpio)) -+ if ((gpio == -666) || (g->gpio == gpio)) { - temp = g->next; - remove_edge_detect(g->gpio); - g = temp; -+ } - } -- if (gpio_list == NULL) -- if (epfd_blocking != -1) -+ if (gpio_list == NULL) { -+ if (epfd_blocking != -1) { - close(epfd_blocking); - epfd_blocking = -1; -- if (epfd_thread != -1) -+ } -+ if (epfd_thread != -1) { - close(epfd_thread); - epfd_thread = -1; -+ } - thread_running = 0; -+ } - } - - void event_cleanup_all(void) diff -Nru rpi.gpio-0.6.3/debian/patches/fix-revision-on-aarch64.patch rpi.gpio-0.6.5/debian/patches/fix-revision-on-aarch64.patch --- rpi.gpio-0.6.3/debian/patches/fix-revision-on-aarch64.patch 1970-01-01 00:00:00.000000000 +0000 +++ rpi.gpio-0.6.5/debian/patches/fix-revision-on-aarch64.patch 2019-01-22 15:25:39.000000000 +0000 @@ -0,0 +1,67 @@ +Author: Dave Jones +Forwarded: https://sourceforge.net/p/raspberry-gpio-python/tickets/161/ +Bug: https://sourceforge.net/p/raspberry-gpio-python/tickets/161/ +Description: Fix Pi revision detection on aarch64 distros + The get_rpi_info function determines the characteristics of the host Pi. + However, it currently depends on querying the Pi's revision from /proc/cpuinfo + and this information only appears to be included on armhf architectures. On + recent kernels (both armhf and aarch64) the Pi's revision code can be queried + from /proc/device-tree/system/linux,revision. This patch uses this path in + preference to /proc/cpuinfo but will still fall back to the latter to preserve + compatibility with older distros. + +--- a/source/cpuinfo.c ++++ b/source/cpuinfo.c +@@ -21,8 +21,10 @@ + */ + + #include ++#include + #include + #include ++#include + #include "cpuinfo.h" + + int get_rpi_info(rpi_info *info) +@@ -35,19 +37,30 @@ + int found = 0; + int len; + +- if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) +- return -1; +- while(!feof(fp) && fgets(buffer, sizeof(buffer), fp)) { +- sscanf(buffer, "Hardware : %s", hardware); +- if (strcmp(hardware, "BCM2708") == 0 || +- strcmp(hardware, "BCM2709") == 0 || +- strcmp(hardware, "BCM2835") == 0 || +- strcmp(hardware, "BCM2836") == 0 || +- strcmp(hardware, "BCM2837") == 0 ) { +- found = 1; ++ if ((fp = fopen("/proc/device-tree/system/linux,revision", "r"))) { ++ uint32_t n; ++ if (fread(&n, sizeof(n), 1, fp) != 1) { ++ fclose(fp); ++ return -1; ++ } ++ sprintf(revision, "%x", ntohl(n)); ++ found = 1; ++ } ++ else if ((fp = fopen("/proc/cpuinfo", "r"))) { ++ while(!feof(fp) && fgets(buffer, sizeof(buffer), fp)) { ++ sscanf(buffer, "Hardware : %s", hardware); ++ if (strcmp(hardware, "BCM2708") == 0 || ++ strcmp(hardware, "BCM2709") == 0 || ++ strcmp(hardware, "BCM2835") == 0 || ++ strcmp(hardware, "BCM2836") == 0 || ++ strcmp(hardware, "BCM2837") == 0 ) { ++ found = 1; ++ } ++ sscanf(buffer, "Revision : %s", revision); + } +- sscanf(buffer, "Revision : %s", revision); + } ++ else ++ return -1; + fclose(fp); + + if (!found) diff -Nru rpi.gpio-0.6.3/debian/patches/series rpi.gpio-0.6.5/debian/patches/series --- rpi.gpio-0.6.3/debian/patches/series 2017-01-31 20:27:00.000000000 +0000 +++ rpi.gpio-0.6.5/debian/patches/series 2019-01-22 15:16:13.000000000 +0000 @@ -1,3 +1,2 @@ spelling.patch -c-is-not-python.patch -warning-fixes.patch +fix-revision-on-aarch64.patch diff -Nru rpi.gpio-0.6.3/debian/patches/warning-fixes.patch rpi.gpio-0.6.5/debian/patches/warning-fixes.patch --- rpi.gpio-0.6.3/debian/patches/warning-fixes.patch 2017-01-31 20:27:00.000000000 +0000 +++ rpi.gpio-0.6.5/debian/patches/warning-fixes.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -From: mirabilos -Subject: Fix several compiler warnings that point out potential bugs -Forwarded: https://sourceforge.net/p/raspberry-gpio-python/tickets/146/ ---- a/source/c_gpio.c -+++ b/source/c_gpio.c -@@ -61,7 +61,7 @@ int setup(void) - { - int mem_fd; - uint8_t *gpio_mem; -- uint32_t peri_base; -+ uint32_t peri_base = 0; - uint32_t gpio_base; - unsigned char buf[4]; - FILE *fp; -@@ -95,8 +95,7 @@ int setup(void) - if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) - return SETUP_CPUINFO_FAIL; - -- while(!feof(fp) && !found) { -- fgets(buffer, sizeof(buffer), fp); -+ while(!feof(fp) && !found && fgets(buffer, sizeof(buffer), fp)) { - sscanf(buffer, "Hardware : %s", hardware); - if (strcmp(hardware, "BCM2708") == 0 || strcmp(hardware, "BCM2835") == 0) { - // pi 1 hardware -@@ -113,6 +112,8 @@ int setup(void) - return SETUP_NOT_RPI_FAIL; - } - -+ if (!peri_base) -+ return SETUP_NOT_RPI_FAIL; - gpio_base = peri_base + GPIO_BASE_OFFSET; - - // mmap the GPIO memory registers ---- a/source/cpuinfo.c -+++ b/source/cpuinfo.c -@@ -37,8 +37,7 @@ int get_rpi_info(rpi_info *info) - - if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) - return -1; -- while(!feof(fp)) { -- fgets(buffer, sizeof(buffer), fp); -+ while(!feof(fp) && fgets(buffer, sizeof(buffer), fp)) { - sscanf(buffer, "Hardware : %s", hardware); - if (strcmp(hardware, "BCM2708") == 0 || - strcmp(hardware, "BCM2709") == 0 || ---- a/source/event_gpio.c -+++ b/source/event_gpio.c -@@ -64,6 +64,15 @@ int epfd_thread = -1; - int epfd_blocking = -1; - - /************* /sys/class/gpio functions ************/ -+#define x_write(fd, buf, len) do { \ -+ size_t x_write_len = (len); \ -+ \ -+ if ((size_t)write((fd), (buf), x_write_len) != x_write_len) { \ -+ close(fd); \ -+ return (-1); \ -+ } \ -+} while (/* CONSTCOND */ 0) -+ - int gpio_export(unsigned int gpio) - { - int fd, len; -@@ -73,7 +82,7 @@ int gpio_export(unsigned int gpio) - return -1; - - len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); -- write(fd, str_gpio, len); -+ x_write(fd, str_gpio, len); - close(fd); - - return 0; -@@ -88,7 +97,7 @@ int gpio_unexport(unsigned int gpio) - return -1; - - len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); -- write(fd, str_gpio, len); -+ x_write(fd, str_gpio, len); - close(fd); - - return 0; -@@ -115,9 +124,9 @@ int gpio_set_direction(unsigned int gpio - return -1; - - if (in_flag) -- write(fd, "in", 3); -+ x_write(fd, "in", 3); - else -- write(fd, "out", 4); -+ x_write(fd, "out", 4); - - close(fd); - return 0; -@@ -133,7 +142,7 @@ int gpio_set_edge(unsigned int gpio, uns - if ((fd = open(filename, O_WRONLY)) < 0) - return -1; - -- write(fd, stredge[edge], strlen(stredge[edge]) + 1); -+ x_write(fd, stredge[edge], strlen(stredge[edge]) + 1); - close(fd); - return 0; - } diff -Nru rpi.gpio-0.6.3/debian/rpi.gpio-common.docs rpi.gpio-0.6.5/debian/rpi.gpio-common.docs --- rpi.gpio-0.6.3/debian/rpi.gpio-common.docs 1970-01-01 00:00:00.000000000 +0000 +++ rpi.gpio-0.6.5/debian/rpi.gpio-common.docs 2018-06-12 12:22:46.000000000 +0000 @@ -0,0 +1 @@ +README.txt diff -Nru rpi.gpio-0.6.3/debian/rpio.gpio-common.docs rpi.gpio-0.6.5/debian/rpio.gpio-common.docs --- rpi.gpio-0.6.3/debian/rpio.gpio-common.docs 2017-01-31 19:16:33.000000000 +0000 +++ rpi.gpio-0.6.5/debian/rpio.gpio-common.docs 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -README.txt diff -Nru rpi.gpio-0.6.3/setup.py rpi.gpio-0.6.5/setup.py --- rpi.gpio-0.6.3/setup.py 2016-10-30 21:43:29.000000000 +0000 +++ rpi.gpio-0.6.5/setup.py 2018-11-16 10:06:48.000000000 +0000 @@ -1,5 +1,5 @@ """ -Copyright (c) 2012-2016 Ben Croston +Copyright (c) 2012-2018 Ben Croston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -33,7 +33,7 @@ 'Topic :: System :: Hardware'] setup(name = 'RPi.GPIO', - version = '0.6.3', + version = '0.6.5', author = 'Ben Croston', author_email = 'ben@croston.org', description = 'A module to control Raspberry Pi GPIO channels', diff -Nru rpi.gpio-0.6.3/source/c_gpio.c rpi.gpio-0.6.5/source/c_gpio.c --- rpi.gpio-0.6.3/source/c_gpio.c 2016-10-30 21:42:00.000000000 +0000 +++ rpi.gpio-0.6.5/source/c_gpio.c 2018-11-16 10:04:06.000000000 +0000 @@ -61,7 +61,7 @@ { int mem_fd; uint8_t *gpio_mem; - uint32_t peri_base; + uint32_t peri_base = 0; uint32_t gpio_base; unsigned char buf[4]; FILE *fp; @@ -95,8 +95,7 @@ if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) return SETUP_CPUINFO_FAIL; - while(!feof(fp) && !found) { - fgets(buffer, sizeof(buffer), fp); + while(!feof(fp) && !found && fgets(buffer, sizeof(buffer), fp)) { sscanf(buffer, "Hardware : %s", hardware); if (strcmp(hardware, "BCM2708") == 0 || strcmp(hardware, "BCM2835") == 0) { // pi 1 hardware @@ -113,6 +112,8 @@ return SETUP_NOT_RPI_FAIL; } + if (!peri_base) + return SETUP_NOT_RPI_FAIL; gpio_base = peri_base + GPIO_BASE_OFFSET; // mmap the GPIO memory registers diff -Nru rpi.gpio-0.6.3/source/cpuinfo.c rpi.gpio-0.6.5/source/cpuinfo.c --- rpi.gpio-0.6.3/source/cpuinfo.c 2016-10-30 21:42:00.000000000 +0000 +++ rpi.gpio-0.6.5/source/cpuinfo.c 2018-11-16 10:04:06.000000000 +0000 @@ -37,8 +37,7 @@ if ((fp = fopen("/proc/cpuinfo", "r")) == NULL) return -1; - while(!feof(fp)) { - fgets(buffer, sizeof(buffer), fp); + while(!feof(fp) && fgets(buffer, sizeof(buffer), fp)) { sscanf(buffer, "Hardware : %s", hardware); if (strcmp(hardware, "BCM2708") == 0 || strcmp(hardware, "BCM2709") == 0 || diff -Nru rpi.gpio-0.6.3/source/event_gpio.c rpi.gpio-0.6.5/source/event_gpio.c --- rpi.gpio-0.6.3/source/event_gpio.c 2016-10-30 21:42:00.000000000 +0000 +++ rpi.gpio-0.6.5/source/event_gpio.c 2018-11-16 10:04:06.000000000 +0000 @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2016 Ben Croston +Copyright (c) 2013-2018 Ben Croston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -64,16 +64,34 @@ int epfd_blocking = -1; /************* /sys/class/gpio functions ************/ +#define x_write(fd, buf, len) do { \ + size_t x_write_len = (len); \ + \ + if ((size_t)write((fd), (buf), x_write_len) != x_write_len) { \ + close(fd); \ + return (-1); \ + } \ +} while (/* CONSTCOND */ 0) + int gpio_export(unsigned int gpio) { int fd, len; char str_gpio[3]; + char filename[33]; + + snprintf(filename, sizeof(filename), "/sys/class/gpio/gpio%d", gpio); + + /* return if gpio already exported */ + if (access(filename, F_OK) != -1) { + return 0; + } - if ((fd = open("/sys/class/gpio/export", O_WRONLY)) < 0) + if ((fd = open("/sys/class/gpio/export", O_WRONLY)) < 0) { return -1; + } len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); - write(fd, str_gpio, len); + x_write(fd, str_gpio, len); close(fd); return 0; @@ -88,7 +106,7 @@ return -1; len = snprintf(str_gpio, sizeof(str_gpio), "%d", gpio); - write(fd, str_gpio, len); + x_write(fd, str_gpio, len); close(fd); return 0; @@ -115,9 +133,9 @@ return -1; if (in_flag) - write(fd, "in", 3); + x_write(fd, "in", 3); else - write(fd, "out", 4); + x_write(fd, "out", 4); close(fd); return 0; @@ -133,7 +151,7 @@ if ((fd = open(filename, O_WRONLY)) < 0) return -1; - write(fd, stredge[edge], strlen(stredge[edge]) + 1); + x_write(fd, stredge[edge], strlen(stredge[edge]) + 1); close(fd); return 0; } @@ -218,7 +236,6 @@ void delete_gpio(unsigned int gpio) { struct gpios *g = gpio_list; - struct gpios *temp; struct gpios *prev = NULL; while (g != NULL) { @@ -227,9 +244,7 @@ gpio_list = g->next; else prev->next = g->next; - temp = g; - g = g->next; - free(temp); + free(g); return; } else { prev = g; @@ -345,7 +360,7 @@ } else { gettimeofday(&tv_timenow, NULL); timenow = tv_timenow.tv_sec*1E6 + tv_timenow.tv_usec; - if (g->bouncetime == -666 || timenow - g->lastcall > g->bouncetime*1000 || g->lastcall == 0 || g->lastcall > timenow) { + if (g->bouncetime == -666 || timenow - g->lastcall > (unsigned int)g->bouncetime*1000 || g->lastcall == 0 || g->lastcall > timenow) { g->lastcall = timenow; event_occurred[g->gpio] = 1; run_callbacks(g->gpio); @@ -407,26 +422,29 @@ } } -void event_cleanup(unsigned int gpio) +void event_cleanup(int gpio) // gpio of -666 means clean every channel used { struct gpios *g = gpio_list; - struct gpios *temp = NULL; + struct gpios *next_gpio = NULL; while (g != NULL) { - if ((gpio == -666) || (g->gpio == gpio)) - temp = g->next; + next_gpio = g->next; + if ((gpio == -666) || ((int)g->gpio == gpio)) remove_edge_detect(g->gpio); - g = temp; + g = next_gpio; } - if (gpio_list == NULL) - if (epfd_blocking != -1) + if (gpio_list == NULL) { + if (epfd_blocking != -1) { close(epfd_blocking); epfd_blocking = -1; - if (epfd_thread != -1) + } + if (epfd_thread != -1) { close(epfd_thread); epfd_thread = -1; + } thread_running = 0; + } } void event_cleanup_all(void) @@ -448,13 +466,14 @@ i = gpio_event_added(gpio); if (i == 0) { // event not already added - if ((g = new_gpio(gpio)) == NULL) + if ((g = new_gpio(gpio)) == NULL) { return 2; + } gpio_set_edge(gpio, edge); g->edge = edge; g->bouncetime = bouncetime; - } else if (i == edge) { // get existing event + } else if (i == (int)edge) { // get existing event g = get_gpio(gpio); if ((bouncetime != -666 && g->bouncetime != bouncetime) || // different event bouncetime used (g->thread_added)) // event already added @@ -507,7 +526,7 @@ // add gpio if it has not been added already ed = gpio_event_added(gpio); - if (ed == edge) { // get existing record + if (ed == (int)edge) { // get existing record g = get_gpio(gpio); if (g->bouncetime != -666 && g->bouncetime != bouncetime) { return -1; @@ -557,7 +576,7 @@ } else { gettimeofday(&tv_timenow, NULL); timenow = tv_timenow.tv_sec*1E6 + tv_timenow.tv_usec; - if (g->bouncetime == -666 || timenow - g->lastcall > g->bouncetime*1000 || g->lastcall == 0 || g->lastcall > timenow) { + if (g->bouncetime == -666 || timenow - g->lastcall > (unsigned int)g->bouncetime*1000 || g->lastcall == 0 || g->lastcall > timenow) { g->lastcall = timenow; finished = 1; } diff -Nru rpi.gpio-0.6.3/source/event_gpio.h rpi.gpio-0.6.5/source/event_gpio.h --- rpi.gpio-0.6.3/source/event_gpio.h 2016-10-30 21:42:00.000000000 +0000 +++ rpi.gpio-0.6.5/source/event_gpio.h 2018-11-16 10:04:06.000000000 +0000 @@ -31,6 +31,6 @@ int event_detected(unsigned int gpio); int gpio_event_added(unsigned int gpio); int event_initialise(void); -void event_cleanup(unsigned int gpio); +void event_cleanup(int gpio); void event_cleanup_all(void); int blocking_wait_for_edge(unsigned int gpio, unsigned int edge, int bouncetime, int timeout); diff -Nru rpi.gpio-0.6.3/source/py_gpio.c rpi.gpio-0.6.5/source/py_gpio.c --- rpi.gpio-0.6.3/source/py_gpio.c 2016-10-30 21:42:00.000000000 +0000 +++ rpi.gpio-0.6.5/source/py_gpio.c 2018-11-16 10:04:06.000000000 +0000 @@ -578,7 +578,7 @@ else chans = 40; for (chan=1; chan<=chans; chan++) - if (*(*pin_to_gpio+chan) == gpio) + if (*(*pin_to_gpio+chan) == (int)gpio) return chan; return -1; } diff -Nru rpi.gpio-0.6.3/source/py_pwm.c rpi.gpio-0.6.5/source/py_pwm.c --- rpi.gpio-0.6.3/source/py_pwm.c 2016-10-30 21:42:00.000000000 +0000 +++ rpi.gpio-0.6.5/source/py_pwm.c 2018-11-16 10:04:06.000000000 +0000 @@ -1,5 +1,5 @@ /* -Copyright (c) 2013 Ben Croston +Copyright (c) 2013-2018 Ben Croston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -47,6 +47,13 @@ if (get_gpio_number(channel, &(self->gpio))) return -1; + // does soft pwm already exist on this channel? + if (pwm_exists(self->gpio)) + { + PyErr_SetString(PyExc_RuntimeError, "A PWM object already exists for this GPIO channel"); + return -1; + } + // ensure channel set as output if (gpio_direction[self->gpio] != OUTPUT) { diff -Nru rpi.gpio-0.6.3/source/soft_pwm.c rpi.gpio-0.6.5/source/soft_pwm.c --- rpi.gpio-0.6.3/source/soft_pwm.c 2016-10-30 21:42:00.000000000 +0000 +++ rpi.gpio-0.6.5/source/soft_pwm.c 2018-11-16 10:04:06.000000000 +0000 @@ -1,5 +1,5 @@ /* -Copyright (c) 2013 Ben Croston +Copyright (c) 2013-2018 Ben Croston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -50,13 +50,14 @@ { if (p->gpio == gpio) { - if (prev == NULL) + if (prev == NULL) { pwm_list = p->next; - else + } else { prev->next = p->next; + } temp = p; p = p->next; - free(temp); + temp->running = 0; // signal the thread to stop. The thread will free() the pwm struct when it's done with it. } else { prev = p; p = p->next; @@ -109,7 +110,7 @@ // clean up output_gpio(p->gpio, 0); - remove_pwm(p->gpio); + free(p); pthread_exit(NULL); } @@ -131,6 +132,7 @@ } struct pwm *find_pwm(unsigned int gpio) +/* Return the pwm record for gpio, creating it if it does not exist */ { struct pwm *p = pwm_list; @@ -203,12 +205,27 @@ p->running = 0; return; } + pthread_detach(threads); } void pwm_stop(unsigned int gpio) { - struct pwm *p; + remove_pwm(gpio); +} - if ((p = find_pwm(gpio)) != NULL) - p->running = 0; +// returns 1 if there is a PWM for this gpio, 0 otherwise +int pwm_exists(unsigned int gpio) +{ + struct pwm *p = pwm_list; + + while (p != NULL) + { + if (p->gpio == gpio) + { + return 1; + } else { + p = p->next; + } + } + return 0; } diff -Nru rpi.gpio-0.6.3/source/soft_pwm.h rpi.gpio-0.6.5/source/soft_pwm.h --- rpi.gpio-0.6.3/source/soft_pwm.h 2016-10-30 21:42:00.000000000 +0000 +++ rpi.gpio-0.6.5/source/soft_pwm.h 2018-11-16 10:04:06.000000000 +0000 @@ -1,5 +1,5 @@ /* -Copyright (c) 2013 Ben Croston +Copyright (c) 2013-2018 Ben Croston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -26,3 +26,4 @@ void pwm_set_frequency(unsigned int gpio, float freq); void pwm_start(unsigned int gpio); void pwm_stop(unsigned int gpio); +int pwm_exists(unsigned int gpio); diff -Nru rpi.gpio-0.6.3/test/issue_94_111_154.py rpi.gpio-0.6.5/test/issue_94_111_154.py --- rpi.gpio-0.6.3/test/issue_94_111_154.py 1970-01-01 00:00:00.000000000 +0000 +++ rpi.gpio-0.6.5/test/issue_94_111_154.py 2018-11-16 10:04:06.000000000 +0000 @@ -0,0 +1,36 @@ +import time +import RPi.GPIO as GPIO + +LED_PIN = 12 + +def issue_154(): + # fails with led off at around 400 + count = 0 + pinRef = GPIO.PWM(LED_PIN,50) # create new PWM instance + while True: + pinRef.start(10) # update PWM value + time.sleep(0.05) + pinRef.stop() + GPIO.output(LED_PIN,0) + time.sleep(0.05) + count = count + 1 + print count + +def issue_94(cycles): + # led flickers. Bug = LED stays off at around cycle 400 + pwm = GPIO.PWM(LED_PIN, 1) + for i in xrange(cycles): + print(i) + pwm.ChangeFrequency(25) + pwm.start(50) + time.sleep(1) + pwm.stop() + +if __name__ == '__main__': + GPIO.setmode(GPIO.BOARD) + GPIO.setup(LED_PIN, GPIO.OUT) + try: +# issue_94(1000) + issue_154() + finally: + GPIO.cleanup() diff -Nru rpi.gpio-0.6.3/test/test.py rpi.gpio-0.6.5/test/test.py --- rpi.gpio-0.6.3/test/test.py 2016-10-30 21:42:00.000000000 +0000 +++ rpi.gpio-0.6.5/test/test.py 2018-11-16 10:04:06.000000000 +0000 @@ -1,6 +1,9 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python +from __future__ import print_function +if hasattr(__builtins__, 'raw_input'): + input = raw_input """ -Copyright (c) 2013-2016 Ben Croston +Copyright (c) 2013-2018 Ben Croston Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in @@ -45,7 +48,9 @@ LED_PIN = 12 LED_PIN_BCM = 18 SWITCH_PIN = 18 +SWITCH_PIN_BCM = 24 LOOP_IN = 16 +LOOP_IN_BCM = 23 LOOP_OUT = 22 non_interactive = False @@ -247,6 +252,15 @@ def tearDown(self): GPIO.cleanup() +class TestSoftPWMExists(unittest.TestCase): + def runTest(self): + GPIO.setmode(GPIO.BOARD) + GPIO.setup(LED_PIN, GPIO.OUT) + pwm = GPIO.PWM(LED_PIN, 50) + with self.assertRaises(RuntimeError): + pwm2 = GPIO.PWM(LED_PIN, 49) + GPIO.cleanup() + class TestSoftPWM(unittest.TestCase): @unittest.skipIf(non_interactive, 'Non interactive mode') def runTest(self): @@ -254,13 +268,13 @@ GPIO.setup(LED_PIN, GPIO.OUT) pwm = GPIO.PWM(LED_PIN, 50) pwm.start(100) - print "\nPWM tests" - response = raw_input('Is the LED on (y/n) ? ').upper() + print("\nPWM tests") + response = input('Is the LED on (y/n) ? ').upper() self.assertEqual(response,'Y') pwm.start(0) - response = raw_input('Is the LED off (y/n) ? ').upper() + response = input('Is the LED off (y/n) ? ').upper() self.assertEqual(response,'Y') - print "LED Brighten/fade test..." + print("LED Brighten/fade test...") for i in range(0,3): for x in range(0,101,5): pwm.ChangeDutyCycle(x) @@ -269,7 +283,7 @@ pwm.ChangeDutyCycle(x) time.sleep(0.1) pwm.stop() - response = raw_input('Did it work (y/n) ? ').upper() + response = input('Did it work (y/n) ? ').upper() self.assertEqual(response,'Y') GPIO.cleanup() @@ -326,15 +340,15 @@ class TestVersions(unittest.TestCase): def test_rpi_info(self): - print 'RPi Board Information' - print '---------------------' - for key,val in GPIO.RPI_INFO.items(): - print '%s => %s'%(key,val) - response = raw_input('\nIs this board info correct (y/n) ? ').upper() + print('RPi Board Information') + print('---------------------') + for key,val in list(GPIO.RPI_INFO.items()): + print('%s => %s'%(key,val)) + response = input('\nIs this board info correct (y/n) ? ').upper() self.assertEqual(response, 'Y') def test_gpio_version(self): - response = raw_input('\nRPi.GPIO version %s - is this correct (y/n) ? '%GPIO.VERSION).upper() + response = input('\nRPi.GPIO version %s - is this correct (y/n) ? '%GPIO.VERSION).upper() self.assertEqual(response, 'Y') class TestGPIOFunction(unittest.TestCase): @@ -362,7 +376,7 @@ def cb(self,chan): self.switchcount += 1 - print 'Button press',self.switchcount + print('Button press',self.switchcount) def setUp(self): GPIO.setmode(GPIO.BOARD) @@ -371,7 +385,7 @@ @unittest.skipIf(non_interactive, 'Non interactive mode') def test_switchbounce(self): self.switchcount = 0 - print "\nSwitch bounce test. Press switch at least 10 times and count..." + print("\nSwitch bounce test. Press switch at least 10 times and count...") GPIO.add_event_detect(SWITCH_PIN, GPIO.FALLING, callback=self.cb, bouncetime=200) while self.switchcount < 10: time.sleep(1) @@ -380,12 +394,12 @@ @unittest.skipIf(non_interactive, 'Non interactive mode') def test_event_detected(self): self.switchcount = 0 - print "\nGPIO.event_detected() switch bounce test. Press switch at least 10 times and count..." + print("\nGPIO.event_detected() switch bounce test. Press switch at least 10 times and count...") GPIO.add_event_detect(SWITCH_PIN, GPIO.FALLING, bouncetime=200) while self.switchcount < 10: if GPIO.event_detected(SWITCH_PIN): self.switchcount += 1 - print 'Button press',self.switchcount + print('Button press',self.switchcount) GPIO.remove_event_detect(SWITCH_PIN) def tearDown(self): @@ -711,14 +725,29 @@ def test_cleanone(self): GPIO.setup(LOOP_OUT, GPIO.OUT) GPIO.setup(LED_PIN, GPIO.OUT) + GPIO.setup(SWITCH_PIN, GPIO.IN) + GPIO.setup(LOOP_IN, GPIO.IN) + GPIO.add_event_detect(SWITCH_PIN, GPIO.FALLING) + GPIO.add_event_detect(LOOP_IN, GPIO.RISING) + time.sleep(0.2) # wait for udev to set permissions self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.OUT) self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT) + self.assertEqual(GPIO.gpio_function(SWITCH_PIN), GPIO.IN) + self.assertEqual(GPIO.gpio_function(LOOP_IN), GPIO.IN) + self.assertTrue(os.path.exists('/sys/class/gpio/gpio%s'%SWITCH_PIN_BCM)) + self.assertTrue(os.path.exists('/sys/class/gpio/gpio%s'%LOOP_IN_BCM)) + GPIO.cleanup(SWITCH_PIN) + time.sleep(0.2) # wait for udev to set permissions + self.assertFalse(os.path.exists('/sys/class/gpio/gpio%s'%SWITCH_PIN_BCM)) + self.assertTrue(os.path.exists('/sys/class/gpio/gpio%s'%LOOP_IN_BCM)) + GPIO.cleanup(LOOP_IN) + time.sleep(0.2) # wait for udev to set permissions + self.assertFalse(os.path.exists('/sys/class/gpio/gpio%s'%SWITCH_PIN_BCM)) + self.assertFalse(os.path.exists('/sys/class/gpio/gpio%s'%LOOP_IN_BCM)) GPIO.cleanup(LOOP_OUT) - GPIO.setmode(GPIO.BOARD) self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN) self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.OUT) GPIO.cleanup(LED_PIN) - GPIO.setmode(GPIO.BOARD) self.assertEqual(GPIO.gpio_function(LOOP_OUT), GPIO.IN) self.assertEqual(GPIO.gpio_function(LED_PIN), GPIO.IN)