123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993 |
- /****************************************************************************
- * drivers/1wire/ds28e17.c
- *
- * Copyright (C) 2018 Haltian Ltd. All rights reserved.
- * Author: Juha Niskanen <juha.niskanen@haltian.com>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * 3. Neither the name NuttX nor the names of its contributors may be
- * used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- ****************************************************************************/
- /****************************************************************************
- * Included Files
- ****************************************************************************/
- #include <nuttx/config.h>
- #include <errno.h>
- #include <debug.h>
- #include <string.h>
- #include <nuttx/kmalloc.h>
- #include <nuttx/i2c/i2c_master.h>
- #include <nuttx/drivers/1wire.h>
- #include <nuttx/1wire/ds28e17.h>
- #include "1wire_internal.h"
- /****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
- #ifndef CONFIG_DS28E17_I2C_FREQUENCY
- # define CONFIG_DS28E17_I2C_FREQUENCY 400000
- #endif
- /* DS28E17 device 1-Wire family ID */
- #define DS_FAMILY 0x19
- /* DS28E17 device I2C commands */
- #define DS_WRITE_DATA_WITH_STOP 0x4b
- #define DS_WRITE_DATA_NO_STOP 0x5a
- #define DS_WRITE_DATA_ONLY 0x69
- #define DS_WRITE_DATA_ONLY_WITH_STOP 0x78
- #define DS_READ_DATA_WITH_STOP 0x87
- #define DS_WRITE_READ_DATA_WITH_STOP 0x2d
- #define DS_WRITE_CONFIGURATION 0xd2
- #define DS_READ_CONFIGURATION 0xe1
- #define DS_ENABLE_SLEEP_MODE 0x1e
- #define DS_READ_DEVICE_REVISION 0xc4
- /* DS28E17 status bits */
- #define DS_STATUS_CRC 0x01
- #define DS_STATUS_ADDRESS 0x02
- #define DS_STATUS_START 0x08
- /* Maximum number of I2C bytes to transfer within one CRC16 protected onewire
- * command (same for either read and write).
- */
- #define DS_DATA_LIMIT 255
- /* Default I2C frequency to use when DS28E17 is detected. */
- #define DS_DEFAULT_FREQUENCY CONFIG_DS28E17_I2C_FREQUENCY
- /* Default I2C stretch value. */
- #define DS_DEFAULT_STRETCH 1
- /* How many times to retry check for chip busy condition vanishing. */
- #define DS_BUSYWAIT_RETRIES 500
- /****************************************************************************
- * Private Types
- ****************************************************************************/
- struct ds28e17_dev_s /* Must be cast-compatible with onewire_master_s */
- {
- FAR struct onewire_dev_s *dev; /* 1-wire interface */
- };
- /* I2C Device, Instance */
- struct ds_i2c_inst_s /* Must be cast-compatible with i2c_master_s */
- {
- FAR const struct i2c_ops_s *ops; /* Standard I2C operations */
- /* 1-wire data */
- FAR struct onewire_master_s *master; /* 1-wire bus master */
- FAR struct onewire_slave_s slave; /* Our slave data on 1-wire bus */
- /* I2C data */
- uint32_t frequency; /* Current I2C frequency */
- uint8_t stretch; /* Current I2C stretch value */
- };
- /****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
- static int ds_i2c_reset(FAR struct i2c_master_s *i2cdev);
- static int ds_i2c_transfer(FAR struct i2c_master_s *i2cdev,
- FAR struct i2c_msg_s *msgs, int count);
- /****************************************************************************
- * Private Data
- ****************************************************************************/
- /* Device Structures, Instantiation */
- static const struct i2c_ops_s ds_i2c_ops =
- {
- .transfer = ds_i2c_transfer
- #ifdef CONFIG_I2C_RESET
- , .reset = ds_i2c_reset
- #endif
- };
- /****************************************************************************
- * Private Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: ds_i2c_sem_wait
- *
- * Description:
- * Take the exclusive access, waiting as necessary
- *
- ****************************************************************************/
- static inline void ds_i2c_sem_wait(FAR struct i2c_master_s *i2cdev)
- {
- FAR struct ds_i2c_inst_s *inst = (FAR struct ds_i2c_inst_s *)i2cdev;
- FAR struct onewire_master_s *master = inst->master;
- return onewire_sem_wait(master);
- }
- /****************************************************************************
- * Name: ds_i2c_sem_post
- *
- * Description:
- * Release the mutual exclusion semaphore
- *
- ****************************************************************************/
- static inline void ds_i2c_sem_post(FAR struct i2c_master_s *i2cdev)
- {
- FAR struct ds_i2c_inst_s *inst = (FAR struct ds_i2c_inst_s *)i2cdev;
- FAR struct onewire_master_s *master = inst->master;
- onewire_sem_post(master);
- }
- static int ds_error(uint8_t buf[])
- {
- /* Warnings */
- if (buf[0] & DS_STATUS_CRC)
- {
- i2cwarn("crc16 match failed\n");
- }
- if ((buf[0] & (DS_STATUS_CRC | DS_STATUS_ADDRESS)) == 0 && buf[1] != 0)
- {
- i2cwarn("I2C short write, no ack for %d bytes\n", buf[1]);
- }
- /* Error conditions */
- if (buf[0] & DS_STATUS_ADDRESS)
- {
- i2cerr("I2C device not responding\n");
- return -ENXIO;
- }
- if (buf[0] & DS_STATUS_START)
- {
- i2cerr("I2C status start\n");
- return -EAGAIN;
- }
- if (buf[0] != 0 || buf[1] != 0)
- {
- i2cerr("I2C IO error\n");
- return -EIO;
- }
- return OK;
- }
- static inline int ds_busywait_time(FAR struct ds_i2c_inst_s *inst)
- {
- int d;
- /* Return busywait time (us) for I2C speeds 100 kHz, 400 kHz
- * and 900 kHz, adjusted with current stretch value.
- */
- switch (inst->frequency)
- {
- case 100000:
- d = 90;
- break;
- case 400000:
- default:
- d = 23;
- break;
- case 900000:
- d = 10;
- break;
- }
- return d * inst->stretch;
- }
- static int ds_busywait(FAR struct ds_i2c_inst_s *inst, size_t length)
- {
- FAR struct onewire_master_s *master = inst->master;
- int retries = DS_BUSYWAIT_RETRIES;
- int delay;
- int ret;
- uint8_t bit = 1;
- /* Calculate delay time from current I2C settings. */
- delay = ds_busywait_time(inst);
- do
- {
- ret = ONEWIRE_READBIT(master->dev, &bit);
- if (ret < 0)
- {
- i2cerr("ERROR: ONEWIRE_READBIT failed\n");
- return ret;
- }
- if (bit == 0)
- {
- return OK;
- }
- if (retries == DS_BUSYWAIT_RETRIES)
- {
- /* First time, after checking bit once, do a big delay
- * for I2C to process all bytes in message.
- */
- up_udelay(delay * length);
- }
- else
- {
- /* Otherwise, wait for one byte duration. */
- up_udelay(delay);
- }
- } while (retries-- > 0);
- i2cwarn("busywait timeout\n");
- return -ETIMEDOUT;
- }
- /****************************************************************************
- * Name: ds_i2c_read
- *
- * Description:
- * Read data from I2C slave.
- *
- ****************************************************************************/
- static int ds_i2c_read(FAR struct ds_i2c_inst_s *inst, uint16_t i2c_addr,
- FAR uint8_t *buffer, ssize_t length)
- {
- FAR struct onewire_master_s *master = inst->master;
- uint16_t crc;
- int ret;
- uint8_t buf[5];
- if (length <= 0)
- {
- return -EINVAL;
- }
- if (length > DS_DATA_LIMIT)
- {
- i2cerr("ERROR: reading too many bytes!\n");
- return -EINVAL;
- }
- /* Send command to DS28E17. */
- buf[0] = DS_READ_DATA_WITH_STOP;
- buf[1] = i2c_addr << 1 | 0x01;
- buf[2] = length;
- crc = onewire_crc16(buf, 3, 0);
- buf[3] = ~(crc & 0xff);
- buf[4] = ~((crc >> 8) & 0xff);
- ret = ONEWIRE_WRITE(master->dev, buf, 5);
- if (ret < 0)
- {
- return ret;
- }
- /* Wait busy indication to vanish. */
- ret = ds_busywait(inst, length + 1);
- if (ret < 0)
- {
- return ret;
- }
- /* Read status from DS28E17. */
- ret = ONEWIRE_READ(master->dev, buf, 1);
- buf[1] = 0;
- /* Check error conditions. */
- ret = ds_error(buf);
- if (ret < 0)
- {
- return ret;
- }
- /* Read received I2C data from DS28E17. */
- return ONEWIRE_READ(master->dev, buffer, length);
- }
- /****************************************************************************
- * Name: ds_i2c_write
- *
- * Description:
- * Write data to I2C slave.
- *
- ****************************************************************************/
- static int ds_i2c_write(FAR struct ds_i2c_inst_s *inst, uint16_t i2c_addr,
- FAR const uint8_t *buffer, ssize_t length, bool stop)
- {
- FAR struct onewire_master_s *master = inst->master;
- uint16_t crc;
- int ret;
- uint8_t buf[3];
- if (length <= 0)
- {
- return -EINVAL;
- }
- if (length > DS_DATA_LIMIT)
- {
- /* TODO: split big writes into multiple chunks. */
- i2cerr("ERROR: writing too many bytes!\n");
- return -EINVAL;
- }
- /* Write command header. */
- buf[0] = stop ? DS_WRITE_DATA_WITH_STOP : DS_WRITE_DATA_NO_STOP;
- buf[1] = i2c_addr << 1;
- buf[2] = length;
- crc = onewire_crc16(buf, 3, 0);
- ret = ONEWIRE_WRITE(master->dev, buf, 3);
- if (ret < 0)
- {
- return ret;
- }
- /* Write payload I2C data to DS28E17. */
- crc = onewire_crc16(buffer, length, crc);
- ret = ONEWIRE_WRITE(master->dev, buffer, length);
- if (ret < 0)
- {
- return ret;
- }
- /* Write checksum. */
- buf[0] = ~(crc & 0xff);
- buf[1] = ~((crc >> 8) & 0xff);
- ret = ONEWIRE_WRITE(master->dev, buf, 2);
- if (ret < 0)
- {
- return ret;
- }
- /* Wait busy indication to vanish. */
- ret = ds_busywait(inst, length + 1);
- if (ret < 0)
- {
- return ret;
- }
- /* Read status from DS28E17. */
- ret = ONEWIRE_READ(master->dev, buf, 2);
- if (ret < 0)
- {
- return ret;
- }
- /* Check error conditions. */
- ret = ds_error(buf);
- if (ret < 0)
- {
- return ret;
- }
- /* Return count of bytes written. */
- return length;
- }
- /****************************************************************************
- * Name: ds_i2c_write_read
- *
- * Description:
- * Write data to I2C slave and read from same address.
- *
- ****************************************************************************/
- static int ds_i2c_write_read(FAR struct ds_i2c_inst_s *inst, uint16_t i2c_addr,
- FAR const uint8_t *wbuffer, ssize_t wlength,
- FAR uint8_t *rbuffer, ssize_t rlength)
- {
- FAR struct onewire_master_s *master = inst->master;
- uint16_t crc;
- int ret;
- uint8_t buf[3];
- if (wlength <= 0 || rlength <= 0)
- {
- return -EINVAL;
- }
- if (wlength > DS_DATA_LIMIT)
- {
- i2cerr("ERROR: writing too many bytes!\n");
- return -EINVAL;
- }
- if (rlength > DS_DATA_LIMIT)
- {
- i2cerr("ERROR: reading too many bytes!\n");
- return -EINVAL;
- }
- /* Write command header. */
- buf[0] = DS_WRITE_READ_DATA_WITH_STOP;
- buf[1] = i2c_addr << 1;
- buf[2] = wlength;
- crc = onewire_crc16(buf, 3, 0);
- ret = ONEWIRE_WRITE(master->dev, buf, 3);
- if (ret < 0)
- {
- return ret;
- }
- /* Write payload I2C data to DS28E17. */
- crc = onewire_crc16(wbuffer, wlength, crc);
- ret = ONEWIRE_WRITE(master->dev, wbuffer, wlength);
- if (ret < 0)
- {
- return ret;
- }
- /* Write read length and checksum. */
- buf[0] = rlength;
- crc = onewire_crc16(buf, 1, crc);
- buf[1] = ~(crc & 0xff);
- buf[2] = ~((crc >> 8) & 0xff);
- ret = ONEWIRE_WRITE(master->dev, buf, 3);
- if (ret < 0)
- {
- return ret;
- }
- /* Wait busy indication to vanish. */
- ret = ds_busywait(inst, wlength + 1 + rlength + 1);
- if (ret < 0)
- {
- return ret;
- }
- /* Read status from DS28E17. */
- ret = ONEWIRE_READ(master->dev, buf, 2);
- if (ret < 0)
- {
- return ret;
- }
- /* Check error conditions. */
- ret = ds_error(buf);
- if (ret < 0)
- {
- return ret;
- }
- /* Read received I2C data from DS28E17. */
- return ONEWIRE_READ(master->dev, rbuffer, rlength);
- }
- static int ds_i2c_setfrequency(FAR struct ds_i2c_inst_s *inst, uint32_t frequency)
- {
- FAR struct onewire_master_s *master = inst->master;
- uint8_t buf[2];
- int speed;
- int ret;
- switch (frequency)
- {
- case 100000:
- speed = 0;
- break;
- case 400000:
- speed = 1;
- break;
- case 900000:
- speed = 2;
- break;
- default:
- i2cerr("ERROR: bad I2C freq %u\n", frequency);
- return -EINVAL;
- }
- i2cinfo("Changing I2C freq %u -> %u\n", inst->frequency, frequency);
- /* Select DS28E17 */
- ret = onewire_reset_select(&inst->slave);
- if (ret < 0)
- {
- i2cerr("ERROR: cannot change I2C freq\n");
- return ret;
- }
- /* Write new speed to device */
- buf[0] = DS_WRITE_CONFIGURATION;
- buf[1] = speed;
- ret = ONEWIRE_WRITE(master->dev, buf, 2);
- if (ret < 0)
- {
- i2cerr("ERROR: cannot change I2C freq\n");
- return ret;
- }
- inst->frequency = frequency;
- return ret;
- }
- /****************************************************************************
- * Name: ds_i2c_process
- *
- * Description:
- * Common I2C transfer logic
- *
- * Initiates a master mode transaction on the I2C bus to transfer the
- * provided messages to and from the slave devices.
- *
- ****************************************************************************/
- static int ds_i2c_process(FAR struct i2c_master_s *i2cdev,
- FAR struct i2c_msg_s *msgs, int count)
- {
- FAR struct ds_i2c_inst_s *inst = (FAR struct ds_i2c_inst_s *)i2cdev;
- FAR struct onewire_master_s *master = inst->master;
- int ret;
- int i;
- /* Check from first message only, if we want to change I2C frequency. */
- if (inst->frequency != msgs[0].frequency)
- {
- ds_i2c_setfrequency(inst, msgs[0].frequency);
- }
- /* Select DS28E17 */
- i = onewire_reset_select(&inst->slave);
- if (i < 0)
- {
- goto errout;
- }
- while (i < count)
- {
- /* First we try to use DS_WRITE_READ_DATA_WITH_STOP to optimize
- * the common case of write followed by read to a same address.
- */
- if (i < count - 1 && msgs[i].addr == msgs[i+1].addr &&
- (msgs[i].flags & I2C_M_READ) == 0 &&
- (msgs[i+1].flags & I2C_M_READ))
- {
- /* Write-read combined transfer. */
- ret = ds_i2c_write_read(inst, msgs[i].addr,
- msgs[i].buffer, msgs[i].length,
- msgs[i+1].buffer, msgs[i+1].length);
- if (ret < 0)
- {
- i = ret;
- goto errout;
- }
- /* We processed two messages here. */
- i += 2;
- }
- else if (msgs[i].flags & I2C_M_READ)
- {
- /* Read transfer. */
- ret = ds_i2c_read(inst, msgs[i].addr, msgs[i].buffer, msgs[i].length);
- if (ret < 0)
- {
- i = ret;
- goto errout;
- }
- i++;
- }
- else
- {
- /* Write transfer. Stop condition only for last transfer. */
- ret = ds_i2c_write(inst, msgs[i].addr, msgs[i].buffer, msgs[i].length,
- i == (count-1));
- if (ret < 0)
- {
- i = ret;
- goto errout;
- }
- i++;
- }
- /* Any more messages to process? */
- if (i < count)
- {
- /* Yes. Resume to same DS28E17. */
- /* Oddness: Skip-ROM does not set RS-bit needed by resume. */
- if (master->nslaves > 1)
- {
- ret = onewire_reset_resume(master);
- }
- else
- {
- ret = onewire_reset_select(&inst->slave);
- }
- if (ret < 0)
- {
- i = ret;
- goto errout;
- }
- }
- }
- errout:
- return i;
- }
- /****************************************************************************
- * Name: ds_i2c_reset
- *
- * Description:
- * Reset an I2C bus
- *
- ****************************************************************************/
- #ifdef CONFIG_I2C_RESET
- static int ds_i2c_reset(FAR struct i2c_master_s *i2cdev)
- {
- FAR struct ds_i2c_inst_s *inst = (FAR struct ds_i2c_inst_s *)i2cdev;
- FAR struct onewire_master_s *master = inst->master;
- int ret;
- ds_i2c_sem_wait(i2cdev);
- ret = ONEWIRE_RESET(master->dev);
- ds_i2c_sem_post(i2cdev);
- return ret;
- }
- #endif
- /****************************************************************************
- * Name: ds_i2c_transfer
- *
- * Description:
- * Generic I2C transfer function
- *
- ****************************************************************************/
- static int ds_i2c_transfer(FAR struct i2c_master_s *i2cdev,
- FAR struct i2c_msg_s *msgs,
- int count)
- {
- int ret;
- ds_i2c_sem_wait(i2cdev);
- ret = ds_i2c_process(i2cdev, msgs, count);
- ds_i2c_sem_post(i2cdev);
- return ret;
- }
- /****************************************************************************
- * Name: ds28e17_selftest
- *
- * Description:
- *
- ****************************************************************************/
- static int ds28e17_selftest(FAR struct ds_i2c_inst_s *inst)
- {
- FAR struct onewire_master_s *master = inst->master;
- uint8_t txbuf[] = { ONEWIRE_CMD_READ_ROM };
- uint8_t rxbuf[8] = { 0 };
- uint64_t rom;
- uint8_t crc;
- int ret;
- /* Read ROM-code of single connected slave and
- * check its checksum.
- */
- ret = ONEWIRE_RESET(master->dev);
- if (ret < 0)
- {
- i2cerr("ERROR: ONEWIRE_RESET failed: %d\n", ret);
- return ret;
- }
- ret = ONEWIRE_WRITE(master->dev, txbuf, sizeof(txbuf));
- if (ret < 0)
- {
- i2cerr("ERROR: ONEWIRE_WRITE failed: %d\n", ret);
- return ret;
- }
- ret = ONEWIRE_READ(master->dev, rxbuf, sizeof(rxbuf));
- if (ret < 0)
- {
- i2cerr("ERROR: ONEWIRE_READ failed: %d\n", ret);
- return ret;
- }
- #ifdef CONFIG_DEBUG_I2C_INFO
- lib_dumpbuffer("ds28e17_selftest: rxbuf", rxbuf, sizeof(rxbuf));
- #endif
- memcpy(&rom, rxbuf, 8);
- i2cinfo("recv rom: 0x%llx\n", rom);
- crc = onewire_crc8(rxbuf, sizeof(rxbuf)-1);
- i2cinfo("crc8=%d, recv crc8=%d\n", crc, (int)rxbuf[7]);
- if (crc != rxbuf[7])
- {
- i2cerr("ERROR: crc8 does not match!\n");
- ret = -EIO;
- }
- return ret;
- }
- /****************************************************************************
- * Public Functions
- ****************************************************************************/
- /****************************************************************************
- * Name: ds28e17_search
- *
- * Description:
- * Search all DS28E17 devices from a 1-wire network.
- *
- * Input Parameters:
- * priv - Pointer to the associated DS28E17
- * cb_search - Callback to call on each device found
- * arg - Argument passed to cb_search
- *
- * Return Value:
- * Number of DS28E17 devices present.
- *
- ****************************************************************************/
- int ds28e17_search(FAR struct ds28e17_dev_s *priv,
- void (*cb_search)(int family, uint64_t romcode, void *arg),
- void *arg)
- {
- FAR struct onewire_master_s *master = (FAR struct onewire_master_s *)priv;
- int ret;
- DEBUGASSERT(master != NULL && cb_search != NULL);
- onewire_sem_wait(master);
- ret = onewire_search(master, DS_FAMILY, false, cb_search, arg);
- onewire_sem_post(master);
- return ret;
- }
- /****************************************************************************
- * Name: ds28e17_lower_half
- *
- * Description:
- * Initialize the lower half of the DS28E17 by creating a i2c_master_s
- * for the virtual i2c master and link it to the associated DS28E17 and
- * its port.
- *
- * Input Parameters:
- * dev - Pointer to the associated DS28E17
- * romcode - The unique 64-bit address in 1-wire network.
- * Use zero for skip-ROM mode.
- *
- * Returned Value:
- * i2c device instance; NULL on failure.
- *
- ****************************************************************************/
- FAR struct i2c_master_s *
- ds28e17_lower_half(FAR struct ds28e17_dev_s *priv, uint64_t romcode)
- {
- FAR struct ds_i2c_inst_s *inst; /* device, single instance */
- FAR struct onewire_master_s *master = (FAR struct onewire_master_s *)priv;
- DEBUGASSERT(master != NULL);
- /* Allocate instance */
- inst = kmm_zalloc(sizeof(struct ds_i2c_inst_s));
- if (inst == NULL)
- {
- i2cerr("ERROR: Failed to allocate instance\n");
- return NULL;
- }
- /* Initialize instance */
- inst->ops = &ds_i2c_ops;
- inst->master = master;
- inst->frequency = 400000; /* power-on frequency */
- inst->stretch = DS_DEFAULT_STRETCH;
- inst->slave.romcode = romcode;
- /* We need a recursive lock as this may be called from a search callback. */
- onewire_sem_wait(master);
- if (onewire_addslave(master, &inst->slave) < 0)
- {
- kmm_free(inst);
- i2cerr("ERROR: Failed to add slave\n");
- onewire_sem_post(master);
- return NULL;
- }
- /* Should default speed be different from DS28E17 power-on frequency? */
- if (inst->frequency != DS_DEFAULT_FREQUENCY)
- {
- ds_i2c_setfrequency(inst, DS_DEFAULT_FREQUENCY);
- }
- /* TODO: better selftest */
- if (master->maxslaves == 1)
- {
- ds28e17_selftest(inst);
- }
- onewire_sem_post(master);
- return (struct i2c_master_s *)inst;
- }
- /****************************************************************************
- * Name: ds28e17_lower_half_unregister
- *
- * Description:
- * Put back the lower half of the DS28E17.
- *
- * Input Parameters:
- * priv - Pointer to the associated DS28E17
- * i2cdev - i2c device instance from ds28e17_lower_half()
- *
- * Returned Value:
- * Zero on success; a negated errno value on failure.
- *
- ****************************************************************************/
- int ds28e17_lower_half_unregister(FAR struct ds28e17_dev_s *priv,
- FAR struct i2c_master_s *i2cdev)
- {
- FAR struct ds_i2c_inst_s *inst = (FAR struct ds_i2c_inst_s *)i2cdev;
- FAR struct onewire_master_s *master = inst->master;
- int ret;
- onewire_sem_wait(master);
- ret = onewire_removeslave(master, &inst->slave);
- if (ret < 0)
- {
- kmm_free(inst);
- i2cerr("ERROR: Failed to remove slave\n");
- onewire_sem_post(master);
- return ret;
- }
- kmm_free(inst);
- onewire_sem_post(master);
- return OK;
- }
- /****************************************************************************
- * Name: ds28e17_initialize
- *
- * Description:
- * Returns a common DS28E17 device from 1-wire lower half device
- *
- * Input Parameters:
- * dev - The allocated 1-wire lower half
- *
- ****************************************************************************/
- FAR struct ds28e17_dev_s *ds28e17_initialize(FAR struct onewire_dev_s *dev)
- {
- FAR struct onewire_master_s *priv;
- priv = onewire_initialize(dev, DS_DEFAULT_MAXSLAVES);
- /* We do not have our own data fields so just cast it. */
- return (FAR struct ds28e17_dev_s *)priv;
- }
|