Lines Matching refs:rctx

42 static void receive_state_machine(struct isotp_recv_ctx *rctx);
65 struct isotp_recv_ctx *rctx; in receive_pool_free() local
71 rctx = CONTAINER_OF(rctx_node, struct isotp_recv_ctx, alloc_node); in receive_pool_free()
72 k_work_submit(&rctx->work); in receive_pool_free()
78 struct isotp_recv_ctx *rctx; in receive_ff_sf_pool_free() local
84 rctx = CONTAINER_OF(rctx_node, struct isotp_recv_ctx, alloc_node); in receive_ff_sf_pool_free()
85 k_work_submit(&rctx->work); in receive_ff_sf_pool_free()
89 static inline void receive_report_error(struct isotp_recv_ctx *rctx, int err) in receive_report_error() argument
91 rctx->state = ISOTP_RX_STATE_ERR; in receive_report_error()
92 rctx->error_nr = err; in receive_report_error()
97 struct isotp_recv_ctx *rctx = (struct isotp_recv_ctx *)arg; in receive_can_tx() local
103 receive_report_error(rctx, ISOTP_N_ERROR); in receive_can_tx()
104 k_work_submit(&rctx->work); in receive_can_tx()
135 static void receive_send_fc(struct isotp_recv_ctx *rctx, uint8_t fs) in receive_send_fc() argument
144 prepare_frame(&frame, &rctx->tx_addr); in receive_send_fc()
146 if ((rctx->tx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { in receive_send_fc()
147 *data++ = rctx->tx_addr.ext_addr; in receive_send_fc()
151 *data++ = rctx->opts.bs; in receive_send_fc()
152 *data++ = rctx->opts.stmin; in receive_send_fc()
164 ret = can_send(rctx->can_dev, &frame, K_MSEC(ISOTP_A_TIMEOUT_MS), receive_can_tx, rctx); in receive_send_fc()
167 receive_report_error(rctx, ISOTP_N_TIMEOUT_A); in receive_send_fc()
168 receive_state_machine(rctx); in receive_send_fc()
207 struct isotp_recv_ctx *rctx = CONTAINER_OF(timer, struct isotp_recv_ctx, timer); in receive_timeout_handler() local
209 switch (rctx->state) { in receive_timeout_handler()
212 receive_report_error(rctx, ISOTP_N_TIMEOUT_CR); in receive_timeout_handler()
216 rctx->state = ISOTP_RX_STATE_SEND_WAIT; in receive_timeout_handler()
220 k_work_submit(&rctx->work); in receive_timeout_handler()
223 static int receive_alloc_buffer(struct isotp_recv_ctx *rctx) in receive_alloc_buffer() argument
227 if (rctx->opts.bs == 0) { in receive_alloc_buffer()
229 buf = receive_alloc_buffer_chain(rctx->length); in receive_alloc_buffer()
232 uint32_t len = MIN(rctx->length, rctx->opts.bs * (rctx->rx_addr.dl - 1)); in receive_alloc_buffer()
238 k_timer_start(&rctx->timer, K_MSEC(ISOTP_ALLOC_TIMEOUT_MS), K_NO_WAIT); in receive_alloc_buffer()
240 if (rctx->wft == ISOTP_WFT_FIRST) { in receive_alloc_buffer()
242 rctx->wft = 0; in receive_alloc_buffer()
243 sys_slist_append(&global_ctx.alloc_list, &rctx->alloc_node); in receive_alloc_buffer()
246 rctx->state = ISOTP_RX_STATE_SEND_WAIT; in receive_alloc_buffer()
247 receive_state_machine(rctx); in receive_alloc_buffer()
253 if (rctx->state == ISOTP_RX_STATE_TRY_ALLOC) { in receive_alloc_buffer()
254 k_timer_stop(&rctx->timer); in receive_alloc_buffer()
255 rctx->wft = ISOTP_WFT_FIRST; in receive_alloc_buffer()
256 sys_slist_find_and_remove(&global_ctx.alloc_list, &rctx->alloc_node); in receive_alloc_buffer()
259 if (rctx->opts.bs != 0) { in receive_alloc_buffer()
260 rctx->buf = buf; in receive_alloc_buffer()
262 net_buf_frag_insert(rctx->buf, buf); in receive_alloc_buffer()
265 rctx->act_frag = buf; in receive_alloc_buffer()
269 static void receive_state_machine(struct isotp_recv_ctx *rctx) in receive_state_machine() argument
274 switch (rctx->state) { in receive_state_machine()
276 rctx->length = receive_get_sf_length(rctx->buf, in receive_state_machine()
277 (rctx->rx_addr.flags & ISOTP_MSG_FDF) != 0); in receive_state_machine()
278 ud_rem_len = net_buf_user_data(rctx->buf); in receive_state_machine()
280 LOG_DBG("SM process SF of length %d", rctx->length); in receive_state_machine()
281 k_fifo_put(&rctx->fifo, rctx->buf); in receive_state_machine()
282 rctx->state = ISOTP_RX_STATE_RECYCLE; in receive_state_machine()
283 receive_state_machine(rctx); in receive_state_machine()
287 rctx->length = receive_get_ff_length(rctx->buf); in receive_state_machine()
288 LOG_DBG("SM process FF. Length: %d", rctx->length); in receive_state_machine()
289 rctx->length -= rctx->buf->len; in receive_state_machine()
290 if (rctx->opts.bs == 0 && in receive_state_machine()
291 rctx->length > CONFIG_ISOTP_RX_BUF_COUNT * CONFIG_ISOTP_RX_BUF_SIZE) { in receive_state_machine()
292 LOG_ERR("Pkt length is %d but buffer has only %d bytes", rctx->length, in receive_state_machine()
294 receive_report_error(rctx, ISOTP_N_BUFFER_OVERFLW); in receive_state_machine()
295 receive_state_machine(rctx); in receive_state_machine()
299 if (rctx->opts.bs) { in receive_state_machine()
300 rctx->bs = rctx->opts.bs; in receive_state_machine()
301 ud_rem_len = net_buf_user_data(rctx->buf); in receive_state_machine()
302 *ud_rem_len = rctx->length; in receive_state_machine()
303 k_fifo_put(&rctx->fifo, rctx->buf); in receive_state_machine()
306 rctx->wft = ISOTP_WFT_FIRST; in receive_state_machine()
307 rctx->state = ISOTP_RX_STATE_TRY_ALLOC; in receive_state_machine()
311 k_timer_stop(&rctx->timer); in receive_state_machine()
312 ret = receive_alloc_buffer(rctx); in receive_state_machine()
318 rctx->state = ISOTP_RX_STATE_SEND_FC; in receive_state_machine()
322 receive_send_fc(rctx, ISOTP_PCI_FS_CTS); in receive_state_machine()
323 k_timer_start(&rctx->timer, K_MSEC(ISOTP_CR_TIMEOUT_MS), K_NO_WAIT); in receive_state_machine()
324 rctx->state = ISOTP_RX_STATE_WAIT_CF; in receive_state_machine()
328 if (++rctx->wft < CONFIG_ISOTP_WFTMAX) { in receive_state_machine()
329 LOG_DBG("Send wait frame number %d", rctx->wft); in receive_state_machine()
330 receive_send_fc(rctx, ISOTP_PCI_FS_WAIT); in receive_state_machine()
331 k_timer_start(&rctx->timer, K_MSEC(ISOTP_ALLOC_TIMEOUT_MS), K_NO_WAIT); in receive_state_machine()
332 rctx->state = ISOTP_RX_STATE_TRY_ALLOC; in receive_state_machine()
336 sys_slist_find_and_remove(&global_ctx.alloc_list, &rctx->alloc_node); in receive_state_machine()
337 LOG_ERR("Sent %d wait frames. Giving up to alloc now", rctx->wft); in receive_state_machine()
338 receive_report_error(rctx, ISOTP_N_BUFFER_OVERFLW); in receive_state_machine()
341 LOG_DBG("SM ERR state. err nr: %d", rctx->error_nr); in receive_state_machine()
342 k_timer_stop(&rctx->timer); in receive_state_machine()
344 if (rctx->error_nr == ISOTP_N_BUFFER_OVERFLW) { in receive_state_machine()
345 receive_send_fc(rctx, ISOTP_PCI_FS_OVFLW); in receive_state_machine()
348 k_fifo_cancel_wait(&rctx->fifo); in receive_state_machine()
349 net_buf_unref(rctx->buf); in receive_state_machine()
350 rctx->buf = NULL; in receive_state_machine()
351 rctx->state = ISOTP_RX_STATE_RECYCLE; in receive_state_machine()
355 rctx->buf = net_buf_alloc_fixed(&isotp_rx_sf_ff_pool, K_NO_WAIT); in receive_state_machine()
356 if (!rctx->buf) { in receive_state_machine()
358 sys_slist_append(&global_ctx.ff_sf_alloc_list, &rctx->alloc_node); in receive_state_machine()
362 sys_slist_find_and_remove(&global_ctx.ff_sf_alloc_list, &rctx->alloc_node); in receive_state_machine()
363 rctx->state = ISOTP_RX_STATE_WAIT_FF_SF; in receive_state_machine()
375 struct isotp_recv_ctx *rctx = CONTAINER_OF(item, struct isotp_recv_ctx, work); in receive_work_handler() local
377 receive_state_machine(rctx); in receive_work_handler()
380 static void process_ff_sf(struct isotp_recv_ctx *rctx, struct can_frame *frame) in process_ff_sf() argument
388 if ((rctx->rx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { in process_ff_sf()
389 if (frame->data[index++] != rctx->rx_addr.ext_addr) { in process_ff_sf()
394 if ((rctx->rx_addr.flags & ISOTP_MSG_FIXED_ADDR) != 0) { in process_ff_sf()
396 rctx->rx_addr.ext_id = frame->id; in process_ff_sf()
400 rctx->tx_addr.ext_id &= ~(ISOTP_FIXED_ADDR_TA_MASK); in process_ff_sf()
401 rctx->tx_addr.ext_id |= rx_sa << ISOTP_FIXED_ADDR_TA_POS; in process_ff_sf()
404 rctx->tx_addr.ext_id &= ~(ISOTP_FIXED_ADDR_PRIO_MASK); in process_ff_sf()
405 rctx->tx_addr.ext_id |= frame->id & ISOTP_FIXED_ADDR_PRIO_MASK; in process_ff_sf()
418 rctx->state = ISOTP_RX_STATE_PROCESS_FF; in process_ff_sf()
419 rctx->rx_addr.dl = can_dl; in process_ff_sf()
420 rctx->sn_expected = 1; in process_ff_sf()
435 if (IS_ENABLED(CONFIG_CAN_FD_MODE) && (rctx->rx_addr.flags & ISOTP_MSG_FDF) != 0 && in process_ff_sf()
452 rctx->state = ISOTP_RX_STATE_PROCESS_SF; in process_ff_sf()
460 net_buf_add_mem(rctx->buf, &frame->data[index], payload_len - index); in process_ff_sf()
463 static inline void receive_add_mem(struct isotp_recv_ctx *rctx, uint8_t *data, size_t len) in receive_add_mem() argument
465 size_t tailroom = net_buf_tailroom(rctx->act_frag); in receive_add_mem()
468 net_buf_add_mem(rctx->act_frag, data, len); in receive_add_mem()
473 net_buf_add_mem(rctx->act_frag, data, tailroom); in receive_add_mem()
474 rctx->act_frag = rctx->act_frag->frags; in receive_add_mem()
475 if (!rctx->act_frag) { in receive_add_mem()
477 receive_report_error(rctx, ISOTP_N_BUFFER_OVERFLW); in receive_add_mem()
481 net_buf_add_mem(rctx->act_frag, data + tailroom, len - tailroom); in receive_add_mem()
484 static void process_cf(struct isotp_recv_ctx *rctx, struct can_frame *frame) in process_cf() argument
486 uint32_t *ud_rem_len = (uint32_t *)net_buf_user_data(rctx->buf); in process_cf()
491 if ((rctx->rx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { in process_cf()
492 if (frame->data[index++] != rctx->rx_addr.ext_addr) { in process_cf()
500 receive_report_error(rctx, ISOTP_N_UNEXP_PDU); in process_cf()
501 k_work_submit(&rctx->work); in process_cf()
505 k_timer_start(&rctx->timer, K_MSEC(ISOTP_CR_TIMEOUT_MS), K_NO_WAIT); in process_cf()
507 if ((frame->data[index++] & ISOTP_PCI_SN_MASK) != rctx->sn_expected++) { in process_cf()
509 receive_report_error(rctx, ISOTP_N_WRONG_SN); in process_cf()
510 k_work_submit(&rctx->work); in process_cf()
518 receive_report_error(rctx, ISOTP_N_ERROR); in process_cf()
526 if (can_dl != rctx->rx_addr.dl && rctx->length > can_dl - index) { in process_cf()
528 receive_report_error(rctx, ISOTP_N_ERROR); in process_cf()
533 data_len = MIN(rctx->length, can_dl - index); in process_cf()
534 receive_add_mem(rctx, &frame->data[index], data_len); in process_cf()
535 rctx->length -= data_len; in process_cf()
536 LOG_DBG("%d bytes remaining", rctx->length); in process_cf()
538 if (rctx->length == 0) { in process_cf()
539 rctx->state = ISOTP_RX_STATE_RECYCLE; in process_cf()
541 k_fifo_put(&rctx->fifo, rctx->buf); in process_cf()
545 if (rctx->opts.bs && !--rctx->bs) { in process_cf()
547 rctx->bs = rctx->opts.bs; in process_cf()
548 *ud_rem_len = rctx->length; in process_cf()
549 k_fifo_put(&rctx->fifo, rctx->buf); in process_cf()
550 rctx->state = ISOTP_RX_STATE_TRY_ALLOC; in process_cf()
556 struct isotp_recv_ctx *rctx = (struct isotp_recv_ctx *)arg; in receive_can_rx() local
564 switch (rctx->state) { in receive_can_rx()
566 __ASSERT_NO_MSG(rctx->buf); in receive_can_rx()
567 process_ff_sf(rctx, frame); in receive_can_rx()
571 process_cf(rctx, frame); in receive_can_rx()
573 if (rctx->state == ISOTP_RX_STATE_WAIT_CF) { in receive_can_rx()
581 receive_report_error(rctx, ISOTP_N_BUFFER_OVERFLW); in receive_can_rx()
588 k_work_submit(&rctx->work); in receive_can_rx()
591 static inline int add_ff_sf_filter(struct isotp_recv_ctx *rctx) in add_ff_sf_filter() argument
596 if ((rctx->rx_addr.flags & ISOTP_MSG_FIXED_ADDR) != 0) { in add_ff_sf_filter()
598 } else if ((rctx->rx_addr.flags & ISOTP_MSG_IDE) != 0) { in add_ff_sf_filter()
604 prepare_filter(&filter, &rctx->rx_addr, mask); in add_ff_sf_filter()
606 rctx->filter_id = can_add_rx_filter(rctx->can_dev, receive_can_rx, rctx, &filter); in add_ff_sf_filter()
607 if (rctx->filter_id < 0) { in add_ff_sf_filter()
608 LOG_ERR("Error adding FF filter [%d]", rctx->filter_id); in add_ff_sf_filter()
615 int isotp_bind(struct isotp_recv_ctx *rctx, const struct device *can_dev, in isotp_bind() argument
624 __ASSERT(rctx, "rctx is NULL"); in isotp_bind()
629 rctx->can_dev = can_dev; in isotp_bind()
630 rctx->rx_addr = *rx_addr; in isotp_bind()
631 rctx->tx_addr = *tx_addr; in isotp_bind()
632 k_fifo_init(&rctx->fifo); in isotp_bind()
638 rctx->opts = *opts; in isotp_bind()
639 rctx->state = ISOTP_RX_STATE_WAIT_FF_SF; in isotp_bind()
650 rctx->rx_addr.ext_id, rctx->tx_addr.ext_id); in isotp_bind()
652 rctx->buf = net_buf_alloc_fixed(&isotp_rx_sf_ff_pool, timeout); in isotp_bind()
653 if (!rctx->buf) { in isotp_bind()
658 ret = add_ff_sf_filter(rctx); in isotp_bind()
661 net_buf_unref(rctx->buf); in isotp_bind()
662 rctx->buf = NULL; in isotp_bind()
666 k_work_init(&rctx->work, receive_work_handler); in isotp_bind()
667 k_timer_init(&rctx->timer, receive_timeout_handler, NULL); in isotp_bind()
672 void isotp_unbind(struct isotp_recv_ctx *rctx) in isotp_unbind() argument
676 if (rctx->filter_id >= 0 && rctx->can_dev) { in isotp_unbind()
677 can_remove_rx_filter(rctx->can_dev, rctx->filter_id); in isotp_unbind()
680 k_timer_stop(&rctx->timer); in isotp_unbind()
682 sys_slist_find_and_remove(&global_ctx.ff_sf_alloc_list, &rctx->alloc_node); in isotp_unbind()
683 sys_slist_find_and_remove(&global_ctx.alloc_list, &rctx->alloc_node); in isotp_unbind()
685 rctx->state = ISOTP_RX_STATE_UNBOUND; in isotp_unbind()
687 while ((buf = k_fifo_get(&rctx->fifo, K_NO_WAIT))) { in isotp_unbind()
691 k_fifo_cancel_wait(&rctx->fifo); in isotp_unbind()
693 if (rctx->buf) { in isotp_unbind()
694 net_buf_unref(rctx->buf); in isotp_unbind()
700 int isotp_recv_net(struct isotp_recv_ctx *rctx, struct net_buf **buffer, k_timeout_t timeout) in isotp_recv_net() argument
705 buf = k_fifo_get(&rctx->fifo, timeout); in isotp_recv_net()
707 ret = rctx->error_nr ? rctx->error_nr : ISOTP_RECV_TIMEOUT; in isotp_recv_net()
708 rctx->error_nr = 0; in isotp_recv_net()
718 int isotp_recv(struct isotp_recv_ctx *rctx, uint8_t *data, size_t len, k_timeout_t timeout) in isotp_recv() argument
723 if (!rctx->recv_buf) { in isotp_recv()
724 rctx->recv_buf = k_fifo_get(&rctx->fifo, timeout); in isotp_recv()
725 if (!rctx->recv_buf) { in isotp_recv()
726 err = rctx->error_nr ? rctx->error_nr : ISOTP_RECV_TIMEOUT; in isotp_recv()
727 rctx->error_nr = 0; in isotp_recv()
735 while (rctx->recv_buf && copied < len) { in isotp_recv()
736 to_copy = MIN(len - copied, rctx->recv_buf->len); in isotp_recv()
737 memcpy((uint8_t *)data + copied, rctx->recv_buf->data, to_copy); in isotp_recv()
739 if (rctx->recv_buf->len == to_copy) { in isotp_recv()
741 rctx->recv_buf = net_buf_frag_del(NULL, rctx->recv_buf); in isotp_recv()
744 net_buf_pull(rctx->recv_buf, to_copy); in isotp_recv()