usb_cdc_class.c File Reference

Pic CDC USB routines. More...

Include dependency graph for usb_cdc_class.c:

Data Structures

struct  line_coding
union  long_union

Defines

#define not_SERIAL_STATE   0xa1
#define req_CLEAR_COMM_FEATURE   0x04
#define req_GET_COMM_FEATURE   0x03
#define req_GET_ENCAPSULATED_RESPONSE   0x01
#define req_GET_LINE_CODING   0x21
#define req_SEND_BREAK   0x23
#define req_SEND_ENCAPSULATED_COMMAND   0x00
#define req_SET_COMM_FEATURE   0x02
#define req_SET_CONTROL_LINE_STATE   0x22
#define req_SET_LINE_CODING   0x20

Functions

uns8 usb_cdc_getc (void)
 Retrieve a received character from the USB serial port.
void usb_cdc_handle_tx ()
 Transmit any buffered characters over ther USB virtual serial port.
void usb_cdc_print_int (uns16 i)
 Print a 16 bit number to the USB virtual serial port.
void usb_cdc_print_str (char *str)
 Print a string out to the USB virtual serial port.
void usb_cdc_putc (uns8 c)
 Sends a single character to the USB serial port.
uns8 usb_cdc_rx_avail ()
 Check to see if a character is available in the receive buffer.
void usb_cdc_set_dcd ()
void usb_cdc_set_dsr ()
void usb_cdc_setup ()
 Set up data structures ready for USB CDC use.
uns8 usb_cdc_tx_empty ()
 Check to see if the transmit buffer is empty.
void usb_ep_data_in_callback (uns8 end_point, uns16 byte_count)
 Callback routine triggered when data has been sent to the host.
void usb_ep_data_out_callback (uns8 end_point, uns8 *buffer, uns16 byte_count)
 Callback routine triggered when data has been sent to the device.
void usb_handle_class_ctrl_read_callback ()
 Callback routine for a class control read.
void usb_handle_class_ctrl_write_callback (uns8 *data, uns16 count)
 Callback routine for a class control write.
void usb_handle_class_request_callback (setup_data_packet sdp)
 Callback routine for a control transfer request that is placed on the class.
void usb_SOF_callback (uns16 frame)
 Callback routine triggered each time a start of frame (SOF) has been received.

Variables

uns8 cdc_rx_buffer [USB_CDC_RX_BUFFER_SIZE]
uns8 cdc_rx_end = 0
uns8 cdc_rx_start = 0
uns8 cdc_tx_buffer [USB_CDC_TX_BUFFER_SIZE]
uns8 cdc_tx_end = 0
uns8 cdc_tx_start = 0
uns8 class_data [8]
uns16 current_bit_rate
uns8 data_bits
long_union dte_rate
uns8 parity

Detailed Description

Communication Device Class (Serial Port) USB routines


Define Documentation

#define not_SERIAL_STATE   0xa1
#define req_CLEAR_COMM_FEATURE   0x04
#define req_GET_COMM_FEATURE   0x03
#define req_GET_ENCAPSULATED_RESPONSE   0x01
#define req_GET_LINE_CODING   0x21
#define req_SEND_BREAK   0x23
#define req_SEND_ENCAPSULATED_COMMAND   0x00
#define req_SET_COMM_FEATURE   0x02
#define req_SET_CONTROL_LINE_STATE   0x22
#define req_SET_LINE_CODING   0x20

Function Documentation

uns8 usb_cdc_getc (  ) 

Receive a character from the USB serial port. If a character has not been received, this routine will wait indefinately.

Returns:
Byte from the receive buffer.

00377 {
00378     uns8 cdc_rx_char, cdc_rx_next;
00379     
00380     while(cdc_rx_end == cdc_rx_start);  // wait until there is something received
00381 
00382     start_crit_sec();   // make sure nobody else can muck with the buffer
00383     
00384     cdc_rx_char = cdc_rx_buffer[cdc_rx_start];  // get character from the front of the buffer
00385     cdc_rx_start++; // increment fifo start
00386     if (cdc_rx_start == USB_CDC_RX_BUFFER_SIZE) {   // if we're at the end
00387         cdc_rx_start = 0;   // then wrap to the beginning
00388     }
00389     
00390     end_crit_sec(); // now they can muck with the buffer
00391     
00392     return (cdc_rx_char);   // return the result we first thought of
00393 
00394 }   // -- getc    

void usb_cdc_handle_tx (  ) 

Generally only used internally, this routine will attempt to place any characters in the transmit queue into the USB buffers. It will fail gracefully if the USB buffer is already owned by the SIE.

00398 {
00399 uns8 cdc_tx_next;
00400 uns8 count;
00401 uns16 buffer_size;
00402 uns8 *buffer;
00403 buffer_descriptor *bd;
00404 
00405     bd = ep_in_bd_location[USB_CDC_DATA_ENDPOINT];
00406     if (test_bit(bd->stat, UOWN)) { // if there's already something in play
00407         return; // give up
00408     }
00409     
00410     buffer_size = ep_in_buffer_size[USB_CDC_DATA_ENDPOINT];
00411     buffer = ep_in_buffer_location[USB_CDC_DATA_ENDPOINT];
00412 
00413     if (cdc_tx_end == cdc_tx_start) { // anything in the fifo?
00414        return; // nope
00415     }
00416     #ifdef CDC_DEBUG
00417         serial_putc('<');
00418     #endif
00419     start_crit_sec();
00420     
00421     count = 0;
00422     while ((cdc_tx_end != cdc_tx_start) && (count < buffer_size)) {
00423         
00424         cdc_tx_next = cdc_tx_start + 1; // get next position
00425         if (cdc_tx_next == USB_CDC_TX_BUFFER_SIZE) {    // if we're at the end of the buffer
00426             cdc_tx_next = 0;    // wrap to the beginning
00427         }
00428         buffer[count] = cdc_tx_buffer[cdc_tx_start];    // transmit the character
00429         #ifdef CDC_DEBUG
00430             serial_putc(buffer[count]);
00431         #endif  
00432         count++;
00433         cdc_tx_start = cdc_tx_next; // move start position of fifo
00434     } 
00435     if (count > 0) {
00436         bd->count = count;
00437         bd->addr = (uns16)buffer;
00438 
00439         toggle_bit(bd->stat, DTS);
00440         clear_bit(bd->stat, KEN);   // clear the keep bit
00441         clear_bit(bd->stat, INCDIS);    // clear the increment disable
00442         set_bit  (bd->stat, DTSEN);
00443         clear_bit(bd->stat, BSTALL);    // clear stall bit
00444         clear_bit(bd->stat, BC9);
00445         clear_bit(bd->stat, BC8);
00446 
00447         set_bit  (bd->stat, UOWN);  // SIE owns the buffer
00448     }
00449     end_crit_sec();
00450     #ifdef CDC_DEBUG
00451         serial_putc('>');
00452         serial_print_str("send=");
00453         serial_print_int(count);
00454         serial_putc(' ');
00455     #endif
00456     #ifdef USB_CDC_USE_LEDS
00457         platform_leds_flash(2);
00458     #endif
00459 }

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_cdc_print_int ( uns16  i  ) 

Print a 16 bit unsigned number in decimal to the USB virtual serial port

Parameters:
i the 16 bit number to be printed

00497                                 {
00498 
00499 char buffer[6]; // up to 5 characters plus \0
00500 uns8 count = 5;
00501     buffer[5] = '\0';
00502     do {
00503         count--;
00504         buffer[count] = '0' + i % 10;
00505         i = i / 10;
00506     } while (i > 0);    
00507     while (buffer[count]) {
00508         usb_cdc_putc(buffer[count]);
00509         count++;
00510     }  
00511     //serial_print_str(&buffer[count]); //  print it out 
00512 //  for(count = 0 ; str[count] != 0; count++)
00513  //   {
00514  //   }
00515 
00516 }   

Here is the call graph for this function:

void usb_cdc_print_str ( char *  str  ) 

Send a null terminated string out the virtual serial port

Parameters:
str the string to be sent

00464                                   {
00465 
00466 uns8 count;
00467 buffer_descriptor *bd;
00468 
00469     for(count = 0 ; str[count] != 0; count++)
00470     {
00471         usb_cdc_putc(str[count]);
00472     }
00473     
00474     // This will give possibly quicker send:
00475     
00476     //bd = ep_in_bd_location[CDC_DATA_ENDPOINT];
00477     //if (!test_bit(bd->stat, UOWN)) {
00478     //  usb_cdc_handle_tx();
00479     //} 
00480     // otherwise we wait for the SOF interrupt to send
00481 }    

Here is the call graph for this function:

void usb_cdc_putc ( uns8  c  ) 

Deliver a single character out the virtual serial port. This routine will add the character to the transmit buffer. The actual buffer will be physically sent on the Start Of Frame (SOF) interrupt (each 1ms) or on the end point interrupt - ie, when the last character or chunk of characters was sent.

Parameters:
c The 8 bit byte to be transmitted.

00348                           {
00349 uns8 cdc_tx_next;
00350 bit  my_store_gie;
00351 #ifdef CDC_IDE_DEBUG
00352 return;
00353 #endif
00354 
00355     cdc_tx_next = cdc_tx_end + 1;   // get next buffer position
00356     if (cdc_tx_next == USB_CDC_TX_BUFFER_SIZE) {    // if we're at the end
00357         cdc_tx_next = 0;    // wrap to the beginning
00358     }
00359     
00360     if ((!intcon.GIE) && (cdc_tx_next == cdc_tx_start)) {
00361         return;
00362     }
00363     while (cdc_tx_next == cdc_tx_start) {
00364 
00365     }
00366     
00367     start_crit_sec();
00368     
00369     cdc_tx_buffer[cdc_tx_end] = c; // put it in
00370     cdc_tx_end = cdc_tx_next;  // move pointer along
00371     
00372     end_crit_sec();
00373     
00374 }

Here is the caller graph for this function:

uns8 usb_cdc_rx_avail (  ) 

If one or more bytes are available in the USB serial port receive buffer, this routine will return true. If there are no bytes available, it will return false.

Returns:
True if buffer is not empty, False if buffer is empty.

00461 { return cdc_rx_start != cdc_rx_end; }

void usb_cdc_set_dcd (  ) 

00340                        {
00341 }

void usb_cdc_set_dsr (  ) 

00343                        {
00344 }       

void usb_cdc_setup (  ) 

Configures the default DTE rate, stop bits etc.

00488                      {
00489     
00490     current_bit_rate = SPBRG_9600;
00491     parity = 0;
00492     // 9600
00493     dte_rate.as_long = 9600;
00494 
00495 }   

uns8 usb_cdc_tx_empty (  ) 

Sometimes it is useful to see if the transmit buffer is empty, since then you can be sure your data is well on its way. In the case of USB, this means that the data has been at least placed into the outbound USB buffer; it's not possible to tell until after the fact if the data has actually been squirted out the USB port.

Returns:
True if transmit buffer is empty, False if buffer still has data in it.

00462 { return cdc_tx_start == cdc_tx_end; }

void usb_ep_data_in_callback ( uns8  end_point,
uns16  byte_count 
)

If you have called usb_send_data to transfer data to the host, this routine will be fired once this data has been transferred. You may send more data by using usb_send_data(). Since the current PicPack USB library supports only single buffering, transfer speed is limited by how quickly you can refill the buffer again. In the future, we may support double buffering (ping poing buffering) which will most likely improve transfer speeds (to be fair, transfer performance has not been a limiting factor in tests so far).

In order for this callback to be triggered, you must define USB_EP_DATA_CALLBACK in your config.h

Parameters:
end_point The endpoint on which the data was transferred
byte_count The number of bytes that were actually transferred

00328                                                                {
00329     #ifdef CDC_DEBUG
00330         serial_print_str(" EP data in: ");
00331         serial_print_int(byte_count);
00332         serial_print_str(" bytes ");
00333     #endif  
00334     // data has been sent, so do we need to send more?
00335     if (end_point == USB_CDC_DATA_ENDPOINT) {   // it's the data end point
00336         usb_cdc_handle_tx();
00337     }   
00338 }   

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_ep_data_out_callback ( uns8  end_point,
uns8 *  buffer_location,
uns16  byte_count 
)

If data is sent to the device and the endpoint is not endpoint 0 (the control transfer endpoint) then this routine is called. Since the routine is passed the actual hardware buffer location, it is important to pull data out of the buffer as soon as possible in order to free up the buffer to receive more data. The buffer is re-primed only once this routine completes since PicPack only supports single-buffered mode. In the future, we may look at supporting double buffering (ping-pong buffering) in order to be able to receive more data even while this routine is being called.

In order for this callback to be triggered, you must define USB_EP_DATA_CALLBACK in your config.h

Parameters:
end_point The endpoint the data was sent do
buffer_lcoation The memory location of the USB buffer where the data was received into
byte_count The number of bytes received

00289                                                 {
00290     uns8 cdc_rx_next;
00291     #ifdef CDC_DEBUG
00292         serial_print_str(" EP data out: ");
00293         serial_print_int(byte_count);
00294         serial_print_str(" bytes ");
00295     #endif
00296     
00297     // We have some data!
00298 
00299     if (end_point == USB_CDC_DATA_ENDPOINT) {   // it's the data end point
00300         uns8 count;
00301         for (count = 0; count < byte_count; count++) {
00302             cdc_rx_next = cdc_rx_end + 1;   // get next buffer position 
00303             if (cdc_rx_next == USB_CDC_RX_BUFFER_SIZE) {    // if we're at the end
00304                 cdc_rx_next = 0;    // then wrap to the beginning
00305             }
00306             if (cdc_rx_next != cdc_rx_start) { // if space in the fifo
00307                 cdc_rx_buffer[cdc_rx_end] = buffer[count]; // put it in
00308                 cdc_rx_end = cdc_rx_next;  // and move pointer along
00309             } else {
00310                 // else... just ignore it, we've lost a byte, no room in the inn
00311                 break;
00312             }   
00313         }   
00314     } else {
00315         #ifdef CDC_DEBUG
00316             serial_print_str("data for ep ");
00317             serial_print_int(end_point);
00318         #endif  
00319     }
00320 
00321     #ifdef USB_CDC_USE_LEDS
00322         platform_leds_flash(3);
00323     #endif  
00324 }       

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_handle_class_ctrl_read_callback (  ) 

When a control transfer is taking place, this routine is called to indicate that a control read for the class has taken place. Since everything in USB land is all about what has just happened, this callback will occur after data has been transferred to the host. If you wish to send more data to the host, use usb_send_data(), or if your control read has sent all the data required, you will need to indicate that the state has changed by setting the control_mode variable to cm_CTRL_READ_AWAITING_STATUS. This will indicate to the stack that it should now wait for the status packet before completing the control transfer.

To allow this callback to trigger, ensure you define USB_CALLBACK_ON_CLASS_CTRL in your config.h

00273                                            {
00274         switch (usb_sdp.bRequest) {
00275             case req_GET_LINE_CODING:
00276                 // we know we've already sent everything, so now wait for status
00277                 control_mode = cm_CTRL_READ_AWAITING_STATUS;
00278                 break;
00279             default:
00280                 #ifdef CDC_DEBUG
00281                     serial_print_str(" cl read ?? ");
00282                     serial_print_int(usb_sdp.bRequest);
00283                 #endif  
00284         }       
00285             
00286 }

Here is the call graph for this function:

void usb_handle_class_ctrl_write_callback ( uns8 *  data,
uns16  count 
)

When a control transfer is taking place, this routine is called to indicate that a control write for the class has taken place. Since everything in USB land is all about what has just happened, this callback will occur after data has been received by the device. If you expect more data from the host, it will arrive in due course since endpoint 0 will be primed for more data automatically. If you have received all the data from the host, you will need to set the control_mode state variable to cm_CTRL_WRITE_SENDING_STATUS and then actually send the status by calling usb_send_status_ack(). Once the status has actually been sent, the control_mode state will automatically change to cm_IDLE to indicate the transfer has completed.

To allow this callback to trigger, ensure you define USB_CALLBACK_ON_CLASS_CTRL in your config.h

00171                                                                    {
00172 
00173     switch (usb_sdp.bRequest) {
00174         case req_SET_LINE_CODING:
00175             // dump it into class_data
00176             memcpy(/* dst */ (void *)&class_data,/* src */ (void *)data, count);
00177             
00178             // Now we need to send an ACK status back
00179 
00180             usb_send_status_ack();
00181             control_mode = cm_CTRL_WRITE_SENDING_STATUS;            
00182 
00183             line_coding *my_lc;
00184             my_lc = (line_coding*) &class_data;
00185             #ifdef CDC_DEBUG
00186                 serial_print_int_hex(my_lc->dte_rate.as_byte_array[0]);
00187                 serial_print_int_hex(my_lc->dte_rate.as_byte_array[1]);
00188                 serial_print_int_hex(my_lc->dte_rate.as_byte_array[2]);
00189                 serial_print_int_hex(my_lc->dte_rate.as_byte_array[3]);
00190                 serial_print_str(" st=");
00191                 serial_print_int(my_lc->stop_bits);
00192                 serial_print_str(" p=");
00193                 serial_print_int(my_lc->parity);
00194                 serial_print_str(" db=");
00195                 serial_print_int(my_lc->data_bits);
00196                 serial_print_str(" bit rate: ");
00197             #endif
00198 
00199             dte_rate.as_byte_array[0] = my_lc->dte_rate.as_byte_array[3];
00200             dte_rate.as_byte_array[1] = my_lc->dte_rate.as_byte_array[2];
00201             dte_rate.as_byte_array[2] = my_lc->dte_rate.as_byte_array[1];
00202             dte_rate.as_byte_array[3] = my_lc->dte_rate.as_byte_array[0];
00203             parity = my_lc->parity;
00204             data_bits = my_lc->data_bits;
00205             
00206             switch (my_lc->dte_rate.as_long) {
00207                 case 2400: 
00208                     current_bit_rate = SPBRG_2400;
00209                     #ifdef CDC_DEBUG
00210                     serial_print_str("2400 ");
00211                     #endif
00212                     break;
00213                 case 4800: 
00214                     current_bit_rate = SPBRG_4800;
00215                     #ifdef CDC_DEBUG
00216                     serial_print_str("4800 ");
00217                     #endif
00218                     break;
00219                 case 9600: 
00220                     current_bit_rate = SPBRG_9600;
00221                     #ifdef CDC_DEBUG
00222                     serial_print_str("9600 ");
00223                     #endif
00224                     break;
00225                 case 19200: 
00226                     current_bit_rate = SPBRG_19200;
00227                     #ifdef CDC_DEBUG
00228                     serial_print_str("19200 ");
00229                     #endif
00230                     break;
00231                 case 38400: 
00232                     current_bit_rate = SPBRG_38400;
00233                     #ifdef CDC_DEBUG
00234                     serial_print_str("38400 ");
00235                     #endif
00236                     break;
00237                 case 115200: 
00238                     current_bit_rate = SPBRG_115200;
00239                     #ifdef CDC_DEBUG
00240                     serial_print_str("115200 ");
00241                     #endif
00242                     break;
00243                 default:    
00244                     #ifdef CDC_DEBUG
00245                         serial_print_str("Don't handle this bit rate");
00246                     #endif
00247             }
00248             
00249             clear_bit(rcsta, SPEN);
00250             clear_bit(txsta, TXEN);
00251             clear_bit(rcsta, CREN); 
00252             
00253   
00254             serial_setup(current_bit_rate);
00255             if (!serial_tx_empty()) {
00256                 #ifdef USB_CDC_USE_LEDS
00257                     platform_leds_flash(1);
00258                 #endif
00259                 set_bit(pie1, TXIE);
00260                 serial_tx_isr();
00261             }
00262             break;
00263         default:
00264             #ifdef CDC_DEBUG
00265                 serial_print_str(" ??cw req=");
00266                 serial_print_int_hex(usb_sdp.bRequest);
00267                 serial_putc(' ');
00268             #endif  
00269             break;
00270     }       
00271 }   

Here is the call graph for this function:

void usb_handle_class_request_callback ( setup_data_packet  sdp  ) 

After receiving a setup packet, where the request is placed on the class, this routine is called. In usb_handle_class_request_callback, you can set up ready for the data stage of the control transfer. The direction of the data stage can be determined by examining test_bit(sdp.bRequest, DATA_STAGE_DIR) although generally it appears to be obvious from the request. The request is stored in sdp.bRequest.

Typically, if it is a control read transfer (that is, it is a request by the host for data), then you will need to move the control_mode state variable to cm_CTRL_READ_DATA_STAGE_CLASS and send data using usb_send_data(). If you only intend to send one packet, you can immediately move the control_mode state variable to cm_CTRL_READ_AWAITING_STATUS to indicate you are waiting for the status to arrive. You could wait for the usb_handle_class_ctrl_read callback and do it (move to cm_CTROL_READ_AWAITING_STATUS) but the PicPack USB stack can handle the control read event for you if you've already switched states.

If it is a control write transfer (that is, it is a request by the host to send data to the device), then you will need to move the control_mode state variable to cm_CTRL_WRITE_DATA_STAGE_CLASS. Then, the usb_handle_class_ctrl_write will be fired when data is received by the device in the data stage.

To allow this callback to trigger, ensure you define USB_CALLBACK_ON_CLASS_CTRL in your config.h

00115                                                               {
00116 
00117     switch (sdp.bRequest) {
00118         case req_SET_LINE_CODING:
00119             // we now expect the line coding to arrive in the data stage
00120             
00121             #ifdef CDC_DEBUG
00122                 serial_print_str("SET_LINE ");
00123             #endif
00124             control_mode = cm_CTRL_WRITE_DATA_STAGE_CLASS;
00125             break;
00126         case req_GET_LINE_CODING:
00127             #ifdef CDC_DEBUG
00128                 serial_print_str("GET_LINE ");
00129                 serial_print_str(" len=");
00130                 serial_print_int(sdp.wLength);
00131                 serial_putc(' ');
00132             #endif
00133             //control_mode = cm_CTRL_READ_DATA_STAGE_CLASS;
00134             control_mode = cm_CTRL_READ_DATA_STAGE_CLASS;
00135             //  need to prime ep0 IN with some funky data here
00136             line_coding my_line_coding;
00137             
00138             // We stored dte rate from ealier
00139             my_line_coding.dte_rate.as_byte_array[0] = dte_rate.as_byte_array[3];
00140             my_line_coding.dte_rate.as_byte_array[1] = dte_rate.as_byte_array[2];
00141             my_line_coding.dte_rate.as_byte_array[2] = dte_rate.as_byte_array[1];
00142             my_line_coding.dte_rate.as_byte_array[3] = dte_rate.as_byte_array[0];           
00143             my_line_coding.stop_bits = 0;   // 1 stop bit
00144             my_line_coding.data_bits = data_bits;   
00145             my_line_coding.parity = parity;     
00146             
00147             usb_send_data(/*ep*/ 0, /*data*/ (uns8 *)&my_line_coding, /*count*/ sizeof(my_line_coding), /*first*/ 1);
00148             // actually we know this will be the last packet, so go straight to waiting for the status ack
00149             control_mode = cm_CTRL_READ_AWAITING_STATUS;
00150             
00151             break;
00152         case req_SET_CONTROL_LINE_STATE:
00153             #ifdef CDC_DEBUG
00154                 serial_print_str("scls=");//dtr = bit 0, rts = bit 1
00155                 serial_print_int_hex(sdp.wValue);
00156             #endif
00157             // no data, so just ack the status
00158             // !!! set dtr, rts
00159             usb_send_status_ack();
00160             control_mode = cm_CTRL_WRITE_SENDING_STATUS;
00161             // Could put a callback here for your own code when DTR or RTS change
00162             break;
00163         default:
00164             #ifdef CDC_DEBUG
00165                 serial_print_str("??r=");
00166                 serial_print_int(sdp.bRequest);
00167             #endif  
00168     }
00169 }

Here is the call graph for this function:

void usb_SOF_callback ( uns16  frame  ) 

Frames in USB occur each 1ms. A SOF packet is sent to each device at the start of each frame. This is a really neat way of getting a 1ms timer without any further work.

Parameters:
frame The frame number. Frames will wrap at 65535.

00483                                    {
00484     // we don't care about the frame number, we only care if there's something to send...
00485     usb_cdc_handle_tx();    // start transmission
00486 }

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

uns8 cdc_rx_buffer[USB_CDC_RX_BUFFER_SIZE]

Receive fifo

uns8 cdc_rx_end = 0

Receive fifo end point

uns8 cdc_rx_start = 0

Receive fifo start point

uns8 cdc_tx_buffer[USB_CDC_TX_BUFFER_SIZE]

Transmit fifo

uns8 cdc_tx_end = 0

Transmit fifo end point

uns8 cdc_tx_start = 0

Transmit fifo start point

uns8 class_data[8]
uns8 data_bits
uns8 parity

Generated on Fri Aug 19 09:09:42 2011 for Pic Pack Library by  doxygen 1.6.1