예제 #1
0
파일: vsfshell.c 프로젝트: LewosPeng/vsf
static vsf_err_t
vsfshell_new_handler_thread(struct vsfshell_t *shell, char *cmd)
{
	struct vsfshell_handler_param_t *param =
		(struct vsfshell_handler_param_t *)vsf_bufmgr_malloc(sizeof(*param));
	struct vsfshell_handler_t *handler;
	vsf_err_t err = VSFERR_NONE;
	
	if (NULL == param)
	{
		goto exit;
	}
	memset(param, 0, sizeof(*param));
	param->shell = shell;
	param->output_pt.sm = &param->sm;
	param->output_pt.thread = (vsfsm_pt_thread_t)vsfshell_output_thread;
	param->output_pt.user_data = shell;
	
	// parse command line
	param->argc = dimof(param->argv);
	if (vsfshell_parse_cmd(cmd, param))
	{
		goto exit_free_argv;
	}
	
	// search handler
	handler =  vsfshell_search_handler(shell, param->argv[0]);
	if (NULL == handler)
	{
		goto exit_free_argv;
	}
	
	param->context = handler->context;
	param->pt.thread = handler->thread;
	param->pt.user_data = param;
	param->pt.sm = &param->sm;
	
	shell->input_sm = &param->sm;
	vsfsm_pt_init(&param->sm, &param->pt);
	goto exit;
	
exit_free_argv:
	vsfshell_free_param(param);
	err = VSFERR_FAIL;
exit:
	return err;
}
예제 #2
0
파일: vsfmal.c 프로젝트: LewosPeng/vsf
vsf_err_t vsf_malstream_write(struct vsf_malstream_t *malstream, uint64_t addr,
							uint32_t size)
{
	struct vsf_stream_t *stream = (struct vsf_stream_t *)malstream->mbufstream;

	malstream->addr = addr;
	malstream->size = size;

	stream->callback_rx.param = malstream;
	stream->callback_rx.on_inout = vsf_malstream_on_inout;
	stream->callback_rx.on_connect = NULL;
	stream->callback_rx.on_disconnect = NULL;
	stream_connect_rx(stream);

	malstream->pt.thread = vsf_malstream_write_thread;
	malstream->pt.user_data = malstream;
	return vsfsm_pt_init(&malstream->sm, &malstream->pt);
}
예제 #3
0
vsf_err_t vsfip_telnetd_start(struct vsfip_telnetd_t *telnetd)
{
	telnetd->pt.thread = vsfip_telnetd_thread;
	telnetd->pt.user_data = telnetd;
	return vsfsm_pt_init(&telnetd->sm, &telnetd->pt);
}
예제 #4
0
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;
}
예제 #5
0
파일: vsfos.c 프로젝트: hank-fan/vsf
vsf_err_t vsfos_modinit(struct vsf_module_t *module,
								struct app_hwcfg_t const *cfg)
{
	struct vsfos_modifs_t *ifs;
	ifs = vsf_bufmgr_malloc(sizeof(struct vsfos_modifs_t));
	if (!ifs) return VSFERR_FAIL;
	memset(ifs, 0, sizeof(*ifs));

	ifs->hwcfg = cfg;

	ifs->pendsvq.size = dimof(ifs->pendsvq_ele);
	ifs->pendsvq.queue = ifs->pendsvq_ele;
	ifs->pendsvq.activate = vsfos_pendsv_activate;

	// init vsftimer
	ifs->vsftimer_memop.alloc = vsftimer_memop_alloc;
	ifs->vsftimer_memop.free = vsftimer_memop_free;

	// init fakefat32_fs
	ifs->fakefat32_fs.Windows_dir[0].memfile.file.name = ".";
	ifs->fakefat32_fs.Windows_dir[0].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.Windows_dir[1].memfile.file.name = "..";
	ifs->fakefat32_fs.Windows_dir[1].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.Windows_dir[2].memfile.file.name = "VSFCDC.inf";
	ifs->fakefat32_fs.Windows_dir[2].memfile.file.size = sizeof(vsfcdc_inf) - 1;
	ifs->fakefat32_fs.Windows_dir[2].memfile.file.attr = VSFILE_ATTR_ARCHIVE | VSFILE_ATTR_READONLY;
	ifs->fakefat32_fs.Windows_dir[2].memfile.f.buff = (uint8_t *)vsfcdc_inf;
	ifs->fakefat32_fs.Windows_dir[3].memfile.file.name = "VSFRNDIS.inf";
	ifs->fakefat32_fs.Windows_dir[3].memfile.file.size = sizeof(vsfrndis_inf) - 1;
	ifs->fakefat32_fs.Windows_dir[3].memfile.file.attr = VSFILE_ATTR_ARCHIVE | VSFILE_ATTR_READONLY;
	ifs->fakefat32_fs.Windows_dir[3].memfile.f.buff = (uint8_t *)vsfrndis_inf;

	ifs->fakefat32_fs.Driver_dir[0].memfile.file.name = ".";
	ifs->fakefat32_fs.Driver_dir[0].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.Driver_dir[1].memfile.file.name = "..";
	ifs->fakefat32_fs.Driver_dir[1].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.Driver_dir[2].memfile.file.name = "Windows";
	ifs->fakefat32_fs.Driver_dir[2].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.Driver_dir[2].memfile.d.child = (struct vsfile_memfile_t *)ifs->fakefat32_fs.Windows_dir;

	ifs->fakefat32_fs.LOSTDIR_dir[0].memfile.file.name = ".";
	ifs->fakefat32_fs.LOSTDIR_dir[0].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.LOSTDIR_dir[1].memfile.file.name = "..";
	ifs->fakefat32_fs.LOSTDIR_dir[1].memfile.file.attr = VSFILE_ATTR_DIRECTORY;

	ifs->fakefat32_fs.RECYCLEBIN_dir[0].memfile.file.name = ".";
	ifs->fakefat32_fs.RECYCLEBIN_dir[0].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.RECYCLEBIN_dir[1].memfile.file.name = "..";
	ifs->fakefat32_fs.RECYCLEBIN_dir[1].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.RECYCLEBIN_dir[2].memfile.file.name = "DESKTOP.INI";
	ifs->fakefat32_fs.RECYCLEBIN_dir[2].memfile.file.size = sizeof(Win_recycle_DESKTOP_INI) - 1;
	ifs->fakefat32_fs.RECYCLEBIN_dir[2].memfile.file.attr = VSFILE_ATTR_ARCHIVE | VSFILE_ATTR_READONLY;
	ifs->fakefat32_fs.RECYCLEBIN_dir[2].memfile.f.buff = (uint8_t *)Win_recycle_DESKTOP_INI;

	ifs->fakefat32_fs.SVI_dir[0].memfile.file.name = ".";
	ifs->fakefat32_fs.SVI_dir[0].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.SVI_dir[1].memfile.file.name = "..";
	ifs->fakefat32_fs.SVI_dir[1].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.SVI_dir[2].memfile.file.name = "IndexerVolumeGuid";
	ifs->fakefat32_fs.SVI_dir[2].memfile.file.size = sizeof(Win10_IndexerVolumeGuid);
	ifs->fakefat32_fs.SVI_dir[2].memfile.file.attr = VSFILE_ATTR_ARCHIVE | VSFILE_ATTR_READONLY | VSFILE_ATTR_SYSTEM | VSFILE_ATTR_HIDDEN,
	ifs->fakefat32_fs.SVI_dir[2].memfile.f.buff = (uint8_t *)Win10_IndexerVolumeGuid;
	ifs->fakefat32_fs.SVI_dir[3].memfile.file.name = "WPSettings.dat";
	ifs->fakefat32_fs.SVI_dir[3].memfile.file.size = sizeof(Win10_WPSettings_dat);
	ifs->fakefat32_fs.SVI_dir[3].memfile.file.attr = VSFILE_ATTR_ARCHIVE | VSFILE_ATTR_READONLY | VSFILE_ATTR_SYSTEM | VSFILE_ATTR_HIDDEN,
	ifs->fakefat32_fs.SVI_dir[3].memfile.f.buff = (uint8_t *)Win10_WPSettings_dat;

	ifs->fakefat32_fs.root_dir[0].memfile.file.name = "VSFDriver";
	ifs->fakefat32_fs.root_dir[0].memfile.file.attr = VSFILE_ATTR_VOLUMID;
	ifs->fakefat32_fs.root_dir[1].memfile.file.name = "LOST.DIR";
	ifs->fakefat32_fs.root_dir[1].memfile.file.attr = VSFILE_ATTR_DIRECTORY | VSFILE_ATTR_SYSTEM | VSFILE_ATTR_HIDDEN;
	ifs->fakefat32_fs.root_dir[1].memfile.d.child = (struct vsfile_memfile_t *)ifs->fakefat32_fs.LOSTDIR_dir;
	ifs->fakefat32_fs.root_dir[2].memfile.file.name = "$RECYCLE.BIN";
	ifs->fakefat32_fs.root_dir[2].memfile.file.attr = VSFILE_ATTR_DIRECTORY | VSFILE_ATTR_SYSTEM | VSFILE_ATTR_HIDDEN;
	ifs->fakefat32_fs.root_dir[2].memfile.d.child = (struct vsfile_memfile_t *)ifs->fakefat32_fs.RECYCLEBIN_dir;
	ifs->fakefat32_fs.root_dir[3].memfile.file.name = "System Volume Information";
	ifs->fakefat32_fs.root_dir[3].memfile.file.attr = VSFILE_ATTR_DIRECTORY | VSFILE_ATTR_SYSTEM | VSFILE_ATTR_HIDDEN;
	ifs->fakefat32_fs.root_dir[3].memfile.d.child = (struct vsfile_memfile_t *)ifs->fakefat32_fs.SVI_dir;
	ifs->fakefat32_fs.root_dir[4].memfile.file.name = "Driver";
	ifs->fakefat32_fs.root_dir[4].memfile.file.attr = VSFILE_ATTR_DIRECTORY;
	ifs->fakefat32_fs.root_dir[4].memfile.d.child = (struct vsfile_memfile_t *)ifs->fakefat32_fs.Driver_dir;

	// init fakefat32
	ifs->mal.fakefat32.sector_size = 512;
	ifs->mal.fakefat32.sector_number = 0x1000;
	ifs->mal.fakefat32.sectors_per_cluster = 8;
	ifs->mal.fakefat32.volume_id = 0xDEADBEEF;
	ifs->mal.fakefat32.disk_id = 0xBABECAFE;
	ifs->mal.fakefat32.root[0].memfile.file.name = "ROOT";
	ifs->mal.fakefat32.root[0].memfile.d.child = (struct vsfile_memfile_t *)ifs->fakefat32_fs.root_dir,

	// init mal
	ifs->mal.mal.drv = &fakefat32_mal_drv;
	ifs->mal.mal.param = &ifs->mal.fakefat32;
	ifs->mal.pbuffer[0] = ifs->mal.buffer[0];
	ifs->mal.pbuffer[1] = ifs->mal.buffer[1];

	// init file
	ifs->fs.memop.alloc_vfs = vsfos_vsfile_alloc_vfs;
	ifs->fs.memop.free_vfs = vsfos_vsfile_free_vfs;

	// init mal2scsi
	ifs->mal.scsistream.mbuf.count = dimof(ifs->mal.buffer);
	ifs->mal.scsistream.mbuf.size = sizeof(ifs->mal.buffer[0]);
	ifs->mal.scsistream.mbuf.buffer_list = ifs->mal.pbuffer;
	ifs->mal.mal2scsi.malstream.mal = &ifs->mal.mal;
	ifs->mal.mal2scsi.cparam.block_size = 512;
	ifs->mal.mal2scsi.cparam.removable = false;
	memcpy(ifs->mal.mal2scsi.cparam.vendor, "Simon   ", 8);
	memcpy(ifs->mal.mal2scsi.cparam.product, "VSFDriver       ", 16);
	memcpy(ifs->mal.mal2scsi.cparam.revision, "1.00", 4);
	ifs->mal.mal2scsi.cparam.type = SCSI_PDT_DIRECT_ACCESS_BLOCK;

	// init scsi device
	ifs->mal.lun[0].op = &vsf_mal2scsi_op;
	ifs->mal.lun[0].stream = (struct vsf_stream_t *)&ifs->mal.scsistream;
	ifs->mal.lun[0].param = &ifs->mal.mal2scsi;
	ifs->mal.scsi_dev.max_lun = 0;
	ifs->mal.scsi_dev.lun = ifs->mal.lun;

	// init rndis
	ifs->usbd.rndis.param.CDCACM.CDC.ep_notify = 1;
	ifs->usbd.rndis.param.CDCACM.CDC.ep_out = 2;
	ifs->usbd.rndis.param.CDCACM.CDC.ep_in = 2;
	ifs->usbd.rndis.param.mac.size = 6;
	ifs->usbd.rndis.param.mac.addr.s_addr64 = 0x0605040302E0;
	ifs->usbd.rndis.param.netif.macaddr.size = 6;
	ifs->usbd.rndis.param.netif.macaddr.addr.s_addr64 = 0x0E0D0C0B0AE0;
	ifs->usbd.rndis.param.cb.param = &ifs->usbd.rndis;
	ifs->usbd.rndis.param.cb.on_connect = vsfos_rndis_on_connect;
	if (0)
	{
		ifs->usbd.rndis.param.netif.ipaddr.size = 4;
		ifs->usbd.rndis.param.netif.ipaddr.addr.s_addr = 0x01202020;
		ifs->usbd.rndis.param.netif.netmask.size = 4;
		ifs->usbd.rndis.param.netif.netmask.addr.s_addr = 0x00FFFFFF;
		ifs->usbd.rndis.param.netif.gateway.size = 4;
		ifs->usbd.rndis.param.netif.gateway.addr.s_addr = 0x01202020;
	}

	// init cdc
	ifs->usbd.cdc.stream_tx.stream.op = &fifostream_op;
	ifs->usbd.cdc.stream_tx.mem.buffer.buffer = ifs->usbd.cdc.txbuff;
	ifs->usbd.cdc.stream_tx.mem.buffer.size = sizeof(ifs->usbd.cdc.txbuff);
	ifs->usbd.cdc.stream_rx.stream.op = &fifostream_op;
	ifs->usbd.cdc.stream_rx.mem.buffer.buffer = ifs->usbd.cdc.rxbuff;
	ifs->usbd.cdc.stream_rx.mem.buffer.size = sizeof(ifs->usbd.cdc.rxbuff);
	ifs->usbd.cdc.param.CDC.ep_notify = 3;
	ifs->usbd.cdc.param.CDC.ep_out = 4;
	ifs->usbd.cdc.param.CDC.ep_in = 4;
	ifs->usbd.cdc.param.CDC.stream_tx = (struct vsf_stream_t *)&ifs->usbd.cdc.stream_tx;
	ifs->usbd.cdc.param.CDC.stream_rx = (struct vsf_stream_t *)&ifs->usbd.cdc.stream_rx;
	ifs->usbd.cdc.param.line_coding.bitrate = 115200;
	ifs->usbd.cdc.param.line_coding.stopbittype = 0;
	ifs->usbd.cdc.param.line_coding.paritytype = 0;
	ifs->usbd.cdc.param.line_coding.datatype = 8;

	// init msc
	ifs->usbd.msc.param.ep_in = 5;
	ifs->usbd.msc.param.ep_out = 5;
	ifs->usbd.msc.param.scsi_dev = &ifs->mal.scsi_dev;

	// init usbd
	ifs->usbd.desc[0] = (struct vsfusbd_desc_filter_t)VSFUSBD_DESC_DEVICE(0, USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor));
	ifs->usbd.desc[1] = (struct vsfusbd_desc_filter_t)VSFUSBD_DESC_CONFIG(0, 0, USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor));
	ifs->usbd.desc[2] = (struct vsfusbd_desc_filter_t)VSFUSBD_DESC_STRING(0, 0, USB_StringLangID, sizeof(USB_StringLangID));
	ifs->usbd.desc[3] = (struct vsfusbd_desc_filter_t)VSFUSBD_DESC_STRING(0x0409, 1, USB_StringVendor, sizeof(USB_StringVendor));
	ifs->usbd.desc[4] = (struct vsfusbd_desc_filter_t)VSFUSBD_DESC_STRING(0x0409, 2, USB_StringProduct, sizeof(USB_StringProduct));
	ifs->usbd.desc[5] = (struct vsfusbd_desc_filter_t)VSFUSBD_DESC_STRING(0x0409, 3, USB_StringSerial, sizeof(USB_StringSerial));
	ifs->usbd.desc[6] = (struct vsfusbd_desc_filter_t)VSFUSBD_DESC_STRING(0x0409, 4, RNDIS_StringFunc, sizeof(RNDIS_StringFunc));
	ifs->usbd.desc[7] = (struct vsfusbd_desc_filter_t)VSFUSBD_DESC_STRING(0x0409, 5, CDC_StringFunc, sizeof(CDC_StringFunc));
	ifs->usbd.desc[8] = (struct vsfusbd_desc_filter_t)VSFUSBD_DESC_STRING(0x0409, 6, MSC_StringFunc, sizeof(MSC_StringFunc));
	ifs->usbd.ifaces[0].class_protocol = (struct vsfusbd_class_protocol_t *)&vsfusbd_RNDISControl_class;
	ifs->usbd.ifaces[0].protocol_param = &ifs->usbd.rndis.param;
	ifs->usbd.ifaces[1].class_protocol = (struct vsfusbd_class_protocol_t *)&vsfusbd_RNDISData_class;
	ifs->usbd.ifaces[1].protocol_param = &ifs->usbd.rndis.param;
	ifs->usbd.ifaces[2].class_protocol = (struct vsfusbd_class_protocol_t *)&vsfusbd_CDCACMControl_class;
	ifs->usbd.ifaces[2].protocol_param = &ifs->usbd.cdc.param;
	ifs->usbd.ifaces[3].class_protocol = (struct vsfusbd_class_protocol_t *)&vsfusbd_CDCACMData_class;
	ifs->usbd.ifaces[3].protocol_param = &ifs->usbd.cdc.param;
	ifs->usbd.ifaces[4].class_protocol = (struct vsfusbd_class_protocol_t *)&vsfusbd_MSCBOT_class;
	ifs->usbd.ifaces[4].protocol_param = &ifs->usbd.msc.param;
	ifs->usbd.config[0].num_of_ifaces = dimof(ifs->usbd.ifaces);
	ifs->usbd.config[0].iface = ifs->usbd.ifaces;
	ifs->usbd.device.num_of_configuration = dimof(ifs->usbd.config);
	ifs->usbd.device.config = ifs->usbd.config;
	ifs->usbd.device.desc_filter = ifs->usbd.desc;
	ifs->usbd.device.device_class_iface = 0;
	ifs->usbd.device.drv = vsfhal_usbd_if;
	ifs->usbd.device.int_priority = 0x01;

	// init telnetd
	ifs->tcpip.telnetd.telnetd.port = 23;
	ifs->tcpip.telnetd.telnetd.session_num = dimof(ifs->tcpip.telnetd.sessions);
	ifs->tcpip.telnetd.sessions[0].session.stream_tx = (struct vsf_stream_t *)&ifs->tcpip.telnetd.sessions[0].stream_tx;
	ifs->tcpip.telnetd.sessions[0].session.stream_rx = (struct vsf_stream_t *)&ifs->tcpip.telnetd.sessions[0].stream_rx;
	ifs->tcpip.telnetd.sessions[0].stream_tx.stream.op = &fifostream_op;
	ifs->tcpip.telnetd.sessions[0].stream_tx.mem.buffer.buffer = (uint8_t *)ifs->tcpip.telnetd.sessions[0].txbuff;
	ifs->tcpip.telnetd.sessions[0].stream_tx.mem.buffer.size = sizeof(ifs->tcpip.telnetd.sessions[0].txbuff);
	ifs->tcpip.telnetd.sessions[0].stream_rx.stream.op = &fifostream_op;
	ifs->tcpip.telnetd.sessions[0].stream_rx.mem.buffer.buffer = (uint8_t *)ifs->tcpip.telnetd.sessions[0].rxbuff;
	ifs->tcpip.telnetd.sessions[0].stream_rx.mem.buffer.size = sizeof(ifs->tcpip.telnetd.sessions[0].rxbuff);

	// init tcpip
	ifs->tcpip.mem_op.get_buffer = vsfos_vsfip_get_buffer;
	ifs->tcpip.mem_op.release_buffer = vsfos_vsfip_release_buffer;
	ifs->tcpip.mem_op.get_socket = vsfos_vsfip_get_socket;
	ifs->tcpip.mem_op.release_socket = vsfos_vsfip_release_socket;
	ifs->tcpip.mem_op.get_tcppcb = vsfos_vsfip_get_tcppcb;
	ifs->tcpip.mem_op.release_tcppcb = vsfos_vsfip_release_tcppcb;

	// init shell
	ifs->shell.echo = true;
	ifs->shell.stream_tx = (struct vsf_stream_t *)&ifs->usbd.cdc.stream_tx;
	ifs->shell.stream_rx = (struct vsf_stream_t *)&ifs->usbd.cdc.stream_rx;

	ifs->pt.user_data = ifs;
	ifs->pt.thread = vsfos_thread;
	module->ifs = ifs;

	vsfsm_evtq_init(&ifs->pendsvq);
	vsfsm_evtq_set(&ifs->pendsvq);
	vsfsm_pt_init(&ifs->sm, &ifs->pt);

	vsfhal_core_pendsv_config(vsfos_on_pendsv, &ifs->pendsvq);
	vsf_leave_critical();

	vsfsm_evtq_set(NULL);
	while (1)
	{
		// no thread runs in mainq, just sleep in main loop
		vsfhal_core_sleep(0);
	}
}