V55
authorjoan <joan@abyz.co.uk>
Sun, 10 Jul 2016 20:29:14 +0000 (21:29 +0100)
committerjoan <joan@abyz.co.uk>
Sun, 10 Jul 2016 20:29:14 +0000 (21:29 +0100)
18 files changed:
command.c
command.h
pig2vcd.1
pigpio.3
pigpio.c
pigpio.h
pigpio.py
pigpiod.1
pigpiod_if.3
pigpiod_if.c
pigpiod_if.h
pigpiod_if2.3
pigpiod_if2.c
pigpiod_if2.h
pigs.1
pigs.c
setup.py
x_pigs

index ef15b5d7e83516b805a3ccfb19753e07e61b2c75..239ec2ef3c468d110d3c82216134a2dfbba6f3b8 100644 (file)
--- a/command.c
+++ b/command.c
@@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
 */
 
 /*
-This version is for pigpio version 53+
+This version is for pigpio version 55+
 */
 
 #include <stdio.h>
@@ -61,9 +61,19 @@ cmdInfo_t cmdInfo[]=
    {PI_CMD_CGI,   "CGI",   101, 4}, // gpioCfgGetInternals
    {PI_CMD_CSI,   "CSI",   111, 1}, // gpioCfgSetInternals
 
+   {PI_CMD_FC,    "FC",    112, 0}, // fileClose
+
    {PI_CMD_FG,    "FG",    121, 0}, // gpioGlitchFilter
+
+   {PI_CMD_FL,    "FL",    127, 6}, // fileList
+
    {PI_CMD_FN,    "FN",    131, 0}, // gpioNoiseFilter
 
+   {PI_CMD_FO,    "FO",    127, 2}, // fileOpen
+   {PI_CMD_FR,    "FR",    121, 6}, // fileRead
+   {PI_CMD_FS,    "FS",    133, 2}, // fileSeek
+   {PI_CMD_FW,    "FW",    193, 0}, // fileWrite
+
    {PI_CMD_GDC,   "GDC",   112, 2}, // gpioGetPWMdutycycle
    {PI_CMD_GPW,   "GPW",   112, 2}, // gpioGetServoPulsewidth
 
@@ -112,6 +122,9 @@ cmdInfo_t cmdInfo[]=
    {PI_CMD_NO,    "NO",    101, 2}, // gpioNotifyOpen
    {PI_CMD_NP,    "NP",    112, 0}, // gpioNotifyPause
 
+   {PI_CMD_PADG,  "PADG",  112, 2}, // gpioGetPad
+   {PI_CMD_PADS,  "PADS",  121, 0}, // gpioSetPad
+
    {PI_CMD_PARSE, "PARSE", 115, 0}, // cmdParseScript
 
    {PI_CMD_PFG,   "PFG",   112, 2}, // gpioGetPWMfrequency
@@ -149,6 +162,8 @@ cmdInfo_t cmdInfo[]=
    {PI_CMD_SERVO, "S",     121, 0}, // gpioServo
    {PI_CMD_SERVO, "SERVO", 121, 0}, // gpioServo
 
+   {PI_CMD_SHELL, "SHELL", 128, 2}, // shell
+
    {PI_CMD_SLR,   "SLR",   121, 6}, // gpioSerialRead
    {PI_CMD_SLRC,  "SLRC",  112, 0}, // gpioSerialReadClose
    {PI_CMD_SLRO,  "SLRO",  131, 0}, // gpioSerialReadOpen
@@ -252,8 +267,14 @@ CF2 ...          Custom function 2\n\
 CGI              Configuration get internals\n\
 CSI v            Configuration set internals\n\
 \n\
+FC h             Close file handle\n\
 FG g steady      Set glitch filter on GPIO\n\
+FL pat n         List files which match pattern\n\
 FN g steady active | Set noise filter on GPIO\n\
+FO file mode     Open a file in mode\n\
+FR h n           Read bytes from file handle\n\
+FS h n from      Seek to file handle position\n\
+FW h ...         Write bytes to file handle\n\
 \n\
 GDC g            Get PWM dutycycle for GPIO\n\
 GPW g            Get servo pulsewidth for GPIO\n\
@@ -293,6 +314,8 @@ NO               Request a notification\n\
 NP h             Pause notification\n\
 \n\
 P/PWM g v        Set GPIO PWM value\n\
+PADG pad         Get pad drive strength\n\
+PADS pad v       Set pad drive strength\n\
 PARSE text       Validate script\n\
 PFG g            Get GPIO PWM frequency\n\
 PFS g v          Set GPIO PWM frequency\n\
@@ -316,7 +339,8 @@ SERO text baud flags | Open serial device at baud with flags\n\
 SERR h n         Read bytes from serial handle\n\
 SERRB h          Read byte from serial handle\n\
 SERW h ...       Write bytes to serial handle\n\
-SERWB h byte        Write byte to serial handle\n\
+SERWB h byte     Write byte to serial handle\n\
+SHELL name str   Execute a shell command\n\
 SLR g v          Read bit bang serial data from GPIO\n\
 SLRC g           Close GPIO for bit bang serial data\n\
 SLRO g baud bitlen | Open GPIO for bit bang serial data\n\
@@ -490,6 +514,21 @@ static errInfo_t errInfo[]=
    {PI_BAD_ISR_INIT     , "bad ISR initialisation"},
    {PI_BAD_FOREVER      , "loop forever must be last chain command"},
    {PI_BAD_FILTER       , "bad filter parameter"},
+   {PI_BAD_PAD          , "bad pad number"},
+   {PI_BAD_STRENGTH     , "bad pad drive strength"},
+   {PI_FIL_OPEN_FAILED  , "file open failed"},
+   {PI_BAD_FILE_MODE    , "bad file mode"},
+   {PI_BAD_FILE_FLAG    , "bad file flag"},
+   {PI_BAD_FILE_READ    , "bad file read"},
+   {PI_BAD_FILE_WRITE   , "bad file write"},
+   {PI_FILE_NOT_ROPEN   , "file not open for read"},
+   {PI_FILE_NOT_WOPEN   , "file not open for write"},
+   {PI_BAD_FILE_SEEK    , "bad file seek"},
+   {PI_NO_FILE_MATCH    , "no files match pattern"},
+   {PI_NO_FILE_ACCESS   , "no permission to access file"},
+   {PI_FILE_IS_A_DIR    , "file is a directory"},
+   {PI_BAD_SHELL_STATUS , "bad shell return status"},
+   {PI_BAD_SCRIPT_NAME  , "bad script name"},
 
 };
 
@@ -507,14 +546,14 @@ static int cmdMatch(char *str)
    return CMD_UNKNOWN_CMD;
 }
 
-static int getNum(char *str, unsigned *val, int8_t *opt)
+static int getNum(char *str, uint32_t *val, int8_t *opt)
 {
    int f, n;
-   unsigned v;
+   intmax_t v;
 
    *opt = 0;
 
-   f = sscanf(str, " %i %n", &v, &n);
+   f = sscanf(str, " %ji %n", &v, &n);
 
    if (f == 1)
    {
@@ -523,7 +562,7 @@ static int getNum(char *str, unsigned *val, int8_t *opt)
       return n;
    }
 
-   f = sscanf(str, " v%i %n", &v, &n);
+   f = sscanf(str, " v%ji %n", &v, &n);
 
    if (f == 1)
    {
@@ -533,7 +572,7 @@ static int getNum(char *str, unsigned *val, int8_t *opt)
       return n;
    }
 
-   f = sscanf(str, " p%i %n", &v, &n);
+   f = sscanf(str, " p%ji %n", &v, &n);
 
    if (f == 1)
    {
@@ -556,7 +595,7 @@ char *cmdStr(void)
 int cmdParse(
    char *buf, uint32_t *p, unsigned ext_len, char *ext, cmdCtlParse_t *ctl)
 {
-   int f, valid, idx, val, pp, pars, n, n2, i;
+   int f, valid, idx, val, pp, pars, n, n2;
    char *p8;
    int32_t *p32;
    char c;
@@ -611,8 +650,8 @@ int cmdParse(
 
          break;
 
-      case 112: /* BI2CC GDC  GPW  I2CC
-                   I2CRB MG  MICS  MILS  MODEG  NC  NP  PFG  PRG
+      case 112: /* BI2CC FC  GDC  GPW  I2CC  I2CRB
+                   MG  MICS  MILS  MODEG  NC  NP  PADG PFG  PRG
                    PROCD  PROCP  PROCS  PRRG  R  READ  SLRC  SPIC
                    WVDEL  WVSC  WVSM  WVSP  WVTX  WVTXR
 
@@ -656,37 +695,23 @@ int cmdParse(
 
       case 116: /* SYS
 
-                   One parameter, a string of letters, digits, '-' and '_'.
+                   One parameter, a string.
                 */
          f = sscanf(buf+ctl->eaten, " %*s%n %n", &n, &n2);
          if ((f >= 0) && n)
          {
+            p[3] = n;
+            ctl->opt[3] = CMD_NUMERIC;
+            memcpy(ext, buf+ctl->eaten, n);
+            ctl->eaten += n2;
             valid = 1;
-
-            for (i=0; i<n; i++)
-            {
-               c = buf[ctl->eaten+i];
-
-               if ((!isalnum(c)) && (c != '_') && (c != '-'))
-               {
-                  valid = 0;
-                  break;
-               }
-            }
-
-            if (valid)
-            {
-               p[3] = n;
-               ctl->opt[3] = CMD_NUMERIC;
-               memcpy(ext, buf+ctl->eaten, n);
-               ctl->eaten += n2;
-            }
          }
 
          break;
 
-      case 121: /* HC I2CRD  I2CRR  I2CRW  I2CWB I2CWQ  P  PFS  PRS
-                   PWM  S  SERVO  SLR  SLRI  W  WDOG  WRITE WVTXM
+      case 121: /* HC  FR  I2CRD  I2CRR  I2CRW  I2CWB I2CWQ  P
+                   PADS  PFS  PRS  PWM  S  SERVO  SLR  SLRI  W
+                   WDOG  WRITE  WVTXM
 
                    Two positive parameters.
                 */
@@ -782,8 +807,53 @@ int cmdParse(
 
          break;
 
-      case 131: /* BI2CO HP I2CO  I2CPC  I2CRI  I2CWB  I2CWW  SLRO
-                   SPIO  TRIG
+      case 127: /* FL  FO
+
+                   Two parameters, first a string, other positive.
+                */
+         f = sscanf(buf+ctl->eaten, " %*s%n %n", &n, &n2);
+         if ((f >= 0) && n)
+         {
+            p[3] = n;
+            ctl->opt[2] = CMD_NUMERIC;
+            memcpy(ext, buf+ctl->eaten, n);
+            ctl->eaten += n2;
+
+            ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[1]);
+
+            if ((ctl->opt[1] > 0) && ((int)p[1] >= 0))
+               valid = 1;
+         }
+
+         break;
+
+      case 128: /* SHELL
+
+                   Two string parameters, the first space teminated.
+                   The second arbitrary.
+                */
+         f = sscanf(buf+ctl->eaten, " %*s%n %n", &n, &n2);
+
+         if ((f >= 0) && n)
+         {
+            valid = 1;
+
+            p[1] = n;
+            memcpy(ext, buf+ctl->eaten, n);
+            ctl->eaten += n;
+            ext[n] = 0; /* terminate first string */
+
+            n2 = strlen(buf+ctl->eaten+1);
+            memcpy(ext+n+1, buf+ctl->eaten+1, n2);
+            ctl->eaten += n2;
+            ctl->eaten ++;
+            p[3] = p[1] + n2 + 1;
+         }
+
+         break;
+
+      case 131: /* BI2CO  HP  I2CO  I2CPC  I2CRI  I2CWB  I2CWW
+                   SLRO  SPIO  TRIG
 
                    Three positive parameters.
                 */
@@ -824,6 +894,26 @@ int cmdParse(
 
          break;
 
+      case 133: /* FS
+
+                   Three parameters.  First and third positive.
+                   Second may be negative when interpreted as an int.
+                */
+         ctl->eaten += getNum(buf+ctl->eaten, &p[1], &ctl->opt[1]);
+         ctl->eaten += getNum(buf+ctl->eaten, &p[2], &ctl->opt[2]);
+         ctl->eaten += getNum(buf+ctl->eaten, &tp1, &to1);
+
+         if ((ctl->opt[1] > 0) && ((int)p[1] >= 0) &&
+             (ctl->opt[2] > 0) &&
+             (to1 == CMD_NUMERIC) && ((int)tp1 >= 0))
+         {
+            p[3] = 4;
+            memcpy(ext, &tp1, 4);
+            valid = 1;
+         }
+
+         break;
+
       case 191: /* PROCR
 
                    One to 11 parameters, first positive,
@@ -880,7 +970,7 @@ int cmdParse(
 
          break;
 
-      case 193: /* BI2CZ  I2CWD  I2CZ  SERW  SPIW  SPIX
+      case 193: /* BI2CZ  FW  I2CWD  I2CZ  SERW  SPIW  SPIX
 
                    Two or more parameters, first >=0, rest 0-255.
                 */
index 3c36bd13d40e649afacfa84d3ea2c6d09892d0e5..7c6efcd347309d434b23d4eb8f145143c8ee1860 100644 (file)
--- a/command.h
+++ b/command.h
@@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
 */
 
 /*
-This version is for pigpio version 53+
+This version is for pigpio version 55+
 */
 
 #ifndef COMMAND_H
index 492ec68a9db9ec5a8adfa37329473d5e43730cb9..24b5a6cd9a216ee35d84dcc08e6a9450792e7a75 100644 (file)
--- a/pig2vcd.1
+++ b/pig2vcd.1
@@ -11,6 +11,10 @@ pig2vd - A utility to convert pigpio notifications to VCD.
 pig2vcd </dev/pigpioXX >file.VCD
 .SH DESCRIPTION
 
+
+.ad l
+
+.nh
 pig2vcd is a utility which reads notifications on stdin and writes the
 output as a Value Change Dump (VCD) file on stdout.
 
index 8bb1011d9aa30242937cf449c9c79d5e2bbc4966..16b0ddf1bd72e2de256a115444a2ae0d3b97ad71 100644 (file)
--- a/pigpio.3
+++ b/pigpio.3
@@ -17,6 +17,10 @@ sudo ./prog
 .SH DESCRIPTION
 
 
+.ad l
+
+.nh
+
 .br
 
 .br
@@ -29,12 +33,12 @@ pigpio is a C library for the Raspberry which allows control of the GPIO.
 .br
 
 .br
-o PWM on any of GPIO 0-31
+o hardware timed PWM on any of GPIO 0-31
 
 .br
 
 .br
-o servo pulses on any of GPIO 0-31
+o hardware timed servo pulses on any of GPIO 0-31
 
 .br
 
@@ -313,15 +317,15 @@ Arduino style: pinMode.
 .br
 
 .EX
-gpioSetMode(17, PI_INPUT);  // Set gpio17 as input.
+gpioSetMode(17, PI_INPUT);  // Set GPIO17 as input.
 .br
 
 .br
-gpioSetMode(18, PI_OUTPUT); // Set gpio18 as output.
+gpioSetMode(18, PI_OUTPUT); // Set GPIO18 as output.
 .br
 
 .br
-gpioSetMode(22,PI_ALT0);    // Set gpio22 to alternative mode 0.
+gpioSetMode(22,PI_ALT0);    // Set GPIO22 to alternative mode 0.
 .br
 
 .EE
@@ -356,7 +360,7 @@ if (gpioGetMode(17) != PI_ALT0)
 .br
 {
 .br
-   gpioSetMode(17, PI_ALT0);  // set gpio17 to ALT0
+   gpioSetMode(17, PI_ALT0);  // set GPIO17 to ALT0
 .br
 }
 .br
@@ -435,7 +439,7 @@ Arduino style: digitalRead.
 .br
 
 .EX
-printf("gpio24 is level %d", gpioRead(24));
+printf("GPIO24 is level %d", gpioRead(24));
 .br
 
 .EE
@@ -478,7 +482,7 @@ Arduino style: digitalWrite
 .br
 
 .EX
-gpioWrite(24, 1); // Set gpio24 high.
+gpioWrite(24, 1); // Set GPIO24 high.
 .br
 
 .EE
@@ -529,15 +533,15 @@ range of 255.
 .br
 
 .EX
-gpioPWM(17, 255); // Sets gpio17 full on.
+gpioPWM(17, 255); // Sets GPIO17 full on.
 .br
 
 .br
-gpioPWM(18, 128); // Sets gpio18 half on.
+gpioPWM(18, 128); // Sets GPIO18 half on.
 .br
 
 .br
-gpioPWM(23, 0);   // Sets gpio23 full off.
+gpioPWM(23, 0);   // Sets GPIO23 full off.
 .br
 
 .EE
@@ -825,15 +829,15 @@ sample
 .br
 
 .EX
-gpioSetPWMfrequency(23, 0); // Set gpio23 to lowest frequency.
+gpioSetPWMfrequency(23, 0); // Set GPIO23 to lowest frequency.
 .br
 
 .br
-gpioSetPWMfrequency(24, 500); // Set gpio24 to 500Hz.
+gpioSetPWMfrequency(24, 500); // Set GPIO24 to 500Hz.
 .br
 
 .br
-gpioSetPWMfrequency(25, 100000); // Set gpio25 to highest frequency.
+gpioSetPWMfrequency(25, 100000); // Set GPIO25 to highest frequency.
 .br
 
 .EE
@@ -878,7 +882,7 @@ will be that set by \fBgpioHardwarePWM\fP.
 .br
 
 .EX
-f = gpioGetPWMfrequency(23); // Get frequency used for gpio23.
+f = gpioGetPWMfrequency(23); // Get frequency used for GPIO23.
 .br
 
 .EE
@@ -978,7 +982,7 @@ the servo pulsewidth.
 .br
 
 .br
-E.g. If you want to update a servo connected to gpio25 at 400Hz
+E.g. If you want to update a servo connected to GPIO25 at 400Hz
 
 .br
 
@@ -1481,11 +1485,19 @@ by one for each report.
 
 .br
 flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
-If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags
-indicate a GPIO which has had a watchdog timeout; if bit 6 is set
-(PI_NTFY_FLAGS_ALIVE) this indicates a keep alive signal on the
-pipe/socket and is sent once a minute in the absence of other
-notification activity.
+
+.br
+
+.br
+PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+indicate a GPIO which has had a watchdog timeout.
+
+.br
+
+.br
+PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+signal on the pipe/socket and is sent once a minute in the absence
+of other notification activity.
 
 .br
 
@@ -2095,19 +2107,14 @@ The following command codes are supported:
 
 .br
 Name           Cmd & Data   Meaning
-
 .br
 Loop Start     255 0        Identify start of a wave block
-
 .br
 Loop Repeat    255 1 x y    loop x + y*256 times
-
 .br
 Delay          255 2 x y    delay x + y*256 microseconds
-
 .br
 Loop Forever   255 3        loop forever
-
 .br
 
 .br
@@ -2362,7 +2369,7 @@ This function configures the level logic for bit bang serial reads.
 .br
 
 .br
-Pass PI_BB_SER_INVERT to invert the serial logic.  Pass PI_BB_SER_NORMAL for
+Use PI_BB_SER_INVERT to invert the serial logic and PI_BB_SER_NORMAL for
 normal logic.  Default is PI_BB_SER_NORMAL.
 
 .br
@@ -3178,31 +3185,22 @@ The following command codes are supported:
 
 .br
 Name      Cmd & Data   Meaning
-
 .br
 End       0            No more commands
-
 .br
 Escape    1            Next P is two bytes
-
 .br
 On        2            Switch combined flag on
-
 .br
 Off       3            Switch combined flag off
-
 .br
 Address   4 P          Set I2C address to P
-
 .br
 Flags     5 lsb msb    Set I2C flags to lsb + (msb << 8)
-
 .br
 Read      6 P          Read P bytes of data
-
 .br
 Write     7 P ...      Write P bytes of data
-
 .br
 
 .br
@@ -3367,31 +3365,22 @@ The following command codes are supported:
 
 .br
 Name      Cmd & Data     Meaning
-
 .br
 End       0              No more commands
-
 .br
 Escape    1              Next P is two bytes
-
 .br
 Start     2              Start condition
-
 .br
 Stop      3              Stop condition
-
 .br
 Address   4 P            Set I2C address to P
-
 .br
 Flags     5 lsb msb      Set I2C flags to lsb + (msb << 8)
-
 .br
 Read      6 P            Read P bytes of data
-
 .br
 Write     7 P ...        Write P bytes of data
-
 .br
 
 .br
@@ -3719,14 +3708,15 @@ PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
 .IP "\fBint serOpen(char *sertty, unsigned baud, unsigned serFlags)\fP"
 .IP "" 4
 This function opens a serial device at a specified baud rate
-with specified flags.
+and with specified flags.  The device name must start with
+/dev/tty or /dev/serial.
 
 .br
 
 .br
 
 .EX
-  sertty: the serial device to open, /dev/tty*
+  sertty: the serial device to open
 .br
     baud: the baud rate in bits per second, see below
 .br
@@ -3847,7 +3837,7 @@ associated with handle and writes them to buf.
 .br
 
 .EX
-handle: >=0, as returned by a call to serial_open
+handle: >=0, as returned by a call to \fBserOpen\fP
 .br
    buf: an array to receive the read data
 .br
@@ -3860,7 +3850,7 @@ handle: >=0, as returned by a call to serial_open
 
 .br
 Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
-PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED.
+PI_BAD_PARAM, or PI_SER_READ_NO_DATA.
 
 .IP "\fBint serDataAvailable(unsigned handle)\fP"
 .IP "" 4
@@ -5146,184 +5136,245 @@ for "Revision       : 000g" the function returns 0.
 .IP "" 4
 Returns the pigpio version.
 
-.IP "\fBint gpioCfgBufferSize(unsigned cfgMillis)\fP"
+.IP "\fBint gpioGetPad(unsigned pad)\fP"
 .IP "" 4
-Configures pigpio to buffer cfgMillis milliseconds of GPIO samples.
+This function returns the pad drive strength in mA.
 
 .br
 
 .br
-This function is only effective if called before \fBgpioInitialise\fP.
 
+.EX
+pad: 0-2, the pad to get
 .br
 
+.EE
+
 .br
 
-.EX
-cfgMillis: 100-10000
 .br
+Returns the pad drive strength if OK, otherwise PI_BAD_PAD.
 
-.EE
+.br
 
+.br
+Pad   GPIO
+.br
+0     0-27
+.br
+1     28-45
+.br
+2     46-53
 .br
 
 .br
-The default setting is 120 milliseconds.
 
+.br
+\fBExample\fP
 .br
 
+.EX
+strength = gpioGetPad(1); // get pad 1 strength
 .br
-The intention is to allow for bursts of data and protection against
-other processes hogging cpu time.
+
+.EE
+
+.IP "\fBint gpioSetPad(unsigned pad, unsigned padStrength)\fP"
+.IP "" 4
+This function sets the pad drive strength in mA.
 
 .br
 
 .br
-I haven't seen a process locked out for more than 100 milliseconds.
 
+.EX
+        pad: 0-2, the pad to set
 .br
+padStrength: 1-16 mA
+.br
+
+.EE
 
 .br
-Making the buffer bigger uses a LOT of memory at the more frequent
-sampling rates as shown in the following table in MBs.
 
 .br
+Returns 0 if OK, otherwise PI_BAD_PAD, or PI_BAD_STRENGTH.
 
 .br
 
-.EX
-                     buffer milliseconds
 .br
-               120 250 500 1sec 2sec 4sec 8sec
+Pad   GPIO
 .br
-
+0     0-27
 .br
-         1      16  31  55  107  ---  ---  ---
+1     28-45
 .br
-         2      10  18  31   55  107  ---  ---
+2     46-53
 .br
-sample   4       8  12  18   31   55  107  ---
+
 .br
- rate    5       8  10  14   24   45   87  ---
+
 .br
- (us)    8       6   8  12   18   31   55  107
+\fBExample\fP
 .br
-        10       6   8  10   14   24   45   87
+
+.EX
+gpioSetPad(0, 16); // set pad 0 strength to 16 mA
 .br
 
 .EE
 
-.IP "\fBint gpioCfgClock(unsigned cfgMicros, unsigned cfgPeripheral, unsigned cfgSource)\fP"
+.IP "\fBint shell(char *scriptName, char *scriptString)\fP"
 .IP "" 4
-Configures pigpio to use a particular sample rate timed by a specified
-peripheral.
+This function uses the system call to execute a shell script
+with the given string as its parameter.
 
 .br
 
 .br
-This function is only effective if called before \fBgpioInitialise\fP.
 
+.EX
+  scriptName: the name of the script, only alphanumeric characters,
 .br
-
+              '-' and '_' are allowed in the name
+.br
+scriptString: the string to pass to the script
 .br
 
-.EX
-    cfgMicros: 1, 2, 4, 5, 8, 10
+.EE
+
 .br
-cfgPeripheral: 0 (PWM), 1 (PCM)
+
 .br
-    cfgSource: deprecated, value is ignored
+The exit status of the system call is returned if OK, otherwise
+PI_BAD_SHELL_STATUS.
+
 .br
 
-.EE
+.br
+scriptName must exist in /opt/pigpio/cgi and must be executable.
 
 .br
 
 .br
-The timings are provided by the specified peripheral (PWM or PCM).
+The returned exit status is normally 256 times that set by the
+shell script exit function.  If the script can't be found 32512 will
+be returned.
 
 .br
 
 .br
-The default setting is 5 microseconds using the PCM peripheral.
+The following table gives some example returned statuses.
 
 .br
 
 .br
-The approximate CPU percentage used for each sample rate is:
+Script exit status   Returned system call status
+.br
+1                    256
+.br
+5                    1280
+.br
+10                   2560
+.br
+200                  51200
+.br
+script not found     32512
+.br
 
 .br
 
+.br
+\fBExample\fP
 .br
 
 .EX
-sample  cpu
+// pass two parameters, hello and world
 .br
- rate    %
+status = shell("scr1", "hello world");
 .br
 
 .br
-  1     25
-.br
-  2     16
+// pass three parameters, hello, string with spaces, and world
 .br
-  4     11
+status = shell("scr1", "hello 'string with spaces' world");
 .br
-  5     10
+
 .br
-  8     15
+// pass one parameter, hello string with spaces world
 .br
- 10     14
+status = shell("scr1", "\"hello string with spaces world\"");
 .br
 
 .EE
 
+.IP "\fBint fileOpen(char *file, unsigned mode)\fP"
+.IP "" 4
+This function returns a handle to a file opened in a specified mode.
+
 .br
 
 .br
-A sample rate of 5 microseconds seeems to be the sweet spot.
 
-.IP "\fBint gpioCfgDMAchannel(unsigned DMAchannel)\fP"
-.IP "" 4
-Configures pigpio to use the specified DMA channel.
+.EX
+file: the file to open
+.br
+mode: the file open mode
+.br
+
+.EE
 
 .br
 
 .br
-This function is only effective if called before \fBgpioInitialise\fP.
+Returns a handle (>=0) if OK, otherwise PI_NO_HANDLE, PI_NO_FILE_ACCESS,
+PI_BAD_FILE_MODE, PI_FILE_OPEN_FAILED, or PI_FILE_IS_A_DIR.
 
 .br
 
 .br
+File
 
-.EX
-DMAchannel: 0-14
 .br
 
-.EE
+.br
+A file may only be opened if permission is granted by an entry in
+/opt/pigpio/access.  This is intended to allow remote access to files
+in a more or less controlled manner.
 
 .br
 
 .br
-The default setting is to use channel 14.
+Each entry in /opt/pigpio/access takes the form of a file path
+which may contain wildcards followed by a single letter permission.
+The permission may be R for read, W for write, U for read/write,
+and N for no access.
 
-.IP "\fBint gpioCfgDMAchannels(unsigned primaryChannel, unsigned secondaryChannel)\fP"
-.IP "" 4
-Configures pigpio to use the specified DMA channels.
+.br
 
 .br
+Where more than one entry matches a file the most specific rule
+applies.  If no entry matches a file then access is denied.
 
 .br
-This function is only effective if called before \fBgpioInitialise\fP.
+
+.br
+Suppose /opt/pigpio/access contains the following entries
 
 .br
 
 .br
 
 .EX
-  primaryChannel: 0-14
+/home/* n
 .br
-secondaryChannel: 0-14
+/home/pi/shared/dir_1/* w
+.br
+/home/pi/shared/dir_2/* r
+.br
+/home/pi/shared/dir_3/* u
+.br
+/home/pi/shared/dir_1/file.txt n
 .br
 
 .EE
@@ -5331,45 +5382,41 @@ secondaryChannel: 0-14
 .br
 
 .br
-The default setting is to use channel 14 for the primary channel and
-channel 6 for the secondary channel.
+Files may be written in directory dir_1 with the exception
+of file.txt.
 
 .br
 
 .br
-The secondary channel is only used for the transmission of waves.
+Files may be read in directory dir_2.
 
 .br
 
 .br
-If possible use one of channels 0 to 6 for the secondary channel
-(a full channel).
+Files may be read and written in directory dir_3.
 
 .br
 
 .br
-A full channel only requires one DMA control block regardless of the
-length of a pulse delay.  Channels 7 to 14 (lite channels) require
-one DMA control block for each 16383 microseconds of delay.  I.e.
-a 10 second pulse delay requires one control block on a full channel
-and 611 control blocks on a lite channel.
-
-.IP "\fBint gpioCfgPermissions(uint64_t updateMask)\fP"
-.IP "" 4
-Configures pigpio to only allow updates (writes or mode changes) for the
-GPIO specified by the mask.
+If a directory allows read, write, or read/write access then files may
+be created in that directory.
 
 .br
 
 .br
-This function is only effective if called before \fBgpioInitialise\fP.
+In an attempt to prevent risky permissions the following paths are
+ignored in /opt/pigpio/access.
 
 .br
 
 .br
 
 .EX
-updateMask: bit (1<<n) is set for each GPIO n which may be updated
+a path containing ..
+.br
+a path containing only wildcards (*?)
+.br
+a path containing less than two non-wildcard parts
 .br
 
 .EE
@@ -5377,112 +5424,159 @@ updateMask: bit (1<<n) is set for each GPIO n which may be updated
 .br
 
 .br
-The default setting depends upon the Pi model. The user GPIO are
-added to the mask.
+Mode
 
 .br
 
 .br
-If the board revision is not recognised then GPIO 0-31 are allowed.
+The mode may have the following values.
 
 .br
 
 .br
-Unknown board   PI_DEFAULT_UPDATE_MASK_UNKNOWN   0xFFFFFFFF
+Macro           Value   Meaning
 .br
-
+PI_FILE_READ      1     open file for reading
 .br
-Type 1 board    PI_DEFAULT_UPDATE_MASK_B1   0x03E6CF93
+PI_FILE_WRITE     2     open file for writing
+.br
+PI_FILE_RW        3     open file for reading and writing
 .br
 
 .br
-Type 2 board    PI_DEFAULT_UPDATE_MASK_A_B2   0xFBC6CF9C
 
 .br
-Type 3 board    PI_DEFAULT_UPDATE_MASK_R3   0x0FFFFFFC
+The following values may be or'd into the mode.
 
 .br
 
-.IP "\fBint gpioCfgSocketPort(unsigned port)\fP"
-.IP "" 4
-Configures pigpio to use the specified socket port.
+.br
+Macro            Value   Meaning
+.br
+PI_FILE_APPEND   4       Writes append data to the end of the file
+.br
+PI_FILE_CREATE   8       The file is created if it doesn't exist
+.br
+PI_FILE_TRUNC    16      The file is truncated
+.br
 
 .br
 
 .br
-This function is only effective if called before \fBgpioInitialise\fP.
+Newly created files are owned by root with permissions owner read and write.
 
 .br
 
+.br
+\fBExample\fP
 .br
 
 .EX
-port: 1024-32000
+#include <stdio.h>
 .br
-
-.EE
-
+#include <pigpio.h>
 .br
 
 .br
-The default setting is to use port 8888.
+int main(int argc, char *argv[])
+.br
+{
+.br
+   int handle, c;
+.br
+   char buf[60000];
+.br
 
-.IP "\fBint gpioCfgInterfaces(unsigned ifFlags)\fP"
-.IP "" 4
-Configures pigpio support of the fifo and socket interfaces.
+.br
+   if (gpioInitialise() < 0) return 1;
+.br
 
+.br
+   // assumes /opt/pigpio/access contains the following line
+.br
+   // /ram/*.c r
 .br
 
 .br
-This function is only effective if called before \fBgpioInitialise\fP.
+   handle = fileOpen("/ram/pigpio.c", PI_FILE_READ);
+.br
 
+.br
+   if (handle >= 0)
+.br
+   {
+.br
+      while ((c=fileRead(handle, buf, sizeof(buf)-1)))
+.br
+      {
+.br
+         buf[c] = 0;
+.br
+         printf("%s", buf);
+.br
+      }
 .br
 
+.br
+      fileClose(handle);
+.br
+   }
 .br
 
-.EX
-ifFlags: 0-7
+.br
+   gpioTerminate();
+.br
+}
 .br
 
 .EE
 
+.IP "\fBint fileClose(unsigned handle)\fP"
+.IP "" 4
+This function closes the file associated with handle.
+
 .br
 
 .br
-The default setting (0) is that both interfaces are enabled.
 
+.EX
+handle: >=0, as returned by a call to \fBfileOpen\fP
 .br
 
+.EE
+
 .br
-Or in PI_DISABLE_FIFO_IF to disable the pipe interface.
 
 .br
+Returns 0 if OK, otherwise PI_BAD_HANDLE.
 
 .br
-Or in PI_DISABLE_SOCK_IF to disable the socket interface.
 
+.br
+\fBExample\fP
 .br
 
+.EX
+fileClose(h);
 .br
-Or in PI_LOCALHOST_SOCK_IF to disable remote socket
-access (this means that the socket interface is only
-usable from the local Pi).
 
-.IP "\fBint gpioCfgMemAlloc(unsigned memAllocMode)\fP"
+.EE
+
+.IP "\fBint fileWrite(unsigned handle, char *buf, unsigned count)\fP"
 .IP "" 4
-Selects the method of DMA memory allocation.
+This function writes count bytes from buf to the the file
+associated with handle.
 
 .br
 
 .br
-This function is only effective if called before \fBgpioInitialise\fP.
 
+.EX
+handle: >=0, as returned by a call to \fBfileOpen\fP
 .br
-
+   buf: the array of bytes to write
 .br
-
-.EX
-memAllocMode: 0-2
+ count: the number of bytes to write
 .br
 
 .EE
@@ -5490,8 +5584,570 @@ memAllocMode: 0-2
 .br
 
 .br
-There are two methods of DMA memory allocation.  The original method
-uses the /proc/self/pagemap file to allocate bus memory.  The new
+Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM,
+PI_FILE_NOT_WOPEN, or PI_BAD_FILE_WRITE.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+status = fileWrite(h, buf, count);
+.br
+if (status == 0)
+.br
+{
+.br
+   // okay
+.br
+}
+.br
+else
+.br
+{
+.br
+   // error
+.br
+}
+.br
+
+.EE
+
+.IP "\fBint fileRead(unsigned handle, char *buf, unsigned count)\fP"
+.IP "" 4
+This function reads up to count bytes from the the file
+associated with handle and writes them to buf.
+
+.br
+
+.br
+
+.EX
+handle: >=0, as returned by a call to \fBfileOpen\fP
+.br
+   buf: an array to receive the read data
+.br
+ count: the maximum number of bytes to read
+.br
+
+.EE
+
+.br
+
+.br
+Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, PI_FILE_NOT_ROPEN, or PI_BAD_FILE_WRITE.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+if (fileRead(h, buf, sizeof(buf)) > 0)
+.br
+{
+.br
+   // process read data
+.br
+}
+.br
+
+.EE
+
+.IP "\fBint fileSeek(unsigned handle, int32_t seekOffset, int seekFrom)\fP"
+.IP "" 4
+This function seeks to a position within the file associated
+with handle.
+
+.br
+
+.br
+
+.EX
+    handle: >=0, as returned by a call to \fBfileOpen\fP
+.br
+seekOffset: the number of bytes to move.  Positive offsets
+.br
+            move forward, negative offsets backwards.
+.br
+  seekFrom: one of PI_FROM_START (0), PI_FROM_CURRENT (1),
+.br
+            or PI_FROM_END (2)
+.br
+
+.EE
+
+.br
+
+.br
+Returns the new byte position within the file (>=0) if OK, otherwise PI_BAD_HANDLE, or PI_BAD_FILE_SEEK.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+fileSeek(0, 20, PI_FROM_START); // Seek to start plus 20
+.br
+
+.br
+size = fileSeek(0, 0, PI_FROM_END); // Seek to end, return size
+.br
+
+.br
+pos = fileSeek(0, 0, PI_FROM_CURRENT); // Return current position
+.br
+
+.EE
+
+.IP "\fBint fileList(char *fpat, char *buf, unsigned count)\fP"
+.IP "" 4
+This function returns a list of files which match a pattern.  The
+pattern may contain wildcards.
+
+.br
+
+.br
+
+.EX
+ fpat: file pattern to match
+.br
+  buf: an array to receive the matching file names
+.br
+count: the maximum number of bytes to read
+.br
+
+.EE
+
+.br
+
+.br
+Returns the number of returned bytes if OK, otherwise PI_NO_FILE_ACCESS,
+or PI_NO_FILE_MATCH.
+
+.br
+
+.br
+The pattern must match an entry in /opt/pigpio/access.  The pattern
+may contain wildcards.  See \fBfileOpen\fP.
+
+.br
+
+.br
+NOTE
+
+.br
+
+.br
+The returned value is not the number of files, it is the number
+of bytes in the buffer.  The file names are separated by newline
+characters.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+#include <stdio.h>
+.br
+#include <pigpio.h>
+.br
+
+.br
+int main(int argc, char *argv[])
+.br
+{
+.br
+   int c;
+.br
+   char buf[1000];
+.br
+
+.br
+   if (gpioInitialise() < 0) return 1;
+.br
+
+.br
+   // assumes /opt/pigpio/access contains the following line
+.br
+   // /ram/*.c r
+.br
+
+.br
+   c = fileList("/ram/p*.c", buf, sizeof(buf));
+.br
+
+.br
+   if (c >= 0)
+.br
+   {
+.br
+      // terminate string
+.br
+      buf[c] = 0;
+.br
+      printf("%s", buf);
+.br
+   }
+.br
+
+.br
+   gpioTerminate();
+.br
+}
+.br
+
+.EE
+
+.IP "\fBint gpioCfgBufferSize(unsigned cfgMillis)\fP"
+.IP "" 4
+Configures pigpio to buffer cfgMillis milliseconds of GPIO samples.
+
+.br
+
+.br
+This function is only effective if called before \fBgpioInitialise\fP.
+
+.br
+
+.br
+
+.EX
+cfgMillis: 100-10000
+.br
+
+.EE
+
+.br
+
+.br
+The default setting is 120 milliseconds.
+
+.br
+
+.br
+The intention is to allow for bursts of data and protection against
+other processes hogging cpu time.
+
+.br
+
+.br
+I haven't seen a process locked out for more than 100 milliseconds.
+
+.br
+
+.br
+Making the buffer bigger uses a LOT of memory at the more frequent
+sampling rates as shown in the following table in MBs.
+
+.br
+
+.br
+
+.EX
+                     buffer milliseconds
+.br
+               120 250 500 1sec 2sec 4sec 8sec
+.br
+
+.br
+         1      16  31  55  107  ---  ---  ---
+.br
+         2      10  18  31   55  107  ---  ---
+.br
+sample   4       8  12  18   31   55  107  ---
+.br
+ rate    5       8  10  14   24   45   87  ---
+.br
+ (us)    8       6   8  12   18   31   55  107
+.br
+        10       6   8  10   14   24   45   87
+.br
+
+.EE
+
+.IP "\fBint gpioCfgClock(unsigned cfgMicros, unsigned cfgPeripheral, unsigned cfgSource)\fP"
+.IP "" 4
+Configures pigpio to use a particular sample rate timed by a specified
+peripheral.
+
+.br
+
+.br
+This function is only effective if called before \fBgpioInitialise\fP.
+
+.br
+
+.br
+
+.EX
+    cfgMicros: 1, 2, 4, 5, 8, 10
+.br
+cfgPeripheral: 0 (PWM), 1 (PCM)
+.br
+    cfgSource: deprecated, value is ignored
+.br
+
+.EE
+
+.br
+
+.br
+The timings are provided by the specified peripheral (PWM or PCM).
+
+.br
+
+.br
+The default setting is 5 microseconds using the PCM peripheral.
+
+.br
+
+.br
+The approximate CPU percentage used for each sample rate is:
+
+.br
+
+.br
+
+.EX
+sample  cpu
+.br
+ rate    %
+.br
+
+.br
+  1     25
+.br
+  2     16
+.br
+  4     11
+.br
+  5     10
+.br
+  8     15
+.br
+ 10     14
+.br
+
+.EE
+
+.br
+
+.br
+A sample rate of 5 microseconds seeems to be the sweet spot.
+
+.IP "\fBint gpioCfgDMAchannel(unsigned DMAchannel)\fP"
+.IP "" 4
+Configures pigpio to use the specified DMA channel.
+
+.br
+
+.br
+This function is only effective if called before \fBgpioInitialise\fP.
+
+.br
+
+.br
+
+.EX
+DMAchannel: 0-14
+.br
+
+.EE
+
+.br
+
+.br
+The default setting is to use channel 14.
+
+.IP "\fBint gpioCfgDMAchannels(unsigned primaryChannel, unsigned secondaryChannel)\fP"
+.IP "" 4
+Configures pigpio to use the specified DMA channels.
+
+.br
+
+.br
+This function is only effective if called before \fBgpioInitialise\fP.
+
+.br
+
+.br
+
+.EX
+  primaryChannel: 0-14
+.br
+secondaryChannel: 0-14
+.br
+
+.EE
+
+.br
+
+.br
+The default setting is to use channel 14 for the primary channel and
+channel 6 for the secondary channel.
+
+.br
+
+.br
+The secondary channel is only used for the transmission of waves.
+
+.br
+
+.br
+If possible use one of channels 0 to 6 for the secondary channel
+(a full channel).
+
+.br
+
+.br
+A full channel only requires one DMA control block regardless of the
+length of a pulse delay.  Channels 7 to 14 (lite channels) require
+one DMA control block for each 16383 microseconds of delay.  I.e.
+a 10 second pulse delay requires one control block on a full channel
+and 611 control blocks on a lite channel.
+
+.IP "\fBint gpioCfgPermissions(uint64_t updateMask)\fP"
+.IP "" 4
+Configures pigpio to only allow updates (writes or mode changes) for the
+GPIO specified by the mask.
+
+.br
+
+.br
+This function is only effective if called before \fBgpioInitialise\fP.
+
+.br
+
+.br
+
+.EX
+updateMask: bit (1<<n) is set for each GPIO n which may be updated
+.br
+
+.EE
+
+.br
+
+.br
+The default setting depends upon the Pi model. The user GPIO are
+added to the mask.
+
+.br
+
+.br
+If the board revision is not recognised then GPIO 0-31 are allowed.
+
+.br
+
+.br
+Unknown board   PI_DEFAULT_UPDATE_MASK_UNKNOWN   0xFFFFFFFF
+.br
+.br
+Type 1 board    PI_DEFAULT_UPDATE_MASK_B1   0x03E6CF93
+.br
+.br
+Type 2 board    PI_DEFAULT_UPDATE_MASK_A_B2   0xFBC6CF9C
+.br
+Type 3 board    PI_DEFAULT_UPDATE_MASK_R3   0x0FFFFFFC
+.br
+
+.IP "\fBint gpioCfgSocketPort(unsigned port)\fP"
+.IP "" 4
+Configures pigpio to use the specified socket port.
+
+.br
+
+.br
+This function is only effective if called before \fBgpioInitialise\fP.
+
+.br
+
+.br
+
+.EX
+port: 1024-32000
+.br
+
+.EE
+
+.br
+
+.br
+The default setting is to use port 8888.
+
+.IP "\fBint gpioCfgInterfaces(unsigned ifFlags)\fP"
+.IP "" 4
+Configures pigpio support of the fifo and socket interfaces.
+
+.br
+
+.br
+This function is only effective if called before \fBgpioInitialise\fP.
+
+.br
+
+.br
+
+.EX
+ifFlags: 0-7
+.br
+
+.EE
+
+.br
+
+.br
+The default setting (0) is that both interfaces are enabled.
+
+.br
+
+.br
+Or in PI_DISABLE_FIFO_IF to disable the pipe interface.
+
+.br
+
+.br
+Or in PI_DISABLE_SOCK_IF to disable the socket interface.
+
+.br
+
+.br
+Or in PI_LOCALHOST_SOCK_IF to disable remote socket
+access (this means that the socket interface is only
+usable from the local Pi).
+
+.IP "\fBint gpioCfgMemAlloc(unsigned memAllocMode)\fP"
+.IP "" 4
+Selects the method of DMA memory allocation.
+
+.br
+
+.br
+This function is only effective if called before \fBgpioInitialise\fP.
+
+.br
+
+.br
+
+.EX
+memAllocMode: 0-2
+.br
+
+.EE
+
+.br
+
+.br
+There are two methods of DMA memory allocation.  The original method
+uses the /proc/self/pagemap file to allocate bus memory.  The new
 method uses the mailbox property interface to allocate bus memory.
 
 .br
@@ -6168,10 +6824,6 @@ PI_HW_CLK_MAX_FREQ 250000000
 .br
 
 .IP "\fBcount\fP" 0
-
-.br
-
-.br
 The number of bytes to be transferred in an I2C, SPI, or Serial
 command.
 
@@ -6246,7 +6898,7 @@ The number may vary between 0 and range (default 255) where
 .br
 
 .IP "\fBedge\fP: 0-2" 0
-The type of GPIO edge to generate an intrrupt.  See\fBgpioSetISRFunc\fP,
+The type of GPIO edge to generate an intrrupt.  See \fBgpioSetISRFunc\fP,
 and \fBgpioSetISRFuncEx\fP.
 
 .br
@@ -6278,6 +6930,22 @@ A function.
 
 .br
 
+.IP "\fB*file\fP" 0
+A full file path.  To be accessible the path must match an entry in
+/opt/pigpio/access.
+
+.br
+
+.br
+
+.IP "\fB*fpat\fP" 0
+A file path which may contain wildcards.  To be accessible the path
+must match an entry in /opt/pigpio/access.
+
+.br
+
+.br
+
 .IP "\fBfrequency\fP: >=0" 0
 
 .br
@@ -6302,14 +6970,14 @@ A Broadcom numbered GPIO, in the range 0-53.
 .br
 
 .br
-There  are 54 General Purpose Input Outputs (GPIO) named gpio0 through
-gpio53.
+There  are 54 General Purpose Input Outputs (GPIO) named GPIO0 through
+GPIO53.
 
 .br
 
 .br
-They are split into two  banks.   Bank  1  consists  of  gpio0  through
-gpio31.  Bank 2 consists of gpio32 through gpio53.
+They are split into two  banks.   Bank  1  consists  of  GPIO0  through
+GPIO31.  Bank 2 consists of GPIO32 through GPIO53.
 
 .br
 
@@ -6597,18 +7265,8 @@ One of
 .br
 
 .br
-A number referencing an object opened by one of
-
-.br
-
-.br
-\fBi2cOpen\fP
-.br
-\fBgpioNotifyOpen\fP
-.br
-\fBserOpen\fP
-.br
-\fBspiOpen\fP
+A number referencing an object opened by one of \fBfileOpen\fP,
+\fBgpioNotifyOpen\fP, \fBi2cOpen\fP, \fBserOpen\fP, \fBspiOpen\fP.
 
 .br
 
@@ -6689,6 +7347,13 @@ A whole number, negative or positive.
 
 .br
 
+.IP "\fBint32_t\fP" 0
+A 32-bit signed value.
+
+.br
+
+.br
+
 .IP "\fBinvert\fP" 0
 A flag used to set normal or inverted bit bang serial data level logic.
 
@@ -6816,12 +7481,12 @@ A value representing milliseconds.
 
 .br
 
-.IP "\fBmode\fP: 0-7" 0
+.IP "\fBmode\fP" 0
 
 .br
 
 .br
-The operational mode of a GPIO, normally INPUT or OUTPUT.
+1. The operational mode of a GPIO, normally INPUT or OUTPUT.
 
 .br
 
@@ -6849,6 +7514,44 @@ PI_ALT5 2
 
 .br
 
+.br
+2. A file open mode.
+
+.br
+
+.br
+
+.EX
+PI_FILE_READ  1
+.br
+PI_FILE_WRITE 2
+.br
+PI_FILE_RW    3
+.br
+
+.EE
+
+.br
+
+.br
+The following values can be or'd into the mode.
+
+.br
+
+.br
+
+.EX
+PI_FILE_APPEND 4
+.br
+PI_FILE_CREATE 8
+.br
+PI_FILE_TRUNC  16
+.br
+
+.EE
+
+.br
+
 .br
 
 .IP "\fBnumBits\fP" 0
@@ -6914,6 +7617,33 @@ The size in bytes of an output buffer.
 
 .br
 
+.IP "\fBpad\fP: 0-2" 0
+A set of GPIO which share common drivers.
+
+.br
+
+.br
+Pad   GPIO
+.br
+0     0-27
+.br
+1     28-45
+.br
+2     46-53
+.br
+
+.br
+
+.br
+
+.IP "\fBpadStrength\fP: 1-16" 0
+The mA which may be drawn from each GPIO whilst still guaranteeing the
+high and low levels.
+
+.br
+
+.br
+
 .IP "\fB*param\fP" 0
 An array of script parameters.
 
@@ -7251,10 +7981,6 @@ A pointer to a buffer to receive data.
 .br
 
 .IP "\fBSCL\fP" 0
-
-.br
-
-.br
 The user GPIO to use for the clock when bit banging I2C.
 
 .br
@@ -7262,10 +7988,6 @@ The user GPIO to use for the clock when bit banging I2C.
 .br
 
 .IP "\fB*script\fP" 0
-
-.br
-
-.br
 A pointer to the text of a script.
 
 .br
@@ -7273,21 +7995,28 @@ A pointer to the text of a script.
 .br
 
 .IP "\fBscript_id\fP" 0
+An id of a stored script as returned by \fBgpioStoreScript\fP.
 
 .br
 
 .br
-An id of a stored script as returned by \fBgpioStoreScript\fP.
+
+.IP "\fB*scriptName\fP" 0
+The name of a \fBshell\fP script to be executed.  The script must be present in
+/opt/pigpio/cgi and must have execute permission.
 
 .br
 
 .br
 
-.IP "\fBSDA\fP" 0
+.IP "\fB*scriptString\fP" 0
+The string to be passed to a \fBshell\fP script to be executed.
 
 .br
 
 .br
+
+.IP "\fBSDA\fP" 0
 The user GPIO to use for data when bit banging I2C.
 
 .br
@@ -7318,21 +8047,41 @@ a returned time.
 .br
 
 .IP "\fBseconds\fP" 0
+The number of seconds.
 
 .br
 
 .br
-The number of seconds.
+
+.IP "\fBseekFrom\fP" 0
 
 .br
 
 .br
 
-.IP "\fB*segs\fP" 0
+.EX
+PI_FROM_START   0
+.br
+PI_FROM_CURRENT 1
+.br
+PI_FROM_END     2
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBseekOffset\fP" 0
+The number of bytes to move forward (positive) or backwards (negative)
+from the seek position (start, current, or end of file).
 
 .br
 
 .br
+
+.IP "\fB*segs\fP" 0
 An array of segments which make up a combined I2C transaction.
 
 .br
@@ -7623,10 +8372,6 @@ See \fBgpio\fP.
 .br
 
 .IP "\fB*userdata\fP" 0
-
-.br
-
-.br
 A pointer to arbitrary user data.  This may be used to identify the instance.
 
 .br
@@ -7975,6 +8720,30 @@ A 16-bit word value.
 #define PI_CMD_WVTAT 101
 .br
 
+.br
+#define PI_CMD_PADS  102
+.br
+#define PI_CMD_PADG  103
+.br
+
+.br
+#define PI_CMD_FO    104
+.br
+#define PI_CMD_FC    105
+.br
+#define PI_CMD_FR    106
+.br
+#define PI_CMD_FW    107
+.br
+#define PI_CMD_FS    108
+.br
+#define PI_CMD_FL    109
+.br
+
+.br
+#define PI_CMD_SHELL 110
+.br
+
 .br
 
 .EE
@@ -8061,7 +8830,7 @@ A 16-bit word value.
 .br
 #define PI_TOO_MANY_CHARS   -37 // waveform has too many chars
 .br
-#define PI_NOT_SERIAL_GPIO  -38 // no bit bang serial read in progress on GPIO
+#define PI_NOT_SERIAL_GPIO  -38 // no bit bang serial read on GPIO
 .br
 #define PI_BAD_SERIAL_STRUC -39 // bad (null) serial structure parameter
 .br
@@ -8235,10 +9004,40 @@ A 16-bit word value.
 .br
 #define PI_BAD_ISR_INIT    -123 // bad ISR initialisation
 .br
-#define PI_BAD_FOREVER     -124 // loop forever must be last chain command
+#define PI_BAD_FOREVER     -124 // loop forever must be last command
 .br
 #define PI_BAD_FILTER      -125 // bad filter parameter
 .br
+#define PI_BAD_PAD         -126 // bad pad number
+.br
+#define PI_BAD_STRENGTH    -127 // bad pad drive strength
+.br
+#define PI_FIL_OPEN_FAILED -128 // file open failed
+.br
+#define PI_BAD_FILE_MODE   -129 // bad file mode
+.br
+#define PI_BAD_FILE_FLAG   -130 // bad file flag
+.br
+#define PI_BAD_FILE_READ   -131 // bad file read
+.br
+#define PI_BAD_FILE_WRITE  -132 // bad file write
+.br
+#define PI_FILE_NOT_ROPEN  -133 // file not open for read
+.br
+#define PI_FILE_NOT_WOPEN  -134 // file not open for write
+.br
+#define PI_BAD_FILE_SEEK   -135 // bad file seek
+.br
+#define PI_NO_FILE_MATCH   -136 // no files match pattern
+.br
+#define PI_NO_FILE_ACCESS  -137 // no permission to access file
+.br
+#define PI_FILE_IS_A_DIR   -138 // file is a directory
+.br
+#define PI_BAD_SHELL_STATUS -139 // bad shell return status
+.br
+#define PI_BAD_SCRIPT_NAME -140 // bad script name
+.br
 
 .br
 #define PI_PIGIF_ERR_0    -2000
index 4588b389e2c599bd5568f15ac7cfc9dc517449a4..3f0b2f84cb99f9bcdd3e77120241755a7e522345 100644 (file)
--- a/pigpio.c
+++ b/pigpio.c
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 For more information, please refer to <http://unlicense.org/>
 */
 
-/* pigpio version 54 */
+/* pigpio version 55 */
 
 /* include ------------------------------------------------------- */
 
@@ -58,11 +58,14 @@ For more information, please refer to <http://unlicense.org/>
 #include <netinet/tcp.h>
 #include <arpa/inet.h>
 #include <sys/select.h>
+#include <fnmatch.h>
+#include <glob.h>
 
 #include "pigpio.h"
 
 #include "command.h"
 
+
 /* --------------------------------------------------------------- */
 
 /*
@@ -299,6 +302,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define DMA_BASE   (pi_peri_phys + 0x00007000)
 #define DMA15_BASE (pi_peri_phys + 0x00E05000)
 #define GPIO_BASE  (pi_peri_phys + 0x00200000)
+#define PADS_BASE  (pi_peri_phys + 0x00100000)
 #define PCM_BASE   (pi_peri_phys + 0x00203000)
 #define PWM_BASE   (pi_peri_phys + 0x0020C000)
 #define SPI_BASE   (pi_peri_phys + 0x00204000)
@@ -308,6 +312,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define CLK_LEN   0xA8
 #define DMA_LEN   0x1000 /* allow access to all channels */
 #define GPIO_LEN  0xB4
+#define PADS_LEN  0x38
 #define PCM_LEN   0x24
 #define PWM_LEN   0x28
 #define SPI_LEN   0x18
@@ -474,7 +479,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
 #define PCM_GRAY_CLR   (1<<1)
 #define PCM_GRAY_EN    (1<<0)
 
-#define CLK_PASSWD  (0x5A<<24)
+#define BCM_PASSWD  (0x5A<<24)
 
 #define CLK_CTL_MASH(x)((x)<<9)
 #define CLK_CTL_BUSY    (1 <<7)
@@ -734,6 +739,9 @@ Assumes two counters per block.  Each counter 4 * 16 (16^4=65536)
 #define PI_SER_CLOSED 0
 #define PI_SER_OPENED 1
 
+#define PI_FILE_CLOSED 0
+#define PI_FILE_OPENED 1
+
 #define PI_NOTIFY_CLOSED  0
 #define PI_NOTIFY_CLOSING 1
 #define PI_NOTIFY_OPENED  2
@@ -843,6 +851,8 @@ Assumes two counters per block.  Each counter 4 * 16 (16^4=65536)
 #define PI_RUNNING  1
 #define PI_ENDING   2
 
+#define PI_MAX_PATH 512
+
 /* typedef ------------------------------------------------------- */
 
 typedef void (*callbk_t) ();
@@ -975,6 +985,13 @@ typedef struct
    int      max_emits;
 } gpioNotify_t;
 
+typedef struct
+{
+   uint16_t state;
+   int16_t  fd;
+   uint32_t mode;
+} fileInfo_t;
+
 typedef struct
 {
    uint16_t state;
@@ -1202,6 +1219,7 @@ static gpioInfo_t       gpioInfo   [PI_MAX_GPIO+1];
 
 static gpioNotify_t     gpioNotify [PI_NOTIFY_SLOTS];
 
+static fileInfo_t       fileInfo   [PI_FILE_SLOTS];
 static i2cInfo_t        i2cInfo    [PI_I2C_SLOTS];
 static serInfo_t        serInfo    [PI_SER_SLOTS];
 static spiInfo_t        spiInfo    [PI_SPI_SLOTS];
@@ -1242,6 +1260,7 @@ static volatile uint32_t * auxReg  = MAP_FAILED;
 static volatile uint32_t * clkReg  = MAP_FAILED;
 static volatile uint32_t * dmaReg  = MAP_FAILED;
 static volatile uint32_t * gpioReg = MAP_FAILED;
+static volatile uint32_t * padsReg = MAP_FAILED;
 static volatile uint32_t * pcmReg  = MAP_FAILED;
 static volatile uint32_t * pwmReg  = MAP_FAILED;
 static volatile uint32_t * spiReg  = MAP_FAILED;
@@ -1408,6 +1427,29 @@ static void closeOrphanedNotifications(int slot, int fd);
 
 /* ======================================================================= */
 
+int myScriptNameValid(char *name)
+{
+   int i, c, len, valid;
+
+   len = strlen(name);
+
+   valid = 1;
+
+   for (i=0; i<len; i++)
+   {
+      c = name[i];
+
+      if ((!isalnum(c)) && (c != '_') && (c != '-'))
+      {
+         valid = 0;
+         break;
+      }
+   }
+   return valid;
+}
+
+/* ----------------------------------------------------------------------- */
+
 static char * myTimeStamp()
 {
    static struct timeval last;
@@ -1430,6 +1472,47 @@ static char * myTimeStamp()
 
 /* ----------------------------------------------------------------------- */
 
+int myPathBad(char *name)
+{
+   int i, c, len, in_part, parts, last_char_dot;
+   char *bad="/*?.";
+
+   parts = 0;
+   in_part = 0;
+   last_char_dot = 0;
+
+   len = strlen(name);
+
+   for (i=0; i<len; i++)
+   {
+      c = name[i];
+
+      if (memchr(bad, c, 4)) /* wildcard or directory character */
+      {
+         if (c == '.')
+         {
+            if (last_char_dot) return 1;
+            last_char_dot = 1;
+         }
+         else last_char_dot = 0;
+
+         in_part = 0;
+      }
+      else /* normal character */
+      {
+         last_char_dot = 0;
+
+         if (!in_part) parts++;
+
+         in_part = 1;
+      }
+   }
+
+   if (parts < 2) return 1; else return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
 static char *myBuf2Str(unsigned count, char *buf)
 {
    static char str[128];
@@ -1774,15 +1857,36 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
 
       case PI_CMD_CSI: res = gpioCfgSetInternals(p[1]); break;
 
+      case PI_CMD_FC: res = fileClose(p[1]); break;
+
       case PI_CMD_FG:
          res = gpioGlitchFilter(p[1], p[2]);
          break;
 
+      case PI_CMD_FL:
+         if (p[1] > bufSize) p[1] = bufSize;
+         res = fileList(buf, buf, p[1]);
+         break;
+
       case PI_CMD_FN:
          memcpy(&p[4], buf, 4);
          res = gpioNoiseFilter(p[1], p[2], p[4]);
          break;
 
+      case PI_CMD_FO: res = fileOpen(buf, p[1]); break;
+
+      case PI_CMD_FR:
+         if (p[2] > bufSize) p[2] = bufSize;
+         res = fileRead(p[1], buf, p[2]);
+         break;
+
+      case PI_CMD_FS:
+         memcpy(&p[4], buf, 4);
+         res = fileSeek(p[1], p[2], p[4]);
+         break;
+
+      case PI_CMD_FW: res = fileWrite(p[1], buf, p[3]); break;
+
       case PI_CMD_GDC: res = gpioGetPWMdutycycle(p[1]); break;
 
       case PI_CMD_GPW: res = gpioGetServoPulsewidth(p[1]); break;
@@ -1923,6 +2027,10 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
 
       case PI_CMD_NP: res = gpioNotifyPause(p[1]); break;
 
+      case PI_CMD_PADG: res = gpioGetPad(p[1]); break;
+
+      case PI_CMD_PADS: res = gpioSetPad(p[1], p[2]); break;
+
       case PI_CMD_PFG: res = gpioGetPWMfrequency(p[1]); break;
 
       case PI_CMD_PFS:
@@ -2018,6 +2126,10 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
       case PI_CMD_SERW: res = serWrite(p[1], buf, p[3]); break;
 
 
+      case PI_CMD_SHELL:
+          res = shell(buf, buf+p[1]+1);
+          break;
+
 
       case PI_CMD_SLR:
          if (p[2] > bufSize) p[2] = bufSize;
@@ -4477,7 +4589,7 @@ int serOpen(char *tty, unsigned serBaud, unsigned serFlags)
 
    SER_CHECK_INITED;
 
-   if (strncmp("/dev/tty", tty, 8))
+   if (strncmp("/dev/tty", tty, 8) && strncmp("/dev/serial", tty, 11))
       SOFT_ERROR(PI_BAD_SER_DEVICE, "bad device (%s)", tty);
 
    switch (serBaud)
@@ -6022,17 +6134,21 @@ static int scrWait(gpioScript_t *s, uint32_t bits)
 
 static int scrSys(char *cmd, uint32_t p1, uint32_t p2)
 {
-   char buf[256];
-   char pars[40];
+   char buf[1024];
+   int status;
+
+   if (!myScriptNameValid(cmd))
+      SOFT_ERROR(PI_BAD_SCRIPT_NAME, "bad script name (%s)", cmd);
+
+   snprintf(buf, sizeof(buf), "/opt/pigpio/cgi/%s %u %u", cmd, p1, p2);
 
-   sprintf(pars, " %u %u", p1, p2);
-   strcpy(buf, "/opt/pigpio/cgi/");
-   strncat(buf, cmd, 200);
-   strcat(buf, pars);
+   DBG(DBG_USER, "%s", buf);
 
-   DBG(DBG_USER, "sys %s", buf);
+   status = system(buf);
 
-   return system(buf);
+   if (status < 0) status = PI_BAD_SHELL_STATUS;
+
+   return status;
 }
 
 /* ----------------------------------------------------------------------- */
@@ -6523,6 +6639,8 @@ static void *pthSocketThreadHandler(void *fdC)
 
          case PI_CMD_BI2CZ:
          case PI_CMD_CF2:
+         case PI_CMD_FL:
+         case PI_CMD_FR:
          case PI_CMD_I2CPK:
          case PI_CMD_I2CRD:
          case PI_CMD_I2CRI:
@@ -6769,6 +6887,11 @@ static int initPeripherals(void)
    if (auxReg == MAP_FAILED)
       SOFT_ERROR(PI_INIT_FAILED, "mmap aux failed (%m)");
 
+   padsReg  = initMapMem(fdMem, PADS_BASE,  PADS_LEN);
+
+   if (padsReg == MAP_FAILED)
+      SOFT_ERROR(PI_INIT_FAILED, "mmap pads failed (%m)");
+
    return 0;
 }
 
@@ -7170,20 +7293,20 @@ static void initHWClk
    {
       do
       {
-         clkReg[clkCtl] = CLK_PASSWD | CLK_CTL_KILL;
+         clkReg[clkCtl] = BCM_PASSWD | CLK_CTL_KILL;
       }
       while (clkReg[clkCtl] & CLK_CTL_BUSY);
    }
 
-   clkReg[clkDiv] = (CLK_PASSWD | CLK_DIV_DIVI(divI) | CLK_DIV_DIVF(divF));
+   clkReg[clkDiv] = (BCM_PASSWD | CLK_DIV_DIVI(divI) | CLK_DIV_DIVF(divF));
 
    usleep(10);
 
-   clkReg[clkCtl] = (CLK_PASSWD | CLK_CTL_MASH(MASH) | CLK_CTL_SRC(clkSrc));
+   clkReg[clkCtl] = (BCM_PASSWD | CLK_CTL_MASH(MASH) | CLK_CTL_SRC(clkSrc));
 
    usleep(10);
 
-   clkReg[clkCtl] |= (CLK_PASSWD | CLK_CTL_ENAB);
+   clkReg[clkCtl] |= (BCM_PASSWD | CLK_CTL_ENAB);
 }
 
 static void initClock(int mainClock)
@@ -11345,7 +11468,7 @@ int gpioHardwareClock(unsigned gpio, unsigned frequency)
    else
    {
       /* frequency 0, stop clock */
-      clkReg[cctl[clock]] = CLK_PASSWD | CLK_CTL_KILL;
+      clkReg[cctl[clock]] = BCM_PASSWD | CLK_CTL_KILL;
 
       if (gpioInfo[gpio].is == GPIO_HW_CLK)
          gpioInfo[gpio].is = GPIO_UNDEFINED;
@@ -11470,6 +11593,403 @@ int gpioHardwarePWM(
 }
 
 
+int gpioSetPad(unsigned pad, unsigned padStrength)
+{
+   DBG(DBG_USER, "pad=%d  padStrength=%d", pad, padStrength);
+
+   CHECK_INITED;
+
+   if (pad > PI_MAX_PAD)
+      SOFT_ERROR(PI_BAD_PAD, "bad pad number (%d)", pad);
+
+   if ((padStrength < PI_MIN_PAD_STRENGTH) ||
+       (padStrength > PI_MAX_PAD_STRENGTH))
+      SOFT_ERROR(PI_BAD_STRENGTH, "bad pad drive strength (%d)", pad);
+
+   /* 1-16 -> 0-7 */
+
+   padStrength += 1;
+   padStrength /= 2;
+   padStrength -= 1;
+
+   padsReg[11+pad] = BCM_PASSWD | 0x18 | (padStrength & 7) ;
+
+   return 0;
+}
+
+int gpioGetPad(unsigned pad)
+{
+   int strength;
+
+   DBG(DBG_USER, "pad=%d", pad);
+
+   CHECK_INITED;
+
+   if (pad > PI_MAX_PAD)
+      SOFT_ERROR(PI_BAD_PAD, "bad pad (%d)", pad);
+
+   strength = padsReg[11+pad] & 7;
+
+   strength *= 2;
+   strength += 2;
+
+   return strength;
+}
+
+int shell(char *scriptName, char *scriptString)
+{
+   int status;
+   char buf[4096];
+
+   DBG(DBG_USER, "name=%s string=%s", scriptName, scriptString);
+
+   CHECK_INITED;
+
+   if (!myScriptNameValid(scriptName))
+      SOFT_ERROR(PI_BAD_SCRIPT_NAME, "bad script name (%s)", scriptName);
+
+   snprintf(buf, sizeof(buf),
+      "/opt/pigpio/cgi/%s %s", scriptName, scriptString);
+
+   DBG(DBG_USER, "%s", buf);
+
+   status = system(buf);
+
+   if (status < 0) status = PI_BAD_SHELL_STATUS;
+
+   return status;
+}
+
+
+int fileApprove(char *filename)
+{
+   char match[PI_MAX_PATH];
+   char buffer[PI_MAX_PATH];
+   char line[PI_MAX_PATH];
+   char mperm;
+   char perm;
+   char term;
+   FILE *f;
+
+   buffer[0] = 0;
+   match[0] = 0;
+
+   f = fopen("/opt/pigpio/access", "r");
+
+   if (!f) return PI_FILE_NONE;
+
+   while (!feof(f))
+   {
+      buffer[0] = 0;
+      perm = 0;
+      term = 0;
+      if (fgets(line, sizeof(line), f))
+      {
+         sscanf(line, " %511s %c%c", buffer, &perm, &term);
+         if (term == 10)
+         {
+            if (myPathBad(buffer)) continue; /* disallow risky lines */
+
+            if (fnmatch(buffer, filename, 0) == 0)
+            {
+               if (match[0])
+               {
+                  if (fnmatch(match, buffer, 0) == 0)
+                  {
+                     strcpy(match, buffer);
+                     mperm = perm;
+                  }
+               }
+               else
+               {
+                  strcpy(match, buffer);
+                  mperm = perm;
+               }
+            }
+         }
+      }
+   }
+
+   fclose(f);
+
+   if (match[0])
+   {
+      switch (toupper(mperm))
+      {
+         case 'R': return PI_FILE_READ;
+         case 'W': return PI_FILE_WRITE;
+         case 'U': return PI_FILE_RW;
+         default : return PI_FILE_NONE;
+      }
+   }
+
+   return PI_FILE_NONE;
+}
+
+int fileOpen(char *file, unsigned mode)
+{
+   int fd=-1;
+   int i, slot, oflag, omode;
+   struct stat statbuf;
+
+   DBG(DBG_USER, "file=%s mode=%d", file, mode);
+
+   CHECK_INITED;
+
+   if ( (mode < PI_FILE_MIN) ||
+        (mode > PI_FILE_MAX) ||
+        ((mode & PI_FILE_RW) == 0) )
+      SOFT_ERROR(PI_BAD_FILE_MODE, "bad mode (%d)", mode);
+
+   if ((fileApprove(file) & mode) == PI_FILE_NONE)
+      SOFT_ERROR(PI_NO_FILE_ACCESS, "no permission to access file (%s)", file);
+
+   slot = -1;
+
+   for (i=0; i<PI_FILE_SLOTS; i++)
+   {
+      if (fileInfo[i].state == PI_FILE_CLOSED)
+      {
+         fileInfo[i].state = PI_FILE_OPENED;
+         slot = i;
+         break;
+      }
+   }
+
+   if (slot < 0)
+      SOFT_ERROR(PI_NO_HANDLE, "no file handles");
+
+   omode = 0;
+   oflag = 0;
+
+   if (mode & PI_FILE_APPEND)
+   {
+      mode |= PI_FILE_WRITE;
+      oflag |= O_APPEND;
+   }
+
+   if (mode & PI_FILE_CREATE)
+   {
+      oflag |= O_CREAT;
+      omode |= (S_IRUSR|S_IWUSR);
+   }
+
+   if (mode & PI_FILE_TRUNC)
+   {
+      mode |= PI_FILE_WRITE;
+      oflag |= O_TRUNC;
+   }
+
+   switch(mode&PI_FILE_RW)
+   {
+      case PI_FILE_READ:
+         fd = open(file, O_RDONLY|oflag, omode);
+         break;
+
+      case PI_FILE_WRITE:
+         fd = open(file, O_WRONLY|oflag, omode);
+         break;
+
+      case PI_FILE_RW:
+         fd = open(file, O_RDWR|oflag, omode);
+         break;
+   }
+
+   if (fd == -1)
+   {
+      fileInfo[slot].state = PI_FILE_CLOSED;
+      return PI_FIL_OPEN_FAILED;
+   }
+   else
+   {
+      if (stat(file, &statbuf) == 0)
+      {
+         if (S_ISDIR(statbuf.st_mode))
+         {
+            close(fd);
+            fileInfo[slot].state = PI_FILE_CLOSED;
+            SOFT_ERROR(PI_FILE_IS_A_DIR, "file is a directory (%s)", file);
+         }
+      }
+   }
+
+   fileInfo[slot].fd = fd;
+   fileInfo[slot].mode = mode;
+
+   return slot;
+}
+
+int fileClose(unsigned handle)
+{
+   DBG(DBG_USER, "handle=%d", handle);
+
+   CHECK_INITED;
+
+   if (handle >= PI_FILE_SLOTS)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   if (fileInfo[handle].state != PI_FILE_OPENED)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   if (fileInfo[handle].fd >= 0) close(fileInfo[handle].fd);
+
+   fileInfo[handle].fd = -1;
+   fileInfo[handle].state = PI_FILE_CLOSED;
+
+   return 0;
+}
+
+int fileWrite(unsigned handle, char *buf, unsigned count)
+{
+   int w;
+
+   DBG(DBG_USER, "handle=%d count=%d [%s]",
+      handle, count, myBuf2Str(count, buf));
+
+   CHECK_INITED;
+
+   if (handle >= PI_FILE_SLOTS)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   if (fileInfo[handle].state != PI_FILE_OPENED)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   if (!count)
+      SOFT_ERROR(PI_BAD_PARAM, "bad count (%d)", count);
+
+   if (!(fileInfo[handle].mode & PI_FILE_WRITE))
+      SOFT_ERROR(PI_FILE_NOT_WOPEN, "file not opened for write");
+
+   w = write(fileInfo[handle].fd, buf, count);
+
+   if (w != count)
+   {
+      if (w == -1) DBG(DBG_USER, "write failed with errno %d", errno);
+
+      return PI_BAD_FILE_WRITE;
+   }
+   return 0;
+}
+
+int fileRead(unsigned handle, char *buf, unsigned count)
+{
+   int r;
+
+   DBG(DBG_USER, "handle=%d count=%d buf=0x%X", handle, count, (unsigned)buf);
+
+   CHECK_INITED;
+
+   if (handle >= PI_FILE_SLOTS)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   if (fileInfo[handle].state != PI_FILE_OPENED)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   if (!count)
+      SOFT_ERROR(PI_BAD_PARAM, "bad count (%d)", count);
+
+   if (!(fileInfo[handle].mode & PI_FILE_READ))
+      SOFT_ERROR(PI_FILE_NOT_ROPEN, "file not opened for read");
+
+   r = read(fileInfo[handle].fd, buf, count);
+
+   if (r == -1)
+   {
+      DBG(DBG_USER, "read failed with errno %d", errno);
+      return PI_BAD_FILE_READ;
+   }
+   else
+   {
+      buf[r] = 0;
+      return r;
+   }
+}
+
+
+int fileSeek(unsigned handle, int32_t seekOffset, int seekFrom)
+{
+   int whence, s;
+
+   DBG(DBG_USER, "handle=%d offset=%d from=%d",
+      handle, seekOffset, seekFrom);
+
+   CHECK_INITED;
+
+   if (handle >= PI_FILE_SLOTS)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   if (fileInfo[handle].state != PI_FILE_OPENED)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
+
+   switch (seekFrom)
+   {
+      case PI_FROM_START:
+         whence = SEEK_SET;
+         break;
+
+      case PI_FROM_CURRENT:
+         whence = SEEK_CUR;
+         break;
+
+      case PI_FROM_END:
+         whence = SEEK_END;
+         break;
+
+      default:
+         SOFT_ERROR(PI_BAD_FILE_SEEK, "bad seek from (%d)", seekFrom);
+   }
+
+   s = lseek(fileInfo[handle].fd, seekOffset, whence);
+
+   if (s == -1)
+   {
+      DBG(DBG_USER, "seek failed with errno %d", errno);
+      return PI_BAD_FILE_SEEK;
+   }
+
+   return s;
+}
+
+int fileList(char *fpat,  char *buf, unsigned count)
+{
+   int len, bufpos;
+   glob_t pglob;
+   int i;
+
+   DBG(DBG_USER, "fpat=%s count=%d buf=%x", fpat, count, (unsigned)buf);
+
+   CHECK_INITED;
+
+   if (fileApprove(fpat) == PI_FILE_NONE)
+      SOFT_ERROR(PI_NO_FILE_ACCESS, "no permission to access file (%s)", fpat);
+
+   bufpos = 0;
+
+   if (glob(fpat, GLOB_MARK, NULL, &pglob) == 0)
+   {
+      for (i=0; i<pglob.gl_pathc; i++)
+      {
+         len = strlen(pglob.gl_pathv[i]);
+         if ((bufpos + len + 1) < count)
+         {
+            strcpy(buf+bufpos, pglob.gl_pathv[i]);
+            bufpos += len;
+            buf[bufpos++] = '\n';
+         }
+      }
+   }
+   else
+   {
+      bufpos = PI_NO_FILE_MATCH;
+   }
+
+   globfree(&pglob);
+
+   return bufpos;
+}
+
+
+
 /* ----------------------------------------------------------------------- */
 
 int gpioTime(unsigned timetype, int *seconds, int *micros)
index 13210a9c4757889330f9d34678934cc4646df83e..e9c3a5f4986025c23e27a794ec391b800ec9e7f3 100644 (file)
--- a/pigpio.h
+++ b/pigpio.h
@@ -31,7 +31,7 @@ For more information, please refer to <http://unlicense.org/>
 #include <stdint.h>
 #include <pthread.h>
 
-#define PIGPIO_VERSION 54
+#define PIGPIO_VERSION 55
 
 /*TEXT
 
@@ -39,9 +39,9 @@ pigpio is a C library for the Raspberry which allows control of the GPIO.
 
 *Features*
 
-o PWM on any of GPIO 0-31
+o hardware timed PWM on any of GPIO 0-31
 
-o servo pulses on any of GPIO 0-31
+o hardware timed servo pulses on any of GPIO 0-31
 
 o callbacks when any of GPIO 0-31 change state
 
@@ -198,6 +198,11 @@ gpioHardwarePWM            Start hardware PWM on supported GPIO
 gpioGlitchFilter           Set a glitch filter on a GPIO
 gpioNoiseFilter            Set a noise filter on a GPIO
 
+gpioGetPad                 Gets a pads drive strength
+gpioSetPad                 Sets a pads drive strength
+
+shell                      Executes a shell command
+
 SCRIPTS
 
 gpioStoreScript            Store a script
@@ -282,16 +287,25 @@ spiXfer                    Transfers bytes with a SPI device
 
 SERIAL
 
-serOpen                    Opens a serial device (/dev/tty*)
+serOpen                    Opens a serial device
 serClose                   Closes a serial device
 
-serWriteByte               Writes a byte to a serial device
 serReadByte                Reads a byte from a serial device
-serWrite                   Writes bytes to a serial device
+serWriteByte               Writes a byte to a serial device
 serRead                    Reads bytes from a serial device
+serWrite                   Writes bytes to a serial device
 
 serDataAvailable           Returns number of bytes ready to be read
 
+FILES
+
+fileOpen                   Opens a file
+fileClose                  Closes a file
+fileRead                   Reads bytes from a file
+fileWrite                  Writes bytes to a file
+fileSeek                   Seeks to a position within a file
+fileList                   List files which match a pattern
+
 CONFIGURATION
 
 gpioCfgBufferSize          Configure the GPIO sample buffer size
@@ -617,8 +631,9 @@ typedef void *(gpioThreadFunc_t) (void *);
 #define PI_WAVE_NOT_FOUND  9998 /* Transmitted wave not found. */
 #define PI_NO_TX_WAVE      9999 /* No wave being transmitted. */
 
-/* I2C, SPI, SER */
+/* Files, I2C, SPI, SER */
 
+#define PI_FILE_SLOTS 8
 #define PI_I2C_SLOTS 32
 #define PI_SPI_SLOTS 16
 #define PI_SER_SLOTS 8
@@ -773,6 +788,29 @@ typedef void *(gpioThreadFunc_t) (void *);
 #define EITHER_EDGE  2
 
 
+/* pads */
+
+#define PI_MAX_PAD 2
+
+#define PI_MIN_PAD_STRENGTH 1
+#define PI_MAX_PAD_STRENGTH 16
+
+/* files */
+
+#define PI_FILE_NONE   0
+#define PI_FILE_MIN    1
+#define PI_FILE_READ   1
+#define PI_FILE_WRITE  2
+#define PI_FILE_RW     3
+#define PI_FILE_APPEND 4
+#define PI_FILE_CREATE 8
+#define PI_FILE_TRUNC  16
+#define PI_FILE_MAX    31
+
+#define PI_FROM_START   0
+#define PI_FROM_CURRENT 1
+#define PI_FROM_END     2
+
 /*F*/
 int gpioInitialise(void);
 /*D
@@ -835,11 +873,11 @@ Returns 0 if OK, otherwise PI_BAD_GPIO or PI_BAD_MODE.
 Arduino style: pinMode.
 
 ...
-gpioSetMode(17, PI_INPUT);  // Set gpio17 as input.
+gpioSetMode(17, PI_INPUT);  // Set GPIO17 as input.
 
-gpioSetMode(18, PI_OUTPUT); // Set gpio18 as output.
+gpioSetMode(18, PI_OUTPUT); // Set GPIO18 as output.
 
-gpioSetMode(22,PI_ALT0);    // Set gpio22 to alternative mode 0.
+gpioSetMode(22,PI_ALT0);    // Set GPIO22 to alternative mode 0.
 ...
 D*/
 
@@ -858,7 +896,7 @@ Returns the GPIO mode if OK, otherwise PI_BAD_GPIO.
 ...
 if (gpioGetMode(17) != PI_ALT0)
 {
-   gpioSetMode(17, PI_ALT0);  // set gpio17 to ALT0
+   gpioSetMode(17, PI_ALT0);  // set GPIO17 to ALT0
 }
 ...
 D*/
@@ -900,7 +938,7 @@ Returns the GPIO level if OK, otherwise PI_BAD_GPIO.
 Arduino style: digitalRead.
 
 ...
-printf("gpio24 is level %d", gpioRead(24));
+printf("GPIO24 is level %d", gpioRead(24));
 ...
 D*/
 
@@ -922,7 +960,7 @@ If PWM or servo pulses are active on the GPIO they are switched off.
 Arduino style: digitalWrite
 
 ...
-gpioWrite(24, 1); // Set gpio24 high.
+gpioWrite(24, 1); // Set GPIO24 high.
 ...
 D*/
 
@@ -949,11 +987,11 @@ The [*gpioSetPWMrange*] function may be used to change the default
 range of 255.
 
 ...
-gpioPWM(17, 255); // Sets gpio17 full on.
+gpioPWM(17, 255); // Sets GPIO17 full on.
 
-gpioPWM(18, 128); // Sets gpio18 half on.
+gpioPWM(18, 128); // Sets GPIO18 half on.
 
-gpioPWM(23, 0);   // Sets gpio23 full off.
+gpioPWM(23, 0);   // Sets GPIO23 full off.
 ...
 D*/
 
@@ -1107,11 +1145,11 @@ sample
 . .
 
 ...
-gpioSetPWMfrequency(23, 0); // Set gpio23 to lowest frequency.
+gpioSetPWMfrequency(23, 0); // Set GPIO23 to lowest frequency.
 
-gpioSetPWMfrequency(24, 500); // Set gpio24 to 500Hz.
+gpioSetPWMfrequency(24, 500); // Set GPIO24 to 500Hz.
 
-gpioSetPWMfrequency(25, 100000); // Set gpio25 to highest frequency.
+gpioSetPWMfrequency(25, 100000); // Set GPIO25 to highest frequency.
 ...
 D*/
 
@@ -1136,7 +1174,7 @@ If hardware PWM is active on the GPIO the reported frequency
 will be that set by [*gpioHardwarePWM*].
 
 ...
-f = gpioGetPWMfrequency(23); // Get frequency used for gpio23.
+f = gpioGetPWMfrequency(23); // Get frequency used for GPIO23.
 ...
 D*/
 
@@ -1187,7 +1225,7 @@ Then set the PWM range using [*gpioSetPWMrange*] to 1E6/frequency.
 Doing this allows you to use units of microseconds when setting
 the servo pulsewidth.
 
-E.g. If you want to update a servo connected to gpio25 at 400Hz
+E.g. If you want to update a servo connected to GPIO25 at 400Hz
 
 . .
 gpioSetPWMfrequency(25, 400);
@@ -1474,11 +1512,13 @@ seqno: starts at 0 each time the handle is opened and then increments
 by one for each report.
 
 flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
-If bit 5 is set (PI_NTFY_FLAGS_WDOG) then bits 0-4 of the flags
-indicate a GPIO which has had a watchdog timeout; if bit 6 is set
-(PI_NTFY_FLAGS_ALIVE) this indicates a keep alive signal on the
-pipe/socket and is sent once a minute in the absence of other
-notification activity.
+
+PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+indicate a GPIO which has had a watchdog timeout.
+
+PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+signal on the pipe/socket and is sent once a minute in the absence
+of other notification activity.
 
 tick: the number of microseconds since system boot.  It wraps around
 after 1h12m.
@@ -2011,7 +2051,7 @@ int gpioSerialReadInvert(unsigned user_gpio, unsigned invert);
 /*D
 This function configures the level logic for bit bang serial reads.
 
-Pass PI_BB_SER_INVERT to invert the serial logic.  Pass PI_BB_SER_NORMAL for
+Use PI_BB_SER_INVERT to invert the serial logic and PI_BB_SER_NORMAL for
 normal logic.  Default is PI_BB_SER_NORMAL.
 
 . .
@@ -2798,10 +2838,11 @@ D*/
 int serOpen(char *sertty, unsigned baud, unsigned serFlags);
 /*D
 This function opens a serial device at a specified baud rate
-with specified flags.
+and with specified flags.  The device name must start with
+/dev/tty or /dev/serial.
 
 . .
-  sertty: the serial device to open, /dev/tty*
+  sertty: the serial device to open
     baud: the baud rate in bits per second, see below
 serFlags: 0
 . .
@@ -2879,13 +2920,13 @@ This function reads up count bytes from the the serial port
 associated with handle and writes them to buf.
 
 . .
-handle: >=0, as returned by a call to serial_open
+handle: >=0, as returned by a call to [*serOpen*]
    buf: an array to receive the read data
  count: the maximum number of bytes to read
 . .
 
 Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
-PI_BAD_PARAM, PI_SER_READ_NO_DATA, or PI_SER_WRITE_FAILED.
+PI_BAD_PARAM, or PI_SER_READ_NO_DATA.
 D*/
 
 
@@ -3631,6 +3672,358 @@ Returns the pigpio version.
 D*/
 
 
+/*F*/
+int gpioGetPad(unsigned pad);
+/*D
+This function returns the pad drive strength in mA.
+
+. .
+pad: 0-2, the pad to get
+. .
+
+Returns the pad drive strength if OK, otherwise PI_BAD_PAD.
+
+Pad @ GPIO
+0   @ 0-27
+1   @ 28-45
+2   @ 46-53
+
+...
+strength = gpioGetPad(1); // get pad 1 strength
+...
+D*/
+
+
+/*F*/
+int gpioSetPad(unsigned pad, unsigned padStrength);
+/*D
+This function sets the pad drive strength in mA.
+
+. .
+        pad: 0-2, the pad to set
+padStrength: 1-16 mA
+. .
+
+Returns 0 if OK, otherwise PI_BAD_PAD, or PI_BAD_STRENGTH.
+
+Pad @ GPIO
+0   @ 0-27
+1   @ 28-45
+2   @ 46-53
+
+...
+gpioSetPad(0, 16); // set pad 0 strength to 16 mA
+...
+D*/
+
+
+/*F*/
+int shell(char *scriptName, char *scriptString);
+/*D
+This function uses the system call to execute a shell script
+with the given string as its parameter.
+
+. .
+  scriptName: the name of the script, only alphanumeric characters,
+              '-' and '_' are allowed in the name
+scriptString: the string to pass to the script
+. .
+
+The exit status of the system call is returned if OK, otherwise
+PI_BAD_SHELL_STATUS.
+
+scriptName must exist in /opt/pigpio/cgi and must be executable.
+
+The returned exit status is normally 256 times that set by the
+shell script exit function.  If the script can't be found 32512 will
+be returned.
+
+The following table gives some example returned statuses.
+
+Script exit status @ Returned system call status
+1                  @ 256
+5                  @ 1280
+10                 @ 2560
+200                @ 51200
+script not found   @ 32512
+
+...
+// pass two parameters, hello and world
+status = shell("scr1", "hello world");
+
+// pass three parameters, hello, string with spaces, and world
+status = shell("scr1", "hello 'string with spaces' world");
+
+// pass one parameter, hello string with spaces world
+status = shell("scr1", "\"hello string with spaces world\"");
+...
+D*/
+
+#pragma GCC diagnostic push
+
+#pragma GCC diagnostic ignored "-Wcomment"
+
+/*F*/
+int fileOpen(char *file, unsigned mode);
+/*D
+This function returns a handle to a file opened in a specified mode.
+
+. .
+file: the file to open
+mode: the file open mode
+. .
+
+Returns a handle (>=0) if OK, otherwise PI_NO_HANDLE, PI_NO_FILE_ACCESS,
+PI_BAD_FILE_MODE, PI_FILE_OPEN_FAILED, or PI_FILE_IS_A_DIR.
+
+File
+
+A file may only be opened if permission is granted by an entry in
+/opt/pigpio/access.  This is intended to allow remote access to files
+in a more or less controlled manner.
+
+Each entry in /opt/pigpio/access takes the form of a file path
+which may contain wildcards followed by a single letter permission.
+The permission may be R for read, W for write, U for read/write,
+and N for no access.
+
+Where more than one entry matches a file the most specific rule
+applies.  If no entry matches a file then access is denied.
+
+Suppose /opt/pigpio/access contains the following entries
+
+. .
+/home/* n
+/home/pi/shared/dir_1/* w
+/home/pi/shared/dir_2/* r
+/home/pi/shared/dir_3/* u
+/home/pi/shared/dir_1/file.txt n
+. .
+
+Files may be written in directory dir_1 with the exception
+of file.txt.
+
+Files may be read in directory dir_2.
+
+Files may be read and written in directory dir_3.
+
+If a directory allows read, write, or read/write access then files may
+be created in that directory.
+
+In an attempt to prevent risky permissions the following paths are
+ignored in /opt/pigpio/access.
+
+. .
+a path containing ..
+a path containing only wildcards (*?)
+a path containing less than two non-wildcard parts
+. .
+
+Mode
+
+The mode may have the following values.
+
+Macro         @ Value @ Meaning
+PI_FILE_READ  @   1   @ open file for reading
+PI_FILE_WRITE @   2   @ open file for writing
+PI_FILE_RW    @   3   @ open file for reading and writing
+
+The following values may be or'd into the mode.
+
+Macro          @ Value @ Meaning
+PI_FILE_APPEND @ 4     @ Writes append data to the end of the file
+PI_FILE_CREATE @ 8     @ The file is created if it doesn't exist
+PI_FILE_TRUNC  @ 16    @ The file is truncated
+
+Newly created files are owned by root with permissions owner read and write.
+
+...
+#include <stdio.h>
+#include <pigpio.h>
+
+int main(int argc, char *argv[])
+{
+   int handle, c;
+   char buf[60000];
+
+   if (gpioInitialise() < 0) return 1;
+
+   // assumes /opt/pigpio/access contains the following line
+   // /ram/*.c r
+
+   handle = fileOpen("/ram/pigpio.c", PI_FILE_READ);
+
+   if (handle >= 0)
+   {
+      while ((c=fileRead(handle, buf, sizeof(buf)-1)))
+      {
+         buf[c] = 0;
+         printf("%s", buf);
+      }
+
+      fileClose(handle);
+   }
+
+   gpioTerminate();
+}
+...
+D*/
+
+#pragma GCC diagnostic pop
+
+/*F*/
+int fileClose(unsigned handle);
+/*D
+This function closes the file associated with handle.
+
+. .
+handle: >=0, as returned by a call to [*fileOpen*]
+. .
+
+Returns 0 if OK, otherwise PI_BAD_HANDLE.
+
+...
+fileClose(h);
+...
+D*/
+
+
+/*F*/
+int fileWrite(unsigned handle, char *buf, unsigned count);
+/*D
+This function writes count bytes from buf to the the file
+associated with handle.
+
+. .
+handle: >=0, as returned by a call to [*fileOpen*]
+   buf: the array of bytes to write
+ count: the number of bytes to write
+. .
+
+Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM,
+PI_FILE_NOT_WOPEN, or PI_BAD_FILE_WRITE.
+
+...
+status = fileWrite(h, buf, count);
+if (status == 0)
+{
+   // okay
+}
+else
+{
+   // error
+}
+...
+D*/
+
+
+/*F*/
+int fileRead(unsigned handle, char *buf, unsigned count);
+/*D
+This function reads up to count bytes from the the file
+associated with handle and writes them to buf.
+
+. .
+handle: >=0, as returned by a call to [*fileOpen*]
+   buf: an array to receive the read data
+ count: the maximum number of bytes to read
+. .
+
+Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, PI_FILE_NOT_ROPEN, or PI_BAD_FILE_WRITE.
+
+...
+if (fileRead(h, buf, sizeof(buf)) > 0)
+{
+   // process read data
+}
+...
+D*/
+
+
+/*F*/
+int fileSeek(unsigned handle, int32_t seekOffset, int seekFrom);
+/*D
+This function seeks to a position within the file associated
+with handle.
+
+. .
+    handle: >=0, as returned by a call to [*fileOpen*]
+seekOffset: the number of bytes to move.  Positive offsets
+            move forward, negative offsets backwards.
+  seekFrom: one of PI_FROM_START (0), PI_FROM_CURRENT (1),
+            or PI_FROM_END (2)
+. .
+
+Returns the new byte position within the file (>=0) if OK, otherwise PI_BAD_HANDLE, or PI_BAD_FILE_SEEK.
+
+...
+fileSeek(0, 20, PI_FROM_START); // Seek to start plus 20
+
+size = fileSeek(0, 0, PI_FROM_END); // Seek to end, return size
+
+pos = fileSeek(0, 0, PI_FROM_CURRENT); // Return current position
+...
+D*/
+
+#pragma GCC diagnostic push
+
+#pragma GCC diagnostic ignored "-Wcomment"
+
+/*F*/
+int fileList(char *fpat,  char *buf, unsigned count);
+/*D
+This function returns a list of files which match a pattern.  The
+pattern may contain wildcards.
+
+. .
+ fpat: file pattern to match
+  buf: an array to receive the matching file names
+count: the maximum number of bytes to read
+. .
+
+Returns the number of returned bytes if OK, otherwise PI_NO_FILE_ACCESS,
+or PI_NO_FILE_MATCH.
+
+The pattern must match an entry in /opt/pigpio/access.  The pattern
+may contain wildcards.  See [*fileOpen*].
+
+NOTE
+
+The returned value is not the number of files, it is the number
+of bytes in the buffer.  The file names are separated by newline
+characters.
+
+...
+#include <stdio.h>
+#include <pigpio.h>
+
+int main(int argc, char *argv[])
+{
+   int c;
+   char buf[1000];
+
+   if (gpioInitialise() < 0) return 1;
+
+   // assumes /opt/pigpio/access contains the following line
+   // /ram/*.c r
+
+   c = fileList("/ram/p*.c", buf, sizeof(buf));
+
+   if (c >= 0)
+   {
+      // terminate string
+      buf[c] = 0;
+      printf("%s", buf);
+   }
+
+   gpioTerminate();
+}
+...
+D*/
+
+#pragma GCC diagnostic pop
+
+
 /*F*/
 int gpioCfgBufferSize(unsigned cfgMillis);
 /*D
@@ -4219,7 +4612,6 @@ PI_HW_CLK_MAX_FREQ 250000000
 . .
 
 count::
-
 The number of bytes to be transferred in an I2C, SPI, or Serial
 command.
 
@@ -4251,7 +4643,7 @@ The number may vary between 0 and range (default 255) where
 0 is off and range is fully on.
 
 edge::0-2
-The type of GPIO edge to generate an intrrupt.  See[*gpioSetISRFunc*],
+The type of GPIO edge to generate an intrrupt.  See [*gpioSetISRFunc*],
 and [*gpioSetISRFuncEx*].
 
 . .
@@ -4264,6 +4656,14 @@ f::
 
 A function.
 
+*file::
+A full file path.  To be accessible the path must match an entry in
+/opt/pigpio/access.
+
+*fpat::
+A file path which may contain wildcards.  To be accessible the path
+must match an entry in /opt/pigpio/access.
+
 frequency::>=0
 
 The number of times a GPIO is swiched on and off per second.  This
@@ -4275,11 +4675,11 @@ gpio::
 
 A Broadcom numbered GPIO, in the range 0-53.
 
-There  are 54 General Purpose Input Outputs (GPIO) named gpio0 through
-gpio53.
+There  are 54 General Purpose Input Outputs (GPIO) named GPIO0 through
+GPIO53.
 
-They are split into two  banks.   Bank  1  consists  of  gpio0  through
-gpio31.  Bank 2 consists of gpio32 through gpio53.
+They are split into two  banks.   Bank  1  consists  of  GPIO0  through
+GPIO31.  Bank 2 consists of GPIO32 through GPIO53.
 
 All the GPIO which are safe for the user to read and write are in
 bank 1.  Not all GPIO in bank 1 are safe though.  Type 1 boards
@@ -4403,12 +4803,8 @@ One of
 
 handle::>=0
 
-A number referencing an object opened by one of
-
-[*i2cOpen*] 
-[*gpioNotifyOpen*] 
-[*serOpen*] 
-[*spiOpen*]
+A number referencing an object opened by one of [*fileOpen*],
+[*gpioNotifyOpen*], [*i2cOpen*], [*serOpen*], [*spiOpen*].
 
 i2cAddr:: 0-0x7F
 The address of a device on the I2C bus.
@@ -4440,6 +4836,9 @@ The number of bytes of data in a buffer.
 int::
 A whole number, negative or positive.
 
+int32_t::
+A 32-bit signed value.
+
 invert::
 A flag used to set normal or inverted bit bang serial data level logic.
 
@@ -4491,9 +4890,9 @@ millis::
 
 A value representing milliseconds.
 
-mode::0-7
+mode::
 
-The operational mode of a GPIO, normally INPUT or OUTPUT.
+1. The operational mode of a GPIO, normally INPUT or OUTPUT.
 
 . .
 PI_INPUT 0
@@ -4506,6 +4905,22 @@ PI_ALT4 3
 PI_ALT5 2
 . .
 
+2. A file open mode.
+
+. .
+PI_FILE_READ  1
+PI_FILE_WRITE 2
+PI_FILE_RW    3
+. .
+
+The following values can be or'd into the mode.
+
+. .
+PI_FILE_APPEND 4
+PI_FILE_CREATE 8
+PI_FILE_TRUNC  16
+. .
+
 numBits::
 
 The number of bits stored in a buffer.
@@ -4534,6 +4949,18 @@ A buffer used to return data from a function.
 outLen::
 The size in bytes of an output buffer.
 
+pad:: 0-2
+A set of GPIO which share common drivers.
+
+Pad @ GPIO
+0   @ 0-27
+1   @ 28-45
+2   @ 46-53
+
+padStrength:: 1-16
+The mA which may be drawn from each GPIO whilst still guaranteeing the
+high and low levels.
+
 *param::
 An array of script parameters.
 
@@ -4680,19 +5107,22 @@ The maximum number of bytes a user customised function should return.
 A pointer to a buffer to receive data.
 
 SCL::
-
 The user GPIO to use for the clock when bit banging I2C.
 
 *script::
-
 A pointer to the text of a script.
 
 script_id::
-
 An id of a stored script as returned by [*gpioStoreScript*].
 
-SDA::
+*scriptName::
+The name of a [*shell*] script to be executed.  The script must be present in
+/opt/pigpio/cgi and must have execute permission.
 
+*scriptString::
+The string to be passed to a [*shell*] script to be executed.
+
+SDA::
 The user GPIO to use for data when bit banging I2C.
 
 secondaryChannel:: 0-6
@@ -4705,11 +5135,21 @@ A pointer to a uint32_t to store the second component of
 a returned time.
 
 seconds::
-
 The number of seconds.
 
-*segs::
+seekFrom::
 
+. .
+PI_FROM_START   0
+PI_FROM_CURRENT 1
+PI_FROM_END     2
+. .
+
+seekOffset::
+The number of bytes to move forward (positive) or backwards (negative)
+from the seek position (start, current, or end of file).
+
+*segs::
 An array of segments which make up a combined I2C transaction.
 
 serFlags::
@@ -4830,7 +5270,6 @@ user_gpio::
 See [*gpio*].
 
 *userdata::
-
 A pointer to arbitrary user data.  This may be used to identify the instance.
 
 You must ensure that the pointer is in scope at the time it is processed.  If
@@ -4999,6 +5438,18 @@ PARAMS*/
 #define PI_CMD_WVTXM 100
 #define PI_CMD_WVTAT 101
 
+#define PI_CMD_PADS  102
+#define PI_CMD_PADG  103
+
+#define PI_CMD_FO    104
+#define PI_CMD_FC    105
+#define PI_CMD_FR    106
+#define PI_CMD_FW    107
+#define PI_CMD_FS    108
+#define PI_CMD_FL    109
+
+#define PI_CMD_SHELL 110
+
 /*DEF_E*/
 
 /*
@@ -5099,7 +5550,7 @@ after this command is issued.
 #define PI_BAD_WAVE_BAUD    -35 // baud rate not 50-250K(RX)/50-1M(TX)
 #define PI_TOO_MANY_PULSES  -36 // waveform has too many pulses
 #define PI_TOO_MANY_CHARS   -37 // waveform has too many chars
-#define PI_NOT_SERIAL_GPIO  -38 // no bit bang serial read in progress on GPIO
+#define PI_NOT_SERIAL_GPIO  -38 // no bit bang serial read on GPIO
 #define PI_BAD_SERIAL_STRUC -39 // bad (null) serial structure parameter
 #define PI_BAD_SERIAL_BUF   -40 // bad (null) serial buf parameter
 #define PI_NOT_PERMITTED    -41 // GPIO operation not permitted
@@ -5186,8 +5637,23 @@ after this command is issued.
 #define PI_BAD_SER_INVERT  -121 // bit bang serial invert not 0 or 1
 #define PI_BAD_EDGE        -122 // bad ISR edge value, not 0-2
 #define PI_BAD_ISR_INIT    -123 // bad ISR initialisation
-#define PI_BAD_FOREVER     -124 // loop forever must be last chain command
+#define PI_BAD_FOREVER     -124 // loop forever must be last command
 #define PI_BAD_FILTER      -125 // bad filter parameter
+#define PI_BAD_PAD         -126 // bad pad number
+#define PI_BAD_STRENGTH    -127 // bad pad drive strength
+#define PI_FIL_OPEN_FAILED -128 // file open failed
+#define PI_BAD_FILE_MODE   -129 // bad file mode
+#define PI_BAD_FILE_FLAG   -130 // bad file flag
+#define PI_BAD_FILE_READ   -131 // bad file read
+#define PI_BAD_FILE_WRITE  -132 // bad file write
+#define PI_FILE_NOT_ROPEN  -133 // file not open for read
+#define PI_FILE_NOT_WOPEN  -134 // file not open for write
+#define PI_BAD_FILE_SEEK   -135 // bad file seek
+#define PI_NO_FILE_MATCH   -136 // no files match pattern
+#define PI_NO_FILE_ACCESS  -137 // no permission to access file
+#define PI_FILE_IS_A_DIR   -138 // file is a directory
+#define PI_BAD_SHELL_STATUS -139 // bad shell return status
+#define PI_BAD_SCRIPT_NAME -140 // bad script name
 
 #define PI_PIGIF_ERR_0    -2000
 #define PI_PIGIF_ERR_99   -2099
index 55bdc75000e419c93b2d61575cac62b23e9f704b..0fdddbab42786506729312c6caa867485afc1cbd 100644 (file)
--- a/pigpio.py
+++ b/pigpio.py
@@ -11,9 +11,9 @@ o the pigpio Python module can run on Windows, Macs, or Linux
 
 o controls one or more Pi's
 
-o independent PWM on any of GPIO 0-31 simultaneously
+o hardware timed PWM on any of GPIO 0-31
 
-o independent servo pulses on any of GPIO 0-31 simultaneously
+o hardware timed servo pulses on any of GPIO 0-31
 
 o callbacks when any of GPIO 0-31 change state
 
@@ -159,6 +159,11 @@ hardware_PWM              Start hardware PWM on supported GPIO
 set_glitch_filter         Set a glitch filter on a GPIO
 set_noise_filter          Set a noise filter on a GPIO
 
+get_pad_strength          Gets a pads drive strength
+set_pad_strength          Sets a pads drive strength
+
+shell                     Executes a shell command
+
 Scripts
 
 store_script              Store a script
@@ -235,7 +240,7 @@ spi_xfer                  Transfers bytes with a SPI device
 
 Serial
 
-serial_open               Opens a serial device (/dev/tty*)
+serial_open               Opens a serial device
 serial_close              Closes a serial device
 
 serial_read               Reads bytes from a serial device
@@ -246,7 +251,16 @@ serial_write_byte         Writes a byte to a serial device
 
 serial_data_available     Returns number of bytes ready to be read
 
-CUSTOM
+Files
+
+file_open                 Opens a file
+file_close                Closes a file
+file_read                 Reads bytes from a file
+file_write                Writes bytes to a file
+file_seek                 Seeks to a position within a file
+file_list                 List files which match a pattern
+
+Custom
 
 custom_1                  User custom function 1
 custom_2                  User custom function 2
@@ -270,7 +284,7 @@ import threading
 import os
 import atexit
 
-VERSION = "1.31"
+VERSION = "1.32"
 
 exceptions = True
 
@@ -333,6 +347,18 @@ WAVE_MODE_REPEAT_SYNC  =3
 WAVE_NOT_FOUND = 9998 # Transmitted wave not found.
 NO_TX_WAVE     = 9999 # No wave being transmitted.
 
+FILE_READ=1
+FILE_WRITE=2
+FILE_RW=3
+
+FILE_APPEND=4
+FILE_CREATE=8
+FILE_TRUNC=16
+
+FROM_START=0
+FROM_CURRENT=1
+FROM_END=2
+
 # pigpio command numbers
 
 _PI_CMD_MODES= 0
@@ -460,6 +486,17 @@ _PI_CMD_FN   =98
 _PI_CMD_WVTXM=100
 _PI_CMD_WVTAT=101
 
+_PI_CMD_PADS =102
+_PI_CMD_PADG =103
+
+_PI_CMD_FO   =104
+_PI_CMD_FC   =105
+_PI_CMD_FR   =106
+_PI_CMD_FW   =107
+_PI_CMD_FS   =108
+_PI_CMD_FL   =109
+_PI_CMD_SHELL=110
+
 # pigpio error numbers
 
 _PI_INIT_FAILED     =-1
@@ -588,7 +625,21 @@ _PI_BAD_EDGE        =-122
 _PI_BAD_ISR_INIT    =-123
 PI_BAD_FOREVER      =-124
 PI_BAD_FILTER       =-125
-
+PI_BAD_PAD          =-126
+PI_BAD_STRENGTH     =-127
+PI_FIL_OPEN_FAILED  =-128
+PI_BAD_FILE_MODE    =-129
+PI_BAD_FILE_FLAG    =-130
+PI_BAD_FILE_READ    =-131
+PI_BAD_FILE_WRITE   =-132
+PI_FILE_NOT_ROPEN   =-133
+PI_FILE_NOT_WOPEN   =-134
+PI_BAD_FILE_SEEK    =-135
+PI_NO_FILE_MATCH    =-136
+PI_NO_FILE_ACCESS   =-137
+PI_FILE_IS_A_DIR    =-138
+PI_BAD_SHELL_STATUS =-139
+PI_BAD_SCRIPT_NAME  =-140
 
 # pigpio error text
 
@@ -716,6 +767,21 @@ _errors=[
    [_PI_BAD_ISR_INIT     , "bad ISR initialisation"],
    [PI_BAD_FOREVER       , "loop forever must be last chain command"],
    [PI_BAD_FILTER        , "bad filter parameter"],
+   [PI_BAD_PAD           , "bad pad number"],
+   [PI_BAD_STRENGTH      , "bad pad drive strength"],
+   [PI_FIL_OPEN_FAILED   , "file open failed"],
+   [PI_BAD_FILE_MODE     , "bad file mode"],
+   [PI_BAD_FILE_FLAG     , "bad file flag"],
+   [PI_BAD_FILE_READ     , "bad file read"],
+   [PI_BAD_FILE_WRITE    , "bad file write"],
+   [PI_FILE_NOT_ROPEN    , "file not open for read"],
+   [PI_FILE_NOT_WOPEN    , "file not open for write"],
+   [PI_BAD_FILE_SEEK     , "bad file seek"],
+   [PI_NO_FILE_MATCH     , "no files match pattern"],
+   [PI_NO_FILE_ACCESS    , "no permission to access file"],
+   [PI_FILE_IS_A_DIR     , "file is a directory"],
+   [PI_BAD_SHELL_STATUS  , "bad shell return status"],
+   [PI_BAD_SCRIPT_NAME   , "bad script name"],
 
 ]
 
@@ -1396,8 +1462,8 @@ class pi():
       Notifications have the following structure.
 
       . .
-      I seqno
-      I flags
+      H seqno
+      H flags
       I tick
       I level
       . .
@@ -1406,11 +1472,14 @@ class pi():
       increments by one for each report.
 
       flags: two flags are defined, PI_NTFY_FLAGS_WDOG and
-      PI_NTFY_FLAGS_ALIVE.  If bit 5 is set (PI_NTFY_FLAGS_WDOG)
-      then bits 0-4 of the flags indicate a GPIO which has had a
-      watchdog timeout; if bit 6 is set (PI_NTFY_FLAGS_ALIVE) this
-      indicates a keep alive signal on the pipe/socket and is sent
-      once a minute in the absence of other notification activity.
+      PI_NTFY_FLAGS_ALIVE.
+
+      PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the
+      flags indicate a GPIO which has had a watchdog timeout.
+
+      PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep
+      alive signal on the pipe/socket and is sent once a minute
+      in the absence of other notification activity.
 
       tick: the number of microseconds since system boot.  It wraps
       around after 1h12m.
@@ -3215,7 +3284,8 @@ class pi():
    def serial_open(self, tty, baud, ser_flags=0):
       """
       Returns a handle for the serial tty device opened
-      at baud bits per second.
+      at baud bits per second.  The device name must start
+      with /dev/tty or /dev/serial.
 
             tty:= the serial device to open.
            baud:= baud rate in bits per second, see below.
@@ -3234,6 +3304,8 @@ class pi():
       h1 = pi.serial_open("/dev/ttyAMA0", 300)
 
       h2 = pi.serial_open("/dev/ttyUSB1", 19200, 0)
+
+      h3 = pi.serial_open("/dev/serial0", 9600)
       ...
       """
       # I p1 baud
@@ -3646,6 +3718,7 @@ class pi():
       """
       return _u2i(_pigpio_command(self.sl, _PI_CMD_SLRI, user_gpio, invert))
 
+
    def custom_1(self, arg1=0, arg2=0, argx=[]):
       """
       Calls a pigpio function customised by the user.
@@ -3721,6 +3794,360 @@ class pi():
       self.sl.l.release()
       return bytes, data
 
+   def get_pad_strength(self, pad):
+      """
+      This function returns the pad drive strength in mA.
+
+      pad:= 0-2, the pad to get.
+
+      Returns the pad drive strength if OK, otherwise PI_BAD_PAD.
+
+      Pad @ GPIO
+      0   @ 0-27
+      1   @ 28-45
+      2   @ 46-53
+
+      ...
+      strength = pi.get_pad_strength(0) # Get pad 0 strength.
+      ...
+      """
+      return _u2i(_pigpio_command(self.sl, _PI_CMD_PADG, pad, 0))
+
+   def set_pad_strength(self, pad, pad_strength):
+      """
+      This function sets the pad drive strength in mA.
+
+
+               pad:= 0-2, the pad to set.
+      pad_strength:= 1-16 mA.
+
+      Returns 0 if OK, otherwise PI_BAD_PAD, or PI_BAD_STRENGTH.
+
+      Pad @ GPIO
+      0   @ 0-27
+      1   @ 28-45
+      2   @ 46-53
+
+      ...
+      pi.set_pad_strength(2, 14) # Set pad 2 to 14 mA.
+      ...
+      """
+      return _u2i(_pigpio_command(self.sl, _PI_CMD_PADS, pad, pad_strength))
+
+
+   def file_open(self, file_name, file_mode):
+      """
+      This function returns a handle to a file opened in a specified mode.
+
+      file_name:= the file to open.
+      file_mode:= the file open mode.
+
+      Returns a handle (>=0) if OK, otherwise PI_NO_HANDLE, PI_NO_FILE_ACCESS,
+      PI_BAD_FILE_MODE, PI_FILE_OPEN_FAILED, or PI_FILE_IS_A_DIR.
+
+      ...
+      h = pi.file_open("/home/pi/shared/dir_3/file.txt",
+              pigpio.FILE_WRITE | pigpio.FILE_CREATE)
+
+      pi.file_write(h, "Hello world")
+
+      pi.file_close(h)
+      ...
+
+      File
+
+      A file may only be opened if permission is granted by an entry in
+      /opt/pigpio/access.  This is intended to allow remote access to files
+      in a more or less controlled manner.
+
+      Each entry in /opt/pigpio/access takes the form of a file path
+      which may contain wildcards followed by a single letter permission.
+      The permission may be R for read, W for write, U for read/write,
+      and N for no access.
+
+      Where more than one entry matches a file the most specific rule
+      applies.  If no entry matches a file then access is denied.
+
+      Suppose /opt/pigpio/access contains the following entries
+
+      . .
+      /home/* n
+      /home/pi/shared/dir_1/* w
+      /home/pi/shared/dir_2/* r
+      /home/pi/shared/dir_3/* u
+      /home/pi/shared/dir_1/file.txt n
+      . .
+
+      Files may be written in directory dir_1 with the exception
+      of file.txt.
+
+      Files may be read in directory dir_2.
+
+      Files may be read and written in directory dir_3.
+
+      If a directory allows read, write, or read/write access then files
+      may be created in that directory.
+
+      In an attempt to prevent risky permissions the following paths are
+      ignored in /opt/pigpio/access.
+
+      . .
+      a path containing ..
+      a path containing only wildcards (*?)
+      a path containing less than two non-wildcard parts
+      . .
+
+      Mode
+
+      The mode may have the following values.
+
+      Constant   @ Value @ Meaning
+      FILE_READ  @   1   @ open file for reading
+      FILE_WRITE @   2   @ open file for writing
+      FILE_RW    @   3   @ open file for reading and writing
+
+      The following values may be or'd into the mode.
+
+      Name        @ Value @ Meaning
+      FILE_APPEND @ 4     @ All writes append data to the end of the file
+      FILE_CREATE @ 8     @ The file is created if it doesn't exist
+      FILE_TRUNC  @ 16    @ The file is truncated
+
+      Newly created files are owned by root with permissions owner
+      read and write.
+
+      ...
+      #!/usr/bin/env python
+
+      import pigpio
+
+      pi = pigpio.pi()
+
+      if not pi.connected:
+         exit()
+
+      # Assumes /opt/pigpio/access contains the following line.
+      # /ram/*.c r
+
+      handle = pi.file_open("/ram/pigpio.c", pigpio.FILE_READ)
+
+      done = False
+
+      while not done:
+         c, d = pi.file_read(handle, 60000)
+         if c > 0:
+            print(d)
+         else:
+            done = True
+
+      pi.file_close(handle)
+
+      pi.stop()
+      ...
+      """
+      # I p1 file_mode
+      # I p2 0
+      # I p3 len
+      ## extension ##
+      # s len data bytes
+      return _u2i(_pigpio_command_ext(
+         self.sl, _PI_CMD_FO, file_mode, 0, len(file_name), [file_name]))
+
+   def file_close(self, handle):
+      """
+      Closes the file associated with handle.
+
+      handle:= >=0 (as returned by a prior call to [*file_open*]).
+
+      ...
+      pi.file_close(handle)
+      ...
+      """
+      return _u2i(_pigpio_command(self.sl, _PI_CMD_FC, handle, 0))
+
+   def file_read(self, handle, count):
+      """
+      Reads up to count bytes from the file associated with handle.
+
+      handle:= >=0 (as returned by a prior call to [*file_open*]).
+       count:= >0, the number of bytes to read.
+
+      The returned value is a tuple of the number of bytes read and a
+      bytearray containing the bytes.  If there was an error the
+      number of bytes read will be less than zero (and will contain
+      the error code).
+
+      ...
+      (b, d) = pi.file_read(h2, 100)
+      if b > 0:
+         # process read data
+      ...
+      """
+      # Don't raise exception.  Must release lock.
+      bytes = u2i(
+         _pigpio_command(self.sl, _PI_CMD_FR, handle, count, False))
+      if bytes > 0:
+         data = self._rxbuf(bytes)
+      else:
+         data = ""
+      self.sl.l.release()
+      return bytes, data
+
+   def file_write(self, handle, data):
+      """
+      Writes the data bytes to the file associated with handle.
+
+      handle:= >=0 (as returned by a prior call to [*file_open*]).
+        data:= the bytes to write.
+
+      ...
+      pi.file_write(h1, b'\\x02\\x03\\x04')
+
+      pi.file_write(h2, b'help')
+
+      pi.file_write(h2, "hello")
+
+      pi.file_write(h1, [2, 3, 4])
+      ...
+      """
+      # I p1 handle
+      # I p2 0
+      # I p3 len
+      ## extension ##
+      # s len data bytes
+
+      return _u2i(_pigpio_command_ext(
+         self.sl, _PI_CMD_FW, handle, 0, len(data), [data]))
+
+   def file_seek(self, handle, seek_offset, seek_from):
+      """
+      Seeks to a position relative to the start, current position,
+      or end of the file.  Returns the new position.
+
+           handle:= >=0 (as returned by a prior call to [*file_open*]).
+      seek_offset:= byte offset.
+        seek_from:= FROM_START, FROM_CURRENT, or FROM_END.
+
+      ...
+      new_pos = pi.file_seek(h, 100, pigpio.FROM_START)
+
+      cur_pos = pi.file_seek(h, 0, pigpio.FROM_CURRENT)
+
+      file_size = pi.file_seek(h, 0, pigpio.FROM_END)
+      ...
+      """
+      # I p1 handle
+      # I p2 seek_offset
+      # I p3 4
+      ## extension ##
+      # I seek_from
+      extents = [struct.pack("I", seek_from)]
+      return _u2i(_pigpio_command_ext(
+         self.sl, _PI_CMD_FS, handle, seek_offset, 4, extents))
+
+   def file_list(self, fpattern):
+      """
+      Returns a list of files which match a pattern.
+
+      fpattern:= file pattern to match.
+
+      Returns the number of returned bytes if OK, otherwise
+      PI_NO_FILE_ACCESS, or PI_NO_FILE_MATCH.
+
+      The pattern must match an entry in /opt/pigpio/access.  The
+      pattern may contain wildcards.  See [*file_open*].
+
+      NOTE
+
+      The returned value is not the number of files, it is the number
+      of bytes in the buffer.  The file names are separated by newline
+      characters.
+
+      ...
+      #!/usr/bin/env python
+
+      import pigpio
+
+      pi = pigpio.pi()
+
+      if not pi.connected:
+         exit()
+
+      # Assumes /opt/pigpio/access contains the following line.
+      # /ram/*.c r
+
+      c, d = pi.file_list("/ram/p*.c")
+      if c > 0:
+         print(d)
+
+      pi.stop()
+      ...
+      """
+      # I p1 60000
+      # I p2 0
+      # I p3 len
+      ## extension ##
+      # s len data bytes
+
+      # Don't raise exception.  Must release lock.
+      bytes = u2i(_pigpio_command_ext(
+         self.sl, _PI_CMD_FL, 60000, 0, len(fpattern), [fpattern], False))
+      if bytes > 0:
+         data = self._rxbuf(bytes)
+      else:
+         data = ""
+      self.sl.l.release()
+      return bytes, data
+
+   def shell(self, shellscr, pstring=""):
+      """
+      This function uses the system call to execute a shell script
+      with the given string as its parameter.
+
+      shellscr:= the name of the script, only alphanumerics,
+                    '-' and '_' are allowed in the name
+      pstring := the parameter string to pass to the script
+
+      The exit status of the system call is returned if OK,
+      otherwise PI_BAD_SHELL_STATUS.
+
+      [*shellscr*] must exist in /opt/pigpio/cgi and must be executable.
+
+      The returned exit status is normally 256 times that set by
+      the shell script exit function.  If the script can't be
+      found 32512 will be returned.
+
+      The following table gives some example returned statuses.
+
+      Script exit status @ Returned system call status
+      1                  @ 256
+      5                  @ 1280
+      10                 @ 2560
+      200                @ 51200
+      script not found   @ 32512
+
+      ...
+      // pass two parameters, hello and world
+      status = pi.shell("scr1", "hello world");
+
+      // pass three parameters, hello, string with spaces, and world
+      status = pi.shell("scr1", "hello 'string with spaces' world");
+
+      // pass one parameter, hello string with spaces world
+      status = pi.shell("scr1", "\\"hello string with spaces world\\"");
+      ...
+      """
+      # I p1 len(shellscr)
+      # I p2 0
+      # I p3 len(shellscr)+len(pstring)+1
+      ## extension ##
+      # s len data bytes
+
+      ls = len(shellscr)
+      lp = len(pstring)
+      return _u2i(_pigpio_command_ext(
+         self.sl, _PI_CMD_SHELL, ls, 0, ls+lp+1, [shellscr+'\x00'+pstring]))
+
    def callback(self, user_gpio, edge=RISING_EDGE, func=None):
       """
       Calls a user supplied function (a callback) whenever the
@@ -4071,8 +4498,48 @@ def xref():
    PI_BAD_SER_INVERT = -121
    PI_BAD_FOREVER = -124
    PI_BAD_FILTER = -125
+   PI_BAD_PAD = -126
+   PI_BAD_STRENGTH = -127
+   PI_FIL_OPEN_FAILED = -128
+   PI_BAD_FILE_MODE = -129
+   PI_BAD_FILE_FLAG = -130
+   PI_BAD_FILE_READ = -131
+   PI_BAD_FILE_WRITE = -132
+   PI_FILE_NOT_ROPEN = -133
+   PI_FILE_NOT_WOPEN = -134
+   PI_BAD_FILE_SEEK = -135
+   PI_NO_FILE_MATCH = -136
+   PI_NO_FILE_ACCESS = -137
+   PI_FILE_IS_A_DIR = -138
+   PI_BAD_SHELL_STATUS = -139
+   PI_BAD_SCRIPT_NAME = -140
    . .
 
+   file_mode:
+   The mode may have the following values.
+
+   . .
+   FILE_READ   1
+   FILE_WRITE  2
+   FILE_RW     3
+   . .
+
+   The following values can be or'd into the file open mode.
+
+   . .
+   FILE_APPEND 4
+   FILE_CREATE 8
+   FILE_TRUNC  16
+   . .
+
+   file_name:
+   A full file path.  To be accessible the path must match
+   an entry in /opt/pigpio/access.
+
+   fpattern:
+   A file path which may contain wildcards.  To be accessible the path
+   must match an entry in /opt/pigpio/access.
+
    frequency: 0-40000
    Defines the frequency to be used for PWM on a GPIO.
    The closest permitted frequency will be used.
@@ -4122,8 +4589,8 @@ def xref():
    of a pulse.
 
    handle: >=0
-   A number referencing an object opened by one of [*i2c_open*],
-   [*notify_open*], [*serial_open*], [*spi_open*].
+   A number referencing an object opened by one of [*file_open*],
+   [*i2c_open*], [*notify_open*], [*serial_open*], [*spi_open*].
 
    host:
    The name or IP address of the Pi running the pigpio daemon.
@@ -4177,6 +4644,18 @@ def xref():
    The offset wave data starts from the beginning of the waveform
    being currently defined.
 
+   pad: 0-2
+   A set of GPIO which share common drivers.
+
+   Pad @  GPIO
+   0   @  0-27
+   1   @  28-45
+   2   @  46-53
+
+   pad_strength: 1-16
+   The mA which may be drawn from each GPIO whilst still guaranteeing the
+   high and low levels.
+
    params: 32 bit number
    When scripts are started they can receive up to 10 parameters
    to define their operation.
@@ -4184,6 +4663,9 @@ def xref():
    port: 
    The port used by the pigpio daemon, defaults to 8888.
 
+   pstring:
+   The string to be passed to a [*shell*] script to be executed.
+
    pud: 0-2
    PUD_DOWN = 1 
    PUD_OFF = 0 
@@ -4230,12 +4712,27 @@ def xref():
    SDA:
    The user GPIO to use for data when bit banging I2C.
 
+   seek_from: 0-2
+   Direction to seek for [*file_seek*].
+
+   FROM_START=0 
+   FROM_CURRENT=1 
+   FROM_END=2 
+
+   seek_offset:
+   The number of bytes to move forward (positive) or backwards
+   (negative) from the seek position (start, current, or end of file).
+
    ser_flags: 32 bit
    No serial flags are currently defined.
 
    serial_*:
    One of the serial_ functions.
 
+   shellscr:
+   The name of a shell script.  The script must exist
+   in /opt/pigpio/cgi and must be executable.
+
    spi_*:
    One of the spi_ functions.
 
index 2ce59b1c99a8d98e5f02f279ae6d1b4419f380e5..c32a4bb76d8b2df692fe00b61f8216847bf56d0e 100644 (file)
--- a/pigpiod.1
+++ b/pigpiod.1
@@ -11,6 +11,10 @@ pigpiod - A utility to start the pigpio library as a daemon.
 sudo pigpiod [OPTION]...
 .SH DESCRIPTION
 
+
+.ad l
+
+.nh
 pigpiod is a utility which launches the pigpio library as a daemon.
 .br
 
index a5f07820a9bbebb550201ba72ecf9b25cf147de7..284a3ae19acf5bdbfd4fa820f85c41d0673f01df 100644 (file)
@@ -17,6 +17,10 @@ gcc -Wall -pthread -o prog prog.c -lpigpiod_if -lrt
 .SH DESCRIPTION
 
 
+.ad l
+
+.nh
+
 .br
 
 .br
@@ -37,12 +41,12 @@ of the GPIO via the socket interface to the pigpio daemon.
 .br
 
 .br
-o PWM on any of GPIO 0-31
+o hardware timed PWM on any of GPIO 0-31
 
 .br
 
 .br
-o servo pulses on any of GPIO 0-31
+o hardware timed servo pulses on any of GPIO 0-31
 
 .br
 
@@ -313,7 +317,7 @@ Set the GPIO mode.
 .EX
 gpio: 0-53.
 .br
-mode: PI_INPUT, PI_OUTPUT, PI_ALT0, _ALT1,
+mode: PI_INPUT, PI_OUTPUT, PI_ALT0, PI_ALT1,
 .br
       PI_ALT2, PI_ALT3, PI_ALT4, PI_ALT5.
 .br
@@ -916,28 +920,65 @@ corresponding bit in bits is set.
 .br
 
 .br
-Notes
+Each notification occupies 12 bytes in the fifo as follows:
 
 .br
 
 .br
-Each notification occupies 12 bytes in the fifo as follows:
 
+.EX
+typedef struct
+.br
+{
+.br
+   uint16_t seqno;
+.br
+   uint16_t flags;
+.br
+   uint32_t tick;
+.br
+   uint32_t level;
+.br
+} gpioReport_t;
 .br
 
+.EE
+
 .br
 
-.EX
-H (16 bit) seqno
 .br
-H (16 bit) flags
+seqno: starts at 0 each time the handle is opened and then increments
+by one for each report.
+
 .br
-I (32 bit) tick
+
 .br
-I (32 bit) level
+flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
+
 .br
 
-.EE
+.br
+PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+indicate a GPIO which has had a watchdog timeout.
+
+.br
+
+.br
+PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+signal on the pipe/socket and is sent once a minute in the absence
+of other notification activity.
+
+.br
+
+.br
+tick: the number of microseconds since system boot.  It wraps around
+after 1h12m.
+
+.br
+
+.br
+level: indicates the level of each GPIO.  If bit 1<<x is set then
+GPIO x is high.
 
 .IP "\fBint notify_pause(unsigned handle)\fP"
 .IP "" 4
@@ -1829,19 +1870,14 @@ The following command codes are supported:
 
 .br
 Name           Cmd & Data   Meaning
-
 .br
 Loop Start     255 0        Identify start of a wave block
-
 .br
 Loop Repeat    255 1 x y    loop x + y*256 times
-
 .br
 Delay          255 2 x y    delay x + y*256 microseconds
-
 .br
 Loop Forever   255 3        loop forever
-
 .br
 
 .br
@@ -2977,31 +3013,22 @@ The following command codes are supported:
 
 .br
 Name      Cmd & Data   Meaning
-
 .br
 End       0            No more commands
-
 .br
 Escape    1            Next P is two bytes
-
 .br
 On        2            Switch combined flag on
-
 .br
 Off       3            Switch combined flag off
-
 .br
 Address   4 P          Set I2C address to P
-
 .br
 Flags     5 lsb msb    Set I2C flags to lsb + (msb << 8)
-
 .br
 Read      6 P          Read P bytes of data
-
 .br
 Write     7 P ...      Write P bytes of data
-
 .br
 
 .br
@@ -3170,31 +3197,22 @@ The following command codes are supported:
 
 .br
 Name      Cmd & Data     Meaning
-
 .br
 End       0              No more commands
-
 .br
 Escape    1              Next P is two bytes
-
 .br
 Start     2              Start condition
-
 .br
 Stop      3              Stop condition
-
 .br
 Address   4 P            Set I2C address to P
-
 .br
 Flags     5 lsb msb      Set I2C flags to lsb + (msb << 8)
-
 .br
 Read      6 P            Read P bytes of data
-
 .br
 Write     7 P ...        Write P bytes of data
-
 .br
 
 .br
@@ -3500,14 +3518,15 @@ PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
 .IP "\fBint serial_open(char *ser_tty, unsigned baud, unsigned ser_flags)\fP"
 .IP "" 4
 This function opens a serial device at a specified baud rate
-with specified flags.
+with specified flags.  The device name must start with
+/dev/tty or /dev/serial.
 
 .br
 
 .br
 
 .EX
-  ser_tty: the serial device to open, /dev/tty*.
+  ser_tty: the serial device to open.
 .br
      baud: the baud rate in bits per second, see below.
 .br
index c2c5c5d3fddc01a3c094d25751bba12e4ae8d57d..3840968a45907b640ded3c806d1044e1f075d32a 100644 (file)
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 For more information, please refer to <http://unlicense.org/>
 */
 
-/* PIGPIOD_IF_VERSION 23 */
+/* PIGPIOD_IF_VERSION 25 */
 
 #include <stdio.h>
 #include <stdlib.h>
index 0b80183ff2821940d921be6bd6d0864bff2da90d..6706b9dd6410e475f875f83ec718392675637a93 100644 (file)
@@ -30,7 +30,7 @@ For more information, please refer to <http://unlicense.org/>
 
 #include "pigpio.h"
 
-#define PIGPIOD_IF_VERSION 23
+#define PIGPIOD_IF_VERSION 25
 
 /*TEXT
 
@@ -42,9 +42,9 @@ of the GPIO via the socket interface to the pigpio daemon.
 
 *Features*
 
-o PWM on any of GPIO 0-31
+o hardware timed PWM on any of GPIO 0-31
 
-o servo pulses on any of GPIO 0-31
+o hardware timed servo pulses on any of GPIO 0-31
 
 o callbacks when any of GPIO 0-31 change state
 
@@ -251,7 +251,7 @@ spi_xfer                   Transfers bytes with a SPI device
 
 SERIAL
 
-serial_open                Opens a serial device (/dev/tty*)
+serial_open                Opens a serial device
 serial_close               Closes a serial device
 
 serial_write_byte          Writes a byte to a serial device
@@ -389,7 +389,7 @@ Set the GPIO mode.
 
 . .
 gpio: 0-53.
-mode: PI_INPUT, PI_OUTPUT, PI_ALT0, _ALT1,
+mode: PI_INPUT, PI_OUTPUT, PI_ALT0, PI_ALT1,
       PI_ALT2, PI_ALT3, PI_ALT4, PI_ALT5.
 . .
 
@@ -727,16 +727,35 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE.
 The notification sends state changes for each GPIO whose
 corresponding bit in bits is set.
 
-Notes
-
 Each notification occupies 12 bytes in the fifo as follows:
 
 . .
-H (16 bit) seqno
-H (16 bit) flags
-I (32 bit) tick
-I (32 bit) level
+typedef struct
+{
+   uint16_t seqno;
+   uint16_t flags;
+   uint32_t tick;
+   uint32_t level;
+} gpioReport_t;
 . .
+
+seqno: starts at 0 each time the handle is opened and then increments
+by one for each report.
+
+flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
+
+PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+indicate a GPIO which has had a watchdog timeout.
+
+PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+signal on the pipe/socket and is sent once a minute in the absence
+of other notification activity.
+
+tick: the number of microseconds since system boot.  It wraps around
+after 1h12m.
+
+level: indicates the level of each GPIO.  If bit 1<<x is set then
+GPIO x is high.
 D*/
 
 /*F*/
@@ -2244,10 +2263,11 @@ D*/
 int serial_open(char *ser_tty, unsigned baud, unsigned ser_flags);
 /*D
 This function opens a serial device at a specified baud rate
-with specified flags.
+with specified flags.  The device name must start with
+/dev/tty or /dev/serial.
 
 . .
-  ser_tty: the serial device to open, /dev/tty*.
+  ser_tty: the serial device to open.
      baud: the baud rate in bits per second, see below.
 ser_flags: 0.
 . .
index fa88cedc2bb3066920c28211603f87e85a8b26fa..2583890d0392925d7869a6c4c2a353b3e105338b 100644 (file)
@@ -17,6 +17,10 @@ gcc -Wall -pthread -o prog prog.c -lpigpiod_if2 -lrt
 .SH DESCRIPTION
 
 
+.ad l
+
+.nh
+
 .br
 
 .br
@@ -31,12 +35,12 @@ of the GPIO via the socket interface to the pigpio daemon.
 .br
 
 .br
-o PWM on any of GPIO 0-31
+o hardware timed PWM on any of GPIO 0-31
 
 .br
 
 .br
-o servo pulses on any of GPIO 0-31
+o hardware timed servo pulses on any of GPIO 0-31
 
 .br
 
@@ -330,7 +334,7 @@ Set the GPIO mode.
 .br
 gpio: 0-53.
 .br
-mode: PI_INPUT, PI_OUTPUT, PI_ALT0, _ALT1,
+mode: PI_INPUT, PI_OUTPUT, PI_ALT0, PI_ALT1,
 .br
       PI_ALT2, PI_ALT3, PI_ALT4, PI_ALT5.
 .br
@@ -971,28 +975,65 @@ corresponding bit in bits is set.
 .br
 
 .br
-Notes
+Each notification occupies 12 bytes in the fifo as follows:
 
 .br
 
 .br
-Each notification occupies 12 bytes in the fifo as follows:
+
+.EX
+typedef struct
+.br
+{
+.br
+   uint16_t seqno;
+.br
+   uint16_t flags;
+.br
+   uint32_t tick;
+.br
+   uint32_t level;
+.br
+} gpioReport_t;
+.br
+
+.EE
 
 .br
 
 .br
+seqno: starts at 0 each time the handle is opened and then increments
+by one for each report.
 
-.EX
-H (16 bit) seqno
 .br
-H (16 bit) flags
+
 .br
-I (32 bit) tick
+flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
+
 .br
-I (32 bit) level
+
 .br
+PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+indicate a GPIO which has had a watchdog timeout.
 
-.EE
+.br
+
+.br
+PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+signal on the pipe/socket and is sent once a minute in the absence
+of other notification activity.
+
+.br
+
+.br
+tick: the number of microseconds since system boot.  It wraps around
+after 1h12m.
+
+.br
+
+.br
+level: indicates the level of each GPIO.  If bit 1<<x is set then
+GPIO x is high.
 
 .IP "\fBint notify_pause(int pi, unsigned handle)\fP"
 .IP "" 4
@@ -2076,19 +2117,14 @@ The following command codes are supported:
 
 .br
 Name           Cmd & Data   Meaning
-
 .br
 Loop Start     255 0        Identify start of a wave block
-
 .br
 Loop Repeat    255 1 x y    loop x + y*256 times
-
 .br
 Delay          255 2 x y    delay x + y*256 microseconds
-
 .br
 Loop Forever   255 3        loop forever
-
 .br
 
 .br
@@ -3443,31 +3479,22 @@ The following command codes are supported:
 
 .br
 Name      Cmd & Data   Meaning
-
 .br
 End       0            No more commands
-
 .br
 Escape    1            Next P is two bytes
-
 .br
 On        2            Switch combined flag on
-
 .br
 Off       3            Switch combined flag off
-
 .br
 Address   4 P          Set I2C address to P
-
 .br
 Flags     5 lsb msb    Set I2C flags to lsb + (msb << 8)
-
 .br
 Read      6 P          Read P bytes of data
-
 .br
 Write     7 P ...      Write P bytes of data
-
 .br
 
 .br
@@ -3642,31 +3669,22 @@ The following command codes are supported:
 
 .br
 Name      Cmd & Data     Meaning
-
 .br
 End       0              No more commands
-
 .br
 Escape    1              Next P is two bytes
-
 .br
 Start     2              Start condition
-
 .br
 Stop      3              Stop condition
-
 .br
 Address   4 P            Set I2C address to P
-
 .br
 Flags     5 lsb msb      Set I2C flags to lsb + (msb << 8)
-
 .br
 Read      6 P            Read P bytes of data
-
 .br
 Write     7 P ...        Write P bytes of data
-
 .br
 
 .br
@@ -4004,7 +4022,12 @@ PI_BAD_HANDLE, PI_BAD_SPI_COUNT, or PI_SPI_XFER_FAILED.
 .IP "\fBint serial_open(int pi, char *ser_tty, unsigned baud, unsigned ser_flags)\fP"
 .IP "" 4
 This function opens a serial device at a specified baud rate
-with specified flags.
+with specified flags.  The device name must start with
+/dev/tty or /dev/serial.
+
+.br
+
+.br
 
 .br
 
@@ -4013,7 +4036,7 @@ with specified flags.
 .EX
        pi: >=0 (as returned by \fBpigpio_start\fP).
 .br
-  ser_tty: the serial device to open, /dev/tty*.
+  ser_tty: the serial device to open.
 .br
      baud: the baud rate in bits per second, see below.
 .br
@@ -4255,56 +4278,65 @@ Returns >= 0 if OK, less than 0 indicates a user defined error.
 .br
 Note, the number of returned bytes will be retMax or less.
 
-.IP "\fBint callback(int pi, unsigned user_gpio, unsigned edge, CBFunc_t f)\fP"
+.IP "\fBint get_pad_strength(int pi, unsigned pad)\fP"
 .IP "" 4
-This function initialises a new callback.
+This function returns the pad drive strength in mA.
 
 .br
 
 .br
 
 .EX
      pi: >=0 (as returned by \fBpigpio_start\fP).
+ pi: >=0 (as returned by \fBpigpio_start\fP).
 .br
-user_gpio: 0-31.
+pad: 0-2, the pad to get.
 .br
-     edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE.
+
+.EE
+
 .br
-        f: the callback function.
+
 .br
+Returns the pad drive strength if OK, otherwise PI_BAD_PAD.
 
-.EE
+.br
 
+.br
+Pad   GPIO
+.br
+0     0-27
+.br
+1     28-45
+.br
+2     46-53
 .br
 
 .br
-The function returns a callback id if OK, otherwise pigif_bad_malloc,
-pigif_duplicate_callback, or pigif_bad_callback.
 
+.br
+\fBExample\fP
 .br
 
+.EX
+strength = get_pad_strength(pi, 0); //  get pad 0 strength
 .br
-The callback is called with the GPIO, edge, and tick, whenever the
-GPIO has the identified edge.
 
-.IP "\fBint callback_ex(int pi, unsigned user_gpio, unsigned edge, CBFuncEx_t f, void *userdata)\fP"
+.EE
+
+.IP "\fBint set_pad_strength(int pi, unsigned pad, unsigned padStrength)\fP"
 .IP "" 4
-This function initialises a new callback.
+This function sets the pad drive strength in mA.
 
 .br
 
 .br
 
 .EX
-       pi: >=0 (as returned by \fBpigpio_start\fP).
-.br
-user_gpio: 0-31.
-.br
-     edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE.
+         pi: >=0 (as returned by \fBpigpio_start\fP).
 .br
-        f: the callback function.
+        pad: 0-2, the pad to set.
 .br
- userdata: a pointer to arbitrary user data.
+padStrength: 1-16 mA.
 .br
 
 .EE
@@ -4312,51 +4344,49 @@ user_gpio: 0-31.
 .br
 
 .br
-The function returns a callback id if OK, otherwise pigif_bad_malloc,
-pigif_duplicate_callback, or pigif_bad_callback.
+Returns 0 if OK, otherwise PI_BAD_PAD, or PI_BAD_STRENGTH.
 
 .br
 
 .br
-The callback is called with the GPIO, edge, tick, and user, whenever
-the GPIO has the identified edge.
-
-.IP "\fBint callback_cancel(unsigned callback_id)\fP"
-.IP "" 4
-This function cancels a callback identified by its id.
+Pad   GPIO
+.br
+0     0-27
+.br
+1     28-45
+.br
+2     46-53
+.br
 
 .br
 
+.br
+\fBExample\fP
 .br
 
 .EX
-callback_id: >=0, as returned by a call to \fBcallback\fP or \fBcallback_ex\fP.
+set_pad_strength(pi, 0, 10); // set pad 0 strength to 10 mA
 .br
 
 .EE
 
-.br
-
-.br
-The function returns 0 if OK, otherwise pigif_callback_not_found.
-
-.IP "\fBint wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout)\fP"
+.IP "\fBint shell_(int pi, char *scriptName, char *scriptString)\fP"
 .IP "" 4
-This function waits for edge on the GPIO for up to timeout
-seconds.
+This function uses the system call to execute a shell script
+with the given string as its parameter.
 
 .br
 
 .br
 
 .EX
-       pi: >=0 (as returned by \fBpigpio_start\fP).
+          pi: >=0 (as returned by \fBpigpio_start\fP).
 .br
-user_gpio: 0-31.
+  scriptName: the name of the script, only alphanumeric characters,
 .br
-     edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE.
+              '-' and '_' are allowed in the name.
 .br
-  timeout: >=0.
+scriptString: the string to pass to the script.
 .br
 
 .EE
@@ -4364,166 +4394,137 @@ user_gpio: 0-31.
 .br
 
 .br
-The function returns when the edge occurs or after the timeout.
+The exit status of the system call is returned if OK, otherwise
+PI_BAD_SHELL_STATUS.
 
 .br
 
 .br
-Do not use this function for precise timing purposes,
-the edge is only checked 20 times a second. Whenever
-you need to know the accurate time of GPIO events use
-a \fBcallback\fP function.
+scriptName must exist in /opt/pigpio/cgi and must be executable.
 
 .br
 
 .br
-The function returns 1 if the edge occurred, otherwise 0.
-.SH PARAMETERS
+The returned exit status is normally 256 times that set by the
+shell script exit function.  If the script can't be found 32512 will
+be returned.
 
 .br
 
 .br
-
-.IP "\fBactive\fP: 0-1000000" 0
+The following table gives some example returned statuses.
 
 .br
 
 .br
-The number of microseconds level changes are reported for once
-a noise filter has been triggered (by \fBsteady\fP microseconds of
-a stable level).
-
+Script exit status   Returned system call status
 .br
-
+1                    256
 .br
-
-.IP "\fB*addrStr\fP" 0
-A string specifying the host or IP address of the Pi running
-the pigpio daemon.  It may be NULL in which case localhost
-is used unless overridden by the PIGPIO_ADDR environment
-variable.
-
+5                    1280
 .br
-
+10                   2560
 .br
-
-.IP "\fBarg1\fP" 0
-An unsigned argument passed to a user customised function.  Its
-meaning is defined by the customiser.
-
+200                  51200
 .br
-
+script not found     32512
 .br
 
-.IP "\fBarg2\fP" 0
-An unsigned argument passed to a user customised function.  Its
-meaning is defined by the customiser.
-
 .br
 
 .br
-
-.IP "\fBargc\fP" 0
-The count of bytes passed to a user customised function.
-
+\fBExample\fP
 .br
 
+.EX
+// pass two parameters, hello and world
 .br
-
-.IP "\fB*argx\fP" 0
-A pointer to an array of bytes passed to a user customised function.
-Its meaning and content is defined by the customiser.
-
+status = shell_(pi, "scr1", "hello world");
 .br
 
 .br
-
-.IP "\fBbaud\fP" 0
-The speed of serial communication (I2C, SPI, serial link, waves) in
-bits per second.
-
+// pass three parameters, hello, string with spaces, and world
 .br
-
+status = shell_(pi, "scr1", "hello 'string with spaces' world");
 .br
 
-.IP "\fBbit\fP" 0
-A value of 0 or 1.
-
 .br
-
+// pass one parameter, hello string with spaces world
+.br
+status = shell_(pi, "scr1", "\"hello string with spaces world\"");
 .br
 
-.IP "\fBbits\fP" 0
-A value used to select GPIO.  If bit n of bits is set then GPIO n is
-selected.
+.EE
 
-.br
+.IP "\fBint file_open(int pi, char *file, unsigned mode)\fP"
+.IP "" 4
+This function returns a handle to a file opened in a specified mode.
 
 .br
-A convenient way to set bit n is to or in (1<<n).
 
 .br
 
+.EX
+  pi: >=0 (as returned by \fBpigpio_start\fP).
 .br
-e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
-
+file: the file to open.
 .br
-
+mode: the file open mode.
 .br
 
-.IP "\fB*buf\fP" 0
-A buffer to hold data being sent or being received.
+.EE
 
 .br
 
 .br
-
-.IP "\fBbufSize\fP" 0
-The size in bytes of a buffer.
+Returns a handle (>=0) if OK, otherwise PI_NO_HANDLE, PI_NO_FILE_ACCESS,
+PI_BAD_FILE_MODE, PI_FILE_OPEN_FAILED, or PI_FILE_IS_A_DIR.
 
 .br
 
 .br
+File
 
 .br
 
 .br
-
-.IP "\fBbVal\fP: 0-255 (Hex 0x0-0xFF, Octal 0-0377)" 0
-An 8-bit byte value.
+A file may only be opened if permission is granted by an entry in
+/opt/pigpio/access.  This is intended to allow remote access to files
+in a more or less controlled manner.
 
 .br
 
 .br
-
-.IP "\fBcallback_id\fP" 0
-A >=0, as returned by a call to \fBcallback\fP or \fBcallback_ex\fP.  This is
-passed to \fBcallback_cancel\fP to cancel the callback.
+Each entry in /opt/pigpio/access takes the form of a file path
+which may contain wildcards followed by a single letter permission.
+The permission may be R for read, W for write, U for read/write,
+and N for no access.
 
 .br
 
 .br
+Where more than one entry matches a file the most specific rule
+applies.  If no entry matches a file then access is denied.
 
-.IP "\fBCBFunc_t\fP" 0
-
-.EX
-typedef void (*CBFunc_t)
-.br
-   (unsigned user_gpio, unsigned level, uint32_t tick);
 .br
 
-.EE
-
 .br
+Suppose /opt/pigpio/access contains the following entries
 
 .br
 
-.IP "\fBCBFuncEx_t\fP" 0
+.br
 
 .EX
-typedef void (*CBFuncEx_t)
+/home/* n
 .br
-   (unsigned user_gpio, unsigned level, uint32_t tick, void * user);
+/home/pi/shared/dir_1/* w
+.br
+/home/pi/shared/dir_2/* r
+.br
+/home/pi/shared/dir_3/* u
+.br
+/home/pi/shared/dir_1/file.txt n
 .br
 
 .EE
@@ -4531,40 +4532,41 @@ typedef void (*CBFuncEx_t)
 .br
 
 .br
-
-.IP "\fBchar\fP" 0
-A single character, an 8 bit quantity able to store 0-255.
+Files may be written in directory dir_1 with the exception
+of file.txt.
 
 .br
 
 .br
-
-.IP "\fBclkfreq\fP: 4689-250000000 (250M)" 0
-The hardware clock frequency.
+Files may be read in directory dir_2.
 
 .br
 
 .br
+Files may be read and written in directory dir_3.
 
-.IP "\fBcount\fP" 0
-The number of bytes to be transferred in an I2C, SPI, or Serial
-command.
+.br
 
 .br
+If a directory allows read, write, or read/write access then files may
+be created in that directory.
 
 .br
 
-.IP "\fBdata_bits\fP: 1-32" 0
-The number of data bits in each character of serial data.
+.br
+In an attempt to prevent risky permissions the following paths are
+ignored in /opt/pigpio/access.
 
 .br
 
 .br
 
 .EX
-#define PI_MIN_WAVE_DATABITS 1
+a path containing ..
 .br
-#define PI_MAX_WAVE_DATABITS 32
+a path containing only wildcards (*?)
+.br
+a path containing less than two non-wildcard parts
 .br
 
 .EE
@@ -4572,39 +4574,755 @@ The number of data bits in each character of serial data.
 .br
 
 .br
+Mode
 
-.IP "\fBdouble\fP" 0
-A floating point number.
+.br
 
 .br
+The mode may have the following values.
 
 .br
 
-.IP "\fBdutycycle\fP: 0-range" 0
-A number representing the ratio of on time to off time for PWM.
+.br
+Macro           Value   Meaning
+.br
+PI_FILE_READ      1     open file for reading
+.br
+PI_FILE_WRITE     2     open file for writing
+.br
+PI_FILE_RW        3     open file for reading and writing
+.br
 
 .br
 
 .br
-The number may vary between 0 and range (default 255) where
-0 is off and range is fully on.
+The following values may be or'd into the mode.
 
 .br
 
+.br
+Macro            Value   Meaning
+.br
+PI_FILE_APPEND   4       Writes append data to the end of the file
+.br
+PI_FILE_CREATE   8       The file is created if it doesn't exist
+.br
+PI_FILE_TRUNC    16      The file is truncated
 .br
 
-.IP "\fBedge\fP" 0
-Used to identify a GPIO level transition of interest.  A rising edge is
-a level change from 0 to 1.  A falling edge is a level change from 1 to 0.
+.br
 
 .br
+Newly created files are owned by root with permissions owner read and write.
 
 .br
 
-.EX
-RISING_EDGE  0
 .br
-FALLING_EDGE 1
+\fBExample\fP
+.br
+
+.EX
+#include <stdio.h>
+.br
+#include <pigpiod_if2.h>
+.br
+
+.br
+int main(int argc, char *argv[])
+.br
+{
+.br
+   int pi, handle, c;
+.br
+   char buf[60000];
+.br
+
+.br
+   pi = pigpio_start(NULL, NULL);
+.br
+
+.br
+   if (pi < 0) return 1;
+.br
+
+.br
+   // assumes /opt/pigpio/access contains the following line
+.br
+   // /ram/*.c r
+.br
+
+.br
+   handle = file_open(pi, "/ram/pigpio.c", PI_FILE_READ);
+.br
+
+.br
+   if (handle >= 0)
+.br
+   {
+.br
+      while ((c=file_read(pi, handle, buf, sizeof(buf)-1)))
+.br
+      {
+.br
+         buf[c] = 0;
+.br
+         printf("%s", buf);
+.br
+      }
+.br
+
+.br
+      file_close(pi, handle);
+.br
+   }
+.br
+
+.br
+   pigpio_stop(pi);
+.br
+}
+.br
+
+.EE
+
+.IP "\fBint file_close(int pi, unsigned handle)\fP"
+.IP "" 4
+This function closes the file associated with handle.
+
+.br
+
+.br
+
+.EX
+    pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+handle: >=0 (as returned by \fBfile_open\fP).
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_HANDLE.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+file_close(pi, handle);
+.br
+
+.EE
+
+.IP "\fBint file_write(int pi, unsigned handle, char *buf, unsigned count)\fP"
+.IP "" 4
+This function writes count bytes from buf to the the file
+associated with handle.
+
+.br
+
+.br
+
+.EX
+    pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+handle: >=0 (as returned by \fBfile_open\fP).
+.br
+   buf: the array of bytes to write.
+.br
+ count: the number of bytes to write.
+.br
+
+.EE
+
+.br
+
+.br
+Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM,
+PI_FILE_NOT_WOPEN, or PI_BAD_FILE_WRITE.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+if (file_write(pi, handle, buf, 100) == 0)
+.br
+{
+.br
+   // file written okay
+.br
+}
+.br
+else
+.br
+{
+.br
+   // error
+.br
+}
+.br
+
+.EE
+
+.IP "\fBint file_read(int pi, unsigned handle, char *buf, unsigned count)\fP"
+.IP "" 4
+This function reads up to count bytes from the the file
+associated with handle and writes them to buf.
+
+.br
+
+.br
+
+.EX
+    pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+handle: >=0 (as returned by \fBfile_open\fP).
+.br
+   buf: an array to receive the read data.
+.br
+ count: the maximum number of bytes to read.
+.br
+
+.EE
+
+.br
+
+.br
+Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, PI_FILE_NOT_ROPEN, or PI_BAD_FILE_WRITE.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+   bytes = file_read(pi, handle, buf, sizeof(buf));
+.br
+
+.br
+   if (bytes >= 0)
+.br
+   {
+.br
+      // process read data
+.br
+   }
+.br
+
+.EE
+
+.IP "\fBint file_seek(int pi, unsigned handle, int32_t seekOffset, int seekFrom)\fP"
+.IP "" 4
+This function seeks to a position within the file associated
+with handle.
+
+.br
+
+.br
+
+.EX
+        pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+    handle: >=0 (as returned by \fBfile_open\fP).
+.br
+seekOffset: the number of bytes to move.  Positive offsets
+.br
+            move forward, negative offsets backwards.
+.br
+  seekFrom: one of PI_FROM_START (0), PI_FROM_CURRENT (1),
+.br
+            or PI_FROM_END (2).
+.br
+
+.EE
+
+.br
+
+.br
+Returns the new byte position within the file (>=0) if OK, otherwise PI_BAD_HANDLE, or PI_BAD_FILE_SEEK.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+file_seek(pi, handle, 123, PI_FROM_START); // Start plus 123
+.br
+
+.br
+size = file_seek(pi, handle, 0, PI_FROM_END); // End, return size
+.br
+
+.br
+pos = file_seek(pi, handle, 0, PI_FROM_CURRENT); // Current position
+.br
+
+.EE
+
+.IP "\fBint file_list(int pi, char *fpat, char *buf, unsigned count)\fP"
+.IP "" 4
+This function returns a list of files which match a pattern.
+
+.br
+
+.br
+
+.EX
+   pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+ fpat: file pattern to match.
+.br
+  buf: an array to receive the matching file names.
+.br
+count: the maximum number of bytes to read.
+.br
+
+.EE
+
+.br
+
+.br
+Returns the number of returned bytes if OK, otherwise PI_NO_FILE_ACCESS,
+or PI_NO_FILE_MATCH.
+
+.br
+
+.br
+The pattern must match an entry in /opt/pigpio/access.  The pattern
+may contain wildcards.  See \fBfile_open\fP.
+
+.br
+
+.br
+NOTE
+
+.br
+
+.br
+The returned value is not the number of files, it is the number
+of bytes in the buffer.  The file names are separated by newline
+characters.
+
+.br
+
+.br
+\fBExample\fP
+.br
+
+.EX
+#include <stdio.h>
+.br
+#include <pigpiod_if2.h>
+.br
+
+.br
+int main(int argc, char *argv[])
+.br
+{
+.br
+   int pi, handle, c;
+.br
+   char buf[60000];
+.br
+
+.br
+   pi = pigpio_start(NULL, NULL);
+.br
+
+.br
+   if (pi < 0) return 1;
+.br
+
+.br
+   // assumes /opt/pigpio/access contains the following line
+.br
+   // /ram/*.c r
+.br
+
+.br
+   c = file_list(pi, "/ram/p*.c", buf, sizeof(buf));
+.br
+
+.br
+   if (c >= 0)
+.br
+   {
+.br
+      buf[c] = 0;
+.br
+      printf("%s", buf);
+.br
+   }
+.br
+
+.br
+   pigpio_stop(pi);
+.br
+}
+.br
+
+.EE
+
+.IP "\fBint callback(int pi, unsigned user_gpio, unsigned edge, CBFunc_t f)\fP"
+.IP "" 4
+This function initialises a new callback.
+
+.br
+
+.br
+
+.EX
+       pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+user_gpio: 0-31.
+.br
+     edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE.
+.br
+        f: the callback function.
+.br
+
+.EE
+
+.br
+
+.br
+The function returns a callback id if OK, otherwise pigif_bad_malloc,
+pigif_duplicate_callback, or pigif_bad_callback.
+
+.br
+
+.br
+The callback is called with the GPIO, edge, and tick, whenever the
+GPIO has the identified edge.
+
+.IP "\fBint callback_ex(int pi, unsigned user_gpio, unsigned edge, CBFuncEx_t f, void *userdata)\fP"
+.IP "" 4
+This function initialises a new callback.
+
+.br
+
+.br
+
+.EX
+       pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+user_gpio: 0-31.
+.br
+     edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE.
+.br
+        f: the callback function.
+.br
+ userdata: a pointer to arbitrary user data.
+.br
+
+.EE
+
+.br
+
+.br
+The function returns a callback id if OK, otherwise pigif_bad_malloc,
+pigif_duplicate_callback, or pigif_bad_callback.
+
+.br
+
+.br
+The callback is called with the GPIO, edge, tick, and user, whenever
+the GPIO has the identified edge.
+
+.IP "\fBint callback_cancel(unsigned callback_id)\fP"
+.IP "" 4
+This function cancels a callback identified by its id.
+
+.br
+
+.br
+
+.EX
+callback_id: >=0, as returned by a call to \fBcallback\fP or \fBcallback_ex\fP.
+.br
+
+.EE
+
+.br
+
+.br
+The function returns 0 if OK, otherwise pigif_callback_not_found.
+
+.IP "\fBint wait_for_edge(int pi, unsigned user_gpio, unsigned edge, double timeout)\fP"
+.IP "" 4
+This function waits for edge on the GPIO for up to timeout
+seconds.
+
+.br
+
+.br
+
+.EX
+       pi: >=0 (as returned by \fBpigpio_start\fP).
+.br
+user_gpio: 0-31.
+.br
+     edge: RISING_EDGE, FALLING_EDGE, or EITHER_EDGE.
+.br
+  timeout: >=0.
+.br
+
+.EE
+
+.br
+
+.br
+The function returns when the edge occurs or after the timeout.
+
+.br
+
+.br
+Do not use this function for precise timing purposes,
+the edge is only checked 20 times a second. Whenever
+you need to know the accurate time of GPIO events use
+a \fBcallback\fP function.
+
+.br
+
+.br
+The function returns 1 if the edge occurred, otherwise 0.
+.SH PARAMETERS
+
+.br
+
+.br
+
+.IP "\fBactive\fP: 0-1000000" 0
+
+.br
+
+.br
+The number of microseconds level changes are reported for once
+a noise filter has been triggered (by \fBsteady\fP microseconds of
+a stable level).
+
+.br
+
+.br
+
+.IP "\fB*addrStr\fP" 0
+A string specifying the host or IP address of the Pi running
+the pigpio daemon.  It may be NULL in which case localhost
+is used unless overridden by the PIGPIO_ADDR environment
+variable.
+
+.br
+
+.br
+
+.IP "\fBarg1\fP" 0
+An unsigned argument passed to a user customised function.  Its
+meaning is defined by the customiser.
+
+.br
+
+.br
+
+.IP "\fBarg2\fP" 0
+An unsigned argument passed to a user customised function.  Its
+meaning is defined by the customiser.
+
+.br
+
+.br
+
+.IP "\fBargc\fP" 0
+The count of bytes passed to a user customised function.
+
+.br
+
+.br
+
+.IP "\fB*argx\fP" 0
+A pointer to an array of bytes passed to a user customised function.
+Its meaning and content is defined by the customiser.
+
+.br
+
+.br
+
+.IP "\fBbaud\fP" 0
+The speed of serial communication (I2C, SPI, serial link, waves) in
+bits per second.
+
+.br
+
+.br
+
+.IP "\fBbit\fP" 0
+A value of 0 or 1.
+
+.br
+
+.br
+
+.IP "\fBbits\fP" 0
+A value used to select GPIO.  If bit n of bits is set then GPIO n is
+selected.
+
+.br
+
+.br
+A convenient way to set bit n is to or in (1<<n).
+
+.br
+
+.br
+e.g. to select bits 5, 9, 23 you could use (1<<5) | (1<<9) | (1<<23).
+
+.br
+
+.br
+
+.IP "\fB*buf\fP" 0
+A buffer to hold data being sent or being received.
+
+.br
+
+.br
+
+.IP "\fBbufSize\fP" 0
+The size in bytes of a buffer.
+
+.br
+
+.br
+
+.br
+
+.br
+
+.IP "\fBbVal\fP: 0-255 (Hex 0x0-0xFF, Octal 0-0377)" 0
+An 8-bit byte value.
+
+.br
+
+.br
+
+.IP "\fBcallback_id\fP" 0
+A >=0, as returned by a call to \fBcallback\fP or \fBcallback_ex\fP.  This is
+passed to \fBcallback_cancel\fP to cancel the callback.
+
+.br
+
+.br
+
+.IP "\fBCBFunc_t\fP" 0
+
+.EX
+typedef void (*CBFunc_t)
+.br
+   (unsigned user_gpio, unsigned level, uint32_t tick);
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBCBFuncEx_t\fP" 0
+
+.EX
+typedef void (*CBFuncEx_t)
+.br
+   (unsigned user_gpio, unsigned level, uint32_t tick, void * user);
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBchar\fP" 0
+A single character, an 8 bit quantity able to store 0-255.
+
+.br
+
+.br
+
+.IP "\fBclkfreq\fP: 4689-250000000 (250M)" 0
+The hardware clock frequency.
+
+.br
+
+.br
+
+.IP "\fBcount\fP" 0
+The number of bytes to be transferred in a file, I2C, SPI, or serial
+command.
+
+.br
+
+.br
+
+.IP "\fBdata_bits\fP: 1-32" 0
+The number of data bits in each character of serial data.
+
+.br
+
+.br
+
+.EX
+#define PI_MIN_WAVE_DATABITS 1
+.br
+#define PI_MAX_WAVE_DATABITS 32
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBdouble\fP" 0
+A floating point number.
+
+.br
+
+.br
+
+.IP "\fBdutycycle\fP: 0-range" 0
+A number representing the ratio of on time to off time for PWM.
+
+.br
+
+.br
+The number may vary between 0 and range (default 255) where
+0 is off and range is fully on.
+
+.br
+
+.br
+
+.IP "\fBedge\fP" 0
+Used to identify a GPIO level transition of interest.  A rising edge is
+a level change from 0 to 1.  A falling edge is a level change from 1 to 0.
+
+.br
+
+.br
+
+.EX
+RISING_EDGE  0
+.br
+FALLING_EDGE 1
 .br
 EITHER_EDGE. 2
 .br
@@ -4630,6 +5348,22 @@ A function.
 
 .br
 
+.IP "\fB*file\fP" 0
+A full file path.  To be accessible the path must match an entry in
+/opt/pigpio/access.
+
+.br
+
+.br
+
+.IP "\fB*fpat\fP" 0
+A file path which may contain wildcards.  To be accessible the path
+must match an entry in /opt/pigpio/access.
+
+.br
+
+.br
+
 .IP "\fBfrequency\fP: >=0" 0
 The number of times a GPIO is swiched on and off per second.  This
 can be set per GPIO and may be as little as 5Hz or as much as
@@ -4640,24 +5374,20 @@ by its dutycycle.
 
 .br
 
-.br
-
-.br
-
 .IP "\fBgpio\fP" 0
 A Broadcom numbered GPIO, in the range 0-53.
 
 .br
 
 .br
-There  are 54 General Purpose Input Outputs (GPIO) named gpio0 through
-gpio53.
+There  are 54 General Purpose Input Outputs (GPIO) named GPIO0 through
+GPIO53.
 
 .br
 
 .br
-They are split into two  banks.   Bank  1  consists  of  gpio0  through
-gpio31.  Bank 2 consists of gpio32 through gpio53.
+They are split into two  banks.   Bank  1  consists  of  GPIO0  through
+GPIO31.  Bank 2 consists of GPIO32 through GPIO53.
 
 .br
 
@@ -4741,8 +5471,8 @@ typedef void *(gpioThreadFunc_t) (void *);
 .br
 
 .IP "\fBhandle\fP: >=0" 0
-A number referencing an object opened by one of \fBi2c_open\fP, \fBnotify_open\fP,
-\fBserial_open\fP, and \fBspi_open\fP.
+A number referencing an object opened by one of \fBfile_open\fP,
+\fBi2c_open\fP, \fBnotify_open\fP, \fBserial_open\fP, and \fBspi_open\fP.
 
 .br
 
@@ -4797,6 +5527,13 @@ A whole number, negative or positive.
 
 .br
 
+.IP "\fBint32_t\fP" 0
+A 32-bit signed value.
+
+.br
+
+.br
+
 .IP "\fBinvert\fP" 0
 A flag used to set normal or inverted bit bang serial data level logic.
 
@@ -4901,6 +5638,48 @@ PI_WAVE_MODE_REPEAT_SYNC   3
 
 .br
 
+.br
+3. A file open mode.
+
+.br
+
+.br
+
+.EX
+PI_FILE_READ  1
+.br
+PI_FILE_WRITE 2
+.br
+PI_FILE_RW    3
+.br
+
+.EE
+
+.br
+
+.br
+The following values can be or'd into the mode.
+
+.br
+
+.br
+
+.EX
+PI_FILE_APPEND 4
+.br
+PI_FILE_CREATE 8
+.br
+PI_FILE_TRUNC  16
+.br
+
+.EE
+
+.br
+
+.br
+
+.br
+
 .br
 
 .IP "\fBnumBytes\fP" 0
@@ -4948,6 +5727,33 @@ The size in bytes of an output buffer.
 
 .br
 
+.IP "\fBpad\fP: 0-2" 0
+A set of GPIO which share common drivers.
+
+.br
+
+.br
+Pad   GPIO
+.br
+0     0-27
+.br
+1     28-45
+.br
+2     46-53
+.br
+
+.br
+
+.br
+
+.IP "\fBpadStrength\fP: 1-16" 0
+The mA which may be drawn from each GPIO whilst still guaranteeing the
+high and low levels.
+
+.br
+
+.br
+
 .IP "\fB*param\fP" 0
 An array of script parameters.
 
@@ -5136,6 +5942,21 @@ An id of a stored script as returned by \fBstore_script\fP.
 
 .br
 
+.IP "\fB*scriptName\fP" 0
+The name of a \fBshell_\fP script to be executed.  The script must be present in
+/opt/pigpio/cgi and must have execute permission.
+
+.br
+
+.br
+
+.IP "\fB*scriptString\fP" 0
+The string to be passed to a \fBshell_\fP script to be executed.
+
+.br
+
+.br
+
 .IP "\fBSDA\fP" 0
 The user GPIO to use for data when bit banging I2C.
 
@@ -5150,6 +5971,34 @@ The number of seconds.
 
 .br
 
+.IP "\fBseekFrom\fP" 0
+
+.br
+
+.br
+
+.EX
+PI_FROM_START   0
+.br
+PI_FROM_CURRENT 1
+.br
+PI_FROM_END     2
+.br
+
+.EE
+
+.br
+
+.br
+
+.IP "\fBseekOffset\fP" 0
+The number of bytes to move forward (positive) or backwards (negative)
+from the seek position (start, current, or end of file).
+
+.br
+
+.br
+
 .IP "\fBser_flags\fP" 0
 Flags which modify a serial open command.  None are currently defined.
 
index ffaab494447006302da455203a793f6df982ef00..bc3d496f9001d30176a92cbc2e2c578ad91034df 100644 (file)
@@ -25,7 +25,7 @@ OTHER DEALINGS IN THE SOFTWARE.
 For more information, please refer to <http://unlicense.org/>
 */
 
-/* PIGPIOD_IF2_VERSION 6 */
+/* PIGPIOD_IF2_VERSION 8 */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -1604,6 +1604,148 @@ int custom_2(int pi, unsigned arg1, char *argx, unsigned count,
    return bytes;
 }
 
+int get_pad_strength(int pi, unsigned pad)
+   {return pigpio_command(pi, PI_CMD_PADG, pad, 0, 1);}
+
+int set_pad_strength(int pi, unsigned pad, unsigned padStrength)
+   {return pigpio_command(pi, PI_CMD_PADS, pad, padStrength, 1);}
+
+int shell_(int pi, char *scriptName, char *scriptString)
+{
+   int ln, ls;
+   gpioExtent_t ext[2];
+
+   ln = strlen(scriptName);
+   ls = strlen(scriptString);
+   /*
+   p1=len(scriptName)
+   p2=0
+   p3=len(scriptName) + len(scriptString) + 1
+   ## extension ##
+   char[]
+   */
+
+   ext[0].size = ln + 1; /* include null byte */
+   ext[0].ptr = scriptName;
+
+   ext[1].size = ls;
+   ext[1].ptr = scriptString;
+
+   return pigpio_command_ext
+      (pi, PI_CMD_SHELL, ln, 0, ln+ls+1, 2, ext, 1);
+}
+
+int file_open(int pi, char *file, unsigned mode)
+{
+   int len;
+   gpioExtent_t ext[1];
+
+   len = strlen(file);
+
+   /*
+   p1=mode
+   p2=0
+   p3=len
+   ## extension ##
+   char file[len]
+   */
+
+   ext[0].size = len;
+   ext[0].ptr = file;
+
+   return pigpio_command_ext
+      (pi, PI_CMD_FO, mode, 0, len, 1, ext, 1);
+}
+
+int file_close(int pi, unsigned handle)
+   {return pigpio_command(pi, PI_CMD_FC, handle, 0, 1);}
+
+int file_write(int pi, unsigned handle, char *buf, unsigned count)
+{
+   gpioExtent_t ext[1];
+
+   /*
+   p1=handle
+   p2=0
+   p3=count
+   ## extension ##
+   char buf[count]
+   */
+
+   ext[0].size = count;
+   ext[0].ptr = buf;
+
+   return pigpio_command_ext
+      (pi, PI_CMD_FW, handle, 0, count, 1, ext, 1);
+}
+
+int file_read(int pi, unsigned handle, char *buf, unsigned count)
+{
+   int bytes;
+
+   bytes = pigpio_command
+      (pi, PI_CMD_FR, handle, count, 0);
+
+   if (bytes > 0)
+   {
+      bytes = recvMax(pi, buf, count, bytes);
+   }
+
+   _pmu(pi);
+
+   return bytes;
+}
+
+int file_seek(int pi, unsigned handle, int32_t seekOffset, int seekFrom)
+{
+   gpioExtent_t ext[1];
+
+   /*
+   p1=handle
+   p2=seekOffset
+   p3=4
+   ## extension ##
+   uint32_t seekFrom
+   */
+
+   ext[0].size = sizeof(uint32_t);
+   ext[0].ptr = &seekFrom;
+
+   return pigpio_command_ext
+      (pi, PI_CMD_FS, handle, seekOffset, 4, 1, ext, 1);
+}
+
+int file_list(int pi, char *fpat,  char *buf, unsigned count)
+{
+   int len;
+   int bytes;
+   gpioExtent_t ext[1];
+
+   len = strlen(fpat);
+
+   /*
+   p1=60000
+   p2=0
+   p3=len
+   ## extension ##
+   char fpat[len]
+   */
+
+   ext[0].size = len;
+   ext[0].ptr = fpat;
+
+   bytes = pigpio_command_ext(pi, PI_CMD_FL, 60000, 0, len, 1, ext, 0);
+
+   if (bytes > 0)
+   {
+      bytes = recvMax(pi, buf, count, bytes);
+   }
+
+   _pmu(pi);
+
+   return bytes;
+}
+
 int callback(int pi, unsigned user_gpio, unsigned edge, CBFunc_t f)
    {return intCallback(pi, user_gpio, edge, f, 0, 0);}
 
index 95de30700443de7f74008ed14381999d71f81d3b..c41d5a1ab3efb35fd3e7d656012c528535fa4518 100644 (file)
@@ -30,7 +30,7 @@ For more information, please refer to <http://unlicense.org/>
 
 #include "pigpio.h"
 
-#define PIGPIOD_IF2_VERSION 6
+#define PIGPIOD_IF2_VERSION 8
 
 /*TEXT
 
@@ -39,9 +39,9 @@ of the GPIO via the socket interface to the pigpio daemon.
 
 *Features*
 
-o PWM on any of GPIO 0-31
+o hardware timed PWM on any of GPIO 0-31
 
-o servo pulses on any of GPIO 0-31
+o hardware timed servo pulses on any of GPIO 0-31
 
 o callbacks when any of GPIO 0-31 change state
 
@@ -166,8 +166,13 @@ bb_serial_invert           Invert serial logic (1 invert, 0 normal)
 hardware_clock             Start hardware clock on supported GPIO
 hardware_PWM               Start hardware PWM on supported GPIO
 
-set_glitch_filter         Set a glitch filter on a GPIO
-set_noise_filter          Set a noise filter on a GPIO
+set_glitch_filter          Set a glitch filter on a GPIO
+set_noise_filter           Set a noise filter on a GPIO
+
+get_pad_strength           Gets a pads drive strength
+set_pad_strength           Sets a pads drive strength
+
+shell_                     Executes a shell command
 
 SCRIPTS
 
@@ -250,7 +255,7 @@ spi_xfer                   Transfers bytes with a SPI device
 
 SERIAL
 
-serial_open                Opens a serial device (/dev/tty*)
+serial_open                Opens a serial device
 serial_close               Closes a serial device
 
 serial_write_byte          Writes a byte to a serial device
@@ -260,6 +265,15 @@ serial_read                Reads bytes from a serial device
 
 serial_data_available      Returns number of bytes ready to be read
 
+FILES
+
+file_open                  Opens a file
+file_close                 Closes a file
+file_read                  Reads bytes from a file
+file_write                 Writes bytes to a file
+file_seek                  Seeks to a position within a file
+file_list                  List files which match a pattern
+
 CUSTOM
 
 custom_1                   User custom function 1
@@ -399,7 +413,7 @@ Set the GPIO mode.
 . .
   pi: >=0 (as returned by [*pigpio_start*]).
 gpio: 0-53.
-mode: PI_INPUT, PI_OUTPUT, PI_ALT0, _ALT1,
+mode: PI_INPUT, PI_OUTPUT, PI_ALT0, PI_ALT1,
       PI_ALT2, PI_ALT3, PI_ALT4, PI_ALT5.
 . .
 
@@ -755,16 +769,35 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE.
 The notification sends state changes for each GPIO whose
 corresponding bit in bits is set.
 
-Notes
-
 Each notification occupies 12 bytes in the fifo as follows:
 
 . .
-H (16 bit) seqno
-H (16 bit) flags
-I (32 bit) tick
-I (32 bit) level
+typedef struct
+{
+   uint16_t seqno;
+   uint16_t flags;
+   uint32_t tick;
+   uint32_t level;
+} gpioReport_t;
 . .
+
+seqno: starts at 0 each time the handle is opened and then increments
+by one for each report.
+
+flags: two flags are defined, PI_NTFY_FLAGS_WDOG and PI_NTFY_FLAGS_ALIVE.
+
+PI_NTFY_FLAGS_WDOG, if bit 5 is set then bits 0-4 of the flags
+indicate a GPIO which has had a watchdog timeout.
+
+PI_NTFY_FLAGS_ALIVE, if bit 6 is set this indicates a keep alive
+signal on the pipe/socket and is sent once a minute in the absence
+of other notification activity.
+
+tick: the number of microseconds since system boot.  It wraps around
+after 1h12m.
+
+level: indicates the level of each GPIO.  If bit 1<<x is set then
+GPIO x is high.
 D*/
 
 /*F*/
@@ -2489,11 +2522,13 @@ D*/
 int serial_open(int pi, char *ser_tty, unsigned baud, unsigned ser_flags);
 /*D
 This function opens a serial device at a specified baud rate
-with specified flags.
+with specified flags.  The device name must start with
+/dev/tty or /dev/serial.
+
 
 . .
        pi: >=0 (as returned by [*pigpio_start*]).
-  ser_tty: the serial device to open, /dev/tty*.
+  ser_tty: the serial device to open.
      baud: the baud rate in bits per second, see below.
 ser_flags: 0.
 . .
@@ -2641,6 +2676,369 @@ Returns >= 0 if OK, less than 0 indicates a user defined error.
 Note, the number of returned bytes will be retMax or less.
 D*/
 
+/*F*/
+int get_pad_strength(int pi, unsigned pad);
+/*D
+This function returns the pad drive strength in mA.
+
+. .
+ pi: >=0 (as returned by [*pigpio_start*]).
+pad: 0-2, the pad to get.
+. .
+
+Returns the pad drive strength if OK, otherwise PI_BAD_PAD.
+
+Pad @ GPIO
+0   @ 0-27
+1   @ 28-45
+2   @ 46-53
+
+...
+strength = get_pad_strength(pi, 0); //  get pad 0 strength
+...
+D*/
+
+
+/*F*/
+int set_pad_strength(int pi, unsigned pad, unsigned padStrength);
+/*D
+This function sets the pad drive strength in mA.
+
+. .
+         pi: >=0 (as returned by [*pigpio_start*]).
+        pad: 0-2, the pad to set.
+padStrength: 1-16 mA.
+. .
+
+Returns 0 if OK, otherwise PI_BAD_PAD, or PI_BAD_STRENGTH.
+
+Pad @ GPIO
+0   @ 0-27
+1   @ 28-45
+2   @ 46-53
+
+...
+set_pad_strength(pi, 0, 10); // set pad 0 strength to 10 mA
+...
+D*/
+
+
+/*F*/
+int shell_(int pi, char *scriptName, char *scriptString);
+/*D
+This function uses the system call to execute a shell script
+with the given string as its parameter.
+
+. .
+          pi: >=0 (as returned by [*pigpio_start*]).
+  scriptName: the name of the script, only alphanumeric characters,
+              '-' and '_' are allowed in the name.
+scriptString: the string to pass to the script.
+. .
+
+The exit status of the system call is returned if OK, otherwise
+PI_BAD_SHELL_STATUS.
+
+scriptName must exist in /opt/pigpio/cgi and must be executable.
+
+The returned exit status is normally 256 times that set by the
+shell script exit function.  If the script can't be found 32512 will
+be returned.
+
+The following table gives some example returned statuses.
+
+Script exit status @ Returned system call status
+1                  @ 256
+5                  @ 1280
+10                 @ 2560
+200                @ 51200
+script not found   @ 32512
+
+...
+// pass two parameters, hello and world
+status = shell_(pi, "scr1", "hello world");
+
+// pass three parameters, hello, string with spaces, and world
+status = shell_(pi, "scr1", "hello 'string with spaces' world");
+
+// pass one parameter, hello string with spaces world
+status = shell_(pi, "scr1", "\"hello string with spaces world\"");
+...
+D*/
+
+#pragma GCC diagnostic push
+
+#pragma GCC diagnostic ignored "-Wcomment"
+
+/*F*/
+int file_open(int pi, char *file, unsigned mode);
+/*D
+This function returns a handle to a file opened in a specified mode.
+
+. .
+  pi: >=0 (as returned by [*pigpio_start*]).
+file: the file to open.
+mode: the file open mode.
+. .
+
+Returns a handle (>=0) if OK, otherwise PI_NO_HANDLE, PI_NO_FILE_ACCESS,
+PI_BAD_FILE_MODE, PI_FILE_OPEN_FAILED, or PI_FILE_IS_A_DIR.
+
+File
+
+A file may only be opened if permission is granted by an entry in
+/opt/pigpio/access.  This is intended to allow remote access to files
+in a more or less controlled manner.
+
+Each entry in /opt/pigpio/access takes the form of a file path
+which may contain wildcards followed by a single letter permission.
+The permission may be R for read, W for write, U for read/write,
+and N for no access.
+
+Where more than one entry matches a file the most specific rule
+applies.  If no entry matches a file then access is denied.
+
+Suppose /opt/pigpio/access contains the following entries
+
+. .
+/home/* n
+/home/pi/shared/dir_1/* w
+/home/pi/shared/dir_2/* r
+/home/pi/shared/dir_3/* u
+/home/pi/shared/dir_1/file.txt n
+. .
+
+Files may be written in directory dir_1 with the exception
+of file.txt.
+
+Files may be read in directory dir_2.
+
+Files may be read and written in directory dir_3.
+
+If a directory allows read, write, or read/write access then files may
+be created in that directory.
+
+In an attempt to prevent risky permissions the following paths are
+ignored in /opt/pigpio/access.
+
+. .
+a path containing ..
+a path containing only wildcards (*?)
+a path containing less than two non-wildcard parts
+. .
+
+Mode
+
+The mode may have the following values.
+
+Macro         @ Value @ Meaning
+PI_FILE_READ  @   1   @ open file for reading
+PI_FILE_WRITE @   2   @ open file for writing
+PI_FILE_RW    @   3   @ open file for reading and writing
+
+The following values may be or'd into the mode.
+
+Macro          @ Value @ Meaning
+PI_FILE_APPEND @ 4     @ Writes append data to the end of the file
+PI_FILE_CREATE @ 8     @ The file is created if it doesn't exist
+PI_FILE_TRUNC  @ 16    @ The file is truncated
+
+Newly created files are owned by root with permissions owner read and write.
+
+...
+#include <stdio.h>
+#include <pigpiod_if2.h>
+
+int main(int argc, char *argv[])
+{
+   int pi, handle, c;
+   char buf[60000];
+
+   pi = pigpio_start(NULL, NULL);
+
+   if (pi < 0) return 1;
+
+   // assumes /opt/pigpio/access contains the following line
+   // /ram/*.c r
+
+   handle = file_open(pi, "/ram/pigpio.c", PI_FILE_READ);
+
+   if (handle >= 0)
+   {
+      while ((c=file_read(pi, handle, buf, sizeof(buf)-1)))
+      {
+         buf[c] = 0;
+         printf("%s", buf);
+      }
+
+      file_close(pi, handle);
+   }
+
+   pigpio_stop(pi);
+}
+...
+D*/
+
+#pragma GCC diagnostic pop
+
+/*F*/
+int file_close(int pi, unsigned handle);
+/*D
+This function closes the file associated with handle.
+
+. .
+    pi: >=0 (as returned by [*pigpio_start*]).
+handle: >=0 (as returned by [*file_open*]).
+. .
+
+Returns 0 if OK, otherwise PI_BAD_HANDLE.
+
+...
+file_close(pi, handle);
+...
+D*/
+
+
+/*F*/
+int file_write(int pi, unsigned handle, char *buf, unsigned count);
+/*D
+This function writes count bytes from buf to the the file
+associated with handle.
+
+. .
+    pi: >=0 (as returned by [*pigpio_start*]).
+handle: >=0 (as returned by [*file_open*]).
+   buf: the array of bytes to write.
+ count: the number of bytes to write.
+. .
+
+Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM,
+PI_FILE_NOT_WOPEN, or PI_BAD_FILE_WRITE.
+
+...
+if (file_write(pi, handle, buf, 100) == 0)
+{
+   // file written okay
+}
+else
+{
+   // error
+}
+...
+D*/
+
+
+/*F*/
+int file_read(int pi, unsigned handle, char *buf, unsigned count);
+/*D
+This function reads up to count bytes from the the file
+associated with handle and writes them to buf.
+
+. .
+    pi: >=0 (as returned by [*pigpio_start*]).
+handle: >=0 (as returned by [*file_open*]).
+   buf: an array to receive the read data.
+ count: the maximum number of bytes to read.
+. .
+
+Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, PI_FILE_NOT_ROPEN, or PI_BAD_FILE_WRITE.
+
+...
+   bytes = file_read(pi, handle, buf, sizeof(buf));
+
+   if (bytes >= 0)
+   {
+      // process read data
+   }
+...
+D*/
+
+
+/*F*/
+int file_seek(int pi, unsigned handle, int32_t seekOffset, int seekFrom);
+/*D
+This function seeks to a position within the file associated
+with handle.
+
+. .
+        pi: >=0 (as returned by [*pigpio_start*]).
+    handle: >=0 (as returned by [*file_open*]).
+seekOffset: the number of bytes to move.  Positive offsets
+            move forward, negative offsets backwards.
+  seekFrom: one of PI_FROM_START (0), PI_FROM_CURRENT (1),
+            or PI_FROM_END (2).
+. .
+
+Returns the new byte position within the file (>=0) if OK, otherwise PI_BAD_HANDLE, or PI_BAD_FILE_SEEK.
+
+...
+file_seek(pi, handle, 123, PI_FROM_START); // Start plus 123
+
+size = file_seek(pi, handle, 0, PI_FROM_END); // End, return size
+
+pos = file_seek(pi, handle, 0, PI_FROM_CURRENT); // Current position
+...
+D*/
+
+#pragma GCC diagnostic push
+
+#pragma GCC diagnostic ignored "-Wcomment"
+
+/*F*/
+int file_list(int pi, char *fpat,  char *buf, unsigned count);
+/*D
+This function returns a list of files which match a pattern.
+
+. .
+   pi: >=0 (as returned by [*pigpio_start*]).
+ fpat: file pattern to match.
+  buf: an array to receive the matching file names.
+count: the maximum number of bytes to read.
+. .
+
+Returns the number of returned bytes if OK, otherwise PI_NO_FILE_ACCESS,
+or PI_NO_FILE_MATCH.
+
+The pattern must match an entry in /opt/pigpio/access.  The pattern
+may contain wildcards.  See [*file_open*].
+
+NOTE
+
+The returned value is not the number of files, it is the number
+of bytes in the buffer.  The file names are separated by newline
+characters.
+
+...
+#include <stdio.h>
+#include <pigpiod_if2.h>
+
+int main(int argc, char *argv[])
+{
+   int pi, handle, c;
+   char buf[60000];
+
+   pi = pigpio_start(NULL, NULL);
+
+   if (pi < 0) return 1;
+
+   // assumes /opt/pigpio/access contains the following line
+   // /ram/*.c r
+
+   c = file_list(pi, "/ram/p*.c", buf, sizeof(buf));
+
+   if (c >= 0)
+   {
+      buf[c] = 0;
+      printf("%s", buf);
+   }
+
+   pigpio_stop(pi);
+}
+...
+D*/
+
+#pragma GCC diagnostic pop
+
 
 /*F*/
 int callback(int pi, unsigned user_gpio, unsigned edge, CBFunc_t f);
@@ -2794,7 +3192,7 @@ clkfreq::4689-250000000 (250M)
 The hardware clock frequency.
 
 count::
-The number of bytes to be transferred in an I2C, SPI, or Serial
+The number of bytes to be transferred in a file, I2C, SPI, or serial
 command.
 
 data_bits::1-32
@@ -2831,21 +3229,28 @@ of the error.
 f::
 A function.
 
+*file::
+A full file path.  To be accessible the path must match an entry in
+/opt/pigpio/access.
+
+*fpat::
+A file path which may contain wildcards.  To be accessible the path
+must match an entry in /opt/pigpio/access.
+
 frequency::>=0
 The number of times a GPIO is swiched on and off per second.  This
 can be set per GPIO and may be as little as 5Hz or as much as
 40KHz.  The GPIO will be on for a proportion of the time as defined
 by its dutycycle.
 
-
 gpio::
 A Broadcom numbered GPIO, in the range 0-53.
 
-There  are 54 General Purpose Input Outputs (GPIO) named gpio0 through
-gpio53.
+There  are 54 General Purpose Input Outputs (GPIO) named GPIO0 through
+GPIO53.
 
-They are split into two  banks.   Bank  1  consists  of  gpio0  through
-gpio31.  Bank 2 consists of gpio32 through gpio53.
+They are split into two  banks.   Bank  1  consists  of  GPIO0  through
+GPIO31.  Bank 2 consists of GPIO32 through GPIO53.
 
 All the GPIO which are safe for the user to read and write are in
 bank 1.  Not all GPIO in bank 1 are safe though.  Type 1 boards
@@ -2883,8 +3288,8 @@ typedef void *(gpioThreadFunc_t) (void *);
 . .
 
 handle::>=0
-A number referencing an object opened by one of [*i2c_open*], [*notify_open*],
-[*serial_open*], and [*spi_open*].
+A number referencing an object opened by one of [*file_open*],
+[*i2c_open*], [*notify_open*], [*serial_open*], and [*spi_open*].
 
 i2c_addr::0-0x7F
 The address of a device on the I2C bus.
@@ -2907,6 +3312,9 @@ The number of bytes of data in a buffer.
 int::
 A whole number, negative or positive.
 
+int32_t::
+A 32-bit signed value.
+
 invert::
 A flag used to set normal or inverted bit bang serial data level logic.
 
@@ -2954,6 +3362,23 @@ PI_WAVE_MODE_ONE_SHOT_SYNC 2
 PI_WAVE_MODE_REPEAT_SYNC   3
 . .
 
+3. A file open mode.
+
+. .
+PI_FILE_READ  1
+PI_FILE_WRITE 2
+PI_FILE_RW    3
+. .
+
+The following values can be or'd into the mode.
+
+. .
+PI_FILE_APPEND 4
+PI_FILE_CREATE 8
+PI_FILE_TRUNC  16
+. .
+
+
 numBytes::
 The number of bytes used to store characters in a string.  Depending
 on the number of bits per character there may be 1, 2, or 4 bytes
@@ -2975,6 +3400,18 @@ A buffer used to return data from a function.
 outLen::
 The size in bytes of an output buffer.
 
+pad:: 0-2
+A set of GPIO which share common drivers.
+
+Pad @ GPIO
+0   @ 0-27
+1   @ 28-45
+2   @ 46-53
+
+padStrength:: 1-16
+The mA which may be drawn from each GPIO whilst still guaranteeing the
+high and low levels.
+
 *param::
 An array of script parameters.
 
@@ -3058,12 +3495,31 @@ A pointer to the text of a script.
 script_id::
 An id of a stored script as returned by [*store_script*].
 
+*scriptName::
+The name of a [*shell_*] script to be executed.  The script must be present in
+/opt/pigpio/cgi and must have execute permission.
+
+*scriptString::
+The string to be passed to a [*shell_*] script to be executed.
+
 SDA::
 The user GPIO to use for data when bit banging I2C.
 
 seconds::
 The number of seconds.
 
+seekFrom::
+
+. .
+PI_FROM_START   0
+PI_FROM_CURRENT 1
+PI_FROM_END     2
+. .
+
+seekOffset::
+The number of bytes to move forward (positive) or backwards (negative)
+from the seek position (start, current, or end of file).
+
 ser_flags::
 Flags which modify a serial open command.  None are currently defined.
 
diff --git a/pigs.1 b/pigs.1
index e55c554f5ae335d83e17fd52227b2607fb076782..28af5614b113211563419810e80ec179f7aad1c6 100644 (file)
--- a/pigs.1
+++ b/pigs.1
@@ -22,6 +22,10 @@ or
 
 .SH DESCRIPTION
 
+.ad l
+
+.nh
+
 
 .br
 The socket and pipe interfaces allow control of the GPIO by passing
@@ -45,10 +49,10 @@ whereas /dev/pigpio uses the pipe interface.
 .br
 .SS Features
 .br
-o PWM on any of GPIO 0-31
+o hardware timed PWM on any of GPIO 0-31
 
 .br
-o servo pulses on any of GPIO 0-31
+o hardware timed servo pulses on any of GPIO 0-31
 
 .br
 o reading/writing all of the GPIO in a bank as one operation
@@ -514,11 +518,40 @@ configuration settings to \fBv\fP.
 
 .br
 
+.IP "\fBFC h\fP - Close file handle"
+.IP "" 4
+This command closes a file handle \fBh\fP previously opened with \fBFO\fP.
+
+.br
+Upon success nothing is returned.  On error a negative status code
+will be returned.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs fc 0 # First close okay.
+.br
+
+.br
+$ pigs fc 0 # Second fails.
+.br
+-25
+.br
+ERROR: unknown handle
+.br
+
+.EE
+
+.br
+
 .IP "\fBFG u stdy\fP - Set a glitch filter on a GPIO"
 .IP "" 4
 
 .br
-Level changes on the GPIO are not reported unless the level
+Level changes on the GPIO \fBu\fP are not reported unless the level
 has been stable for at least \fBstdy\fP microseconds.  The
 level is then reported.  Level changes of less than \fBstdy\fP
 microseconds are ignored.
@@ -529,11 +562,77 @@ after it was first detected.
 
 .br
 
+\fBExample\fP
+.br
+
+.EX
+$ pigs fg 4 250
+.br
+
+.br
+$ pigs fg 4 1000000
+.br
+-125
+.br
+ERROR: bad filter parameter
+.br
+
+.EE
+
+.br
+
+.IP "\fBFL pat num\fP - List files which match pattern"
+.IP "" 4
+This command returns a list of the files matching \fBpat\fP. Up
+to \fBnum\fP bytes may be returned.
+
+.br
+Upon success the count of returned bytes followed by the matching
+files is returned.  On error a negative status code will be returned.
+
+.br
+A newline (0x0a) character separates each file name.
+
+.br
+Only files which have a matching entry in /opt/pigpio/access may
+be listed.
+
+.br
+Suppose /opt/pigpio/access contains
+
+.br
+/sys/bus/w1/devices/28*/w1_slave r
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs -a fl "/sys/bus/w1/devices/28*/w1_slave" 5000
+.br
+90 /sys/bus/w1/devices/28-000005d34cd2/w1_slave
+.br
+/sys/bus/w1/devices/28-001414abbeff/w1_slave
+.br
+
+.br
+$ pigs -a fl "/sys/bus/*" 5000
+.br
+ERROR: no permission to access file
+.br
+-137
+.br
+
+.EE
+
+.br
+
 .IP "\fBFN u stdy actv\fP - Set a noise filter on a GPIO"
 .IP "" 4
 
 .br
-Level changes on the GPIO are ignored until a level which has
+Level changes on the GPIO \fBu\fP are ignored until a level which has
 been stable for \fBstdy\fP microseconds is detected.  Level
 changes on the GPIO are then reported for \fBactv\fP microseconds
 after which the process repeats.
@@ -545,6 +644,311 @@ such reports.
 
 .br
 
+\fBExample\fP
+.br
+
+.EX
+$ pigs fn 7 250 1000
+.br
+
+.br
+$ pigs fn 7 2500000 1000
+.br
+-125
+.br
+ERROR: bad filter parameter
+.br
+
+.EE
+
+.br
+
+.IP "\fBFO file mode\fP - Open a file in mode"
+.IP "" 4
+This function returns a handle to a file \fBfile\fP opened
+in a specified mode \fBmode\fP.
+
+.br
+Upon success a handle (>=0) is returned.  On error a negative status code
+will be returned.
+
+.br
+File
+
+.br
+A file may only be opened if permission is granted by an entry in
+/opt/pigpio/access.  This is intended to allow remote access to files
+in a more or less controlled manner.
+
+.br
+Each entry in /opt/pigpio/access takes the form of a file path
+which may contain wildcards followed by a single letter permission.
+The permission may be R for read, W for write, U for read/write,
+and N for no access.
+
+.br
+Where more than one entry matches a file the most specific rule
+applies.  If no entry matches a file then access is denied.
+
+.br
+Suppose /opt/pigpio/access contains the following entries
+
+.br
+
+.EX
+/home/* n
+.br
+/home/pi/shared/dir_1/* w
+.br
+/home/pi/shared/dir_2/* r
+.br
+/home/pi/shared/dir_3/* u
+.br
+/home/pi/shared/dir_1/file.txt n
+.br
+
+.EE
+
+.br
+Files may be written in directory dir_1 with the exception
+of file.txt.
+
+.br
+Files may be read in directory dir_2.
+
+.br
+Files may be read and written in directory dir_3.
+
+.br
+If a directory allows read, write, or read/write access then files may
+be created in that directory.
+
+.br
+In an attempt to prevent risky permissions the following paths are
+ignored in /opt/pigpio/access.
+
+.br
+
+.EX
+a path containing ..
+.br
+a path containing only wildcards (*?)
+.br
+a path containing less than two non-wildcard parts
+.br
+
+.EE
+
+.br
+Mode
+
+.br
+The mode may have the following values.
+
+.br
+
+.EX
+        Value   Meaning
+READ      1     open file for reading
+WRITE     2     open file for writing
+RW        3     open file for reading and writing
+
+.EE
+
+.br
+The following values may be or'd into the mode.
+
+.br
+
+.EX
+         Value   Meaning
+APPEND     4     All writes append data to the end of the file
+CREATE     8     The file is created if it doesn't exist
+TRUNC     16     The file is truncated
+
+.EE
+
+.br
+Newly created files are owned by root with permissions owner read and write.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ ls /ram/*.c
+.br
+/ram/command.c      /ram/pigpiod.c  /ram/pigs.c
+.br
+/ram/x_pigpiod_if.c /ram/pig2vcd.c  /ram/pigpiod_if2.c
+.br
+/ram/x_pigpio.c     /ram/x_repeat.c /ram/pigpio.c
+.br
+/ram/pigpiod_if.c   /ram/x_pigpiod_if2.c
+.br
+
+.br
+# assumes /opt/pigpio/access contains the following line
+.br
+# /ram/*.c r
+.br
+
+.br
+$ pigs fo /ram/pigpio.c 1
+.br
+0
+.br
+
+.br
+$ pigs fo /ram/new.c 1
+.br
+-128
+.br
+ERROR: file open failed
+.br
+
+.br
+$ pigs fo /ram/new.c 9
+.br
+1
+.br
+
+.br
+$ ls /ram/*.c -l
+.br
+-rw-r--r-- 1 joan joan  42923 Jul 10 11:22 /ram/command.c
+.br
+-rw------- 1 root root      0 Jul 10 16:54 /ram/new.c
+.br
+-rw-r--r-- 1 joan joan   2971 Jul 10 11:22 /ram/pig2vcd.c
+.br
+-rw------- 1 joan joan 296235 Jul 10 11:22 /ram/pigpio.c
+.br
+-rw-r--r-- 1 joan joan   9266 Jul 10 11:22 /ram/pigpiod.c
+.br
+-rw-r--r-- 1 joan joan  37331 Jul 10 11:22 /ram/pigpiod_if2.c
+.br
+-rw-r--r-- 1 joan joan  33088 Jul 10 11:22 /ram/pigpiod_if.c
+.br
+-rw-r--r-- 1 joan joan   7990 Jul 10 11:22 /ram/pigs.c
+.br
+-rw-r--r-- 1 joan joan  19970 Jul 10 11:22 /ram/x_pigpio.c
+.br
+-rw-r--r-- 1 joan joan  20804 Jul 10 11:22 /ram/x_pigpiod_if2.c
+.br
+-rw-r--r-- 1 joan joan  19844 Jul 10 11:22 /ram/x_pigpiod_if.c
+.br
+-rw-r--r-- 1 joan joan  19907 Jul 10 11:22 /ram/x_repeat.c
+.br
+
+.EE
+
+.br
+
+.IP "\fBFR h num\fP - Read bytes from file handle"
+.IP "" 4
+This command returns up to \fBnum\fP bytes of data read from the
+file associated with handle \fBh\fP.
+
+.br
+Upon success the count of returned bytes followed by the bytes themselves
+is returned.  On error a negative status code will be returned.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs fr 0 10
+.br
+5 48 49 128 144 255
+.br
+
+.br
+$ pigs fr 0 10
+.br
+0
+.br
+
+.EE
+
+.br
+
+.IP "\fBFS h num from\fP - Seek to file handle position"
+.IP "" 4
+This command seeks to a position within the file associated
+with handle \fBh\fP.
+
+.br
+The number of bytes to move is \fBnum\fP.  Positive offsets
+move forward, negative offsets backwards.  The move start
+position is determined by \fBfrom\fP as follows.
+
+.br
+
+.EX
+    From
+0   start
+1   current position
+2   end
+
+.EE
+
+.br
+Upon success the new byte position within the file (>=0) is
+returned.  On error a negative status code will be returned.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs fs 0 0 0 # Seek to start of file plus 200
+.br
+200
+.br
+
+.br
+$ pigs fs 0 0 1 # Return current position
+.br
+200
+.br
+
+.br
+$ pigs fs 0 0 2 # Seek to end of file, return size
+.br
+296235
+.br
+
+.EE
+
+.br
+
+.IP "\fBFW h bvs\fP - Write bytes to file handle"
+.IP "" 4
+This command writes bytes \fBbvs\fP to the file
+associated with handle \fBh\fP.
+
+.br
+Upon success nothing is returned.  On error a negative status code
+will be returned.
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs fw 0 23 45 67 89
+.br
+
+.EE
+
+.br
+
 .IP "\fBGDC u\fP - Get GPIO PWM dutycycle"
 .IP "" 4
 
@@ -1710,6 +2114,96 @@ $ pigs p 4 255 # 100%
 
 .br
 
+.IP "\fBPADG pad\fP - Get pad drive strength"
+.IP "" 4
+
+.br
+This command gets the \fBpad\fP drive strength \fBpadma\fP in mA.
+
+.br
+Returns the pad drive strength if OK.  On error a negative status code
+will be returned.
+
+.br
+
+.EX
+Pad   GPIO
+0     0-27
+1     28-45
+2     46-53
+
+.EE
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs padg 0
+.br
+8
+.br
+$ pigs pads 0 16
+.br
+$ pigs padg 0
+.br
+16
+.br
+pigs padg 3
+.br
+-126
+.br
+ERROR: bad pad number
+.br
+
+.EE
+
+.br
+
+.IP "\fBPADS pad padma\fP - Set pad drive strength"
+.IP "" 4
+
+.br
+This command sets the \fBpad\fP drive strength \fBpadma\fP in mA.
+
+.br
+Upon success nothing is returned.  On error a negative status code
+will be returned.
+
+.br
+
+.EX
+Pad   GPIO
+0     0-27
+1     28-45
+2     46-53
+
+.EE
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+$ pigs pads 0 16
+.br
+$ pigs padg 0
+.br
+16
+.br
+$ pigs pads 0 17
+.br
+-127
+.br
+ERROR: bad pad drive strength
+.br
+
+.EE
+
+.br
+
 .IP "\fBPARSE t\fP - Validate script"
 .IP "" 4
 
@@ -2447,8 +2941,9 @@ Upon success a handle (>=0) is returned.  On error a negative status code
 will be returned.
 
 .br
-The UART is /dev/ttyAMA0.  The consoles are /dev/ttyx.  The USB
-devices are /dev/ttyUSBx.
+The device name must start with /dev/tty or /dev/serial.
+
+.br
 
 .br
 The baud rate must be one of 50, 75, 110, 134, 150,
@@ -2588,6 +3083,81 @@ $ pigs serwb 0 0xf0
 
 .br
 
+.IP "\fBSHELL name str\fP - Execute a shell command"
+.IP "" 4
+
+.br
+This command uses the system call to execute a shell script \fBname\fP
+with the given string \fBstr\fP as its parameter.
+
+.br
+The exit status of the system call is returned if OK, otherwise
+PI_BAD_SHELL_STATUS.
+
+.br
+\fBname\fP must exist in /opt/pigpio/cgi and must be executable.
+
+.br
+The returned exit status is normally 256 times that set
+by the shell script exit function.  If the script can't
+be found 32512 will be returned.
+
+.br
+The following table gives some example returned statuses.
+
+.br
+
+.EX
+Script exit status   Returned system call status
+1                    256
+5                    1280
+10                   2560
+200                  51200
+script not found     32512
+
+.EE
+
+.br
+
+\fBExample\fP
+.br
+
+.EX
+# pass two parameters, hello and world
+.br
+$ pigs shell scr1 hello world
+.br
+256
+.br
+
+.br
+# pass three parameters, hello, string with spaces, and world
+.br
+$ pigs shell scr1 "hello 'string with spaces' world"
+.br
+256
+.br
+
+.br
+# pass one parameter, hello string with spaces world
+.br
+$ pigs shell scr1 "\"hello string with spaces world\""
+.br
+256
+.br
+
+.br
+# non-existent script
+.br
+$ pigs shell scr78 par1
+.br
+32512
+.br
+
+.EE
+
+.br
+
 .IP "\fBSLR u num\fP - Read bit bang serial data from GPIO"
 .IP "" 4
 
@@ -3916,7 +4486,7 @@ The command expects the number of data bits per serial character.
 
 .br
 
-.IP "\fBdev\fP - a tty serial device (/dev/tty*)" 0
+.IP "\fBdev\fP - a tty serial device (/dev/tty* or /dev/serial*)" 0
 The command expects the name of a tty serial device, e.g.
 
 .br
@@ -3928,6 +4498,28 @@ The command expects the name of a tty serial device, e.g.
 .br
 /dev/tty0
 .br
+/dev/serial0
+.br
+
+.EE
+
+.br
+
+.IP "\fBfile\fP - a file name" 0
+The file name must match an entry in /opt/pigpio/access.
+
+.br
+
+.IP "\fBfrom\fP - 0-2" 0
+Position to seek from \fBFS\fP.
+
+.br
+
+.EX
+    From
+0   start
+1   current position
+2   end
 
 .EE
 
@@ -3979,8 +4571,8 @@ of doing so range from no effect, to a crash, or corrupted data.
 The command expects a handle.
 
 .br
-A handle is a number referencing an object opened by one of \fBI2CO\fP, \fBNO\fP,
-\fBSERO\fP, \fBSPIO\fP.
+A handle is a number referencing an object opened by one of \fBFO\fP,
+\fBI2CO\fP, \fBNO\fP, \fBSERO\fP, \fBSPIO\fP.
 
 .br
 
@@ -4020,24 +4612,58 @@ The value is returned by the mode get command.
 .br
 
 .EX
-Mode   Input Output ALT0 ALT1 ALT2 ALT3 ALT4 ALT5
-Code       R      W    0    1    2    3    4    5
-Value      0      1    4    5    6    7    3    2
+Mode    Input   Output   ALT0   ALT1   ALT2   ALT3   ALT4   ALT5
+Code      R        W       0      1      2      3      4      5
+Value     0        1       4      5      6      7      3      2
+
+.EE
+
+.br
+
+.IP "\fBmode\fP - file open mode" 0
+One of the following values.
+
+.br
+
+.EX
+        Value   Meaning
+READ      1     open file for reading
+WRITE     2     open file for writing
+RW        3     open file for reading and writing
+
+.EE
+
+.br
+The following values can be or'd into the mode.
+
+.br
+
+.EX
+         Value   Meaning
+APPEND   4       All writes append data to the end of the file
+CREATE   8       The file is created if it doesn't exist
+TRUNC    16      The file is truncated
 
 .EE
 
 .br
 
-.IP "\fBnum\fP - number of bytes to read (1-)" 0
-The command expects the number of bytes to read.
+.IP "\fBname\fP - the name of a script" 0
+Only alphanumeric characters, '-' and '_' are allowed in the name.
+
+.br
+
+.IP "\fBnum\fP - maximum number of bytes to return (1-)" 0
+The command expects the maximum number of bytes to return.
 
 .br
 For the I2C and SPI commands the requested number of bytes will always
 be returned.
 
 .br
-For the serial commands the smaller of the number of bytes available to be
-read (which may be zero) and \fBnum\fP bytes will be returned.
+For the serial and file commands the smaller of the number of
+bytes available to be read (which may be zero) and \fBnum\fP bytes
+will be returned.
 
 .br
 
@@ -4075,11 +4701,38 @@ There is no mechanism to read the pull up down state.
 
 .br
 
+.IP "\fBpad\fP - 0-2" 0
+A set of GPIO which share common drivers.
+
+.br
+
+.EX
+Pad   GPIO
+0     0-27
+1     28-45
+2     46-53
+
+.EE
+
+.br
+
+.IP "\fBpadma\fP - 1-16" 0
+The mA which may be drawn from each GPIO whilst still guaranteeing the
+high and low levels.
+
+.br
+
 .IP "\fBpars\fP - script parameters" 0
 The command expects 0 to 10 numbers as parameters to be passed to the script.
 
 .br
 
+.IP "\fBpat\fP - a file name pattern" 0
+A file path which may contain wildcards.  To be accessible the path
+must match an entry in /opt/pigpio/access.
+
+.br
+
 .IP "\fBpdc\fP - hardware PWM dutycycle (0-1000000)" 0
 The command expects a dutycycle.
 
@@ -4141,8 +4794,13 @@ the active part of a noise filter (\fBFN\fP).
 
 .br
 
-.IP "\fBt\fP - text (a string of text)" 0
-The command expects a text string.
+.IP "\fBstr\fP - a string" 0
+The command expects a string.
+
+.br
+
+.IP "\fBt\fP - a string" 0
+The command expects a string.
 
 .br
 
diff --git a/pigs.c b/pigs.c
index 1e87d3c7c41c41e8cfe1acdc856fe8c12caf9e03..d4c91d0102d583c054d0c6dc326498f77ba789ad 100644 (file)
--- a/pigs.c
+++ b/pigs.c
@@ -26,7 +26,7 @@ For more information, please refer to <http://unlicense.org/>
 */
 
 /*
-This version is for pigpio version 34+
+This version is for pigpio version 55+
 */
 
 #include <stdio.h>
@@ -48,8 +48,8 @@ This program provides a socket interface to some of
 the commands available from pigpio.
 */
 
-char command_buf[8192];
-char response_buf[8192];
+char command_buf[CMD_MAX_EXTENSION];
+char response_buf[CMD_MAX_EXTENSION];
 
 int printFlags = 0;
 
@@ -171,7 +171,10 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
          printf("%s", cmdUsage);
          break;
 
-      case 6: /* BI2CZ CF2 I2CPK I2CRD I2CRI I2CRK I2CZ SERR SLR SPIX SPIR */
+      case 6: /*
+                 BI2CZ  CF2  FL  FR  I2CPK  I2CRD  I2CRI  I2CRK  I2CZ
+                 SERR  SLR  SPIX  SPIR
+              */
          printf("%d", r);
          if (r < 0) fatal("ERROR: %s", cmdErrStr(r));
          if (r > 0)
@@ -186,7 +189,8 @@ void print_result(int sock, int rv, cmdCmd_t cmd)
 
                else if (printFlags & PRINT_ASCII)
                {
-                  if ((ch > 31) && (ch < 127)) printf("%c", ch);
+                  if (isprint(ch) || (ch == '\n') || (ch == '\r'))
+                     printf("%c", ch);
                   else printf("\\x%02hhx", ch);
                }
                else printf(" %hhu", response_buf[i]);
@@ -221,6 +225,8 @@ void get_extensions(int sock, int command, int res)
    {
       case PI_CMD_BI2CZ:
       case PI_CMD_CF2:
+      case PI_CMD_FL:
+      case PI_CMD_FR:
       case PI_CMD_I2CPK:
       case PI_CMD_I2CRD:
       case PI_CMD_I2CRI:
index 3e0a76da762927a16e85c13f1a7f94b38565515d..a10af60ec2b58cddc4a8c2dc4530eb51634a911b 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
 from distutils.core import setup
 
 setup(name='pigpio',
-      version='1.31',
+      version='1.32',
       author='joan',
       author_email='joan@abyz.co.uk',
       maintainer='joan',
diff --git a/x_pigs b/x_pigs
index 1435493a11476f3ce28e8a0672e5dd7e512d0738..38fe12029da5e1a24a1741788116656421f68528 100755 (executable)
--- a/x_pigs
+++ b/x_pigs
@@ -50,7 +50,7 @@ s=$(pigs bs2 0)
 if [[ $s = "" ]]; then echo "BS2 ok"; else echo "BS2 fail ($s)"; fi
 
 s=$(pigs h)
-if [[ ${#s} = 4593 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
+if [[ ${#s} = 4966 ]]; then echo "HELP ok"; else echo "HELP fail (${#s})"; fi
 
 s=$(pigs hwver)
 if [[ $s -ne 0 ]]; then echo "HWVER ok"; else echo "HWVER fail ($s)"; fi