AnsweredAssumed Answered

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

Question asked by Kai Liu on Jun 12, 2013
Latest reply on Jun 19, 2013 by Kai Liu

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.

Outcomes