module USB_Demo {

import from USB_Types all;
import from USB_Templates all;
import from USB_PortType all;
import from USB_PortTypes all;
import from USB_Component all;

type component Demo_CT extends USB_CT {
}

modulepar {
	hexstring mp_vendor_id := '1d50'H;
	hexstring mp_product_id := '6141'H;
}

function f_init_usb() runs on USB_CT {
	f_usb_init_vid_pid(mp_vendor_id, mp_product_id);
}



testcase TC_get_desc_device() runs on Demo_CT {
	f_init_usb();
	var USB_StandardDescriptors descs;
	descs := f_usb_get_desc_std(USB_DescriptorType_DEVICE, 0, 256);
	/* FIXME: do some verifications and set veridct */
	setverdict(pass);
}
testcase TC_get_desc_device_illegal_idx() runs on Demo_CT {
	f_init_usb();
	f_usb_get_desc_exp_fail(USB_DescriptorType_DEVICE, 23, 256);
}
testcase TC_get_desc_config() runs on Demo_CT {
	f_init_usb();
	var USB_StandardDescriptors descs;
	descs := f_usb_get_desc_std(USB_DescriptorType_CONFIGURATION, 0, 256);
	/* FIXME: do some verifications and set veridct */
	setverdict(pass);
}
testcase TC_get_desc_config_illegal_idx() runs on Demo_CT {
	f_init_usb();
	f_usb_get_desc_exp_fail(USB_DescriptorType_CONFIGURATION, 23, 256);
}
testcase TC_get_config() runs on Demo_CT {
	f_init_usb();
	var integer cfg_num := f_usb_get_config();
	if (cfg_num == 0) {
		setverdict(pass);
	} else {
		setverdict(fail, "unexpected configuration: ", cfg_num);
	}
}
testcase TC_get_interface() runs on Demo_CT {
	f_init_usb();
	var integer altsett_num := f_usb_get_interface(0);
	if (altsett_num == 0) {
		setverdict(pass);
	} else {
		setverdict(fail, "unexpected interface altsetting: ", altsett_num);
	}
}
testcase TC_get_status() runs on Demo_CT {
	f_init_usb();

	/* valid get_status on device */
	f_usb_get_status(RequestRecipient_Device, 0);

	/* valid get_status on interface */
	f_usb_get_status(RequestRecipient_Interface, 0);

	/* valid get_status on endpoint */
	f_usb_get_status(RequestRecipient_Endpoint, 1);
}
testcase TC_get_status_invalid() runs on Demo_CT {
	f_init_usb();

	f_usb_dev_req_exp_fail(ts_DevReq_GET_STATUS(RequestRecipient_Device, 1));

	/* Gets blocked by kernel USB? */
	//f_usb_dev_req_exp_fail(ts_DevReq_GET_STATUS(RequestRecipient_Interface, 100));
	//f_usb_dev_req_exp_fail(ts_DevReq_GET_STATUS(RequestRecipient_Endpoint, 100));
}




testcase TC_foobar() runs on Demo_CT {
	var USB_result res;

	f_init_usb();

	var USB_descriptor desc;
	USB.send(ts_USB_get_device_descriptor(g_dev_hdl));
	USB.receive(tr_USB_descriptor(g_dev_hdl, result_code := 0)) -> value desc {
		log("Received device descriptor ", desc);
		var USB_StandardDescriptor udesc := dec_USB_StandardDescriptor(desc.data);
		log("Decoded device descriptor ", udesc);
	}

	USB.send(ts_USB_get_active_config_descriptor(g_dev_hdl));
	USB.receive(tr_USB_descriptor(g_dev_hdl, result_code := 0)) -> value desc {
		log("Received config descriptor ", desc);
		var USB_StandardDescriptor udesc := dec_USB_StandardDescriptor(desc.data);
		log("Decoded config descriptor ", udesc);
	}

/*
	var USB_DeviceRequest gcfg := {
		req_type := {
			direction := Device_to_Host,
			req_type := RequestType_Standard,
			recipient := RequestRecipient_Device
		},
		bRequest := '06'O,
		wValue := hex2int('0200'H),
		wIndex := 0,
		wLength := 100
	};
	var octetstring gcfg_enc := enc_USB_DeviceRequest(gcfg);
	var USB_transfer xfer := {
		device_hdl := g_dev_hdl,
		transfer_hdl := 99,
		endpoint := 0,
		ttype := USB_TRANSFER_TYPE_CONTROL,
		data := gcfg_enc,
		timeout_msec := 1000
	};
	USB.send(xfer);
*/
	USB.send(ts_UsbXfer_DevReq(ts_DevReq_GET_DESCRIPTOR(USB_DescriptorType_CONFIGURATION, 0, 256),
g_dev_hdl, 99));
	USB.receive(USB_transfer_compl:?);

	USB.send(ts_USB_claim_interface(g_dev_hdl, 0, 25));
	USB.receive(USB_result:?) -> value res { log("Received ", res); }
}


control {
	execute( TC_get_desc_device() );
	execute( TC_get_desc_device_illegal_idx() );
	execute( TC_get_desc_config() );
	execute( TC_get_desc_config_illegal_idx() );
	execute( TC_get_config() );
	execute( TC_get_interface() );
	execute( TC_get_status() );
	execute( TC_get_status_invalid() );
}

}
