Lines Matching +full:serial +full:- +full:state

1 // SPDX-License-Identifier: GPL-2.0
3 * Sensirion SPS30 particulate matter sensor serial driver
51 static int sps30_serial_xfer(struct sps30_state *state, const unsigned char *buf, size_t size) in sps30_serial_xfer() argument
53 struct serdev_device *serdev = to_serdev_device(state->dev); in sps30_serial_xfer()
54 struct sps30_serial_priv *priv = state->priv; in sps30_serial_xfer()
57 priv->num = 0; in sps30_serial_xfer()
58 priv->escaped = false; in sps30_serial_xfer()
59 priv->done = false; in sps30_serial_xfer()
65 return -EIO; in sps30_serial_xfer()
67 ret = wait_for_completion_interruptible_timeout(&priv->new_frame, SPS30_SERIAL_TIMEOUT); in sps30_serial_xfer()
71 return -ETIMEDOUT; in sps30_serial_xfer()
149 chksum = sps30_serial_calc_chksum(buf + 1, num - 1); in sps30_serial_prep_frame()
156 static bool sps30_serial_frame_valid(struct sps30_state *state, const unsigned char *buf) in sps30_serial_frame_valid() argument
158 struct sps30_serial_priv *priv = state->priv; in sps30_serial_frame_valid()
161 if ((priv->num < SPS30_SERIAL_FRAME_MIN_SIZE) || in sps30_serial_frame_valid()
162 (priv->num != SPS30_SERIAL_FRAME_MIN_SIZE + in sps30_serial_frame_valid()
163 priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET])) { in sps30_serial_frame_valid()
164 dev_err(state->dev, "frame has invalid number of bytes\n"); in sps30_serial_frame_valid()
168 if ((priv->buf[SPS30_SERIAL_FRAME_ADR_OFFSET] != buf[SPS30_SERIAL_FRAME_ADR_OFFSET]) || in sps30_serial_frame_valid()
169 (priv->buf[SPS30_SERIAL_FRAME_CMD_OFFSET] != buf[SPS30_SERIAL_FRAME_CMD_OFFSET])) { in sps30_serial_frame_valid()
170 dev_err(state->dev, "frame has wrong ADR and CMD bytes\n"); in sps30_serial_frame_valid()
174 if (priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]) { in sps30_serial_frame_valid()
175 dev_err(state->dev, "frame with non-zero state received (0x%02x)\n", in sps30_serial_frame_valid()
176 priv->buf[SPS30_SERIAL_FRAME_MISO_STATE_OFFSET]); in sps30_serial_frame_valid()
181 chksum = sps30_serial_calc_chksum(priv->buf + 1, priv->num - 3); in sps30_serial_frame_valid()
182 if (priv->buf[priv->num - 2] != chksum) { in sps30_serial_frame_valid()
183 dev_err(state->dev, "frame integrity check failed\n"); in sps30_serial_frame_valid()
190 static int sps30_serial_command(struct sps30_state *state, unsigned char cmd, in sps30_serial_command() argument
193 struct sps30_serial_priv *priv = state->priv; in sps30_serial_command()
198 ret = sps30_serial_xfer(state, buf, size); in sps30_serial_command()
202 if (!sps30_serial_frame_valid(state, buf)) in sps30_serial_command()
203 return -EIO; in sps30_serial_command()
206 rsp_size = min_t(size_t, priv->buf[SPS30_SERIAL_FRAME_MISO_LEN_OFFSET], rsp_size); in sps30_serial_command()
207 memcpy(rsp, &priv->buf[SPS30_SERIAL_FRAME_MISO_DATA_OFFSET], rsp_size); in sps30_serial_command()
216 struct iio_dev *indio_dev = dev_get_drvdata(&serdev->dev); in sps30_serial_receive_buf()
218 struct sps30_state *state; in sps30_serial_receive_buf() local
225 state = iio_priv(indio_dev); in sps30_serial_receive_buf()
226 priv = state->priv; in sps30_serial_receive_buf()
229 if (priv->done) in sps30_serial_receive_buf()
233 if (!priv->num && size && buf[0] != SPS30_SERIAL_SOF_EOF) in sps30_serial_receive_buf()
236 if (priv->num + size >= ARRAY_SIZE(priv->buf)) in sps30_serial_receive_buf()
237 size = ARRAY_SIZE(priv->buf) - priv->num; in sps30_serial_receive_buf()
241 /* remove stuffed bytes on-the-fly */ in sps30_serial_receive_buf()
243 priv->escaped = true; in sps30_serial_receive_buf()
247 byte = sps30_serial_get_byte(priv->escaped, byte); in sps30_serial_receive_buf()
248 if (priv->escaped && !byte) in sps30_serial_receive_buf()
249 dev_warn(state->dev, "unrecognized escaped char (0x%02x)\n", byte); in sps30_serial_receive_buf()
251 priv->buf[priv->num++] = byte; in sps30_serial_receive_buf()
254 if (!priv->escaped && byte == SPS30_SERIAL_SOF_EOF) { in sps30_serial_receive_buf()
255 if (priv->num < SPS30_SERIAL_FRAME_MIN_SIZE) in sps30_serial_receive_buf()
258 priv->done = true; in sps30_serial_receive_buf()
259 complete(&priv->new_frame); in sps30_serial_receive_buf()
264 priv->escaped = false; in sps30_serial_receive_buf()
275 static int sps30_serial_start_meas(struct sps30_state *state) in sps30_serial_start_meas() argument
280 return sps30_serial_command(state, SPS30_SERIAL_START_MEAS, buf, sizeof(buf), NULL, 0); in sps30_serial_start_meas()
283 static int sps30_serial_stop_meas(struct sps30_state *state) in sps30_serial_stop_meas() argument
285 return sps30_serial_command(state, SPS30_SERIAL_STOP_MEAS, NULL, 0, NULL, 0); in sps30_serial_stop_meas()
288 static int sps30_serial_reset(struct sps30_state *state) in sps30_serial_reset() argument
292 ret = sps30_serial_command(state, SPS30_SERIAL_RESET, NULL, 0, NULL, 0); in sps30_serial_reset()
298 static int sps30_serial_read_meas(struct sps30_state *state, __be32 *meas, size_t num) in sps30_serial_read_meas() argument
304 return -EINTR; in sps30_serial_read_meas()
306 ret = sps30_serial_command(state, SPS30_SERIAL_READ_MEAS, NULL, 0, meas, num * sizeof(num)); in sps30_serial_read_meas()
311 return -ETIMEDOUT; in sps30_serial_read_meas()
313 return -EIO; in sps30_serial_read_meas()
318 static int sps30_serial_clean_fan(struct sps30_state *state) in sps30_serial_clean_fan() argument
320 return sps30_serial_command(state, SPS30_SERIAL_CLEAN_FAN, NULL, 0, NULL, 0); in sps30_serial_clean_fan()
323 static int sps30_serial_read_cleaning_period(struct sps30_state *state, __be32 *period) in sps30_serial_read_cleaning_period() argument
328 ret = sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf), in sps30_serial_read_cleaning_period()
333 return -EIO; in sps30_serial_read_cleaning_period()
338 static int sps30_serial_write_cleaning_period(struct sps30_state *state, __be32 period) in sps30_serial_write_cleaning_period() argument
344 return sps30_serial_command(state, SPS30_SERIAL_PERIOD, buf, sizeof(buf), NULL, 0); in sps30_serial_write_cleaning_period()
347 static int sps30_serial_show_info(struct sps30_state *state) in sps30_serial_show_info() argument
350 * tell device do return serial number and add extra nul byte just in case in sps30_serial_show_info()
351 * serial number isn't a valid string in sps30_serial_show_info()
354 struct device *dev = state->dev; in sps30_serial_show_info()
357 ret = sps30_serial_command(state, SPS30_SERIAL_DEV_INFO, buf, 1, buf, sizeof(buf) - 1); in sps30_serial_show_info()
360 if (ret != sizeof(buf) - 1) in sps30_serial_show_info()
361 return -EIO; in sps30_serial_show_info()
363 dev_info(dev, "serial number: %s\n", buf); in sps30_serial_show_info()
365 ret = sps30_serial_command(state, SPS30_SERIAL_READ_VERSION, NULL, 0, buf, sizeof(buf) - 1); in sps30_serial_show_info()
369 return -EIO; in sps30_serial_show_info()
389 struct device *dev = &serdev->dev; in sps30_serial_probe()
395 return -ENOMEM; in sps30_serial_probe()
397 init_completion(&priv->new_frame); in sps30_serial_probe()
430 MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor serial driver");