2 * Copyright (c) 2011 Jan Vesely
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /** @addtogroup drvusbuhcihc
39 #include <usb/debug.h>
41 #include <usb/host/utils/malloc32.h>
43 #include "link_pointer.h"
44 #include "transfer_descriptor.h"
46 /** Initialize Transfer Descriptor
48 * @param[in] instance Memory place to initialize.
49 * @param[in] err_count Number of retries hc should attempt.
50 * @param[in] size Size of data source.
51 * @param[in] toggle Value of toggle bit.
52 * @param[in] iso True if TD represents Isochronous transfer.
53 * @param[in] low_speed Target device's speed.
54 * @param[in] target Address and endpoint receiving the transfer.
55 * @param[in] pid Packet identification (SETUP, IN or OUT).
56 * @param[in] buffer Source of data.
57 * @param[in] next Net TD in transaction.
60 * Uses a mix of supplied and default values.
62 * - all TDs have vertical flag set (makes transfers to endpoints atomic)
63 * - in the error field only active it is set
64 * - if the packet uses PID_IN and is not isochronous SPD is set
66 * Dumps 8 bytes of buffer if PID_SETUP is used.
68 void td_init(td_t
*instance
, int err_count
, size_t size
, bool toggle
, bool iso
,
69 bool low_speed
, usb_target_t target
, usb_packet_id pid
, const void *buffer
,
74 assert((pid
== USB_PID_SETUP
) || (pid
== USB_PID_IN
)
75 || (pid
== USB_PID_OUT
));
77 const uint32_t next_pa
= addr_to_phys(next
);
78 assert((next_pa
& LINK_POINTER_ADDRESS_MASK
) == next_pa
);
81 | LINK_POINTER_VERTICAL_FLAG
82 | (next_pa
? next_pa
: LINK_POINTER_TERMINATE_FLAG
);
85 | ((err_count
& TD_STATUS_ERROR_COUNT_MASK
)
86 << TD_STATUS_ERROR_COUNT_POS
)
87 | (low_speed
? TD_STATUS_LOW_SPEED_FLAG
: 0)
88 | (iso
? TD_STATUS_ISOCHRONOUS_FLAG
: 0)
89 | TD_STATUS_ERROR_ACTIVE
;
91 if (pid
== USB_PID_IN
&& !iso
) {
92 instance
->status
|= TD_STATUS_SPD_FLAG
;
96 | (((size
- 1) & TD_DEVICE_MAXLEN_MASK
) << TD_DEVICE_MAXLEN_POS
)
97 | (toggle
? TD_DEVICE_DATA_TOGGLE_ONE_FLAG
: 0)
98 | ((target
.address
& TD_DEVICE_ADDRESS_MASK
)
99 << TD_DEVICE_ADDRESS_POS
)
100 | ((target
.endpoint
& TD_DEVICE_ENDPOINT_MASK
)
101 << TD_DEVICE_ENDPOINT_POS
)
102 | ((pid
& TD_DEVICE_PID_MASK
) << TD_DEVICE_PID_POS
);
104 instance
->buffer_ptr
= addr_to_phys(buffer
);
106 usb_log_debug2("Created TD(%p): %X:%X:%X:%X(%p).\n",
107 instance
, instance
->next
, instance
->status
, instance
->device
,
108 instance
->buffer_ptr
, buffer
);
109 td_print_status(instance
);
110 if (pid
== USB_PID_SETUP
) {
111 usb_log_debug2("SETUP BUFFER: %s\n",
112 usb_debug_str_buffer(buffer
, 8, 8));
116 /** Convert TD status into standard error code
118 * @param[in] instance TD structure to use.
119 * @return Error code.
121 errno_t
td_status(const td_t
*instance
)
125 /* This is hc internal error it should never be reported. */
126 if ((instance
->status
& TD_STATUS_ERROR_BIT_STUFF
) != 0)
129 /* CRC or timeout error, like device not present or bad data,
130 * it won't be reported unless err count reached zero */
131 if ((instance
->status
& TD_STATUS_ERROR_CRC
) != 0)
134 /* HC does not end transactions on these, it should never be reported */
135 if ((instance
->status
& TD_STATUS_ERROR_NAK
) != 0)
138 /* Buffer overrun or underrun */
139 if ((instance
->status
& TD_STATUS_ERROR_BUFFER
) != 0)
142 /* Device babble is something serious */
143 if ((instance
->status
& TD_STATUS_ERROR_BABBLE
) != 0)
146 /* Stall might represent err count reaching zero or stall response from
147 * the device. If err count reached zero, one of the above is reported*/
148 if ((instance
->status
& TD_STATUS_ERROR_STALLED
) != 0)
154 /** Print values in status field (dw1) in a human readable way.
156 * @param[in] instance TD structure to use.
158 void td_print_status(const td_t
*instance
)
161 const uint32_t s
= instance
->status
;
162 usb_log_debug2("TD(%p) status(%#" PRIx32
"):%s %d,%s%s%s%s%s%s%s%s%s%s%s %zu.\n",
163 instance
, instance
->status
,
164 (s
& TD_STATUS_SPD_FLAG
) ? " SPD," : "",
165 (s
>> TD_STATUS_ERROR_COUNT_POS
) & TD_STATUS_ERROR_COUNT_MASK
,
166 (s
& TD_STATUS_LOW_SPEED_FLAG
) ? " LOW SPEED," : "",
167 (s
& TD_STATUS_ISOCHRONOUS_FLAG
) ? " ISOCHRONOUS," : "",
168 (s
& TD_STATUS_IOC_FLAG
) ? " IOC," : "",
169 (s
& TD_STATUS_ERROR_ACTIVE
) ? " ACTIVE," : "",
170 (s
& TD_STATUS_ERROR_STALLED
) ? " STALLED," : "",
171 (s
& TD_STATUS_ERROR_BUFFER
) ? " BUFFER," : "",
172 (s
& TD_STATUS_ERROR_BABBLE
) ? " BABBLE," : "",
173 (s
& TD_STATUS_ERROR_NAK
) ? " NAK," : "",
174 (s
& TD_STATUS_ERROR_CRC
) ? " CRC/TIMEOUT," : "",
175 (s
& TD_STATUS_ERROR_BIT_STUFF
) ? " BIT_STUFF," : "",
176 (s
& TD_STATUS_ERROR_RESERVED
) ? " RESERVED," : "",
177 td_act_size(instance
)