Where to get Nr. of transferred data in a USB bulk read?

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Where to get Nr. of transferred data in a USB bulk read?

Jump to solution
748 Views
kai_liu
Senior Contributor I

I am porting ADB USB host project from Arduino UHS to FSL KL25Z. It is painful since the USB stacks have no common at all. Anyway I have almost finished my work until I tried to write low-level access functions like USB bulk read / bulk write.

In Arduino UHS ADB project, it is simple and forward, two functions are enough.

int USB::bulkWrite(usb_device * device, uint16_t length, uint8_t * data) // return int as USB status, 0x00 as successful
     USB::write(device, &(device->bulk_out) , length, data);
          max3421e_write(uint8_t reg, uint8_t value)

int USB::bulkRead(usb_device * device, uint16_t length, uint8_t * data, boolean poll) // return int as nr of bulk read successfully
     USB::read(device, &(device->bulk_in), length, data, poll ? 1 : USB_NAK_LIMIT);
          max3421e_write(uint8_t reg, uint8_t value)
          max3421e_read(uint8_t reg)

The call is simple, application->class->USB->H/W.

Let us look into PHDC USB host project from FSL USB.

class\phdc\usb_host_phdc.c

USB_STATUS usb_class_phdc_recv_data( USB_PHDC_PARAM* call_param_ptr ) 
{
     ...usb_host_class_intf_validate(call_param_ptr ->ccs_ptr)...
     usb_hostdev_tr_init (&tr, (tr_callback)usb_class_phdc_recv_data_callback, call_param_ptr); 
     tr.RX_BUFFER       = call_param_ptr ->buff_ptr;
     tr.RX_LENGTH       = call_param_ptr ->buff_size; 
     call_param_ptr ->tr_index = tr.TR_INDEX;
     call_param_ptr ->tr_pipe_handle = pipe; 
     usb_status = _usb_host_recv_data(phdc_cis_ptr ->generalClass.host_handle, pipe, &tr);
}

host_common\host_rcv.c

uint_32 _usb_host_recv_data( _usb_host_handle hci_handle, _usb_pipe_handle  pipe_handle,TR_INIT_PARAM_STRUCT_PTR  tr_params_ptr) 
{
     ...status = _usb_host_recv_data_call_interface (hci_handle, pipe_descr_ptr, pipe_tr_ptr);
     if (status == USB_OK)
         return USB_STATUS_TRANSFER_QUEUED;
     ....
}

host_common\host_main.c

USB_STATUS _usb_host_recv_data_call_interface( _usb_host_handle handle, struct pipe_descriptor_struct _PTR_ pipe_descr_ptr, struct pipe_tr_struct _PTR_ pipe_tr_ptr) 
{
     ...
     temp_ptr = (USB_HOST_CALLBACK_FUNCTIONS_STRUCT_PTR)usb_host_ptr->CALLBACK_STRUCT_PTR;
     if (temp_ptr->HOST_RECV != NULL){
         error = temp_ptr->HOST_RECV (handle, pipe_descr_ptr, pipe_tr_ptr);
     }
     return error;
}

Here temp_ptr->HOST_RECV() is _usb_khci_recv() in khci_kinetis.c

khci_kinetis.c

USB_STATUS _usb_khci_recv(_usb_host_handle handle, PIPE_DESCRIPTOR_STRUCT_PTR pipe_desc_ptr, PIPE_TR_STRUCT_PTR pipe_tr_ptr)
{
    msg.type = TR_MSG_RECV;
    msg.pipe_desc = pipe_desc_ptr;
    msg.pipe_tr = pipe_tr_ptr;
    ......
}

khci_kinetis.c

void _usb_khci_task(void)
{
    case TR_MSG_RECV:
        buf = msg.pipe_tr->RX_BUFFER;
        remain = msg.pipe_tr->RX_LENGTH;
        do{
            res = _usb_khci_atom_tr(TR_IN, usb_host_state_struct_ptr->speed, msg.pipe_desc, buf, remain);
        }while(1)
    ......
}

The whole process of USB bulkRead transfer implemented in FSL USB stack is:

  1. usb_class_phdc_recv_data() // application, class level call
  2. _usb_host_recv_data() // general purpose function for bulkIn
  3. _usb_host_recv_data_call_interface() // clue function to function map
  4. _usb_khci_recv() // push tr to message pool, and return from top of stack
  5. _usb_khci_task() // main loop
  6. _usb_khci_atom_tr() // real H/W API for register access

In current implementation, Application->Class->Clue->MessagePool, then return to main loop for H/W access. My question is:

How application knows how many bytes have been read? by _usb_khci_process_tr_complete() to notify application by callback functions like usb_class_phdc_recv_data_callback()?

FSL did offer many documentations for its USB stack. But we still need a design specification describing internal structure of USB stack, since it is much complex than other implementations.

Tags (1)
0 Kudos
1 Solution
380 Views
kai_liu
Senior Contributor I

In _usb_khci_task(),

     res = _usb_khci_atom_tr(TR_IN, usb_host_state_struct_ptr->speed, msg.pipe_desc, buf, remain);

is used to return count of reading USB IN pipes, otherwise return negative values as errors. The outer while loop means it will try best to read all responses from IN piples.

And its value should be processed in

     _usb_khci_process_tr_complete() -> usb_class_phdc_receive_callback()

FSL USB host stack use many callbacks and split the low-level register access in main loop() by

     main()->poll()->_usb_khci_task()->_usb_khci_atom_tr()

Its receive/send functions including:

     usb_class_phdc_send_data() / usb_class_phdc_receive_data()

just prepares Transfer params into a queue, they will not touch registers. The real data processing is taken in

     usb_class_phdc_send_data_callback() / usb_class_phdc_receive_data_callback()

It is complex than simpler implementation of Arduino UHS. However, it is still doable with cost of longer R+D time.

BTW, PHDC is a good starting point for generic USB transfer based upon BulkIn/BulkOut/Control and optional Interrupt IN.

View solution in original post

0 Kudos
1 Reply
381 Views
kai_liu
Senior Contributor I

In _usb_khci_task(),

     res = _usb_khci_atom_tr(TR_IN, usb_host_state_struct_ptr->speed, msg.pipe_desc, buf, remain);

is used to return count of reading USB IN pipes, otherwise return negative values as errors. The outer while loop means it will try best to read all responses from IN piples.

And its value should be processed in

     _usb_khci_process_tr_complete() -> usb_class_phdc_receive_callback()

FSL USB host stack use many callbacks and split the low-level register access in main loop() by

     main()->poll()->_usb_khci_task()->_usb_khci_atom_tr()

Its receive/send functions including:

     usb_class_phdc_send_data() / usb_class_phdc_receive_data()

just prepares Transfer params into a queue, they will not touch registers. The real data processing is taken in

     usb_class_phdc_send_data_callback() / usb_class_phdc_receive_data_callback()

It is complex than simpler implementation of Arduino UHS. However, it is still doable with cost of longer R+D time.

BTW, PHDC is a good starting point for generic USB transfer based upon BulkIn/BulkOut/Control and optional Interrupt IN.

0 Kudos