static vsf_err_t vsfip_telnetd_session_tx_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt) { struct vsfip_telnetd_session_t *session = (struct vsfip_telnetd_session_t *)pt->user_data; uint32_t len; vsf_err_t err; vsfsm_pt_begin(pt); session->caller_txpt.sm = pt->sm; while (!session->disconnect) { len = stream_get_data_size(session->stream_tx); if (!len && vsfsm_sem_pend(&session->stream_tx_sem, pt->sm)) { vsfsm_pt_wfe(pt, VSFIP_TELNETD_EVT_STREAM_IN); if (session->disconnect) break; continue; } retry_alloc_buf: session->outbuf = VSFIP_TCPBUF_GET(len); if (NULL == session->outbuf) { vsfsm_pt_delay(pt, 5); if (session->disconnect) break; goto retry_alloc_buf; } session->outbuf->app.size = stream_read(session->stream_tx, &session->outbuf->app); if (!session->outbuf->app.size) { vsfip_buffer_release(session->outbuf); continue; } session->caller_txpt.state = 0; vsfsm_pt_entry(pt); err = vsfip_tcp_send(&session->caller_txpt, evt, session->so, &session->so->remote_sockaddr, session->outbuf, false); if (err > 0) return err; else if (err < 0) { session->disconnect = true; } } // close tcp socket session->caller_txpt.state = 0; vsfsm_pt_entry(pt); err = vsfip_tcp_close(&session->caller_txpt, evt, session->so); if (err > 0) return err; // close socket no matter if tcp closed OK or not vsfip_close(session->so); session->connected = false; vsfsm_pt_end(pt); return VSFERR_NONE; }
static vsf_err_t vsfip_telnetd_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt) { struct vsfip_telnetd_t *telnetd = (struct vsfip_telnetd_t *)pt->user_data; vsf_err_t err = VSFERR_NONE; int i; vsfsm_pt_begin(pt); telnetd->caller_pt.sm = pt->sm; telnetd->so = vsfip_socket(AF_INET, IPPROTO_TCP); if (NULL == telnetd->so) { return VSFERR_FAIL; } if ((vsfip_bind(telnetd->so, telnetd->port) != 0) || (vsfip_listen(telnetd->so, telnetd->session_num) != 0)) { err = VSFERR_FAIL; goto fail_socket_connect; } while (1) { telnetd->caller_pt.state = 0; vsfsm_pt_entry(pt); err = vsfip_tcp_accept(&telnetd->caller_pt, evt, telnetd->so, &telnetd->cur_session); if (err > 0) return err; else if (err < 0) { continue; } // get session for (i = 0; i < telnetd->session_num; i++) { if (!telnetd->sessions[i].connected) { struct vsfip_telnetd_session_t *session = &telnetd->sessions[i]; session->connected = true; session->disconnect = false; session->so = telnetd->cur_session; session->stream_rx->callback_tx.param = session; session->stream_rx->callback_tx.on_inout = vsfip_telnetd_session_stream_on_out; session->stream_tx->callback_rx.param = session; session->stream_tx->callback_rx.on_inout = vsfip_telnetd_session_stream_on_in; stream_connect_tx(session->stream_rx); stream_connect_rx(session->stream_tx); vsfsm_sem_init(&session->stream_tx_sem, 0, VSFIP_TELNETD_EVT_STREAM_IN); vsfsm_sem_init(&session->stream_rx_sem, 0, VSFIP_TELNETD_EVT_STREAM_OUT); session->txpt.thread = vsfip_telnetd_session_tx_thread; session->txpt.user_data = session; session->rxpt.thread = vsfip_telnetd_session_rx_thread; session->rxpt.user_data = session; vsfsm_pt_init(&session->txsm, &session->txpt); vsfsm_pt_init(&session->rxsm, &session->rxpt); break; } } if (i == telnetd->session_num) { telnetd->caller_pt.state = 0; vsfsm_pt_entry(pt); err = vsfip_tcp_close(&telnetd->caller_pt, evt, telnetd->cur_session); if (err > 0) return err; vsfip_close(telnetd->cur_session); } } fail_socket_connect: vsfip_close(telnetd->so); telnetd->so = NULL; vsfsm_pt_end(pt); return VSFERR_NONE; }
// vsfos static vsf_err_t vsfos_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt) { struct vsfos_modifs_t *ifs = (struct vsfos_modifs_t *)pt->user_data; vsf_err_t err; vsfsm_pt_begin(pt); vsfhal_core_init(NULL); vsfhal_tickclk_init(); vsfhal_tickclk_start(); // timer VSFPOOL_INIT(&ifs->vsftimer_pool, struct vsftimer_t, VSFOSCFG_VSFSM_PENDSVQ_LEN); vsftimer_init(&ifs->vsftimer_memop); vsfhal_tickclk_config_cb(vsfos_tickclk_callback_int, NULL); // file VSFPOOL_INIT(&ifs->vfsfile_pool, struct vsfile_vfsfile_t, VSFOSCFG_VFS_NO); vsfile_init(&ifs->fs.memop); ifs->caller_pt.state = 0; vsfsm_pt_entry(pt); err = vsfile_addfile(&ifs->caller_pt, evt, NULL, "msc_root", VSFILE_ATTR_DIRECTORY); if (err != 0) return err; ifs->caller_pt.state = 0; vsfsm_pt_entry(pt); err = vsfile_getfile(&ifs->caller_pt, evt, NULL, "/msc_root", &ifs->file); if (err != 0) return err; ifs->caller_pt.state = 0; ifs->caller_pt.user_data = &ifs->mal.fakefat32; err = vsfile_mount(&ifs->caller_pt, evt, (struct vsfile_fsop_t *)&fakefat32_fs_op, ifs->file); if (err != 0) return err; // vsfip { struct vsfip_buffer_t *buffer; int i; buffer = &ifs->tcpip.buffer_pool.buffer[0]; for (i = 0; i < VSFOSCFG_VSFIP_BUFFER_NUM; i++) { buffer->buffer = ifs->tcpip.buffer_mem[i]; buffer++; } } VSFPOOL_INIT(&ifs->tcpip.buffer_pool, struct vsfip_buffer_t, VSFOSCFG_VSFIP_BUFFER_NUM); VSFPOOL_INIT(&ifs->tcpip.socket_pool, struct vsfip_socket_t, VSFOSCFG_VSFIP_SOCKET_NUM); VSFPOOL_INIT(&ifs->tcpip.tcppcb_pool, struct vsfip_tcppcb_t, VSFOSCFG_VSFIP_TCPPCB_NUM); vsfip_init((struct vsfip_mem_op_t *)&ifs->tcpip.mem_op); STREAM_INIT(&ifs->usbd.cdc.stream_rx); STREAM_INIT(&ifs->usbd.cdc.stream_tx); vsfscsi_init(&ifs->mal.scsi_dev); vsfusbd_device_init(&ifs->usbd.device); vsfshell_init(&ifs->shell); vsfos_busybox_init(&ifs->shell); if ((ifs->hwcfg->usbd.pullup.port != IFS_DUMMY_PORT) && (vsfhal_gpio_if != NULL)) { uint8_t port = ifs->hwcfg->usbd.pullup.port; uint8_t pin = ifs->hwcfg->usbd.pullup.pin; vsfhal_gpio_init(port); vsfhal_gpio_clear(port, 1 << pin); vsfhal_gpio_config_pin(port, pin, GPIO_OUTPP); } ifs->usbd.device.drv->disconnect(); vsfsm_pt_delay(pt, 200); if ((ifs->hwcfg->usbd.pullup.port != IFS_DUMMY_PORT) && (vsfhal_gpio_if != NULL)) { uint8_t port = ifs->hwcfg->usbd.pullup.port; uint8_t pin = ifs->hwcfg->usbd.pullup.pin; vsfhal_gpio_set(port, 1 << pin); } ifs->usbd.device.drv->connect(); while (1) { vsfsm_pt_delay(pt, 1000); asm("nop"); vsfsm_pt_delay(pt, 1000); asm("nop"); vsfsm_pt_delay(pt, 1000); asm("nop"); vsfsm_pt_delay(pt, 1000); asm("nop"); vsfsm_pt_delay(pt, 1000); asm("nop"); vsfsm_pt_delay(pt, 1000); asm("nop"); } vsfsm_pt_end(pt); 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; }
// vsfshell_input_thread is used to process the events // from the sender of the stream_rx vsf_err_t vsfshell_input_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt) { struct vsfshell_t *shell = (struct vsfshell_t *)pt->user_data; struct vsfsm_pt_t *output_pt = &shell->output_pt; char *cmd = (char *)shell->tbuffer.buffer.buffer; struct vsf_buffer_t buffer; vsfsm_pt_begin(pt); vsfsm_pt_wfe(pt, VSFSHELL_EVT_STREAMTX_ONCONN); vsfshell_printf(output_pt, "vsfshell 0.1 beta by SimonQian" VSFSHELL_LINEEND); vsfshell_printf(output_pt, VSFSHELL_PROMPT); shell->prompted = true; while (1) { vsfsm_pt_wfe(pt, VSFSHELL_EVT_STREAMRX_ONIN); do { buffer.buffer = (uint8_t *)&shell->ch; buffer.size = 1; buffer.size = stream_read(shell->stream_rx, &buffer); if (0 == buffer.size) { break; } if (shell->echo) { if ('\r' == shell->ch) { vsfshell_printf(output_pt, VSFSHELL_LINEEND); } else if ('\b' == shell->ch) { if (shell->tbuffer.position) { vsfshell_printf(output_pt, "\b \b"); shell->tbuffer.position--; } continue; } else if (//!((shell->ch >= ' ') && (shell->ch <= '~')) || (shell->tbuffer.position >= shell->tbuffer.buffer.size - 1)) { continue; } else { vsfshell_printf(output_pt, "%c", shell->ch); } } if ('\r' == shell->ch) { if (shell->tbuffer.position > 0) { // create new handler thread cmd[shell->tbuffer.position] = '\0'; if (vsfshell_new_handler_thread(shell, cmd)) { vsfshell_printf(output_pt, "Fail to execute : %s" VSFSHELL_LINEEND, cmd); vsfshell_printf(output_pt, VSFSHELL_PROMPT); } shell->tbuffer.position = 0; } else { vsfshell_printf(output_pt, VSFSHELL_PROMPT); } shell->prompted = true; break; } else if (shell->ch != '\n') { cmd[shell->tbuffer.position++] = shell->ch; } } while (buffer.size > 0); } vsfsm_pt_end(pt); return VSFERR_NOT_READY; }
static vsf_err_t uvc_ctrl_thread(struct vsfsm_pt_t *pt, vsfsm_evt_t evt) { vsf_err_t err; struct vsfusbh_uvc_t *hdata = (struct vsfusbh_uvc_t *)pt->user_data; struct vsfusbh_urb_t *vsfurb = &hdata->ctrl_urb; vsfsm_pt_begin(pt); if (hdata->set_param.video_enable) { // negotiate hdata->video_iso_packet_len = 1024; hdata->video_iso_ep = 1; // commit param vsfurb->transfer_buffer = hdata->ctrl_urb_buf; memcpy(vsfurb->transfer_buffer, negotiate_temp, 26); vsfurb->transfer_length = 26; vsfurb->pipe = usb_sndctrlpipe(vsfurb->vsfdev, 0); err = vsfusbh_control_msg(hdata->usbh, vsfurb, USB_TYPE_CLASS |USB_RECIP_INTERFACE | USB_DIR_OUT, SET_CUR, 0x0200, 0x0001); if (err != VSFERR_NONE) return err; vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE); if (vsfurb->status != URB_OK) return VSFERR_FAIL; // set interfaces vsfurb->transfer_buffer = NULL; vsfurb->transfer_length = 0; err = vsfusbh_set_interface(hdata->usbh, vsfurb, 1, 4); if (err != VSFERR_NONE) return err; vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE); if (vsfurb->status != URB_OK) return VSFERR_FAIL; // enable video vsfsm_post_evt_pending(&hdata->video_sm, UAV_ISO_ENABLE); } else { vsfurb->transfer_buffer = NULL; vsfurb->transfer_length = 0; err = vsfusbh_set_interface(hdata->usbh, vsfurb, 1, 0); if (err != VSFERR_NONE) return err; vsfsm_pt_wfe(pt, VSFSM_EVT_URB_COMPLETE); if (vsfurb->status != URB_OK) return VSFERR_FAIL; } vsf_bufmgr_free(hdata->ctrl_urb_buf); hdata->ctrl_urb_buf = NULL; memcpy(&hdata->cur_param, &hdata->set_param, sizeof(struct vsfusbh_uvc_param_t)); vsfusbh_uvc_report(hdata, &hdata->cur_param, NULL); vsfsm_pt_end(pt); return VSFERR_NONE; }