static vsf_err_t vsf_malstream_read_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt) { struct vsf_malstream_t *malstream = (struct vsf_malstream_t *)pt->user_data; struct vsfmal_t *mal = malstream->mal; struct vsf_stream_t *stream = (struct vsf_stream_t *)malstream->mbufstream; uint64_t cur_addr; vsf_err_t err; vsfsm_pt_begin(pt); mal->op_block_size = mal->drv->block_size(mal, malstream->addr, 0, VSFMAL_OP_READ); if (mal->op_block_size != malstream->mbufstream->mem.multibuf.size) { return VSFERR_BUG; } mal->pt.user_data = mal; malstream->offset = 0; while (malstream->offset < malstream->size) { while (stream_get_free_size(stream) < mal->op_block_size) { vsfsm_pt_wfe(pt, VSF_MALSTREAM_ON_INOUT); } mal->pt.state = 0; vsfsm_pt_entry(pt); cur_addr = malstream->addr + malstream->offset; err = mal->drv->read(&mal->pt, evt, cur_addr, vsf_multibuf_get_empty(&malstream->mbufstream->mem.multibuf), mal->op_block_size); if (err > 0) return err; else if (err < 0) goto end; vsf_multibuf_push(&malstream->mbufstream->mem.multibuf); malstream->offset += mal->op_block_size; if (malstream->offset >= malstream->size) { // fix before callback stream->callback_tx.on_inout = NULL; } if (stream->rx_ready && (stream->callback_rx.on_inout != NULL)) { stream->callback_rx.on_inout(stream->callback_rx.param); } } end: if (malstream->cb.on_finish != NULL) { malstream->cb.on_finish(malstream->cb.param); } vsfsm_pt_end(pt); return VSFERR_NONE; }
static struct vsfsm_state_t * vsfusbd_CDCData_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt) { struct vsfusbd_CDC_param_t *param = (struct vsfusbd_CDC_param_t *)sm->user_data; struct vsfusbd_device_t *device = param->device; switch (evt) { case VSFSM_EVT_INIT: param->stream_tx->callback_rx.param = param; param->stream_tx->callback_rx.on_inout = vsfusbd_CDCData_streamtx_on_in; param->stream_tx->callback_rx.on_connect = vsfusbd_CDCData_streamtx_on_txconn; param->stream_rx->callback_tx.param = param; param->stream_rx->callback_tx.on_inout = vsfusbd_CDCData_streamrx_on_out; param->stream_rx->callback_tx.on_connect = vsfusbd_CDCData_streamrx_on_rxconn; param->out_enable = false; param->in_enable = false; break; case VSFUSBD_CDC_EVT_STREAMTX_ONCONN: vsfusbd_set_IN_handler(device, param->ep_in, vsfusbd_CDCData_IN_hanlder); break; case VSFUSBD_CDC_EVT_STREAMRX_ONCONN: vsfusbd_set_OUT_handler(device, param->ep_out, vsfusbd_CDCData_OUT_hanlder); vsfsm_post_evt(sm, VSFUSBD_CDC_EVT_STREAMRX_ONOUT); break; case VSFUSBD_CDC_EVT_STREAMTX_ONIN: if (!param->in_enable) { param->in_enable = true; vsfusbd_CDCData_IN_hanlder(param->device, param->ep_in); } break; case VSFUSBD_CDC_EVT_STREAMRX_ONOUT: if (!param->out_enable && (stream_get_free_size(param->stream_rx) >= device->drv->ep.get_OUT_epsize(param->ep_out))) { param->out_enable = true; device->drv->ep.enable_OUT(param->ep_out); } break; } return NULL; }
uint32_t debug(const char *format, ...) { va_list ap; struct vsf_buffer_t buffer; uint32_t size_avail, size_out, i, colon; uint8_t *ptr; if (debug_stream == NULL) return 0; size_avail = stream_get_free_size(debug_stream); if (size_avail < 3) return 0; // TODO: manual parse format va_start(ap, format); size_out = vsnprintf((char *)debug_info, VSFCFG_DEBUG_INFO_PARSE_LEN, format, ap); va_end(ap); if (size_out < 3) return 0; ptr = debug_info; i = 0; colon = 0; while (ptr < debug_info + size_out - 3) { if ((*ptr == ':') && (colon++ > 0)) break; if ((*ptr == '/') || (*ptr == '\\')) i = ptr - debug_info + 1; ptr++; } size_avail = min(size_avail, size_out - i); debug_info[i + size_avail - 2] = '\r'; debug_info[i + size_avail - 1] = '\n'; buffer.buffer = debug_info + i; buffer.size = size_avail; return stream_write(debug_stream, &buffer); }
static vsf_err_t vsfusbd_CDCData_OUT_hanlder(struct vsfusbd_device_t *device, uint8_t ep) { struct vsfusbd_config_t *config = &device->config[device->configuration]; int8_t iface = config->ep_OUT_iface_map[ep]; struct vsfusbd_CDC_param_t *param = NULL; uint16_t pkg_size, ep_size; uint8_t buffer[64]; struct vsf_buffer_t rx_buffer; if (iface < 0) { return VSFERR_FAIL; } param = (struct vsfusbd_CDC_param_t *)config->iface[iface].protocol_param; if (NULL == param) { return VSFERR_FAIL; } ep_size = device->drv->ep.get_OUT_epsize(ep); pkg_size = device->drv->ep.get_OUT_count(ep); if (pkg_size > ep_size) { return VSFERR_FAIL; } device->drv->ep.read_OUT_buffer(ep, buffer, pkg_size); rx_buffer.buffer = buffer; rx_buffer.size = pkg_size; stream_write(param->stream_rx, &rx_buffer); if (stream_get_free_size(param->stream_rx) < ep_size) { param->out_enable = false; } else { device->drv->ep.enable_OUT(ep); } return VSFERR_NONE; }
static vsf_err_t vsfusbd_CDCData_class_poll(uint8_t iface, struct vsfusbd_device_t *device) { struct vsfusbd_config_t *config = &device->config[device->configuration]; struct vsfusbd_CDC_param_t *param = (struct vsfusbd_CDC_param_t *)config->iface[iface].protocol_param; if (NULL == param) { return VSFERR_FAIL; } if (!param->out_enable) { uint16_t ep_size = device->drv->ep.get_OUT_epsize(param->ep_out); if (stream_get_free_size(param->stream_tx) >= ep_size) { param->out_enable = true; device->drv->ep.enable_OUT(param->ep_out); } } return VSFERR_NONE; }
// vsfshell_output_thread is used to process the events // from the receiver of the stream_tx vsf_err_t vsfshell_output_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt, const char *format, ...) { struct vsfshell_t *shell = (struct vsfshell_t *)pt->user_data; uint32_t str_len, size_avail; struct vsf_buffer_t buffer; va_list ap; char *printf_buff; uint32_t printf_size; vsfsm_pt_begin(pt); // get lock here if (vsfsm_crit_enter(&shell->output_crit, pt->sm)) { vsfsm_pt_wfe(pt, VSFSHELL_EVT_OUTPUT_CRIT_AVAIL); } shell->output_sm = pt->sm; if (shell->output_interrupted && (pt->sm == &shell->sm)) { // is vsfshell_input_thread is interrupted // and current pt is vsfshell_input_thread // then output the VSFSHELL_PROMPT and the original commandline shell->output_interrupted = false; size_avail = stream_get_free_size(shell->stream_tx); while (size_avail < strlen(VSFSHELL_PROMPT)) { vsfsm_pt_wfe(pt, VSFSHELL_EVT_STREAMTX_ONOUT); size_avail = stream_get_free_size(shell->stream_tx); } buffer.buffer = (uint8_t *)VSFSHELL_PROMPT; buffer.size = strlen(VSFSHELL_PROMPT); stream_write(shell->stream_tx, &buffer); shell->prompted = true; shell->tbuffer.buffer.buffer[shell->tbuffer.position] = '\0'; shell->printf_pos = (char *)shell->tbuffer.buffer.buffer; str_len = strlen(shell->printf_pos); while (str_len > 0) { size_avail = stream_get_free_size(shell->stream_tx); if (!size_avail) { vsfsm_pt_wfe(pt, VSFSHELL_EVT_STREAMTX_ONOUT); size_avail = stream_get_free_size(shell->stream_tx); str_len = strlen(shell->printf_pos); } if (size_avail) { buffer.buffer = (uint8_t *)shell->printf_pos; buffer.size = min(str_len, size_avail); buffer.size = stream_write(shell->stream_tx, &buffer); shell->printf_pos += buffer.size; str_len = strlen(shell->printf_pos); } } } va_start(ap, format); printf_size = sizeof(shell->printf_buff); printf_buff = shell->printf_buff; if (pt->sm != shell->input_sm) { // if current pt is not frontend, then add a new line if (shell->input_sm == &shell->sm) { // if current frontend pt is vsfshell_input_thread // then set output_interrupted, so that current command line // input will be recovered later shell->output_interrupted = true; } if (shell->prompted) { // add a new line if prompt is outputed strcpy(shell->printf_buff, VSFSHELL_LINEEND); printf_size -= strlen(VSFSHELL_LINEEND); printf_buff += strlen(VSFSHELL_LINEEND); shell->prompted = false; } } str_len = vsnprintf(printf_buff, printf_size, format, ap); va_end(ap); shell->printf_pos = shell->printf_buff; while (str_len > 0) { size_avail = stream_get_free_size(shell->stream_tx); if (!size_avail) { vsfsm_pt_wfe(pt, VSFSHELL_EVT_STREAMTX_ONOUT); size_avail = stream_get_free_size(shell->stream_tx); str_len = strlen(shell->printf_pos); } if (size_avail) { buffer.buffer = (uint8_t *)shell->printf_pos; buffer.size = min(str_len, size_avail); buffer.size = stream_write(shell->stream_tx, &buffer); shell->printf_pos += buffer.size; str_len = strlen(shell->printf_pos); } } shell->output_sm = NULL; vsfsm_crit_leave(&shell->output_crit); vsfsm_pt_end(pt); return VSFERR_NONE; }