Example #1
0
static vsf_err_t vsfusbd_MSCBOT_ErrHandler(struct vsfusbd_device_t *device,
			struct vsfusbd_MSCBOT_param_t *param,  uint8_t error)
{
	param->CSW.dCSWStatus = error;

	// OUT:	NACK(don't enable_OUT, if OUT is enabled, it will be disabled after data is sent)
	// IN:	if (dCBWDataTransferLength > 0)
	// 		  send_ZLP
	// 		send_CSW
	if (((param->CBW.bmCBWFlags & USBMSC_CBWFLAGS_DIR_MASK) ==
				USBMSC_CBWFLAGS_DIR_IN) &&
		(param->CBW.dCBWDataTransferLength > 0))
	{
		if (param->scsi_transact != NULL)
		{
			param->scsi_transact->data_size = 0;
		}

		param->transact.ep = param->ep_in;
		param->transact.data_size = 0;
		param->transact.stream = NULL;
		param->transact.cb.on_finish = vsfusbd_MSCBOT_on_data_finish;
		param->transact.cb.param = param;
		return vsfusbd_ep_send(param->device, &param->transact);
	}
	else
	{
		vsfusbd_MSCBOT_SendCSW(device, param);
	}

	return VSFERR_NONE;
}
Example #2
0
static vsf_err_t vsfusbd_MSCBOT_SendCSW(struct vsfusbd_device_t *device,
							struct vsfusbd_MSCBOT_param_t *param)
{
	struct USBMSC_CSW_t *CSW = &param->CSW;
	uint32_t remain_size;

	CSW->dCSWSignature = SYS_TO_LE_U32(USBMSC_CSW_SIGNATURE);
	CSW->dCSWTag = param->CBW.dCBWTag;
	remain_size = param->CBW.dCBWDataTransferLength;
	if (param->scsi_transact != NULL)
	{
		remain_size -= param->scsi_transact->data_size;
		vsfscsi_release_transact(param->scsi_transact);
	}
	CSW->dCSWDataResidue = SYS_TO_LE_U32(remain_size);

	param->bufstream.mem.buffer.buffer = (uint8_t *)&param->CSW;
	param->bufstream.mem.buffer.size = sizeof(param->CSW);
	param->bufstream.mem.read = true;
	param->bufstream.stream.op = &bufstream_op;
	STREAM_INIT(&param->bufstream);

	param->transact.ep = param->ep_in;
	param->transact.data_size = sizeof(param->CSW);
	param->transact.stream = (struct vsf_stream_t *)&param->bufstream;
	param->transact.cb.on_finish = vsfusbd_MSCBOT_on_idle;
	param->transact.cb.param = param;
	return vsfusbd_ep_send(param->device, &param->transact);
}
Example #3
0
static void vsfusbd_CDCData_on_in(void *p)
{
	struct vsfusbd_CDC_param_t *param = (struct vsfusbd_CDC_param_t *)p;
	struct vsf_stream_t *stream = param->stream_tx;
	uint32_t size;

	size = stream_get_data_size(stream);
	if (size > 0)
	{
		param->IN_transact.data_size = size;
		param->IN_transact.stream = param->stream_tx;
		param->IN_transact.zlp = true;
		// stream->callback_rx.on_inout will be overwritten
		vsfusbd_ep_send(param->device, &param->IN_transact);
	}
}
Example #4
0
static vsf_err_t versaloon_poll(uint8_t iface, struct vsfusbd_device_t *device)
{
    struct vsfusbd_config_t *config = &device->config[device->configuration];
    struct vsfusbd_Versaloon_param_t *param =
        (struct vsfusbd_Versaloon_param_t *)config->iface[iface].protocol_param;

    if(cmd_len & 0x80000000)
    {
        // A valid USB package has been received
        LED_USB_ON();

        ProcessCommand(&buffer_out[0], cmd_len & 0xFFFF);
        if(rep_len > 0)
        {
            // indicate reply data is valid
            rep_len |= 0x80000000;
        }
        else
        {
            // no data to send, set cmd_len to 0
            cmd_len = 0;
        }
        count_out = 0;				// set USB receive pointer to 0

        if(rep_len & 0x80000000)	// there is valid data to be sent to PC
        {
            struct vsfusbd_transact_t *transact =
                    &device->IN_transact[param->ep_in];
            struct vsf_buffer_t *buffer = &transact->tbuffer.buffer;

            buffer->buffer = buffer_out;
            buffer->size = rep_len & 0xFFFF;
            transact->pkt.in.zlp = (rep_len & VERSALOON_REP_ZLP) ? true : false;
            transact->callback.callback = NULL;
            vsfusbd_ep_send(device, param->ep_in);

            // reset command length and reply length for next command
            cmd_len = 0;
            rep_len = 0;
        }

        LED_USB_OFF();
    }

    return VSFERR_NONE;
}
Example #5
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;
}
Example #6
0
static void vsfusbd_MSCBOT_on_cbw(void *p)
{
	struct vsfusbd_MSCBOT_param_t *param = (struct vsfusbd_MSCBOT_param_t *)p;
	struct vsfusbd_device_t *device = param->device;
	struct vsfscsi_lun_t *lun;

	if (param->transact.data_size ||
		(param->CBW.dCBWSignature != USBMSC_CBW_SIGNATURE) ||
		(param->CBW.bCBWCBLength < 1) || (param->CBW.bCBWCBLength > 16))
	{
		vsfusbd_MSCBOT_on_idle(param);
		return;
	}

	if (param->CBW.bCBWLUN > param->scsi_dev.max_lun)
	{
	reply_failure:
		vsfusbd_MSCBOT_ErrHandler(device, param, USBMSC_CSW_FAIL);
		return;
	}

	param->CSW.dCSWStatus = USBMSC_CSW_OK;
	lun = &param->scsi_dev.lun[param->CBW.bCBWLUN];
	if (vsfscsi_execute(lun, param->CBW.CBWCB))
	{
		goto reply_failure;
	}

	if (param->CBW.dCBWDataTransferLength)
	{
		struct vsfusbd_transact_t *transact = &param->transact;

		if (!lun->transact.data_size)
		{
			goto reply_failure;
		}
		param->scsi_transact = &lun->transact;
		transact->data_size = param->scsi_transact->data_size;
		transact->stream = param->scsi_transact->stream;
		transact->cb.on_finish = vsfusbd_MSCBOT_on_data_finish;
		transact->cb.param = param;

		if ((param->CBW.bmCBWFlags & USBMSC_CBWFLAGS_DIR_MASK) ==
					USBMSC_CBWFLAGS_DIR_IN)
		{
			transact->ep = param->ep_in;
			vsfusbd_ep_send(param->device, transact);
		}
		else
		{
			transact->ep = param->ep_out;
			vsfusbd_ep_recv(param->device, transact);
		}
	}
	else
	{
		if (param->scsi_transact->data_size && param->scsi_transact)
		{
			vsfscsi_cancel_transact(param->scsi_transact);
			param->scsi_transact = NULL;
		}
		vsfusbd_MSCBOT_SendCSW(device, param);
	}
}