/** * SIM800 IP configuration commands fail if the IP application is running, * even though the configuration settings are already right. The following * monkey dance is therefore needed. */ static int sim800_config(struct cellular *modem, const char *option, const char *value, int attempts) { at_set_timeout(modem->at, 10); for (int i=0; i<attempts; i++) { /* Blindly try to set the configuration option. */ at_command(modem->at, "AT+%s=%s", option, value); /* Query the setting status. */ const char *response = at_command(modem->at, "AT+%s?", option); /* Bail out on timeouts. */ if (response == NULL) return -1; /* Check if the setting has the correct value. */ char expected[16]; if (snprintf(expected, sizeof(expected), "+%s: %s", option, value) >= (int) sizeof(expected)) { return -1; } if (!strcmp(response, expected)) return 0; vTaskDelay(pdMS_TO_TICKS(1000)); } return -1; }
static int sim800_pdp_open(struct cellular *modem, const char *apn) { at_set_timeout(modem->at, SET_TIMEOUT); /* Configure and open context for FTP/HTTP applications. */ at_command_simple(modem->at, "AT+SAPBR=3,1,APN,\"%s\"", apn); at_command(modem->at, "AT+SAPBR=1,1"); /* Skip the configuration if context is already open. */ if (sim800_ipstatus(modem) == 0) return 0; /* Commands below don't check the response. This is intentional; instead * of trying to stay in sync with the GPRS state machine we blindly issue * the command sequence needed to transition through all the states and * reach IP STATUS. See SIM800 Series_TCPIP_Application Note_V1.01.pdf for * the GPRS states documentation. */ /* Configure context for TCP/IP applications. */ at_command(modem->at, "AT+CSTT=\"%s\"", apn); /* Establish context. */ at_command(modem->at, "AT+CIICR"); /* Read local IP address. Switches modem to IP STATUS state. */ at_set_command_scanner(modem->at, scanner_cifsr); at_command(modem->at, "AT+CIFSR"); return sim800_ipstatus(modem); }
static int telit2_socket_waitack(struct cellular *modem, int connid) { const char *response; at_set_timeout(modem->at, 5); for (int i=0; i<TELIT2_WAITACK_TIMEOUT; i++) { /* Read number of bytes waiting. */ int ack_waiting; response = at_command(modem->at, "AT#SI=%d", connid); at_simple_scanf(response, "#SI: %*d,%*d,%*d,%*d,%d", &ack_waiting); /* ack_waiting is meaningless if socket is not connected. Check this. */ int socket_status; response = at_command(modem->at, "AT#SS=%d", connid); at_simple_scanf(response, "#SS: %*d,%d", &socket_status); if (socket_status == 0) { errno = ECONNRESET; return -1; } /* Return if all bytes were acknowledged. */ if (ack_waiting == 0) return 0; sleep(1); } errno = ETIMEDOUT; return -1; }
static int sim800_attach(struct cellular *modem) { at_set_callbacks(modem->at, &sim800_callbacks, (void *) modem); at_set_timeout(modem->at, 2); /* Perform autobauding. */ for (int i=0; i<SIM800_AUTOBAUD_ATTEMPTS; i++) { const char *response = at_command(modem->at, "AT"); if (response != NULL) /* Modem replied. Good. */ break; } /* Disable local echo. */ at_command(modem->at, "ATE0"); /* Disable local echo again; make sure it was disabled successfully. */ at_command_simple(modem->at, "ATE0"); /* Initialize modem. */ static const char *const init_strings[] = { // "AT+IPR=0", /* Enable autobauding if not already enabled. */ "AT+IFC=0,0", /* Disable hardware flow control. */ "AT+CMEE=2", /* Enable extended error reporting. */ "AT+CLTS=0", /* Don't sync RTC with network time, it's broken. */ "AT+CIURC=0", /* Disable "Call Ready" URC. */ "AT&W0", /* Save configuration. */ "AT+BTSPPCFG=\"TT\",1", "AT+BTPAIRCFG=0", "AT+BTSPPGET=1", "AT+BTPOWER=1", NULL }; for (const char *const *command=init_strings; *command; command++) at_command_simple(modem->at, "%s", *command); /* Configure IP application. */ // /* Switch to multiple connections mode; it's less buggy. */ // if (sim800_config(modem, "CIPMUX", "1", SIM800_CIPCFG_RETRIES) != 0) // return -1; // /* Receive data manually. */ // if (sim800_config(modem, "CIPRXGET", "1", SIM800_CIPCFG_RETRIES) != 0) // return -1; // /* Enable quick send mode. */ // if (sim800_config(modem, "CIPQSEND", "1", SIM800_CIPCFG_RETRIES) != 0) // return -1; return 0; }
static void grub_keyboard_controller_write (grub_uint8_t c) { at_command (KEYBOARD_COMMAND_WRITE); keyboard_controller_wait_until_ready (); grub_outb (c, KEYBOARD_REG_DATA); }
// handle an incoming at command from the remote radio static void handle_at_command(__pdata uint8_t len) { if (len < 2 || len > AT_CMD_MAXLEN || pbuf[0] != (uint8_t)'R' || pbuf[1] != (uint8_t)'T') { // assume its an AT command reply register uint8_t i; for (i=0; i<len; i++) { putchar(pbuf[i]); } return; } // setup the command in the at_cmd buffer memcpy(at_cmd, pbuf, len); at_cmd[len] = 0; at_cmd[0] = 'A'; // replace 'R' at_cmd_len = len; at_cmd_ready = true; // run the AT command, capturing any output to the packet // buffer // this reply buffer will be sent at the next opportunity printf_start_capture(pbuf, sizeof(pbuf)); at_command(); len = printf_end_capture(); if (len > 0) { packet_inject(pbuf, len); } }
static grub_uint8_t grub_keyboard_controller_read (void) { at_command (KEYBOARD_COMMAND_READ); keyboard_controller_wait_until_ready (); return grub_inb (KEYBOARD_REG_DATA); }
static int telit2_attach(struct cellular *modem) { at_set_callbacks(modem->at, &telit2_callbacks, (void *) modem); at_set_timeout(modem->at, 1); at_command(modem->at, "AT"); /* Aid autobauding. Always a good idea. */ at_command(modem->at, "ATE0"); /* Disable local echo. */ /* Initialize modem. */ static const char *const init_strings[] = { "AT&K0", /* Disable hardware flow control. */ "AT#SELINT=2", /* Set Telit module compatibility level. */ "AT+CMEE=2", /* Enable extended error reporting. */ NULL }; for (const char *const *command=init_strings; *command; command++) at_command_simple(modem->at, "%s", *command); return 0; }
int main(int argc, char *argv[]) { int fd; bdaddr_t bdaddr; uint8_t channel; switch (argc) { case 2: str2ba(argv[1], &bdaddr); channel = 1; break; case 3: str2ba(argv[1], &bdaddr); channel = atoi(argv[2]); break; default: usage(); exit(-1); } if (bacmp(BDADDR_ANY, &bdaddr)) { printf("Connecting to %s on channel %d\n", argv[1], channel); fd = open_socket(&bdaddr, channel); } else { printf("Opening device %s\n", argv[1]); fd = open_device(argv[1]); } if (fd < 0) exit(-2); at_command(fd, "ATZ\r\n", 10000); at_command(fd, "AT+CPBS=\"ME\"\r\n", 10000); at_command(fd, "AT+CPBR=1,100\r\n", 100000); close(fd); return 0; }
static int telit2_op_iccid(struct cellular *modem, char *buf, size_t len) { char fmt[24]; if (snprintf(fmt, sizeof(fmt), "#CCID: %%[0-9]%ds", (int) len) >= (int) sizeof(fmt)) { errno = ENOSPC; return -1; } at_set_timeout(modem->at, 5); const char *response = at_command(modem->at, "AT#CCID"); at_simple_scanf(response, fmt, buf); buf[len-1] = '\0'; return 0; }
static void manager (struct uart * uart) { if (_anyset (uart->flags, UART_WAKE)) { at_wake (uart); } if (_anyset (uart->flags, UART_COMMAND)) { at_command (uart); } if (_anyset (uart->flags, UART_ATBR)) { atbr (uart); } return; }
static int telit2_pdp_open(struct cellular *modem, const char *apn) { at_set_timeout(modem->at, 5); at_command_simple(modem->at, "AT+CGDCONT=1,IP,\"%s\"", apn); at_set_timeout(modem->at, 150); const char *response = at_command(modem->at, "AT#SGACT=1,1"); if (response == NULL) return -1; if (!strcmp(response, "+CME ERROR: context already activated")) return 0; int ip[4]; at_simple_scanf(response, "#SGACT: %d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3]); return 0; }
static ssize_t telit2_socket_recv(struct cellular *modem, int connid, void *buffer, size_t length, int flags) { (void) flags; int cnt = 0; while (cnt < (int) length) { int chunk = (int) length - cnt; /* Limit read size to avoid overflowing AT response buffer. */ if (chunk > 128) chunk = 128; /* Perform the read. */ at_set_timeout(modem->at, 150); at_set_command_scanner(modem->at, scanner_srecv); const char *response = at_command(modem->at, "AT#SRECV=%d,%d", connid, chunk); if (response == NULL) return -1; /* Find the header line. */ int bytes; at_simple_scanf(response, "#SRECV: %*d,%d", &bytes); /* Bail out if we're out of data. Message is misleading. */ /* FIXME: We should maybe block until we receive something? */ if (!strcmp(response, "+CME ERROR: activation failed")) break; /* Locate the payload. */ const char *data = strchr(response, '\n'); if (data == NULL) { errno = EPROTO; return -1; } data += 1; /* Copy payload to result buffer. */ memcpy((char *)buffer + cnt, data, bytes); cnt += bytes; } return cnt; }
static int sim800_ftp_getdata(struct cellular *modem, char *buffer, size_t length) { struct cellular_sim800 *priv = (struct cellular_sim800 *) modem; int retries = 0; retry: at_set_timeout(modem->at, SET_TIMEOUT); at_set_command_scanner(modem->at, scanner_ftpget2); const char *response = at_command(modem->at, "AT+FTPGET=2,%zu", length); if (response == NULL) return -1; int cnflength; if (sscanf(response, "+FTPGET: 2,%d", &cnflength) == 1) { /* Zero means no data is available. Wait for it. */ if (cnflength == 0) { /* Bail out on timeout. */ if (++retries >= SIM800_FTP_TIMEOUT) { return -1; } vTaskDelay(pdMS_TO_TICKS(1000)); goto retry; } /* Locate the payload. */ const char *data = strchr(response, '\n'); if (data == NULL) { return -1; } data += 1; /* Copy payload to result buffer. */ memcpy((char *)buffer, data, cnflength); return cnflength; } else if (priv->ftpget1_status == 0) { /* Transfer finished. */ return 0; } else { return -1; } }
/** * Retrieve AT+CIPSTATUS state. * * @returns Zero if context is open, -1 and sets errno otherwise. */ static int sim800_ipstatus(struct cellular *modem) { at_set_timeout(modem->at, 10); at_set_command_scanner(modem->at, scanner_cipstatus); const char *response = at_command(modem->at, "AT+CIPSTATUS"); if (response == NULL) return -1; const char *state = strstr(response, "STATE: "); if (!state) { return -1; } state += strlen("STATE: "); if (!strncmp(state, "IP STATUS", strlen("IP STATUS"))) return 0; if (!strncmp(state, "IP PROCESSING", strlen("IP PROCESSING"))) return 0; return -1; }
static int sim800_socket_waitack(struct cellular *modem, int connid) { const char *response; if(connid == SIM800_NSOCKETS) { return 0; } else if(connid < SIM800_NSOCKETS) { at_set_timeout(modem->at, 5); for (int i=0; i<SIM800_WAITACK_TIMEOUT; i++) { /* Read number of bytes waiting. */ int nacklen; response = at_command(modem->at, "AT+CIPACK=%d", connid); at_simple_scanf(response, "+CIPACK: %*d,%*d,%d", &nacklen); /* Return if all bytes were acknowledged. */ if (nacklen == 0) return 0; vTaskDelay(pdMS_TO_TICKS(1000)); } } return -1; }
int main(int argc, char *argv[]) { assert(argc-1 == 1); const char *devpath = argv[1]; printf("allocating channel...\n"); struct at *at = at_alloc_unix(devpath, B115200); printf("opening port...\n"); assert(at_open(at) == 0); printf("attaching callbacks\n"); at_set_callbacks(at, &generic_modem_callbacks, NULL); const char *commands[] = { "AT", "ATE0", "AT+CGMR", "AT+CGSN", "AT+CCID", "AT+CMEE=0", "AT+BLAH", "AT+CMEE=2", "AT+BLAH", NULL }; printf("sending commands...\n"); at_set_timeout(at, 10); for (const char **command=commands; *command; command++) { const char *result = at_command(at, *command); printf("%s => %s\n", *command, result ? result : strerror(errno)); } printf("freeing resources...\n"); at_free(at); return 0; }
static int telit2_op_clock_gettime(struct cellular *modem, struct timespec *ts) { struct tm tm; int offset; at_set_timeout(modem->at, 1); const char *response = at_command(modem->at, "AT+CCLK?"); memset(&tm, 0, sizeof(struct tm)); at_simple_scanf(response, "+CCLK: \"%d/%d/%d,%d:%d:%d%d\"", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &offset); /* Most modems report some starting date way in the past when they have * no date/time estimation. */ if (tm.tm_year < 14) { errno = EINVAL; return 1; } /* Adjust values and perform conversion. */ tm.tm_year += 2000 - 1900; tm.tm_mon -= 1; time_t unix_time = timegm(&tm); if (unix_time == -1) { errno = EINVAL; return -1; } /* Telit modems return local date/time instead of UTC (as defined in 3GPP * 27.007). Remove the timezone shift. */ unix_time -= 15*60*offset; /* All good. Return the result. */ ts->tv_sec = unix_time; ts->tv_nsec = 0; return 0; }
int main(int argc, char *argv[]) { int fd; bdaddr_t bdaddr; uint8_t channel; char *atcmd; char prompt[]="at> "; int hci_nr = 0; switch (argc) { case 2: str2ba(argv[1], &bdaddr); channel = 1; break; case 3: str2ba(argv[1], &bdaddr); channel = atoi(argv[2]); break; case 4: str2ba(argv[1], &bdaddr); channel = atoi(argv[2]); hci_nr = atoi(argv[3]); break; default: usage(); exit(-1); } if (bacmp(BDADDR_ANY, &bdaddr)) { printf("Connecting to %s on channel %d\n", argv[1], channel); fd = open_socket(&bdaddr, channel, hci_nr); } else { printf("Opening device %s\n", argv[1]); fd = open_device(argv[1]); } if (fd < 0) exit(-2); at_command(fd, "ATZ\r\n", 10000); while(1) { atcmd = readline(prompt); if((!strcmp(atcmd,"exit")) || (!strcmp(atcmd,"quit"))) { close(fd); exit(0); } else { strcat(atcmd,"\r\n"); at_command(fd, atcmd, 100000); } } close(fd); return 0; }
static ssize_t sim800_socket_recv(struct cellular *modem, int connid, void *buffer, size_t length, int flags) { struct cellular_sim800 *priv = (struct cellular_sim800 *) modem; (void) flags; int cnt = 0; // TODO its dumb and exceptions should be handled in other right way // FIXME: It has to be changed. Leave for now if(connid == SIM800_NSOCKETS) { if(priv->spp_status != SIM800_SOCKET_STATUS_CONNECTED) { return -1; } /* Copy payload to result buffer. */ cnt = strlen(spp_recv_buf); if(cnt) { memcpy(buffer, spp_recv_buf, cnt); *(((char*)buffer) + cnt) = '\0'; spp_recv_buf[0] = '\0'; } } else if(connid < SIM800_NSOCKETS) { if(priv->socket_status[connid] != SIM800_SOCKET_STATUS_CONNECTED) { return -1; } char tries = 4; while ( (cnt < (int) length) && tries-- ){ int chunk = (int) length - cnt; /* Limit read size to avoid overflowing AT response buffer. */ chunk = chunk > 480 ? 480 : chunk; /* Perform the read. */ at_set_timeout(modem->at, SET_TIMEOUT); at_set_command_scanner(modem->at, scanner_ciprxget); const char *response = at_command(modem->at, "AT+CIPRXGET=2,%d,%d", connid, chunk); if (response == NULL) return -1; /* Find the header line. */ int requested, confirmed; // TODO: // 1. connid is not checked // 2. there is possible a bug here. if not all data are ready (confirmed < requested) // then wierd things can happen. see memcpy // requested should be equal to chunk // confirmed is that what can be read at_simple_scanf(response, "+CIPRXGET: 2,%*d,%d,%d", &requested, &confirmed); /* Bail out if we're out of data. */ /* FIXME: We should maybe block until we receive something? */ if (confirmed == 0) break; /* Locate the payload. */ /* TODO: what if no \n is in input stream? * should use strnchr at least */ const char *data = strchr(response, '\n'); if (data++ == NULL) { return -1; } /* Copy payload to result buffer. */ memcpy((char *)buffer + cnt, data, confirmed); cnt += confirmed; } } return cnt; }
/// main loop for time division multiplexing transparent serial /// void tdm_serial_loop(void) { __pdata uint16_t last_t = timer2_tick(); __pdata uint16_t last_link_update = last_t; _canary = 42; for (;;) { __pdata uint8_t len; __pdata uint16_t tnow, tdelta; __pdata uint8_t max_xmit; if (_canary != 42) { panic("stack blown\n"); } if (pdata_canary != 0x41) { panic("pdata canary changed\n"); } // give the AT command processor a chance to handle a command at_command(); // display test data if needed if (test_display) { display_test_output(); test_display = 0; } if (seen_mavlink && feature_mavlink_framing && !at_mode_active) { seen_mavlink = false; MAVLink_report(); } // set right receive channel radio_set_channel(fhop_receive_channel()); // get the time before we check for a packet coming in tnow = timer2_tick(); // see if we have received a packet if (radio_receive_packet(&len, pbuf)) { // update the activity indication received_packet = true; fhop_set_locked(true); // update filtered RSSI value and packet stats statistics.average_rssi = (radio_last_rssi() + 7*(uint16_t)statistics.average_rssi)/8; statistics.receive_count++; // we're not waiting for a preamble // any more transmit_wait = 0; if (len < 2) { // not a valid packet. We always send // two control bytes at the end of every packet continue; } // extract control bytes from end of packet memcpy(&trailer, &pbuf[len-sizeof(trailer)], sizeof(trailer)); len -= sizeof(trailer); if (trailer.window == 0 && len != 0) { // its a control packet if (len == sizeof(struct statistics)) { memcpy(&remote_statistics, pbuf, len); } // don't count control packets in the stats statistics.receive_count--; } else if (trailer.window != 0) { // sync our transmit windows based on // received header sync_tx_windows(len); last_t = tnow; if (trailer.command == 1) { handle_at_command(len); } else if (len != 0 && !packet_is_duplicate(len, pbuf, trailer.resend) && !at_mode_active) { // its user data - send it out // the serial port //printf("rcv(%d,[", len); LED_ACTIVITY = LED_ON; serial_write_buf(pbuf, len); LED_ACTIVITY = LED_OFF; //printf("]\n"); } } continue; } // see how many 16usec ticks have passed and update // the tdm state machine. We re-fetch tnow as a bad // packet could have cost us a lot of time. tnow = timer2_tick(); tdelta = tnow - last_t; tdm_state_update(tdelta); last_t = tnow; // update link status every 0.5s if (tnow - last_link_update > 32768) { link_update(); last_link_update = tnow; } if (lbt_rssi != 0) { // implement listen before talk if (radio_current_rssi() < lbt_rssi) { lbt_listen_time += tdelta; } else { lbt_listen_time = 0; if (lbt_rand == 0) { lbt_rand = ((uint16_t)rand()) % lbt_min_time; } } if (lbt_listen_time < lbt_min_time + lbt_rand) { // we need to listen some more continue; } } // we are allowed to transmit in our transmit window // or in the other radios transmit window if we have // bonus ticks #if USE_TICK_YIELD if (tdm_state != TDM_TRANSMIT && !(bonus_transmit && tdm_state == TDM_RECEIVE)) { // we cannot transmit now continue; } #else if (tdm_state != TDM_TRANSMIT) { continue; } #endif if (transmit_yield != 0) { // we've give up our window continue; } if (transmit_wait != 0) { // we're waiting for a preamble to turn into a packet continue; } if (!received_packet && radio_preamble_detected() || radio_receive_in_progress()) { // a preamble has been detected. Don't // transmit for a while transmit_wait = packet_latency; continue; } // sample the background noise when it is out turn to // transmit, but we are not transmitting, // averaged over around 4 samples statistics.average_noise = (radio_current_rssi() + 3*(uint16_t)statistics.average_noise)/4; if (duty_cycle_wait) { // we're waiting for our duty cycle to drop continue; } // how many bytes could we transmit in the time we // have left? if (tdm_state_remaining < packet_latency) { // none .... continue; } max_xmit = (tdm_state_remaining - packet_latency) / ticks_per_byte; if (max_xmit < PACKET_OVERHEAD) { // can't fit the trailer in with a byte to spare continue; } max_xmit -= PACKET_OVERHEAD; if (max_xmit > max_data_packet_length) { max_xmit = max_data_packet_length; } // ask the packet system for the next packet to send if (send_at_command && max_xmit >= strlen(remote_at_cmd)) { // send a remote AT command len = strlen(remote_at_cmd); memcpy(pbuf, remote_at_cmd, len); trailer.command = 1; send_at_command = false; } else { // get a packet from the serial port memset(pbuf, 0x40, 16); len = packet_get_next(max_xmit-16, pbuf+16) + 16; trailer.command = packet_is_injected(); if (len == 16) len = 0; } if (len > max_data_packet_length) { panic("oversized tdm packet"); } trailer.bonus = (tdm_state == TDM_RECEIVE); trailer.resend = packet_is_resend(); if (tdm_state == TDM_TRANSMIT && len == 0 && send_statistics && max_xmit >= sizeof(statistics)) { // send a statistics packet send_statistics = 0; memcpy(pbuf, &statistics, sizeof(statistics)); len = sizeof(statistics); // mark a stats packet with a zero window trailer.window = 0; trailer.resend = 0; } else { // calculate the control word as the number of // 16usec ticks that will be left in this // tdm state after this packet is transmitted trailer.window = (uint16_t)(tdm_state_remaining - flight_time_estimate(len+sizeof(trailer))); } // set right transmit channel radio_set_channel(fhop_transmit_channel()); memcpy(&pbuf[len], &trailer, sizeof(trailer)); if (len != 0 && trailer.window != 0) { // show the user that we're sending real data LED_ACTIVITY = LED_ON; } if (len == 0) { // sending a zero byte packet gives up // our window, but doesn't change the // start of the next window transmit_yield = 1; } // after sending a packet leave a bit of time before // sending the next one. The receivers don't cope well // with back to back packets transmit_wait = packet_latency; // if we're implementing a duty cycle, add the // transmit time to the number of ticks we've been transmitting if ((duty_cycle - duty_cycle_offset) != 100) { transmitted_ticks += flight_time_estimate(len+sizeof(trailer)); } // start transmitting the packet if (!radio_transmit(len + sizeof(trailer), pbuf, tdm_state_remaining + (silence_period/2)) && len != 0 && trailer.window != 0 && trailer.command == 0) { packet_force_resend(); } if (lbt_rssi != 0) { // reset the LBT listen time lbt_listen_time = 0; lbt_rand = 0; } // set right receive channel radio_set_channel(fhop_receive_channel()); // re-enable the receiver radio_receiver_on(); if (len != 0 && trailer.window != 0) { LED_ACTIVITY = LED_OFF; } } }
/*! * \brief Sequentially initializes the modem step-by-step */ void BridgeCommunicator::initBridgeModem() { QByteArray at_command(1, '\r'); switch (_currentInitStep) { case IBMS_UnInitialized: Q_EMIT snlProcessingStarted(IBMS_ReadyToUse, tr("Initializing modem...")); // show the progress dialog at_command.prepend("ATE0"); _timerModemInitNotResponse.start(1000); break; case IBMS_ATE0: _bReconnect = false; at_command.prepend("ATI"); break; case IBMS_ATI: at_command.prepend("AT+CGATT=1"); break; case IBMS_CGATT: at_command.prepend("AT+CIPCSGP=1,\"vpnl.kyivstar.net\",\"1\",\"1\""); break; case IBMS_CIPCSGP: // at_command.prepend("AT+CDNSORIP=0"); // WARNING: this string for SIM-300 ONLY at_command.prepend("AT"); // this string for SIM-900 (skip current step) break; case IBMS_CDNSORIP: at_command.prepend("AT+CIPMODE=1"); break; case IBMS_CIPMODE: /* +CIPCCFG: <NmRetry>,<WaitTm * 200 ms>,<SendSz>,<esc> +CIPCCFG: <3-8>,<2-10>,<256-1024>,<0,1> */ at_command.prepend("AT+CIPCCFG=5,6,1024,1"); break; case IBMS_CIPCCFG: at_command.prepend( QString("AT+CIPSTART=\"UDP\",\"%1\",\"%2\"") .arg(_mw->currentChannelSettings().deviceIp) .arg(_mw->currentChannelSettings().devicePort) .toLatin1() ); break; case IBMS_WaitForConnect: _timerModemInitNotResponse.start(20000); return; default: return; // modem initialization finished } sendThroughConcreteChannel(at_command); addToLog(at_command, tr("Send: "), tr("[ AT-command ]"), Qt::green); Q_EMIT snlTxData(); if (IBMS_UnInitialized != _currentInitStep) _timerModemInitNotResponse.start(10000); }
static int telit2_ftp_getdata(struct cellular *modem, char *buffer, size_t length) { /* FIXME: This function's flow is really ugly. */ int retries = 0; retry: at_set_timeout(modem->at, 150); at_set_command_scanner(modem->at, scanner_ftprecv); const char *response = at_command(modem->at, "AT#FTPRECV=%zu", length); if (response == NULL) return -1; int bytes; if (sscanf(response, "#FTPRECV: %d", &bytes) == 1) { /* Zero means no data is available. Wait for it. */ if (bytes == 0) { /* Bail out on timeout. */ if (++retries >= TELIT2_FTP_TIMEOUT) { errno = ETIMEDOUT; return -1; } sleep(1); goto retry; } /* Locate the payload. */ const char *data = strchr(response, '\n'); if (data == NULL) { errno = EPROTO; return -1; } data += 1; /* Copy payload to result buffer. */ memcpy(buffer, data, bytes); return bytes; } /* Error or EOF? */ int eof; response = at_command(modem->at, "AT#FTPGETPKT?"); /* Expected response: #FTPGETPKT: <remotefile>,<viewMode>,<eof> */ #if 0 /* The %[] specifier is not supported on some embedded systems. */ at_simple_scanf(response, "#FTPGETPKT: %*[^,],%*d,%d", &eof); #else /* Parse manually. */ if (response == NULL) return -1; errno = EPROTO; /* Check the initial part of the response. */ if (strncmp(response, "#FTPGETPKT: ", 12)) return -1; /* Skip the filename. */ response = strchr(response, ','); if (response == NULL) return -1; response++; at_simple_scanf(response, "%*d,%d", &eof); #endif if (eof == 1) return 0; return -1; }