{"id":8764,"date":"2024-03-26T07:50:32","date_gmt":"2024-03-26T14:50:32","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=8764"},"modified":"2024-03-26T07:50:32","modified_gmt":"2024-03-26T14:50:32","slug":"using-software-tracing-to-record-usb-requests","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/tracing\/embedded\/usb\/requests\/","title":{"rendered":"Using Software Tracing to Record USB Requests"},"content":{"rendered":"<p>This tutorial shows how to use Software Tracing to easily record all USB requests handled by a device, and to quickly find differences between broken and working firmware versions that handle some requests differently. We will demonstrate it based on the old STM32 CDC example that didn&#8217;t work with the regular Windows 10 CDC driver. We will record the requests and replies from both projects, will locate the critical difference, and patch the old project to work with the regular driver.<\/p>\n<p>Before you begin, install VisualGDB 6.0 or later.<\/p>\n<ol>\n<li>Start Visual Studio and open Tools-&gt;VisualGDB-&gt;Manage VisualGDB Packages. Then, locate the STM32 BSP under the <strong>Installed<\/strong> section and check the &#8220;<strong>Allow installing multiple versions<\/strong>&#8221; checkbox:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/01-multiver.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8765\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/01-multiver.png\" alt=\"\" width=\"1027\" height=\"542\" \/><\/a><\/li>\n<li>Go to the Online section, check the &#8220;show old packages&#8221; checkbox, locate <strong>STM32 Devices v3.6<\/strong> and install it: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/02-getold.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8766\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/02-getold.png\" alt=\"\" width=\"1027\" height=\"542\" \/><\/a><\/li>\n<li>Now you can start creating projects with both BSP versions. First, locate the VisualGDB Embedded Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/01-emb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8767\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/01-emb.png\" alt=\"\" width=\"1014\" height=\"675\" \/><\/a><\/li>\n<li>Enter the name and location of the first project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/02-prjname.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8768\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/02-prjname.png\" alt=\"\" width=\"1014\" height=\"675\" \/><\/a><\/li>\n<li>Proceed with the default settings on the next page:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/03-cmake.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8769\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/03-cmake.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Pick the ARM toolchain and select the device you are targeting. In this tutorial we will use the STM32F4Discovery board that uses STM32F407VG. Make sure you select the old BSP version first:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/04-oldver.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8770\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/04-oldver.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>On the next page choose the <strong>USB Communications Device<\/strong> and click &#8220;Next&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/05-comm.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8771\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/05-comm.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Finally, configure the debug settings that work with your setup and ensure the software tracing is enabled at the bottom of the page:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/06-stlink.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8772\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/06-stlink.png\" alt=\"\" width=\"925\" height=\"693\" \/><\/a><\/li>\n<li>Try building and running the project. If you are using the regular USB COM port driver bundled with Windows 10\/11, it won&#8217;t be able to start the device properly:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/07-com-bad.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8773\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/07-com-bad.png\" alt=\"\" width=\"622\" height=\"318\" \/><\/a><\/li>\n<li>Create a new project for the same device, this time picking the latest BSP:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/08-new.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8774\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/08-new.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Run it and make sure the device got recognized:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/09-com-good.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8775\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/09-com-good.png\" alt=\"\" width=\"622\" height=\"318\" \/><\/a><\/li>\n<li>Normally, we could step through both versions of the project, trying to find the critical difference, however given that USB requests expire after a brief timeout, it would not be practical. Instead, we will use the software tracepoints to record USB-related activity happening on the device, and will compare the traces later. First of all, use Code Explorer to locate all functions related to descriptors, and then navigate the call tree to see that most descriptors are queried from <strong>USBD_LL_SetupStage()<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/10-descr.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8776\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/10-descr.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Click on the tracepoints bar on the line after the call to <strong>USBD_ParseSetupRequest()<\/strong> and create a new tracepoint recording <strong>pdev-&gt;request<\/strong>: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/12-trace.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8777\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/12-trace.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>The old STM32 BSP uses a slightly different memory layout than the new one, so VisualGDB will ask you to verify the tracing settings, and will not agree to place the tracing buffer at the end of RAM. Instead, select &#8220;Store tracing data =&gt; After the end of global variables&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/11-traceloc.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8778\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/11-traceloc.png\" alt=\"\" width=\"1120\" height=\"760\" \/><\/a><\/li>\n<li>Look through the code (or use the Code Explorer) to find the queried descriptors are sent back to the PC via <strong>USBD_CtrlSendData()<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/13-senddata.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8779\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/13-senddata.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Add a tracepoint there using the annotation on top of the function (or via the Tracepoints window) and configure to trace <strong>pbuf<\/strong> as a dynamic array of <strong>len<\/strong> elements:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/14-tp2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8780\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/14-tp2.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Now you can press F5 to start debugging and VisualGDB will record each descriptor request and each outgoing packet sent via <strong>USBD_CtrlSendData()<\/strong>. You can immediately see the very first request, or browse through multiple ones if you suspect a particular one:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/15-data.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8781\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/15-data.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>As we don&#8217;t know which request is different, we will instead export all traced data into a text file, and will compare it against a newer option. Select all events, right-click on them and click &#8220;Export Selected Events&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/16-export.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8782\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/16-export.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Stop the debugging session. VisualGDB will create a trace file that can be replayed at any later moment:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/17-rename.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8783\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/17-rename.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Now open the newer version of the project and create the same tracepoints:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/18-dyn.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8784\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/18-dyn.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Run a debugging session to capture the events and export them to another text file:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/19-export2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8785\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/19-export2.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Use a diff tool (e.g. KDiff3) to compare the requests and replies in both versions. You can quickly see that the very first request yields a slightly different reply:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/20-diff.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8786\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/20-diff.png\" alt=\"\" width=\"1119\" height=\"559\" \/><\/a><\/li>\n<li>Set a breakpoint in <strong>USBD_CtrlSendData(), <\/strong>wait for it to trigger, and use the call stack to see which function calls it: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/21-stack.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8787\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/21-stack.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>You can manually check the value of <strong>req-&gt;wValue<\/strong> to see which descriptor is being requested, or just step out of <strong>USBD_CtlSendData()<\/strong> and forcibly step into the first line of <strong>USBD_GetDescriptor()<\/strong> to run the same code again:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/22-setnext.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8788\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/22-setnext.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Stepping through it quickly reveals that the first queried descriptor is the device descriptor and its bytes [4] and [5] are indeed <strong>00<\/strong> instead of <strong>02 <\/strong>in the newer version:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/23-desc.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8789\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/23-desc.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Go to the definition of <strong>USBD_DeviceDescriptor<\/strong> and replace the bytes in question with <strong>0x02<\/strong>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/24-patched.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8790\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/24-patched.png\" alt=\"\" width=\"1231\" height=\"795\" \/><\/a><\/li>\n<li>Now the old version of the firmware will behave just like the new one, having the COM port successfully recognized and started:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/25-com4.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8791\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2024\/03\/25-com4.png\" alt=\"\" width=\"622\" height=\"318\" \/><\/a><\/li>\n<\/ol>\n<p>You can keep the recorded trace files for reference, so if the firmware stops working at a later stage, you could always compare its behavior to the times when it worked fine. Trace files can be opened via <strong>File-&gt;Open<\/strong> in Visual Studio, or converted to XML files by running the following command:<\/p>\n<pre>VisualGDB.exe \/trace2xml &lt;file.vgdbtrace&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use Software Tracing to easily record all USB requests handled by a device, and to<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[247],"tags":[248,204],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8764"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=8764"}],"version-history":[{"count":1,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8764\/revisions"}],"predecessor-version":[{"id":8792,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8764\/revisions\/8792"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=8764"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=8764"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=8764"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}