pic_usb.c File Reference

Include dependency graph for pic_usb.c:

Functions

void turn_usb_ints_on ()
 Turn on USB interrupts.
void usb_configure_endpoints ()
void usb_enable_module ()
 Enables the USB hardware and starts USB negotiations.
usb_state_type usb_get_state ()
 Query the current state of the USB connection.
void usb_handle_isr ()
 Handle USB interrupts.
void usb_handle_reset ()
void usb_handle_stall ()
void usb_handle_standard_request (setup_data_packet sdp)
void usb_handle_transaction (uns8 stat)
void usb_prime_ep0_out_e ()
void usb_prime_ep0_out_o ()
void usb_send_data (uns8 ep, uns8 *data, uns8 send_count, bit first)
 Send data over an endpoint pipe.
void usb_send_data_chunk ()
void usb_send_empty_data_pkt ()
 Send an empty data packet.
void usb_send_one_byte (uns8 data)
void usb_setup ()
 Setup USB hardware ready for use.
void usb_stall_ep0 ()
 Send a stall on control transfer endpoint.
void usb_stall_on_in ()

Variables

uns8 buffer_byte
control_mode_type control_mode
buffer_descriptordelivery_bd
uns8 * delivery_buffer
uns8 delivery_buffer_size
uns16 delivery_bytes_max_send
uns16 delivery_bytes_sent
uns16 delivery_bytes_to_send
uns8 * delivery_ptr
uns8 usb_address
setup_data_packet usb_sdp
usb_state_type usb_state = st_POWERED
usb_status_type usb_status

Function Documentation

void turn_usb_ints_on (  ) 

If you are using interrupt-driven code (generally the best way of doing things) you can turn on USB interrupts using turn_usb_ints_on(). Don't forget that you will also need to call turn_global_ints_on() as well. Typically this is called in your system setup routine.

00962                         {
00963     
00964     set_bit(uie,  STALLIE); // interrupt on stall
00965     set_bit(uie,  TRNIE);   //   on transaction complete
00966     set_bit(uie,  URSTIE);  //   on reset 
00967     set_bit(pie2, USBIE);   // general USB interrupts
00968     #ifdef USB_CALLBACK_ON_SOF 
00969         set_bit(uie, SOFIE);
00970     #endif  
00971 }

void usb_configure_endpoints (  ) 

00066                                {
00067     
00068 #ifdef USB_DEBUG
00069     serial_print_str("Config eps ");
00070 #endif  
00071 #ifdef USB_EP1
00072     set_bit  (uep1, EPHSHK);    // EP handshaking on
00073     #ifdef USB_EP1_OUT_SIZE
00074         set_bit(uep1, EPOUTEN); // EP OUT enabled
00075     #else
00076         clear_bit(uep1, EPOUTEN);   // EP OUT disabled
00077     #endif
00078     #ifdef USB_EP1_IN_SIZE
00079         set_bit(uep1, EPINEN);  // EP IN enabled
00080     #else
00081         clear_bit(uep1, EPINEN);    // EP IN disabled
00082     #endif
00083     set_bit  (uep1, EPCONDIS);  // control transfers off
00084     
00085     // for IN
00086     #ifdef USB_EP1_IN_SIZE
00087         set_bit(bd1in.stat, DTS);   // turn on data togle sync TOGGLE
00088         clear_bit(bd1in.stat, KEN); // clear the keep bit
00089         clear_bit(bd1in.stat, INCDIS);  // clear the increment disable
00090         clear_bit(bd1in.stat, DTSEN);
00091         clear_bit(bd1in.stat, BSTALL);  // clear stall bit
00092         clear_bit(bd1in.stat, BC9);
00093         clear_bit(bd1in.stat, BC8);
00094     
00095         clear_bit(bd1in.stat, UOWN);    // uC owns the buffer
00096     #endif
00097     // for OUT
00098     #ifdef USB_EP1_OUT_SIZE
00099         bd1out.count = USB_EP1_OUT_SIZE;
00100         bd1out.addr  = USB_EP1_OUT_ADDR;
00101         
00102         clear_bit(bd1out.stat, DTS);    // turn on data togle sync TOGGLE
00103         clear_bit(bd1out.stat, KEN);    // clear the keep bit
00104         clear_bit(bd1out.stat, INCDIS); // clear the increment disable
00105         clear_bit(bd1out.stat, DTSEN);
00106         clear_bit(bd1out.stat, BSTALL); // clear stall bit
00107         clear_bit(bd1out.stat, BC9);
00108         clear_bit(bd1out.stat, BC8);
00109         set_bit  (bd1out.stat, UOWN);   // SIE owns the buffer
00110         
00111     #endif
00112     
00113 
00114 #endif
00115 
00116 #ifdef USB_EP2
00117     set_bit  (uep2, EPHSHK);    // EP handshaking on
00118     #ifdef USB_EP2_OUT_SIZE
00119         set_bit(uep2, EPOUTEN); // EP OUT enabled
00120     #else
00121         clear_bit(uep2, EPOUTEN);   // EP OUT disabled
00122     #endif
00123     #ifdef USB_EP2_IN_SIZE
00124         set_bit(uep2, EPINEN);  // EP IN enabled
00125     #else
00126         clear_bit(uep2, EPINEN);    // EP IN disabled
00127     #endif
00128     set_bit  (uep2, EPCONDIS);  // control transfers off
00129 
00130     // for IN
00131     #ifdef USB_EP2_IN_SIZE
00132     
00133         set_bit(bd2in.stat, DTS);   // turn on data togle sync TOGGLE
00134         clear_bit(bd2in.stat, KEN); // clear the keep bit
00135         clear_bit(bd2in.stat, INCDIS);  // clear the increment disable
00136         clear_bit(bd2in.stat, DTSEN);
00137         clear_bit(bd2in.stat, BSTALL);  // clear stall bit
00138         clear_bit(bd2in.stat, BC9);
00139         clear_bit(bd2in.stat, BC8);
00140     
00141         clear_bit(bd2in.stat, UOWN);    // uC owns the buffer
00142     #endif
00143     // for OUT
00144     #ifdef USB_EP2_OUT_SIZE
00145         bd2out.count = USB_EP2_OUT_SIZE;
00146         bd2out.addr  = USB_EP2_OUT_ADDR;
00147 
00148         clear_bit(bd2out.stat, DTS);    // turn on data togle sync TOGGLE
00149         clear_bit(bd2out.stat, KEN);    // clear the keep bit
00150         clear_bit(bd2out.stat, INCDIS); // clear the increment disable
00151         clear_bit(bd2out.stat, DTSEN);
00152         clear_bit(bd2out.stat, BSTALL); // clear stall bit
00153         clear_bit(bd2out.stat, BC9);
00154         clear_bit(bd2out.stat, BC8);
00155         set_bit  (bd2out.stat, UOWN);   // SIE owns the buffer
00156     #endif
00157 #endif
00158 
00159 #ifdef USB_EP3
00160     set_bit  (uep3, EPHSHK);    // EP handshaking on
00161     #ifdef USB_EP3_OUT_SIZE
00162         set_bit(uep3, EPOUTEN); // EP OUT enabled
00163     #else
00164         clear_bit(uep3, EPOUTEN);   // EP OUT disabled
00165     #endif
00166     #ifdef USB_EP3_IN_SIZE
00167         set_bit(uep3, EPINEN);  // EP IN enabled
00168     #else
00169         clear_bit(uep3, EPINEN);    // EP IN disabled
00170     #endif
00171     set_bit  (uep3, EPCONDIS);  // control transfers off
00172     // for IN
00173     #ifdef USB_EP3_IN_SIZE
00174         set_bit(bd3in.stat, DTS);   // ready for toggle
00175         clear_bit(bd3in.stat, KEN); // clear the keep bit
00176         clear_bit(bd3in.stat, INCDIS);  // clear the increment disable
00177         clear_bit(bd3in.stat, DTSEN);
00178         clear_bit(bd3in.stat, BSTALL);  // clear stall bit
00179         clear_bit(bd3in.stat, BC9);
00180         clear_bit(bd3in.stat, BC8);
00181     
00182         clear_bit(bd3in.stat, UOWN);    // uC owns the buffer
00183     #endif
00184     // for OUT
00185     #ifdef USB_EP3_OUT_SIZE
00186         bd3out.count = USB_EP3_OUT_SIZE;
00187         bd3out.addr  = USB_EP3_OUT_ADDR;
00188 
00189         clear_bit(bd3out.stat, DTS);    // turn on data togle sync TOGGLE
00190         clear_bit(bd3out.stat, KEN);    // clear the keep bit
00191         clear_bit(bd3out.stat, INCDIS); // clear the increment disable
00192         clear_bit(bd3out.stat, DTSEN);
00193         clear_bit(bd3out.stat, BSTALL); // clear stall bit
00194         clear_bit(bd3out.stat, BC9);
00195         clear_bit(bd3out.stat, BC8);
00196         set_bit  (bd3out.stat, UOWN);   // SIE owns the buffer
00197     #endif
00198 
00199 #endif
00200     
00201 }

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_enable_module (  ) 

After you've called usb_setup(), you can call usb_enable_module() whenever you're ready for USB negotiations to occur. Normally, this would need to occur relatively quickly after power-up if your PIC is powered by USB and it's purpose is to talk over USB. This is normally called from your main() routine once all other configuration is done.

Once the USB module has successfully negotiated a connection with the host, usb_device_configured_callback() will be called if you have requested this in your config.h file. This will indicate a successful connection. Because of the way USB works, there is no way to tell that it *hasn't* worked, except via a timer - if you haven't had a good connection in several seconds, you can assume it has failed (although this may just mean the user is hunting for a driver disk etc).

01033                          {
01034     uir = 0;
01035     set_bit(ucon, USBEN);   // enable USB serial interface engine (SIE)
01036     usb_state = st_DEFAULT;
01037 }

usb_state_type usb_get_state (  ) 

Returns the USB state, either powered, default, address or connect. This is updated as the negotiation progresses. It may be useful to query this if, after a suitable time-out, the connection has not been made.

01039                                {
01040     return usb_state;
01041 }

void usb_handle_isr (  ) 

usb_handle_isr() should be inserted in your interrupt service routine. Alternatively, if you have reason not to want to do interrupt-driven USB, for example, a bootloader, you can poll this routine.

Make sure you call turn_usb_ints() and turn_global_ints_on() to ensure interrupts occur.

It will check for any of the USB interrupt flags and handle: USB transactions, USB reset, USB stall, USB Start Of Frame (including calling usb_SOF_callback() if configured in your config.h and most importantly USB transaction, which is where all the hard work is done.

00928                       {
00929     
00930     while (test_bit(pir2, USBIF)) {
00931         
00932         while (test_bit(uir, TRNIF)) {
00933             uns8 stat = ustat;
00934             clear_bit(uir, TRNIF);
00935             usb_handle_transaction(stat);
00936         }
00937         
00938         if (test_bit(uir, URSTIF)) {
00939             usb_handle_reset();
00940             clear_bit(uir, URSTIF);
00941         }   
00942         
00943         if (test_bit(uir, STALLIF)) {
00944             usb_handle_stall();
00945             clear_bit(uir, STALLIF);
00946         }
00947         if (test_bit(uir, SOFIF)) {
00948             #ifdef USB_CALLBACK_ON_SOF
00949                 #ifdef ufrm
00950                     usb_SOF_callback(ufrm);
00951                 #else
00952                     usb_SOF_callback(ufrmh << 8 | ufrml);
00953                 #endif  
00954                 clear_bit(uir, SOFIF);
00955             #endif
00956         }
00957         
00958         clear_bit(pir2, USBIF);
00959     }
00960 }

Here is the call graph for this function:

void usb_handle_reset (  ) 

00853                         {
00854     usb_address = 0;
00855     //uaddr = 0;
00856     
00857     control_mode = cm_IDLE;
00858     usb_status   = us_IDLE;
00859     
00860     // clear fifo
00861     clear_bit(uir, TRNIF);
00862     clear_bit(uir, TRNIF);
00863     clear_bit(uir, TRNIF);
00864     clear_bit(uir, TRNIF);
00865     
00866     // init buffers
00867 
00868     
00869     // EP0 OUT
00870     bd0out_e.count = USB_EP0_OUT_E_SIZE;    // 8 byte buffer
00871     bd0out_e.addr = USB_EP0_OUT_E_ADDR;
00872     
00873     clear_bit(bd0out_e.stat, DTS);  // turn on data togle sync TOGGLE
00874     clear_bit(bd0out_e.stat, KEN);  // clear the keep bit
00875     clear_bit(bd0out_e.stat, INCDIS);   // clear the increment disable
00876     clear_bit  (bd0out_e.stat, DTSEN);  // !!!!!!
00877     clear_bit(bd0out_e.stat, BSTALL);   // clear stall bit
00878     clear_bit(bd0out_e.stat, BC9);
00879     clear_bit(bd0out_e.stat, BC8);
00880 
00881     set_bit  (bd0out_e.stat, UOWN); // SIE owns the buffer
00882                                 // since we expect frist transaction to be SETUP
00883     // EP0 OUT
00884     bd0out_o.count = USB_EP0_OUT_O_SIZE;    // 8 byte buffer
00885     bd0out_o.addr = USB_EP0_OUT_O_ADDR;
00886     
00887     clear_bit(bd0out_o.stat, DTS);  // turn on data togle sync TOGGLE
00888     clear_bit(bd0out_o.stat, KEN);  // clear the keep bit
00889     clear_bit(bd0out_o.stat, INCDIS);   // clear the increment disable
00890     clear_bit  (bd0out_o.stat, DTSEN);  // !!!!!!
00891     clear_bit(bd0out_o.stat, BSTALL);   // clear stall bit
00892     clear_bit(bd0out_o.stat, BC9);
00893     clear_bit(bd0out_o.stat, BC8);
00894 
00895     set_bit  (bd0out_o.stat, UOWN); // SIE owns the buffer
00896                                 // since we expect frist transaction to be SETUP
00897                                 
00898     
00899     
00900     // EP0 IN
00901     bd0in.count = USB_EP0_IN_SIZE;  // 8 byte buffer
00902     bd0in.addr = USB_EP0_IN_ADDR;
00903     clear_bit(bd0in.stat, DTS); // turn on data togle sync TOGGLE
00904     clear_bit(bd0in.stat, KEN); // clear the keep bit
00905     clear_bit(bd0in.stat, INCDIS);  // clear the increment disable
00906     clear_bit(bd0in.stat, BSTALL);  // clear stall bit
00907     clear_bit(bd0in.stat, BC9);
00908     clear_bit(bd0in.stat, BC8);
00909     
00910     clear_bit(bd0in.stat, UOWN);    // uC owns the buffer
00911 
00912     #ifdef USB_DEBUG
00913         serial_print_str("\nR ");
00914         serial_print_int_hex(uir);
00915     #endif
00916 }

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_handle_stall (  ) 

00918                         {
00919     #ifdef USB_DEBUG
00920         serial_print_str(" U:Stall ");
00921     #endif
00922     clear_bit(bd0in.stat, UOWN);
00923     clear_bit(bd0in.stat, BSTALL);
00924 }

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_handle_standard_request ( setup_data_packet  sdp  ) 

00428                                                         {
00429 
00430     switch (sdp.bRequest) {
00431         case req_Get_Descriptor:
00432             #ifdef USB_DEBUG
00433                 serial_print_str(" GD: ");
00434             #endif
00435             uns8 descriptor_type = sdp.wValue >> 8; // high byte is descriptor
00436             uns8 descriptor_num  = sdp.wValue & 0xff; // low byte is particular descriptor
00437             #ifdef USB_DEBUG
00438                 serial_print_int(descriptor_type);
00439             #endif
00440             usb_get_descriptor_callback(descriptor_type, descriptor_num, &delivery_ptr, &delivery_bytes_to_send);
00441             if (delivery_ptr != 0) {    // we've got something
00442                 control_mode = cm_CTRL_READ_DATA_STAGE;
00443                 delivery_bytes_max_send = sdp.wLength;  // maximum host wants
00444                 delivery_bytes_sent = 0;    // clear our sent countr
00445                 delivery_buffer_size = USB_EP0_IN_SIZE;
00446                 delivery_bd = &bd0in;
00447                 delivery_buffer = (uns8 *)USB_EP0_IN_ADDR;
00448                 clear_bit(bd0in.stat, DTS); // ready to get toggled
00449                 usb_send_data_chunk();
00450             } else {
00451                 #ifdef USB_DEBUG
00452                     serial_print_str(" <stall> ");
00453                 #endif
00454                 usb_stall_ep0();
00455             }
00456         
00457             break;
00458         case req_Set_Address:
00459             usb_address = sdp.wValue & 0xff;
00460             #ifdef USB_DEBUG
00461                 serial_print_str(" SA:");
00462                 serial_print_int_hex(usb_address);
00463             #endif              
00464             usb_status = us_SET_ADDRESS;
00465             
00466             // Send a status ack - when we confirm that, THEN change address
00467             usb_send_status_ack();
00468             control_mode = cm_CTRL_WRITE_SENDING_STATUS;
00469             break;
00470         case req_Set_Configuration:
00471             #ifdef USB_DEBUG
00472                 serial_print_str(" SC: ");
00473             #endif          
00474 
00475             //sdp.wValue & 0xff; // MORE WORK see p136
00476             usb_configure_endpoints();
00477             // and do a call back to let the app know we're ready
00478             #ifdef USB_CALLBACK_ON_DEVICE_CONFIGURED
00479                 usb_device_configured_callback();
00480             #endif  
00481 
00482             //set_bit(ucon, PPBRST);    // reset ping pong buffers to even
00483             //clear_bit(ucon, PPBRST);
00484 
00485             usb_send_status_ack();
00486             control_mode = cm_CTRL_WRITE_SENDING_STATUS;
00487             
00488             usb_state = st_CONFIGURED;
00489             
00490             // reset ping pong buffers
00491             
00492             
00493             // device is up - so now get the endpoints happy
00494             break;
00495         case req_Get_Interface:
00496                 #ifdef USB_DEBUG
00497                     serial_print_str(" GI ");
00498                 #endif  
00499                 control_mode = cm_CTRL_READ_DATA_STAGE;
00500                 usb_send_one_byte(1);
00501         case req_Get_Status:
00502                 // this is wrong - needs to send two bytes !!
00503                 #ifdef USB_DEBUG                
00504                     serial_print_str(" GS ");
00505                 #endif
00506 
00507                 #ifdef USB_SELF_POWERED
00508                     usb_send_one_byte(1);
00509                 #else
00510                     usb_send_one_byte(0);   // bus powered
00511                 #endif
00512                 break;  
00513         default:
00514             #ifdef USB_DEBUG
00515                 serial_print_str(" ??SR ");     
00516                 serial_print_int(sdp.bRequest);
00517             #endif
00518             break;
00519             
00520     }   
00521 }   

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_handle_transaction ( uns8  stat  ) 

!usb_stall_on_in();

00524                                        {
00525 
00526 uns8 end_point, pid;
00527 bit even;
00528 uns8 count;
00529 
00530     even = !test_bit(stat, PPBI);
00531     end_point = stat >> 3;
00532     
00533     if (test_bit(stat, DIR)) {  // IN
00534         #ifdef USB_DEBUG            
00535             serial_print_str("\nDI[");
00536                 for (count=0; count < 8; count++) {
00537                     serial_print_int_hex(buffer_0_in[count]);
00538                     serial_putc(']');
00539                 }
00540         #endif          
00541         pid = (bd0in.stat >> 2) & 0x0f; // mask out pid
00542 
00543     } else {    // OUT
00544         if (even) {
00545             pid = (bd0out_e.stat >> 2) & 0x0f;  // mask out pid
00546         } else {
00547             pid = (bd0out_o.stat >> 2) & 0x0f;  // mask out pid
00548         }   
00549         #ifdef USB_DEBUG
00550             serial_print_str("\nDO ");
00551             if (even) {
00552                 for (count=0; count < 8; count++) {
00553                     serial_print_int_hex(buffer_0_out_e[count]);
00554                     serial_putc(' ');
00555                 }
00556             } else {
00557                 for (count=0; count < 8; count++) {
00558                     serial_print_int_hex(buffer_0_out_o[count]);
00559                     serial_putc(' ');
00560                 }
00561             }
00562             
00563         #endif
00564 
00565     }
00566     #ifdef USB_DEBUG
00567         if (end_point != 0) {
00568             serial_putc('E');
00569             serial_print_int_hex(end_point);
00570             serial_print_spc();
00571         }
00572     #endif      
00573 
00574             
00575     
00576     if (end_point == 0) {
00577         if (!(test_bit(stat, DIR))) {
00578             #ifdef USB_DEBUG_HIGH
00579             if (even) {
00580                 serial_print_str(" (e) ");
00581             } else {
00582                 serial_print_str(" (o) ");
00583             }
00584             #endif
00585         }       
00586         #ifdef USB  _DEBUG_HIGH
00587             serial_print_str(" bytes: ");
00588             if (test_bit(stat, DIR)) {
00589                 serial_print_int(bd0in.count);
00590             } else {
00591                 if (even) {
00592                     serial_print_int(bd0out_e.count);
00593                 } else {
00594                     serial_print_int(bd0out_o.count);
00595                 }   
00596             }   
00597         #endif
00598         if (pid == pid_SETUP) {
00599 
00600             #ifdef USB_DEBUG
00601                 serial_print_str(" Setup ");            
00602             #endif
00603             if (even) {
00604             //  for (count=0; count < 8; count++) {
00605             //      serial_print_int_hex(buffer_0_out_e[count]);
00606             //      serial_putc(' ');
00607             //  }
00608                 memcpy(/*dst*/ (void*)&usb_sdp, /*src*/ (void *)&buffer_0_out_e, 8);
00609                 usb_prime_ep0_out_e();
00610             } else {
00611             //  for (count=0; count < 8; count++) {
00612             //      serial_print_int_hex(buffer_0_out_o[count]);
00613             //      serial_putc(' ');
00614             //  }
00615                 memcpy(/*dst*/ (void*)&usb_sdp, /*src*/ (void *)&buffer_0_out_o, 8);
00616                 usb_prime_ep0_out_o();
00617             }
00618             
00619             // We may have issued a stall on previous transfer, so need to grab the buffer back for 
00620             // our use. Presumably this happens so you can stall continuously. However, we really want
00621             // it back.
00622             
00623             clear_bit  (bd0in.stat, UOWN);  // SIE owns the buffer
00624         
00625             #ifdef USB_DEBUG
00626 
00627             serial_print_str("RT= ");
00628             serial_print_int_hex(usb_sdp.bmRequestType);
00629             serial_print_str(" rq=");
00630             serial_print_int_hex(usb_sdp.bRequest);
00631             serial_print_str(" Va=");
00632             serial_print_int_hex_16bit(usb_sdp.wValue);
00633             serial_print_str(" In=");
00634             serial_print_int_hex_16bit(usb_sdp.wIndex);
00635             serial_print_str(" Ln=");
00636             serial_print_int_hex_16bit(usb_sdp.wLength);
00637 
00638 
00639 
00640                 serial_putc(' ');
00641                 if (test_bit(usb_sdp.bmRequestType, DATA_STAGE_DIR)) {
00642                     serial_print_str(" Data=IN");
00643                 } else {
00644                     serial_print_str(" Data=OUT/NO");
00645                 }
00646             #endif
00647             //serial_print_str(" len: ");
00648             //serial_print_int(usb_sdp.wLength);    
00649             // Is it a standard request?
00650             //serial_putc('\\');
00651             
00652             if (!test_bit(usb_sdp.bmRequestType, REQUEST_TYPE1) && // std request
00653                 !test_bit(usb_sdp.bmRequestType, REQUEST_TYPE0)) {
00654                 //serial_print_str(" Std req ");
00655                 if ((usb_sdp.bmRequestType & 0b00011111) == 0) {
00656                     //serial_print_str(" 2dev ");
00657                 } else if ((usb_sdp.bmRequestType & 0b00011111) == 1) { 
00658                     //serial_print_str(" 2int ");
00659                 } else if ((usb_sdp.bmRequestType & 0b00011111) == 0b00011) {   
00660                     //serial_print_str(" 2oth ");
00661                 }
00662                 #ifdef USB_DEBUG
00663                     serial_print_str(" std ");
00664                 #endif  
00665                 usb_handle_standard_request(usb_sdp);   
00666             } else if (!test_bit(usb_sdp.bmRequestType, REQUEST_TYPE1) && // class request
00667                     test_bit(usb_sdp.bmRequestType, REQUEST_TYPE0)) {
00668                     #ifdef USB_DEBUG
00669                         serial_print_str(" class ");
00670                     #endif
00671                 #ifdef USB_CALLBACK_ON_CLASS_CTRL
00672                     usb_handle_class_request_callback(usb_sdp);
00673                 #endif  
00674             } else {
00675                 //serial_print_str(" req no ");
00676                 //serial_print_int(usb_sdp.bRequest);
00677                 // serial_print_spc();
00678                 #ifdef USB_DEBUG
00679                     serial_print_str(" ??req t=");
00680                     serial_print_int(usb_sdp.bmRequestType);
00681                     serial_putc(' ');
00682                 #endif  
00683             }
00684             clear_bit(ucon, PKTDIS);    
00685 
00686         } else if (pid == pid_IN) {
00687             #ifdef USB_DEBUG
00688                 serial_print_str(" IN ");
00689             #endif
00690             if (control_mode == cm_CTRL_READ_DATA_STAGE) {
00691                 // it's ours, so send next chunk
00692                 usb_send_data_chunk();
00693             } else if (control_mode == cm_CTRL_WRITE_SENDING_STATUS) {
00694                 //serial_print_str("std ");
00695                 control_mode = cm_IDLE;
00696                 if (usb_status == us_SET_ADDRESS) {
00697                     #ifdef USB_DEBUG
00698                         serial_print_str(" addr to ");
00699                         serial_print_int(uaddr);
00700                     #endif
00701                     usb_state = st_ADDRESS;
00702                     uaddr = usb_address;
00703                     usb_status = us_IDLE;
00704                 }
00705                 #ifdef USB_DEBUG
00706                     serial_print_str(" ----\n");
00707                 #endif  
00708             } else if (control_mode == cm_CTRL_READ_AWAITING_STATUS) {
00709                 // Must have been last IN of the read, so still waiting for status
00710                 #ifdef USB_DEBUG
00711                     serial_print_str(" last read, waiting status");
00712                 #endif
00714                 //usb_prime_ep0_out();  // !! NEW
00715                 //???
00716                 nop(); // boostc bug
00717             } else if (control_mode == cm_CTRL_READ_DATA_STAGE_CLASS) {
00718                 #ifdef USB_DEBUG
00719                     serial_print_str(" ctrl read data stage class - more to come? ");
00720                 #endif  
00721                 // Must be more to come
00722                 #ifdef USB_CALLBACK_ON_CLASS_CTRL
00723                     usb_handle_class_ctrl_read_callback();
00724                 #else
00725                     nop(); // otherwise boostc bug
00726                 #endif  
00727             } else {
00728                 #ifdef USB_DEBUG
00729                     serial_print_str(" ?? cm=");
00730                     serial_print_int((uns8)control_mode);
00731                     serial_print_spc();
00732                 #else
00733                     nop(); // boostc bug
00734                 #endif  
00735                     
00736             }
00737         } else if (pid == pid_ACK) {
00738             #ifdef USB_DEBUG
00739                 serial_print_str("****A\n");
00740             #endif
00741             if (control_mode == cm_CTRL_READ_DATA_STAGE) {  
00742                 #ifdef USB_DEBUG
00743                     serial_print_str(" &2 ");
00744                 #endif
00745                 usb_send_data_chunk();
00746             } else if (control_mode == cm_CTRL_READ_DATA_STAGE_CLASS) {
00747                 #ifdef USB_CALLBACK_ON_CLASS_CTRL
00748                     usb_handle_class_ctrl_read_callback();
00749                 #else
00750                     nop(); // boostc bug
00751                 #endif  
00752             } else if (control_mode == cm_CTRL_WRITE_SENDING_STATUS) {
00753                 #ifdef USB_DEBUG
00754                     serial_print_str(" st sent ");
00755                 #endif
00756                 control_mode = cm_IDLE;
00757             } else if (control_mode == cm_CTRL_READ_AWAITING_STATUS) {
00758                 #ifdef USB_DEBUG
00759                     serial_print_str(" now what? ");
00760                 #endif
00761                 control_mode = cm_IDLE;
00762             }
00763                 
00764     
00765         } else if (pid == pid_OUT) {
00766             uns8 count;
00767             uns8 *buffer;
00768             
00769             if (even) {
00770                 count = bd0out_e.count;
00771                 buffer = &buffer_0_out_e;
00772                 usb_prime_ep0_out_e();
00773             } else {
00774                 count = bd0out_o.count;
00775                 buffer = &buffer_0_out_o;
00776                 usb_prime_ep0_out_o();
00777             }
00778             
00779             // We've done an out
00780             //serial_print_str(" OUT ");
00781             if (control_mode == cm_CTRL_READ_AWAITING_STATUS) {
00782                 #ifdef USB_DEBUG
00783                     serial_print_str(" ----\n");
00784                 #endif
00785                 control_mode = cm_IDLE;
00786             } else if (control_mode == cm_CTRL_WRITE_DATA_STAGE_CLASS) {
00787                 #ifdef USB_CALLBACK_ON_CLASS_CTRL
00788                     usb_handle_class_ctrl_write_callback(buffer, count);
00789                     // !! should include bc bits here for total count
00790                     // this only works for 8 bit data packets
00791                 #else
00792                     nop(); // boostc bug
00793                 #endif  
00794             } else if (control_mode == cm_CTRL_READ_DATA_STAGE) {
00795                 //serial_print_str(" Status early ");
00796                 control_mode = cm_IDLE;
00797             } else {
00798             
00799                 #ifdef USB_DEBUG
00800                     serial_print_str("??unk pid_OUT ");
00801                     serial_print_int((uns8)control_mode);
00802                 #endif  
00803             }
00804                 
00805         } else {
00806             #ifdef USB_DEBUG
00807                 serial_print_str(" UKPID = ");
00808                 serial_print_int(pid);
00809             #endif  
00810         }
00811 
00812     } else {    // Not endpoint 0
00813         buffer_descriptor *bd;
00814         if (test_bit(stat, DIR)) {
00815             // in
00816             #ifdef USB_EP_DATA_CALLBACK
00817                 bd = ep_in_bd_location[end_point];
00818                 usb_ep_data_in_callback(end_point, bd->count);
00819             #else
00820                 nop();
00821             #endif  
00822         } else { // out
00823 
00824             bd = ep_out_bd_location[end_point];
00825             // issue callback
00826             #ifdef USB_EP_DATA_CALLBACK
00827                 usb_ep_data_out_callback(end_point, ep_out_buffer_location[end_point],
00828                                     bd->count);
00829             #endif                      
00830             // re-prime endpoint
00831             bd->count = ep_out_buffer_size[end_point];
00832             bd->addr  = (uns16)ep_out_buffer_location[end_point];
00833         
00834             // Address shouldn't change, so don't need to update it
00835 
00836             clear_bit(bd->stat, DTS);   // turn on data togle sync TOGGLE
00837             clear_bit(bd->stat, KEN);   // clear the keep bit
00838             clear_bit(bd->stat, INCDIS);    // clear the increment disable
00839             clear_bit(bd->stat, DTSEN);
00840             clear_bit(bd->stat, BSTALL);    // clear stall bit
00841             clear_bit(bd->stat, BC9);
00842             clear_bit(bd->stat, BC8);
00843             set_bit  (bd->stat, UOWN);  // SIE owns the buffer
00844                         
00845                 
00846         }   
00847     }
00848     
00849     
00850         
00851 }

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_prime_ep0_out_e (  ) 

! clear

00384                            {
00385 
00386     bd0out_e.count = USB_EP0_OUT_E_SIZE;
00387     bd0out_e.addr = USB_EP0_OUT_E_ADDR;
00388     //changed from clear to set 
00389     clear_bit(bd0out_e.stat, DTS);  // turn on data togle sync TOGGLE
00390     clear_bit(bd0out_e.stat, KEN);  // clear the keep bit
00391     clear_bit(bd0out_e.stat, INCDIS);   // clear the increment disable
00393     clear_bit(bd0out_e.stat, DTSEN); 
00394     clear_bit(bd0out_e.stat, BSTALL);   // clear stall bit
00395     clear_bit(bd0out_e.stat, BC9);  
00396     clear_bit(bd0out_e.stat, BC8);
00397 
00398     set_bit  (bd0out_e.stat, UOWN); // SIE owns the buffer
00399 
00400     #ifdef USB_DEBUG
00401         serial_putc('P');
00402         serial_putc('E');
00403     #endif  
00404 }                         

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_prime_ep0_out_o (  ) 

! clear

00406                            {
00407 
00408     bd0out_o.count = USB_EP0_OUT_O_SIZE;
00409     bd0out_o.addr = USB_EP0_OUT_O_ADDR;
00410     //changed from clear to set 
00411     clear_bit(bd0out_o.stat, DTS);  // turn on data togle sync TOGGLE
00412     clear_bit(bd0out_o.stat, KEN);  // clear the keep bit
00413     clear_bit(bd0out_o.stat, INCDIS);   // clear the increment disable
00415     clear_bit(bd0out_o.stat, DTSEN); 
00416     clear_bit(bd0out_o.stat, BSTALL);   // clear stall bit
00417     clear_bit(bd0out_o.stat, BC9);  
00418     clear_bit(bd0out_o.stat, BC8);
00419 
00420     set_bit  (bd0out_o.stat, UOWN); // SIE owns the buffer
00421 
00422     #ifdef USB_DEBUG
00423         serial_putc('P');
00424         serial_putc('O');
00425     #endif  
00426 }                         

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_send_data ( uns8  ep,
uns8 *  data,
uns8  send_count,
bit  first 
)

Use this routine to send data across the USB pipe.

Parameters:
ep Endpoint that the data should be sent from
data pointer to the data
send_count the number of bytes to send
first True if this is the first in a series of sends. Generally, this can be set to False, since it will automatically be set to the right value on endpoint creation. However, in the case of control transfers, the data stage needs to have the first parameter set to True to ensure the DTS bit is set correctly.

00211                                                                     {
00212 uns8 count;
00213 buffer_descriptor *bd;
00214 uns8 *buffer;
00215 
00216     // this is going to be an IN transaction
00217     #ifdef USB_DEBUG
00218         serial_print_str("Send:EP");
00219         serial_print_int(ep);
00220         serial_putc(' ');
00221     #endif
00222     // need to grab buffer descriptor
00223     buffer = ep_in_buffer_location[ep];
00224     
00225     bd = ep_in_bd_location[ep];
00226     
00227     if (test_bit(bd->stat, UOWN)) {
00228     #ifdef USB_DEBUG
00229         serial_print_str(" !Adon't own it! ");
00230     #endif
00231         return;
00232     }
00233     
00234     count = 0;  
00235     while ((count < send_count)) {
00236         buffer[count] = data[count];
00237         count++;
00238     }           
00239     
00240 
00241     bd->count = count;
00242     bd->addr = (uns16)buffer;
00243     if (first) {
00244         clear_bit(bd->stat, DTS);   // So when it flips, will end up set 
00245     }
00246 
00247     toggle_bit(bd->stat, DTS);  // flip the DTS bit
00248     clear_bit(bd->stat, KEN);   // clear the keep bit
00249     clear_bit(bd->stat, INCDIS);    // clear the increment disable
00250     set_bit  (bd->stat, DTSEN);
00251     clear_bit(bd->stat, BSTALL);    // clear stall bit
00252     clear_bit(bd->stat, BC9);
00253     clear_bit(bd->stat, BC8);
00254 
00255     set_bit  (bd->stat, UOWN);  // SIE owns the buffer
00256 }   

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_send_data_chunk (  ) 

00260                            {
00261     
00262 uns8 count;
00263 uns8 now = 0;
00264 
00265     if (test_bit(bd0in.stat, UOWN)) {
00266     #ifdef USB_DEBUG
00267         serial_print_str(" !Bdon't own it! ");
00268     #endif
00269         return;
00270     }
00271 
00272     count = 0;
00273     while ((count < delivery_buffer_size) &&
00274            (delivery_bytes_sent < delivery_bytes_to_send) && 
00275            (delivery_bytes_sent < delivery_bytes_max_send)) {
00276         delivery_buffer[count] = *delivery_ptr;
00277         delivery_ptr++;
00278         delivery_bytes_sent++;
00279         count++;
00280         now++;
00281     }           
00282     #ifdef USB_DEBUG
00283         serial_print_str(" wrote ");
00284         serial_print_int(now);
00285     #endif
00286     if ((count < delivery_buffer_size) && 
00287         ((delivery_bytes_sent == delivery_bytes_max_send) ||
00288         (delivery_bytes_sent == delivery_bytes_to_send)))  {
00289         #ifdef USB_DEBUG_x
00290         serial_print_str(" c=");
00291         serial_print_int(count);
00292         serial_print_str(" dbsz=");
00293         serial_print_int(delivery_buffer_size);
00294        
00295         serial_print_str(" dbs=");
00296         serial_print_int(delivery_bytes_sent);
00297         serial_print_str(" dbms=");
00298         serial_print_int(delivery_bytes_max_send);
00299         serial_print_str(" dbts=");
00300         serial_print_int(delivery_bytes_to_send);
00301         #endif
00302         if (control_mode != cm_CTRL_WRITE_SENDING_STATUS) {
00303             control_mode = cm_CTRL_READ_AWAITING_STATUS;    // we're done with data stage
00304             #ifdef USB_DEBUG_HIGH
00305                 serial_print_str(" st2READWAITSTAT ");
00306             #endif  
00307         }
00308     }   
00309 
00310     
00311     bd0in.count = count;
00312     bd0in.addr = (uns16)&buffer_0_in;
00313     //serial_print_str("Buffer=");
00314     //serial_print_int_hex_16bit(bd0in.addr);
00315     toggle_bit(bd0in.stat, DTS);
00316     //these not required for 14k50, but random things seem to happen if you don't clear them
00317     clear_bit(bd0in.stat, KEN);     // clear the keep bit
00318     clear_bit(bd0in.stat, INCDIS);  // clear the increment disable
00319     set_bit  (bd0in.stat, DTSEN);
00320     clear_bit(bd0in.stat, BSTALL);  // clear stall bit
00321     clear_bit(bd0in.stat, BC9);
00322     clear_bit(bd0in.stat, BC8);
00323 
00324     set_bit  (bd0in.stat, UOWN);    // SIE owns the buffer
00325     /*
00326     delivery_bd->count = count;
00327     delivery_bd->addr = (uns16)delivery_buffer;
00328     toggle_bit(delivery_bd->stat, DTS);
00329     clear_bit(delivery_bd->stat, KEN);  // clear the keep bit
00330     clear_bit(delivery_bd->stat, INCDIS);   // clear the increment disable
00331     set_bit  (delivery_bd->stat, DTSEN);
00332     clear_bit(delivery_bd->stat, BSTALL);   // clear stall bit
00333     clear_bit(delivery_bd->stat, BC9);
00334     clear_bit(delivery_bd->stat, BC8);
00335 
00336     set_bit  (delivery_bd->stat, UOWN); // SIE owns the buffer
00337     */
00338 }

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_send_empty_data_pkt (  ) 

Use this routine to send an data across the USB pipe on endpoint 0. This is the equivalent of sending a status acknowledge.

00341                                {
00342     delivery_buffer_size = USB_EP0_IN_SIZE;
00343     delivery_bd = &bd0in;
00344     delivery_buffer = &buffer_0_in;
00345     delivery_bytes_sent = 0;
00346     delivery_bytes_to_send = 0;
00347     delivery_bytes_max_send = 0;
00348     delivery_ptr = (uns8 *) 0;
00349     clear_bit(bd0in.stat, DTS); // ready to get toggled 
00350     usb_send_data_chunk();
00351 }

Here is the call graph for this function:

void usb_send_one_byte ( uns8  data  ) 

00370                                   {
00371     delivery_buffer_size = USB_EP0_IN_SIZE;
00372     delivery_bytes_sent = 0;
00373     delivery_bytes_to_send = 1;
00374     delivery_bytes_max_send = 0;
00375     buffer_byte = data;
00376     delivery_ptr = (uns8 *) &buffer_byte;
00377     delivery_bd = &bd0in;
00378     delivery_buffer = &buffer_0_in;
00379     
00380     clear_bit(bd0in.stat, DTS); // ready to get toggled
00381     usb_send_data_chunk();
00382 }

Here is the call graph for this function:

Here is the caller graph for this function:

void usb_setup (  ) 

usb_setup() configures the PIC USB hardware ready for use and prepares the internal data structures used to keep track of where the endpoint buffers are.

After calling usb_setup(), you are ready to call usb_enable_module() to actually start USB negotiations. Ensure that you have usb_handle_isr() in your interrupt service routine.

00973                  {
00974 
00975     usb_state = st_POWERED;
00976     
00977     // init hardware
00978     #ifdef UTRDIS
00979         clear_bit(ucfg, UTRDIS);    // enable internal tranceiver
00980     #endif
00981     set_bit  (ucfg, FSEN);  // clear for low speed, set for high speed
00982     set_bit  (ucfg, UPUEN); // enable on-chip pull-ups
00983 
00984     clear_bit(ucfg, PPB1);  // double buffering for EP0 OUT
00985     set_bit(ucfg, PPB0);    
00986 
00987     // if using ping pong buffers, need to do this:
00988     set_bit(ucon, PPBRST);  // reset ping pong buffers to even
00989     clear_bit(ucon, PPBRST);
00990 
00991     // init endpoint 0
00992         
00993     set_bit(uep0,   EPHSHK);    // EP0 handshaking on
00994     set_bit(uep0,   EPOUTEN);   // EP0 OUT enable 
00995     set_bit(uep0,   EPINEN);    // EP0 IN enable 
00996     clear_bit(uep0, EPCONDIS);  // EP0 control transfers on (and IN and OUT)
00997     
00998     // init interrupts
00999     // Config buffer descriptor table
01000 
01001     ep_out_bd_location[0] = &bd0out_e;
01002     #if USB_HIGHEST_EP >= 1
01003         ep_out_bd_location[1] = &bd1out;
01004     #endif
01005     #if USB_HIGHEST_EP >= 2
01006         ep_out_bd_location[2] = &bd2out;
01007     #endif
01008     #if USB_HIGHEST_EP >= 3
01009         ep_out_bd_location[3] = &bd3out;
01010     #endif
01011     #if USB_HIGHEST_EP >= 4
01012         ep_out_bd_location[4] = &bd4out;
01013     #endif
01014     
01015     ep_in_bd_location[0] = &bd0in;
01016     #if USB_HIGHEST_EP >= 1
01017         ep_in_bd_location[1] = &bd1in;
01018     #endif
01019     #if USB_HIGHEST_EP >= 2
01020         ep_in_bd_location[2] = &bd2in;
01021     #endif
01022     #if USB_HIGHEST_EP >= 3
01023         ep_in_bd_location[3] = &bd3in;
01024     #endif
01025     #if USB_HIGHEST_EP >= 4
01026         ep_in_bd_location[4] = &bd4in;
01027     #endif
01028 
01029 
01030 }

void usb_stall_ep0 (  ) 

Use this routine to send a stall on the control transfer endpoint - usually used to indicate that the requested function is not available.

00203                      {
00204     set_bit(bd0in.stat, BSTALL);    // stall
00205     set_bit(bd0in.stat, UOWN);  // SIE owns the buffer
00206 //  set_bit(bd0out.stat, BSTALL);   // stall
00207 //  set_bit(bd0out.stat, UOWN); // SIE owns the buffer
00208     // ??set_bit(uep0,EPSTALL);
00209 }

Here is the caller graph for this function:

void usb_stall_on_in (  ) 

00353                        {
00354 
00355     clear_bit(bd0in.stat, DTS); // ready to get toggled 
00356 
00357     clear_bit(bd0in.stat, KEN); // clear the keep bit
00358     clear_bit(bd0in.stat, INCDIS);  // clear the increment disable
00359     clear_bit(bd0in.stat, DTSEN);
00360     set_bit(bd0in.stat, BSTALL);    // clear stall bit
00361     clear_bit(bd0in.stat, BC9);
00362     clear_bit(bd0in.stat, BC8);
00363 
00364     set_bit  (bd0in.stat, UOWN);    // SIE owns the buffer
00365 }


Variable Documentation

Store the control mode state

uns8* delivery_ptr

Store the usb address

Store the last setup data packet

usb_state_type usb_state = st_POWERED

Store the current USB device state


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