#include "i2c.h" #include "firm.h" #include "ezusb_reg.h" #include "surf_mem.h" #undef SURF_DRIVER #include "surf_drv.h" /* * USB related stuff */ /* the device descriptor */ static code Byte dev_desc[] = { 0x12, // bLength : Length of Descriptor 0x01, // bDescriptorType : Descriptor Type = Device 0x00, // bcdUSB (L) : USB Specification Version 1.00 (L) 0x01, // bcdUSB (H) : USB Specification Version 1.00 (H) 0x00, // bDeviceClass : Device Class (0xff is Vendor Specific) 0x00, // bDeviceSubClass : Device Sub-Class (0xff is Vendor Specific) 0x00, // bDeviceProtocol : Device Protocol (0xff is Vendor Specific) 0x40, // bMaxPacketSize0 : Maximum Packet Size for EP0 0x42, // idVendor (L) : Vendor ID (L) 0x42, // idVendor (H) : Vendor ID (H) 0xef, // idProduct (L) : Product ID (L) 0xbe, // idProduct (H) : Product ID (H) 0x0a, // bcdDevice (L) : Device Release Number (BCD,L) 0x00, // bcdDevice (H) : Device Release Number (BCD,H) 0x01, // iManufacturer : Manufacturer Index String 0x02, // iProduct : Product Index String 0x03, // iSerialNumber : Serial Number Index String 0x01 // bNumConfigurations : Number of Configurations in this Device }; /* the configuration descriptor */ static code Byte conf_desc[] = { 0x09, // bLength : Length of Descriptor 0x02, // bDescriptorType : Descriptor Type = Configuration 0x5f, // wTotalLength (L) : Total Length (L) including Interface and Endpoint 0x00, // wTotalLength (H) : Total Length (H) 0x01, // bNumInterfaces : One Interface in this Configuration 0x01, // bConfigurationValue : Configuration Value Used by Set_Configuration Request // to Select this Configuration 0x00, // iConfiguration : Index of String Describing this Configuration 0xc0, // bmAttributes : Attributes 0x01, // MaxPower : Maximum Power // Interface 0, alternate setting 0 0x09, // bLength : Length of Descriptor 0x04, // bDescriptorType : Descriptor Type = Interface 0x00, // bInterfaceNumber : Zero-based index of this Interface 0x00, // bAlternateSetting : Alternate Setting 0x0b, // bNumEndpoints : Number of Endpoints in this Interface 0xff, // bInterfaceClass : Interface Class 0xff, // bInterfaceSubClass : Interface Sub-Class (boot interface) 0xff, // bInterfaceProtocol : Interface Protocol (keyboard) 0x01, // iInterface : Index to String Descriptor for this Interface /* // HID Descriptor 0x09, // bLength : Length of Descriptor 0x21, // bDescriptorType : Descriptor Type = HID 0x00, // bcdHID (L) : HID Class Specification release number (L) 0x01, // bcdHID (H) : HID Class Specification release number (H) 0x21, // bCountryCode : Hardare target country = US 0x01, // bNumDescriptors : Number of HID class descriptors to follow 0x22, // bDescriptorType : Report descriptor type 0x3f, // wDescriptorLength(L): Total length of Report descriptor (L) 0x00, // wDescriptorLength(H): Total length of Report descriptor (H) */ // Endpoint Descriptor --- channel 0 in 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x81, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- channel 0 out 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x01, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- channel 1 in 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x82, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- channel 1 out 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x02, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- channel 2 in 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x83, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- channel 2 out 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x03, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- channel 3 in 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x84, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- channel 3 out 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x04, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- loopback in 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x85, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- loopback out 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x05, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01, // bInterval : Polling intervall in Milliseconds // Endpoint Descriptor --- dmesg in 0x07, // bLength : Length of Descriptor 0x05, // bDescriptorType : Descriptor Type = Endpoint 0x86, // bEndpointAddress : Endpoint Address 0x02, // bmAttributes : Endpoint Attributes = bulk 0x40, // wMaxPacketSize (L) : Maximum Packet Size (L) 0x00, // wMaxPacketSize (H) : Maximum Packet Size (H) 0x01 // bInterval : Polling intervall in Milliseconds }; /* language ID string descriptor */ static code Byte string_langid[] = { 0x03 }; /* manufacturer string descriptor */ static code Byte string_mfg[] = { 0x0c, 0x03, 'A',0, 'T',0, 'L',0, 'A',0, 'S',0, }; /* product string descriptor */ static code Byte string_prod[] = { 0x16, 0x03, 'S',0, 'u',0, 'R',0, 'F',0, ' ',0, 'b',0, 'o',0, 'a',0, 'r',0, 'd',0 }; /* serial number */ static code Byte string_sernum[] = { 0x1a, 0x3, /* '2',0, '0',0, '0',0, '3',0, '1',0, '1',0, 'L',0, 'B',0, 'L',0, */ /* '0',0, '0',0, '1',0 */ '2',0, '0',0, '0',0, '4',0, '0',0, '2',0, 'L',0, 'B',0, 'L',0, '0',0, '0',0, '5',0 }; /* interface string descriptor */ static code Byte string_if[] = { 0x0a, 0x03, 'S',0, 'u',0, 'r',0, 'f',0 }; static code byte string_rev[] = { /* format is major minor subminor */ /* if revision is experimental, put an e in the minor number */ 0x08, 0x03, 0x00, 0x00, 0x1e, 0x00, 0x06, 0x00 /* this is revision 00.1e.06 */ }; /* index for all string descriptors */ #define NUM_STRING 6 static data unsigned int string_index[NUM_STRING] = { (unsigned int)string_langid, (unsigned int)string_mfg, (unsigned int)string_prod, (unsigned int)string_sernum, (unsigned int)string_if, (unsigned int)string_rev }; static xdata setup_dat * data sdat = (xdata setup_dat *)&SETUPDAT; /***************************************************************************** * usb_isr() * * USB interrupt service routine * Performs five major tasks: * + parse the SETUP packets upon SUDAV interrupt and answer them * + ack IN0 interrupts * + ack IN1 interrupts * + ack IN2 interrupts * + ack OUT0 interrupts and send the SETLED command to the keyboard * * According to the EZ-USB Technical Reference Manual it is essential to * clear HSNACK when stalling EP0 (see section 12.12). *****************************************************************************/ void usb_isr(void) interrupt 8 using 1 critical { register byte i; /* clear INT2 interrupt */ EXIF &= 0xef; /* was this the SUDAV interrupt? */ if (USBIRQ & 0x01) { /* clear SUDAV interrupt */ USBIRQ = 0x01; /* debug for Joe */ /* FLASH; */ #ifdef VERBOSE_DEBUG log("control interrupt bRequest 0x"); logn((&_lookup) + (sdat->bRequest >> 4), 1); logn((&_lookup) + (sdat->bRequest & 0x0f), 1); log(" bmRequestType 0x"); logn((&_lookup) + (sdat->bmRequestType >> 4), 1); logn((&_lookup) + (sdat->bmRequestType & 0x0f), 1); log(" wValueL 0x"); logn((&_lookup) + (sdat->wValueL >> 4), 1); logn((&_lookup) + (sdat->wValueL & 0x0f), 1); log("\n\r"); #endif switch (sdat->bRequest) { /* bRequest == 0x00 */ case 0x00: switch (sdat->bmRequestType) { /* GetStatus(Device) TODO */ case 0x80: /* GetStatus(Interface) */ case 0x81: /* GetStatus(Endpoint) TODO*/ case 0x82: INBUF(0,0) = 0x00; INBUF(0,1) = 0x00; IN0BC = 0x02; EP0CS = 0x02; /* clear HSNACK */ break; default: EP0CS = 0x03; /* stall */ break; } break; /* bRequest == 0x01 */ case 0x01: switch (sdat->bmRequestType) { /* ClearFeature(Device) TODO */ case 0x00: EP0CS = 0x02; /* clear HSNACK */ break; /* ClearFeature(Interface) TODO */ case 0x01: EP0CS = 0x02; /* clear HSNACK */ break; /* ClearFeature(Endpoint) */ case 0x02: switch (sdat->wIndexL) { /* ClearFeature(EP) should reset TOGGLE bit (ref. USB spec 1.1, section 5.8.5) */ case 0x00: /* OUT0 */ TOGCTL = 0x00; TOGCTL = 0x20; EP0CS = 0x02; /* clear HSNACK */ break; case 0x80: /* IN0 */ TOGCTL = 0x10; TOGCTL = 0x30; EP0CS = 0x02; /* clear HSNACK */ break; case 0x81: /* IN1 */ EP0CS = 0x03; /* stall */ break; case 0x82: /* IN2 */ EP0CS = 0x03; /* stall */ break; } break; } /* SetFeature */ case 0x03: switch (sdat->bmRequestType) { /* SetFeature(Device) TODO */ case 0x00: EP0CS = 0x02; /* clear HSNACK */ break; /* SetFeature(Interface) TODO */ case 0x01: EP0CS = 0x02; /* clear HSNACK */ break; /* SetFeature(Endpoint) */ case 0x02: switch (sdat->wIndexL) { case 0x00: /* OUT0 */ EP0CS |= 0x01; /* stall endpoint */ TOGCTL = 0x00; TOGCTL = 0x20; OUT0BC = 0x00; EP0CS |= 0x02; /* clear HSNACK */ break; case 0x80: /* IN0 */ EP0CS |= 0x01; /* stall endpoint */ TOGCTL = 0x10; TOGCTL = 0x30; EP0CS |= 0x02; /* clear HSNACK */ break; case 0x81: /* IN1 */ EP0CS = 0x03; /* stall */ break; case 0x82: /* IN2 */ EP0CS = 0x03; /* stall */ break; default: EP0CS = 0x03; /* stall */ break; } break; /* Get_Protocol TODO */ case 0xa1: if (sdat->wIndexL == 0) { INBUF(0,0) = 1; /* always send Report protocol */ IN0BC = 0x01; EP0CS = 0x02; /* clear HSNACK */ } else EP0CS = 0x03; /* stall */ break; default: EP0CS = 0x03; /* stall */ break; } break; /* GetDescriptor */ case 0x06: switch (sdat->wValueH) { /* type: device */ case USB_DT_DEVICE: EP0CS = 0x02; /* clear HSNACK */ SUDPTRH = (Byte)((unsigned int)dev_desc >> 8); SUDPTRL = (unsigned int)dev_desc & 0xff; break; /* type: configuration */ case USB_DT_CONFIG: EP0CS = 0x02; /* clear HSNACK */ SUDPTRH = (Byte)((unsigned int)conf_desc >> 8); SUDPTRL = (unsigned int)conf_desc & 0xff; break; /* type: string */ case USB_DT_STRING: if (sdat->wValueL < NUM_STRING) { EP0CS = 0x02; /* clear HSNACK */ SUDPTRH = (Byte)(string_index[sdat->wValueL] >> 8); SUDPTRL = string_index[sdat->wValueL] & 0xff; } else { EP0CS = 0x03; /* stall */ } break; default: EP0CS = 0x03; /* stall */ } /* GetConfiguration */ case 0x08: if (sdat->bmRequestType == 0x80) { INBUF(0,0) = 0x01; IN0BC = 0x01; EP0CS = 0x02; /* clear HSNACK */ } else { EP0CS = 0x03; /* stall */ } break; /* SetConfiguration */ case 0x09: switch (sdat->bmRequestType) { /* SetConfiguration */ case 0x00: EP0CS = 0x02; /* clear HSNACK */ break; /* Set_Report */ case 0x21: break; default: EP0CS = 0x03; /* stall */ break; } break; /* bRequest == 0x0a */ case 0x0a: switch (sdat->bmRequestType) { /* GetInterface */ case 0x81: INBUF(0,0) = 0x00; IN0BC = 0x01; EP0CS = 0x02; /* clear HSNACK */ break; /* Set_Idle */ case 0x21: if (sdat->wIndexL == 0) { if (sdat->wValueH > 0) { } else { } EP0CS = 0x02; /* clear HSNACK */ } else EP0CS = 0x03; /* stall */ break; default: EP0CS = 0x03; /* stall */ break; } break; /* bRequest == 0x0b */ case 0x0b: switch (sdat->bmRequestType) { /* SetInterface */ case 0x01: if (sdat->wValueL == 0) { /* only AS 0 supported */ if (sdat->wIndexL == 0) { IN1CS |= 0x02; /* remove busy */ TOGCTL = 0x11; TOGCTL = 0x31; /* reset toggle of IN1 */ EP0CS = 0x02; /* clear HSNACK */ } else EP0CS = 0x03; /* stall */ } else EP0CS = 0x03; /* stall */ break; /* Set_Protocol TODO */ case 0x21: EP0CS = 0x02; /* clear HSNACK */ break; default: EP0CS = 0x03; /* stall */ break; } break; #if 0 case 0xb5: /* xor PORTA */ switch (sdat->bmRequestType) { case 0x40: /* host-to-device vendor-specific */ OUTA ^= sdat->wValueL; EP0CS = 0x02; /* clear HSNACK */ break; default: EP0CS = 0x03; /* stall */ break; } break; case 0xb6: /* xor PORTB */ switch (sdat->bmRequestType) { case 0x40: /* host-to-device vendor-specific */ OUTB ^= sdat->wValueL; EP0CS = 0x02; /* clear HSNACK */ break; default: EP0CS = 0x03; /* stall */ break; } break; #endif case SURF_GLOB_RESET_PFAIL: _power_fail = 0; break; default: EP0CS = 0x03; /* stall */ break; } } /* interesting interrupts go here */ /* was this an IN0 interrupt? */ if (IN07IRQ & 0x01) { /* clear IN0 interrupt */ IN07IRQ = 0x01; } /* was this a OUT0 interrupt? */ if (OUT07IRQ & 0x01) { /* clear OUT0 interrupt */ OUT07IRQ = 0x01; /* arm endpoint again */ OUT0BC = 0x00; } #if 0 /* was this an IN1..4 interrupt? */ for (i = 1; i < 5; ++i) if (IN07IRQ & 1 << i) { IN07IRQ = 1 << i; FLASH; } #endif /* was this an OUT1..4 interrupt? */ for (i = 1; i < 5; ++i) if (OUT07IRQ & 1 << i) { volatile byte len = OUTBC(i); OUT07IRQ = 1 << i; switch (OUTBUF(i, 0)) { case SURF_MOD_SEL_RD: OUTB = (OUTB & 0x3f) | ((i - 1) << 6); break; case SURF_MOD_SEL_WR: OUTB = (OUTB & 0x3f) | ((i - 1) << 6); OUTB |= ENSING; break; /* fix me! the global commands have no business here */ case SURF_GLOB_WRITE: OUTB &= ~ENSING; break; case SURF_GLOB_RESET: OUTB &= ~NRESET; SLEEP; OUTB |= NRESET; break; case SURF_MOD_SET_ANAL: VOLT(2 * i - 2) = OUTBUF(i, 1); VOLT(2 * i - 2) <<= 8; VOLT(2 * i - 2) += OUTBUF(i, 2); break; case SURF_MOD_SET_DIG: VOLT(2 * i - 1) = OUTBUF(i, 1); VOLT(2 * i - 1) <<= 8; VOLT(2 * i - 1) += OUTBUF(i, 2); /* FLASH; */ break; case SURF_MOD_ENA: if (OUTBUF(i, 1)) { /* turn on */ OUTA |= 1 << (i - 1); } else OUTA &= ~(1 << (i - 1)); break; case SURF_MOD_END: if (OUTBUF(i, 1)) { /* turn on */ OUTA |= 1 << (i + 3); } else OUTA &= ~(1 << (i + 3)); break; case SURF_MOD_STATUS: if (INCS(i) & 0x02) /* busy */ break; /* status byte */ INBUF(i, 0) = _vtable[i]; /* fix me! status byte */ /* analog supply voltage */ INBUF(i, 1) = ADCANLVH(i); INBUF(i, 2) = ADCANLVL(i); /* digital supply voltage */ INBUF(i, 3) = ADCDIGVH(i); INBUF(i, 4) = ADCDIGVL(i); /* ground voltage */ INBUF(i, 5) = ADCGNDVH(i); INBUF(i, 6) = ADCGNDVL(i); /* analog current */ INBUF(i, 7) = ADCANLIH(i); INBUF(i, 8) = ADCANLIL(i); /* digital current */ INBUF(i, 9) = ADCDIGIH(i); INBUF(i, 10) = ADCDIGIL(i); /* temperature */ INBUF(i, 11) = ADCTEMPH(i); INBUF(i, 12) = ADCTEMPL(i); INBC(i) = 13; break; case SURF_MOD_COMP_ANL: if (OUTBUF(i, 1)) _firm_regulate |= (1 << (2 * (i - 1))); else _firm_regulate &= ~(1 << (2 * (i - 1))); break; case SURF_MOD_COMP_DIG: if (OUTBUF(i, 1)) _firm_regulate |= (1 << (2 * i - 1)); else _firm_regulate &= ~(1 << (2 * i - 1)); break; case SURF_MOD_TOL_ANL: _vtol[2 * (i - 1)] = OUTBUF(i, 1); break; case SURF_MOD_TOL_DIG: _vtol[2 * i - 1] = OUTBUF(i, 1); break; default: FLASH; break; } OUTBC(i) = 0; } /* was this the URES interrupt? */ if (USBIRQ & 0x10) { /* clear request */ USBIRQ = 0x10; /* initialize global variables */ } }