Exemplo n.º 1
0
static vsf_err_t vsfusbd_HID_class_poll(uint8_t iface, 
										struct vsfusbd_device_t *device)
{
	struct vsfusbd_config_t *config = &device->config[device->configuration];
	struct vsfusbd_HID_param_t *param = 
		(struct vsfusbd_HID_param_t *)config->iface[iface].protocol_param;
	struct vsfusbd_HID_report_t *report;
	uint8_t ep = param->ep_in;
	struct vsfusbd_transact_t *transact = &device->IN_transact[ep];
	struct vsf_buffer_t *buffer = &transact->tbuffer.buffer;
	
	if (NULL == param)
	{
		return VSFERR_FAIL;
	}
	
	report = &param->reports[param->poll_report_idx];
	buffer->buffer = report->buffer.buffer;
	buffer->size = report->buffer.size;
	transact->callback.callback = NULL;
	transact->pkt.in.zlp = true;
	switch (report->type)
	{
	case USB_HID_REPORT_TYPE_INPUT:
		// TODO: process multi-report and idle, need 1 ms systick module
		if (!vsfusbd_ep_send_nb_isready(device, ep))
		{
			if (vsfusbd_HID_class_update_report(report, &param->temp_buffer))
			{
				return VSFERR_FAIL;
			}
			transact->tbuffer.buffer = param->temp_buffer;
			if (vsfusbd_ep_send_nb(device, ep))
			{
				return VSFERR_FAIL;
			}
			param->poll_report_idx++;
			if (param->poll_report_idx >= param->num_of_report)
			{
				param->poll_report_idx = 0;
			}
		}
		break;
	case USB_HID_REPORT_TYPE_OUTPUT:
		break;
	default:
		break;
	}
	
	return VSFERR_NONE;
}
Exemplo n.º 2
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->output_state = HID_OUTPUT_STATE_WAIT;
		param->busy = false;
		param->num_of_INPUT_report = 0;
		param->num_of_OUTPUT_report = 0;
		param->num_of_FEATURE_report = 0;
		for(i = 0; i < param->num_of_report; i++)
		{
			param->reports[i].pos = 0;
			param->reports[i].idle_cnt = 0;
			param->reports[i].changed = true;
			switch (param->reports[i].type)
			{
			case USB_HID_REPORT_OUTPUT:
				param->num_of_OUTPUT_report++;
				break;
			case USB_HID_REPORT_INPUT:
				param->num_of_INPUT_report++;
				break;
			case USB_HID_REPORT_FEATURE:
				param->num_of_FEATURE_report++;
				break;
			}
		}
		
		// enable timer
		param->timer4ms.sm = &param->iface->sm;
		param->timer4ms.evt = VSFUSBD_HID_EVT_TIMER4MS;
		param->timer4ms.interval = 4;
		vsftimer_register(&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_TYPE_INPUT) &&
					(report->idle != 0))
				{
					report->idle_cnt++;
				}
			}
			if (param->busy)
			{
				break;
			}
		}
		// fall through
	case VSFUSBD_HID_EVT_INREPORT:
		{
			uint8_t ep = param->ep_in;
			struct vsfusbd_transact_t *transact = &device->IN_transact[ep];
			struct vsfusbd_HID_report_t *report;
			bool busy = false;
			uint8_t i;
			
			for (i = 0; i < param->num_of_report; i++)
			{
				report = &param->reports[i];
				if ((report->type == USB_HID_REPORT_TYPE_INPUT) &&
					(report->changed || ((report->idle != 0) &&
							(report->idle_cnt >= report->idle))))
				{
					report->idle_cnt = 0;
					transact->tbuffer.buffer = report->buffer;
					transact->callback.callback = vsfusbd_HID_INREPORT_callback;
					transact->callback.param = param;
					vsfusbd_ep_send_nb(device, ep);
					busy = true;
					break;
				}
			}
			param->busy = busy;
		}
		break;
	}
	
	return NULL;
}