⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb in a nutshell - chapter 7 - pdiusbd11 and pic16f87x example.htm

📁 altra下载线资料。max7000系列
💻 HTM
📖 第 1 页 / 共 4 页
字号:
          packet and issue an ACK before we can change the address. Otherwise 
          the device may never see the IN token being sent on the default 
          address. </P>
          <P>The completion of the status stage is signalled by an interrupt on 
          EP0 IN. In order to differentiate between a set address response and a 
          normal EP0_IN interrupt we set a variable, CtlTransferInProgress to 
          PROGRESS_ADDRESS. In the EP0 IN handler a check is made of 
          CtlTransferInProgress. If it equals PROGRESS_ADDRESS then the Set 
          Address Enable command is issued to the PDIUSBD11 and 
          CtlTransferInProgress is set to PROGRESS_IDLE. The host gives 2ms for 
          the device to change its address before the next command is sent. </P><PRE>                    case GET_DESCRIPTOR:
                        GetDescriptor(&amp;SetupPacket);
                        break;
  
                    case GET_CONFIGURATION:
                        D11WriteEndpoint(D11_ENDPOINT_EP0_IN, &amp;DeviceConfigured, 1);
                        break;

                    case SET_CONFIGURATION:
                        printf("Set Configuration\n\r");
                        DeviceConfigured = SetupPacket.wValue &amp; 0xFF;
                        D11WriteEndpoint(D11_ENDPOINT_EP0_IN, NULL, 0);
                        if (DeviceConfigured) {
                            RB3 = 0;
                            printf("\n\r *** Device Configured *** \n\r");
                            }
                        else {
                            RB3 = 1; /* Device Not Configured */
                            printf("\n\r ** Device Not Configured *** \n\r");
                            }
                        break;

                    //case SET_DESCRIPTOR:
                    default:
                        /* Unsupported - Request Error - Stall */
                        ErrorStallControlEndPoint();
                        break;

                }
                break;
</PRE>
          <P>The Get Configuration and Set Configuration is used to "enable" the 
          USB device allowing data to be transferred on endpoints other than 
          endpoint zero. Set Configuration should be issued with wValue equal to 
          that of a bConfigurationValue of the configuration you want to enable. 
          In our case we only have one configuration, configuration 1. A zero 
          configuration value means the device is not configured while a 
          non-zero configuration value indicates the device is configured. The 
          code does not fully type check the configuration value, it only copies 
          it into a local storage variable, DeviceConfigured. If the value in 
          wValue does not match the bConfigurationValue of a Configuration, it 
          should return with a USB Request Error. </P><PRE>            case STANDARD_INTERFACE_REQUEST:
                printf("Standard Interface Request\n\r");
                switch (SetupPacket.bRequest) {
                        
                    case GET_STATUS:
                        /* Get Status Request to Interface should return */
                        /* Zero, Zero (Reserved for future use) */
                        Buffer[0] = 0x00;
                        Buffer[1] = 0x00;
                        D11WriteEndpoint(D11_ENDPOINT_EP0_IN, Buffer, 2);
                        break;

                    case SET_INTERFACE:
                        /* Device Only supports default setting, Stall may be */
                        /* returned in the status stage of the request */
                        if (SetupPacket.wIndex == 0 &amp;&amp; SetupPacket.wValue == 0)  
                            /* Interface Zero, Alternative Setting = 0 */
                            D11WriteEndpoint(D11_ENDPOINT_EP0_IN, NULL, 0);     
                        else ErrorStallControlEndPoint();
                        break;

                    case GET_INTERFACE:
                        if (SetupPacket.wIndex == 0) { /* Interface Zero */
                            Buffer[0] = 0; /* Alternative Setting */
                            D11WriteEndpoint(D11_ENDPOINT_EP0_IN, Buffer, 1);
                            break;
                         } /* else fall through as RequestError */

                    //case CLEAR_FEATURE:
                    //case SET_FEATURE:
                        /* Interface has no defined features. Return RequestError */
                    default:
                        ErrorStallControlEndPoint();
                        break;

                }
                break;
</PRE>
          <P>Of the Standard Interface Requests, none perform any real function. 
          The Get Status request must return a word of zero and is reserved for 
          future use. The Set Interface and Get Interface requests are used with 
          alternative Interface Descriptors. We have not defined any alternative 
          Interface Descriptors so Get Interface returns zero and any request to 
          Set an interface other than to set interface zero with an alternative 
          setting of zero is processed with a Request Error. </P><PRE>            case STANDARD_ENDPOINT_REQUEST:
                printf("Standard Endpoint Request\n\r");
                switch (SetupPacket.bRequest) {

                    case CLEAR_FEATURE:
                    case SET_FEATURE:
                        /* Halt(Stall) feature required to be implemented on all Interrupt and */
                        /* Bulk Endpoints. It is not required nor recommended on the Default Pipe */
                          
                        if (SetupPacket.wValue == ENDPOINT_HALT)
                        {
                            if (SetupPacket.bRequest == CLEAR_FEATURE) Buffer[0] = 0x00;
                            else                                       Buffer[0] = 0x01;
                            switch (SetupPacket.wIndex &amp; 0xFF) {
                                case 0x01 : D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + \
                                              D11_ENDPOINT_EP1_OUT, Buffer, 1);
                                            break;
                                case 0x81 : D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + \
                                              D11_ENDPOINT_EP1_IN, Buffer, 1);
                                            break;
                                case 0x02 : D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + \
                                              D11_ENDPOINT_EP2_OUT, Buffer, 1);
                                            break;
                                case 0x82 : D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + \
                                              D11_ENDPOINT_EP2_IN, Buffer, 1);
                                            break;
                                case 0x03 : D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + \
                                              D11_ENDPOINT_EP3_OUT, Buffer, 1);
                                            break;
                                case 0x83 : D11CmdDataWrite(D11_SET_ENDPOINT_STATUS + \
                                              D11_ENDPOINT_EP3_IN, Buffer, 1);
                                            break;
                                default   : /* Invalid Endpoint - RequestError */
                                            ErrorStallControlEndPoint();
                                            break;
                            }
                            D11WriteEndpoint(D11_ENDPOINT_EP0_IN, NULL, 0);
                        } else {
                            /* No other Features for Endpoint - Request Error */
                            ErrorStallControlEndPoint();
                        }
                        break;
</PRE>
          <P>The Set Feature and Clear Feature requests are used to set endpoint 
          specific features. The standard defines one endpoint feature selector, 
          ENDPOINT_HALT. We check what endpoint the request is directed to and 
          set/clear the STALL bit accordingly. This HALT feature is not required 
          on the default endpoints. </P><PRE>                    case GET_STATUS:
                        /* Get Status Request to Endpoint should return */
                        /* Halt Status in D0 for Interrupt and Bulk */
                        switch (SetupPacket.wIndex &amp; 0xFF) {
                            case 0x01 : D11CmdDataRead(D11_READ_ENDPOINT_STATUS + \
                                          D11_ENDPOINT_EP1_OUT, Buffer, 1);
                                        break;
                            case 0x81 : D11CmdDataRead(D11_READ_ENDPOINT_STATUS + \
                                          D11_ENDPOINT_EP1_IN, Buffer, 1);
                                        break;
                            case 0x02 : D11CmdDataRead(D11_READ_ENDPOINT_STATUS + \
                                          D11_ENDPOINT_EP2_OUT, Buffer, 1);
                                        break;
                            case 0x82 : D11CmdDataRead(D11_READ_ENDPOINT_STATUS + \
                                          D11_ENDPOINT_EP2_IN, Buffer, 1);
                                        break;
                            case 0x03 : D11CmdDataRead(D11_READ_ENDPOINT_STATUS + \
                                          D11_ENDPOINT_EP3_OUT, Buffer, 1);
                                        break;
                            case 0x83 : D11CmdDataRead(D11_READ_ENDPOINT_STATUS + \
                                          D11_ENDPOINT_EP3_IN, Buffer, 1);
                                        break;
                            default   : /* Invalid Endpoint - RequestError */
                                        ErrorStallControlEndPoint();
                                        break;
                        }
                        if (Buffer[0] &amp; 0x08) Buffer[0] = 0x01;
                        else                  Buffer[0] = 0x00;
                        Buffer[1] = 0x00;
                        D11WriteEndpoint(D11_ENDPOINT_EP0_IN, Buffer, 2);
                        break;
                    
                    default:
                        /* Unsupported - Request Error - Stall */
                        ErrorStallControlEndPoint();
                        break;
                }
                break;
</PRE>
          <P>The Get Status request when directed to the endpoint returns the 
          status of the endpoint, ie. if it is halted or not. Like the Set/Clear 
          feature request ENDPOINT_HALT, we only need to report the status of 
          the generic endpoints. </P>
          <P>Any undefined Standard Endpoint Requests are handled by USB Request 
          Error. </P><PRE>            case VENDOR_DEVICE_REQUEST:
            case VENDOR_ENDPOINT_REQUEST:
                printf("Vendor Device bRequest = 0x%X, wValue = 0x%X, wIndex = 0x%X\n\r", \
                    SetupPacket.bRequest, SetupPacket.wValue, SetupPacket.wIndex);
                switch (SetupPacket.bRequest) {

                    case VENDOR_GET_ANALOG_VALUE:
                        printf("Get Analog Value, Channel %x :",SetupPacket.wIndex &amp; 0x07);
                        ADCON0 = 0xC1 | (SetupPacket.wIndex &amp; 0x07) &lt;&lt; 3;            
                        /* Wait Acquistion time of Sample and Hold */
                        for (a = 0; a &lt;= 255; a++);
                        ADGO = 1;
                        while(ADGO);
                        Buffer[0] = ADRESL;
                        Buffer[1] = ADRESH;
                        a = (Buffer[1] &lt;&lt; 8) + Buffer[0];
                        a = (a * 500) / 1024;
                        printf(" Value = %d.%02d\n\r",(unsigned int)a/100,(unsigned int)a%100);
                        D11WriteEndpoint(D11_ENDPOINT_EP0_IN, Buffer, 2);
                        break;
</PRE>
          <P>Now comes the functional parts of the USB device. The Vendor 
          Requests can be dreamed up by the designer. We have dreamed up two 
          requests, VENDOR_GET_ANALOG_VALUE and VENDOR_SET_RB_HIGH_NIBBLE. 
          VENDOR_GET_ANALOG_VALUE reads the 10-bit Analog Value on Channel x 
          dictated by wIndex. This is ANDed with 0x07 to allow 8 possible 
          channels, supporting the larger PIC16F877 if required. The analog 
          value is returned in a two byte data packet. </P><PRE>                    case VENDOR_SET_RB_HIGH_NIBBLE:
                        printf("Write High Nibble of PORTB\n\r");
                        PORTB = (PORTB &amp; 0x0F) | (SetupPacket.wIndex &amp; 0xF0);
                        D11WriteEndpoint(D11_ENDPOINT_EP0_IN, NULL, 0);
                        break;

                    default:
                        ErrorStallControlEndPoint();
                        break;    
                }
                break;
</PRE>
          <P>The VENDOR_SET_RB_HIGH_NIBBLE can be used to set the high nibble 
          bits of PORTB[3:7]. </P><PRE>            default: 
                printf("UnSupported Request Type 0x%X\n\r",SetupPacket.bmRequestType);
                ErrorStallControlEndPoint();
                break;
        }
    } else {
    printf("Data Packet?\n\r");
    /* This is a Data Packet */
    }
}

</PRE>
          <P>Any unsupported request types such as class device request, class 
          interface request etc is dealt with by a USB Request Error. </P><PRE>void GetDescriptor(PUSB_SETUP_REQUEST SetupPacket)
{
    switch((SetupPacket-&gt;wValue &amp; 0xFF00) &gt;&gt; 8) {

        case TYPE_DEVICE_DESCRIPTOR:
            printf("\n\rDevice Descriptor: Bytes Asked For %d, Size of Descriptor %d\n\r", \
                    SetupPacket-&gt;wLength,DeviceDescriptor.bLength);
            pSendBuffer = (const unsigned char *)&amp;DeviceDescriptor;
            BytesToSend = DeviceDescriptor.bLength;
            if (BytesToSend &gt; SetupPacket-&gt;wLength)
                BytesToSend = SetupPacket-&gt;wLength;
            WriteBufferToEndPoint();
            break;

        case TYPE_CONFIGURATION_DESCRIPTOR:
            printf("\n\rConfiguration Descriptor: Bytes Asked For %d, Size of Descriptor %d\n\r", \
                    SetupPacket-&gt;wLength, sizeof(ConfigurationDescriptor));
            pSendBuffer = (const unsigned char *)&amp;ConfigurationDescriptor;
            BytesToSend = sizeof(ConfigurationDescriptor);
            if (BytesToSend &gt; SetupPacket-&gt;wLength)
                BytesToSend = SetupPacket-&gt;wLength;
            WriteBufferToEndPoint();
            break;
</PRE>
          <P>The Get Descriptor requests involve responses greater than the 8 
          byte maximum packet size limit of the endpoint. Therefore they must be 
          broken up into 8 byte chunks. Both the Device and Configuration 
          requests load the address of the relevant descriptors into pSendBuffer 
          and sets the BytesToSend to the length of the descriptor. The request 
          will also specify a descriptor length in wLength specifying the 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -