Skip to content

Instantly share code, notes, and snippets.

@hlord2000
Created May 28, 2025 17:15
Show Gist options
  • Save hlord2000/d473e5b549a9d79989d6dc74a6e10eab to your computer and use it in GitHub Desktop.
Save hlord2000/d473e5b549a9d79989d6dc74a6e10eab to your computer and use it in GitHub Desktop.
--- /opt/ncs/ncs-v3.0/nrf/applications/serial_lte_modem/src/slm_at_socket.c 2025-04-15 11:53:22.452023051 -0400
+++ src/slm_at_socket.c 2025-05-28 13:00:00.173393697 -0400
@@ -1656,6 +1656,224 @@
return err;
}
+/* Begin app specific commands */
+
+SLM_AT_CMD_CUSTOM(qiopen, "AT+QIOPEN", handle_qiopen_socket);
+static int handle_qiopen_socket(enum at_parser_cmd_type cmd_type, struct at_parser *parser,
+ uint32_t param_count)
+{
+ int err = -EINVAL;
+ uint16_t context_id;
+
+ char service_type[16] = {0};
+ int service_type_size = 16;
+
+ char url[SLM_MAX_URL] = {0};
+ int url_size = SLM_MAX_URL;
+ uint16_t port;
+
+ switch (cmd_type) {
+ case AT_PARSER_CMD_TYPE_SET:
+ err = at_parser_num_get(parser, 1, &context_id);
+ if (err) {
+ return err;
+ }
+
+ err = util_string_get(parser, 3, service_type, &service_type_size);
+ if (err) {
+ return err;
+ }
+
+ if (find_avail_socket() < 0) {
+ LOG_ERR("Max socket count reached");
+ return -EINVAL;
+ }
+ INIT_SOCKET(sock);
+
+ err = at_parser_num_get(parser, 2, &sock.cid);
+ if (err) {
+ return err;
+ }
+
+ if (sock.cid > 10) {
+ return -EINVAL;
+ }
+
+ sock.family = AF_INET;
+
+ if (slm_util_casecmp(service_type, "TCP")) {
+ sock.type = SOCK_STREAM;
+ sock.role = 0; // Client
+ } else if (slm_util_casecmp(service_type, "UDP")) {
+ sock.type = SOCK_DGRAM;
+ sock.role = 0; // Client
+ } else if (slm_util_casecmp(service_type, "TCP LISTENER")) {
+ sock.type = SOCK_STREAM;
+ sock.role = 1; // Server
+ } else if (slm_util_casecmp(service_type, "UDP SERVICE")) {
+ sock.type = SOCK_DGRAM;
+ sock.role = 1; // Server
+ } else {
+ LOG_ERR("Invalid service type");
+ return -EINVAL;
+ }
+
+ err = do_socket_open();
+ if (err) {
+ return err;
+ }
+
+ err = util_string_get(parser, 4, url, &url_size);
+ if (err) {
+ return err;
+ }
+
+ err = at_parser_num_get(parser, 5, &port);
+ if (err) {
+ return err;
+ }
+
+ if (!slm_util_casecmp(url, "127.0.0.1")) {
+ err = do_connect(url, port);
+ if (err) {
+ return err;
+ }
+ } else if (sock.type == SOCK_STREAM && sock.role == 1) {
+ err = do_listen();
+ if (err) {
+ return err;
+ }
+ } else if (sock.type == SOCK_DGRAM && sock.role == 1) {
+ err = slm_bind_to_local_addr(sock.fd, sock.family, port);
+ if (err) {
+ return err;
+ }
+ }
+
+ break;
+
+ case AT_PARSER_CMD_TYPE_READ:
+ if (sock.fd != INVALID_SOCKET) {
+ rsp_send("\r\n+QIOPEN: %d,%d,%d,%d,%d\r\n", sock.fd,
+ sock.family, sock.role, sock.type, sock.cid);
+ }
+ err = 0;
+ break;
+
+ case AT_PARSER_CMD_TYPE_TEST:
+ rsp_send("\r\n+QIOPEN: (%d,%d,%d),(%d,%d,%d),(%d,%d),<cid>",
+ AT_SOCKET_CLOSE, AT_SOCKET_OPEN, AT_SOCKET_OPEN6,
+ SOCK_STREAM, SOCK_DGRAM, SOCK_RAW,
+ AT_SOCKET_ROLE_CLIENT, AT_SOCKET_ROLE_SERVER);
+ err = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return err;
+}
+
+SLM_AT_CMD_CUSTOM(qiclose, "AT+QICLOSE", handle_qiclose_socket);
+static int handle_qiclose_socket(enum at_parser_cmd_type cmd_type, struct at_parser *parser,
+ uint32_t param_count)
+{
+ int err = -EINVAL;
+ uint16_t cid;
+
+ err = at_parser_num_get(parser, 1, &cid);
+ if (err) {
+ return err;
+ }
+
+ if (cid > 10) {
+ return -EINVAL;
+ }
+
+ for (int i = 0; i < SLM_MAX_SOCKET_COUNT; i++) {
+ if (socks[i].cid == cid) {
+ sock = socks[i];
+ }
+ }
+
+ switch (cmd_type) {
+ case AT_PARSER_CMD_TYPE_SET:
+ err = do_socket_close();
+ if (err) {
+ return err;
+ }
+ break;
+
+ case AT_PARSER_CMD_TYPE_READ:
+ if (sock.fd != INVALID_SOCKET) {
+ rsp_send("\r\n+QICLOSE: %d,%d,%d,%d,%d\r\n", sock.fd,
+ sock.family, sock.role, sock.type, sock.cid);
+ }
+ err = 0;
+ break;
+
+ case AT_PARSER_CMD_TYPE_TEST:
+ rsp_send("\r\n+QICLOSE: (%d,%d,%d),(%d,%d,%d),(%d,%d),<cid>",
+ AT_SOCKET_CLOSE, AT_SOCKET_OPEN, AT_SOCKET_OPEN6,
+ SOCK_STREAM, SOCK_DGRAM, SOCK_RAW,
+ AT_SOCKET_ROLE_CLIENT, AT_SOCKET_ROLE_SERVER);
+ err = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ return err;
+}
+
+SLM_AT_CMD_CUSTOM(qisend, "AT+QISEND", handle_at_qisend);
+static int handle_at_qisend(enum at_parser_cmd_type cmd_type, struct at_parser *parser,
+ uint32_t param_count)
+{
+
+ int err = -EINVAL;
+ int size;
+ uint16_t cid;
+
+ err = at_parser_num_get(parser, 1, &cid);
+ if (err) {
+ return err;
+ }
+
+ /*
+ for (int i = 0; i < SLM_MAX_SOCKET_COUNT; i++) {
+ if (socks[i].cid == cid) {
+ sock = socks[i];
+ }
+ }
+ */
+
+ switch (cmd_type) {
+ case AT_PARSER_CMD_TYPE_SET:
+ size = sizeof(udp_url);
+ err = util_string_get(parser, 3, udp_url, &size);
+ if (err) {
+ return err;
+ }
+ err = at_parser_num_get(parser, 4, &udp_port);
+ if (err) {
+ return err;
+ }
+ err = enter_datamode(socket_datamode_callback);
+ if (err) {
+ return err;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return err;
+}
+
/**@brief API to initialize Socket AT commands handler
*/
int slm_at_socket_init(void)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment