*****************************************************************
1. Introducation
*****************************************************************
ADSP21535 has one USB Device Controller (UDC) which supports four
types of USB transfers (Control, Bulk, Interrupt, ISO).
The USB driver makes it possible for the applications in user
mode to access the UDC. The USB driver processes USB enumeration
automatically and provides the interface for USB to transfer
information to the application.
With the USB driver, the user application will be able to
communicate with USB Host (PC) via three types of transfer:
Bulk, Interrupt, ISO. The Control transfer will be processed by
USB driver internally, no related interface will be visible to
user application.
*****************************************************************
2. System interface
*****************************************************************
The USB driver register itself is a standard character device
driver.
The Major number of USB driver is 221. The device name is /dev/adi_usb
So the standard file operations can be used to access the USB
driver:
1) open()
open("/dev/adi_usb",...) will return the fd of USB driver
The USB driver can be accessed by multi-process at the same time.
2) close()
3) read()
USB driver does *NOT* support this operation
4) write()
USB driver does *NOT* support this operation
5) ioctl()
Following ioctl commands are supported
CMD_USB_BULK_INTR_READ:
Read from USB BULK pipe.
The argument points to structure of 'usb_bulk_intr_ioctl' show as below.
typedef struct
{
unsigned char * buf;
int len;
int flag;
} usb_bulk_intr_ioctl;
The 'buf' is the buffer to receive data.
The 'len' is the count of data to receive.
The 'flag' must be 1 means read from BULK pipe
The number of received data will be returned
CMD_USB_BULK_INTR_WRITE:
Write to USB BULK/INTERRUPT pipe.
The argument points to structure of usb_bulk_intr_ioctl.
The 'buf' points to the buffer to send.
The 'len' is the count of data to send.
The 'flag' is 1 means write to BULK pipe
The 'flag' is 2 means write to INTERRUPT pipe
The number of data sent out will be returned
CMD_USB_ISO_READ:
Read from USB ISO pipe.
The argument points to structure of 'usb_iso_data' show as below.
typedef struct
{
unsigned short len;
char * data_buf;
} usb_iso_frame;
typedef struct
{
unsigned long frame_num;
usb_iso_frame frame[1];
} usb_iso_data;
The 'frame_num" is the number of frames to receive.
The 'frame' points to each ISO frames.
The 'frame_num' will be set with the number of frames actually received
when return. The 'len' of each ISO frame will also be set to the length
of the frame data. The data of each ISO frame will be copied to buffer
pointed by 'data_buf' of the frame.
CMD_USB_ISO_WRITE:
Write USB ISO pipe.
The argument points to structure of 'usb_iso_data'.
The 'frame_num" is the number of frames to be transmitted.
The 'frame' points to each ISO frames.
The 'frame_num' shall be set with the number of frames to send.
The 'len' of each ISO frame shall also be set to the length
of the frame data. The 'data_buf' of each ISO frame shall point
to the data buffer of the frame.
The 'frame_num' will be set with the number of frames actually transmitted
when return.
NOTE:
A set of user space APIs are available to simplify programming.
*****************************************************************
3. User API for USB driver
*****************************************************************
1) usb_pipe_open()
Syntax:
usb_pipe_handle usb_pipe_open (int pipe_type)
Description:
Open one of the pipes of the UDC. One pipe consists of two endpoints
that have the same type (Bulk, Interrupt or Isochronous)
The specific pipe will NOT be accessible until it has been opened.
NOTE:
When Interrupt pipe type is specified, the returned pipe handle can NOT
be used to call usb_pipe_read(). Since only USB Interrupt IN
(data to USB Host) is supported by USB kernel driver and USB Host.
Parameters:
pipe_type The type of the pipe to be opened
1: Bulk pipe
2: Interrupt pipe
3: Isochronous pipe
Return:
The handle of the opened endpoint will be returned if succeed,
otherwise negative error number will returned.
2) usb_pipe_close()
Syntax:
void usb_pipe_close (usb_pipe_handle pipe)
Description:
Close the pipe that had been opened
Parameters:
pipe The handle returned by usb_pipe_open()
3) usb_pipe_write()
Syntax:
int usb_pipe_write (usb_pipe_handle pipe, char * buf, int len)
Description:
Send data to USB Host through the specific pipe. The data will be stored
into internal buffer first, and will be written into the FIFO of the
specific endpoint of UDC whenever the room of FIFO is available.
Eventually, the data will be sent to USB Host.
Parameters:
pipe The handle returned by usb_pipe_open()
buf The pointer of the buffer for data to be sent
len The length of data.
Return:
The bytes of the data sent out will be returned if success, otherwise
negative error number will be returned
4) usb_pipe_read()
Syntax:
int usb_pipe_read (usb_pipe_handle pipe, char * buf, int len)
Description:
Get data sent by USB Host via specific USB endpoint.
Whenever the data from USB Host are received, they will be stored
into internal buffer first. Then the data will be returned to the caller
whenever this function is called.
Parameters:
pipe The handle returned by usb_pipe_open()
buf The pointer of the buffer for data to be sent
len The length of data
Return:
The bytes of the data sent out will be returned if success, otherwise
negative error number will be returned
5) usb_pipe_iso_write()
Syntax:
int usb_pipe_iso_write (usb_pipe_handle pipe, usb_iso_data * iso_data)
Description:
Send Isochronous data to USB Host.
Parameters:
pipe The handle returned by usb_pipe_open()
iso_data ISO frames descriptor
Return:
The bytes of the data sent out will be returned if success, otherwise
negative error number will be returned
6) usb_pipe_iso_read()
Syntax:
int usb_pipe_iso_read (usb_pipe_handle pipe, usb_iso_data * iso_data)
Description:
Get Isochronous data sent by USB Host.
Parameters:
pipe The handle returned by usb_pipe_open()
iso_data ISO frames descriptor
Return:
The bytes of the data sent out will be returned if success, otherwise
negative error number will be returned
*****************************************************************
4. Usage of USB driver
*****************************************************************
1) Read/Write from/to USB BULK/INTERRUPT pipe
a) Call usb_pipe_open() to open pipe
b) Call usb_pipe_read()/write() to read/write
c) Call usb_pipe_close() to close pipe
2) Read from USB ISO pipe
a) Call usb_pipe_open() to open ISO pipe
b) Allocate 'usb_iso_data' structure
iso_data = (usb_iso_data *) malloc(sizeof(usb_iso_data) +
(frame_num - 1) * sizeof(usb_iso_frame));
c) Set the 'frame_num'of usb_iso_data structure with number frames
you want to read.
iso_data->frame_num = frame_num;
d) Setup buffer for each frame
for (i = 0; i < frame_num; i++)
iso_data->frame[i].data_buf = malloc(...);
NOTE: Sufficient memory shall be allocated for each frame.
Buffer of each frame shall be able to hold at least 8-byte data.
e) Call usb_pipe_iso_read() to read ISO frames
f) Check 'iso_data->frame_num' to determine the number received frames.
g) Check each frame's length and data
for (i = 0; i < iso_data->frame_num; i++)
{
len = iso_data->frame[i].len;
memcpy(buf, iso_data->frame[i].data_buf, len);
......
}
h) Call usb_pipe_close() to close the ISO pipe
3) Write to USB ISO pipe
a) Call usb_pipe_open() to open ISO pipe
b) Allocate 'usb_iso_data' structure
iso_data = (usb_iso_data *) malloc(sizeof(usb_iso_data) +
(frame_num - 1) * sizeof(usb_iso_frame));
c) Set the 'frame_num'of usb_iso_data structure with number frames
you want to write.
iso_data->frame_num = frame_num;
d) Setup buffer and length for each frame
for(i=0;i<frame_num; i++)
{
iso_data->frame[i].data_buf = malloc(len);
memcpy(iso_data->frame[i].data_buf, ...);
iso_dat->frame[i].len = len;
}
NOTE: Lenght of each frame shall NOT exceed 8-byte data.
e) Call usb_pipe_iso_write() to write ISO frames
f) Check 'iso_data->frame_num' to determine the number of frames transmitted.
g) Call usb_pipe_close() to close the ISO pipe
For detail information for usage for USB drive, pls refer to usb_test.c
*****************************************************************
5. NOTE
*****************************************************************
1) Read from Interrupt pipe is NOT supported.
2) The length of each ISO frames sent to USB Host must be same as
the maximum packet size of ISO IN endpoint. It is set to 8
bytes now.
3) Don't try to write more than 63 bytes to the Bulk OUT endpoint
from USB Host(PC) each time. The size of Bulk OUT DMA buffer
is only 63-bytes. Sending 64-byte packet will be NAKed
forever!
The root cause of this issue is a UDC hardware bug. The bug
will prevent us from getting a correct data length for the Bulk
OUT transfer unless we make the size of DMA buffer less than
max packet size (64-bytes).
1. Introducation
*****************************************************************
ADSP21535 has one USB Device Controller (UDC) which supports four
types of USB transfers (Control, Bulk, Interrupt, ISO).
The USB driver makes it possible for the applications in user
mode to access the UDC. The USB driver processes USB enumeration
automatically and provides the interface for USB to transfer
information to the application.
With the USB driver, the user application will be able to
communicate with USB Host (PC) via three types of transfer:
Bulk, Interrupt, ISO. The Control transfer will be processed by
USB driver internally, no related interface will be visible to
user application.
*****************************************************************
2. System interface
*****************************************************************
The USB driver register itself is a standard character device
driver.
The Major number of USB driver is 221. The device name is /dev/adi_usb
So the standard file operations can be used to access the USB
driver:
1) open()
open("/dev/adi_usb",...) will return the fd of USB driver
The USB driver can be accessed by multi-process at the same time.
2) close()
3) read()
USB driver does *NOT* support this operation
4) write()
USB driver does *NOT* support this operation
5) ioctl()
Following ioctl commands are supported
CMD_USB_BULK_INTR_READ:
Read from USB BULK pipe.
The argument points to structure of 'usb_bulk_intr_ioctl' show as below.
typedef struct
{
unsigned char * buf;
int len;
int flag;
} usb_bulk_intr_ioctl;
The 'buf' is the buffer to receive data.
The 'len' is the count of data to receive.
The 'flag' must be 1 means read from BULK pipe
The number of received data will be returned
CMD_USB_BULK_INTR_WRITE:
Write to USB BULK/INTERRUPT pipe.
The argument points to structure of usb_bulk_intr_ioctl.
The 'buf' points to the buffer to send.
The 'len' is the count of data to send.
The 'flag' is 1 means write to BULK pipe
The 'flag' is 2 means write to INTERRUPT pipe
The number of data sent out will be returned
CMD_USB_ISO_READ:
Read from USB ISO pipe.
The argument points to structure of 'usb_iso_data' show as below.
typedef struct
{
unsigned short len;
char * data_buf;
} usb_iso_frame;
typedef struct
{
unsigned long frame_num;
usb_iso_frame frame[1];
} usb_iso_data;
The 'frame_num" is the number of frames to receive.
The 'frame' points to each ISO frames.
The 'frame_num' will be set with the number of frames actually received
when return. The 'len' of each ISO frame will also be set to the length
of the frame data. The data of each ISO frame will be copied to buffer
pointed by 'data_buf' of the frame.
CMD_USB_ISO_WRITE:
Write USB ISO pipe.
The argument points to structure of 'usb_iso_data'.
The 'frame_num" is the number of frames to be transmitted.
The 'frame' points to each ISO frames.
The 'frame_num' shall be set with the number of frames to send.
The 'len' of each ISO frame shall also be set to the length
of the frame data. The 'data_buf' of each ISO frame shall point
to the data buffer of the frame.
The 'frame_num' will be set with the number of frames actually transmitted
when return.
NOTE:
A set of user space APIs are available to simplify programming.
*****************************************************************
3. User API for USB driver
*****************************************************************
1) usb_pipe_open()
Syntax:
usb_pipe_handle usb_pipe_open (int pipe_type)
Description:
Open one of the pipes of the UDC. One pipe consists of two endpoints
that have the same type (Bulk, Interrupt or Isochronous)
The specific pipe will NOT be accessible until it has been opened.
NOTE:
When Interrupt pipe type is specified, the returned pipe handle can NOT
be used to call usb_pipe_read(). Since only USB Interrupt IN
(data to USB Host) is supported by USB kernel driver and USB Host.
Parameters:
pipe_type The type of the pipe to be opened
1: Bulk pipe
2: Interrupt pipe
3: Isochronous pipe
Return:
The handle of the opened endpoint will be returned if succeed,
otherwise negative error number will returned.
2) usb_pipe_close()
Syntax:
void usb_pipe_close (usb_pipe_handle pipe)
Description:
Close the pipe that had been opened
Parameters:
pipe The handle returned by usb_pipe_open()
3) usb_pipe_write()
Syntax:
int usb_pipe_write (usb_pipe_handle pipe, char * buf, int len)
Description:
Send data to USB Host through the specific pipe. The data will be stored
into internal buffer first, and will be written into the FIFO of the
specific endpoint of UDC whenever the room of FIFO is available.
Eventually, the data will be sent to USB Host.
Parameters:
pipe The handle returned by usb_pipe_open()
buf The pointer of the buffer for data to be sent
len The length of data.
Return:
The bytes of the data sent out will be returned if success, otherwise
negative error number will be returned
4) usb_pipe_read()
Syntax:
int usb_pipe_read (usb_pipe_handle pipe, char * buf, int len)
Description:
Get data sent by USB Host via specific USB endpoint.
Whenever the data from USB Host are received, they will be stored
into internal buffer first. Then the data will be returned to the caller
whenever this function is called.
Parameters:
pipe The handle returned by usb_pipe_open()
buf The pointer of the buffer for data to be sent
len The length of data
Return:
The bytes of the data sent out will be returned if success, otherwise
negative error number will be returned
5) usb_pipe_iso_write()
Syntax:
int usb_pipe_iso_write (usb_pipe_handle pipe, usb_iso_data * iso_data)
Description:
Send Isochronous data to USB Host.
Parameters:
pipe The handle returned by usb_pipe_open()
iso_data ISO frames descriptor
Return:
The bytes of the data sent out will be returned if success, otherwise
negative error number will be returned
6) usb_pipe_iso_read()
Syntax:
int usb_pipe_iso_read (usb_pipe_handle pipe, usb_iso_data * iso_data)
Description:
Get Isochronous data sent by USB Host.
Parameters:
pipe The handle returned by usb_pipe_open()
iso_data ISO frames descriptor
Return:
The bytes of the data sent out will be returned if success, otherwise
negative error number will be returned
*****************************************************************
4. Usage of USB driver
*****************************************************************
1) Read/Write from/to USB BULK/INTERRUPT pipe
a) Call usb_pipe_open() to open pipe
b) Call usb_pipe_read()/write() to read/write
c) Call usb_pipe_close() to close pipe
2) Read from USB ISO pipe
a) Call usb_pipe_open() to open ISO pipe
b) Allocate 'usb_iso_data' structure
iso_data = (usb_iso_data *) malloc(sizeof(usb_iso_data) +
(frame_num - 1) * sizeof(usb_iso_frame));
c) Set the 'frame_num'of usb_iso_data structure with number frames
you want to read.
iso_data->frame_num = frame_num;
d) Setup buffer for each frame
for (i = 0; i < frame_num; i++)
iso_data->frame[i].data_buf = malloc(...);
NOTE: Sufficient memory shall be allocated for each frame.
Buffer of each frame shall be able to hold at least 8-byte data.
e) Call usb_pipe_iso_read() to read ISO frames
f) Check 'iso_data->frame_num' to determine the number received frames.
g) Check each frame's length and data
for (i = 0; i < iso_data->frame_num; i++)
{
len = iso_data->frame[i].len;
memcpy(buf, iso_data->frame[i].data_buf, len);
......
}
h) Call usb_pipe_close() to close the ISO pipe
3) Write to USB ISO pipe
a) Call usb_pipe_open() to open ISO pipe
b) Allocate 'usb_iso_data' structure
iso_data = (usb_iso_data *) malloc(sizeof(usb_iso_data) +
(frame_num - 1) * sizeof(usb_iso_frame));
c) Set the 'frame_num'of usb_iso_data structure with number frames
you want to write.
iso_data->frame_num = frame_num;
d) Setup buffer and length for each frame
for(i=0;i<frame_num; i++)
{
iso_data->frame[i].data_buf = malloc(len);
memcpy(iso_data->frame[i].data_buf, ...);
iso_dat->frame[i].len = len;
}
NOTE: Lenght of each frame shall NOT exceed 8-byte data.
e) Call usb_pipe_iso_write() to write ISO frames
f) Check 'iso_data->frame_num' to determine the number of frames transmitted.
g) Call usb_pipe_close() to close the ISO pipe
For detail information for usage for USB drive, pls refer to usb_test.c
*****************************************************************
5. NOTE
*****************************************************************
1) Read from Interrupt pipe is NOT supported.
2) The length of each ISO frames sent to USB Host must be same as
the maximum packet size of ISO IN endpoint. It is set to 8
bytes now.
3) Don't try to write more than 63 bytes to the Bulk OUT endpoint
from USB Host(PC) each time. The size of Bulk OUT DMA buffer
is only 63-bytes. Sending 64-byte packet will be NAKed
forever!
The root cause of this issue is a UDC hardware bug. The bug
will prevent us from getting a correct data length for the Bulk
OUT transfer unless we make the size of DMA buffer less than
max packet size (64-bytes).
No comments:
Post a Comment