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_descriptor * | delivery_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 |
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.
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 }
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 }
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 }
void usb_handle_stall | ( | ) |
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 }
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 }
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 }
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 }
void usb_send_data | ( | uns8 | ep, | |
uns8 * | data, | |||
uns8 | send_count, | |||
bit | first | |||
) |
Use this routine to send data across the USB pipe.
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 }
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 }
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 }
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 }
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 }
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 }
uns8 buffer_byte |
Store the control mode state
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 |
Store the usb address
Store the last setup data packet
usb_state_type usb_state = st_POWERED |
Store the current USB device state