Table of Contents
This chapter currently contains a copy of the old Thomas Milius programming documentation. These have been edited to remove unnecessary information on writing a host driver (information of this can be found in the host driver writing book).
This chapter is provided for historical reference only and will be removed in future versions, use the information provided in other parts of the book in preference to the information contained here which may be out of date or simply inaccurate.
Isochronous transfer has the highest priority at USB. If requests on it are pending it can be done every USB frame. There is no acknowledgement whether the data has been transferred correctly. An isochronous transfer cannot been split up into several transaction, so the size of the data buffer must fit exactly to the data payload size. Note that Isochronous transfers can be only done on devices with normal speed. The frame repeat number must be set to 1.
Bulk transfers have the lowest priority at USB. It is done if free capacity at the USB is available. There is an acknowledgement whether the data has been transferred correctly. The transfer can be split up into several transactions which can be processed over a lot of frames. Note that Bulk transfers can be only done on devices with normal speed. The frame repeat number must be set to 0.
Interrupt Transfers are similar to Bulk transfers but they have a priority immediately beyond Isochronous Transfer at USB. An interval of frames must be given after which the next transfer can be done. In detail this is meaning that if a new request has been set generated by the host software the transfer will be first done after USB frame has reached a value which is less or equal than the value calculated from the last frame number where an interrupt transfer was done at this endpoint by adding the interval of frames. Note that it can happen that a long time distance is passing between two requests. This may be based on a device which is responding with NAKs if there is no data. Therefore the last frame number can't be always taken as the base of calculation. USB module must check whether the last frame number is inside an interval between actual frame number minus repeat interval size and actual frame number. This may lead to a gap in worst case of one repeating interval but this will only happen at slow devices which won't respond regularly and this can be tolerated. There is an acknowledgement whether the data has been transferred correctly. The transfer can be split up into several transactions which can be processed over a lot of frames. If the frame number has been reached where an interrupt request can be processed it should be sorted into the queue of waiting interrupt requests by the frame number of next interval start of this interrupt pipe. Note that Interrupt transfers can be done on devices with low or normal speed.
There are the following other functions:
USB_FastAccessInformation
There are two fundamental data structures used at the communications between the programs and the USB module:
Data buffer structure
Waiting mode structure
Because access to data buffers must be done by the programs on the host, the USB-Module and the USB host controller driver (including. the USB Hardware in some cases) it is stored in memory with public address range like RMA or dynamic areas. It must be therefore allocated/released by special functions. Data buffers are generally owned by one program. The control is passed on to other parts of the USB software. Note that these software is only allowed to change the content of the data buffer but it is never allowed to release the buffer. A data buffer must always been passed back to the program which has allocated it.
To allow the usage of existing data structures inside RISCOS like buffers programs can declare a particular piece of memory from the public address space as an USB data buffer. There are two ways to generate such a buffer. You can use the normal functions and passing them the address of the beginning of the memory of the buffer. In this case only the additional information will be allocated from the memory by the USB_BufferMalloc function. Of course it will calculate the total size of the buffer space as a multiple of the data payload size of the related pipe. You must keep care that the buffer you passed to the function is large enough or you must change the size value. In the other case your application can generate a buffer of the format described below completely itself. However take care that the size is always a multiple of the data pay load size of the pipe you want to use. Of course you can change the buffer address inside the USB buffer structure as you like from request to request for eg implementing a device FS.
The waiting information is included into the buffer structure even the programs shall not try to access it directly but shall always use the according functions. This saves an acknowledgement from the program to the USB module that it has evaluated the result of a request.
The number of bytes in the buffer which are really used should be set to the number of bytes which you are expecting to receive. An error will be generated if you will receive less or more bytes and an according flag has been set. If you are not expecting a fixed size so set this value to zero. It will be left unchanged during the whole transfer. So you are able to compare the received bytes inside the actual position with the expected size. A zero length buffer can be generated by setting the USB_TRANSACTION_EXACT_SIZE flag at request generating. The actual transfer position will be reset to zero automatically if request is started. At the end of the transfer it will pointing exactly one byte behind the received data. After the transfer has been done you can evaluate the data buffer content.
Fill the data into the buffer and set the number of bytes which are really used with the according size. The actual transfer position will be reset to zero automatically if request is started. Note that this value remains unchanged after the transfer has been done. It is granted that actual transfer position is pointing directly to the beginning of the data which has not been sent if an error occurred. A zero length buffer can be generated by setting the number of bytes which are really used to zero and setting the USB_TRANSACTION_EXACT_SIZE flag at request generating.
Table 9.1. Format of data buffer structure
Position | Data type | Description |
---|---|---|
0x00 | unsigned long | Pointer to begin of buffer data. If data is included in this structure it will point behind the waiting structure else it must point to the piece of memory which is used as data buffer. |
0x04 | unsigned long | Allocated data buffer size in Bytes. If the offset is added to this value you are getting the whole size of the buffer structure. |
0x08 | unsigned long | Number of Bytes in the buffer which are really used for data in the moment. |
0x0C | unsigned long | Actual position of data transfer. |
0x10 | unsigned long | Number of the frame in which the transaction has been completed. Must be filled by the USB host controller driver. |
0x14 | unsigned long | Data toggle as the transaction has been completed. Must be filled by the USB host controller driver. |
0x18 | various. Size may vary from version to version | Waiting structure. Exact structure see below. |
... | At later version here there may be additional information located. | |
(0x18 + Size of Waiting Structure) word allocated | data of arbitrary size word aligned. Only if data buffer memory is hold inside this buffer. Not used if this memory is located elsewhere. |
Programs should only set the size (sizeof(waiting) in C), the waiting mode and additional parameters belonging to this mode. All other operations are done internally the USB-module. Note that a copy of your waiting structure is placed inside one buffer of a request. The setting of the size is needed to grant future compatibility. If an application mallocs a new buffer for USB requests the size of the waiting structure is automatically initialised.
Table 9.2. Format of Waiting structure
Position | Data type | Description |
---|---|---|
0x00 | int | Size of this structure (actual 0x3C Bytes). |
0x04 | int | Waiting Mode |
0x08 | int | Result |
0x0C | int | Flag that shows that no result has been received. That means that the waiting is still going on. |
Table 9.3. additional data for WAITING_TYPE_MESSAGE
Position | Data type | Description |
---|---|---|
0x10 | Pointer | Pointer to WIMP message block located in common address space. |
0x14 | int | Destination task handle |
0x18 | int | Icon handle |
Table 9.4. Additional data for WAITING_TYPE_SWI
Position | Data type | Description |
---|---|---|
0x10 | int | Number of the SWI to call |
0x14-0x3C | int | An array of 10 register values passed to the SWI call. |
Table 9.5. Additional data for WAITING_TYPE_APCS
Position | Data type | Description |
---|---|---|
0x10 | Pointer | Pointer to APCS-Function located in common address space. |
0x14-0x24 | int | An array of 4 register values passed to the APCS function call. |
Please note that in all modes except WAITING_TYPE_RETURN the calling program is only informed that a request has been finished. It will be not informed whether the operation has been successful. It has to use USB_RequestGetState to get this information.