📄 usb.c
字号:
///////////////////////////////////////////////////////////////////////////
//// usb.c ////
//// ////
//// Standard USB request and token handler code. ////
//// ////
//// This file is part of CCS's PIC USB driver code, which includes: ////
//// usb_desc.h - an example set of config and device descriptors ////
//// usb.c - USB token and request handler code ////
//// usb.h - definitions, prototypes and global variables ////
//// And the hardware peripheral level. At the time of writing, ////
//// CCS provides two hardware peripheral drivers. National ////
//// USBN960x (usbn960x.cc) and PIC16C7x5 (usb_pic.c). ////
//// ////
//// When developing using this driver, files must be included in this ////
//// order: ////
//// usb.h ////
//// usb_desc.h (or your own descriptor file) ////
//// <hardware layer code> ////
//// usb.c ////
//// ////
//// Two examples are given using CCS's PIC USB driver. ////
//// ex_usb_scope.c is a bulk device that sends 512 bytes to the ////
//// host and uses the USBN960x. ex_usb_hid.c is a HID device and ////
//// uses the PIC16C7x5. ////
//// ////
//// The majority of this code is called and used by the interrupt ////
//// generated by the hardware level, and therefore it is not meant ////
//// to be called by the user. The following functions are of use to ////
//// the user (for more docs on the functions, read the comments at ////
//// each function): ////
//// ////
//// ************************* NOTE ************************** ////
//// This code will not create a multiple configuration device. ////
//// If you wish to create a multiple configuration device then you ////
//// will have to modify these drivers. ////
//// ////
//// ************************* NOTE ************************** ////
//// This code does not support Get_Idle, Set_Idle, Get_Protocol ////
//// and Set_Protocol HID-specific requests. These requests are ////
//// optional. If you want to support these requests you must ////
//// provide the code yourself. See usb_get_idle(), usb_set_idle(), ////
//// usb_get_protocol() and usb_set_protocol(). ////
//// ////
//// ********************** FUNCTIONS *********************** ////
//// ////
//// usb_enumerated() - returns TRUE if device has been enumerated ////
//// (configured) by host, FALSE if it has not. ////
//// Do not try to use the USB peripheral until you ////
//// are enumerated. ////
//// ////
//// usb_wait_for_enumeration() - Sits in an infinte loop until device ////
//// is enumerated. ////
//// ////
//// usb_puts() - Sends a multiple packet message to the host ////
//// ////
//// ////
//// THE FOLLOWING FUNCTIONS ARE IN-EFFECIENT, BUT PROVIDE AN EXAMPLE ////
//// OF HOW TO GET DATA FROM THE USB CODE: ////
//// ////
//// usb_kbhit() - Similar to kbhit(), returns TRUE if there is new ////
//// data in the USB RX buffers. ////
//// ////
//// usb_gets() - Gets data from the local USB RX buffers. ////
//// ////
//// ////
//// The rest of the functions in this file are part of the USB ////
//// interrupt service routine and are not meant to be called by the ////
//// user. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// ////
//// If you wish to provide your own USB peripheral hardware layer, it ////
//// must include the following functions: ////
//// ////
//// void usb_stall_ep(int8 endpoint, int1 direction); ////
//// void usb_unstall_ep(int8 endpoint, int1 direction); ////
//// int1 usb_endpoint_stalled(int8 endpoint, int1 direction); ////
//// void usb_set_address(int8 address); ////
//// void usb_set_configured(int config); ////
//// int8 usb_get_packet(int8 endpoint, int8 * ptr, int8 max); ////
//// int1 usb_put_packet(int endpoint, int * ptr, int len, PID_TOGGLE toggle); ////
//// void usb_wrongstate(); ////
//// ////
//// CCS provides a USB peripheral hardware layer for PIC16C765 ////
//// (pic_usb.h) and National's USBN960x (usbn960x.c). See these ////
//// files for more documentation. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// ////
//// Version History: ////
//// ////
//// December 5th, 2003: Fixed a potential bug where descriptors are ////
//// evenly dividable by 8 (MAX_EP0_PACKET_SIZE) ////
//// ////
//// October 15th, 2003: Support for boot protocol added. ////
//// Set USB_BOOT_PROTOCOL to TRUE to support this. ////
//// The array hid_protocol[] saves which protocol mode each ////
//// interface is in. It is your applications job to send ////
//// data that either fit the boot protocol or HID protocol. ////
//// ////
//// May 6th, 2003: Fixed a potential stack overflow using PCM ////
//// ////
//// October 28th, 2002: Problem with usb_puts and timeout fixed. ////
//// ////
//// October 28th, 2002: Typo fixed in get_next_string_character(), ////
//// although it didn't cause any serious problems ////
//// ////
//// October 25th, 2002: Another change to usb_puts() was made to fix ////
//// problems with multiple packet messages ////
//// October 29th, 2002: Fixed a problem with multiple packet string ////
//// descriptors that require a 0 len packet to ////
//// end message. ////
//// ////
//// October 23rd, 2002: usb_puts() will bomb out of error quicker ////
//// ////
//// August 2nd, 2002: Initial Public Release ////
//// ////
//// TODO: Change usb_kbhit(), usb_gets(), usb_token_reset() and ////
//// usb_isr_tok_out_dne() to use pointers instead of multiple ////
//// #if code #endif. ////
//// ////
///////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2002 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
///////////////////////////////////////////////////////////////////////////
#IFNDEF __USB_DRIVER__
#DEFINE __USB_DRIVER__
#include <usb.h>
#IFNDEF __USB_HARDWARE__
#ERROR You must include USB hardware driver.
#ENDIF
#IFNDEF __USB_DESCRIPTORS__
#include <usb_desc.h> //if USB descriptors haven't been included by the users, use CCS's default ones
#ENDIF
#IF USB_BOOT_PROTOCOL
int hid_protocol[USB_NUM_INTERFACES]={1};
#ENDIF
int USB_Interface[USB_NUM_INTERFACES]; //config state for all of our interfaces, NUM_INTERFACES defined with descriptors
/// BEGIN User Functions
/**************************************************************
/* usb_enumerated()
/*
/* Input: Global variable USB_Curr_Config
/* Returns: Returns a 1 if device is configured / enumerated,
/* Returns a 0 if device is un-configured / not enumerated.
/*
/* Summary: Use this to see if device is configured / enumerated.
/***************************************************************/
int1 usb_enumerated(void) {
if (USB_Curr_Config) {return(1);}
else {return(0);}
}
/**************************************************************
/* usb_wait_for_enumeration()
/*
/* Input: Global variable USB_Curr_Config
/*
/* Summary: Waits in-definately until device is configured / enumerated.
/***************************************************************/
void usb_wait_for_enumeration(void) {
while (USB_Curr_Config == 0) {restart_wdt();}
}
/****************************************************************************
/* usb_puts(endpoint, *ptr, len, packet_size, timeout)
/*
/* Inputs: endpoint - endpoint to send data out
/* ptr - points to array of data to send
/* len - amount of data to send
/* packet_size - the max packet size of the endpoint
/* timeout - time in seconds, for each packet, to wait before timeout.
/* set to 0 for no timeout.
/*
/* Summary: Used for sending multiple packets of data as one message. If sending
/* only one packet it is more effecient to use only usb_put_packet()
/*
/*****************************************************************************/
int1 usb_puts(int8 endpoint, int8 * ptr, int16 len, int8 packet_size, int8 timeout) {
int16 i=0, tries;
int8 seconds;
int1 res=1;
int8 this_packet_len;
//send data packets until timeout or no more packets to send
while ((i < len)&&(res)) {
if ((len - i) > packet_size) {this_packet_len=packet_size;}
else {this_packet_len=len-i;}
tries=0;
seconds=0;
do {
res=usb_put_packet(endpoint,ptr + i,this_packet_len,TOGGLE); //send 64 byte packets
delay_ms(1);
tries++;
if (tries==1000) {tries=0; seconds++;}
} while ((!res)&&(seconds != timeout));
i+=packet_size;
}
//send 0len packet if needed
if ((res)&&(i==len)) {
tries=0;
seconds=0;
do {
res=usb_put_packet(endpoint,ptr,0,TOGGLE); //indicate end of message
delay_ms(1);
tries++;
if (tries==1000) {tries=0; seconds++;}
} while ((!res)&&(seconds != timeout));
}
return(res);
}
/****************************************************************************
/* usb_kbhit(endpoint)
/*
/* Input: endpoint - endpoint to check
/*
/* Output: TRUE if there is new data in RX buffer, FALSE if there is not.
/*
/* Summary: Similar to kbhit(), sees if there is new data in the RX USB buffers.
/*
/* NOTE - After getting the data, you must clear the .rx and .ov status bits.
/*
/*****************************************************************************/
int1 usb_kbhit(int8 endpoint) {
#IF USB_EP1_RX_ENABLE
if (endpoint==1) {
return(usb_ep1_rx_status.rx);
}
#ENDIF
#IF USB_EP2_RX_ENABLE
if (endpoint==2) {
return(usb_ep2_rx_status.rx);
}
#ENDIF
#IF USB_EP3_RX_ENABLE
if (endpoint==3) {
return(usb_ep3_rx_status.rx);
}
#ENDIF
#IF USB_EP4_RX_ENABLE
if (endpoint==4) {
return(usb_ep4_rx_status.rx);
}
#ENDIF
#IF USB_EP5_RX_ENABLE
if (endpoint==5) {
return(usb_ep5_rx_status.rx);
}
#ENDIF
#IF USB_EP6_RX_ENABLE
if (endpoint==6) {
return(usb_ep6_rx_status.rx);
}
#ENDIF
#IF USB_EP7_RX_ENABLE
if (endpoint==7) {
return(usb_ep7_rx_status.rx);
}
#ENDIF
#IF USB_EP8_RX_ENABLE
if (endpoint==8) {
return(usb_ep8_rx_status.rx);
}
#ENDIF
#IF USB_EP9_RX_ENABLE
if (endpoint==9) {
return(usb_ep9_rx_status.rx);
}
#ENDIF
#IF USB_EP10_RX_ENABLE
if (endpoint==10) {
return(usb_ep10_rx_status.rx);
}
#ENDIF
#IF USB_EP11_RX_ENABLE
if (endpoint==11) {
return(usb_ep11_rx_status.rx);
}
#ENDIF
#IF USB_EP12_RX_ENABLE
if (endpoint==12) {
return(usb_ep12_rx_status.rx);
}
#ENDIF
#IF USB_EP13_RX_ENABLE
if (endpoint==13) {
return(usb_ep13_rx_status.rx);
}
#ENDIF
#IF USB_EP14_RX_ENABLE
if (endpoint==14) {
return(usb_ep14_rx_status.rx);
}
#ENDIF
#IF USB_EP15_RX_ENABLE
if (endpoint==15) {
return(usb_ep15_rx_status.rx);
}
#ENDIF
}
/****************************************************************************
/* usb_gets(endpoint,ptr, max)
/*
/* Input: endpoint - endpoint to get data from
/* ptr - place / array to store data to
/* max - max amount of data to get from USB and store into ptr
/*
/* Output: Amount of data returned. It may be less than max.
/*
/* Summary: Gets data from the USB RX buffers, and stores into a user specified array.
/*
/* NOTE - This function will wait in-definately until data has arrived.
/* USe usb_kbhit() to prevent being stuck in an infinite loop.
/*
/* NOTE - THIS FUNCTION IS HORRIBLY IN-EFFECIENT, AND IS HERE ONLY TO PROVIDE
/* AN EXAMPLE OF WHERE AND HOW TO RECEIVE DATA.
/* The big reason for this is that all the data is currently
/* located in usb_epX_rx_buffer, where X is the endpoint. Instead
/* of taking data from the usb_epX_rx_buffer[] and storing into
/* ptr it would be less resource hungry to just read usb_epX_rx_buffer[]
/* directly. Remember, when accessing usb_epX_rx_buffer[] directly
/* be sure to clear usb_epX_rx_status.rx and usb_epX_rx_status.ov bits
/* when you are done dealing with the data in the RX buffer.
/*
/*
/*****************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -