/****************************************************************************** * Function: byte USBGenRead(byte *buffer, byte len) * * PreCondition: Value of input argument 'len' should be smaller than the * maximum endpoint size responsible for receiving report * data from USB host for HID class. * Input argument 'buffer' should point to a buffer area that * is bigger or equal to the size specified by 'len'. * * Input: buffer : Pointer to where received bytes are to be stored * len : The number of bytes expected. * * Output: The number of bytes copied to buffer. * * Side Effects: Publicly accessible variable usbgen_rx_len is updated * with the number of bytes copied to buffer. * Once USBGenRead is called, subsequent retrieval of * usbgen_rx_len can be done by calling macro * mUSBGenGetRxLength(). * * Overview: USBGenRead copies a string of bytes received through * the OUT endpoint to a user's specified location. * It is a non-blocking function. It does not wait * for data if there is no data available. Instead it returns * '0' to notify the caller that there is no data available. * * Note: If the actual number of bytes received is larger than the * number of bytes expected (len), only the expected number * of bytes specified will be copied to buffer. * If the actual number of bytes received is smaller than the * number of bytes expected (len), only the actual number * of bytes received will be copied to buffer. *****************************************************************************/ byte USBGenRead(byte *buffer, byte len) { usbgen_rx_len = 0; if(!mUSBGenRxIsBusy()) { /* * Adjust the expected number of bytes to equal * the actual number of bytes received. */ if(len > USBGEN_BD_OUT.Cnt) len = USBGEN_BD_OUT.Cnt; /* * Copy data from dual-ram buffer to user's buffer */ for(usbgen_rx_len = 0; usbgen_rx_len < len; usbgen_rx_len++) buffer[usbgen_rx_len] = usbgen_out[usbgen_rx_len]; /* * Prepare dual-ram buffer for next OUT transaction */ USBGEN_BD_OUT.Cnt = sizeof(usbgen_out); mUSBBufferReady(USBGEN_BD_OUT); }//end if return usbgen_rx_len; }//end USBGenRead
/****************************************************************************** * Function: byte HIDRxReport(char *buffer, byte len) * * PreCondition: Value of input argument 'len' should be smaller than the * maximum endpoint size responsible for receiving report * data from USB host for HID class. * Input argument 'buffer' should point to a buffer area that * is bigger or equal to the size specified by 'len'. * * Input: buffer : Pointer to where received bytes are to be stored * len : The number of bytes expected. * * Output: The number of bytes copied to buffer. * * Side Effects: Publicly accessible variable hid_rpt_rx_len is updated * with the number of bytes copied to buffer. * Once HIDRxReport is called, subsequent retrieval of * hid_rpt_rx_len can be done by calling macro * mHIDGetRptRxLength(). * * Overview: HIDRxReport copies a string of bytes received through * USB HID OUT endpoint to a user's specified location. * It is a non-blocking function. It does not wait * for data if there is no data available. Instead it returns * '0' to notify the caller that there is no data available. * * Note: If the actual number of bytes received is larger than the * number of bytes expected (len), only the expected number * of bytes specified will be copied to buffer. * If the actual number of bytes received is smaller than the * number of bytes expected (len), only the actual number * of bytes received will be copied to buffer. *****************************************************************************/ uint8_t HIDRxReport(char *buffer, uint8_t len) { hid_rpt_rx_len = 0; if(!mHIDRxIsBusy()) { /* * Adjust the expected number of bytes to equal * the actual number of bytes received. */ if(len > HID_BD_OUT.Cnt) len = HID_BD_OUT.Cnt; /* * Copy data from dual-ram buffer to user's buffer */ for(hid_rpt_rx_len = 0; hid_rpt_rx_len < len; hid_rpt_rx_len++) buffer[hid_rpt_rx_len] = hid_report_out[hid_rpt_rx_len]; /* * Prepare dual-ram buffer for next OUT transaction */ HID_BD_OUT.Cnt = sizeof(hid_report_out); mUSBBufferReady(HID_BD_OUT); }//end if return hid_rpt_rx_len; }//end HIDRxReport
/****************************************************************************** * Function: byte getsUSBUSART(char *buffer, * byte len) * * PreCondition: Value of input argument 'len' should be smaller than the * maximum endpoint size responsible for receiving bulk * data from USB host for CDC class. * Input argument 'buffer' should point to a buffer area that * is bigger or equal to the size specified by 'len'. * * Input: buffer : Pointer to where received bytes are to be stored * len : The number of bytes expected. * * Output: The number of bytes copied to buffer. * * Side Effects: Publicly accessible variable cdc_rx_len is updated with * the number of bytes copied to buffer. * Once getsUSBUSART is called, subsequent retrieval of * cdc_rx_len can be done by calling macro mCDCGetRxLength(). * * Overview: getsUSBUSART copies a string of bytes received through * USB CDC Bulk OUT endpoint to a user's specified location. * It is a non-blocking function. It does not wait * for data if there is no data available. Instead it returns * '0' to notify the caller that there is no data available. * * Note: If the actual number of bytes received is larger than the * number of bytes expected (len), only the expected number * of bytes specified will be copied to buffer. * If the actual number of bytes received is smaller than the * number of bytes expected (len), only the actual number * of bytes received will be copied to buffer. *****************************************************************************/ byte getsUSBUSART(char *buffer, byte len) { cdc_rx_len = 0; if(!mCDCUsartRxIsBusy()) { /* * Adjust the expected number of bytes to equal * the actual number of bytes received. */ if(len > CDC_BULK_BD_OUT.Cnt) len = CDC_BULK_BD_OUT.Cnt; /* * Copy data from dual-ram buffer to user's buffer */ for(cdc_rx_len = 0; cdc_rx_len < len; cdc_rx_len++) buffer[cdc_rx_len] = cdc_data_rx[cdc_rx_len]; /* * Prepare dual-ram buffer for next OUT transaction */ CDC_BULK_BD_OUT.Cnt = sizeof(cdc_data_rx); mUSBBufferReady(CDC_BULK_BD_OUT); }//end if return cdc_rx_len; }//end getsUSBUSART
/****************************************************************************** * Function: void HIDTxReport(char *buffer, byte len) * * PreCondition: mHIDTxIsBusy() must return false. * * Value of 'len' must be equal to or smaller than * HID_INT_IN_EP_SIZE * For an interrupt endpoint, the largest buffer size is * 64 bytes. * * Input: buffer : Pointer to the starting location of data bytes * len : Number of bytes to be transferred * * Output: None * * Side Effects: None * * Overview: Use this macro to transfer data located in data memory. * * Remember: mHIDTxIsBusy() must return false before user * can call this function. * Unexpected behavior will occur if this function is called * when mHIDTxIsBusy() == 0 * * Typical Usage: * if(!mHIDTxIsBusy()) * HIDTxReport(buffer, 3); * * Note: None *****************************************************************************/ void HIDTxReport(char *buffer, uint8_t len) { uint8_t i; /* * Value of len should be equal to or smaller than HID_INT_IN_EP_SIZE. * This check forces the value of len to meet the precondition. */ if(len > HID_INT_IN_EP_SIZE) len = HID_INT_IN_EP_SIZE; /* * Copy data from user's buffer to a USB module accessible RAM packet buffer */ for (i = 0; i < len; i++) hid_report_in[i] = buffer[i]; HID_BD_IN.Cnt = len; mUSBBufferReady(HID_BD_IN); }//end HIDTxReport
/****************************************************************************** * Function: void USBGenWrite(byte *buffer, byte len) * * PreCondition: mUSBGenTxIsBusy() must return false. * * Value of 'len' must be equal to or smaller than * USBGEN_EP_SIZE * For an interrupt/bulk endpoint, the largest buffer size is * 64 bytes. * * Input: buffer : Pointer to the starting location of data bytes * len : Number of bytes to be transferred * * Output: None * * Side Effects: None * * Overview: Use this macro to transfer data located in data memory. * * Remember: mUSBGenTxIsBusy() must return false before user * can call this function. * Unexpected behavior will occur if this function is called * when mUSBGenTxIsBusy() != 0 * * Typical Usage: * if(!mUSBGenTxIsBusy()) * USBGenWrite(buffer, 3); * * Note: None *****************************************************************************/ void USBGenWrite(byte *buffer, byte len) { byte i; /* * Value of len should be equal to or smaller than USBGEN_EP_SIZE. * This check forces the value of len to meet the precondition. */ if(len > USBGEN_EP_SIZE) len = USBGEN_EP_SIZE; /* * Copy data from user's buffer to dual-ram buffer */ for (i = 0; i < len; i++) usbgen_in[i] = buffer[i]; USBGEN_BD_IN.Cnt = len; mUSBBufferReady(USBGEN_BD_IN); }//end USBGenWrite
void BootService(void) { BlinkUSBStatus(); if((usb_device_state < CONFIGURED_STATE)||(UCONbits.SUSPND==1)) return; if(trf_state == SENDING_RESP) { if(!mBootTxIsBusy()) { BOOT_BD_OUT.Cnt = sizeof(dataPacket); mUSBBufferReady(BOOT_BD_OUT); trf_state = WAIT_FOR_CMD; }//end if return; }//end if if(!mBootRxIsBusy()) { counter = 0; switch(dataPacket.CMD) { case READ_VERSION: ReadVersion(); counter=0x04; break; case READ_FLASH: case READ_CONFIG: ReadProgMem(); counter+=0x05; break; case WRITE_FLASH: WriteProgMem(); counter=0x01; break; case ERASE_FLASH: EraseProgMem(); counter=0x01; break; case READ_EEDATA: ReadEE(); counter+=0x05; break; case WRITE_EEDATA: WriteEE(); counter=0x01; break; case WRITE_CONFIG: WriteConfig(); counter=0x01; break; case RESET: //When resetting, make sure to drop the device off the bus //for a period of time. Helps when the device is suspended. UCONbits.USBEN = 0; big_counter = 0; while(--big_counter); Reset(); break; case UPDATE_LED: if(dataPacket.led_num == 3) { mLED_3 = dataPacket.led_status; counter = 0x01; }//end if if(dataPacket.led_num == 4) { mLED_4 = dataPacket.led_status; counter = 0x01; }//end if break; default: break; }//end switch() trf_state = SENDING_RESP; if(counter != 0) { BOOT_BD_IN.Cnt = counter; mUSBBufferReady(BOOT_BD_IN); }//end if }//end if }//end BootService
/****************************************************************************** * Function: void CDCTxService(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: CDCTxService handles device-to-host transaction(s). * This function should be called once per Main Program loop. * * Note: None *****************************************************************************/ void CDCTxService(void) { byte byte_to_send; if(mCDCUsartTxIsBusy()) return; /* * Completing stage is necessary while [ mCDCUSartTxIsBusy()==1 ]. * By having this stage, user can always check cdc_trf_state, * and not having to call mCDCUsartTxIsBusy() directly. */ if(cdc_trf_state == CDC_TX_COMPLETING) cdc_trf_state = CDC_TX_READY; /* * If CDC_TX_READY state, nothing to do, just return. */ if(cdc_trf_state == CDC_TX_READY) return; /* * If CDC_TX_BUSY_ZLP state, send zero length packet */ if(cdc_trf_state == CDC_TX_BUSY_ZLP) { CDC_BULK_BD_IN.Cnt = 0; cdc_trf_state = CDC_TX_COMPLETING; } else if(cdc_trf_state == CDC_TX_BUSY) { /* * First, have to figure out how many byte of data to send. */ if(cdc_tx_len > sizeof(cdc_data_tx)) byte_to_send = sizeof(cdc_data_tx); else byte_to_send = cdc_tx_len; /* * Next, load the number of bytes to send to Cnt in buffer descriptor */ CDC_BULK_BD_IN.Cnt = byte_to_send; /* * Subtract the number of bytes just about to be sent from the total. */ cdc_tx_len = cdc_tx_len - byte_to_send; pCDCDst.bRam = (byte*)&cdc_data_tx; // Set destination pointer if(cdc_mem_type == _ROM) // Determine type of memory source { while(byte_to_send) { *pCDCDst.bRam = *pCDCSrc.bRom; pCDCDst.bRam++; pCDCSrc.bRom++; byte_to_send--; }//end while(byte_to_send) } else // _RAM { while(byte_to_send) { *pCDCDst.bRam = *pCDCSrc.bRam; pCDCDst.bRam++; pCDCSrc.bRam++; byte_to_send--; }//end while(byte_to_send._word) }//end if(cdc_mem_type...) /* * Lastly, determine if a zero length packet state is necessary. * See explanation in USB Specification 2.0: Section 5.8.3 */ if(cdc_tx_len == 0) { if(CDC_BULK_BD_IN.Cnt == sizeof(cdc_data_tx)) cdc_trf_state = CDC_TX_BUSY_ZLP; else cdc_trf_state = CDC_TX_COMPLETING; }//end if(cdc_tx_len...) }//end if(cdc_tx_sate == CDC_TX_BUSY) /* * Both CDC_TX_BUSY and CDC_TX_BUSY_ZLP states use the following macro */ mUSBBufferReady(CDC_BULK_BD_IN); }//end CDCTxService