<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Linux CDC ACM Host App passing misaligned bytes to app_usbd_cdc_acm_read()</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/61838/linux-cdc-acm-host-app-passing-misaligned-bytes-to-app_usbd_cdc_acm_read</link><description>Hi, 
 I am using a Linux Host to communicate with my nRF52840 as a USB CDC ACM device. As a test, I ran minicom and was able to transfer bytes to my Nordic app successfully. I used the Nordic egs to get this far. When I switch from minicom to my Linux</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Tue, 02 Jun 2020 21:01:51 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/61838/linux-cdc-acm-host-app-passing-misaligned-bytes-to-app_usbd_cdc_acm_read" /><item><title>RE: Linux CDC ACM Host App passing misaligned bytes to app_usbd_cdc_acm_read()</title><link>https://devzone.nordicsemi.com/thread/252850?ContentTypeID=1</link><pubDate>Tue, 02 Jun 2020 21:01:51 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e4bf548d-56c0-42be-a5ce-282faf07a24c</guid><dc:creator>Mark J</dc:creator><description>&lt;p&gt;I have updated my cdc_acm_user_ev_handler() implementation to read into a byte and then add that byte to my incoming byte array. Cleaner and easier to understand.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_cdc_acm_user_event_t event)
{
  ret_code_t ret;

  app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);

  switch (event)
  {
    case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:

      SEGGER_RTT_printf(0, &amp;quot;CDC Port Open\n&amp;quot;);

      // This call does not actually read any incoming bytes, it simply REQUESTS that
      // the m_rx_byte will be overwritten by 1 incoming byte whenever that byte comes in. 
      // When this byte is received, an APP_USBD_CDC_ACM_USER_EVT_RX_DONE will be generated.
      // Note that NRF_ERROR_IO_PENDING should be returned if no bytes have been recieved
      // but (for some reason) when this call is made within this event type, NRF_SUCCESS always
      // seems to be returned, so ignore the return value.
      app_usbd_cdc_acm_read(&amp;amp;m_app_cdc_acm, &amp;amp;m_rx_byte, 1);
      
      break;

    case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
      SEGGER_RTT_printf(0, &amp;quot;CDC Port Close\n&amp;quot;);
      break;

    case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
      // DEBUG SEGGER_RTT_printf(0, &amp;quot;CDC Tx Done\n&amp;quot;);
      break;
     
    case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
    {
      // Copy the byte read (that triggered this event) into m_rx_buffer[].
      m_rx_buffer[m_rx_idx++] = m_rx_byte;

      // There may be additional bytes available to read. Continue to process all available bytes. 
      while(true)
      {
        // Read additional bytes 1 at a time. If they are available, NRF_SUCCESS will be returned.
        // If a byte is not available, this app_usbd_cdc_acm_read() call will REQUEST that it is
        // read into m_rx_byte when it comes in. When this happens, this event will be triggered again.
        // Note that even if we have a full pckt received before this read call, it is required so that we can get
        // this APP_USBD_CDC_ACM_USER_EVT_RX_DONE event again when the next pckt is received.
        ret = app_usbd_cdc_acm_read(&amp;amp;m_app_cdc_acm, &amp;amp;m_rx_byte, 1);

        // DEBUG SEGGER_RTT_printf(0, &amp;quot;Read with ret %d and size %d and byte 0x%02X into idx %d\n&amp;quot;, ret, size, m_rx_buffer[m_rx_idx], m_rx_idx);
   
        // Check ret.
        if(ret == NRF_SUCCESS) 
        {
          // Update m_rx_buffer[] and keep going as there may be more bytes.
          m_rx_buffer[m_rx_idx++] = m_rx_byte;
        }
        else if(ret == NRF_ERROR_IO_PENDING) 
        { 
          // DEBUG for(int x=0; x&amp;lt;m_rx_idx; x++) { SEGGER_RTT_printf(0, &amp;quot;idx %d: 0x%02X\n&amp;quot;, x, m_rx_buffer[x]); }

          // Check the pckt len at m_rx_buffer[1] to see if we have a complete pckt.
          if(m_rx_idx&amp;gt;=2)
          {
            uint8_t pcktLenInPckt =  m_rx_buffer[1];
            if(m_rx_idx &amp;gt;= pcktLenInPckt)
            {
              // Schedule an event on the main thread to process the pckt. Will run usbd_cdc_data_handler() below on main.
              app_sched_event_put(NULL,  0, main_usbd_cdc_sched_handler);
            }
          }
          
          // All done reading data that drove the event.
          return; 
        }
        else
        {
          SEGGER_RTT_printf(0, &amp;quot;app_usbd_cdc_acm_read() error: %d. USB read fail.\n&amp;quot;, ret);

          return;
        }
        
      }

      break; // case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
    }

    default:
      break;
  }
}
&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Linux CDC ACM Host App passing misaligned bytes to app_usbd_cdc_acm_read()</title><link>https://devzone.nordicsemi.com/thread/252808?ContentTypeID=1</link><pubDate>Tue, 02 Jun 2020 15:36:09 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:84638e87-a463-41be-b65e-ff8cc93e6f9a</guid><dc:creator>Mark J</dc:creator><description>&lt;p&gt;Hi Jorgen,&lt;/p&gt;
&lt;p&gt;Thanks for the reply. To answer your question - no I have not tested with the latest SDK as I have to move on to getting code delivered. I can work around the known issue in my rev SDK (incorrect return value of&amp;nbsp;&lt;span&gt;NRF_SUCCESS from&amp;nbsp;app_usbd_cdc_acm_read() when handling the&amp;nbsp;APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Regarding the docs, I would suggest that my long winded explanation of the issue is better than the /* Setup first transfer*/ comment in the example. Usually Nordic docs and examples are much better than industry standard, so I was a little surprised at the docs and examples for this API.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Thanks,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Mark J&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Linux CDC ACM Host App passing misaligned bytes to app_usbd_cdc_acm_read()</title><link>https://devzone.nordicsemi.com/thread/252747?ContentTypeID=1</link><pubDate>Tue, 02 Jun 2020 12:53:42 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:f2a5efaf-1630-461b-b73a-bf2cef4c20db</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>&lt;p&gt;I think the&amp;nbsp;&lt;a href="https://infocenter.nordicsemi.com/topic/sdk_nrf5_v16.0.0/lib_usbd_class_cdc.html#usb_cdc_send_receive"&gt;library documentation&lt;/a&gt;&amp;nbsp;explains how the function works pretty similarly to how you describe it.&lt;/p&gt;
&lt;p&gt;For the issue with wrong return code when called from the&amp;nbsp;&lt;span&gt;APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN, I was not able to reproduce this with the USBD CDC ACM example in SDK 16. I modified the code to print the return code, and also check the available data in the internal buffer:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
{
    bsp_board_led_on(LED_CDC_ACM_OPEN);
    NRF_LOG_INFO(&amp;quot;PORT_OPEN Bytes waiting: %d&amp;quot;, app_usbd_cdc_acm_bytes_stored(p_cdc_acm));

    /*Setup first transfer*/
    ret_code_t ret = app_usbd_cdc_acm_read(&amp;amp;m_app_cdc_acm,
                                           m_rx_buffer,
                                           READ_SIZE);

    NRF_LOG_INFO(&amp;quot;ret: %d&amp;quot;, ret);
    UNUSED_VARIABLE(ret);
    break;
}&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;This is the output:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="text"&gt;&amp;lt;info&amp;gt; app: PORT_OPEN Bytes waiting: 0
&amp;lt;info&amp;gt; app: ret: 146&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Did you test with the latest SDK?&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Linux CDC ACM Host App passing misaligned bytes to app_usbd_cdc_acm_read()</title><link>https://devzone.nordicsemi.com/thread/252480?ContentTypeID=1</link><pubDate>Fri, 29 May 2020 17:45:53 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:63ef5172-07c3-420f-b919-9595eec79e90</guid><dc:creator>Mark J</dc:creator><description>&lt;p&gt;Hi Jorgen,&lt;/p&gt;
&lt;p&gt;Thanks for replying ...&lt;/p&gt;
&lt;p&gt;In the end, the issue was actually my misunderstanding of the Nordic&amp;nbsp;&lt;a href="https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.0.0%2Fgroup__app__usbd__cdc__acm.html"&gt;USB CDC ACM Class&lt;/a&gt;. Specifically - the&amp;nbsp;&lt;span&gt;app_usbd_cdc_acm_read() call. The implementation of reads within this class is .... special (choosing my words carefully).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The&amp;nbsp;&lt;span&gt;app_usbd_cdc_acm_read() function DOES NOT always read. It is commonly more of a read REQUEST that the driver reads incoming data into the buffer provided when the specified number of data bytes are available and then notifies&amp;nbsp;the API consumer via th&lt;/span&gt;e&amp;nbsp;APP_USBD_CDC_ACM_USER_EVT_RX_DONE&amp;nbsp;event.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;When handling the&amp;nbsp;APP_USBD_CDC_ACM_USER_EVT_RX_DONE&amp;nbsp;event, API consumers can call&amp;nbsp;app_usbd_cdc_acm_read() in case there are any additional bytes to read. If there are, NRF_SUCCESS is returned and bytes are read into the provided buffer. If not,&amp;nbsp;a value of&amp;nbsp;NRF_ERROR_IO_PENDING is returned.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;It took alot of empirical&amp;nbsp;testing to resolve how the API worked. Better API doc text and more comments within the example code would have made my task dramatically easier.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Note that I believe that I found a bug .... When calling&amp;nbsp;app_usbd_cdc_acm_read() when handling the&amp;nbsp;APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN event (as per the eg), I received&amp;nbsp;a return value of&amp;nbsp;NRF_SUCCESS - when no incomming bytes were present. The return should have been&amp;nbsp;NRF_ERROR_IO_PENDING. When calling&amp;nbsp;app_usbd_cdc_acm_read() within the&amp;nbsp;APP_USBD_CDC_ACM_USER_EVT_RX_DONE&amp;nbsp;event, returns from the function seemed to be correct.&lt;/p&gt;
&lt;p&gt;Below is my event handler code with heavy comments.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst,
                                    app_usbd_cdc_acm_user_event_t event)
{
  ret_code_t ret;

  app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);

  switch (event)
  {
    case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:

      SEGGER_RTT_printf(0, &amp;quot;CDC Port Open\n&amp;quot;);

      // This call does not actually read any incoming bytes, it simply REQUESTS that
      // the m_rx_buffer[] will be filled by 1 byte whenever 1 byte comes in. 
      // When this byte is received, an APP_USBD_CDC_ACM_USER_EVT_RX_DONE will be generated.
      // Note that NRF_ERROR_IO_PENDING should be returned if no bytes have been recieved
      // but (for some reason) when this call is made within this event type, NRF_SUCCESS always
      // seems to be returned, so ignore the return value.
      app_usbd_cdc_acm_read(&amp;amp;m_app_cdc_acm, &amp;amp;(m_rx_buffer[m_rx_idx]), 1);
      
      break;

    case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
      SEGGER_RTT_printf(0, &amp;quot;CDC Port Close\n&amp;quot;);
      break;

    case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
      SEGGER_RTT_printf(0, &amp;quot;CDC Tx Done\n&amp;quot;);
      break;
     
    case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
    {
      SEGGER_RTT_printf(0, &amp;quot;Read event.\n&amp;quot;);

      // Get amount of incoming data. Should match the length of data within the last request (i.e. read()).
      size_t size = app_usbd_cdc_acm_rx_size(p_cdc_acm);

      // Increment m_rx_idx by the number of bytes in for proper rx indexing.
      m_rx_idx+=size;

      // As per the usbd_ble_uart eg (the eg that uses a Softdevice), read data in 1 char at
      // a time and add it to our buffer at m_rx_idx.
      while(true)
      {
        // Read additional bytes 1 at a time. If they are available, NRF_SUCCESS will be returned.
        // If a byte is not available, this app_usbd_cdc_acm_read() call will REQUEST that it is
        // read into m_rx_buffer[m_rx_idx] when it comes in. When this happens, this event will be triggered again.
        // Note that even if we have a full pckt received before this read call, it is required so that we can get
        // this APP_USBD_CDC_ACM_USER_EVT_RX_DONE event again when the next pckt is sent.
        ret = app_usbd_cdc_acm_read(&amp;amp;m_app_cdc_acm, &amp;amp;(m_rx_buffer[m_rx_idx]), 1);

        // DEBUG SEGGER_RTT_printf(0, &amp;quot;Read with ret %d and size %d and byte 0x%02X into idx %d\n&amp;quot;, ret, size, m_rx_buffer[m_rx_idx], m_rx_idx);
   
        // Check ret.
        if(ret == NRF_SUCCESS) { m_rx_idx++; } // Keep going as there may be more bytes.
        else if(ret == NRF_ERROR_IO_PENDING) 
        { 
          // DEBUG for(int x=0; x&amp;lt;m_rx_idx; x++) { SEGGER_RTT_printf(0, &amp;quot;idx %d: 0x%02X\n&amp;quot;, x, m_rx_buffer[x]); }

          // Check the pckt len at m_rx_buffer[1] to see if we have a complete pckt.
          if(m_rx_idx&amp;gt;=2)
          {
            uint8_t pcktLenInPckt =  m_rx_buffer[1];
            if(m_rx_idx &amp;gt;= pcktLenInPckt)
            {
              // Schedule an event on the main thread to process the pckt. Will run usbd_cdc_data_handler() below from main.
              app_sched_event_put(NULL,  0, main_usbd_cdc_sched_handler);
            }
          }
          
          // All done reading data that drove the event.
          return; 
        }
        else
        {
          SEGGER_RTT_printf(0, &amp;quot;app_usbd_cdc_acm_read() error: %d. USB read fail.\n&amp;quot;, ret);

          return;
        }
        
      }

      break; // case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
    }

    default:
      break;
  }
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I will suggest this comment as an answer in the hope that somebody can verify it.&lt;/p&gt;
&lt;p&gt;I would strongly encourage Nordic to update both API docs and any examples that use&amp;nbsp;&lt;span&gt;app_usbd_cdc_acm_read().&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Thanks,&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Mark J&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Linux CDC ACM Host App passing misaligned bytes to app_usbd_cdc_acm_read()</title><link>https://devzone.nordicsemi.com/thread/252461?ContentTypeID=1</link><pubDate>Fri, 29 May 2020 15:00:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:78fc2a8e-2849-4c0b-a969-3424d62ae357</guid><dc:creator>J&amp;#248;rgen Holmefjord</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Unfortunately, I&amp;#39;m not aware of any Linux CDC Host communication examples. If you are not able to reproduce the issue with minicom you may get better suggestions if you ask your question in a Linux forum. Especially if you think that the issue lays on the Linux side with your port setup, and not on the Nordic side.&lt;/p&gt;
&lt;p&gt;Best regards,&lt;br /&gt;Jørgen&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>