Lines Matching refs:sctx

753 static inline void send_report_error(struct isotp_send_ctx *sctx, uint32_t err)  in send_report_error()  argument
755 sctx->state = ISOTP_TX_ERR; in send_report_error()
756 sctx->error_nr = err; in send_report_error()
761 struct isotp_send_ctx *sctx = (struct isotp_send_ctx *)arg; in send_can_tx_cb() local
765 sctx->tx_backlog--; in send_can_tx_cb()
766 k_sem_give(&sctx->tx_sem); in send_can_tx_cb()
768 if (sctx->state == ISOTP_TX_WAIT_BACKLOG) { in send_can_tx_cb()
769 if (sctx->tx_backlog > 0) { in send_can_tx_cb()
773 sctx->state = ISOTP_TX_WAIT_FIN; in send_can_tx_cb()
776 k_work_submit(&sctx->work); in send_can_tx_cb()
781 struct isotp_send_ctx *sctx = CONTAINER_OF(timer, struct isotp_send_ctx, timer); in send_timeout_handler() local
783 if (sctx->state != ISOTP_TX_SEND_CF) { in send_timeout_handler()
784 send_report_error(sctx, ISOTP_N_TIMEOUT_BS); in send_timeout_handler()
788 k_work_submit(&sctx->work); in send_timeout_handler()
791 static void send_process_fc(struct isotp_send_ctx *sctx, struct can_frame *frame) in send_process_fc() argument
795 if ((sctx->rx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { in send_process_fc()
796 if (sctx->rx_addr.ext_addr != *data++) { in send_process_fc()
803 send_report_error(sctx, ISOTP_N_UNEXP_PDU); in send_process_fc()
811 send_report_error(sctx, ISOTP_N_ERROR); in send_process_fc()
818 sctx->state = ISOTP_TX_SEND_CF; in send_process_fc()
819 sctx->wft = 0; in send_process_fc()
820 sctx->tx_backlog = 0; in send_process_fc()
821 k_sem_reset(&sctx->tx_sem); in send_process_fc()
822 sctx->opts.bs = *data++; in send_process_fc()
823 sctx->opts.stmin = *data++; in send_process_fc()
824 sctx->bs = sctx->opts.bs; in send_process_fc()
825 LOG_DBG("Got CTS. BS: %d, STmin: %d", sctx->opts.bs, in send_process_fc()
826 sctx->opts.stmin); in send_process_fc()
831 k_timer_start(&sctx->timer, K_MSEC(ISOTP_BS_TIMEOUT_MS), K_NO_WAIT); in send_process_fc()
832 if (sctx->wft >= CONFIG_ISOTP_WFTMAX) { in send_process_fc()
834 send_report_error(sctx, ISOTP_N_WFT_OVRN); in send_process_fc()
837 sctx->wft++; in send_process_fc()
842 send_report_error(sctx, ISOTP_N_BUFFER_OVERFLW); in send_process_fc()
846 send_report_error(sctx, ISOTP_N_INVALID_FS); in send_process_fc()
852 struct isotp_send_ctx *sctx = (struct isotp_send_ctx *)arg; in send_can_rx_cb() local
860 if (sctx->state == ISOTP_TX_WAIT_FC) { in send_can_rx_cb()
861 k_timer_stop(&sctx->timer); in send_can_rx_cb()
862 send_process_fc(sctx, frame); in send_can_rx_cb()
865 send_report_error(sctx, ISOTP_N_UNEXP_PDU); in send_can_rx_cb()
868 k_work_submit(&sctx->work); in send_can_rx_cb()
871 static size_t get_send_ctx_data_len(struct isotp_send_ctx *sctx) in get_send_ctx_data_len() argument
873 return sctx->is_net_buf ? net_buf_frags_len(sctx->buf) : sctx->len; in get_send_ctx_data_len()
876 static const uint8_t *get_send_ctx_data(struct isotp_send_ctx *sctx) in get_send_ctx_data() argument
878 if (sctx->is_net_buf) { in get_send_ctx_data()
879 return sctx->buf->data; in get_send_ctx_data()
881 return sctx->data; in get_send_ctx_data()
885 static void pull_send_ctx_data(struct isotp_send_ctx *sctx, size_t len) in pull_send_ctx_data() argument
887 if (sctx->is_net_buf) { in pull_send_ctx_data()
888 net_buf_pull_mem(sctx->buf, len); in pull_send_ctx_data()
890 sctx->data += len; in pull_send_ctx_data()
891 sctx->len -= len; in pull_send_ctx_data()
895 static inline int send_sf(struct isotp_send_ctx *sctx) in send_sf() argument
898 size_t len = get_send_ctx_data_len(sctx); in send_sf()
903 prepare_frame(&frame, &sctx->tx_addr); in send_sf()
905 data = get_send_ctx_data(sctx); in send_sf()
906 pull_send_ctx_data(sctx, len); in send_sf()
908 if ((sctx->tx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { in send_sf()
909 frame.data[index++] = sctx->tx_addr.ext_addr; in send_sf()
912 if (IS_ENABLED(CONFIG_CAN_FD_MODE) && (sctx->tx_addr.flags & ISOTP_MSG_FDF) != 0 && in send_sf()
920 if (len > sctx->tx_addr.dl - index) { in send_sf()
928 (IS_ENABLED(CONFIG_CAN_FD_MODE) && (sctx->tx_addr.flags & ISOTP_MSG_FDF) != 0 && in send_sf()
941 sctx->state = ISOTP_TX_SEND_SF; in send_sf()
942 ret = can_send(sctx->can_dev, &frame, K_MSEC(ISOTP_A_TIMEOUT_MS), send_can_tx_cb, sctx); in send_sf()
946 static inline int send_ff(struct isotp_send_ctx *sctx) in send_ff() argument
950 size_t len = get_send_ctx_data_len(sctx); in send_ff()
954 prepare_frame(&frame, &sctx->tx_addr); in send_ff()
956 frame.dlc = can_bytes_to_dlc(sctx->tx_addr.dl); in send_ff()
958 if ((sctx->tx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { in send_ff()
959 frame.data[index++] = sctx->tx_addr.ext_addr; in send_ff()
977 sctx->sn = 1; in send_ff()
978 data = get_send_ctx_data(sctx); in send_ff()
979 pull_send_ctx_data(sctx, sctx->tx_addr.dl - index); in send_ff()
980 memcpy(&frame.data[index], data, sctx->tx_addr.dl - index); in send_ff()
982 ret = can_send(sctx->can_dev, &frame, K_MSEC(ISOTP_A_TIMEOUT_MS), send_can_tx_cb, sctx); in send_ff()
986 static inline int send_cf(struct isotp_send_ctx *sctx) in send_cf() argument
995 prepare_frame(&frame, &sctx->tx_addr); in send_cf()
997 if ((sctx->tx_addr.flags & ISOTP_MSG_EXT_ADDR) != 0) { in send_cf()
998 frame.data[index++] = sctx->tx_addr.ext_addr; in send_cf()
1002 frame.data[index++] = ISOTP_PCI_TYPE_CF | sctx->sn; in send_cf()
1004 rem_len = get_send_ctx_data_len(sctx); in send_cf()
1005 len = MIN(rem_len, sctx->tx_addr.dl - index); in send_cf()
1007 data = get_send_ctx_data(sctx); in send_cf()
1011 (IS_ENABLED(CONFIG_CAN_FD_MODE) && (sctx->tx_addr.flags & ISOTP_MSG_FDF) != 0 && in send_cf()
1024 ret = can_send(sctx->can_dev, &frame, K_MSEC(ISOTP_A_TIMEOUT_MS), send_can_tx_cb, sctx); in send_cf()
1026 sctx->sn++; in send_cf()
1027 pull_send_ctx_data(sctx, len); in send_cf()
1028 sctx->bs--; in send_cf()
1029 sctx->tx_backlog++; in send_cf()
1037 static inline void free_send_ctx(struct isotp_send_ctx **sctx) in free_send_ctx() argument
1039 if ((*sctx)->is_net_buf) { in free_send_ctx()
1040 net_buf_unref((*sctx)->buf); in free_send_ctx()
1041 (*sctx)->buf = NULL; in free_send_ctx()
1044 if ((*sctx)->is_ctx_slab) { in free_send_ctx()
1045 k_mem_slab_free(&ctx_slab, (void *)*sctx); in free_send_ctx()
1049 static int alloc_send_ctx(struct isotp_send_ctx **sctx, k_timeout_t timeout) in alloc_send_ctx() argument
1053 ret = k_mem_slab_alloc(&ctx_slab, (void **)sctx, timeout); in alloc_send_ctx()
1058 (*sctx)->is_ctx_slab = 1; in alloc_send_ctx()
1081 static void send_state_machine(struct isotp_send_ctx *sctx) in send_state_machine() argument
1085 switch (sctx->state) { in send_state_machine()
1088 send_ff(sctx); in send_state_machine()
1089 k_timer_start(&sctx->timer, K_MSEC(ISOTP_BS_TIMEOUT_MS), K_NO_WAIT); in send_state_machine()
1090 sctx->state = ISOTP_TX_WAIT_FC; in send_state_machine()
1096 k_timer_stop(&sctx->timer); in send_state_machine()
1098 ret = send_cf(sctx); in send_state_machine()
1100 sctx->state = ISOTP_TX_WAIT_BACKLOG; in send_state_machine()
1106 send_report_error(sctx, ret == -EAGAIN ? in send_state_machine()
1112 if (sctx->opts.bs && !sctx->bs) { in send_state_machine()
1113 k_timer_start(&sctx->timer, K_MSEC(ISOTP_BS_TIMEOUT_MS), K_NO_WAIT); in send_state_machine()
1114 sctx->state = ISOTP_TX_WAIT_FC; in send_state_machine()
1117 } else if (sctx->opts.stmin) { in send_state_machine()
1118 sctx->state = ISOTP_TX_WAIT_ST; in send_state_machine()
1123 k_sem_take(&sctx->tx_sem, K_FOREVER); in send_state_machine()
1129 k_timer_start(&sctx->timer, stmin_to_timeout(sctx->opts.stmin), K_NO_WAIT); in send_state_machine()
1130 sctx->state = ISOTP_TX_SEND_CF; in send_state_machine()
1140 if (sctx->filter_id >= 0) { in send_state_machine()
1141 can_remove_rx_filter(sctx->can_dev, sctx->filter_id); in send_state_machine()
1145 k_timer_stop(&sctx->timer); in send_state_machine()
1147 if (sctx->has_callback) { in send_state_machine()
1148 sctx->fin_cb.cb(sctx->error_nr, sctx->fin_cb.arg); in send_state_machine()
1149 free_send_ctx(&sctx); in send_state_machine()
1151 k_sem_give(&sctx->fin_sem); in send_state_machine()
1154 sctx->state = ISOTP_TX_STATE_RESET; in send_state_machine()
1164 struct isotp_send_ctx *sctx = CONTAINER_OF(item, struct isotp_send_ctx, work); in send_work_handler() local
1166 send_state_machine(sctx); in send_work_handler()
1169 static inline int add_fc_filter(struct isotp_send_ctx *sctx) in add_fc_filter() argument
1174 if ((sctx->rx_addr.flags & ISOTP_MSG_IDE) != 0) { in add_fc_filter()
1180 prepare_filter(&filter, &sctx->rx_addr, mask); in add_fc_filter()
1182 sctx->filter_id = can_add_rx_filter(sctx->can_dev, send_can_rx_cb, sctx, in add_fc_filter()
1184 if (sctx->filter_id < 0) { in add_fc_filter()
1185 LOG_ERR("Error adding FC filter [%d]", sctx->filter_id); in add_fc_filter()
1192 static int send(struct isotp_send_ctx *sctx, const struct device *can_dev, in send() argument
1201 __ASSERT_NO_MSG(sctx); in send()
1214 sctx->fin_cb.cb = complete_cb; in send()
1215 sctx->fin_cb.arg = cb_arg; in send()
1216 sctx->has_callback = 1; in send()
1218 k_sem_init(&sctx->fin_sem, 0, 1); in send()
1219 sctx->has_callback = 0; in send()
1222 k_sem_init(&sctx->tx_sem, 0, 1); in send()
1223 sctx->can_dev = can_dev; in send()
1224 sctx->tx_addr = *tx_addr; in send()
1225 sctx->rx_addr = *rx_addr; in send()
1226 sctx->error_nr = ISOTP_N_OK; in send()
1227 sctx->wft = 0; in send()
1228 k_work_init(&sctx->work, send_work_handler); in send()
1229 k_timer_init(&sctx->timer, send_timeout_handler, NULL); in send()
1231 switch (sctx->tx_addr.dl) { in send()
1233 if ((sctx->tx_addr.flags & ISOTP_MSG_FDF) == 0) { in send()
1234 sctx->tx_addr.dl = 8; in send()
1236 sctx->tx_addr.dl = 64; in send()
1248 if ((sctx->tx_addr.flags & ISOTP_MSG_FDF) == 0) { in send()
1254 LOG_ERR("Invalid TX_DL: %u", sctx->tx_addr.dl); in send()
1258 len = get_send_ctx_data_len(sctx); in send()
1260 sctx->tx_addr.ext_id, sctx->rx_addr.ext_id); in send()
1262 if (len > sctx->tx_addr.dl - (((tx_addr->flags & ISOTP_MSG_EXT_ADDR) != 0) ? 2 : 1) - in send()
1263 ((sctx->tx_addr.dl > ISOTP_4BIT_SF_MAX_CAN_DL) ? 1 : 0)) { in send()
1264 ret = add_fc_filter(sctx); in send()
1267 free_send_ctx(&sctx); in send()
1272 sctx->state = ISOTP_TX_SEND_FF; in send()
1273 k_work_submit(&sctx->work); in send()
1276 sctx->filter_id = -1; in send()
1277 ret = send_sf(sctx); in send()
1279 free_send_ctx(&sctx); in send()
1286 k_sem_take(&sctx->fin_sem, K_FOREVER); in send()
1287 ret = sctx->error_nr; in send()
1288 free_send_ctx(&sctx); in send()
1295 int isotp_send(struct isotp_send_ctx *sctx, const struct device *can_dev, in isotp_send() argument
1301 sctx->data = data; in isotp_send()
1302 sctx->len = len; in isotp_send()
1303 sctx->is_ctx_slab = 0; in isotp_send()
1304 sctx->is_net_buf = 0; in isotp_send()
1306 return send(sctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); in isotp_send()
1318 struct isotp_send_ctx *sctx; in isotp_send_ctx_buf() local
1323 ret = alloc_send_ctx(&sctx, timeout); in isotp_send_ctx_buf()
1328 sctx->data = data; in isotp_send_ctx_buf()
1329 sctx->len = len; in isotp_send_ctx_buf()
1330 sctx->is_net_buf = 0; in isotp_send_ctx_buf()
1332 return send(sctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); in isotp_send_ctx_buf()
1342 struct isotp_send_ctx *sctx; in isotp_send_net_ctx_buf() local
1347 ret = alloc_send_ctx(&sctx, timeout); in isotp_send_net_ctx_buf()
1352 sctx->is_net_buf = 1; in isotp_send_net_ctx_buf()
1353 sctx->buf = data; in isotp_send_net_ctx_buf()
1355 return send(sctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); in isotp_send_net_ctx_buf()
1366 struct isotp_send_ctx *sctx; in isotp_send_buf() local
1372 ret = alloc_send_ctx(&sctx, timeout); in isotp_send_buf()
1379 k_mem_slab_free(&ctx_slab, (void *)sctx); in isotp_send_buf()
1385 sctx->is_net_buf = 1; in isotp_send_buf()
1386 sctx->buf = buf; in isotp_send_buf()
1388 return send(sctx, can_dev, tx_addr, rx_addr, complete_cb, cb_arg); in isotp_send_buf()