This commit is contained in:
joan 2015-11-22 10:49:55 +00:00
parent 92bd13d857
commit 88c63e3e9f
3 changed files with 202 additions and 61 deletions

View File

@ -1369,6 +1369,21 @@ else
.EE .EE
.IP "\fBint gpioNotifyOpenWithSize(int bufSize)\fP"
.IP "" 4
This function requests a free notification handle.
.br
.br
It differs from \fBgpioNotifyOpen\fP in that the pipe size may be
specified, whereas \fBgpioNotifyOpen\fP uses the default pipe size.
.br
.br
See \fBgpioNotifyOpen\fP for further details.
.IP "\fBint gpioNotifyBegin(unsigned handle, uint32_t bits)\fP" .IP "\fBint gpioNotifyBegin(unsigned handle, uint32_t bits)\fP"
.IP "" 4 .IP "" 4
This function starts notifications on a previously opened handle. This function starts notifications on a previously opened handle.

233
pigpio.c
View File

@ -25,10 +25,12 @@ OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/> For more information, please refer to <http://unlicense.org/>
*/ */
/* pigpio version 40 */ /* pigpio version 41 */
/* include ------------------------------------------------------- */ /* include ------------------------------------------------------- */
#define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
@ -39,11 +41,11 @@ For more information, please refer to <http://unlicense.org/>
#include <syslog.h> #include <syslog.h>
#include <poll.h> #include <poll.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h>
#include <termios.h> #include <termios.h>
#include <signal.h> #include <signal.h>
#include <errno.h> #include <errno.h>
#include <time.h> #include <time.h>
#include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <limits.h> #include <limits.h>
#include <pthread.h> #include <pthread.h>
@ -2966,7 +2968,7 @@ int rawWaveAddGeneric(unsigned numIn1, rawWave_t *in1)
int i2cWriteQuick(unsigned handle, unsigned bit) int i2cWriteQuick(unsigned handle, unsigned bit)
{ {
int err; int status;
DBG(DBG_USER, "handle=%d bit=%d", handle, bit); DBG(DBG_USER, "handle=%d bit=%d", handle, bit);
@ -2984,17 +2986,22 @@ int i2cWriteQuick(unsigned handle, unsigned bit)
if (bit > 1) if (bit > 1)
SOFT_ERROR(PI_BAD_PARAM, "bad bit (%d)", bit); SOFT_ERROR(PI_BAD_PARAM, "bad bit (%d)", bit);
err = my_smbus_access( status = my_smbus_access(
i2cInfo[handle].fd, bit, 0, PI_I2C_SMBUS_QUICK, NULL); i2cInfo[handle].fd, bit, 0, PI_I2C_SMBUS_QUICK, NULL);
if (err < 0) return PI_I2C_WRITE_FAILED; if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_WRITE_FAILED;
}
return err; return status;
} }
int i2cReadByte(unsigned handle) int i2cReadByte(unsigned handle)
{ {
union my_smbus_data data; union my_smbus_data data;
int status;
DBG(DBG_USER, "handle=%d", handle); DBG(DBG_USER, "handle=%d", handle);
@ -3009,17 +3016,22 @@ int i2cReadByte(unsigned handle)
if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_BYTE) == 0) if ((i2cInfo[handle].funcs & PI_I2C_FUNC_SMBUS_READ_BYTE) == 0)
SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver"); SOFT_ERROR(PI_BAD_SMBUS_CMD, "SMBUS command not supported by driver");
if (my_smbus_access( status = my_smbus_access(
i2cInfo[handle].fd, PI_I2C_SMBUS_READ, 0, PI_I2C_SMBUS_BYTE, &data)) i2cInfo[handle].fd, PI_I2C_SMBUS_READ, 0, PI_I2C_SMBUS_BYTE, &data);
if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_READ_FAILED; return PI_I2C_READ_FAILED;
else }
return 0xFF & data.byte;
return 0xFF & data.byte;
} }
int i2cWriteByte(unsigned handle, unsigned bVal) int i2cWriteByte(unsigned handle, unsigned bVal)
{ {
int err; int status;
DBG(DBG_USER, "handle=%d bVal=%d", handle, bVal); DBG(DBG_USER, "handle=%d bVal=%d", handle, bVal);
@ -3037,22 +3049,27 @@ int i2cWriteByte(unsigned handle, unsigned bVal)
if (bVal > 0xFF) if (bVal > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad bVal (%d)", bVal); SOFT_ERROR(PI_BAD_PARAM, "bad bVal (%d)", bVal);
err = my_smbus_access( status = my_smbus_access(
i2cInfo[handle].fd, i2cInfo[handle].fd,
PI_I2C_SMBUS_WRITE, PI_I2C_SMBUS_WRITE,
bVal, bVal,
PI_I2C_SMBUS_BYTE, PI_I2C_SMBUS_BYTE,
NULL); NULL);
if (err < 0) return PI_I2C_WRITE_FAILED; if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_WRITE_FAILED;
}
return err; return status;
} }
int i2cReadByteData(unsigned handle, unsigned reg) int i2cReadByteData(unsigned handle, unsigned reg)
{ {
union my_smbus_data data; union my_smbus_data data;
int status;
DBG(DBG_USER, "handle=%d reg=%d", handle, reg); DBG(DBG_USER, "handle=%d reg=%d", handle, reg);
@ -3070,11 +3087,16 @@ int i2cReadByteData(unsigned handle, unsigned reg)
if (reg > 0xFF) if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg); SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (my_smbus_access( status = my_smbus_access(i2cInfo[handle].fd,
i2cInfo[handle].fd, PI_I2C_SMBUS_READ, reg, PI_I2C_SMBUS_BYTE_DATA, &data)) PI_I2C_SMBUS_READ, reg, PI_I2C_SMBUS_BYTE_DATA, &data);
if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_READ_FAILED; return PI_I2C_READ_FAILED;
else }
return 0xFF & data.byte;
return 0xFF & data.byte;
} }
@ -3082,7 +3104,7 @@ int i2cWriteByteData(unsigned handle, unsigned reg, unsigned bVal)
{ {
union my_smbus_data data; union my_smbus_data data;
int err; int status;
DBG(DBG_USER, "handle=%d reg=%d bVal=%d", handle, reg, bVal); DBG(DBG_USER, "handle=%d reg=%d bVal=%d", handle, reg, bVal);
@ -3105,22 +3127,27 @@ int i2cWriteByteData(unsigned handle, unsigned reg, unsigned bVal)
data.byte = bVal; data.byte = bVal;
err = my_smbus_access( status = my_smbus_access(
i2cInfo[handle].fd, i2cInfo[handle].fd,
PI_I2C_SMBUS_WRITE, PI_I2C_SMBUS_WRITE,
reg, reg,
PI_I2C_SMBUS_BYTE_DATA, PI_I2C_SMBUS_BYTE_DATA,
&data); &data);
if (err < 0) return PI_I2C_WRITE_FAILED; if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_WRITE_FAILED;
}
return err; return status;
} }
int i2cReadWordData(unsigned handle, unsigned reg) int i2cReadWordData(unsigned handle, unsigned reg)
{ {
union my_smbus_data data; union my_smbus_data data;
int status;
DBG(DBG_USER, "handle=%d reg=%d", handle, reg); DBG(DBG_USER, "handle=%d reg=%d", handle, reg);
@ -3138,15 +3165,20 @@ int i2cReadWordData(unsigned handle, unsigned reg)
if (reg > 0xFF) if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg); SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (my_smbus_access( status = (my_smbus_access(
i2cInfo[handle].fd, i2cInfo[handle].fd,
PI_I2C_SMBUS_READ, PI_I2C_SMBUS_READ,
reg, reg,
PI_I2C_SMBUS_WORD_DATA, PI_I2C_SMBUS_WORD_DATA,
&data)) &data));
if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_READ_FAILED; return PI_I2C_READ_FAILED;
else }
return 0xFFFF & data.word;
return 0xFFFF & data.word;
} }
@ -3154,7 +3186,7 @@ int i2cWriteWordData(unsigned handle, unsigned reg, unsigned wVal)
{ {
union my_smbus_data data; union my_smbus_data data;
int err; int status;
DBG(DBG_USER, "handle=%d reg=%d wVal=%d", handle, reg, wVal); DBG(DBG_USER, "handle=%d reg=%d wVal=%d", handle, reg, wVal);
@ -3177,22 +3209,27 @@ int i2cWriteWordData(unsigned handle, unsigned reg, unsigned wVal)
data.word = wVal; data.word = wVal;
err = my_smbus_access( status = my_smbus_access(
i2cInfo[handle].fd, i2cInfo[handle].fd,
PI_I2C_SMBUS_WRITE, PI_I2C_SMBUS_WRITE,
reg, reg,
PI_I2C_SMBUS_WORD_DATA, PI_I2C_SMBUS_WORD_DATA,
&data); &data);
if (err < 0) return PI_I2C_WRITE_FAILED; if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_WRITE_FAILED;
}
return err; return status;
} }
int i2cProcessCall(unsigned handle, unsigned reg, unsigned wVal) int i2cProcessCall(unsigned handle, unsigned reg, unsigned wVal)
{ {
union my_smbus_data data; union my_smbus_data data;
int status;
DBG(DBG_USER, "handle=%d reg=%d wVal=%d", handle, reg, wVal); DBG(DBG_USER, "handle=%d reg=%d wVal=%d", handle, reg, wVal);
@ -3215,14 +3252,19 @@ int i2cProcessCall(unsigned handle, unsigned reg, unsigned wVal)
data.word = wVal; data.word = wVal;
if (my_smbus_access( status = (my_smbus_access(
i2cInfo[handle].fd, i2cInfo[handle].fd,
PI_I2C_SMBUS_WRITE, PI_I2C_SMBUS_WRITE,
reg, PI_I2C_SMBUS_PROC_CALL, reg, PI_I2C_SMBUS_PROC_CALL,
&data)) &data));
if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_READ_FAILED; return PI_I2C_READ_FAILED;
else }
return 0xFFFF & data.word;
return 0xFFFF & data.word;
} }
@ -3230,7 +3272,7 @@ int i2cReadBlockData(unsigned handle, unsigned reg, char *buf)
{ {
union my_smbus_data data; union my_smbus_data data;
int i; int i, status;
DBG(DBG_USER, "handle=%d reg=%d buf=%08X", handle, reg, (unsigned)buf); DBG(DBG_USER, "handle=%d reg=%d buf=%08X", handle, reg, (unsigned)buf);
@ -3248,13 +3290,18 @@ int i2cReadBlockData(unsigned handle, unsigned reg, char *buf)
if (reg > 0xFF) if (reg > 0xFF)
SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg); SOFT_ERROR(PI_BAD_PARAM, "bad reg (%d)", reg);
if (my_smbus_access( status = (my_smbus_access(
i2cInfo[handle].fd, i2cInfo[handle].fd,
PI_I2C_SMBUS_READ, PI_I2C_SMBUS_READ,
reg, reg,
PI_I2C_SMBUS_BLOCK_DATA, PI_I2C_SMBUS_BLOCK_DATA,
&data)) &data));
if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_READ_FAILED; return PI_I2C_READ_FAILED;
}
else else
{ {
if (data.block[0] <= PI_I2C_SMBUS_BLOCK_MAX) if (data.block[0] <= PI_I2C_SMBUS_BLOCK_MAX)
@ -3272,7 +3319,7 @@ int i2cWriteBlockData(
{ {
union my_smbus_data data; union my_smbus_data data;
int i, err; int i, status;
DBG(DBG_USER, "handle=%d reg=%d count=%d [%s]", DBG(DBG_USER, "handle=%d reg=%d count=%d [%s]",
handle, reg, count, myBuf2Str(count, buf)); handle, reg, count, myBuf2Str(count, buf));
@ -3297,16 +3344,20 @@ int i2cWriteBlockData(
for (i=1; i<=count; i++) data.block[i] = buf[i-1]; for (i=1; i<=count; i++) data.block[i] = buf[i-1];
data.block[0] = count; data.block[0] = count;
err = my_smbus_access( status = my_smbus_access(
i2cInfo[handle].fd, i2cInfo[handle].fd,
PI_I2C_SMBUS_WRITE, PI_I2C_SMBUS_WRITE,
reg, reg,
PI_I2C_SMBUS_BLOCK_DATA, PI_I2C_SMBUS_BLOCK_DATA,
&data); &data);
if (err < 0) return PI_I2C_WRITE_FAILED; if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_WRITE_FAILED;
}
return err; return status;
} }
@ -3315,7 +3366,7 @@ int i2cBlockProcessCall(
{ {
union my_smbus_data data; union my_smbus_data data;
int i; int i, status;
DBG(DBG_USER, "handle=%d reg=%d count=%d [%s]", DBG(DBG_USER, "handle=%d reg=%d count=%d [%s]",
handle, reg, count, myBuf2Str(count, buf)); handle, reg, count, myBuf2Str(count, buf));
@ -3339,10 +3390,16 @@ int i2cBlockProcessCall(
for (i=1; i<=count; i++) data.block[i] = buf[i-1]; for (i=1; i<=count; i++) data.block[i] = buf[i-1];
data.block[0] = count; data.block[0] = count;
if (my_smbus_access(
status = (my_smbus_access(
i2cInfo[handle].fd, PI_I2C_SMBUS_WRITE, reg, i2cInfo[handle].fd, PI_I2C_SMBUS_WRITE, reg,
PI_I2C_SMBUS_BLOCK_PROC_CALL, &data)) PI_I2C_SMBUS_BLOCK_PROC_CALL, &data));
if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_READ_FAILED; return PI_I2C_READ_FAILED;
}
else else
{ {
if (data.block[0] <= PI_I2C_SMBUS_BLOCK_MAX) if (data.block[0] <= PI_I2C_SMBUS_BLOCK_MAX)
@ -3360,7 +3417,7 @@ int i2cReadI2CBlockData(
{ {
union my_smbus_data data; union my_smbus_data data;
int i; int i, status;
uint32_t size; uint32_t size;
DBG(DBG_USER, "handle=%d reg=%d count=%d buf=%08X", DBG(DBG_USER, "handle=%d reg=%d count=%d buf=%08X",
@ -3389,9 +3446,15 @@ int i2cReadI2CBlockData(
size = PI_I2C_SMBUS_I2C_BLOCK_DATA; size = PI_I2C_SMBUS_I2C_BLOCK_DATA;
data.block[0] = count; data.block[0] = count;
if (my_smbus_access(
i2cInfo[handle].fd, PI_I2C_SMBUS_READ, reg, size, &data)) status = (my_smbus_access(
i2cInfo[handle].fd, PI_I2C_SMBUS_READ, reg, size, &data));
if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_READ_FAILED; return PI_I2C_READ_FAILED;
}
else else
{ {
if (data.block[0] <= PI_I2C_SMBUS_I2C_BLOCK_MAX) if (data.block[0] <= PI_I2C_SMBUS_I2C_BLOCK_MAX)
@ -3409,7 +3472,7 @@ int i2cWriteI2CBlockData(
{ {
union my_smbus_data data; union my_smbus_data data;
int i, err; int i, status;
DBG(DBG_USER, "handle=%d reg=%d count=%d [%s]", DBG(DBG_USER, "handle=%d reg=%d count=%d [%s]",
handle, reg, count, myBuf2Str(count, buf)); handle, reg, count, myBuf2Str(count, buf));
@ -3435,16 +3498,20 @@ int i2cWriteI2CBlockData(
data.block[0] = count; data.block[0] = count;
err = my_smbus_access( status = my_smbus_access(
i2cInfo[handle].fd, i2cInfo[handle].fd,
PI_I2C_SMBUS_WRITE, PI_I2C_SMBUS_WRITE,
reg, reg,
PI_I2C_SMBUS_I2C_BLOCK_BROKEN, PI_I2C_SMBUS_I2C_BLOCK_BROKEN,
&data); &data);
if (err < 0) return PI_I2C_WRITE_FAILED; if (status < 0)
{
DBG(DBG_USER, "error=%d (%m)", status);
return PI_I2C_WRITE_FAILED;
}
return err; return status;
} }
int i2cWriteDevice(unsigned handle, char *buf, unsigned count) int i2cWriteDevice(unsigned handle, char *buf, unsigned count)
@ -3468,9 +3535,12 @@ int i2cWriteDevice(unsigned handle, char *buf, unsigned count)
bytes = write(i2cInfo[handle].fd, buf, count); bytes = write(i2cInfo[handle].fd, buf, count);
if (bytes != count) if (bytes != count)
{
DBG(DBG_USER, "error=%d (%m)", bytes);
return PI_I2C_WRITE_FAILED; return PI_I2C_WRITE_FAILED;
else }
return 0;
return 0;
} }
int i2cReadDevice(unsigned handle, char *buf, unsigned count) int i2cReadDevice(unsigned handle, char *buf, unsigned count)
@ -3494,9 +3564,12 @@ int i2cReadDevice(unsigned handle, char *buf, unsigned count)
bytes = read(i2cInfo[handle].fd, buf, count); bytes = read(i2cInfo[handle].fd, buf, count);
if (bytes != count) if (bytes != count)
{
DBG(DBG_USER, "error=%d (%m)", bytes);
return PI_I2C_READ_FAILED; return PI_I2C_READ_FAILED;
else }
return bytes;
return bytes;
} }
int i2cOpen(unsigned i2cBus, unsigned i2cAddr, unsigned i2cFlags) int i2cOpen(unsigned i2cBus, unsigned i2cAddr, unsigned i2cFlags)
@ -5161,17 +5234,21 @@ static void alertActivityFilter(int numSamples)
} }
} }
static void * pthAlertThread(void *x) static void * pthAlertThread(void *x)
{ {
struct timespec req, rem; struct timespec req, rem;
uint32_t oldLevel, newLevel, level, reportedLevel; uint32_t oldLevel, newLevel, level, reportedLevel;
uint32_t oldSlot, newSlot; uint32_t oldSlot, newSlot;
uint32_t stick, expected, nowTick; uint32_t stick, expected, nowTick, ft;
int32_t diff; int32_t diff;
int cycle, pulse; int cycle, pulse;
int emit, seqno, emitted; int emit, seqno, emitted;
uint32_t changes, bits, changedBits, timeoutBits; uint32_t changes, bits, changedBits, timeoutBits;
int numSamples, d; int numSamples, d, ticks, i;
int b, n, v; int b, n, v;
int rp, wp; int rp, wp;
int err; int err;
@ -5192,8 +5269,11 @@ static void * pthAlertThread(void *x)
oldSlot = dmaCurrentSlot(dmaNowAtICB()); oldSlot = dmaCurrentSlot(dmaNowAtICB());
oldSlot = (oldSlot / PULSE_PER_CYCLE) * PULSE_PER_CYCLE;
cycle = (oldSlot/PULSE_PER_CYCLE); cycle = (oldSlot/PULSE_PER_CYCLE);
pulse = (oldSlot%PULSE_PER_CYCLE);
pulse = 0;
stopped = 0; stopped = 0;
@ -5208,6 +5288,8 @@ static void * pthAlertThread(void *x)
{ {
newSlot = dmaCurrentSlot(dmaNowAtICB()); newSlot = dmaCurrentSlot(dmaNowAtICB());
newSlot = (newSlot / PULSE_PER_CYCLE) * PULSE_PER_CYCLE;
numSamples = 0; numSamples = 0;
changedBits = 0; changedBits = 0;
@ -5247,6 +5329,22 @@ static void * pthAlertThread(void *x)
diff = stick - expected; diff = stick - expected;
if ((diff < -1) || (diff > 1))
{
if (gpioCfg.clockMicros > 1)
{
ft = gpioSample[numSamples-PULSE_PER_CYCLE].tick;
ticks = stick - ft;
for (i=1; i<PULSE_PER_CYCLE; i++)
{
gpioSample[numSamples-PULSE_PER_CYCLE+i].tick =
((i*ticks)/PULSE_PER_CYCLE) + ft;
}
}
}
diff += (TICKSLOTS/2); diff += (TICKSLOTS/2);
if (diff < 0) if (diff < 0)
@ -10072,12 +10170,12 @@ static void closeOrphanedNotifications(int slot, int fd)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
int gpioNotifyOpen(void) int gpioNotifyOpenWithSize(int bufSize)
{ {
int i, slot, fd; int i, slot, fd;
char name[32]; char name[32];
DBG(DBG_USER, ""); DBG(DBG_USER, "bufSize=%d", bufSize);
CHECK_INITED; CHECK_INITED;
@ -10108,6 +10206,17 @@ int gpioNotifyOpen(void)
SOFT_ERROR(PI_BAD_PATHNAME, "open %s failed (%m)", name); SOFT_ERROR(PI_BAD_PATHNAME, "open %s failed (%m)", name);
} }
if (bufSize != 0)
{
i = fcntl(fd, F_SETPIPE_SZ, bufSize);
if (i != bufSize)
{
gpioNotify[slot].state = PI_NOTIFY_CLOSED;
SOFT_ERROR(PI_BAD_PATHNAME,
"fcntl %s size %d failed (%m)", name, bufSize);
}
}
gpioNotify[slot].seqno = 0; gpioNotify[slot].seqno = 0;
gpioNotify[slot].bits = 0; gpioNotify[slot].bits = 0;
gpioNotify[slot].fd = fd; gpioNotify[slot].fd = fd;
@ -10120,6 +10229,10 @@ int gpioNotifyOpen(void)
return slot; return slot;
} }
int gpioNotifyOpen(void)
{
return gpioNotifyOpenWithSize(0);
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */

View File

@ -31,7 +31,7 @@ For more information, please refer to <http://unlicense.org/>
#include <stdint.h> #include <stdint.h>
#include <pthread.h> #include <pthread.h>
#define PIGPIO_VERSION 40 #define PIGPIO_VERSION 41
/*TEXT /*TEXT
@ -172,6 +172,7 @@ gpioSetGetSamplesFuncEx Requests a gpio samples callback, extended
gpioSetTimerFuncEx Request a regular timed callback, extended gpioSetTimerFuncEx Request a regular timed callback, extended
gpioNotifyOpen Request a notification handle gpioNotifyOpen Request a notification handle
gpioNotifyOpenWithSize Request a notification handle with sized pipe
gpioNotifyBegin Start notifications for selected gpios gpioNotifyBegin Start notifications for selected gpios
gpioNotifyPause Pause notifications gpioNotifyPause Pause notifications
gpioNotifyClose Close a notification gpioNotifyClose Close a notification
@ -1412,6 +1413,18 @@ else
D*/ D*/
/*F*/
int gpioNotifyOpenWithSize(int bufSize);
/*D
This function requests a free notification handle.
It differs from [*gpioNotifyOpen*] in that the pipe size may be
specified, whereas [*gpioNotifyOpen*] uses the default pipe size.
See [*gpioNotifyOpen*] for further details.
D*/
/*F*/ /*F*/
int gpioNotifyBegin(unsigned handle, uint32_t bits); int gpioNotifyBegin(unsigned handle, uint32_t bits);
/*D /*D