Example #1
0
//////////////////////////////////////////////////////////////////////
//
// THREAD FUNCTION TO RUN MIDI INPUT
//
//////////////////////////////////////////////////////////////////////
void RunMIDIInput()
{
	SMQ_MSG msg;
	unsigned short num_read;
	byte uch;
	
	// wait for setup to complete
	vos_wait_semaphore(&setupSem);
	vos_signal_semaphore(&setupSem);
	
	for(;;)
	{
		vos_dev_read(hUART, &uch, 1, &num_read);
		if(num_read > 0)
		{
			if(uch == 0xf8)
			{
				msg.status = 0xf8;
				msg.param1 = 0x00;
				msg.param2 = 0x00;
				SMQWrite(&msg);
			}
		}
	}
	
}
Example #2
0
////////////////////////////////////////////////////////////////////
// Main application thread
void RunPlaypad()
{
	SMQ_MSG msg;	
	
	// wait for setup to complete
	vos_wait_semaphore(&setupSem);
	vos_signal_semaphore(&setupSem);
		
	arpie_init();
	
	for(;;)
	{
		SMQRead(&msg);
		switch(msg.status)
		{
			case 0x80:
			case 0x90:
				if(msg.status == 0x80 || msg.param2 == 0)
				{
					arpie_event(EVENT_KEYUP, msg.param1/16, msg.param1%16);
				}
				else
				{
					arpie_event(EVENT_KEYDOWN, msg.param1/16, msg.param1%16);
				}
				break;
			case 0xf8: // clock tick
				arpie_event(EVENT_TICK, 0, 0);
				break;
		}
	}
}
Example #3
0
void HelloWorld(void) {
    BYTE Counter = 0;
    vos_wait_semaphore(&DevicesStarted);
    vos_signal_semaphore(&DevicesStarted);
    dprint("Hello World has started\n", 0);
    while (1) {
        vos_delay_msecs(1000);
        dprint("Hello World %d ", &Counter++);
        }
    }
Example #4
0
void StartupDevices(void) {
    gpio_ioctl_cb_t gpio_iocb;
    common_ioctl_cb_t uart_iocb;
    BYTE Status = 0;
// Open GPIO driver and configure it
    hDevice[LEDs] = vos_dev_open(LEDs);
// Set LED3 pin to output
    gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK;
    gpio_iocb.value = LED3;
    Status |= vos_dev_ioctl(hDevice[LEDs], &gpio_iocb);

// Open UART driver and configure it
    hDevice[UART] = vos_dev_open(UART);
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_BAUD_RATE;
    uart_iocb.set.uart_baud_rate = UART_BAUD_3000000;
    Status = vos_dev_ioctl(hDevice[UART], &uart_iocb);
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_FLOW_CONTROL;
    uart_iocb.set.param = UART_FLOW_NONE;
//    Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb);
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_DATA_BITS;
    uart_iocb.set.param = UART_DATA_BITS_8;
    Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb);
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_STOP_BITS;
    uart_iocb.set.param = UART_STOP_BITS_1;
    Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb);
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_PARITY;
    uart_iocb.set.param = UART_PARITY_NONE;
//    Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb);
// Since baud rate >= 115200 enable DMA for this channel
    uart_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
    Status |= vos_dev_ioctl(hDevice[UART], &uart_iocb);
// Finally enable UART interrupts are we're ready to go!
    vos_enable_interrupts(VOS_UART_INT_IEN);

// Open two more GPIO drivers for the Logic Analyser and configure them
    hDevice[LA_In] = vos_dev_open(LA_In);
// Set all port bits to input
    gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK;
    gpio_iocb.value = 0;
    Status |= vos_dev_ioctl(hDevice[LA_In], &gpio_iocb);
    hDevice[LA_Out] = vos_dev_open(LA_Out);
// Set all port bits to output
    gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK;
    gpio_iocb.value = 0xFF;
    Status |= vos_dev_ioctl(hDevice[LA_Out], &gpio_iocb);

// Spin up USB Host
    hDevice[Host] = vos_dev_open(Host);

// Let other tasks know that devices are initialized
    vos_signal_semaphore(&DevicesStarted);

    CheckStatus(Status, ErrorStartupDevices);
    }
Example #5
0
void HandleChapter9Request(BYTE ThreadID, usb_deviceRequest_t* Setup) {
    BYTE Temp;
    usbslave_ioctl_cb_t iocb;
    dprint("\nIn HandleChapter9Request with %x", &Setup->bRequest);
    switch (Setup->bRequest) {
        case USB_REQUEST_CODE_SET_ADDRESS:
            dprint("\nAt SetAddress with %X", &Setup->wValue);
            iocb.ioctl_code = VOS_IOCTL_USBSLAVE_SET_ADDRESS;
            Temp = Setup->wValue & 0xFF;
            iocb.set = (void*) Temp;
            i_vos_dev_ioctl(ThreadID, hDevice[Slave], &iocb);
            SendACK(ThreadID);
            break;
        case USB_REQUEST_CODE_GET_DESCRIPTOR:
            Temp = Setup->wValue >> 8;
            dprint("\nIn Get Descriptor with %x", &Temp);
            switch (Temp) {
                case USB_DESCRIPTOR_TYPE_DEVICE:
                    dprint("\nGet Device Descriptor (%X)", &Setup->wLength);
                    SendResponse(ThreadID, &MyDeviceDescriptor[0], Setup->wLength ,sizeof(MyDeviceDescriptor));
                    break;
                case USB_DESCRIPTOR_TYPE_CONFIGURATION:
                    dprint("\nGet Configuration Descriptor (%X)", &Setup->wLength);
                    SendResponse(ThreadID, &MyConfigurationDescriptor[0], Setup->wLength ,sizeof(MyConfigurationDescriptor));
                    break;
                case 0x22:    // This is request for the HID Report Descriptor
                    SendResponse(ThreadID, &KeyboardReportDescriptor[0], Setup->wLength ,sizeof(KeyboardReportDescriptor));
                    break;
// Need to complete these - catch as an error for now
                case USB_DESCRIPTOR_TYPE_ENDPOINT:
                case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER:
                case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
                    CheckStatus(Setup->wValue & 0xF, ErrorUnknownDescriptorType);
                    break;
                }
            break;
        case USB_REQUEST_CODE_SET_CONFIGURATION:
            dprint("\nSet Configuration = %x", &Setup->wValue);
            SendACK(ThreadID);
            vos_signal_semaphore(&EnumerationComplete);
            break;
// Need to complete these - catch as an error for now
        case USB_REQUEST_CODE_GET_STATUS:
        case USB_REQUEST_CODE_CLEAR_FEATURE:
        case USB_REQUEST_CODE_SET_FEATURE:
        case USB_REQUEST_CODE_SET_DESCRIPTOR:
        case USB_REQUEST_CODE_GET_CONFIGURATION:
        case USB_REQUEST_CODE_GET_INTERFACE:
        case USB_REQUEST_CODE_SET_INTERFACE:
        case USB_REQUEST_CODE_SYNCH_FRAME:
            CheckStatus(Setup->bRequest, ErrorUnknownRequest);
            break;
        }
    }
Example #6
0
void fifo_write(FIFO_TYPE *pfifo, unsigned char *data, int count)
{	
	int i;
	for(i=0; i<count; ++i)
	{
		vos_wait_semaphore(&pfifo->semWrite);	
		vos_lock_mutex(&pfifo->mutex);
		pfifo->data[pfifo->head] = data[i]; 
		pfifo->head = FIFO_INC(pfifo->head);
		vos_unlock_mutex(&pfifo->mutex);
	}
	vos_signal_semaphore(&pfifo->semRead);	
}
Example #7
0
int fifo_read(FIFO_TYPE *pfifo, unsigned char *data, int size)
{
	int count = 0;
	vos_wait_semaphore(&pfifo->semRead);	
	vos_lock_mutex(&pfifo->mutex);
	while(count < size && pfifo->tail != pfifo->head)
	{
		data[count] = pfifo->data[pfifo->tail];		
		pfifo->tail = FIFO_INC(pfifo->tail);	
		vos_signal_semaphore(&pfifo->semWrite);	
		++count;
	}
	vos_unlock_mutex(&pfifo->mutex);
	return count;
}
Example #8
0
void RunUSBSend()
{
	unsigned char attached;
	uint8 msg[3];
	int param = 1;	
	int i;
	unsigned short bytes_written;
	VOS_HANDLE hUSB;
	
	// wait for setup to complete
	vos_wait_semaphore(&setupSem);
	vos_signal_semaphore(&setupSem);
	
	msg[0] = 0;
	while(1)
	{
		int count = fifo_read(&stSPIReadFIFO, usbSendBuffer, 64);
		for(i=0;i<count;++i)
		{
			if(usbSendBuffer[i]&0x80)
			{				
				msg[0] = usbSendBuffer[i];
				param = 1;
			}
			else if(param == 1)
			{
				msg[1] = usbSendBuffer[i];
				param = 2;
			}
			else if(param == 2)
			{
				msg[2] = usbSendBuffer[i];
				param = 1;
				if(msg[0])
				{
					VOS_ENTER_CRITICAL_SECTION;
					hUSB = PortA.hUSBHOSTGENERIC;
					VOS_EXIT_CRITICAL_SECTION;
					if(hUSB)
					{
						vos_dev_write(hUSB, msg, 3, &bytes_written);						
					}
				}
			}		
		}
	}
}
Example #9
0
//////////////////////////////////////////////////////////////////////
//
// APPLICATION SETUP THREAD FUNCTION
//
//////////////////////////////////////////////////////////////////////
void Setup()
{
	common_ioctl_cb_t spis_iocb;
	usbhostGeneric_ioctl_t generic_iocb;
	gpio_ioctl_cb_t gpio_iocb;
	common_ioctl_cb_t uart_iocb;
	unsigned char uchLeds;
	common_ioctl_cb_t ss_iocb;

	hSPISlave = vos_dev_open(VOS_DEV_SPISLAVE);
	
	// Open up the base level drivers
	hGpioA  	= vos_dev_open(VOS_DEV_GPIO_A);
	

	gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK;
	gpio_iocb.value = 0b11000110;
	vos_dev_ioctl(hGpioA, &gpio_iocb);
	setGpioA(0b11000110,0);

	ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_SCK_CPHA;
	ss_iocb.set.param = SPI_SLAVE_SCK_CPHA_0;
	vos_dev_ioctl(hSPISlave, &ss_iocb);

	ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_SCK_CPOL;
	ss_iocb.set.param = SPI_SLAVE_SCK_CPOL_0;
	vos_dev_ioctl(hSPISlave, &ss_iocb);
	
	ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_DATA_ORDER;
	ss_iocb.set.param = SPI_SLAVE_DATA_ORDER_MSB;
	vos_dev_ioctl(hSPISlave, &ss_iocb);
	
	ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_SET_MODE;
	ss_iocb.set.param = SPI_SLAVE_MODE_FULL_DUPLEX;
	vos_dev_ioctl(hSPISlave, &ss_iocb);

	ss_iocb.ioctl_code = VOS_IOCTL_SPI_SLAVE_SET_ADDRESS;
	ss_iocb.set.param = 0;
	vos_dev_ioctl(hSPISlave, &ss_iocb);

	ss_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
	ss_iocb.set.param = DMA_ACQUIRE_AND_RETAIN;
	vos_dev_ioctl(hSPISlave, &ss_iocb);
	
	// Release other application threads
	vos_signal_semaphore(&setupSem);
}
Example #10
0
void RunSPISend()
{
	unsigned short bytes_written;
	
	
	// wait for setup to complete
	vos_wait_semaphore(&setupSem);
	vos_signal_semaphore(&setupSem);

	while(1)
	{
		int count = fifo_read(&stSPIWriteFIFO, spiSendBuffer, 64);		
		vos_dev_write(hSPISlave, spiSendBuffer, (unsigned short)count, &bytes_written);		
		setGpioA(LED_SIGNAL,0); 
		setGpioA(LED_SIGNAL,LED_SIGNAL|LED_ACTIVITY); 		
		
	}
}
Example #11
0
void RunSPIReceive()
{
	unsigned short bytes_read;
	
	common_ioctl_cb_t spi_iocb;
	
	// wait for setup to complete
	vos_wait_semaphore(&setupSem);
	vos_signal_semaphore(&setupSem);

	while(1)
	{
		spi_iocb.ioctl_code = VOS_IOCTL_COMMON_GET_RX_QUEUE_STATUS;
		vos_dev_ioctl(hSPISlave, &spi_iocb);
		if(spi_iocb.get.queue_stat)
		{
			if(0==vos_dev_read(hSPISlave, (char*)spiRxBuffer, spi_iocb.get.queue_stat, &bytes_read))
				fifo_write(&stSPIReadFIFO, spiRxBuffer, (int)bytes_read);
		}
	}
}
Example #12
0
//////////////////////////////////////////////////////////////////////
//
// APPLICATION SETUP THREAD FUNCTION
//
//////////////////////////////////////////////////////////////////////
void Setup()
{
	common_ioctl_cb_t spis_iocb;
	usbhostGeneric_ioctl_t generic_iocb;
	gpio_ioctl_cb_t gpio_iocb;
	common_ioctl_cb_t uart_iocb;
	unsigned char uchLeds;

	// Open up the base level drivers
	hGpioA  	= vos_dev_open(VOS_DEV_GPIO_A);
	PortA.hUSBHOST = vos_dev_open(VOS_DEV_USBHOST_1);
	//PortB.hUSBHOST = vos_dev_open(VOS_DEV_USBHOST_2);

	gpio_iocb.ioctl_code = VOS_IOCTL_GPIO_SET_MASK;
	gpio_iocb.value = 0b00001110;
	vos_dev_ioctl(hGpioA, &gpio_iocb);
	uchLeds = 0b00001000;
	vos_dev_write(hGpioA,&uchLeds,1,NULL);

	hUART = vos_dev_open(VOS_DEV_UART);

	/* UART ioctl call to enable DMA and link to DMA driver */
	uart_iocb.ioctl_code = VOS_IOCTL_COMMON_ENABLE_DMA;
	vos_dev_ioctl(hUART, &uart_iocb);

	// Set up for MIDI
    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_BAUD_RATE;
	uart_iocb.set.uart_baud_rate = 31250;
	vos_dev_ioctl(hUART, &uart_iocb);

    uart_iocb.ioctl_code = VOS_IOCTL_UART_SET_FLOW_CONTROL;
	uart_iocb.set.param = UART_FLOW_NONE;
	vos_dev_ioctl(hUART, &uart_iocb);

	// Set up the metronome
	MetroInit(&metro, VOS_DEV_TIMER0, TIMER_0);
	
	// Release other application threads
	vos_signal_semaphore(&setupSem);
}
Example #13
0
/////////////////////////////////////////////////////////////////////
// Thread to dispatch tick events to the playpad thread
// at timed intervals
void RunMetronome() 
{
	SMQ_MSG tick;		
	
	// wait for setup to complete
	vos_wait_semaphore(&setupSem);
	vos_signal_semaphore(&setupSem);
	
	// Prepare standard tick message
	tick.status = 0xf8;
	tick.param1 = 0x00;
	tick.param2 = 0x00;
	
	// Start the metronome
	MetroStart(&metro, VOS_DEV_TIMER0, 120);
	for(;;) 
	{
		// run!
		SMQWrite(&tick);
		MetroDelay(&metro);
	}
}
int incHead(int oldHe

/////////////////////////////////////////////////////////////////////////////
// WRITE
            void SMQWrite(uint8 tag, uint8 device, int size, uint8 *data)
{
    int newHead;
    vos_lock_mutex(&mAccess);

    newHead = head + 1;
    if(newHead >= SMQ_LEN)
        newHead = 0;
    if(newHead != tail)
    {
        queue[head].status = msg->status;
        queue[head].param1 = msg->param1;
        queue[head].param2 = msg->param2;
        head = newHead;
        vos_signal_semaphore(&semAvailable);
    }
    vos_unlock_mutex(&mAccess);
}
Example #15
0
//////////////////////////////////////////////////////////////////////
//
// THREAD FUNCTION TO RUN USB HOST PORT
//
//////////////////////////////////////////////////////////////////////
void RunHostPort(HOST_PORT_DATA *pHostData)
{
	unsigned char status;
	unsigned char buf[64];
	unsigned short num_read;
	unsigned int handle;
	usbhostGeneric_ioctl_t generic_iocb;
	usbhostGeneric_ioctl_cb_attach_t genericAtt;
	usbhost_device_handle_ex ifDev;
	usbhost_ioctl_cb_t hc_iocb;
	usbhost_ioctl_cb_vid_pid_t hc_iocb_vid_pid;
	gpio_ioctl_cb_t gpio_iocb;

	SMQ_MSG msg;
	msg.status = 0x90;

	// wait for setup to complete
	vos_wait_semaphore(&setupSem);
	vos_signal_semaphore(&setupSem);

	// loop forever
	while(1)
	{
		// is the device enumerated on this port?
		if (usbhost_connect_state(pHostData->hUSBHOST) == PORT_STATE_ENUMERATED)
		{
			// user ioctl to find first hub device
			hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_NEXT_HANDLE;
			hc_iocb.handle.dif = NULL;
			hc_iocb.set = NULL;
			hc_iocb.get = &ifDev;
			if (vos_dev_ioctl(pHostData->hUSBHOST, &hc_iocb) == USBHOST_OK)
			{

				hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_VID_PID;
				hc_iocb.handle.dif = ifDev;
				hc_iocb.get = &hc_iocb_vid_pid;
				
				// attach the Launchpad device to the USB host device
				pHostData->hUSBHOSTGENERIC = vos_dev_open(pHostData->uchDeviceNumber);
				genericAtt.hc_handle = pHostData->hUSBHOST;
				genericAtt.ifDev = ifDev;
				generic_iocb.ioctl_code = VOS_IOCTL_USBHOSTGENERIC_ATTACH;
				generic_iocb.set.att = &genericAtt;
				if (vos_dev_ioctl(pHostData->hUSBHOSTGENERIC, &generic_iocb) == USBHOSTGENERIC_OK)
				{
					setLed(pHostData->uchActivityLed, 1);
					
					// now we loop until the launchpad is detached
					while(1)
					{
						int pos = 0;
						byte param = 1;
						
						// read data
						status = vos_dev_read(pHostData->hUSBHOSTGENERIC, buf, 64, &num_read);
						if(status != USBHOSTGENERIC_OK)
							break;
							
						setLed(pHostData->uchActivityLed, 0);

						// interpret MIDI data and pass to application thread
						
						while(pos < num_read)
						{
							if(buf[pos] & 0x80)
							{
								msg.status = buf[pos];
								param = 1;
							}
							else if(param == 1)
							{
								msg.param1 = buf[pos];
								param = 2;
							}
							else if(param == 2)
							{
								msg.param2 = buf[pos];
								SMQWrite(&msg);										
								param = 1;
							}
							++pos;
						}
						
						setLed(pHostData->uchActivityLed, 1);
					}					
				}
				vos_dev_close(pHostData->hUSBHOSTGENERIC);
			}
		}
		setLed(pHostData->uchActivityLed, 0);
	}
}	
Example #16
0
void WaitForDevicesStarted(void) {
    vos_wait_semaphore(&DevicesStarted);
    vos_signal_semaphore(&DevicesStarted);
    }
Example #17
0
//////////////////////////////////////////////////////////////////////
//
// RUN USB HOST PORT
//
//////////////////////////////////////////////////////////////////////
void RunHostPort(HOST_PORT_DATA *pHostData)
{
	int i;
	int midiParam;
	unsigned char status;
	unsigned char buf[64];	
	unsigned short num_bytes;
	unsigned int handle;
	usbhostGeneric_ioctl_t generic_iocb;
	usbhostGeneric_ioctl_cb_attach_t genericAtt;
	usbhost_device_handle_ex ifDev;
	usbhost_ioctl_cb_t hc_iocb;
	usbhost_ioctl_cb_vid_pid_t hc_iocb_vid_pid;
	gpio_ioctl_cb_t gpio_iocb;
	VOS_HANDLE hUSB;

	// wait for setup to complete
	vos_wait_semaphore(&setupSem);
	vos_signal_semaphore(&setupSem);
	
	// Open the base USB Host driver
	pHostData->hUSBHOST = vos_dev_open(pHostData->uchDeviceNumberBase);
	
	// loop forever
	while(1)
	{
		vos_delay_msecs(10);
		// is the device enumerated on this port?
		if (usbhost_connect_state(pHostData->hUSBHOST) == PORT_STATE_ENUMERATED)
		{
			// user ioctl to find first hub device
			hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_NEXT_HANDLE;
			hc_iocb.handle.dif = NULL;
			hc_iocb.set = NULL;
			hc_iocb.get = &ifDev;
			if (vos_dev_ioctl(pHostData->hUSBHOST, &hc_iocb) == USBHOST_OK)
			{
				// query the device VID/PID
				hc_iocb.ioctl_code = VOS_IOCTL_USBHOST_DEVICE_GET_VID_PID;
				hc_iocb.handle.dif = ifDev;
				hc_iocb.get = &hc_iocb_vid_pid;
				
				// Load the function driver
				hUSB = vos_dev_open(pHostData->uchDeviceNumber);
				
				// Attach the function driver to the base driver
				genericAtt.hc_handle = pHostData->hUSBHOST;
				genericAtt.ifDev = ifDev;
				generic_iocb.ioctl_code = VOS_IOCTL_USBHOSTGENERIC_ATTACH;
				generic_iocb.set.att = &genericAtt;
				if (vos_dev_ioctl(hUSB, &generic_iocb) == USBHOSTGENERIC_OK)
				{					
					// Turn on the LED for this port
					setGpioA(pHostData->uchActivityLed, pHostData->uchActivityLed);

					// flag that the port is attached
					VOS_ENTER_CRITICAL_SECTION;
					pHostData->hUSBHOSTGENERIC = hUSB;
					VOS_EXIT_CRITICAL_SECTION;
										
					// now we loop until the launchpad is detached
					while(1)
					{
						// listen for data from launchpad
						uint16 result = vos_dev_read(hUSB, buf, 64, &num_bytes);
						if(0 != result)
							break; // break when the launchpad is detached						
						fifo_write(&stSPIWriteFIFO, buf, (int)num_bytes); 
					}					
					
					// flag that the port is no longer attached
					VOS_ENTER_CRITICAL_SECTION;
					pHostData->hUSBHOSTGENERIC = NULL;
					VOS_EXIT_CRITICAL_SECTION;
					
					// turn off the activity LED
					setGpioA(pHostData->uchActivityLed, 0);
				}
				
				// close the function driver
				vos_dev_close(hUSB);
			}
		}
	}
}	
Example #18
0
void i_vos_signal_semaphore(BYTE ThreadID, vos_semaphore_t* s) {
    CallVOS(ThreadID);
    vos_signal_semaphore(s);
    ThreadRunning(ThreadID);
    }
// This function is run inside the thread created in init
// It will respond to standard USB requests
// some of the requests are forwarded to the flash drive when appropriate
void usbslaveboms_setup(usbSlaveBoms_context *ctx)
{
	usbslave_ioctl_cb_t iocb; // this is a structure used by underlying VOS driver
	usb_deviceRequest_t *devReq; // this struct is defined in usb.h and is used to store the 9 byte setup request
	unsigned char bmRequestType; // The request type is defined by USB standard
	unsigned char state = UNATTACHED;  // assume unattached at the start

	// This will wait till the flash drive is enumed so we don't
	// start responding to commands right away
	vos_wait_semaphore(&ctx->enumed);
	vos_signal_semaphore(&ctx->enumed);

	vos_wait_semaphore(&setupDoneSemaphore); // wait for setup to complete
	vos_signal_semaphore(&setupDoneSemaphore); // reset semaphore for next guy

	while (1)
	{
		switch (state)
		{
		case UNATTACHED:

			if (!ctx->attached)
				vos_delay_msecs(100); // this delay is to avoid a tight loop
			else
			{
				state = ATTACHED;
			}

			break;

		case ATTACHED:

			if (!ctx->attached) // check to see if we somehow became unattached
			{
				state = UNATTACHED;
				break;
			}

			// we now make a blocking call requesting the 9 byte setup
			// packet on the control endpoint
			iocb.ioctl_code = VOS_IOCTL_USBSLAVE_WAIT_SETUP_RCVD;
			iocb.request.setup_or_bulk_transfer.buffer = ctx->setup_buffer;
			iocb.request.setup_or_bulk_transfer.size = 9;
			vos_dev_ioctl(ctx->handle, &iocb);

			// decode the raw data by pointing to our structure
			devReq = (usb_deviceRequest_t *) ctx->setup_buffer;
			// valid types here are standard, class, and vendor
			// BOMS devices do not have vendor specific calls
			// even if they did, we wouldn't support them.
			bmRequestType = devReq->bmRequestType & (USB_BMREQUESTTYPE_STANDARD | USB_BMREQUESTTYPE_CLASS);

			// we only need to handle standard and class requests for BOMS
			if (bmRequestType == USB_BMREQUESTTYPE_STANDARD)
			{
				standard_request(ctx); // standard request that all USB devices support
			}
			else if (bmRequestType == USB_BMREQUESTTYPE_CLASS)
			{
				class_request(ctx); // the request is specific to this device class (only 2 in our case)
			}

			break;

		default:
			asm {HALT}; // if we somehow got here the fecal matter has hit the turbine
			break;
		}
	}

	return;
}