tiagotauruz

v-usb

Jul 27th, 2017
482
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* Nes/Snes/Genesis/SMS/Atari to USB
  2.  * Copyright (C) 2006-2007 Raphaël Assénat
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License along
  15.  * with this program; if not, write to the Free Software Foundation, Inc.,
  16.  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17.  *
  18.  * The author may be contacted at raph@raphnet.net
  19.  */
  20. #include <avr/io.h>
  21. #include <avr/interrupt.h>
  22. #include <avr/pgmspace.h>
  23. #include <avr/wdt.h>
  24. #include <util/delay.h>
  25. #include <string.h>
  26.  
  27. #include "usbdrv.h"
  28. #include "oddebug.h"
  29. #include "gamepad.h"
  30.  
  31. #include "twelve.h"
  32.  
  33. #include "devdesc.h"
  34.  
  35. static uchar *rt_usbHidReportDescriptor=NULL;
  36. static uchar rt_usbHidReportDescriptorSize=0;
  37. static uchar *rt_usbDeviceDescriptor=NULL;
  38. static uchar rt_usbDeviceDescriptorSize=0;
  39.  
  40. PROGMEM int usbDescriptorStringSerialNumber[]  = {
  41.     USB_STRING_DESCRIPTOR_HEADER(4),
  42.     '1','0','0','0'
  43. };
  44.  
  45. char usbDescriptorConfiguration[] = { 0 }; // dummy
  46.  
  47. uchar my_usbDescriptorConfiguration[] = {    /* USB configuration descriptor */
  48.     9,          /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
  49.     USBDESCR_CONFIG,    /* descriptor type */
  50.     18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 9, 0,
  51.                 /* total length of data returned (including inlined descriptors) */
  52.     1,          /* number of interfaces in this configuration */
  53.     1,          /* index of this configuration */
  54.     0,          /* configuration name string index */
  55. #if USB_CFG_IS_SELF_POWERED
  56.     USBATTR_SELFPOWER,  /* attributes */
  57. #else
  58.     USBATTR_BUSPOWER,   /* attributes */
  59. #endif
  60.     USB_CFG_MAX_BUS_POWER/2,            /* max USB current in 2mA units */
  61. /* interface descriptor follows inline: */
  62.     9,          /* sizeof(usbDescrInterface): length of descriptor in bytes */
  63.     USBDESCR_INTERFACE, /* descriptor type */
  64.     0,          /* index of this interface */
  65.     0,          /* alternate setting for this interface */
  66.     USB_CFG_HAVE_INTRIN_ENDPOINT,   /* endpoints excl 0: number of endpoint descriptors to follow */
  67.     USB_CFG_INTERFACE_CLASS,
  68.     USB_CFG_INTERFACE_SUBCLASS,
  69.     USB_CFG_INTERFACE_PROTOCOL,
  70.     0,          /* string index for interface */
  71. //#if (USB_CFG_DESCR_PROPS_HID & 0xff)    /* HID descriptor */
  72.     9,          /* sizeof(usbDescrHID): length of descriptor in bytes */
  73.     USBDESCR_HID,   /* descriptor type: HID */
  74.     0x01, 0x01, /* BCD representation of HID version */
  75.     0x00,       /* target country code */
  76.     0x01,       /* number of HID Report (or other HID class) Descriptor infos to follow */
  77.     0x22,       /* descriptor type: report */
  78.     USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH, 0,  /* total length of report descriptor */
  79. //#endif
  80. #if USB_CFG_HAVE_INTRIN_ENDPOINT    /* endpoint descriptor for endpoint 1 */
  81.     7,          /* sizeof(usbDescrEndpoint) */
  82.     USBDESCR_ENDPOINT,  /* descriptor type = endpoint */
  83.     0x81,       /* IN endpoint number 1 */
  84.     0x03,       /* attrib: Interrupt endpoint */
  85.     8, 0,       /* maximum packet size */
  86.     USB_CFG_INTR_POLL_INTERVAL, /* in ms */
  87. #endif
  88. };
  89.  
  90. static Gamepad *curGamepad;
  91.  
  92.  
  93. /* ----------------------- hardware I/O abstraction ------------------------ */
  94.  
  95. static void hardwareInit(void)
  96. {
  97.     uchar   i, j;
  98.  
  99.     // init port C as input with pullup
  100.     DDRC = 0x00;
  101.     PORTC = 0xff;
  102.    
  103.     /* 1101 1000 bin: activate pull-ups except on USB lines
  104.      *
  105.      * USB signals are on bit 0 and 2.
  106.      *
  107.      * Bit 1 is connected with bit 0 (rev.C pcb error), so the pullup
  108.      * is not enabled.
  109.      * */
  110.     PORTD = 0xf8;  
  111.  
  112.     /* Usb pin are init as outputs */
  113.     DDRD = 0x01 | 0x04;    
  114.  
  115.    
  116.     j = 0;
  117.     while(--j){     /* USB Reset by device only required on Watchdog Reset */
  118.         i = 0;
  119.         while(--i); /* delay >10ms for USB reset */
  120.     }
  121.     DDRD = 0x00;    /* 0000 0000 bin: remove USB reset condition */
  122.             /* configure timer 0 for a rate of 12M/(1024 * 256) = 45.78 Hz (~22ms) */
  123.     TCCR0 = 5;      /* timer 0 prescaler: 1024 */
  124.  
  125.     TCCR2 = (1<<WGM21)|(1<<CS22)|(1<<CS21)|(1<<CS20);
  126.     OCR2 = 196; // for 60 hz
  127.  
  128. }
  129.  
  130. static uchar    reportBuffer[6];    /* buffer for HID reports */
  131.  
  132.  
  133.  
  134. /* ------------------------------------------------------------------------- */
  135. /* ----------------------------- USB interface ----------------------------- */
  136. /* ------------------------------------------------------------------------- */
  137.  
  138. static uchar    idleRate;           /* in 4 ms units */
  139.  
  140. uchar   usbFunctionDescriptor(struct usbRequest *rq)
  141. {
  142.     if ((rq->bmRequestType & USBRQ_TYPE_MASK) != USBRQ_TYPE_STANDARD)
  143.         return 0;
  144.  
  145.     if (rq->bRequest == USBRQ_GET_DESCRIPTOR)
  146.     {
  147.         // USB spec 9.4.3, high byte is descriptor type
  148.         switch (rq->wValue.bytes[1])
  149.         {
  150.             case USBDESCR_DEVICE:
  151.                 usbMsgPtr = rt_usbDeviceDescriptor;    
  152.                 return rt_usbDeviceDescriptorSize;
  153.             case USBDESCR_HID_REPORT:
  154.                 usbMsgPtr = rt_usbHidReportDescriptor;
  155.                 return rt_usbHidReportDescriptorSize;
  156.             case USBDESCR_CONFIG:
  157.                 usbMsgPtr = my_usbDescriptorConfiguration;
  158.                 return sizeof(my_usbDescriptorConfiguration);
  159.         }
  160.     }
  161.  
  162.     return 0;
  163. }
  164.  
  165. uchar   usbFunctionSetup(uchar data[8])
  166. {
  167.     usbRequest_t    *rq = (void *)data;
  168.  
  169.     usbMsgPtr = reportBuffer;
  170.     if((rq->bmRequestType & USBRQ_TYPE_MASK) == USBRQ_TYPE_CLASS){    /* class request type */
  171.         if(rq->bRequest == USBRQ_HID_GET_REPORT){  /* wValue: ReportType (highbyte), ReportID (lowbyte) */
  172.             /* we only have one report type, so don't look at wValue */
  173.             curGamepad->buildReport(reportBuffer);
  174.             return curGamepad->report_size;
  175.         }else if(rq->bRequest == USBRQ_HID_GET_IDLE){
  176.             usbMsgPtr = &idleRate;
  177.             return 1;
  178.         }else if(rq->bRequest == USBRQ_HID_SET_IDLE){
  179.             idleRate = rq->wValue.bytes[1];
  180.         }
  181.     }else{
  182.     /* no vendor specific requests implemented */
  183.     }
  184.     return 0;
  185. }
  186.  
  187. /* ------------------------------------------------------------------------- */
  188.  
  189.  
  190. int main(void)
  191. {
  192.     char must_report = 0, first_run = 1;
  193.     uchar   idleCounter = 0;
  194.     int run_mode;
  195.  
  196.     // led pin as output
  197. //  DDRD |= 0x20;
  198.  
  199.     /* Dip switch common: DB0, outputs: DB1 and DB2 */
  200.     DDRB |= 0x01;
  201.     DDRB &= ~0x06;
  202.    
  203.     PORTB |= 0x06; /* enable pull up on DB1 and DB2 */
  204.     PORTB &= ~0x01; /* Set DB0 to low */
  205.  
  206.     _delay_ms(10); /* let pins settle */
  207.  
  208.     run_mode = (PINB & 0x06)>>1;
  209.  
  210.     curGamepad = twelveGetGamepad();
  211.    
  212.  
  213.     // configure report descriptor according to
  214.     // the current gamepad
  215.     rt_usbHidReportDescriptor = curGamepad->reportDescriptor;
  216.     rt_usbHidReportDescriptorSize = curGamepad->reportDescriptorSize;
  217.  
  218.     if (curGamepad->deviceDescriptor != 0)
  219.     {
  220.         rt_usbDeviceDescriptor = (void*)curGamepad->deviceDescriptor;
  221.         rt_usbDeviceDescriptorSize = curGamepad->deviceDescriptorSize;
  222.     }
  223.     else
  224.     {
  225.         // use descriptor from devdesc.c
  226.         //
  227.         rt_usbDeviceDescriptor = (void*)usbDescrDevice;
  228.         rt_usbDeviceDescriptorSize = getUsbDescrDevice_size();
  229.     }
  230.  
  231.     // patch the config descriptor with the HID report descriptor size
  232.     my_usbDescriptorConfiguration[25] = rt_usbHidReportDescriptorSize;
  233.  
  234.     //wdt_enable(WDTO_2S);
  235.     hardwareInit();
  236.     curGamepad->init();
  237.     odDebugInit();
  238.     usbInit();
  239.     sei();
  240.     DBG1(0x00, 0, 0);
  241.  
  242.    
  243.     for(;;){    /* main event loop */
  244.         wdt_reset();
  245.  
  246.         // this must be called at each 50 ms or less
  247.         usbPoll();
  248.  
  249.         if (first_run) {
  250.             curGamepad->update();
  251.             first_run = 0;
  252.         }
  253.  
  254.         if(TIFR & (1<<TOV0)){   /* 22 ms timer */
  255.             TIFR = 1<<TOV0;
  256.             if(idleRate != 0){
  257.                 if(idleCounter > 4){
  258.                     idleCounter -= 5;   /* 22 ms in units of 4 ms */
  259.                 }else{
  260.                     idleCounter = idleRate;
  261.                     must_report = 1;
  262.                 }
  263.             }
  264.         }
  265.  
  266.         if (TIFR & (1<<OCF2))
  267.         {
  268.             TIFR = 1<<OCF2;
  269.             if (!must_report)
  270.             {
  271.                 curGamepad->update();
  272.                 if (curGamepad->changed()) {
  273.                     must_report = 1;
  274.                 }
  275.             }
  276.  
  277.         }
  278.        
  279.            
  280.         if(must_report)
  281.         {
  282.             if (usbInterruptIsReady())
  283.             {  
  284.  
  285.             must_report = 0;
  286.  
  287.             curGamepad->buildReport(reportBuffer);
  288.             usbSetInterrupt(reportBuffer, curGamepad->report_size);
  289.             }
  290.         }
  291.         /* 
  292.         if(must_report && usbInterruptIsReady()){
  293.             must_report = 0;
  294.  
  295.             curGamepad->buildReport(reportBuffer);
  296.             usbSetInterrupt(reportBuffer, curGamepad->report_size);
  297.         }
  298. */
  299.     }
  300.     return 0;
  301. }
  302.  
  303. /* ------------------------------------------------------------------------- */
RAW Paste Data