import unittest
import usbtest
import usb

DESC_DATA_VALUE		= 0x55
TIMEOUT			= 1000

class TestCase(unittest.TestCase):
	"Test various tricky control transfers"

	def setUp(self):
		self.dev = usbtest.dev.open()
		self.dev.claimInterface(0)
		self.dev.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_VENDOR
				| usb.RECIP_INTERFACE, usbtest.REQ_INIT_DESC,
				0, DESC_DATA_VALUE, 0, timeout=TIMEOUT)

	def tearDown(self):
		self.dev.releaseInterface()
		del self.dev

	def testInvalidInReq(self):
		try:
			self.dev.controlMsg(usb.ENDPOINT_IN | usb.TYPE_VENDOR
					| usb.RECIP_INTERFACE,
					usbtest.REQ_INVALID, 8, 0, 0,
					timeout=TIMEOUT)
		except usb.USBError:
			pass
		else:
			fail("expected a USBError")

	def testInvalidOutReq(self):
		try:
			self.dev.controlMsg(usb.ENDPOINT_OUT | usb.TYPE_VENDOR
					| usb.RECIP_INTERFACE,
					usbtest.REQ_INVALID, 8, 0, 0,
					timeout=TIMEOUT)
		except usb.USBError:
			pass
		else:
			fail("expected a USBError")

	def testSetInterface(self):
		self.dev.setAltInterface(0)

	def testGetInterface(self):
		altsetting, = self.dev.controlMsg(usb.ENDPOINT_IN
				| usb.TYPE_STANDARD | usb.RECIP_INTERFACE,
				usb.REQ_GET_INTERFACE, 1, 0, 0, timeout=TIMEOUT)
		self.failUnlessEqual(altsetting, 0)

	def doTestCtrlIn(self, dt, length, desc_len=-1):
		if desc_len == -1:
			desc_len = length
		data_len = min(length, desc_len)

		desc = self.dev.controlMsg(usb.ENDPOINT_IN |
				usb.TYPE_VENDOR | usb.RECIP_INTERFACE,
				usbtest.REQ_GET_DESC, length, dt << 8, 0,
				timeout=TIMEOUT)
		self.failUnlessEqual(len(desc), data_len)
		self.failUnlessEqual(desc[0], desc_len)
		self.failUnlessEqual(desc[1], dt)
		for i in range(2, data_len):
			self.failUnlessEqual(desc[i], DESC_DATA_VALUE)

	def testCtrlInSize2(self):
		self.doTestCtrlIn(usbtest.DT_SIZE2, 2)

	def testCtrlInSize63(self):
		self.doTestCtrlIn(usbtest.DT_SIZE63, 63)

	def testCtrlInSize64(self):
		self.doTestCtrlIn(usbtest.DT_SIZE64, 64)

	def testCtrlInSize65(self):
		self.doTestCtrlIn(usbtest.DT_SIZE65, 65)

	def testCtrlInSize127(self):
		self.doTestCtrlIn(usbtest.DT_SIZE127, 127)

	def testCtrlInSize128(self):
		self.doTestCtrlIn(usbtest.DT_SIZE128, 128)

	def testCtrlInSize129(self):
		self.doTestCtrlIn(usbtest.DT_SIZE129, 129)

	def testCtrlInTruncated(self):
		self.doTestCtrlIn(usbtest.DT_SIZE129, 3, 129)

	def testCtrlInShortZLP(self):
		self.doTestCtrlIn(usbtest.DT_SIZE128, 256, 128)

	def testCtrlInShortNoZLP(self):
		self.doTestCtrlIn(usbtest.DT_SIZE127, 256, 127)

def suite():
	return unittest.makeSuite(TestCase, 'test')
