/********************************************************************* * Flowcode USB Component Code * * File: USB_Code.c * * (c) 2007 Matrix Multimedia Ltd. * http://www.matrixmultimedia.com * * Software License Agreement * * The software supplied herewith by Matrix Multimedia Ltd (the * “Company”) for its Flowcode graphical programming language is * intended and supplied to you, the Company’s customer, for use * solely and exclusively on the Company's products. The software * is owned by the Company, and is protected under applicable * copyright laws. All rights are reserved. Any use in violation * of the foregoing restrictions may subject the user to criminal * sanctions under applicable laws, as well as to civil liability * for the breach of the terms and conditions of this licence. * * THIS SOFTWARE IS PROVIDED IN AN “AS IS” CONDITION. NO WARRANTIES, * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT NOT LIMITED * TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. THE COMPANY SHALL NOT, * IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL OR * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER. * * Changelog: * * date | by | description * -------+----+----------------------------------------------------- * 240407 | ST | Created * 040107 | BR | Modified for BoostC USB Component * | | * | | * | | * * * ********************************************************************/ /********************************************************************* Return & parameter types: void char short char* oo_tdata Pin directions: 0 = OUTPUT 2 = INPUT 3 = BIDIRECTIONAL Macro substitutions: %a = ?? %b = ?? %c = ?? %d = ?? %e = ?? %f = ?? %g = ?? %h = ?? %i = ?? %j = ?? ********************************************************************** [Settings] CLSID={4B174520-75AB-4B14-A0F7-2AA6C203F1DC} IsAnalogue=0 MultipleAllowed=0 Description=USB Flowcode Component ********************************************************************** [Port] DesiredPort=0 PortMandatory=0 SamePortAsID=0 [Pins] Count=0 [PinPort] # PORTA = 0 # PORTB = 1 # PORTC = 2 # PORTD = 3 # PORTE = 4 [PinDesiredBit] [PinDirection] # DIR_INPUT = 2 # DIR_OUTPUT = 0 # DIR_BIDIRECTIONAL = 3 [PinMustUsePort] # boolean [SamePortAsPinX] # -1 = any pin # otherwise, the pin number [PinMustUsePin] # boolean [PinValue] # boolean (0 = off, 1 = on) ********************************************************************** [MacroNames] Count=12 1=GetDefines 2=InitUSB 3=USBSleep 4=USBActivity 5=USBReset 6=CopyDescriptorToEP0 7=USBStall 8=Count_Error 9=Process_Req 10=ServiceUSB 11=IntUSB 12=PutEP1 [MacroReturns] 1=void 2=void 3=void 4=void 5=void 6=void 7=void 8=void 9=void 10=void 11=void 12=char [MacroIsPrivate] 1=1 2=0 3=0 4=0 5=0 6=0 7=0 8=0 9=0 10=0 11=0 12=0 [MacroParameters_GetDefines] Count=0 [MacroParamTypes_GetDefines] [MacroParameters_InitUSB] Count=0 [MacroParamTypes_InitUSB] [MacroParameters_USBSleep] Count=0 [MacroParamTypes_USBSleep] [MacroParameters_USBActivity] Count=0 [MacroParamTypes_USBActivity] [MacroParameters_USBReset] Count=0 [MacroParamTypes_USBReset] [MacroParameters_CopyDescriptorToEP0] Count=0 [MacroParamTypes_CopyDescriptorToEP0] [MacroParameters_USBStall] Count=0 [MacroParamTypes_USBStall] [MacroParameters_Count_Error] Count=0 [MacroParamTypes_Count_Error] [MacroParameters_Process_Req] Count=0 [MacroParamTypes_Process_Req] [MacroParameters_ServiceUSB] Count=0 [MacroParamTypes_ServiceUSB] [MacroParameters_IntUSB] Count=0 [MacroParamTypes_IntUSB] [MacroParameters_PutEP1] Count=2 1=bytes 2=buffer [MacroParamTypes_PutEP1] 1=char 2=char* ********************************************************************/ /******************************************************************** * ADDITIONAL CODE ********************************************************************/ /*InitialisationCode_Start*/ //Include The USB definition file #include /*InitialisationCode_End*/ /*InterruptCode_Start*/ /*InterruptCode_End*/ /******************************************************************** * FUNCTIONS ********************************************************************/ void GetDefines() { /*Macro_GetDefines_Start*/ } //Dummy end of function to allow defines to be added correctly //Common Defines #define VID_LO %a //0xd8 //VID=04d8 //%b #define VID_HI %b //0x04 //%c #define PID_LO %c //0x09 //PID=0009 //%d #define PID_HI %d //0x00 //%e #define RELEASE_NUM0 %e //0x00 //Release=2.0 //%f #define RELEASE_NUM1 %f //0x02 //%g #define MX_CUSTOM_8 %h #define MX_CUSTOM_9 %i #define MX_CUSTOM_10 %j //Global Variables unsigned char USB_IsIdle; unsigned char USB_status_device; unsigned char USB_Curr_Config; unsigned char USB_address_pending; unsigned char USB_dev_req; unsigned char USB_Interface [3]; unsigned char USB_USTAT; unsigned char ACTIVE_BUF; unsigned char USB_protocol; unsigned char USWSTAT; unsigned int USB_PID_ERR = 0; //error counters unsigned int USB_CRC5_ERR = 0; unsigned int USB_CRC16_ERR = 0; unsigned int USB_DFN8_ERR = 0; unsigned int USB_BTO_ERR = 0; unsigned int USB_WRT_ERR = 0; unsigned int USB_OWN_ERR = 0; unsigned int USB_BTS_ERR = 0; unsigned char * EP0_start; //ep0 pointers modified from CC unsigned char * EP0_end; // modified from CC unsigned char EP0_maxLength; //Structure definitions struct BufferDescriptorEntry // buffer descriptor { unsigned char EPStat; unsigned char bytes; unsigned int address; }; struct BufferStruct // buffer structure { unsigned char bmRequestType; unsigned char bRequest; unsigned int wValue; unsigned int wIndex; unsigned int wLength; }; struct BufferDescriptorEntry * BDT= (struct BufferDescriptorEntry *)0x400; struct BufferStruct * Buffer; //define Buffer as pointer to a BufferStruct struct BufferStruct BufferCopy; struct BufferDescriptorEntry BDTCopy; //string descriptors in unicode format const char String0 [] = {4,STRING,9,4}; const char String1 [] = {36, STRING, 'M',0, 'a',0, 't',0, 'r',0, 'i',0, 'x',0, ' ',0, 'M',0, 'u',0, 'l',0, 't',0, 'i',0, 'm',0, 'e',0, 'd',0, 'i',0, 'a',0}; const char String2[] = {34,STRING, 'E',0, 'C',0, 'I',0, 'O',0, ' ',0, 'U',0, 'S',0, 'B',0, ' ',0, 'E',0, 'X',0, 'A',0, 'M',0, 'P',0, 'L',0, 'E',0}; // Report descriptor prepared by USB DESCRIPTOR TOOL // http://www.usb.org/developers/hidpage/#Descriptor_Tool const char ReportDescriptor1[] = { 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x02, // USAGE (Mouse) 0xa1, 0x01, // COLLECTION (Application) 0x09, 0x01, // USAGE (Pointer) 0xa1, 0x00, // COLLECTION (Physical) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x03, // USAGE_MAXIMUM (Button 3) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x95, 0x03, // REPORT_COUNT (3) 0x75, 0x01, // REPORT_SIZE (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x95, 0x01, // REPORT_COUNT (1) 0x75, 0x05, // REPORT_SIZE (5) 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7f, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x02, // REPORT_COUNT (2) 0x81, 0x06, // INPUT (Data,Var,Rel) 0xc0, // END_COLLECTION 0xc0 // END_COLLECTION }; const char DeviceDescriptor [] = {0x12, // 18 bytes long DEVICE, // descriptor type 0x10, 0x01, // USB specification release (1.10) 0x00, // class code 0x00, // subclass code 0x00, // protocol code 0x08, // maximum packet size VID_LO, VID_HI, // vendor id (04d8) microchip PID_LO, PID_LO, //product id (0009) RELEASE_NUM0, RELEASE_NUM1, // device release number 2.00 0x01, // index to string that describes vendor 0x02, // index to string that describes product 0x00, // index to string that describes serial number (none) 0x01 // number of possible configurations }; //CONFIG DESCRIPTOR ORDER CORRESPONDS TO HID 1.0 OR LATER const char ConfigDescriptor [] = {0x09, // 9 bytes long CONFIGURATION, // descriptor type 0x22, 0x00, // total length of config, interface, HID and endpoint descriptors 0x01, // number of interfaces 0x01, // configuration number 0x00, // index to string that describes configuration (none) 0xA0, // configuration attributes , remote wakeup 0x32, // current consumption in 2mA units (100 mA) /* Interface Descriptor */ 0x09,// 9 bytes long INTERFACE, // descriptor type 0x00, // number of this interface (zerp based) 0x00, // alternate setting (none) 0x01, // number of endpoints used by interface 0x03, // class code 0x01, // subclass code 0x02, // protocol 0x00, // index to string that describes endpoint (none) /* HID descriptor described above */ 0x09, 0x21, 0x10, 0x01, 0x00, 0x01, 0x22, sizeof(ReportDescriptor1), sizeof(ReportDescriptor1)>>8, /* Endpoint 1 descriptor */ 0x07, // 7 bytes long ENDPOINT, // descriptor type 0x81, // endpoint characteristics (IN endpoint) 0x03, // endpoint attributes (interrupt) 0x03, 0x00, // max packet size (HID 3 byte report) 0x0A //polling interval in 1 msec increments (10) }; const unsigned int ReportDescrSize = sizeof(ReportDescriptor1); const char HIDDescriptor [] = {0x09, // 9 bytes long 0x21, // descriptor type, HID=21 0x10, 0x01, // HUD class version 1.10 0x00, // country code (none) 0x01, // Number of HID class descriptors 0x22, // Type of class descriptor (report) sizeof(ReportDescriptor1), sizeof(ReportDescriptor1)>>8 // Size of report descriptor }; //internal function implementations // Dummy function to close the defines section off void CUSTOM_Dummy_Function(); void CUSTOM_Dummy_Function() { /*Macro_GetDefines_End*/ } /* ********************************************************************* */ /* Enable Wakeup on interupt and Activity interrupt then put the */ /* device to sleep to save power. Activity on the D+/D- lines will */ /* set the ACTIVITY interrupt, waking up the part. */ /* ********************************************************************* */ void USBSleep () { /*Macro_USBSleep_Start*/ bACTIVITY_E = 1; // enable activity interrupt bUIDLE = 0; //disable idle interrupt bSUSPND = 1; // put in suspend mode USB_IsIdle = 1; // mark device as idle /*Macro_USBSleep_End*/ } /* ********************************************************************* */ /* Service the Activity Interrupt. This is only enabled when the */ /* device is put to sleep as a result of inactivity on the bus. This */ /* code wakes up the part, disables the activity interrupt and reenables */ /* the idle interrupt. */ /* ********************************************************************* */ void USBActivity () { /*Macro_USBActivity_Start*/ bACTIVITY = 0; bACTIVITY_E = 0; bSUSPND = 0; //normal operation USB_IsIdle = 0; /*Macro_USBActivity_End*/ } /* ****************************************************************** */ /* USB Reset interrupt triggered (SE0) */ /* initialize the Buffer Descriptor Table, */ /* Transition to the DEFAULT state, */ /* Set address to 0 */ /* enable the USB */ /* ****************************************************************** */ void USBReset () { /*Macro_USBReset_Start*/ USB_Curr_Config = 0; USB_IsIdle = 0; bTOK_DONE=0; // clear TOK_DNE bit in uir 4 times to bTOK_DONE=0; // clear out the USTAT FIFO. See Microchip bTOK_DONE=0; // 18F2455 data sheet. bTOK_DONE=0; bd0cntoe=8; //set up for 8 byte buffer bd0statoe = 0x88; // EP0 Out buffer (USB OWNS) bd0statie = 0x08; // EP0 In buffer (MCU OWNS) uaddr = 0; // clear address uir = 0; // clear USB interrupt flag uie = 00000101b; // enable reset and activity interrupt uep0 = ENDPT_CONTROL; USWSTAT=DEFAULT_STATE; USB_status_device = 1; /*Macro_USBReset_End*/ } /* ******************* */ /* CopyDescriptorToEP0 ************************************************** */ /* copies the next chunk of buffer descriptor over to the EP0 In buffer. */ /* Inputs: */ /* EP0_start - points to first byte of configuration table to transfer */ /* EP0_end - total number of bytes to transfer */ /* EP0_maxLength - maximum number of bytes that can be sent during */ /* a single transfer */ /* */ /* toggles the data0/1 bit before setting the UOWN bit over to SIE. */ /* ********************************************************************** */ void CopyDescriptorToEP0 () { /*Macro_CopyDescriptorToEP0_Start*/ unsigned char * USBbuffer; /* pointer to the USB Buffers */ unsigned char bufindex; USBbuffer = (unsigned char *) ((unsigned int)bd0adrlie + (unsigned int)(bd0adrhie <<8)); bufindex = 0; while ((bufindex < EP0_maxLength) && ((unsigned short)EP0_start <(unsigned short) EP0_end)) { USBbuffer [bufindex] = *EP0_start; ++ EP0_start; ++ bufindex; } if (bufindex < EP0_maxLength) /* are we sending a short packet? */ USB_dev_req = 0; /* Yes, clear the device reqest */ bd0cntie = bufindex; bd0statie &= 0x40; /* save only the DTS bit */ bd0statie ^= 0x40; /* toggle data DTS bit */ bd0statie |= 0x88; /* set OWN and DTSEN bits */ /*Macro_CopyDescriptorToEP0_End*/ } /* ******** */ /* Init USB ********************************************************* */ /* Initializes the USB peripheral, sets up the interrupts */ /* ****************************************************************** */ void InitUSB () { /*Macro_InitUSB_Start*/ ucfg= 00010100b; //use onchip receiver, internal pullup resistors, low speed and no pingpong buffers uie = 00000001b; // enable the Reset interrupt ONLY!! uir = 0; // clear all USB interrupt flags pie2= 00100000b ; //enable usb interrupts ucon = 01000000b; // reset pingpong buffers ucon = 00001000b; // unlock pingpong buffers and enable usb USB_Curr_Config = 0; USB_status_device = 1; char USB_Interface [] = {0,0,0}; USB_dev_req = NULL; // clear all error counters USB_PID_ERR = 0; USB_CRC5_ERR = 0; USB_CRC16_ERR = 0; USB_DFN8_ERR = 0; USB_BTO_ERR = 0; USB_BTS_ERR = 0; intcon = intcon | 11000000b; // Enable GIE & PEIE /*Macro_InitUSB_End*/ } /* ********************************************************************* */ /* This is activated by the STALL bit in the UIR register. It really */ /* just tells us that the SIE sent a STALL handshake. So far, Don't */ /* see that any action is required. Clear the bit and move on. */ /* ********************************************************************* */ void USBStall () { /*Macro_USBStall_Start*/ bSTALL = 0; /*Macro_USBStall_End*/ } /* ****************************************************************** */ /* The SIE detected an error. This code increments the appropriate */ /* error counter and clears the flag. */ /* ****************************************************************** */ void Count_Error () { /*Macro_Count_Error_Start*/ if (bPID_ERR && bPID_ERR_E){ ++ USB_PID_ERR; } if (bCRC5 && bCRC5_E){ ++ USB_CRC5_ERR; } if (bCRC16 && bCRC16_E){ ++ USB_CRC16_ERR; } if (bDFN8 && bDFN8_E){ ++ USB_DFN8_ERR; } if (bBTO_ERR && bBTO_ERR_E){ ++ USB_BTO_ERR; } if (bBTS_ERR && bBTS_ERR_E){ ++ USB_BTS_ERR; } ueir = 0; //Clear all USB error flag bits bUERR = 0; //Clear master USB error flag bit /*Macro_Count_Error_End*/ } /* ******************************************************************* */ /* Process token done interrupt... Most of the work gets done through */ /* this interrupt. Token Done is signaled in response to an In, Out, */ /* or Setup transaction. */ /* ******************************************************************* */ void Process_Req (void) { /*Macro_Process_Req_Start*/ unsigned char *OutBuffer; unsigned char *UEPArray; unsigned char DescriptorType; unsigned char Endpoint; unsigned char Interface; unsigned char DescriptorID; unsigned char StringID; USB_USTAT = ustat; ACTIVE_BUF =(USB_USTAT >>3)*2; //EP*2 (IF OUTPUT) ACTIVE_BUF =(ACTIVE_BUF + (USB_USTAT&0x4)>>2); //=EP*2 + 1 (IF INPUT) //save data in buffer descriptor table BDTCopy.EPStat = BDT[ACTIVE_BUF].EPStat; BDTCopy.bytes = BDT[ACTIVE_BUF].bytes; BDTCopy.address = BDT[ACTIVE_BUF].address; bTOK_DONE = 0; if ((BDTCopy.EPStat & 0x3C) == TOKEN_IN) // TOKEN IN { if (USB_USTAT == 0x04) { /* Process EP0 In's */ if (USB_dev_req == GET_DESCRIPTOR) { FCD_Custom0_CopyDescriptorToEP0 (); } } else if (USB_USTAT == 0x0C) { /* process EP1 In's */ } else { /* process EP2 In's */ } } else if ((BDTCopy.EPStat & 0x3C) == TOKEN_OUT) //TOKEN OUT { if (USB_USTAT == 0x00) { /* process EP1 Out's */ } else if (USB_USTAT == 0x08) { /* process EP1 Out's */ } else { /* process EP2 Out's */ } } else if ((BDTCopy.EPStat & 0x3C) == TOKEN_SETUP) // TOKEN SETUP { Buffer = (struct BufferStruct *) ((unsigned int)bd0adrloe + (unsigned int)(bd0adrhoe <<8)); BufferCopy.bmRequestType = Buffer->bmRequestType; BufferCopy.bRequest = Buffer->bRequest; BufferCopy.wValue = Buffer->wValue; BufferCopy.wIndex = Buffer->wIndex; BufferCopy.wLength = Buffer->wLength; bPID_ERR=0; // Clear REQUEST ERROR bd0cntoe = 0x08; if (BufferCopy.bmRequestType == 0x21) bd0statoe = 0xC8; else bd0statoe = 0x88;/* Turn the buffer around, make it available for the SIE */ bd0statie = 0x08; bPKT_DIS = 0; USB_dev_req = 0; switch (BufferCopy.bmRequestType) { // First bmRequestType ************************************ case HOSTTODEVICE: // 00 switch (BufferCopy.bRequest) { //================ case CLEAR_FEATURE: //01 /* Remote wakeup is only valid device feature */ if (BufferCopy.wValue == 1) { USB_status_device &= 0xFD; Send_0Len_pkt; } else { STALL_EP0;} break; //================ case SET_FEATURE: //03 /* Set Device Feature. Only valid device */ if ((BufferCopy.wValue & 0xff) == 1) { USB_status_device |= 0x02; /* feature is remote wakeup */ Send_0Len_pkt; } else { STALL_EP0;} break; //================ case SET_ADDRESS: //05 USB_address_pending = BufferCopy.wValue; if (USB_address_pending < 0x80) { Send_0Len_pkt; USB_dev_req = SET_ADDRESS; uie = 00001001b; //enable transaction complete and reset interrupts } else { STALL_EP0;} break; //================ case SET_CONFIGURATION: //09 if (BufferCopy.wValue <= NUM_CONFIGURATIONS) USB_Curr_Config = BufferCopy.wValue; if (BufferCopy.wValue == 0) { USWSTAT= ADDRESS_STATE; } else { USWSTAT= CONFIG_STATE; } Send_0Len_pkt; bd1statie = 0x48; //SET MCU AS OWNER OF THIS BUFFER, ENABLE DATA TOGGLE SYNC uep1 = ENDPT_NON_CONTROL; break; //================ default: { STALL_EP0;} break; } break; // Second bmRequestType ************************************ case HOSTTOINTERFACE: //01 switch (BufferCopy.bRequest) { //================ case SET_INTERFACE: //0B if (USWSTAT == CONFIG_STATE) { Interface = BufferCopy.wIndex; USB_Interface [Interface] = BufferCopy.wValue; Send_0Len_pkt; } else { STALL_EP0;} break; //================ case CLEAR_FEATURE: //01 //================ case SET_FEATURE: //03 /* Set Interface feature - Not Valid */ //================ default: { STALL_EP0;} break; //================ } break; // Third bmRequestType ************************************ case HOSTTOENDPOINT: switch (BufferCopy.bRequest) { //================ case CLEAR_FEATURE: //01 UEPArray = (unsigned char *) &uep0; Endpoint = BufferCopy.wIndex & 0x0F; if (BufferCopy.wValue == 0) /* Only valid feature is 0 (Remote Wakeup) */ { if (((USWSTAT & 0x03) == ADDRESS_STATE) && (Endpoint == 0)) { UEPArray [Endpoint] &= 0xFE; Send_0Len_pkt; } else if (((USWSTAT& 0x03) == CONFIG_STATE) && (Endpoint < 3)) { UEPArray [Endpoint] &= 0xFE; Send_0Len_pkt; } else { STALL_EP0;} } else { STALL_EP0;} break; //================ case SET_FEATURE: //03 UEPArray = (unsigned char *) &uep0; Endpoint = BufferCopy.wIndex & 0x0F; if (BufferCopy.wValue == 0) /* Only valid feature is 0 (Remote Wakeup) */ { if (((USWSTAT& 0x03) == ADDRESS_STATE) && (Endpoint == 0)) { UEPArray [Endpoint] |= 1; Send_0Len_pkt; } else if (((USWSTAT& 0x03) == CONFIG_STATE) && (Endpoint < 3)) { UEPArray [Endpoint] |= 1; Send_0Len_pkt; } else { STALL_EP0;} } else { STALL_EP0;} break; //================ default: { STALL_EP0;} } break; // Fourth bmRequestType ************************************ case DEVICETOHOST: //80 switch (BufferCopy.bRequest) { //================ case GET_CONFIGURATION: OutBuffer = (unsigned char *) ((unsigned int)bd0adrlie + (unsigned int)(bd0adrhie <<8)); OutBuffer [0] = USB_Curr_Config; bd0cntie = 1; bd0statie = 0xc8; break; //================ case GET_DESCRIPTOR: DescriptorID = (unsigned char) (BufferCopy.wValue >> 8); if (DescriptorID == DEVICE) { USB_dev_req = GET_DESCRIPTOR; EP0_start = DeviceDescriptor; EP0_end = DeviceDescriptor + sizeof(DeviceDescriptor); if (BufferCopy.wLength < ((unsigned short)EP0_end - (unsigned short)EP0_start)) EP0_end = EP0_start + BufferCopy.wLength; EP0_maxLength = 8; FCD_Custom0_CopyDescriptorToEP0 (); } else if (DescriptorID == CONFIGURATION) { USB_dev_req = GET_DESCRIPTOR; EP0_start = ConfigDescriptor; EP0_end = ConfigDescriptor + sizeof(ConfigDescriptor); if (BufferCopy.wLength < ((unsigned short)EP0_end - (unsigned short)EP0_start)) EP0_end = EP0_start + BufferCopy.wLength; EP0_maxLength = 8; FCD_Custom0_CopyDescriptorToEP0 (); } else if (DescriptorID == STRING) { StringID = (unsigned char) BufferCopy.wValue; USB_dev_req = GET_DESCRIPTOR; EP0_maxLength = 8; switch (StringID) { case 0: EP0_start = String0; // String0 is start of string0 EP0_end = String0 + String0[0]; // String[0] is length of String0 if (BufferCopy.wLength < ((unsigned short)EP0_end - (unsigned short)EP0_start)) EP0_end = EP0_start + BufferCopy.wLength; FCD_Custom0_CopyDescriptorToEP0 (); // this copies the whole string in 8 byte pieces break; case 1: EP0_start = String1; EP0_end = String1 + String1[0]; if (BufferCopy.wLength < ((unsigned short)EP0_end - (unsigned short)EP0_start)) EP0_end = EP0_start + BufferCopy.wLength; FCD_Custom0_CopyDescriptorToEP0 (); break; case 2: EP0_start = String2; EP0_end = String2 + String2[0]; if (BufferCopy.wLength < ((unsigned short)EP0_end - (unsigned short)EP0_start)) EP0_end = EP0_start + BufferCopy.wLength; FCD_Custom0_CopyDescriptorToEP0 (); break; // Additional string processing can be added here default: { STALL_PID_EP0IN;} /* REQUEST ERROR */ } } else { STALL_PID_EP0IN;} /* REQUEST ERROR */ break; //================ case GET_STATUS: OutBuffer = (unsigned char *)BDT [EP0IN].address; OutBuffer[0] = USB_status_device; OutBuffer[1] = 0; bd0cntie = 2; bd0statie = 0xc8; break; //================ default: break; } //================ break; // Fifth bmRequestType ************************************ case INTERFACETOHOST: switch (BufferCopy.bRequest) { //================ case GET_INTERFACE: Interface = BufferCopy.wIndex; if ((USWSTAT== CONFIG_STATE) && (Interface < NUM_INTERFACES)) { OutBuffer = (unsigned char *) BDT [EP0IN].address; OutBuffer[0] = USB_Interface [Interface]; bd0cntie = 1; bd0statie = 0xc8; } else { STALL_EP0;} break; //================ case GET_STATUS: OutBuffer = (unsigned char *) BDT [EP0IN].address; OutBuffer[1] = 0; bd0cntie = 2; Interface = BufferCopy.wIndex; if ((USWSTAT == ADDRESS_STATE) && (Interface == 0)) { OutBuffer[0] = USB_Interface [Interface]; bd0statie = 0xc8; } else if ((USWSTAT == CONFIG_STATE) && (Interface < NUM_INTERFACES)) { OutBuffer[0] = USB_Interface [Interface]; bd0statie = 0xc8; } else { STALL_EP0;} break; //================ case GET_DESCRIPTOR: DescriptorType = BufferCopy.wValue >> 8; if (DescriptorType == HID_REPORT_DESCRIPTOR) /* 22 special HID request to return report descriptor */ { USB_dev_req = GET_DESCRIPTOR; if (BufferCopy.wIndex == 0); { EP0_start = ReportDescriptor1; EP0_end = EP0_start + sizeof (ReportDescriptor1); EP0_maxLength = 8; if (BufferCopy.wLength < sizeof (ReportDescriptor1)) EP0_end = EP0_start + BufferCopy.wLength; FCD_Custom0_CopyDescriptorToEP0 (); } if (BufferCopy.wIndex == 1); { /* Repeat above code for another Report Descriptor. */ } } else if (DescriptorType == HID_DESCRIPTOR) /* 21 HID descriptor */ { USB_dev_req = GET_DESCRIPTOR; if (BufferCopy.wIndex == 0) { EP0_start = HIDDescriptor; EP0_end = EP0_start + sizeof (HIDDescriptor); EP0_maxLength = 8; if (BufferCopy.wLength < sizeof (HIDDescriptor)) EP0_end = EP0_start + BufferCopy.wLength; FCD_Custom0_CopyDescriptorToEP0 (); } if (BufferCopy.wIndex == 1) { /* Repeat above code for another HID Descriptor. */ } } else { STALL_EP0;} /* unrecognised request */ break; //================ default: break; } //================ break; // Sixth bmRequestType ************************************ case ENDPOINTTOHOST: if (BufferCopy.bRequest == GET_STATUS) { UEPArray = (unsigned char *) &uep0; Endpoint = BufferCopy.wIndex & 0x0F; OutBuffer = (unsigned char *) ((unsigned int)bd0adrlie + (unsigned int)(bd0adrhie <<8)); // OutBuffer = (unsigned char * ) bd0adrlie; OutBuffer[1] = 0; bd0cntie = 2; if (Endpoint < 3) { OutBuffer[0] = UEPArray [Endpoint] & 0x01; bd0statie = 0xc8; } else { STALL_EP0;} } break; // Seventh bmRequestType (others) ************************************ default: if (BufferCopy.bmRequestType & 0x20) { OutBuffer = (unsigned char *) ((unsigned int)bd0adrlie + (unsigned int)(bd0adrhie <<8)); switch (BufferCopy.bmRequestType) { case 0x21: /* Host to Device HID request */ switch (BufferCopy.bRequest) { case HID_SET_PROTOCOL: /* Set Protocol */ USB_protocol = BufferCopy.wValue; Send_0Len_pkt; break; case HID_SET_REPORT: /* Set HID Report */ // Add Set_Report Function above for OUT TOKEN and uncomment // following two lines // USB_dev_req = HID_SET_REPORT; break; case HID_SET_IDLE: /* Set Idle */ STALL_EP0; break; default: STALL_EP0; } break; case 0xA1: /* Dev2HostHIDRequest */ switch (BufferCopy.bRequest) { case HID_GET_PROTOCOL: /* Get Protocol */ OutBuffer[0] = USB_protocol; bd0cntie = 1; bd0statie = 0xC8; break; case HID_GET_REPORT: /* Get HID Report */ // Add Get_Report Function here and uncomment following two lines // BD0IST = 0xc8; // Turn over BDT to SIE break; case HID_GET_IDLE: /* Get Idle */ STALL_EP0; break; default: // device does not support get idle, just stall STALL_EP0; } break; case 0x22: /* Host2DevReportRequest */ STALL_EP0; break; case 0x23: /* Host2DevPhysicalRequest */ STALL_EP0; break; case 0xA2: /* Dev2HostReportRequest */ STALL_EP0; break; case 0xA3: /* Dev2HostPhysicalRequest */ STALL_EP0; break; default: STALL_EP0; } } } } /*Macro_Process_Req_End*/ } /* ********************************************************************* */ /* Branch off and service the USB interrupt flags */ /* ********************************************************************* */ void ServiceUSB () { /*Macro_ServiceUSB_Start*/ if (bTOK_DONE) { FCD_Custom0_Process_Req(); } if (bSTALL) { FCD_Custom0_USBStall (); } if (bUERR) { FCD_Custom0_Count_Error (); } if (bUIDLE) { FCD_Custom0_USBSleep (); } /*Macro_ServiceUSB_End*/ } //////////////////////////////////////////////////////////////// // Int service routine. Branch off to different int //////////////////////////////////////////////////////////////// void IntUSB (void) { /*Macro_IntUSB_Start*/ if (bUSBIE && bUSBIF) { if (bACTIVITY && bACTIVITY_E) // WAS IT AN ACTIVITY WAKEUP? { FCD_Custom0_USBActivity (); } if (bUSBRST && bUSBRST_E)// USB reset must be serviced immediately { FCD_Custom0_USBReset(); } if (bTOK_DONE && bTOK_DONE_E) // WAS IT A TOKEN DONE { if (USB_dev_req == SET_ADDRESS) // Finish Set Address { USB_dev_req = NULL; USB_Curr_Config = 0; uaddr = USB_address_pending; uie = 00000001b; // enable just the reset interrupt if (USB_address_pending > 0) { USWSTAT= ADDRESS_STATE; } else { USWSTAT= DEFAULT_STATE; } } bTOK_DONE=0; // clear Token Done flag } bUSBIF=0; // Clear USB interrupt flag } /*Macro_IntUSB_End*/ } /* PutEP1 **************************************************************** */ /* Tests the EP1 IN OWNS bit. If there is a buffer available to us, your */ /* buffer is copied and turned over to the SIE for transmission on the */ /* next IN transfer and returns TRUE (1). If the buffer is not available, */ /* FALSE is returned (0). */ /* *********************************************************************** */ unsigned char PutEP1 (unsigned char bytes, signed char *buffer) { /*Macro_PutEP1_Start*/ signed char * tobuffer; unsigned char i; ddrb=0; //setup b for output if ((bd1statie & 0x80) == 0) /* do we own the buffer? UOWN=0*/ { bd1cntie = bytes; tobuffer = (signed char *) ((unsigned int)bd1adrlie + (unsigned int)(bd1adrhie <<8)); for (i = 0; i < bytes; i++) { tobuffer [i] = buffer[i]; } bd1statie &= 0x40; /* save only the Data 1/0 bit */ bd1statie ^= 0x40; /* toggle Data 0/1 bit */ bd1statie ^= 0x88; /* release buffer */ return TRUE; } return FALSE; /* Buffer not available, return false */ /*Macro_PutEP1_End*/ }