|
| 1 | +/* |
| 2 | + * Copyright (C) 2014 Freie Universität Berlin |
| 3 | + * |
| 4 | + * This file is subject to the terms and conditions of the GNU Lesser General |
| 5 | + * Public License. See the file LICENSE in the top level directory for more |
| 6 | + * details. |
| 7 | + */ |
| 8 | +#include <errno.h> |
| 9 | +#include <string.h> |
| 10 | + |
| 11 | +#include "netapi.h" |
| 12 | +#include "msg.h" |
| 13 | +#include "netdev/base.h" |
| 14 | +#include "thread.h" |
| 15 | + |
| 16 | +#include "basic_mac.h" |
| 17 | + |
| 18 | +#define ENABLE_DEBUG (0) |
| 19 | +#if ENABLE_DEBUG |
| 20 | +#define DEBUG_ENABLED |
| 21 | +#endif |
| 22 | +#include "debug.h" |
| 23 | + |
| 24 | +#define BASIC_MAC_MSG_QUEUE_SIZE (16) |
| 25 | + |
| 26 | +static struct { |
| 27 | + kernel_pid_t registrar_pid; |
| 28 | + kernel_pid_t recipant_pid; |
| 29 | +} _basic_mac_registry[BASIC_MAC_REGISTRY_SIZE]; |
| 30 | + |
| 31 | +static int _basic_mac_recv_cb(netdev_t *dev, void *src, size_t src_len, |
| 32 | + void *dest, size_t dest_len, void *payload, |
| 33 | + size_t payload_len) |
| 34 | +{ |
| 35 | + (void)dev; |
| 36 | + kernel_pid_t current_pid = thread_getpid(); |
| 37 | + size_t offset; |
| 38 | + netapi_rcv_pkt_t packet; |
| 39 | + netapi_ack_t ack_mem; |
| 40 | + msg_t msg_pkt, msg_ack; |
| 41 | + |
| 42 | + packet.type = NETAPI_CMD_RCV; |
| 43 | + packet.ack = &ack_mem; |
| 44 | + packet.src = src; |
| 45 | + packet.src_len = src_len; |
| 46 | + packet.dest = dest; |
| 47 | + packet.dest_len = dest_len; |
| 48 | + msg_pkt.type = NETAPI_MSG_TYPE; |
| 49 | + msg_pkt.content.ptr = (char *)(&packet); |
| 50 | + |
| 51 | + for (int i = 0; i < BASIC_MAC_REGISTRY_SIZE; i++) { |
| 52 | + if (_basic_mac_registry[i].registrar_pid == current_pid) { |
| 53 | + netapi_ack_t *ack; |
| 54 | + offset = 0; |
| 55 | + |
| 56 | + while (offset < payload_len) { |
| 57 | + packet.data = (void *)(((char *)payload) + offset); |
| 58 | + packet.data_len = payload_len - offset; |
| 59 | + |
| 60 | + msg_send_receive(&msg_pkt, &msg_ack, |
| 61 | + _basic_mac_registry[i].recipant_pid); |
| 62 | + ack = (netapi_ack_t *)(msg_ack.content.ptr); |
| 63 | + |
| 64 | + if (msg_ack.type == NETAPI_MSG_TYPE && |
| 65 | + ack->type == NETAPI_CMD_ACK && |
| 66 | + ack->orig == NETAPI_CMD_RCV) { |
| 67 | + if (ack->result > 0) { |
| 68 | + offset += (ack->result); |
| 69 | + } |
| 70 | + else { |
| 71 | + DEBUG("Error code received for registrar \"%s\" with " |
| 72 | + "recipant \"%s\": %d", |
| 73 | + thread_getname(_basic_mac_registry[i].registrar_pid), |
| 74 | + thread_getname(_basic_mac_registry[i].recipant_pid), |
| 75 | + -ack->result); |
| 76 | + |
| 77 | + return ack->result; |
| 78 | + } |
| 79 | + } |
| 80 | + else { |
| 81 | + DEBUG("Unexpected msg instead of ACK. Abort for registrar " |
| 82 | + "\"%s\" with recipant \"%s\": msg.type = %d, " |
| 83 | + |
| 84 | + "ack->type = %d, ack->orig = %d", |
| 85 | + thread_getname(_basic_mac_registry[i].registrar_pid), |
| 86 | + thread_getname(_basic_mac_registry[i].recipant_pid), |
| 87 | + msg_ack->type, ack->type, ack->orig); |
| 88 | + |
| 89 | + return -ENOMSG; |
| 90 | + } |
| 91 | + |
| 92 | + } |
| 93 | + } |
| 94 | + } |
| 95 | + |
| 96 | + return payload_len; |
| 97 | +} |
| 98 | + |
| 99 | +static inline int _basic_mac_send(netdev_t *dev, netapi_snd_pkt_t *pkt) |
| 100 | +{ |
| 101 | + return dev->driver->send_data(dev, pkt->dest, pkt->dest_len, pkt->ulh, |
| 102 | + pkt->data, pkt->data_len); |
| 103 | +} |
| 104 | + |
| 105 | +static int _basic_mac_get_option(netdev_t *dev, netapi_conf_t *conf) |
| 106 | +{ |
| 107 | + int res; |
| 108 | + |
| 109 | + switch ((basic_mac_conf_type_t)conf->param) { |
| 110 | + case BASIC_MAC_PROTO: |
| 111 | + case BASIC_MAC_CHANNEL: |
| 112 | + case BASIC_MAC_ADDRESS: |
| 113 | + case BASIC_MAC_NID: |
| 114 | + case BASIC_MAC_ADDRESS2: |
| 115 | + if ((res = dev->driver->get_option(dev, (netdev_opt_t)conf->param, conf->data, |
| 116 | + &(conf->data_len))) == 0) { |
| 117 | + return (int)conf->data_len; |
| 118 | + } |
| 119 | + else { |
| 120 | + return res; |
| 121 | + } |
| 122 | + |
| 123 | + default: |
| 124 | + break; |
| 125 | + } |
| 126 | + |
| 127 | + return -ENOTSUP; |
| 128 | +} |
| 129 | + |
| 130 | +static int _basic_mac_set_option(netdev_t *dev, netapi_conf_t *conf) |
| 131 | +{ |
| 132 | + switch ((basic_mac_conf_type_t)(conf->param)) { |
| 133 | + case BASIC_MAC_PROTO: |
| 134 | + case BASIC_MAC_CHANNEL: |
| 135 | + case BASIC_MAC_ADDRESS: |
| 136 | + case BASIC_MAC_NID: |
| 137 | + case BASIC_MAC_ADDRESS2: |
| 138 | + return dev->driver->set_option(dev, (netdev_opt_t)conf->param, |
| 139 | + conf->data, conf->data_len); |
| 140 | + |
| 141 | + default: |
| 142 | + break; |
| 143 | + } |
| 144 | + |
| 145 | + return -ENOTSUP; |
| 146 | +} |
| 147 | + |
| 148 | +static void *_basic_mac_runner(void *args) |
| 149 | +{ |
| 150 | + netdev_t *dev = (netdev_t *)args; |
| 151 | + msg_t msg_cmd, msg_ack, msg_queue[BASIC_MAC_MSG_QUEUE_SIZE]; |
| 152 | + |
| 153 | + netapi_cmd_t *cmd; |
| 154 | + netapi_ack_t *ack; |
| 155 | + |
| 156 | + msg_ack.type = NETAPI_MSG_TYPE; |
| 157 | + |
| 158 | + msg_init_queue(msg_queue, BASIC_MAC_MSG_QUEUE_SIZE); |
| 159 | + |
| 160 | + while (1) { |
| 161 | + msg_receive(&msg_cmd); |
| 162 | + |
| 163 | + if (msg_cmd.type == NETDEV_MSG_EVENT_TYPE) { |
| 164 | + dev->driver->event(dev, msg_cmd.content.value); |
| 165 | + } |
| 166 | + else if (msg_cmd.type == NETAPI_MSG_TYPE) { |
| 167 | + cmd = (netapi_cmd_t *)(msg_cmd.content.ptr); |
| 168 | + ack = cmd->ack; |
| 169 | + msg_ack.content.ptr = (char *)ack; |
| 170 | + |
| 171 | + switch (cmd->type) { |
| 172 | + case NETAPI_CMD_SND: |
| 173 | + ack->result = _basic_mac_send(dev, (netapi_snd_pkt_t *)cmd); |
| 174 | + |
| 175 | + break; |
| 176 | + |
| 177 | + case NETAPI_CMD_GET: |
| 178 | + ack->result = _basic_mac_get_option(dev, |
| 179 | + (netapi_conf_t *)cmd); |
| 180 | + break; |
| 181 | + |
| 182 | + case NETAPI_CMD_SET: |
| 183 | + ack->result = _basic_mac_set_option(dev, |
| 184 | + (netapi_conf_t *)cmd); |
| 185 | + break; |
| 186 | + |
| 187 | + case NETAPI_CMD_REG: |
| 188 | + do { |
| 189 | + netapi_reg_t *reg = (netapi_reg_t *)cmd; |
| 190 | + ack->result = -ENOBUFS; |
| 191 | + |
| 192 | + for (int i = 0; i < BASIC_MAC_REGISTRY_SIZE; i++) { |
| 193 | + if (_basic_mac_registry[i].registrar_pid == KERNEL_PID_UNDEF) { |
| 194 | + _basic_mac_registry[i].registrar_pid = thread_getpid(); |
| 195 | + _basic_mac_registry[i].recipant_pid = reg->reg_pid; |
| 196 | + ack->result = NETAPI_STATUS_OK; |
| 197 | + break; |
| 198 | + } |
| 199 | + |
| 200 | + } |
| 201 | + } while (0); |
| 202 | + |
| 203 | + break; |
| 204 | + |
| 205 | + case NETAPI_CMD_UNREG: |
| 206 | + do { |
| 207 | + netapi_reg_t *reg = (netapi_reg_t *)cmd; |
| 208 | + ack->result = NETAPI_STATUS_OK; |
| 209 | + |
| 210 | + for (int i = 0; i < BASIC_MAC_REGISTRY_SIZE; i++) { |
| 211 | + if (_basic_mac_registry[i].registrar_pid == thread_getpid() && |
| 212 | + _basic_mac_registry[i].recipant_pid == reg->reg_pid) { |
| 213 | + _basic_mac_registry[i].recipant_pid = KERNEL_PID_UNDEF; |
| 214 | + break; |
| 215 | + } |
| 216 | + |
| 217 | + } |
| 218 | + } while (0); |
| 219 | + |
| 220 | + break; |
| 221 | + |
| 222 | + default: |
| 223 | + ack->result = -ENOTSUP; |
| 224 | + break; |
| 225 | + } |
| 226 | + |
| 227 | + ack->type = NETAPI_CMD_ACK; |
| 228 | + ack->orig = cmd->type; |
| 229 | + msg_reply(&msg_cmd, &msg_ack); |
| 230 | + } |
| 231 | + } |
| 232 | + |
| 233 | + /* never reached */ |
| 234 | + return NULL; |
| 235 | +} |
| 236 | + |
| 237 | +void basic_mac_init_module(void) |
| 238 | +{ |
| 239 | + for (int i = 0; i < BASIC_MAC_REGISTRY_SIZE; i++) { |
| 240 | + _basic_mac_registry[i].registrar_pid = KERNEL_PID_UNDEF; |
| 241 | + _basic_mac_registry[i].recipant_pid = KERNEL_PID_UNDEF; |
| 242 | + } |
| 243 | +} |
| 244 | + |
| 245 | +kernel_pid_t basic_mac_init(char *stack, int stacksize, char priority, int flags, |
| 246 | + const char *name, netdev_t *dev) |
| 247 | +{ |
| 248 | + dev->driver->add_receive_data_callback(dev, _basic_mac_recv_cb); |
| 249 | + |
| 250 | + return thread_create(stack, stacksize, priority, flags, _basic_mac_runner, |
| 251 | + (void *)dev, name); |
| 252 | +} |
0 commit comments