+/*********************************************************/
+/*** Module : USB communication ***/
+/*** Author : Roman Bartosinski (bartosr@centrum.cz) ***/
+/*** Modify : 14.01.2003 ***/
+/*********************************************************/
+
+#include <cpu_def.h>
+#include <system_def.h>
+#include <stdio.h>
+#include "pdiusb.h"
+#include <h8s2633h.h>
+/*#include <usb/usb_spec.h>*/
+#include "usb_defs.h"
+#include <usb/usb.h>
+#include <usb/usb_com.h>
+
+
+/* Queued USB Module */
+typedef volatile struct{
+ unsigned char *first;
+ unsigned char *last;
+ unsigned char *begin;
+ unsigned char *end;
+} usb_com_que_t;
+
+#define USB_COM_BUF_LEN 80 //(80*8)
+
+usb_com_que_t usb_com_que_in; /* input queue */
+unsigned char usb_com_buf_in[USB_COM_BUF_LEN];
+usb_com_que_t usb_com_que_out; /* output queue */
+unsigned char usb_com_buf_out[USB_COM_BUF_LEN];
+
+int usb_com_init( void);
+int usb_com_put(usb_com_que_t *q, int c);
+int usb_com_get(usb_com_que_t *q);
+
+usb_vendor_extension_fnc_t *usb_vendor_extension=0;
+
+#ifdef PDIUSB_WITH_ADD_IRQ_HANDLER
+/* usb irq handler struct */
+irq_handler_t usb_irq_handler;
+#elif defined(PDIUSB_WITH_EXCPTVECT_SET)
+void usb_isr(void) __attribute__ ((interrupt_handler));
+#endif /*PDIUSB_WITH_EXCPTVECT_SET*/
+
+int usb_irq_cnt;
+
+/* common external function for pdiusb module */
+ void pdiSendCommand( unsigned char byCmd) {
+ writeb( byCmd, PDIUSB_COMMAND_ADDR);
+ }
+ unsigned char pdiReadData( unsigned char byCount, unsigned char *pbyData) {
+ unsigned char out = byCount;
+
+ while (byCount--) {
+ *pbyData = readb( PDIUSB_READ_DATA_ADDR);
+ pbyData++;
+ }
+
+ return out;
+ }
+ void pdiWriteData( unsigned char byCount, unsigned char *pbyData) {
+ while (byCount--) {
+ writeb( *pbyData++, PDIUSB_WRITE_DATA_ADDR);
+ }
+ }
+
+
+/* usb communication module */
+ /* data */
+ usb_flags_t usb_flags;
+ unsigned char usb_address;
+ unsigned char usb_interface;
+ usb_control_ep_t usb_rxtx_control;
+ usb_bulk_ep_t usb_rx_bulk, usb_tx_bulk;
+
+ volatile unsigned int usb_last_irq;
+ // internal buffer for data from/to control req. - must be global
+ unsigned char ctrl_data[PDI_EP0_PACKET_SIZE];
+
+ typeof(msec_time) usb_start = 0, usb_stop = 0;
+
+
+
+/* functions */
+ int usb_run( void) {
+ int ret = 0;
+ if ( usb_flags.running) {
+#ifdef USE_USB_WITH_IRQ
+ if (!usb_flags.bits.was_int) return ret;
+ usb_flags.was_int = 0;
+#else
+ ret = usb_test_interrupt();
+ if ( usb_flags.request == 1) {
+ usb_answer_to_request();
+ }
+ if ( usb_flags.request == 2) { // request is set in usb_answer_to_request()
+ if (( usb_rxtx_control.dreq.bmRequestType & USB_DATA_DIR_MASK)==USB_DATA_DIR_TO_HOST) {
+ unsigned int now = usb_rxtx_control.bytes;
+ if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+ if ( usb_rxtx_control.next_pkt_fnc )
+ if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, now, USB_NEXT_PKT_SEND) ) {
+ usb_stall_ep0();
+ return -1;
+ }
+ debugPrint( DBG_HIGH, ("CNTR send 1.data (%d)\n", now));
+ pdiWriteEndpoint( PDI_EP0_TX, now, usb_rxtx_control.data);
+ usb_rxtx_control.data += now;
+ if ( !(usb_rxtx_control.bytes -= now)) {
+ usb_flags.request = 3;
+ }
+ }
+ }
+ if ( usb_flags.request == 3) {
+ if ( !usb_rxtx_control.dreq.wLength ||
+ (usb_rxtx_control.dreq.bmRequestType & USB_DATA_DIR_MASK)==USB_DATA_DIR_FROM_HOST) {
+ pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+ if ( usb_rxtx_control.complete_fnc )
+ usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+ usb_rxtx_control.next_pkt_fnc = NULL;
+ usb_rxtx_control.complete_fnc = NULL;
+ }
+ }
+#endif
+ }
+ return ret;
+ }
+
+ int usb_test_interrupt( void) { //_naked {
+ unsigned char usb_last_status;
+ int ret = 0;
+// INTERRUPT_PRE(0);
+// LEDr = 1;
+// EA=0;
+ usb_last_irq = pdiGetInterrupt();
+ if ( usb_last_irq) {
+ ret = 1;
+ debugPrint( DBG_MEDIUM, ("USB Interrupt 0x%X\n",usb_last_irq));
+ if ( usb_last_irq & PDI_INT_BUSRESET) { // D12 - Bus reset reached
+ usb_flags.configured = 0;
+ if ( usb_flags.running && usb_flags.stop_request) {
+ usb_flags.running = 0;
+ usb_flags.stop_request = 0;
+ }
+ debugPrint( DBG_HIGH, ("Bus Reset\n"));
+ } else {
+ if ( usb_last_irq & PDI_INT_SUSPEND) { // D12 - Suspend flag changed
+ debugPrint( DBG_HIGH, ("Suspend Changed\n"));
+ }
+ // it must be first b/c tx and rx can be sended all together
+ if ( usb_last_irq & PDI_INT_EP0_IN) { // D12 - Ep0TxDone - data in EP0 was sended
+ usb_last_status = pdiGetLastTransStatus( PDI_EP0_TX);
+ debugPrint( DBG_HIGH, ("Ep0-Tx LTS=0x%X\n", usb_last_status));
+ if (( usb_last_status & PDI_LTSTAT_RXTX_OK) && usb_flags.request > 1) {
+ if ( usb_flags.request == 2) {
+ unsigned int now = usb_rxtx_control.bytes;
+ if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+
+ if ( usb_rxtx_control.next_pkt_fnc )
+ if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, now, USB_NEXT_PKT_SEND) ) {
+ usb_stall_ep0();
+ return -1;
+ }
+
+ debugPrint( DBG_HIGH, ("CNTR data\n"));
+ pdiWriteEndpoint( PDI_EP0_TX, now, usb_rxtx_control.data);
+ usb_rxtx_control.data += now;
+ if ( !(usb_rxtx_control.bytes -= now)) {
+ usb_flags.request = 3;
+ }
+ } else if ( usb_flags.request == 3) {
+ debugPrint( DBG_HIGH, ("CNTR ack\n"));
+ usb_flags.request = 0;
+
+ if ( usb_rxtx_control.complete_fnc )
+ usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+ usb_rxtx_control.next_pkt_fnc = NULL;
+ usb_rxtx_control.complete_fnc = NULL;
+
+ } else {
+ debugPrint( DBG_LOW, ("tx ... ???\n"));
+ }
+ }
+ }
+
+ if ( usb_last_irq & PDI_INT_EP0_OUT) { // D12 - Ep0RxDone - some data was received in EP0
+ usb_last_status = pdiGetLastTransStatus( PDI_EP0_RX);
+ debugPrint( DBG_HIGH, ("Ep0-Rx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ if ( usb_last_status & PDI_LTSTAT_SETUP) {
+ if ( usb_flags.request) {
+ debugPrint( DBG_HIGH, ("!!! New setup, but last not ack ...\n"));
+ }
+ usb_flags.request = 1; // Standard_requests();
+ if ( usb_rxtx_control.complete_fnc )
+ usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_FAIL);
+ usb_rxtx_control.next_pkt_fnc = NULL;
+ usb_rxtx_control.complete_fnc = NULL;
+ } else {
+ if ( usb_flags.request == 2) {
+ unsigned int now = usb_rxtx_control.bytes;
+ if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+ debugPrint( DBG_HIGH, ("CNTR data\n"));
+ ret = pdiReadEndpoint( PDI_EP0_RX, now, usb_rxtx_control.data);
+
+ if(ret>usb_rxtx_control.bytes)
+ ret = usb_rxtx_control.bytes;
+
+ usb_rxtx_control.data += ret;
+
+ if ( usb_rxtx_control.next_pkt_fnc ) {
+ if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, ret, USB_NEXT_PKT_REC) ) {
+ usb_stall_ep0();
+ return -1;
+ }
+ }
+
+ if (!(usb_rxtx_control.bytes -= ret)) {
+ usb_rxtx_control.data -= usb_rxtx_control.dreq.wLength;
+ usb_flags.request = 3;
+ }
+ } else if ( usb_flags.request == 3) {
+ debugPrint( DBG_HIGH, ("CNTR ack\n"));
+ usb_flags.request = 0;
+ pdiReadEndpoint( PDI_EP0_RX, 0, 0);
+ if ( usb_rxtx_control.complete_fnc )
+ usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+ usb_rxtx_control.next_pkt_fnc = NULL;
+ usb_rxtx_control.complete_fnc = NULL;
+ } else {
+ pdiReadEndpoint( PDI_EP0_RX, 0, 0);
+ }
+ }
+ }
+ }
+ if ( usb_last_irq & PDI_INT_EP1_OUT) { // D12 - Ep1RxDone - some data was received in EP1
+ usb_last_status = pdiGetLastTransStatus( PDI_EP1_RX);
+ debugPrint( DBG_HIGH, ("Ep1-Rx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ pdiSetEpStatus( PDI_EP1_OUT, PDI_SET_EP_STALLED);
+ }
+ }
+ if ( usb_last_irq & PDI_INT_EP1_IN) { // D12 - Ep1TxDone - data in EP1 was sended
+ usb_last_status = pdiGetLastTransStatus( PDI_EP1_TX);
+ debugPrint( DBG_HIGH, ("Ep1-Tx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ pdiSetEpStatus( PDI_EP1_IN, PDI_SET_EP_STALLED);
+ }
+ }
+
+ if ( usb_last_irq & PDI_INT_EP2_OUT) { // D12 - Ep2RxDone - some data was received in EP2
+ usb_last_status = pdiGetLastTransStatus( PDI_EP2_RX);
+ debugPrint( DBG_HIGH, ("Ep2-Rx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ if ( usb_flags.terminal_mode) {
+ unsigned char hlpbfr[PDI_EP2_PACKET_SIZE], now = PDI_EP2_PACKET_SIZE, i;
+ MoreRead:
+ now = pdiReadEndpoint( PDI_EP2_RX, now, hlpbfr);
+ for(i=0;i<now;i++) {
+ usb_tm_rcv++;
+ if (usb_com_put( &usb_com_que_in, hlpbfr[i])<0) { /* nevkladat dalsi */
+ break;
+ }
+ }
+ if(now==PDI_EP2_PACKET_SIZE) goto MoreRead;
+ } else {
+ unsigned long now = usb_rx_bulk.remain;
+ if ( now > PDI_EP2_PACKET_SIZE) now = PDI_EP2_PACKET_SIZE;
+
+ if ( !usb_flags.bits.bulk_rx_data) {
+ usb_flags.bulk_rx_data = 1;
+ usb_start = msec_time;
+ }
+
+ ReadAgain:
+ ret = pdiReadEndpoint( PDI_EP2_RX, now, usb_rx_bulk.data);
+ usb_rx_bulk.data += now;
+ if ( !( usb_rx_bulk.remain -= now)) {
+ //usb_rx_bulk.data -= usb_rx_bulk.bytes; /* read again */
+ usb_stop = msec_time;
+ usb_flags.bulk_rx_data = 0;
+ // complete_func or set flag(event)
+ }
+ if ( usb_rx_bulk.remain > 0 && usb_rx_bulk.remain <= PDI_EP2_PACKET_SIZE)
+ goto ReadAgain;
+ }
+ }
+ }
+ if ( usb_last_irq & PDI_INT_EP2_IN) { // D12 - Ep2TxDone - data in EP2 was sended
+ usb_last_status = pdiGetLastTransStatus( PDI_EP2_TX);
+ debugPrint( DBG_HIGH, ("Ep2-Tx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ if ( usb_flags.terminal_mode) {
+ int ch = usb_com_get( &usb_com_que_out);
+ usb_tm_snded++;
+ if ( ch < 0) {
+ usb_flags.bulk_tx_data = 0;
+ } else {
+ unsigned char uchr = ch;
+ usb_flags.bulk_tx_data = 1;
+ pdiWriteEndpoint( PDI_EP2_TX, 1, &uchr);
+ }
+ } else {
+ if ( usb_tx_bulk.remain) {
+ unsigned int now = usb_tx_bulk.remain;
+ if ( now > PDI_EP2_PACKET_SIZE) now = PDI_EP2_PACKET_SIZE;
+ pdiWriteEndpoint( PDI_EP2_TX, now, usb_tx_bulk.data);
+ usb_tx_bulk.data += now;
+ if (!(usb_tx_bulk.remain -= now)) {
+ // complete_func or set flag(event)
+ }
+ }
+ }
+ }
+ }
+ ret = 0;
+ }
+ }
+// EA=1;
+// LEDr = 0;
+// INTERRUPT_POST();
+ return ret;
+ }
+
+
+// ************************************
+ void usb_init( void) {
+ usb_last_irq = 0; usb_address = 0; usb_interface = 0;
+ usb_flags.word = 0;
+
+ usb_com_init();
+
+#ifdef USE_USB_WITH_IRQ
+ usb_irq_cnt=0;
+ #ifdef PDIUSB_WITH_ADD_IRQ_HANDLER
+ if( test_irq_handler( ISR_USB_INTV, &usb_irq_handler)==0)
+ add_irq_handler( ISR_USB_INTV, &usb_irq_handler);
+ #elif defined(PDIUSB_WITH_EXCPTVECT_SET)
+ excptvec_set(ISR_USB_INTV,&usb_isr);
+ #endif /*PDIUSB_WITH_ADD_IRQ_HANDLER*/
+ //*((char*)0xfffa1f) |= 0x04; /* It must be here for pull-up INT signal in usb_isr function */
+#endif
+ debugPrint(DBG_MEDIUM,("# Usb Inited\n"));
+ }
+
+ void usb_connect_bus( void) {
+ debugPrint(DBG_MEDIUM,("Usb connect to bus\n"));
+ usb_flags.running = 1;
+ usb_last_irq = 0;
+ pdiSetDMA( PDI_DMA_EP4_INT | PDI_DMA_EP5_INT); // ???
+ pdiSetMode( PDI_MODE_NO_LAZY_CLOCK | PDI_MODE_CLOCK_RUNNING | PDI_MODE_SOFT_CONNECT | PDI_CLOCK_SET_TO_ONE | PDI_CLOCK_4M);
+ }
+ void usb_disconnect_bus( void) {
+ debugPrint(DBG_MEDIUM,("Usb disconnect from bus\n"));
+ pdiSetMode( PDI_MODE_NO_LAZY_CLOCK | PDI_MODE_CLOCK_RUNNING | PDI_CLOCK_SET_TO_ONE | PDI_CLOCK_4M);
+ usb_flags.configured = 0;
+ usb_flags.stop_request = 1;
+ }
+
+ void usb_stall_ep0( void) {
+ pdiSetEpStatus( PDI_EP0_TX, PDI_SET_EP_STALLED); pdiSetEpStatus( PDI_EP0_RX, PDI_SET_EP_STALLED);
+ }
+
+
+// ************************************
+// *** Common send/receive fncs ***
+// ************************************
+/*
+ void usb_send_to_usb( unsigned char idx, unsigned char maxb) {
+ debugPrint( DBG_HIGH,("USB Send EP#%d (max=%d) <- buff 0x%lX, cnt %d\n",usb_ep[idx].ep, maxb, (unsigned long)usb_ep[idx].buff,usb_ep[idx].bytes));
+ if ( !usb_ep[idx].bytes) pdiWriteEndpoint( usb_ep[idx].ep, 0, 0);
+ else {
+ if ( usb_ep[idx].bytes > maxb) {
+ pdiWriteEndpoint( usb_ep[idx].ep, maxb, usb_ep[idx].buff);
+ usb_ep[idx].bytes -= maxb;
+ usb_ep[idx].buff += maxb;
+ } else {
+ pdiWriteEndpoint( usb_ep[idx].ep, usb_ep[idx].bytes, usb_ep[idx].buff);
+ usb_ep[idx].buff += usb_ep[idx].bytes;
+ usb_ep[idx].bytes = 0;
+// if ( usending) usending = 0;
+ }
+ }
+ }
+
+ unsigned char usb_receive_from_usb( unsigned char idx, unsigned char maxb) {
+ unsigned char ret = 0;
+
+ ret = (unsigned char)usb_ep[idx].bytes;
+ if ( !ret || ret > maxb) ret = maxb;
+ debugPrint( DBG_HIGH,("USB Receive EP#%d ->buff 0x%lX,cnt %d,(max %d)\n",usb_ep[idx].ep,(unsigned long)usb_ep[idx].buff,usb_ep[idx].bytes,ret));
+ if ( !usb_ep[idx].bytes) {
+// ureceiving = 0;
+ pdiReadEndpoint( usb_ep[idx].ep, 0, 0);
+ return 0xff; // too_small_buffer error
+ }
+ do {
+ ret = pdiReadEndpoint( usb_ep[idx].ep, ret, usb_ep[idx].buff);
+ debugPrint( DBG_HIGH,(" - really readed %d\n", ret));
+ usb_ep[idx].buff += ret;
+ usb_ep[idx].bytes -= ret;
+ } while (( ret == maxb) && usb_ep[idx].bytes);
+ return ret;
+ }
+*/
+
+
+#ifdef DEBUG
+ char *ReqRecipient( char rqt) {
+ switch ( rqt & USB_RECIPIENT) {
+ case USB_RECIPIENT_DEVICE: return "DEVICE";
+ case USB_RECIPIENT_INTERFACE: return "INTERFACE";
+ case USB_RECIPIENT_ENDPOINT: return "ENDPOINT";
+ }
+ return "OTHER";
+ }
+ char *ReqType( char rqt) {
+ switch ( rqt & USB_REQUEST_TYPE_MASK) {
+ case USB_STANDARD_REQUEST: return "STANDARD";
+ case USB_CLASS_REQUEST: return "CLASS";
+ case USB_VENDOR_REQUEST: return "VENDOR";
+ }
+ return "RESERVED";
+ }
+ char *ReqName( char req) {
+ switch ( req & USB_REQUEST_MASK) {
+ case USB_REQUEST_GET_STATUS: return "GET STATUS";
+ case USB_REQUEST_CLEAR_FEATURE: return "CLEAR FEATURE";
+ case USB_REQUEST_SET_FEATURE: return "SET FEATURE";
+ case USB_REQUEST_SET_ADDRESS: return "SET ADDRESS";
+ case USB_REQUEST_GET_DESCRIPTOR: return "GET DESCRIPTOR";
+ case USB_REQUEST_SET_DESCRIPTOR: return "SET DESCRIPTOR";
+ case USB_REQUEST_GET_CONFIGURATION: return "GET CONFIGURATION";
+ case USB_REQUEST_SET_CONFIGURATION: return "SET CONFIGURATION";
+ case USB_REQUEST_GET_INTERFACE: return "GET INTERFACE";
+ case USB_REQUEST_SET_INTERFACE: return "SET INTERFACE";
+ case USB_REQUEST_SYNC_FRAME: return "SYNC FRAME";
+ }
+ return "UNKNOWN";
+ }
+#endif
+
+
+ void usb_set_control_data(usb_control_ep_t *ep, void *buff, int size)
+ {
+ ep->data = (unsigned char *) buff;
+ ep->bytes = size;
+ usb_flags.request = 2;
+ debugPrint( DBG_HIGH,("usb_set_control_data buff=0x%lx, len=%d\n", (long)buff, size));
+ }
+
+ void usb_set_control_ack(usb_control_ep_t *ep)
+ {
+ ep->data = NULL;
+ ep->bytes = 0;
+ usb_flags.request = 3;
+ debugPrint( DBG_HIGH,("usb_set_control_ack\n"));
+ }
+
+
+ /*
+ ***********************************
+ *** Execute device requests ***
+ ***********************************
+ */
+ void usb_answer_to_request( void) {
+ USB_DEVICE_REQUEST *pdreq = &usb_rxtx_control.dreq;
+
+ debugPrint( DBG_MEDIUM,("Process usb setup packet\n"));
+ usb_rxtx_control.req_size=pdiReadEndpoint( PDI_EP0_RX, 255, (unsigned char *)pdreq);
+ if ( usb_rxtx_control.req_size == 0xff) {
+ /*LEDr = 1; SetLeds( hlp[0]);*/
+ debugPrint( DBG_LOW,("! BIG Setup packet\n"));
+ usb_stall_ep0();
+ return;
+ }
+ pdiAckSetupControl();
+ /* !!! it must be here !!! */
+ pdreq->wValue = SWAP( pdreq->wValue);
+ pdreq->wIndex = SWAP( pdreq->wIndex);
+ pdreq->wLength = SWAP( pdreq->wLength);
+
+ usb_rxtx_control.next_pkt_fnc = NULL;
+ usb_rxtx_control.complete_fnc = NULL;
+
+ ctrl_data[0] = ctrl_data[1] = 0; // we need only 2 bytes
+
+ #ifdef DEBUG
+ debugPrint( DBG_HIGH, ("Receive (0x%X) %s req. for %s , data %s host\n",
+ pdreq->bmRequestType, ReqType( pdreq->bmRequestType),
+ ReqRecipient(pdreq->bmRequestType),
+ ((pdreq->bmRequestType & USB_DATA_DIR_MASK) ? "TO":"FROM")));
+ debugPrint( DBG_HIGH, (" Request (0x%X) %s\n", pdreq->bRequest,
+ ((!(pdreq->bmRequestType&USB_REQUEST_TYPE_MASK))? ReqName( pdreq->bRequest):"UNKNOWN")));
+ #endif
+
+ switch( pdreq->bmRequestType & USB_RECIPIENT) {
+ case USB_RECIPIENT_DEVICE:
+ switch( pdreq->bmRequestType & USB_REQUEST_TYPE_MASK) {
+ case USB_STANDARD_REQUEST:
+ switch( pdreq->bRequest) {
+ case USB_REQUEST_GET_STATUS:
+ #ifdef USB_MY_SELF_POWER
+ ctrl_data[0]=1;
+ #else
+ ctrl_data[0]=0;
+ #endif
+ USB_SET_CONTROL_DATA( &ctrl_data, 2);
+ //pdiWriteEndpoint( PDI_EP0_TX, 2, hlp);
+ break;
+ case USB_REQUEST_SET_ADDRESS:
+ usb_address = ( unsigned char)( pdreq->wValue & DEVICE_ADDRESS_MASK);
+ pdiSetAddressEnable( usb_address | PDI_ENAD_ENABLE);
+ USB_SET_CONTROL_ACK;
+ //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+ break;
+ case USB_REQUEST_GET_DESCRIPTOR:
+ usb_get_descriptor();
+ break;
+ case USB_REQUEST_GET_CONFIGURATION:
+ if ( usb_flags.configured) ctrl_data[0] = 1;
+ USB_SET_CONTROL_DATA( &ctrl_data, 1);
+ //pdiWriteEndpoint( PDI_EP0_TX, 1, hlp);
+ break;
+ case USB_REQUEST_SET_CONFIGURATION:
+ if (LSB( pdreq->wValue) < 2) {
+ if ( LSB( pdreq->wValue)) {
+ pdiSetEndpointEnable( usb_flags.configured=1);
+ } else {
+ pdiSetEndpointEnable( usb_flags.configured=0);
+ }
+ USB_SET_CONTROL_ACK;
+ //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+ } else
+ usb_stall_ep0();
+ break;
+ default:
+ usb_stall_ep0();
+ break;
+ }
+
+ break;
+ case USB_VENDOR_REQUEST:
+ if(usb_vendor_extension) {
+ int ret;
+ ret = usb_vendor_extension(&usb_rxtx_control, pdreq);
+ if (ret<0) {
+ usb_stall_ep0();
+ break;
+ }
+ if (ret>0) {
+ break;
+ }
+ }
+
+ switch ( pdreq->bRequest) {
+ case USB_VENDOR_START_TRANSFER:
+ {
+ unsigned long max = ((long)pdreq->wIndex << 16)+pdreq->wValue;
+ usb_rx_bulk.remain = ( usb_rx_bulk.bytes < max) ? usb_rx_bulk.bytes : max;
+ }
+ USB_SET_CONTROL_ACK;
+ break;
+ case USB_VENDOR_CONTROL_TERMINAL_MODE:
+ if ( pdreq->wValue == 1) usb_flags.terminal_mode = 1;
+ else usb_flags.terminal_mode = 0;
+ USB_SET_CONTROL_ACK;
+ break;
+ default:
+ USB_SET_CONTROL_ACK;
+ //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+ break;
+ }
+ break;
+ case USB_CLASS_REQUEST:
+ usb_stall_ep0();
+ default:
+ usb_stall_ep0();
+ break;
+ }
+ break;
+ case USB_RECIPIENT_INTERFACE:
+ if (( pdreq->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_STANDARD_REQUEST) {
+ switch( pdreq->bRequest) {
+ case USB_REQUEST_GET_STATUS:
+ USB_SET_CONTROL_DATA( &ctrl_data, 2);
+ //pdiWriteEndpoint( PDI_EP0_TX, 2, hlp);
+ break;
+ case USB_REQUEST_GET_INTERFACE:
+ debugPrint( DBG_HIGH,("ReqIfc=%d Now ifc=%d\n", pdreq->wIndex, usb_interface));
+ USB_SET_CONTROL_DATA( &ctrl_data, 1); // alternate interface
+ //pdiWriteEndpoint( PDI_EP0_TX, 1, hlp);
+ break;
+ case USB_REQUEST_SET_INTERFACE:
+ //if (( dreq.wValue == 0) && ( dreq.wIndex == 0))
+ if ( pdreq->wIndex < 1) { // mame jen 2 pokusne interface
+ usb_interface = (unsigned char) pdreq->wIndex;
+ USB_SET_CONTROL_ACK;
+ //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+ } else
+ usb_stall_ep0();
+ break;
+ default:
+ usb_stall_ep0();
+ }
+ } else
+ usb_stall_ep0();
+ break;
+ case USB_RECIPIENT_ENDPOINT:
+ if (( pdreq->bmRequestType & USB_REQUEST_TYPE_MASK) == USB_STANDARD_REQUEST) {
+ switch( pdreq->bRequest) {
+ case USB_REQUEST_GET_STATUS:
+ case USB_REQUEST_CLEAR_FEATURE:
+ case USB_REQUEST_SET_FEATURE:
+ {
+ ctrl_data[0] = ( unsigned char)(( pdreq->wIndex & PDI_CNT_EP)<<1);
+ if ( pdreq->wIndex & ( unsigned char) USB_ENDPOINT_DIRECTION_MASK)
+ ctrl_data[0]++;
+ if ( pdreq->bRequest == USB_REQUEST_GET_STATUS) {
+ ctrl_data[0] = pdiSelectEp( ctrl_data[0]); // endpoint in
+ ctrl_data[0] = (( ctrl_data[0] & PDI_SELEP_STALL) == PDI_SELEP_STALL);
+ USB_SET_CONTROL_DATA( &ctrl_data, 2);
+ //pdiWriteEndpoint( PDI_EP0_TX, 2, hlp);
+ } else {
+ if ( pdreq->bRequest == USB_REQUEST_CLEAR_FEATURE) {
+ pdiSetEpStatus( ctrl_data[0], 0);
+ //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+ } else {
+ pdiSetEpStatus( ctrl_data[0], 1);
+ //pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+ }
+ USB_SET_CONTROL_ACK;
+ }
+ }
+ break;
+ default:
+ usb_stall_ep0();
+ }
+ } else
+ usb_stall_ep0();
+ break;
+// case USB_RECIPIENT_OTHER:
+ default:
+ usb_stall_ep0();
+ break;
+ }
+// usb_flags.command = 0; // ??? data or ack stage ???
+
+#ifdef USE_USB_WITH_IRQ
+// send data if it is needed
+ if ( usb_flags.request == 2) { // request is set to data stage
+ if (( usb_rxtx_control.dreq.bmRequestType & USB_DATA_DIR_MASK)==USB_DATA_DIR_TO_HOST) {
+ unsigned int now = usb_rxtx_control.bytes;
+ if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+ if ( usb_rxtx_control.next_pkt_fnc )
+ if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, now, USB_NEXT_PKT_SEND) ) {
+ usb_stall_ep0();
+ return;
+ }
+ debugPrint( DBG_HIGH, ("CNTR send 1.data (%d)\n", now));
+ pdiWriteEndpoint( PDI_EP0_TX, now, usb_rxtx_control.data);
+ usb_rxtx_control.data += now;
+ if ( !(usb_rxtx_control.bytes -= now)) {
+ usb_flags.request = 3;
+ }
+ }
+ }
+ if ( usb_flags.request == 3) {
+ if ( !usb_rxtx_control.dreq.wLength ||
+ (usb_rxtx_control.dreq.bmRequestType & USB_DATA_DIR_MASK)==USB_DATA_DIR_FROM_HOST) {
+ pdiWriteEndpoint( PDI_EP0_TX, 0, 0);
+ if ( usb_rxtx_control.complete_fnc )
+ usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+ usb_rxtx_control.next_pkt_fnc = NULL;
+ usb_rxtx_control.complete_fnc = NULL;
+ }
+ }
+#endif
+ }
+
+#ifdef DEBUG
+ char *DescType( unsigned char desc) {
+ switch ( desc) {
+ case USB_DESCRIPTOR_TYPE_DEVICE: return"DEVICE";
+ case USB_DESCRIPTOR_TYPE_CONFIGURATION: return"CONFIGURATION";
+ case USB_DESCRIPTOR_TYPE_STRING: return"STRING";
+ case USB_DESCRIPTOR_TYPE_INTERFACE: return"INTERFACE";
+ case USB_DESCRIPTOR_TYPE_ENDPOINT: return"ENDPOINT";
+ case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: return"DEVICE_QUALIFIER";
+ case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION: return"OTHER_SPEED_CONFIG";
+ case USB_DESCRIPTOR_TYPE_POWER: return"POWER";
+ }
+ return "UNKNOWN";
+ }
+#endif
+
+ void usb_get_descriptor( void) {
+ unsigned int size;
+ unsigned short wVal = usb_rxtx_control.dreq.wValue;
+ debugPrint( DBG_MEDIUM, (" - %s descriptor\n", DescType(MSB( wVal))));
+ switch ( MSB( wVal)) {
+ case USB_DESCRIPTOR_TYPE_DEVICE:
+ usb_rxtx_control.data = (unsigned char *) &usb_device_descriptor;
+ size = sizeof( USB_DEVICE_DESCRIPTOR);
+ break;
+ case USB_DESCRIPTOR_TYPE_CONFIGURATION:
+ usb_rxtx_control.data = (unsigned char *) &usb_config_0;
+ size = CONFIG_0_DESCRIPTOR_LENGTH;
+ break;
+ case USB_DESCRIPTOR_TYPE_STRING:
+ if ( LSB( wVal) < USB_CNT_STRINGS) {
+ usb_rxtx_control.data = (unsigned char *) StringDescriptors[ LSB( wVal)];
+ size = *usb_rxtx_control.data;
+ } else {
+ usb_stall_ep0();
+ return;
+ }
+ break;
+ default:
+ usb_stall_ep0();
+ return;
+ }
+ usb_rxtx_control.bytes = ( usb_rxtx_control.dreq.wLength < size) ? usb_rxtx_control.dreq.wLength : size;
+ usb_flags.request = 2;
+ //usb_send_to_usb( SEND_EP0, PDI_EP0_PACKET_SIZE);
+ }
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*** ***/
+/*** USB with IRQ ***/
+/*** ***/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+
+ #ifdef PDIUSB_WITH_EXCPTVECT_SET
+ void usb_isr(void)
+ #else /*PDIUSB_WITH_EXCPTVECT_SET*/
+ void usb_isr(int intno, void *dev_id, struct pt_regs *regs)
+ #endif /*PDIUSB_WITH_EXCPTVECT_SET*/
+ {
+ unsigned char usb_last_status;
+
+ usb_irq_cnt++;
+ usb_last_irq = pdiGetInterrupt();
+ if ( usb_last_irq) {
+ usb_flags.was_int = 1;
+
+ debugPrint( DBG_INT, ("USB Interrupt 0x%X\n",usb_last_irq));
+ if ( usb_last_irq & PDI_INT_BUSRESET) { // D12 - Bus reset reached
+ usb_flags.configured = 0;
+ if ( usb_flags.running && usb_flags.stop_request) {
+ usb_flags.running = 0;
+ usb_flags.stop_request = 0;
+ }
+ debugPrint( DBG_INT, ("Bus Reset\n"));
+ } else {
+ if ( usb_last_irq & PDI_INT_SUSPEND) { // D12 - Suspend flag changed
+ debugPrint( DBG_INT, ("Suspend Changed\n"));
+ }
+ // it must be first b/c tx and rx can be sended all together
+ if ( usb_last_irq & PDI_INT_EP0_IN) { // D12 - Ep0TxDone - data in EP0 was sended
+ usb_last_status = pdiGetLastTransStatus( PDI_EP0_TX);
+ debugPrint( DBG_INT, ("Ep0-Tx LTS=0x%X\n", usb_last_status));
+ if (( usb_last_status & PDI_LTSTAT_RXTX_OK) && usb_flags.request > 1) {
+ if ( usb_flags.request == 2) {
+ unsigned int now = usb_rxtx_control.bytes;
+ if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+ debugPrint( DBG_INT, ("CNTR data\n"));
+ pdiWriteEndpoint( PDI_EP0_TX, now, usb_rxtx_control.data);
+ usb_rxtx_control.data += now;
+ if ( !(usb_rxtx_control.bytes -= now)) {
+ usb_flags.request = 3;
+ }
+ } else if ( usb_flags.request == 3) {
+ debugPrint( DBG_INT, ("CNTR ack\n"));
+ usb_flags.request = 0;
+ } else {
+ debugPrint( DBG_INT, ("tx 0 ... ???\n"));
+ }
+ }
+ }
+
+ if ( usb_last_irq & PDI_INT_EP0_OUT) { // D12 - Ep0RxDone - some data was received in EP0
+ usb_last_status = pdiGetLastTransStatus( PDI_EP0_RX);
+ debugPrint( DBG_INT, ("Ep0-Rx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ if ( usb_last_status & PDI_LTSTAT_SETUP) {
+ if ( usb_flags.request) {
+ debugPrint( DBG_INT, ("!!! New setup, but last not ack ...\n"));
+ }
+ usb_flags.request = 1; // Standard_requests();
+ usb_answer_to_request();
+ } else {
+ if ( usb_flags.request == 2) {
+ unsigned int now = usb_rxtx_control.bytes, ret;
+ if ( now > PDI_EP0_PACKET_SIZE) now = PDI_EP0_PACKET_SIZE;
+ debugPrint( DBG_INT, ("CNTR data\n"));
+ ret = pdiReadEndpoint( PDI_EP0_RX, now, usb_rxtx_control.data);
+
+ if(ret>usb_rxtx_control.bytes)
+ ret = usb_rxtx_control.bytes;
+
+ usb_rxtx_control.data += ret;
+
+ if ( usb_rxtx_control.next_pkt_fnc ) {
+ if( usb_rxtx_control.next_pkt_fnc(&usb_rxtx_control, ret, USB_NEXT_PKT_REC) ) {
+ usb_stall_ep0();
+ }
+ }
+
+ if (!(usb_rxtx_control.bytes -= ret)) {
+ usb_rxtx_control.data -= usb_rxtx_control.dreq.wLength;
+ usb_flags.request = 3;
+ }
+ } else if ( usb_flags.request == 3) {
+ debugPrint( DBG_INT, ("CNTR ack\n"));
+ usb_flags.request = 0;
+ pdiReadEndpoint( PDI_EP0_RX, 0, 0);
+ if ( usb_rxtx_control.complete_fnc )
+ usb_rxtx_control.complete_fnc(&usb_rxtx_control, USB_COMPLETE_OK);
+ usb_rxtx_control.next_pkt_fnc = NULL;
+ usb_rxtx_control.complete_fnc = NULL;
+ } else {
+ pdiReadEndpoint( PDI_EP0_RX, 0, 0);
+ }
+ }
+ }
+ }
+ if ( usb_last_irq & PDI_INT_EP1_OUT) { // D12 - Ep1RxDone - some data was received in EP1
+ usb_last_status = pdiGetLastTransStatus( PDI_EP1_RX);
+ debugPrint( DBG_INT, ("Ep1-Rx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ pdiSetEpStatus( PDI_EP1_OUT, PDI_SET_EP_STALLED);
+ }
+ }
+ if ( usb_last_irq & PDI_INT_EP1_IN) { // D12 - Ep1TxDone - data in EP1 was sended
+ usb_last_status = pdiGetLastTransStatus( PDI_EP1_TX);
+ debugPrint( DBG_INT, ("Ep1-Tx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ pdiSetEpStatus( PDI_EP1_IN, PDI_SET_EP_STALLED);
+ }
+ }
+
+ if ( usb_last_irq & PDI_INT_EP2_OUT) { // D12 - Ep2RxDone - some data was received in EP2
+ usb_last_status = pdiGetLastTransStatus( PDI_EP2_RX);
+ debugPrint( DBG_INT, ("Ep2-Rx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ if ( usb_flags.terminal_mode) {
+ unsigned char hlpbfr[PDI_EP2_PACKET_SIZE], now = PDI_EP2_PACKET_SIZE, i;
+ MoreRead:
+ now = pdiReadEndpoint( PDI_EP2_RX, now, hlpbfr);
+ for(i=0;i<now;i++) {
+ usb_tm_rcv++;
+ if (usb_com_put( &usb_com_que_in, hlpbfr[i])<0) { /* nevkladat dalsi */
+ break;
+ }
+ }
+ if(now==PDI_EP2_PACKET_SIZE) goto MoreRead;
+ } else {
+ unsigned char now = (usb_rx_bulk.remain > (unsigned long)PDI_EP2_PACKET_SIZE)?PDI_EP2_PACKET_SIZE:(unsigned char)usb_rx_bulk.remain;
+ // unsigned char hlp[2];
+
+ if ( !usb_flags.bits.bulk_rx_data) {
+ usb_flags.bulk_rx_data = 1;
+ usb_start = msec_time;
+ }
+ // if ( now > PDI_EP2_PACKET_SIZE) now = PDI_EP2_PACKET_SIZE;
+ ReadAgain:
+ now = pdiReadEndpoint( PDI_EP2_RX, now, usb_rx_bulk.data);
+ usb_rx_bulk.data += now;
+ if ( !( usb_rx_bulk.remain -= now)) {
+ usb_stop = msec_time;
+ usb_flags.bulk_rx_data = 0;
+ // complete_func or set flag(event)
+ }
+ if ( usb_rx_bulk.remain > 0 && usb_rx_bulk.remain <= PDI_EP2_PACKET_SIZE)
+ goto ReadAgain;
+ }
+ }
+ }
+ if ( usb_last_irq & PDI_INT_EP2_IN) { // D12 - Ep2TxDone - data in EP2 was sended
+ usb_last_status = pdiGetLastTransStatus( PDI_EP2_TX);
+ debugPrint( DBG_INT, ("Ep2-Tx LTS=0x%X\n", usb_last_status));
+ if ( usb_last_status & PDI_LTSTAT_RXTX_OK) {
+ if ( usb_flags.terminal_mode) {
+ int ch;
+ usb_tm_snded++;
+ ch = usb_com_get( &usb_com_que_out);
+ if ( ch < 0) {
+ usb_flags.bulk_tx_data = 0;
+ } else {
+ unsigned char uchr = ch;
+ usb_flags.bulk_tx_data = 1;
+ pdiWriteEndpoint( PDI_EP2_TX, 1, &uchr);
+ }
+ } else {
+ if ( usb_tx_bulk.remain) {
+ unsigned int now = usb_tx_bulk.remain;
+ if ( now > PDI_EP2_PACKET_SIZE) now = PDI_EP2_PACKET_SIZE;
+ pdiWriteEndpoint( PDI_EP2_TX, now, usb_tx_bulk.data);
+ usb_tx_bulk.data += now;
+ if (!(usb_tx_bulk.remain -= now)) {
+ // complete_func or set flag(event)
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+#ifdef PDIUSB_WITH_ADD_IRQ_HANDLER
+ irq_handler_t usb_irq_handler = {
+ handler: usb_isr,
+ flags: 0,
+ dev_id: 0,
+ devname: "usb",
+ next: 0
+ };
+#endif /*PDIUSB_WITH_ADD_IRQ_HANDLER*/
+
+
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+/*** ***/
+/*** USB COM Emulator Module ***/
+/*** ***/
+/*****************************************************************************/
+/*****************************************************************************/
+/*****************************************************************************/
+ int usb_tm_snd;
+ int usb_tm_snded;
+ int usb_tm_rcv;
+
+ int usb_com_init( void) {
+ usb_tm_snd = 0;
+ usb_tm_snded = 0;
+ usb_tm_rcv = 0;
+
+ usb_com_que_in.begin=usb_com_buf_in;
+ usb_com_que_in.end=usb_com_que_in.begin+sizeof(usb_com_buf_in);
+ usb_com_que_in.first=usb_com_que_in.begin;
+ usb_com_que_in.last=usb_com_que_in.begin;
+
+ usb_com_que_out.begin=usb_com_buf_out;
+ usb_com_que_out.end=usb_com_que_out.begin+sizeof(usb_com_buf_out);
+ usb_com_que_out.first=usb_com_que_out.begin;
+ usb_com_que_out.last=usb_com_que_out.begin;
+
+ return 1;
+ }
+
+ /* put character c into queue, if full return -1 */
+ int usb_com_put(usb_com_que_t *q, int c)
+ {
+ unsigned char *p=q->last;
+ *(p++)=(unsigned char)c;
+ if (p==q->end) p=q->begin;
+ if (p==q->first) return -1;
+ q->last=p;
+ return c;
+ }
+ /* get character from queue, if empty return -1 */
+ int usb_com_get(usb_com_que_t *q)
+ {
+ unsigned char *p;
+ int c;
+ p=q->first;
+ if(p==q->last) return -1;
+ c=*(p++);
+ if(p==q->end) p=q->begin;
+ q->first=p;
+ return c;
+ }
+
+/*
+ int usb_com_sendch(int c) {
+ if ( usb_flags.terminal_mode) {
+ usb_tm_snd++;
+ if ( !usb_flags.bits.bulk_tx_data) { // hned poslat - atomicke nastaveni flagu ...
+ unsigned char byte = c;
+ pdiWriteEndpoint( PDI_EP2_TX, 1, (unsigned char *)&byte);
+ usb_flags.bulk_tx_data = 1;
+ } else {
+ if( usb_com_put(&usb_com_que_out,c)<0){ // nevejde se
+#ifdef USE_USB_WITH_IRQ
+ while( usb_com_que_out.last == usb_com_que_out.first-1); // Wait if buffer is full !@#$%^&*
+ if( usb_com_put(&usb_com_que_out,c)<0) // case (last==end and first==begin) not respected
+#endif
+ c=-1;
+ }
+ }
+ }
+ return c;
+ }
+*/
+ void usb_com_start_send( void) {
+ if ( !usb_flags.bits.bulk_tx_data &&
+ usb_com_que_out.first != usb_com_que_out.last) {
+ int ch;
+ ch = usb_com_get( &usb_com_que_out);
+ if ( ch >= 0) {
+ unsigned char byte = ch;
+ usb_flags.bulk_tx_data = 1;
+ pdiWriteEndpoint( PDI_EP2_TX, 1, &byte);
+ }
+ }
+ }
+
+ int usb_com_sendch(int c) {
+ if ( usb_flags.terminal_mode) {
+ usb_tm_snd++;
+#ifndef USE_USB_WITH_IRQ
+ if( !usb_flags.bits.bulk_tx_data) {
+ unsigned char byte = c;
+ usb_flags.bulk_tx_data = 1;
+ pdiWriteEndpoint( PDI_EP2_TX, 1, &byte);
+ return c;
+ }
+#endif
+ if( usb_com_put(&usb_com_que_out,c)<0){ /* nevejde se */
+
+#ifdef USE_USB_WITH_IRQ
+ if ( !usb_flags.bits.bulk_tx_data) {
+ usb_com_start_send();
+ } else {
+ while( usb_com_que_out.last == usb_com_que_out.first-1); /* Wait if buffer is full !@#$%^&* */
+ }
+ if( usb_com_put(&usb_com_que_out,c)<0) /* case (last==end and first==begin) isn't respected */
+#endif
+ c=-1;
+ }
+ }
+ return c;
+ }
+
+
+
+ int usb_com_recch() {
+ int val;
+ if ( !usb_flags.bits.terminal_mode) return -1;
+ val=usb_com_get(&usb_com_que_in);
+ return val;
+ }
+
+ int usb_com_sendstr(const char *s) {
+ int cnt=0;
+ while(*s)
+ {
+ if(usb_com_sendch((unsigned char)(*(s++)))<0) break;
+ cnt++;
+ }
+ return cnt;
+ }
+