V31
authorjoan <joan@abyz.me.uk>
Mon, 2 Mar 2015 22:38:55 +0000 (22:38 +0000)
committerjoan <joan@abyz.me.uk>
Mon, 2 Mar 2015 22:38:55 +0000 (22:38 +0000)
EXAMPLES/C/IR_RECEIVER/ir_hasher.c
command.c
pigpio.3
pigpio.c
pigpio.h

index ef154a10b1f015d44ff60346b87d8c4bbbf88906..4131b9b92af1b896afeb243975776605477bbbaa 100644 (file)
@@ -118,6 +118,8 @@ Pi_Hasher_t *Pi_Hasher(int gpio, Pi_Hasher_CB_t callback, int timeout)
 
    gpioSetMode(gpio, PI_INPUT);
    gpioSetAlertFuncEx(gpio, _cb, hasher);
+
+   return hasher;
 }
 
 void Pi_Hasher_cancel(Pi_Hasher_t *hasher)
@@ -127,6 +129,8 @@ void Pi_Hasher_cancel(Pi_Hasher_t *hasher)
       gpioSetAlertFunc(hasher->gpio, 0);
 
       free(hasher);
+
+      hasher = NULL;
    }
 }
 
index b875d1181a470ebbc9780fb78355a128953f8daa..06fc9147515cd105f2226be38d48f49195b2518f 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 30+
+This version is for pigpio version 31+
 */
 
 #include <stdio.h>
@@ -494,6 +494,8 @@ static errInfo_t errInfo[]=
    {PI_BAD_DATABITS     , "serial data bits not 1-32"},
    {PI_MSG_TOOBIG       , "socket/pipe message too big"},
    {PI_BAD_MALLOC_MODE  , "bad memory allocation mode"},
+   {PI_TOO_MANY_PARTS   , "too many I2C transaction parts"},
+   {PI_BAD_I2C_PART     , "a combined I2C transaction failed"},
 
 };
 
index b766fb5c842f26847b0773d0d4425b01f6d38ceb..08c5dd94137f39edc3e36525db64b9dd6610d98c 100644 (file)
--- a/pigpio.3
+++ b/pigpio.3
@@ -2062,6 +2062,42 @@ No flags are currently defined.  This parameter should be set to zero.
 Returns a handle (>=0) if OK, otherwise PI_BAD_I2C_BUS, PI_BAD_I2C_ADDR,
 PI_BAD_FLAGS, PI_NO_HANDLE, or PI_I2C_OPEN_FAILED.
 
+.br
+
+.br
+For the smbus commands the low level transactions are shown at the end
+of the function description.  The following abbreviations are used.
+
+.br
+
+.br
+
+.EX
+S     (1 bit) : Start bit
+.br
+P     (1 bit) : Stop bit
+.br
+Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.
+.br
+A, NA (1 bit) : Accept and not accept bit.
+.br
+.br
+.br
+Addr  (7 bits): I2C 7 bit address.
+.br
+Comm  (8 bits): Command byte, a data byte which often selects a register.
+.br
+Data  (8 bits): A data byte.
+.br
+Count (8 bits): A data byte containing the length of a block operation.
+.br
+
+.br
+[..]: Data sent by the device.
+.br
+
+.EE
+
 .IP "\fBint i2cClose(unsigned handle)\fP"
 .IP "" 4
 This closes the I2C device associated with the handle.
@@ -2157,6 +2193,12 @@ PI_I2C_WRITE_FAILED.
 .br
 Quick command. smbus 2.0 5.5.1
 
+.EX
+S Addr Rd/Wr [A] P
+.br
+
+.EE
+
 .IP "\fBint i2cWriteByte(unsigned handle, unsigned bVal)\fP"
 .IP "" 4
 This sends a single byte to the device associated with handle.
@@ -2184,6 +2226,12 @@ PI_I2C_WRITE_FAILED.
 .br
 Send byte. smbus 2.0 5.5.2
 
+.EX
+S Addr Wr [A] Data [A] P
+.br
+
+.EE
+
 .IP "\fBint i2cReadByte(unsigned handle)\fP"
 .IP "" 4
 This reads a single byte from the device associated with handle.
@@ -2209,6 +2257,12 @@ or PI_I2C_READ_FAILED.
 .br
 Receive byte. smbus 2.0 5.5.3
 
+.EX
+S Addr Rd [A] [Data] NA P
+.br
+
+.EE
+
 .IP "\fBint i2cWriteByteData(unsigned handle, unsigned i2cReg, unsigned bVal)\fP"
 .IP "" 4
 This writes a single byte to the specified register of the device
@@ -2239,6 +2293,12 @@ PI_I2C_WRITE_FAILED.
 .br
 Write byte. smbus 2.0 5.5.4
 
+.EX
+S Addr Wr [A] Comm [A] Data [A] P
+.br
+
+.EE
+
 .IP "\fBint i2cWriteWordData(unsigned handle, unsigned i2cReg, unsigned wVal)\fP"
 .IP "" 4
 This writes a single 16 bit word to the specified register of the device
@@ -2269,6 +2329,12 @@ PI_I2C_WRITE_FAILED.
 .br
 Write word. smbus 2.0 5.5.4
 
+.EX
+S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
+.br
+
+.EE
+
 .IP "\fBint i2cReadByteData(unsigned handle, unsigned i2cReg)\fP"
 .IP "" 4
 This reads a single byte from the specified register of the device
@@ -2297,6 +2363,12 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 .br
 Read byte. smbus 2.0 5.5.5
 
+.EX
+S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
+.br
+
+.EE
+
 .IP "\fBint i2cReadWordData(unsigned handle, unsigned i2cReg)\fP"
 .IP "" 4
 This reads a single 16 bit word from the specified register of the device
@@ -2325,6 +2397,12 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 .br
 Read word. smbus 2.0 5.5.5
 
+.EX
+S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
+.br
+
+.EE
+
 .IP "\fBint i2cProcessCall(unsigned handle, unsigned i2cReg, unsigned wVal)\fP"
 .IP "" 4
 This writes 16 bits of data to the specified register of the device
@@ -2355,6 +2433,14 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 .br
 Process call. smbus 2.0 5.5.6
 
+.EX
+S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
+.br
+   S Addr Rd [A] [DataLow] A [DataHigh] NA P
+.br
+
+.EE
+
 .IP "\fBint i2cWriteBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP"
 .IP "" 4
 This writes up to 32 bytes to the specified register of the device
@@ -2387,6 +2473,12 @@ PI_I2C_WRITE_FAILED.
 .br
 Block write. smbus 2.0 5.5.7
 
+.EX
+S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
+.br
+
+.EE
+
 .IP "\fBint i2cReadBlockData(unsigned handle, unsigned i2cReg, char *buf)\fP"
 .IP "" 4
 This reads a block of up to 32 bytes from the specified register of
@@ -2422,6 +2514,14 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 .br
 Block read. smbus 2.0 5.5.7
 
+.EX
+S Addr Wr [A] Comm [A]
+.br
+   S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
+.br
+
+.EE
+
 .IP "\fBint i2cBlockProcessCall(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP"
 .IP "" 4
 This writes data bytes to the specified register of the device
@@ -2462,6 +2562,14 @@ bytes sent/received must be 32 or less.
 .br
 Block write-block read. smbus 2.0 5.5.8
 
+.EX
+S Addr Wr [A] Comm [A] Count [A] Data [A] ...
+.br
+   S Addr Rd [A] [Count] A [Data] ... A P
+.br
+
+.EE
+
 .IP "\fBint i2cReadI2CBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP"
 .IP "" 4
 This reads count bytes from the specified register of the device
@@ -2489,6 +2597,18 @@ i2cReg: 0-255, the register to read
 Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
 PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 
+.br
+
+.br
+
+.EX
+S Addr Wr [A] Comm [A]
+.br
+   S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
+.br
+
+.EE
+
 .IP "\fBint i2cWriteI2CBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP"
 .IP "" 4
 This writes 1 to 32 bytes to the specified register of the device
@@ -2516,6 +2636,16 @@ i2cReg: 0-255, the register to write
 Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
 PI_I2C_WRITE_FAILED.
 
+.br
+
+.br
+
+.EX
+S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
+.br
+
+.EE
+
 .IP "\fBint spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)\fP"
 .IP "" 4
 This function returns a handle for the SPI device on the channel.
@@ -5697,10 +5827,6 @@ The number of bits stored in a buffer.
 .br
 
 .IP "\fBnumBytes\fP" 0
-
-.br
-
-.br
 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
 per character.
@@ -5710,21 +5836,20 @@ per character.
 .br
 
 .IP "\fBnumPar\fP: 0-10" 0
-
-.br
-
-.br
 The number of parameters passed to a script.
 
 .br
 
 .br
 
-.IP "\fBnumPulses\fP" 0
+.IP "\fBnumParts\fP" 0
+The number of parts in a combined I2C transaction.
 
 .br
 
 .br
+
+.IP "\fBnumPulses\fP" 0
 The number of pulses to be added to a waveform.
 
 .br
@@ -5732,10 +5857,6 @@ The number of pulses to be added to a waveform.
 .br
 
 .IP "\fBoffset\fP" 0
-
-.br
-
-.br
 The associated data starts this number of microseconds from the start of
 tghe waveform.
 
@@ -5744,43 +5865,58 @@ tghe waveform.
 .br
 
 .IP "\fB*param\fP" 0
+An array of script parameters.
 
 .br
 
 .br
-An array of script parameters.
+
+.IP "\fB*parts\fP" 0
+An array of the part transactions which make up a combined I2C transaction.
 
 .br
 
 .br
 
-.IP "\fBport\fP: 1024-32000" 0
+.IP "\fBpi_i2c_msg_t\fP" 0
 
+.EX
+typedef struct
 .br
-
+{
 .br
-The port used to bind to the pigpio socket.  Defaults to 8888.
-
+   uint16_t addr;  // slave address
 .br
-
+   uint16_t flags;
+.br
+   uint16_t len;   // msg length
+.br
+   uint8_t  *buf;  // pointer to msg data
+.br
+} pi_i2c_msg_t;
 .br
 
-.IP "\fBpos\fP" 0
+.EE
 
 .br
 
 .br
-The position of an item.
+
+.IP "\fBport\fP: 1024-32000" 0
+The port used to bind to the pigpio socket.  Defaults to 8888.
 
 .br
 
 .br
 
-.IP "\fBprimaryChannel\fP: 0-14" 0
+.IP "\fBpos\fP" 0
+The position of an item.
 
 .br
 
 .br
+
+.IP "\fBprimaryChannel\fP: 0-14" 0
 The DMA channel used to time the sampling of gpios and to time servo and
 PWM pulses.
 
@@ -6902,6 +7038,12 @@ A 16-bit word value.
 #define PI_MSG_TOOBIG      -103 // socket/pipe message too big
 .br
 #define PI_BAD_MALLOC_MODE -104 // bad memory allocation mode
+.br
+#define PI_TOO_MANY_PARTS  -105 // too many I2C transaction parts
+.br
+#define PI_BAD_I2C_PART    -106 // a combined I2C transaction failed
+.br
+
 .br
 
 .br
index 0559a4bc826c15825399bf45f2e029c09bf9e716..29bf97ace5f466c617204ab0fa0f03e6425e49a0 100644 (file)
--- a/pigpio.c
+++ b/pigpio.c
@@ -25,7 +25,9 @@ OTHER DEALINGS IN THE SOFTWARE.
 For more information, please refer to <http://unlicense.org/>
 */
 
-/* pigpio version 30 */
+/* pigpio version 31 */
+
+/* include ------------------------------------------------------- */
 
 #include <stdio.h>
 #include <string.h>
@@ -178,7 +180,7 @@ bit 0 READ_LAST_NOT_SET_ERROR
 6 C3  System Timer Compare 3
 */
 
-/* --------------------------------------------------------------- */
+/* define -------------------------------------------------------- */
 
 #define THOUSAND 1000
 #define MILLION  1000000
@@ -283,14 +285,8 @@ bit 0 READ_LAST_NOT_SET_ERROR
    }                                                               \
    while (0)
 
-static volatile uint32_t piModel = 1;
-
 #define PI_PERI_BUS 0x7E000000
 
-static volatile uint32_t pi_peri_phys = 0x20000000;
-static volatile uint32_t pi_dram_bus  = 0x40000000;
-static volatile uint32_t pi_mem_flag  = 0x00000004;
-
 #define AUX_BASE   (pi_peri_phys + 0x00215000)
 #define CLK_BASE   (pi_peri_phys + 0x00101000)
 #define DMA_BASE   (pi_peri_phys + 0x00007000)
@@ -720,6 +716,7 @@ static volatile uint32_t pi_mem_flag  = 0x00000004;
 #define SRX_BUF_SIZE 8192
 
 #define PI_I2C_SLAVE 0x0703
+#define PI_I2C_RDWR  0x0707
 #define PI_I2C_SMBUS 0x0720
 
 #define PI_I2C_SMBUS_READ  1
@@ -758,7 +755,31 @@ static volatile uint32_t pi_mem_flag  = 0x00000004;
 #define MB_UNLOCK_MEMORY_TAG   0x3000E
 #define MB_RELEASE_MEMORY_TAG  0x3000F
 
-/* --------------------------------------------------------------- */
+#define PI_SCRIPT_FREE     0
+#define PI_SCRIPT_RESERVED 1
+#define PI_SCRIPT_IN_USE   2
+#define PI_SCRIPT_DYING    3
+
+#define PI_SCRIPT_HALT   0
+#define PI_SCRIPT_RUN    1
+#define PI_SCRIPT_DELETE 2
+
+#define PI_SCRIPT_STACK_SIZE 256
+
+#define PI_SPI_FLAGS_CHANNEL(x)    ((x&7)<<29)
+
+#define PI_SPI_FLAGS_GET_CHANNEL(x) (((x)>>29)&7)
+#define PI_SPI_FLAGS_GET_BITLEN(x)  (((x)>>16)&63)
+#define PI_SPI_FLAGS_GET_RX_LSB(x)  (((x)>>15)&1)
+#define PI_SPI_FLAGS_GET_TX_LSB(x)  (((x)>>14)&1)
+#define PI_SPI_FLAGS_GET_3WREN(x)   (((x)>>10)&15)
+#define PI_SPI_FLAGS_GET_3WIRE(x)   (((x)>>9)&1)
+#define PI_SPI_FLAGS_GET_AUX_SPI(x) (((x)>>8)&1)
+#define PI_SPI_FLAGS_GET_RESVD(x)   (((x)>>5)&7)
+#define PI_SPI_FLAGS_GET_CSPOLS(x)  (((x)>>2)&7)
+#define PI_SPI_FLAGS_GET_MODE(x)     ((x)&3)
+
+/* typedef ------------------------------------------------------- */
 
 typedef void (*callbk_t) ();
 
@@ -830,17 +851,6 @@ typedef struct
    pthread_t       pthId;
 } gpioTimer_t;
 
-#define PI_SCRIPT_FREE     0
-#define PI_SCRIPT_RESERVED 1
-#define PI_SCRIPT_IN_USE   2
-#define PI_SCRIPT_DYING    3
-
-#define PI_SCRIPT_HALT   0
-#define PI_SCRIPT_RUN    1
-#define PI_SCRIPT_DELETE 2
-
-#define PI_SCRIPT_STACK_SIZE 256
-
 typedef struct
 {
    unsigned id;
@@ -892,19 +902,6 @@ typedef struct
    uint32_t flags;
 } spiInfo_t;
 
-#define PI_SPI_FLAGS_CHANNEL(x)    ((x&7)<<29)
-
-#define PI_SPI_FLAGS_GET_CHANNEL(x) (((x)>>29)&7)
-#define PI_SPI_FLAGS_GET_BITLEN(x)  (((x)>>16)&63)
-#define PI_SPI_FLAGS_GET_RX_LSB(x)  (((x)>>15)&1)
-#define PI_SPI_FLAGS_GET_TX_LSB(x)  (((x)>>14)&1)
-#define PI_SPI_FLAGS_GET_3WREN(x)   (((x)>>10)&15)
-#define PI_SPI_FLAGS_GET_3WIRE(x)   (((x)>>9)&1)
-#define PI_SPI_FLAGS_GET_AUX_SPI(x) (((x)>>8)&1)
-#define PI_SPI_FLAGS_GET_RESVD(x)   (((x)>>5)&7)
-#define PI_SPI_FLAGS_GET_CSPOLS(x)  (((x)>>2)&7)
-#define PI_SPI_FLAGS_GET_MODE(x)     ((x)&3)
-
 typedef struct
 {
    uint32_t startTick;
@@ -983,6 +980,12 @@ struct my_smbus_ioctl_data
    union my_smbus_data *data;
 };
 
+typedef struct
+{
+   pi_i2c_msg_t *msgs; /* pointers to pi_i2c_msgs */
+   uint32_t     nmsgs; /* number of pi_i2c_msgs */
+} my_i2c_rdwr_ioctl_data_t;
+
 typedef struct
 {
    unsigned div;
@@ -998,34 +1001,27 @@ typedef struct
    unsigned  size;          /* in bytes */
 } DMAMem_t;
 
-/* --------------------------------------------------------------- */
+/* global -------------------------------------------------------- */
 
 /* initialise once then preserve */
 
-static volatile gpioCfg_t gpioCfg =
-{
-   PI_DEFAULT_BUFFER_MILLIS,
-   PI_DEFAULT_CLK_MICROS,
-   PI_DEFAULT_CLK_PERIPHERAL,
-   PI_DEFAULT_DMA_PRIMARY_CHANNEL,
-   PI_DEFAULT_DMA_SECONDARY_CHANNEL,
-   PI_DEFAULT_SOCKET_PORT,
-   PI_DEFAULT_IF_FLAGS,
-   0,
-   0,
-   PI_DEFAULT_MEM_ALLOC_MODE,
-};
-
-static volatile gpioStats_t gpioStats;
+static volatile uint32_t piModel      = 1;
+static volatile uint32_t pi_peri_phys = 0x20000000;
+static volatile uint32_t pi_dram_bus  = 0x40000000;
+static volatile uint32_t pi_mem_flag  = 0x0C;
 
-static int gpioMaskSet = 0;
+static int libInitialised = 0;
 
 /* initialise every gpioInitialise */
 
 static struct timespec libStarted;
 static int waveClockInited = 0;
 
-/* initialse if not libInitialised */
+static volatile gpioStats_t gpioStats;
+
+static int gpioMaskSet = 0;
+
+/* initialise if not libInitialised */
 
 static uint64_t gpioMask;
 
@@ -1058,8 +1054,7 @@ static volatile uint32_t notifyBits  = 0;
 static volatile uint32_t scriptBits  = 0;
 
 static volatile int DMAstarted = 0;
-
-static int      libInitialised = 0;
+static volatile int terminating = 0;
 
 static int pthAlertRunning  = 0;
 static int pthFifoRunning   = 0;
@@ -1085,19 +1080,7 @@ static gpioTimer_t      gpioTimer  [PI_MAX_TIMER+1];
 
 static int pwmFreq[PWM_FREQS];
 
-/* no initialisation required */
-
-static unsigned bufferBlocks; /* number of blocks in buffer */
-static unsigned bufferCycles; /* number of cycles */
-
-static pthread_attr_t pthAttr;
-
-static pthread_t pthAlert;
-static pthread_t pthFifo;
-static pthread_t pthSocket;
-
-static gpioSample_t gpioSample[DATUMS];
-static gpioReport_t gpioReport[DATUMS];
+/* reset after gpioTerminated */
 
 /* resources which must be released on gpioTerminate */
 
@@ -1133,7 +1116,70 @@ static volatile uint32_t * systReg = MAP_FAILED;
 static volatile uint32_t * dmaIn   = MAP_FAILED;
 static volatile uint32_t * dmaOut  = MAP_FAILED;
 
-/* constant data */
+static uint32_t hw_clk_freq[3];
+static uint32_t hw_pwm_freq[2];
+static uint32_t hw_pwm_duty[2];
+static uint32_t hw_pwm_real_range[2];
+
+static volatile gpioCfg_t gpioCfg =
+{
+   PI_DEFAULT_BUFFER_MILLIS,
+   PI_DEFAULT_CLK_MICROS,
+   PI_DEFAULT_CLK_PERIPHERAL,
+   PI_DEFAULT_DMA_PRIMARY_CHANNEL,
+   PI_DEFAULT_DMA_SECONDARY_CHANNEL,
+   PI_DEFAULT_SOCKET_PORT,
+   PI_DEFAULT_IF_FLAGS,
+   DBG_MIN_LEVEL,
+   0,
+   PI_DEFAULT_MEM_ALLOC_MODE,
+};
+
+/* no initialisation required */
+
+static unsigned bufferBlocks; /* number of blocks in buffer */
+static unsigned bufferCycles; /* number of cycles */
+
+static pthread_t pthAlert;
+static pthread_t pthFifo;
+static pthread_t pthSocket;
+
+static gpioSample_t gpioSample[DATUMS];
+static gpioReport_t gpioReport[DATUMS];
+
+static uint32_t spi_dummy;
+
+static unsigned old_mode_ce0;
+static unsigned old_mode_ce1;
+static unsigned old_mode_sclk;
+static unsigned old_mode_miso;
+static unsigned old_mode_mosi;
+
+static uint32_t old_spi_cs;
+static uint32_t old_spi_clk;
+
+static unsigned old_mode_ace0;
+static unsigned old_mode_ace1;
+static unsigned old_mode_ace2;
+static unsigned old_mode_asclk;
+static unsigned old_mode_amiso;
+static unsigned old_mode_amosi;
+
+static uint32_t old_spi_cntl0;
+static uint32_t old_spi_cntl1;
+
+/* const --------------------------------------------------------- */
+
+static const uint8_t clkDef[PI_MAX_GPIO + 1] =
+{
+ /*             0     1     2     3     4     5     6     7     8     9 */
+   /* 0 */   0x00, 0x00, 0x00, 0x00, 0x84, 0x94, 0xA4, 0x00, 0x00, 0x00,
+   /* 1 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 2 */   0x82, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 3 */   0x00, 0x00, 0x84, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 4 */   0x00, 0x00, 0x94, 0xA4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 5 */   0x00, 0x00, 0x00, 0x00,
+};
 
 /*
  7 6 5 4 3 2 1 0
@@ -1156,17 +1202,15 @@ CC: 00 CLK0, 01 CLK1, 10 CLK2
  gpio44 GPCLK1 ALT0 Compute module only (reserved for system use)
 */
 
-uint32_t hw_clk_freq[3];
-
-uint8_t clkDef[PI_MAX_GPIO + 1] =
+static const uint8_t PWMDef[PI_MAX_GPIO + 1] =
 {
/*             0     1     2     3     4     5     6     7     8     9 */
-   /* 0 */   0x00, 0x00, 0x00, 0x00, 0x84, 0x94, 0xA4, 0x00, 0x00, 0x00,
-   /* 1 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-   /* 2 */   0x82, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-   /* 3 */   0x00, 0x00, 0x84, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
-   /* 4 */   0x00, 0x00, 0x94, 0xA4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00,
-   /* 5 */   0x00, 0x00, 0x00, 0x00,
  /*          0     1     2     3     4     5     6     7     8     9 */
+   /* 0 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 1 */   0x00, 0x00, 0x84, 0x94, 0x00, 0x00, 0x00, 0x00, 0x82, 0x92,
+   /* 2 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 3 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   /* 4 */   0x84, 0x94, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00,
+   /* 5 */   0x00, 0x00, 0x85, 0x95,
 };
 
 /*
@@ -1188,21 +1232,6 @@ uint8_t clkDef[PI_MAX_GPIO + 1] =
  gpio53 pwm1 ALT1
 */
 
-uint32_t hw_pwm_freq[2];
-uint32_t hw_pwm_duty[2];
-uint32_t hw_pwm_real_range[2];
-
-uint8_t PWMDef[PI_MAX_GPIO + 1] =
-{
-   /*          0     1     2     3     4     5     6     7     8     9 */
-   /* 0 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-   /* 1 */   0x00, 0x00, 0x84, 0x94, 0x00, 0x00, 0x00, 0x00, 0x82, 0x92,
-   /* 2 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-   /* 3 */   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-   /* 4 */   0x84, 0x94, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00,
-   /* 5 */   0x00, 0x00, 0x85, 0x95,
-};
-
 static const clkCfg_t clkCfg[]=
 {
    /* valid servo */
@@ -1227,18 +1256,18 @@ static const uint16_t pwmRealRange[PWM_FREQS]=
    { 25,   50,  100,  125,  200,  250,  400,   500,   625,
     800, 1000, 1250, 2000, 2500, 4000, 5000, 10000, 20000};
  
-/* ======================================================================= */
-
-/* Internal prototypes.
-*/
+/* prototype ----------------------------------------------------- */
 
 static void intNotifyBits(void);
+
 static void intScriptBits(void);
+
 static int  gpioNotifyOpenInBand(int fd);
+
 static void initHWClk
    (int clkCtl, int clkDiv, int clkSrc, int divI, int divF, int MASH);
-static void initDMAgo(volatile uint32_t  *dmaAddr, uint32_t cbAddr);
 
+static void initDMAgo(volatile uint32_t  *dmaAddr, uint32_t cbAddr);
 
 /* ======================================================================= */
 
@@ -1444,7 +1473,7 @@ static void flushMemory(void)
 
 static void waitForDMAstarted(void)
 {
-   while (!DMAstarted)
+   while ((!DMAstarted) && (!terminating))
    {
       if (piModel == 1) myGpioDelay(1000);
       else flushMemory();
@@ -1531,7 +1560,7 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf)
 
 
       case PI_CMD_CF2:
-         /* a couple of extra precautions for untruested code */
+         /* a couple of extra precautions for untrusted code */
          if (p[2] > bufSize) p[2] = bufSize;
          res = gpioCustom2(p[1], buf, p[3], buf, p[2]);
          if (res > p[2]) res = p[2];
@@ -2110,7 +2139,7 @@ static void myGpioSetServo(unsigned gpio, int oldVal, int newVal)
 https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface
 */
 
-int mbCreate(void)
+static int mbCreate(void)
 {
    /* <0 error */
 
@@ -2119,14 +2148,14 @@ int mbCreate(void)
    return mknod(MB_DEV, S_IFCHR|0600, makedev(MB_DEV_MAJOR, 0));
 }
 
-int mbOpen(void)
+static int mbOpen(void)
 {
    /* <0 error */
 
    return open(MB_DEV, 0);
 }
 
-void mbClose(int fd)
+static void mbClose(int fd)
 {
    close(fd);
 }
@@ -2136,7 +2165,7 @@ static int mbProperty(int fd, void *buf)
    return ioctl(fd, MB_IOCTL, buf);
 }
 
-unsigned mbAllocateMemory(
+static unsigned mbAllocateMemory(
    int fd, unsigned size, unsigned align, unsigned flags)
 {
    int i=1;
@@ -2157,7 +2186,7 @@ unsigned mbAllocateMemory(
    return p[5];
 }
 
-unsigned mbLockMemory(int fd, unsigned handle)
+static unsigned mbLockMemory(int fd, unsigned handle)
 {
    int i=1;
    unsigned p[32];
@@ -2175,7 +2204,7 @@ unsigned mbLockMemory(int fd, unsigned handle)
    return p[5];
 }
 
-unsigned mbUnlockMemory(int fd, unsigned handle)
+static unsigned mbUnlockMemory(int fd, unsigned handle)
 {
    int i=1;
    unsigned p[32];
@@ -2193,7 +2222,7 @@ unsigned mbUnlockMemory(int fd, unsigned handle)
    return p[5];
 }
 
-unsigned mbReleaseMemory(int fd, unsigned handle)
+static unsigned mbReleaseMemory(int fd, unsigned handle)
 {
    int i=1;
    unsigned p[32];
@@ -2211,7 +2240,7 @@ unsigned mbReleaseMemory(int fd, unsigned handle)
    return p[5];
 }
 
-void *mbMapMem(unsigned base, unsigned size)
+static void *mbMapMem(unsigned base, unsigned size)
 {
    void *mem = MAP_FAILED;
 
@@ -2220,13 +2249,13 @@ void *mbMapMem(unsigned base, unsigned size)
    return mem;
 }
 
-int mbUnmapMem(void *addr, unsigned size)
+static int mbUnmapMem(void *addr, unsigned size)
 {
    /* 0 okay, -1 fail */
    return munmap(addr, size);
 }
 
-void mbDMAFree(DMAMem_t *DMAMemP)
+static void mbDMAFree(DMAMem_t *DMAMemP)
 {
    if (DMAMemP->handle)
    {
@@ -2237,7 +2266,7 @@ void mbDMAFree(DMAMem_t *DMAMemP)
    }
 }
 
-int mbDMAAlloc(DMAMem_t *DMAMemP, unsigned size, uint32_t pi_mem_flag)
+static int mbDMAAlloc(DMAMem_t *DMAMemP, unsigned size, uint32_t pi_mem_flag)
 {
    DMAMemP->size = size;
 
@@ -3388,30 +3417,50 @@ int i2cClose(unsigned handle)
    return 0;
 }
 
-/* ======================================================================= */
+int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts)
+{
+   int retval, fd;
+   my_i2c_rdwr_ioctl_data_t rdwr;
 
-/*SPI */
+   DBG(DBG_USER, "handle=%d", handle);
 
-static uint32_t spi_dummy; /* only used to prevent warning */
+   CHECK_INITED;
 
-static unsigned old_mode_ce0;
-static unsigned old_mode_ce1;
-static unsigned old_mode_sclk;
-static unsigned old_mode_miso;
-static unsigned old_mode_mosi;
+   if (handle >= PI_I2C_SLOTS)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
-static uint32_t old_spi_cs;
-static uint32_t old_spi_clk;
+   if (i2cInfo[handle].state != PI_I2C_OPENED)
+      SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle);
 
-static unsigned old_mode_ace0;
-static unsigned old_mode_ace1;
-static unsigned old_mode_ace2;
-static unsigned old_mode_asclk;
-static unsigned old_mode_amiso;
-static unsigned old_mode_amosi;
+   if (parts == NULL)
+      SOFT_ERROR(PI_BAD_POINTER, "null parts");
 
-static uint32_t old_spi_cntl0;
-static uint32_t old_spi_cntl1;
+   if (numParts > PI_I2C_RDRW_IOCTL_MAX_MSGS)
+      SOFT_ERROR(PI_TOO_MANY_PARTS, "too many parts (%d)", numParts);
+
+   fd = open(PI_I2C_COMBINED, O_RDWR);
+
+   if (fd >= 0)
+   {
+      write(fd, "1", 1);
+      close(fd);
+   }
+
+   rdwr.msgs = parts;
+   rdwr.nmsgs = numParts;
+
+   retval = ioctl(i2cInfo[handle].fd, PI_I2C_RDWR, &rdwr);
+
+   DBG(0, "i2cTransaction retval=%d", retval);
+
+   if (retval >= 0) return retval;
+   else             return PI_BAD_I2C_PART;
+}
+
+
+/* ======================================================================= */
+
+/*SPI */
 
 static uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf)
 {
@@ -3767,7 +3816,7 @@ static void spiInit(uint32_t flags)
    }
 }
 
-void spiTerm(uint32_t flags)
+static void spiTerm(uint32_t flags)
 {
    int resvd;
 
@@ -6341,8 +6390,9 @@ static void initClearGlobals(void)
    notifyBits  = 0;
    scriptBits  = 0;
 
-   libInitialised   = 0;
-   DMAstarted       = 0;
+   libInitialised = 0;
+   DMAstarted     = 0;
+   terminating    = 0;
 
    pthAlertRunning  = 0;
    pthFifoRunning   = 0;
@@ -6598,19 +6648,22 @@ static void initReleaseResources(void)
 
 int initInitialise(void)
 {
-   int i;
+   int rev, i;
    struct sockaddr_in server;
    char * portStr;
    unsigned port;
    struct sched_param param;
+   pthread_attr_t pthAttr;
+
+   DBG(DBG_STARTUP, "");
+
+   if (libInitialised) return PIGPIO_VERSION;
 
    waveClockInited = 0;
 
    clock_gettime(CLOCK_REALTIME, &libStarted);
 
-   DBG(DBG_STARTUP, "");
-
-   if (libInitialised) return PIGPIO_VERSION;
+   rev = gpioHardwareRevision();
 
    initClearGlobals();
 
@@ -6623,13 +6676,11 @@ int initInitialise(void)
 
    if (!gpioMaskSet)
    {
-      i = gpioHardwareRevision();
-
-      if      (i ==  0) gpioMask = PI_DEFAULT_UPDATE_MASK_R0;
-      else if (i == 17) gpioMask = PI_DEFAULT_UPDATE_MASK_COMPUTE;
-      else if (i <   4) gpioMask = PI_DEFAULT_UPDATE_MASK_R1;
-      else if (i <  16) gpioMask = PI_DEFAULT_UPDATE_MASK_R2;
-      else              gpioMask = PI_DEFAULT_UPDATE_MASK_R3;
+      if      (rev ==  0) gpioMask = PI_DEFAULT_UPDATE_MASK_R0;
+      else if (rev == 17) gpioMask = PI_DEFAULT_UPDATE_MASK_COMPUTE;
+      else if (rev <   4) gpioMask = PI_DEFAULT_UPDATE_MASK_R1;
+      else if (rev <  16) gpioMask = PI_DEFAULT_UPDATE_MASK_R2;
+      else                gpioMask = PI_DEFAULT_UPDATE_MASK_R3;
 
       gpioMaskSet = 1;
    }
@@ -6937,10 +6988,14 @@ void gpioTerminate(void)
 
    DBG(DBG_USER, "");
 
-   gpioMaskSet = 0;
+   terminating = 1;
 
    if (libInitialised)
    {
+      libInitialised = 0;
+
+      gpioMaskSet = 0;
+
       /* reset DMA */
 
       DMAstarted = 0;
@@ -6948,8 +7003,6 @@ void gpioTerminate(void)
       dmaIn[DMA_CS] = DMA_CHANNEL_RESET;
       dmaOut[DMA_CS] = DMA_CHANNEL_RESET;
 
-      libInitialised = 0;
-
       if (gpioCfg.showStats)
       {
          fprintf(stderr,
@@ -8573,6 +8626,8 @@ static int intGpioSetTimerFunc(unsigned id,
                                int user,
                                void *userdata)
 {
+   pthread_attr_t pthAttr;
+
    DBG(DBG_INTERNAL, "id=%d millis=%d function=%08X user=%d userdata=%08X",
       id, millis, (uint32_t)f, user, (uint32_t)userdata);
 
@@ -8587,6 +8642,14 @@ static int intGpioSetTimerFunc(unsigned id,
 
       if (!gpioTimer[id].running)
       {
+         if (pthread_attr_init(&pthAttr))
+            SOFT_ERROR(PI_TIMER_FAILED,
+               "pthread_attr_init failed (%m)");
+
+         if (pthread_attr_setstacksize(&pthAttr, STACK_SIZE))
+            SOFT_ERROR(PI_TIMER_FAILED,
+               "pthread_attr_setstacksize failed (%m)");
+
          if (pthread_create(
             &gpioTimer[id].pthId, &pthAttr, pthTimerTick, &gpioTimer[id]))
                SOFT_ERROR(PI_TIMER_FAILED,
@@ -9377,7 +9440,7 @@ unsigned gpioHardwareRevision(void)
                   chars = 4;
                   pi_peri_phys = 0x20000000;
                   pi_dram_bus  = 0x40000000;
-                  pi_mem_flag  = 0x0c;
+                  pi_mem_flag  = 0x0C;
                }
                else if (strstr (buf, "ARMv7") != NULL)
                {
index be6e8139c2633ea0f6ffce4c18b212798df3d273..69afbc83249c9ba3d6509dd88d9d936f55e826e5 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 30
+#define PIGPIO_VERSION 31
 
 /*TEXT
 
@@ -319,6 +319,8 @@ OVERVIEW*/
 
 #define PI_LOCKFILE "/var/run/pigpio.pid"
 
+#define PI_I2C_COMBINED "/sys/module/i2c_bcm2708/parameters/combined"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -399,6 +401,29 @@ uint32_t next;
 uint32_t pad[2];
 } rawCbs_t;
 
+/* max pi_i2c_msg_t per transaction */
+
+#define  PI_I2C_RDRW_IOCTL_MAX_MSGS 42
+
+/* flags for pi_i2c_msg_t */
+
+#define PI_I2C_M_WR           0x0000 /* write data */
+#define PI_I2C_M_RD           0x0001 /* read data */
+#define PI_I2C_M_TEN          0x0010 /* ten bit chip address */
+#define PI_I2C_M_RECV_LEN     0x0400 /* length will be first received byte */
+#define PI_I2C_M_NO_RD_ACK    0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_IGNORE_NAK   0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+#define PI_I2C_M_NOSTART      0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */
+
+typedef struct
+{
+   uint16_t addr;  /* slave address       */
+   uint16_t flags;
+   uint16_t len;   /* msg length          */
+   uint8_t  *buf;  /* pointer to msg data */
+} pi_i2c_msg_t;
+
 typedef void (*gpioAlertFunc_t)    (int      gpio,
                                     int      level,
                                     uint32_t tick);
@@ -1699,7 +1724,6 @@ user_gpio: 0-31, previously opened with [*gpioSerialReadOpen*]
 Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO.
 D*/
 
-
 /*F*/
 int i2cOpen(unsigned i2cBus, unsigned i2cAddr, unsigned i2cFlags);
 /*D
@@ -1715,6 +1739,22 @@ No flags are currently defined.  This parameter should be set to zero.
 
 Returns a handle (>=0) if OK, otherwise PI_BAD_I2C_BUS, PI_BAD_I2C_ADDR,
 PI_BAD_FLAGS, PI_NO_HANDLE, or PI_I2C_OPEN_FAILED.
+
+For the smbus commands the low level transactions are shown at the end
+of the function description.  The following abbreviations are used.
+
+. .
+S     (1 bit) : Start bit
+P     (1 bit) : Stop bit
+Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.
+A, NA (1 bit) : Accept and not accept bit. 
+Addr  (7 bits): I2C 7 bit address.
+Comm  (8 bits): Command byte, a data byte which often selects a register.
+Data  (8 bits): A data byte.
+Count (8 bits): A data byte containing the length of a block operation.
+
+[..]: Data sent by the device.
+. .
 D*/
 
 
@@ -1762,6 +1802,10 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
 PI_I2C_WRITE_FAILED.
 D*/
 
+int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts);
+/*
+This performs a combined I2C transction made up of count parts.
+*/
 
 /*F*/
 int i2cWriteQuick(unsigned handle, unsigned bit);
@@ -1778,6 +1822,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
 PI_I2C_WRITE_FAILED.
 
 Quick command. smbus 2.0 5.5.1
+. .
+S Addr Rd/Wr [A] P
+. .
 D*/
 
 
@@ -1795,6 +1842,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
 PI_I2C_WRITE_FAILED.
 
 Send byte. smbus 2.0 5.5.2
+. .
+S Addr Wr [A] Data [A] P
+. .
 D*/
 
 
@@ -1811,6 +1861,9 @@ Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE,
 or PI_I2C_READ_FAILED.
 
 Receive byte. smbus 2.0 5.5.3
+. .
+S Addr Rd [A] [Data] NA P
+. .
 D*/
 
 
@@ -1830,6 +1883,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
 PI_I2C_WRITE_FAILED.
 
 Write byte. smbus 2.0 5.5.4
+. .
+S Addr Wr [A] Comm [A] Data [A] P
+. .
 D*/
 
 
@@ -1849,6 +1905,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
 PI_I2C_WRITE_FAILED.
 
 Write word. smbus 2.0 5.5.4
+. .
+S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P
+. .
 D*/
 
 
@@ -1867,6 +1926,9 @@ Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE,
 PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 
 Read byte. smbus 2.0 5.5.5
+. .
+S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
+. .
 D*/
 
 
@@ -1885,6 +1947,9 @@ Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE,
 PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 
 Read word. smbus 2.0 5.5.5
+. .
+S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
+. .
 D*/
 
 
@@ -1904,6 +1969,10 @@ Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE,
 PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 
 Process call. smbus 2.0 5.5.6
+. .
+S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
+   S Addr Rd [A] [DataLow] A [DataHigh] NA P
+. .
 D*/
 
 
@@ -1925,6 +1994,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
 PI_I2C_WRITE_FAILED.
 
 Block write. smbus 2.0 5.5.7
+. .
+S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
+. .
 D*/
 
 
@@ -1946,6 +2018,10 @@ Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE,
 PI_BAD_PARAM, or PI_I2C_READ_FAILED.
 
 Block read. smbus 2.0 5.5.7
+. .
+S Addr Wr [A] Comm [A]
+   S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
+. .
 D*/
 
 
@@ -1972,6 +2048,10 @@ sent and a minimum of 1 byte may be received.  The total number of
 bytes sent/received must be 32 or less.
 
 Block write-block read. smbus 2.0 5.5.8
+. .
+S Addr Wr [A] Comm [A] Count [A] Data [A] ...
+   S Addr Rd [A] [Count] A [Data] ... A P
+. .
 D*/
 
 
@@ -1991,6 +2071,11 @@ i2cReg: 0-255, the register to read
 
 Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE,
 PI_BAD_PARAM, or PI_I2C_READ_FAILED.
+
+. .
+S Addr Wr [A] Comm [A]
+   S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
+. .
 D*/
 
 
@@ -2010,6 +2095,10 @@ i2cReg: 0-255, the register to write
 
 Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or
 PI_I2C_WRITE_FAILED.
+
+. .
+S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
+. .
 D*/
 
 
@@ -3742,38 +3831,47 @@ numBits::
 The number of bits stored in a buffer.
 
 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
 per character.
 
 numPar:: 0-10
-
 The number of parameters passed to a script.
 
-numPulses::
+numParts::
+The number of parts in a combined I2C transaction.
 
+numPulses::
 The number of pulses to be added to a waveform.
 
 offset::
-
 The associated data starts this number of microseconds from the start of
 tghe waveform.
 
 *param::
-
 An array of script parameters.
 
-port:: 1024-32000
+*parts::
+An array of the part transactions which make up a combined I2C transaction.
 
+pi_i2c_msg_t::
+. .
+typedef struct
+{
+   uint16_t addr;  // slave address
+   uint16_t flags;
+   uint16_t len;   // msg length
+   uint8_t  *buf;  // pointer to msg data
+} pi_i2c_msg_t;
+. .
+
+port:: 1024-32000
 The port used to bind to the pigpio socket.  Defaults to 8888.
 
 pos::
-
 The position of an item.
 
 primaryChannel:: 0-14
-
 The DMA channel used to time the sampling of gpios and to time servo and
 PWM pulses.
 
@@ -4323,6 +4421,9 @@ after this command is issued.
 #define PI_BAD_STOPBITS    -102 // serial (half) stop bits not 2-8
 #define PI_MSG_TOOBIG      -103 // socket/pipe message too big
 #define PI_BAD_MALLOC_MODE -104 // bad memory allocation mode
+#define PI_TOO_MANY_PARTS  -105 // too many I2C transaction parts
+#define PI_BAD_I2C_PART    -106 // a combined I2C transaction failed
+
 
 #define PI_PIGIF_ERR_0    -2000
 #define PI_PIGIF_ERR_99   -2099