This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TM4C123GE6PM:USB 器件:是否添加描述符回调函数?

Guru**** 2387830 points
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1202573/tm4c123ge6pm-usb-device-add-descriptor-callback-function

器件型号:TM4C123GE6PM

您好!

我有一个适用于 TM4C123GXL launchpad 的 USB 批量传输示例的修改版本、该示例现已启动并正在运行。  我看到 MCU 成功使用了 Microsoft OS 字符串描述符、需要处理此请求以加载 WinUSB 驱动程序。  我想知道添加"描述符"处理程序来处理此自定义字符串描述符的最佳方法是什么。

我在如下所示的 usbdbulk.c 文件中看到一个潜在选项、始于第329行:

我问的是,因为所有其他的字符串描述符处理工作正常,不想破坏它们。  此外、我将该文件存储在本地项目中、因此我可以修改在 usbulbulk_structs.c 中无法修改的内容  理想情况下、我不会修改任何更低级的驱动程序代码、因为它已全部编译完毕(我认为是)。  我已经尝试在 usblib 驱动程序文件夹中修改了源代码、但没有进行任何更改-我假设这个代码是链接的、而不是每次在 CCS 中编译/编译时都编译。

任何关于定制(Microsoft OS 字符串描述符)字符串描述符处理程序的好位置的方向都会非常感谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Robert:

     如果您知道要更改什么以适合您的应用程序、您可以更改库源文件、但需要重新构建 usblib.lib、以便在链接到库时反映您的更改。 另一种可行的方法是将  usbdbulk.c 复制到当前项目文件夹。 对其进行更改、编译工程后应该会有更新的更改。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Charles:

    感谢您的答复!  我认为我的选择是正确的,你是正确的,我必须重新编译 usblib,因为我做了一些测试更改,但没有被采纳,因为我链接到它,而不是编译它。  关于那个主题-你知道重新编译这个库的步骤的大致顺序吗? 或者是否有某处 PDF 文件讨论过重新编译 TI 库?   

    在 USB 问题主题上-我想我已经弄清楚了(理论上)您必须做什么来处理这个问题、不幸的是、您(我认为)必须编辑 usbdenum.c 文件。  我认为这是因为您必须修改该文件中第1937行中的较低级别的枚举处理程序-见下文。

    //*****************************************************************************
    //
    // This function handles the GET_DESCRIPTOR standard USB request.
    //
    // \param pvInstance is the USB device controller instance data.
    // \param psUSBRequest holds the data for this request.
    //
    // This function will return most of the descriptors requested by the host
    // controller.  The descriptor specified by \e
    // pvInstance->psInfo->pui8DeviceDescriptor will be returned when the device
    // descriptor is requested.  If a request for a specific configuration
    // descriptor is made, then the appropriate descriptor from the \e
    // g_pConfigDescriptors will be returned.  When a request for a string
    // descriptor is made, the appropriate string from the
    // \e pvInstance->psInfo->pStringDescriptors will be returned.  If the
    // \e pvInstance->psInfo->psCallbacks->GetDescriptor is specified it will be
    // called to handle the request.  In this case it must call the
    // USBDCDSendDataEP0() function to send the data to the host controller.  If
    // the callback is not specified, and the descriptor request is not for a
    // device, configuration, or string descriptor then this function will stall
    // the request to indicate that the request was not supported by the device.
    //
    // \return None.
    //
    //*****************************************************************************
    static void
    USBDGetDescriptor(void *pvInstance, tUSBRequest *psUSBRequest)
    {
        bool bConfig;
        tDCDInstance *psUSBControl;
        tDeviceInfo *psDevice;
        const tConfigHeader *psConfig;
        const tDeviceDescriptor *psDeviceDesc;
        uint8_t ui8Index;
        int32_t i32Index;
    
        ASSERT(psUSBRequest != 0);
        ASSERT(pvInstance != 0);
    
        //
        // Create the device information pointer.
        //
        psUSBControl = (tDCDInstance *)pvInstance;
        psDevice = g_ppsDevInfo[0];
    
        //
        // Need to ACK the data on end point 0 without setting last data as there
        // will be a data phase.
        //
        MAP_USBDevEndpointDataAck(USB0_BASE, USB_EP_0, false);
    
        //
        // Assume we are not sending the configuration descriptor until we
        // determine otherwise.
        //
        bConfig = false;
    
        //
        // Which descriptor are we being asked for?
        //
        switch(psUSBRequest->wValue >> 8)
        {
            //
            // This request was for a device descriptor.
            //
            case USB_DTYPE_DEVICE:
            {
                //
                // Return the externally provided device descriptor.
                //
                psUSBControl->pui8EP0Data =
                                        (uint8_t *)psDevice->pui8DeviceDescriptor;
    
                //
                // The size of the device descriptor is in the first byte.
                //
                psUSBControl->ui32EP0DataRemain =
                    psDevice->pui8DeviceDescriptor[0];
    
                break;
            }
    
            //
            // This request was for a configuration descriptor.
            //
            case USB_DTYPE_CONFIGURATION:
            {
                //
                // Which configuration are we being asked for?
                //
                ui8Index = (uint8_t)(psUSBRequest->wValue & 0xFF);
    
                //
                // Is this valid?
                //
                psDeviceDesc =
                    (const tDeviceDescriptor *)psDevice->pui8DeviceDescriptor;
    
                if(ui8Index >= psDeviceDesc->bNumConfigurations)
                {
                    //
                    // This is an invalid configuration index.  Stall EP0 to
                    // indicate a request error.
                    //
                    USBDCDStallEP0(0);
                    psUSBControl->pui8EP0Data = 0;
                    psUSBControl->ui32EP0DataRemain = 0;
                }
                else
                {
                    //
                    // Return the externally specified configuration descriptor.
                    //
                    psConfig = psDevice->ppsConfigDescriptors[ui8Index];
    
                    //
                    // Start by sending data from the beginning of the first
                    // descriptor.
                    //
                    psUSBControl->ui8ConfigSection = 0;
                    psUSBControl->ui16SectionOffset = 0;
                    psUSBControl->pui8EP0Data =
                                    (uint8_t *)psConfig->psSections[0]->pui8Data;
    
                    //
                    // Determine the total size of the configuration descriptor
                    // by counting the sizes of the sections comprising it.
                    //
                    psUSBControl->ui32EP0DataRemain =
                                                USBDCDConfigDescGetSize(psConfig);
    
                    //
                    // Remember that we need to send the configuration descriptor
                    // and which descriptor we need to send.
                    //
                    psUSBControl->ui8ConfigIndex = ui8Index;
    
                    bConfig = true;
                }
                break;
            }
    
            //
            // This request was for a string descriptor.
            //
            case USB_DTYPE_STRING:
            {
                //
                // Determine the correct descriptor index based on the requested
                // language ID and index.
                //
                i32Index = USBDStringIndexFromRequest(psUSBRequest->wIndex,
                                                      psUSBRequest->wValue & 0xFF);
    
                //
                // If the mapping function returned -1 then stall the request to
                // indicate that the request was not valid.
                //
                if(i32Index == -1)
                {
                    USBDCDStallEP0(0);
                    break;
                }
    
                //
                // Return the externally specified configuration descriptor.
                //
                psUSBControl->pui8EP0Data =
                    (uint8_t *)psDevice->ppui8StringDescriptors[i32Index];
    
                //
                // The total size of a string descriptor is in byte 0.
                //
                psUSBControl->ui32EP0DataRemain =
                    psDevice->ppui8StringDescriptors[i32Index][0];
    
                break;
            }
    
            //
            // Any other request is not handled by the default enumeration handler
            // so see if it needs to be passed on to another handler.
            //
            default:
            {
                //
                // If there is a handler for requests that are not handled then
                // call it.
                //
                if(psDevice->psCallbacks->pfnGetDescriptor)
                {
                    psDevice->psCallbacks->pfnGetDescriptor(g_psDCDInst[0].pvCBData,
                                                          psUSBRequest);
                }
                else
                {
                    //
                    // Whatever this was this handler does not understand it so
                    // just stall the request.
                    //
                    USBDCDStallEP0(0);
                }
    
                return;
            }
        }
    
        //
        // If this request has data to send, then send it.
        //
        if(psUSBControl->pui8EP0Data)
        {
            //
            // If there is more data to send than is requested then just
            // send the requested amount of data.
            //
            if(psUSBControl->ui32EP0DataRemain > psUSBRequest->wLength)
            {
                psUSBControl->ui32EP0DataRemain = psUSBRequest->wLength;
            }
    
            //
            // Now in the transmit data state.  Be careful to call the correct
            // function since we need to handle the configuration descriptor
            // differently from the others.
            //
            if(!bConfig)
            {
                USBDEP0StateTx(0);
            }
            else
            {
                USBDEP0StateTxConfig(0);
            }
        }
    }

    我认为我最初的方法不会起作用,因为"USB_DTYPE_STRING"需要从窗口捕捉描述符消息,因为它是一个"字符串描述符"请求。  仅当调用此函数中用于未知请求类型的默认情况时、才会触发自定义处理程序。  因此、"我认为"我需要修改 USB_DTYPE_string 情况、以查找字符串描述符偏移值0xEE (由 windows 为 OS 描述符指定)并捕获该值、而不是让失速事件执行。  不确定最佳的解决方法是什么、但您是否同意 TI USB 驱动程序库源代码、MOD 应该在该代码处处理来自操作系统的"非标准"字符串描述符请求?  坚持 if 语句来获取0xEE 偏移 case 是否几乎是所有可能需要添加的语句?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    关于这个主题-您知道重新编译这个库的步骤的大致顺序吗?

    尊敬的 Robert:

     usblib 位于 C:\ti\TivaWare_C_Series-2.2.0.295\usblib 中。 您只需像常规 CCS 工程一样导入和编译它。 我刚刚尝试了一下、在构建结束时会生成新的 usblib.lib。  

    在 USB 问题主题上-我想我已经弄清楚了(理论上)您必须做什么来处理这个问题、并且不幸的是您必须(我想)编辑 usbdenum.c 文件。  [/报价]

    抱歉、关于自定义  USB_DTYPE_STRING 的 USB 主题、我真的没有太多的知识和经验、我认为我无法提供有关如何做到这一点的指导。 如果你让它的工作,请与 我们分享,我相信它会对社区有益。 很抱歉缺少指导。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Charles:

    感谢大家花时间在这里为我提供帮助。  我将在本周给 usblib 重新编译一个快照、看看我是否可以使用断点来捕获字符串描述符。  我想、如果我能做到这一点、我就可以提出一个处理/响应计划、即使第一步不优雅也是如此。

    关于 TI 将来的 usblib 构建的一些反馈-如果您能够为该枚举案例语句中处理的一些事件分配自定义处理程序、那会非常好。  你们走对了、底部有一个自定义处理程序检查、默认情况下可以处理其他请求类型、 但是在每种请求类型中、最好能选择连接自定义处理程序、而不是编辑低级驱动程序源代码。  我认为这是相当合理的、因为更多参与的产品开发可能会处理更多类似的情况。  在这种情况下、您处理的是字符串请求、但只有一个子集、如果该子集之外的任何内容进入、那么能够将类似于默认案例的处理程序连接到 Case 语句 tat Fall 中的其他处理案例将会很好 超出了基本消息预期。

    不确定这是否合理、但长话短说、如果 driverlib 可以在以下情况下支持自定义处理程序、那将是很棒的:

            //
            // This request was for a device descriptor.
            //
            case USB_DTYPE_DEVICE:
            {
                //
                // Return the externally provided device descriptor.
                //
                psUSBControl->pui8EP0Data =
                                        (uint8_t *)psDevice->pui8DeviceDescriptor;
    
                //
                // The size of the device descriptor is in the first byte.
                //
                psUSBControl->ui32EP0DataRemain =
                    psDevice->pui8DeviceDescriptor[0];
    
                break;
            }
    
            //
            // This request was for a configuration descriptor.
            //
            case USB_DTYPE_CONFIGURATION:
            {
                //
                // Which configuration are we being asked for?
                //
                ui8Index = (uint8_t)(psUSBRequest->wValue & 0xFF);
    
                //
                // Is this valid?
                //
                psDeviceDesc =
                    (const tDeviceDescriptor *)psDevice->pui8DeviceDescriptor;
    
                if(ui8Index >= psDeviceDesc->bNumConfigurations)
                {
                    //
                    // This is an invalid configuration index.  Stall EP0 to
                    // indicate a request error.
                    //
                    USBDCDStallEP0(0);
                    psUSBControl->pui8EP0Data = 0;
                    psUSBControl->ui32EP0DataRemain = 0;
                }
                else
                {
                    //
                    // Return the externally specified configuration descriptor.
                    //
                    psConfig = psDevice->ppsConfigDescriptors[ui8Index];
    
                    //
                    // Start by sending data from the beginning of the first
                    // descriptor.
                    //
                    psUSBControl->ui8ConfigSection = 0;
                    psUSBControl->ui16SectionOffset = 0;
                    psUSBControl->pui8EP0Data =
                                    (uint8_t *)psConfig->psSections[0]->pui8Data;
    
                    //
                    // Determine the total size of the configuration descriptor
                    // by counting the sizes of the sections comprising it.
                    //
                    psUSBControl->ui32EP0DataRemain =
                                                USBDCDConfigDescGetSize(psConfig);
    
                    //
                    // Remember that we need to send the configuration descriptor
                    // and which descriptor we need to send.
                    //
                    psUSBControl->ui8ConfigIndex = ui8Index;
    
                    bConfig = true;
                }
                break;
            }
    
            //
            // This request was for a string descriptor.
            //
            case USB_DTYPE_STRING:
            {
                //
                // Determine the correct descriptor index based on the requested
                // language ID and index.
                //
                i32Index = USBDStringIndexFromRequest(psUSBRequest->wIndex,
                                                      psUSBRequest->wValue & 0xFF);
    
                //
                // If the mapping function returned -1 then stall the request to
                // indicate that the request was not valid.
                //
                if(i32Index == -1)
                {
                    USBDCDStallEP0(0);
                    break;
                }
    
                //
                // Return the externally specified configuration descriptor.
                //
                psUSBControl->pui8EP0Data =
                    (uint8_t *)psDevice->ppui8StringDescriptors[i32Index];
    
                //
                // The total size of a string descriptor is in byte 0.
                //
                psUSBControl->ui32EP0DataRemain =
                    psDevice->ppui8StringDescriptors[i32Index][0];
    
                break;
            }

    正如你们支持客户为上述情况之外的请求类型连接自定义处理程序一样-这是在下面所示的默认情况下完成的。

            //
            // Any other request is not handled by the default enumeration handler
            // so see if it needs to be passed on to another handler.
            //
            default:
            {
                //
                // If there is a handler for requests that are not handled then
                // call it.
                //
                if(psDevice->psCallbacks->pfnGetDescriptor)
                {
                    psDevice->psCallbacks->pfnGetDescriptor(g_psDCDInst[0].pvCBData,
                                                          psUSBRequest);
                }
                else
                {
                    //
                    // Whatever this was this handler does not understand it so
                    // just stall the request.
                    //
                    USBDCDStallEP0(0);
                }
    
                return;
            }
        }

    我之所以提出这一切、是因为 USB 驱动程序库已经非常接近支持这一点。