1 /* 2 * uqmi -- tiny QMI support implementation 3 * 4 * Copyright (C) 2014-2015 Felix Fietkau <nbd@openwrt.org> 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the 18 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301 USA. 20 */ 21 22 #include <stdlib.h> 23 24 #include "qmi-message.h" 25 26 static const struct { 27 const char *name; 28 QmiWdaLinkLayerProtocol val; 29 } link_modes[] = { 30 { "802.3", QMI_WDA_LINK_LAYER_PROTOCOL_802_3 }, 31 { "raw-ip", QMI_WDA_LINK_LAYER_PROTOCOL_RAW_IP }, 32 }; 33 34 static const struct { 35 const char *name; 36 QmiWdaDataAggregationProtocol aggreg; 37 } aggregation_protocols[] = { 38 { "tlp", QMI_WDA_DATA_AGGREGATION_PROTOCOL_TLP }, 39 { "qc-cm", QMI_WDA_DATA_AGGREGATION_PROTOCOL_QC_NCM }, 40 { "mbim", QMI_WDA_DATA_AGGREGATION_PROTOCOL_MBIM }, 41 { "rndis", QMI_WDA_DATA_AGGREGATION_PROTOCOL_RNDIS }, 42 { "qmap", QMI_WDA_DATA_AGGREGATION_PROTOCOL_QMAP }, 43 { "qmapv5", QMI_WDA_DATA_AGGREGATION_PROTOCOL_QMAPV5 }, 44 }; 45 46 static struct { 47 uint32_t max_size_dl; 48 uint32_t max_datagrams_dl; 49 QmiWdaDataAggregationProtocol aggregation_protocol_dl; 50 uint32_t max_size_ul; 51 uint32_t max_datagrams_ul; 52 QmiWdaDataAggregationProtocol aggregation_protocol_ul; 53 int8_t flow_control; 54 } wda_aggregation_info = { 55 .max_size_dl = 0, 56 .max_datagrams_dl = 0, 57 .aggregation_protocol_dl = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED, 58 .max_size_ul = 0, 59 .max_datagrams_ul = 0, 60 .aggregation_protocol_ul = QMI_WDA_DATA_AGGREGATION_PROTOCOL_DISABLED, 61 .flow_control = -1, 62 }; 63 64 #define cmd_wda_set_data_format_cb no_cb 65 66 static void 67 cmd_wda_set_data_format_send(struct qmi_msg *msg, QmiWdaLinkLayerProtocol link_layer_proto) 68 { 69 struct qmi_wda_set_data_format_request data_req = { 70 QMI_INIT(link_layer_protocol, link_layer_proto), 71 QMI_INIT(uplink_data_aggregation_protocol, wda_aggregation_info.aggregation_protocol_ul), 72 QMI_INIT(uplink_data_aggregation_max_datagrams, wda_aggregation_info.max_datagrams_ul), 73 QMI_INIT(uplink_data_aggregation_max_size, wda_aggregation_info.max_size_ul), 74 QMI_INIT(downlink_data_aggregation_protocol, wda_aggregation_info.aggregation_protocol_dl), 75 QMI_INIT(downlink_data_aggregation_max_datagrams, wda_aggregation_info.max_datagrams_dl), 76 QMI_INIT(downlink_data_aggregation_max_size, wda_aggregation_info.max_size_dl), 77 QMI_INIT(downlink_minimum_padding, 0), 78 }; 79 80 if (wda_aggregation_info.flow_control >= 0) 81 qmi_set(&data_req, flow_control, wda_aggregation_info.flow_control); 82 83 qmi_set_wda_set_data_format_request(msg, &data_req); 84 } 85 86 static enum qmi_cmd_result 87 cmd_wda_set_data_format_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 88 { 89 QmiWdaLinkLayerProtocol link_layer_proto; 90 int i; 91 92 for (i = 0; i < ARRAY_SIZE(link_modes); i++) { 93 if (strcasecmp(link_modes[i].name, arg) != 0) 94 continue; 95 96 link_layer_proto = link_modes[i].val; 97 } 98 99 if (link_layer_proto == QMI_WDA_LINK_LAYER_PROTOCOL_UNKNOWN) { 100 uqmi_add_error("Invalid auth mode (valid: 802.3, raw-ip)"); 101 return QMI_CMD_EXIT; 102 } 103 104 cmd_wda_set_data_format_send(msg, link_layer_proto); 105 106 return QMI_CMD_REQUEST; 107 } 108 109 #define cmd_wda_downlink_data_aggregation_protocol_cb no_cb 110 111 static enum qmi_cmd_result cmd_wda_downlink_data_aggregation_protocol_prepare( 112 struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, 113 char *arg) 114 { 115 for (uint32_t i = 0; i < ARRAY_SIZE(aggregation_protocols); i++) { 116 if (strcasecmp(aggregation_protocols[i].name, arg)) 117 continue; 118 119 wda_aggregation_info.aggregation_protocol_dl = aggregation_protocols[i].aggreg; 120 return QMI_CMD_DONE; 121 } 122 123 uqmi_add_error("Invalid protocol (valid: tlp, qc-cm, mbim, rndis, qmap, qmapv5"); 124 return QMI_CMD_EXIT; 125 } 126 127 #define cmd_wda_uplink_data_aggregation_protocol_cb no_cb 128 129 static enum qmi_cmd_result cmd_wda_uplink_data_aggregation_protocol_prepare( 130 struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, 131 char *arg) 132 { 133 for (uint32_t i = 0; i < ARRAY_SIZE(aggregation_protocols); i++) { 134 if (strcasecmp(aggregation_protocols[i].name, arg)) 135 continue; 136 137 wda_aggregation_info.aggregation_protocol_ul = aggregation_protocols[i].aggreg; 138 return QMI_CMD_DONE; 139 } 140 141 uqmi_add_error("Invalid protocol (valid: tlp, qc-cm, mbim, rndis, qmap, qmapv5"); 142 return QMI_CMD_EXIT; 143 } 144 145 #define cmd_wda_downlink_data_aggregation_max_datagrams_cb no_cb 146 147 static enum qmi_cmd_result cmd_wda_downlink_data_aggregation_max_datagrams_prepare( 148 struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, 149 char *arg) 150 { 151 uint32_t max_datagrams = strtoul(arg, NULL, 10); 152 153 wda_aggregation_info.max_datagrams_dl = max_datagrams; 154 return QMI_CMD_DONE; 155 } 156 157 #define cmd_wda_downlink_data_aggregation_max_size_cb no_cb 158 159 static enum qmi_cmd_result cmd_wda_downlink_data_aggregation_max_size_prepare( 160 struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, 161 char *arg) 162 { 163 uint32_t max_size = strtoul(arg, NULL, 10); 164 165 wda_aggregation_info.max_size_dl = max_size; 166 return QMI_CMD_DONE; 167 } 168 169 #define cmd_wda_uplink_data_aggregation_max_datagrams_cb no_cb 170 171 static enum qmi_cmd_result cmd_wda_uplink_data_aggregation_max_datagrams_prepare( 172 struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, 173 char *arg) 174 { 175 uint32_t max_datagrams = strtoul(arg, NULL, 10); 176 177 wda_aggregation_info.max_datagrams_ul = max_datagrams; 178 return QMI_CMD_DONE; 179 } 180 181 #define cmd_wda_uplink_data_aggregation_max_size_cb no_cb 182 183 static enum qmi_cmd_result cmd_wda_uplink_data_aggregation_max_size_prepare( 184 struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, 185 char *arg) 186 { 187 uint32_t max_size = strtoul(arg, NULL, 10); 188 189 wda_aggregation_info.max_size_ul = max_size; 190 return QMI_CMD_DONE; 191 } 192 193 #define cmd_wda_flow_control_cb no_cb 194 195 static enum qmi_cmd_result cmd_wda_flow_control_prepare( 196 struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, 197 char *arg) 198 { 199 uint32_t val = strtoul(arg, NULL, 10); 200 201 if (val != 0 && val != 1) { 202 uqmi_add_error("Invalid value (valid: 0, 1)"); 203 return QMI_CMD_EXIT; 204 } 205 206 wda_aggregation_info.flow_control = !!val; 207 208 return QMI_CMD_DONE; 209 } 210 211 static const char * 212 wda_link_layer_protocol_to_string(QmiWdaLinkLayerProtocol proto) 213 { 214 for (int i = 0; i < ARRAY_SIZE(link_modes); i++) { 215 if (link_modes[i].val == proto) 216 return link_modes[i].name; 217 } 218 return "unknown"; 219 } 220 221 static const char * 222 wda_data_aggregation_protocol_to_string(QmiWdaDataAggregationProtocol proto) 223 { 224 for (int i = 0; i < ARRAY_SIZE(aggregation_protocols); i++) { 225 if (aggregation_protocols[i].aggreg == proto) 226 return aggregation_protocols[i].name; 227 } 228 return "unknown"; 229 } 230 231 static void 232 cmd_wda_get_data_format_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg) 233 { 234 struct qmi_wda_get_data_format_response res; 235 void *root; 236 237 qmi_parse_wda_get_data_format_response(msg, &res); 238 root = blobmsg_open_table(&status, NULL); 239 blobmsg_add_u8(&status, "qos-format", res.data.qos_format); 240 blobmsg_add_string(&status, "link-layer-protocol", 241 wda_link_layer_protocol_to_string(res.data.link_layer_protocol)); 242 blobmsg_add_string(&status, "data-aggregation-protocol", 243 wda_data_aggregation_protocol_to_string(res.data.uplink_data_aggregation_protocol)); 244 blobmsg_add_u32(&status, "uplink-data-aggregation-max-datagrams", 245 res.data.uplink_data_aggregation_max_datagrams); 246 blobmsg_add_u32(&status, "uplink-data-aggregation-max-size", 247 res.data.uplink_data_aggregation_max_size); 248 blobmsg_add_string(&status, "downlink-data-aggregation-protocol", 249 wda_data_aggregation_protocol_to_string(res.data.downlink_data_aggregation_protocol)); 250 blobmsg_add_u32(&status, "downlink-data-aggregation-max-datagrams", 251 res.data.downlink_data_aggregation_max_datagrams); 252 blobmsg_add_u32(&status, "downlink-data-aggregation-max-size", 253 res.data.downlink_data_aggregation_max_size); 254 blobmsg_add_u32(&status, "download-minimum-padding", 255 res.data.download_minimum_padding); 256 blobmsg_add_u8(&status, "flow-control", res.data.flow_control); 257 blobmsg_close_table(&status, root); 258 } 259 260 static enum qmi_cmd_result 261 cmd_wda_get_data_format_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg) 262 { 263 struct qmi_wda_get_data_format_request data_req = {}; 264 qmi_set_wda_get_data_format_request(msg, &data_req); 265 return QMI_CMD_REQUEST; 266 } 267
This page was automatically generated by LXR 0.3.1. • OpenWrt