Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | /* * Copyright (c) 2019 Intel Corporation. * * SPDX-License-Identifier: Apache-2.0 * */ /* CANBUS related functions that are generic in all the drivers. */ #include <net/net_pkt.h> #include <net/socket_can.h> #ifndef ZEPHYR_DRIVERS_CAN_SOCKET_CAN_GENERIC_H_ #define ZEPHYR_DRIVERS_CAN_SOCKET_CAN_GENERIC_H_ #define SOCKET_CAN_NAME_1 "SOCKET_CAN_1" #define SEND_TIMEOUT K_MSEC(100) #define RX_THREAD_STACK_SIZE 512 #define RX_THREAD_PRIORITY 2 #define BUF_ALLOC_TIMEOUT K_MSEC(50) /* TODO: make msgq size configurable */ CAN_DEFINE_MSGQ(socket_can_msgq, 5); K_THREAD_STACK_DEFINE(rx_thread_stack, RX_THREAD_STACK_SIZE); struct socket_can_context { struct device *can_dev; struct net_if *iface; struct k_msgq *msgq; /* TODO: remove the thread and push data to net directly from rx isr */ k_tid_t rx_tid; struct k_thread rx_thread_data; }; static inline void socket_can_iface_init(struct net_if *iface) { struct device *dev = net_if_get_device(iface); struct socket_can_context *socket_context = dev->driver_data; socket_context->iface = iface; LOG_DBG("Init CAN interface %p dev %p", iface, dev); } static inline void tx_irq_callback(u32_t error_flags, void *arg) { char *caller_str = (char *)arg; if (error_flags) { LOG_DBG("TX error from %s! error-code: %d", caller_str, error_flags); } } /* This is called by net_if.c when packet is about to be sent */ static inline int socket_can_send(struct device *dev, struct net_pkt *pkt) { struct socket_can_context *socket_context = dev->driver_data; int ret; if (net_pkt_family(pkt) != AF_CAN) { return -EPFNOSUPPORT; } ret = can_send(socket_context->can_dev, (struct zcan_frame *)pkt->frags->data, SEND_TIMEOUT, tx_irq_callback, "socket_can_send"); if (ret) { LOG_DBG("Cannot send socket CAN msg (%d)", ret); } /* If something went wrong, then we need to return negative value to * net_if.c:net_if_tx() so that the net_pkt will get released. */ return -ret; } static inline int socket_can_setsockopt(struct device *dev, void *obj, int level, int optname, const void *optval, socklen_t optlen) { struct socket_can_context *socket_context = dev->driver_data; struct net_context *ctx = obj; int ret; if (level != SOL_CAN_RAW && optname != CAN_RAW_FILTER) { errno = EINVAL; return -1; } __ASSERT_NO_MSG(optlen == sizeof(struct zcan_filter)); ret = can_attach_msgq(socket_context->can_dev, socket_context->msgq, optval); if (ret == CAN_NO_FREE_FILTER) { errno = ENOSPC; return -1; } net_context_set_filter_id(ctx, ret); return 0; } static inline void socket_can_close(struct device *dev, int filter_id) { struct socket_can_context *socket_context = dev->driver_data; can_detach(socket_context->can_dev, filter_id); } static struct canbus_api socket_can_api = { .iface_api.init = socket_can_iface_init, .send = socket_can_send, .close = socket_can_close, .setsockopt = socket_can_setsockopt, }; static struct socket_can_context socket_can_context_1; static inline void rx_thread(void *ctx, void *unused1, void *unused2) { struct socket_can_context *socket_context = ctx; struct net_pkt *pkt; struct zcan_frame msg; int ret; ARG_UNUSED(unused1); ARG_UNUSED(unused2); while (1) { k_msgq_get((struct k_msgq *)socket_context->msgq, &msg, K_FOREVER); pkt = net_pkt_rx_alloc_with_buffer(socket_context->iface, sizeof(msg), AF_CAN, 0, BUF_ALLOC_TIMEOUT); if (!pkt) { LOG_ERR("Failed to obtain RX buffer"); continue; } if (net_pkt_write(pkt, (void *)&msg, sizeof(msg))) { LOG_ERR("Failed to append RX data"); net_pkt_unref(pkt); continue; } ret = net_recv_data(socket_context->iface, pkt); if (ret < 0) { net_pkt_unref(pkt); } } } #endif /* ZEPHYR_DRIVERS_CAN_SOCKET_CAN_GENERIC_H_ */ |