Table of Contents
Every device in the USB system has a set of endpoints. An endpoint is a unique identifier on a device which is used to create a path for data to flow over (see section 5.3.1 (page 32) in the USB Specification version 1.1). An endpoint has a unique identifying address. Each endpoint may either be used for input or output except the control endpoint which is bidirectional.
Each endpoint has an address which is a bitfield containing its USB address and flags to specify direction.
Table 4.1. Endpoint address bitfield
Bit | Definition | Value | Description |
---|---|---|---|
0-29 | USB Endpoint number | ||
30 | USB_PIPE_ADDRESS_BOTH | 0 | Bit 31 determines direction |
1 | Bidirectional | ||
31 | USB_PIPE_ADDRESS_IN | 0 | OUT endpoint |
1 | IN endpoint |
If bit 30 (USB_PIPE_ADDRESS_BOTH) is set then the endpoint is bi-directional and bit 31 (USB_PIPE_ADDRESS_IN) should not be examined.
Endpoint address 0 represents the special control endpoint. The control endpoint is unique in being bi-directional i.e. pipes attached to this endpoint can be read and written to. This requires some special consideration when performing transactions (see Chapter 8). The USB specification defines a standard set of transactions that may be performed on this endpoint to obtain device information and change the devices configuration. Every device has a control endpoint and must support the minimum set of device descriptors (see section 9.3 (page 183) in the USB Specification version 1.1
A pipe is a communication channel between a driver and a specified endpoint on a device.
It is established by calling usb_pipe_open (USB_PipeOpen (SWI&5538B)) with the endpoint the driver wishes to attach the pipe to. The pipe can either be opened exclusively which is the default behaviour or may be shared (more than one pipe per endpoint may be opened).
A pipe should be closed when the driver no longer wishes to perform transactions through it. This is achieved using usb_pipe_close (USB_PipeClose (SWI&5538C)) with the specified pipe.
A pipe may be cleared, i.e. all transactions removed, using usb_pipe_clear (USB_PipeClear (SWI&5538D)) with the specified pipe.
A pipe may become halted from either an error condition from a failed transaction or by calling usb_pipe_halt(USB_PipeHalt (SWI&5538E)) with the specified pipe. Once a pipe is in the halted state a driver should resolve the error condition and clear the pipe which will return the pipe to the active state and allow transactions to be processed once more.
A control pipe has several special properties that differentiate it from a normal pipe, including it's bi-directionality and that in normal operation it cannot be halted.
A pipe on the control endpoint should always be opened shared to allow other drivers access to the configuration and control information of a device.
A halt condition from a transaction on a control pipe means that the transaction was not understood or not supported by the device but does not halt the pipe.
Example 4.1. Obtaining a control pipe
This example shows how to obtain a default pipe given a controller name and device number. These are typically obtained from the information in a new device message, usually obtained when the device is found using usb_devmgr_find_free(USBLib_DevMgrFindFree (SWI &56340)) see Chapter 3 for more details.
This example is identical in function to the one show in Example 3.2.
static usb_pipe_t* get_default_pipe(const char *controller_name, unsigned long device_number) { int result; void *hc_ref; struct usb_device_s* dev_ref; struct usb_endpoint_s* control_ep; usb_pipe_t* control_pipe; hc_ref = usb_find_object(NULL, (unsigned long)controller_name, USB_REFERENCE_CONTROLLER, 0, NULL, &result); if (result != USB_RESULT_OK) { printf("failed to find host-controller %s\n", dev->controller_name); return NULL; } dev_ref = usb_find_device_ref(device_number, hc_ref); if (dev_ref == NULL) { fprintf(stderr, "failed to find device reference\n"); return NULL; } /* obtain control pipe */ control_pipe = usb_get_default_pipe(dev_ref, dev_ref->hostcontroller, &control_ep); if (control_pipe == NULL) { fprintf(stderr, "failed to open default pipe\n"); } return control_pipe; } |