Ejemplo n.º 1
0
/**
 * Registers a URC with the AT engine.  URC stands for unsolicited result
 * code.  These are asynchronous commands that can appear at any time,
 * except when a command is already in progress (defined as the point between
 * when the control character of the command is sent to when the response
 * message returns from the command).  The idea is that when you register
 * a command and it is seen, then you will get a call back to the handler.
 * This allows you to sanely handle state changes as they occur and avoid
 * unnecessary polling for status when URCs can provide interrupt based
 * updates for you.
 * @param ati An at_info structure.
 * @param pfx The URC prefix.  These often look like "+SOMECMD:"
 * @param flags Control flags that change behavior of AT engine.  These are
 *        needed because there are differences in how devices send URCs.
 * @param rsp_cb The callback to invoke when a URC is received.
 * @param rsp_up A void* parameter to pass to the call back when invoked.
 * @return The pointer to the URC entry in our list, or NULL if we failed
 *         to register the URC.
 */
struct at_urc* at_register_urc(struct at_info *ati, const char *pfx,
                               const enum at_urc_flags flags,
                               bool (*rsp_cb)(struct at_rsp *rsp, void *rsp_up),
                               void *rsp_up)
{
        if (ati->urc_list.count >= AT_URC_MAX_URCS) {
                 /* Full up */
                pr_warning("[at] URC list full\r\n");
                return NULL;
        }

        const size_t pfx_len = strlen(pfx);
        if (pfx_len >= AT_URC_MAX_LEN) {
                /* URC prefix is too long */
                pr_warning_str_msg("[at] URC prefix too long: ", pfx);
                return NULL;
        }

        /* If here, we have space and its ok.  Add it */
        struct at_urc *aturc = ati->urc_list.urcs + ati->urc_list.count;
        ++ati->urc_list.count;

        aturc->rsp_cb = rsp_cb;
        aturc->rsp_up = rsp_up;
        aturc->flags = flags;
        aturc->pfx_len = pfx_len;
        strcpy(aturc->pfx, pfx); /* Sane b/c len check above */

        return aturc;
}
Ejemplo n.º 2
0
/**
 * Puts a new AT command in the execute queue.
 * @param ati The at_info state struct.
 * @param cmd The string command to execute.
 * @param timeout_ms The amount of time to wait for a response in ms.
 * @param rsp_cb The callback to execute when the command completes.  May
 *        be NULL if you want no callback (not advised).
 * @param rsp_up A void* parameter to pass to the call back when invoked.
 * @return The pointer to the location of the at_cmd struct in the queue,
 *         else NULL if submisison failed.
 */
struct at_cmd* at_put_cmd(struct at_info *ati, const char *cmd,
                          const tiny_millis_t timeout_ms,
                          bool (*rsp_cb)(struct at_rsp *rsp, void *rsp_up),
                          void *rsp_up)
{
        if (ati->cmd_queue.count >= AT_CMD_MAX_CMDS) {
                 /* Full up */
                pr_warning("[at] Command queue full");
                return NULL;
        }

        if (strlen(cmd) >= AT_CMD_MAX_LEN) {
                /* Command too long */
                pr_warning_str_msg("[at] Command too long: ", cmd);
                return NULL;
        }

        /* If here, we have space and its ok.  Add it */
        struct at_cmd *atcmd = ati->cmd_queue.head + ati->cmd_queue.count;
        if (atcmd >= ati->cmd_queue.cmds + AT_CMD_MAX_CMDS)
                atcmd -= AT_CMD_MAX_CMDS;

        ++ati->cmd_queue.count;
        atcmd->timeout_ms = timeout_ms;
        atcmd->rsp_cb = rsp_cb;
        atcmd->rsp_up = rsp_up;
        strcpy(atcmd->cmd, cmd); /* Sane b/c len check above */

        return atcmd;
}
static void dropped_char_timer_cb( xTimerHandle xTimer )
{
        for(size_t i = 0; i < __UART_COUNT; ++i) {
                volatile struct usart_info* ui = usart_data + i;

                /* Warning for dropped characters */
                if (ui->char_dropped) {
                        ui->char_dropped = false;
                        pr_warning_str_msg(LOG_PFX "Dropped char: ",
                                           serial_get_name(ui->serial));
                }
        }
}
Ejemplo n.º 4
0
static void process_cmd_or_urc_msg(struct at_info *ati, char *msg)
{
	/*
	 * We are starting a new message series or handling a device
	 * where URCs come in at any time (including mid message).
	 * Gotta figure out what type of message this is before we
	 * process it.
	 */
	if (ati->sparse_urc_cb && ati->sparse_urc_cb(msg)) {
		/* It was a sparse URC that was handled. */
		return;
	}

	/* Not a sparse URC. Let's see if it is a registered URC */
	struct at_urc* const urc = is_urc_msg(ati, msg);
	if (urc) {
		begin_urc_msg(ati, urc);
		return process_urc_msg(ati, msg);
	}

	/*
	 * Check if there is a command in progress.
	 * If so, then cmd_ip will be set and we will treat this
	 * message as a command response.
	 */
	if (ati->cmd_ip)
		return process_cmd_msg(ati, msg);

	/*
	 * If we end up here we have data but have no URC that handles
	 * it nor is there any command in progress. This means that we
	 * have an unhandled message (and these should not happen).
	 * Log it and move on with life.
	 */
	pr_warning_str_msg("[at] Unhandled msg received: ", msg);

	/* Need clean the buffer for new msgs */
	serial_buffer_clear(ati->sb);
}
Ejemplo n.º 5
0
static void open_log_file(struct logging_status *ls)
{
        pr_info("Logging: Opening log file\r\n");
        ls->writing_status = WRITING_INACTIVE;

        const int rc = InitFS();
        if (0 != rc) {
                pr_error_int_msg("Logging: FS init error: ", rc);
                return;
        }

        pr_debug("Logging: FS init success.  Opening file...\r\n");
        // Open a file if one is set, else create a new one.
        ls->writing_status = ls->name[0] ? open_existing_log_file(ls) :
                open_new_log_file(ls);

        if (WRITING_INACTIVE == ls->writing_status) {
                pr_warning_str_msg("Logging: Failed to open: ", ls->name);
                return;
        }

        pr_info_str_msg("Logging: Opened " , ls->name);
        ls->flush_tick = xTaskGetTickCount();
}