Пример #1
0
vsf_err_t vsf_malstream_read(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_tx.param = malstream;
	stream->callback_tx.on_inout = vsf_malstream_on_inout;
	stream->callback_tx.on_connect = NULL;
	stream->callback_tx.on_disconnect = NULL;
	stream_connect_tx(stream);

	malstream->pt.thread = vsf_malstream_read_thread;
	malstream->pt.user_data = malstream;
	return vsfsm_pt_init(&malstream->sm, &malstream->pt);
}
Пример #2
0
void vsfusbd_CDCData_connect(struct vsfusbd_CDC_param_t *param)
{
	stream_connect_tx(param->stream_rx);
	stream_connect_rx(param->stream_tx);
}
Пример #3
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;
}
Пример #4
0
static struct vsfsm_state_t *
vsfusbd_HID_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
	struct vsfusbd_HID_param_t *param =
						(struct vsfusbd_HID_param_t *)sm->user_data;
	struct vsfusbd_device_t *device = param->device;
	uint8_t i;

	switch (evt)
	{
	case VSFSM_EVT_INIT:
		if (param->ep_out != 0)
		{
			vsfusbd_set_OUT_handler(device, param->ep_out,
										vsfusbd_HID_OUT_hanlder);
			device->drv->ep.enable_OUT(param->ep_out);
		}

		param->bufstream.mem.read = true;
		param->bufstream.stream.op = &bufstream_op;
		param->bufstream.stream.callback_tx.on_connect = NULL;
		param->bufstream.stream.callback_tx.on_disconnect = NULL;
		param->bufstream.stream.callback_tx.on_inout = NULL;

		param->output_state = HID_OUTPUT_STATE_WAIT;
		param->busy = false;
		for(i = 0; i < param->num_of_report; i++)
		{
			struct vsfusbd_HID_report_t *report = &param->reports[i];

			report->pos = 0;
			report->idle_cnt = 0;
			report->changed = true;
		}

		// enable timer
		param->timer4ms.sm = sm;
		param->timer4ms.evt = VSFUSBD_HID_EVT_TIMER4MS;
		param->timer4ms.interval = 4;
		param->timer4ms.trigger_cnt = -1;
		vsftimer_enqueue(&param->timer4ms);
		break;
	case VSFUSBD_HID_EVT_TIMER4MS:
		{
			struct vsfusbd_HID_report_t *report;
			uint8_t i;

			for (i = 0; i < param->num_of_report; i++)
			{
				report = &param->reports[i];
				if ((report->type == USB_HID_REPORT_INPUT) &&
					(report->idle != 0))
				{
					report->idle_cnt++;
				}
			}
			if (param->busy)
			{
				break;
			}
		}
		// fall through
	case VSFUSBD_HID_EVT_INREPORT:
		{
			struct vsfusbd_transact_t *transact = &param->IN_transact;
			struct vsfusbd_HID_report_t *report;
			uint8_t i;

			for (i = 0; i < param->num_of_report; i++)
			{
				report = &param->reports[i];
				if ((report->type == USB_HID_REPORT_INPUT) &&
					(report->changed || ((report->idle != 0) &&
							(report->idle_cnt >= report->idle))))
				{
					param->bufstream.mem.buffer = report->buffer;
					stream_init(&param->stream);
					stream_connect_tx(&param->stream);

					transact->ep = param->ep_in;
					transact->data_size = report->buffer.size;
					transact->stream = &param->stream;
					transact->zlp = false;
					transact->cb.on_finish = vsfusbd_HID_INREPORT_callback;
					transact->cb.param = param;
					vsfusbd_ep_send(device, transact);

					report->changed = false;
					report->idle_cnt = 0;
					param->busy = true;
					break;
				}
			}
		}
		break;
	}

	return NULL;
}
Пример #5
0
static struct vsfsm_state_t *
vsfshell_evt_handler(struct vsfsm_t *sm, vsfsm_evt_t evt)
{
	struct vsfshell_t *shell = (struct vsfshell_t *)sm->user_data;
	
	switch (evt)
	{
	case VSFSM_EVT_INIT:
		shell->prompted = false;
		shell->output_interrupted = false;
		shell->tbuffer.buffer.buffer = (uint8_t *)shell->cmd_buff;
		shell->tbuffer.buffer.size = sizeof(shell->cmd_buff);
		shell->tbuffer.position = 0;
		vsfsm_crit_init(&shell->output_crit, VSFSHELL_EVT_OUTPUT_CRIT_AVAIL);
		
		shell->stream_rx->callback_rx.param = shell;
		shell->stream_rx->callback_rx.on_inout = vsfshell_streamrx_on_in;
		shell->stream_rx->callback_rx.on_connect = vsfshell_streamrx_on_txconn;
		shell->stream_tx->callback_tx.param = shell;
		shell->stream_tx->callback_tx.on_inout = vsfshell_streamtx_on_out;
		shell->stream_tx->callback_tx.on_connect = vsfshell_streamtx_on_rxconn;
		
		// shell->output_pt is only called by shell->input_pt
		shell->output_pt.thread = (vsfsm_pt_thread_t)vsfshell_output_thread;
		shell->output_pt.sm = sm;
		shell->output_pt.user_data = shell;
		// shell->input_pt is used to hanlde the events from stream_rx
		shell->input_pt.thread = vsfshell_input_thread;
		shell->input_pt.sm = sm;
		shell->input_pt.user_data = shell;
		shell->input_pt.state = 0;
		shell->input_pt.thread(&shell->input_pt, VSFSM_EVT_INIT);
		// default input sm is shell itself
		shell->input_sm = &shell->sm;
		
		stream_connect_rx(shell->stream_rx);
		stream_connect_tx(shell->stream_tx);
		break;
	case VSFSHELL_EVT_STREAMRX_ONCONN:
		break;
	case VSFSHELL_EVT_STREAMTX_ONCONN:
		// pass to shell->input_pt
		shell->input_pt.thread(&shell->input_pt, evt);
		break;
	case VSFSHELL_EVT_STREAMRX_ONIN:
		if (shell->input_sm == &shell->sm)
		{
			// pass to shell->input_pt
			shell->input_pt.thread(&shell->input_pt, evt);
		}
		else if (shell->input_sm != NULL)
		{
			vsfsm_post_evt(shell->input_sm, evt);
		}
		break;
	case VSFSHELL_EVT_STREAMTX_ONOUT:
		if (shell->output_sm == &shell->sm)
		{
			// pass to shell->input_pt
			shell->input_pt.thread(&shell->input_pt, evt);
		}
		else if (shell->output_sm != NULL)
		{
			vsfsm_post_evt(shell->output_sm, evt);
		}
		break;
	}
	
	return NULL;
}
Пример #6
0
static vsf_err_t vsf_mal2scsi_execute(struct vsfscsi_lun_t *lun, uint8_t *CDB,
							uint8_t CDB_size, uint32_t size)
{
	struct vsf_mal2scsi_t *mal2scsi = (struct vsf_mal2scsi_t *)lun->param;
	struct vsfscsi_transact_t *transact = &lun->dev->transact;
	struct vsfmal_t *mal = mal2scsi->malstream.mal;
	uint8_t group_code = CDB[0] & 0xE0, cmd_code = CDB[0] & 0x1F;
	uint8_t *pbuf;

	if (transact->lun != NULL)
	{
		return VSFERR_FAIL;
	}

	// check user_handler first
	if (mal2scsi->vendor_handlers != NULL)
	{
		struct vsfscsi_handler_t *handler =
				vsfscsi_get_handler(mal2scsi->vendor_handlers, CDB[0]);
		if (handler != NULL)
		{
			return handler->handler(lun, CDB);
		}
	}

	if (!mal2scsi->malstream.mal_ready || (transact->lun != NULL))
	{
		goto exit_not_ready;
	}

	switch (group_code)
	{
	case SCSI_GROUPCODE6:
		switch (cmd_code)
		{
		case SCSI_CMDCODE_MODE_SELECT:
		case SCSI_CMDCODE_TEST_UNIT_READY:
		case SCSI_CMDCODE_VERIFY:
		case SCSI_CMDCODE_FORMAT_UNIT:
		case SCSI_CMDCODE_START_STOP_UNIT:
		case SCSI_CMDCODE_ALLOW_MEDIUM_REMOVAL:
			break;
		case SCSI_CMDCODE_REQUEST_SENSE:
			pbuf = vsf_mal2scsi_prepare_transact(lun, 18, false, true);
			if (NULL == pbuf)
			{
				goto exit_not_ready;
			}

			pbuf[0] = 0x70;
			pbuf[2] = lun->sensekey;
			pbuf[7] = 0x0A;
			pbuf[12] = lun->asc;
			transact->data_size = min(CDB[4], 18);
			break;
		case SCSI_CMDCODE_READ:
			transact->LBA = GET_BE_U16(&CDB[2]);
			transact->data_size = CDB[4];
			goto do_mal_read;
			break;
		case SCSI_CMDCODE_WRITE:
			transact->LBA = GET_BE_U16(&CDB[2]);
			transact->data_size = CDB[4];
			goto do_mal_write;
			break;
		case SCSI_CMDCODE_INQUIRY:
			if (CDB[1] & 1)
			{
				// When the EVPD bit is set to one,
				// the PAGE CODE field specifies which page of
				// vital product data information the device server shall return
				if (CDB[2] != 0)
				{
					goto exit_invalid_field_in_command;
				}

				// 0x00: Supported VPD Pages
				pbuf = vsf_mal2scsi_prepare_transact(lun, 5, false, true);
				if (NULL == pbuf)
				{
					goto exit_not_ready;
				}
			}
			else
			{
				struct vsf_mal2scsi_cparam_t *cparam =
							(struct vsf_mal2scsi_cparam_t *)&mal2scsi->cparam;

				if (CDB[2] != 0)
				{
					// If the PAGE CODE field is not set to zero
					// when the EVPD bit is set to zero,
					// the command shall be terminated with CHECK CONDITION status,
					// with the sense key set to ILLEGAL REQUEST,
					// and the additional sense code set to INVALID FIELD IN CDB.
					goto exit_invalid_field_in_command;
				}

				// If the EVPD bit is set to zero,
				// the device server shall return the standard INQUIRY data.
				pbuf = vsf_mal2scsi_prepare_transact(lun, 36, false, true);
				if (NULL == pbuf)
				{
					goto exit_not_ready;
				}

				pbuf[0] = cparam->type;
				if (cparam->removable)
				{
					pbuf[1] = 0x80;
				}
				pbuf[3] = 2;
				pbuf[4] = 31;
				pbuf += 8;
				memcpy(pbuf, cparam->vendor, sizeof(cparam->vendor));
				pbuf += sizeof(cparam->vendor);
				memcpy(pbuf, cparam->product, sizeof(cparam->product));
				pbuf += sizeof(cparam->product);
				memcpy(pbuf, cparam->revision, sizeof(cparam->revision));
			}
			break;
		case SCSI_CMDCODE_MODE_SENSE:
			pbuf = vsf_mal2scsi_prepare_transact(lun, 4, false, true);
			if (NULL == pbuf)
			{
				goto exit_not_ready;
			}

			pbuf[0] = 3;
			break;
		default:
			goto exit_invalid_command;
		}
		break;
	case SCSI_GROUPCODE10_1:
		switch (cmd_code)
		{
		case SCSI_CMDCODE_READ_FORMAT_CAPACITIES:
			pbuf = vsf_mal2scsi_prepare_transact(lun, 12, false, true);
			if (NULL == pbuf)
			{
				goto exit_not_ready;
			}

			pbuf[3] = 8;
			SET_BE_U32(&pbuf[4], mal->cap.block_num);
			SET_BE_U32(&pbuf[8], mal->cap.block_size);
			pbuf[8] = 2;
			break;
		case SCSI_CMDCODE_READ_CAPACITY:
			pbuf = vsf_mal2scsi_prepare_transact(lun, 8, false, true);
			if (NULL == pbuf)
			{
				goto exit_not_ready;
			}

			SET_BE_U32(&pbuf[0], mal->cap.block_num - 1);
			SET_BE_U32(&pbuf[4], mal->cap.block_size);
			break;
		case SCSI_CMDCODE_READ:
			transact->LBA = GET_BE_U32(&CDB[2]);
			transact->data_size = GET_BE_U16(&CDB[7]);
			goto do_mal_read;
			break;
		case SCSI_CMDCODE_WRITE:
			transact->LBA = GET_BE_U32(&CDB[2]);
			transact->data_size = GET_BE_U16(&CDB[7]);
			goto do_mal_write;
			break;
		default:
			goto exit_invalid_command;
		}
		break;
	case SCSI_GROUPCODE10_2:
		switch (cmd_code)
		{
		case SCSI_CMDCODE_MODE_SELECT:
			break;
		case SCSI_CMDCODE_MODE_SENSE:
			break;
		default:
			goto exit_invalid_command;
		}
		break;
	case SCSI_GROUPCODE16:
		switch (cmd_code)
		{
		case SCSI_CMDCODE_READ:
			transact->LBA = GET_BE_U64(&CDB[2]);
			transact->data_size = GET_BE_U32(&CDB[10]);

		do_mal_read:
			transact->LBA *= mal->cap.block_size;
			transact->data_size *= mal->cap.block_size;
			pbuf = vsf_mal2scsi_prepare_transact(lun, transact->data_size,
													false, false);
			if (NULL == pbuf)
			{
				goto exit_not_ready;
			}

			vsf_malstream_read(&mal2scsi->malstream, transact->LBA,
									transact->data_size);
			break;
		case SCSI_CMDCODE_WRITE:
			transact->LBA = GET_BE_U64(&CDB[2]);
			transact->data_size = GET_BE_U32(&CDB[10]);

		do_mal_write:
			transact->LBA *= mal->cap.block_size;
			transact->data_size *= mal->cap.block_size;
			pbuf = vsf_mal2scsi_prepare_transact(lun, transact->data_size,
													true, false);
			if (NULL == pbuf)
			{
				goto exit_not_ready;
			}

			vsf_malstream_write(&mal2scsi->malstream, transact->LBA,
									transact->data_size);
			break;
		default:
			goto exit_invalid_command;
		}
		break;
	case SCSI_GROUPCODE12:
		switch (cmd_code)
		{
		case SCSI_CMDCODE_READ:
			transact->LBA = GET_BE_U32(&CDB[2]);
			transact->data_size = GET_BE_U32(&CDB[6]);
			goto do_mal_read;
			break;
		case SCSI_CMDCODE_WRITE:
			transact->LBA = GET_BE_U32(&CDB[2]);
			transact->data_size = GET_BE_U32(&CDB[6]);
			goto do_mal_write;
			break;
		default:
			goto exit_invalid_command;
		}
		break;
	default:
		goto exit_invalid_command;
	}

	lun->sensekey = SCSI_SENSEKEY_NO_SENSE;
	lun->asc = SCSI_ASC_NONE;
	if (transact->lun->stream != NULL)
	{
		if (transact->lun->stream->op == &bufstream_op)
		{
			stream_connect_tx(transact->lun->stream);
		}
	}
	return VSFERR_NONE;
exit_invalid_command:
	lun->sensekey = SCSI_SENSEKEY_ILLEGAL_REQUEST;
	lun->asc = SCSI_ASC_INVALID_COMMAND;
	return VSFERR_FAIL;
exit_invalid_field_in_command:
	lun->sensekey = SCSI_SENSEKEY_ILLEGAL_REQUEST;
	lun->asc = SCSI_ASC_INVALID_FIELD_IN_COMMAND;
	return VSFERR_FAIL;
exit_not_ready:
	lun->sensekey = SCSI_SENSEKEY_NOT_READY;
	lun->asc = SCSI_ASC_NONE;
	return VSFERR_FAIL;
}