Changes in / [f58154c5:b2995c3] in mainline
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
.bzrignore
rf58154c5 rb2995c3 53 53 ./uspace/app/klog/klog 54 54 ./uspace/app/lsusb/lsusb 55 ./uspace/app/mkbd/mkbd56 55 ./uspace/app/mkfat/mkfat 57 56 ./uspace/app/netstart/netstart -
uspace/drv/ohci/batch.c
rf58154c5 rb2995c3 44 44 #include "hw_struct/transfer_descriptor.h" 45 45 46 /** OHCI specific data required for USB transfer */47 46 typedef struct ohci_transfer_batch { 48 /** Endpoint descriptor of the target endpoint. */49 47 ed_t *ed; 50 /** List of TDs needed for the transfer */51 48 td_t **tds; 52 /** Number of TDs used by the transfer */53 49 size_t td_count; 54 /** Dummy TD to be left at the ED and used by the next transfer */55 50 size_t leave_td; 56 /** Data buffer, must be accessible byb the OHCI hw. */ 57 void *device_buffer; 51 char *device_buffer; 58 52 } ohci_transfer_batch_t; 59 /*----------------------------------------------------------------------------*/ 60 static void batch_control(usb_transfer_batch_t *instance, 61 usb_direction_t data_dir, usb_direction_t status_dir); 62 static void batch_data(usb_transfer_batch_t *instance); 63 /*----------------------------------------------------------------------------*/ 64 /** Safely destructs ohci_transfer_batch_t structure 65 * 66 * @param[in] ohci_batch Instance to destroy. 67 */ 53 68 54 static void ohci_transfer_batch_dispose(void *ohci_batch) 69 55 { … … 83 69 } 84 70 /*----------------------------------------------------------------------------*/ 85 /** Allocate memory initialize internal structures 86 * 87 * @param[in] fun DDF function to pass to callback. 88 * @param[in] ep Communication target 89 * @param[in] buffer Data source/destination. 90 * @param[in] buffer_size Size of the buffer. 91 * @param[in] setup_buffer Setup data source (if not NULL) 92 * @param[in] setup_size Size of setup_buffer (should be always 8) 93 * @param[in] func_in function to call on inbound transfer completion 94 * @param[in] func_out function to call on outbound transfer completion 95 * @param[in] arg additional parameter to func_in or func_out 96 * @return Valid pointer if all structures were successfully created, 97 * NULL otherwise. 98 * 99 * Allocates and initializes structures needed by the OHCI hw for the transfer. 100 */ 71 static void batch_control(usb_transfer_batch_t *instance, 72 usb_direction_t data_dir, usb_direction_t status_dir); 73 static void batch_data(usb_transfer_batch_t *instance); 74 /*----------------------------------------------------------------------------*/ 101 75 usb_transfer_batch_t * batch_get(ddf_fun_t *fun, endpoint_t *ep, 102 76 char *buffer, size_t buffer_size, char* setup_buffer, size_t setup_size, … … 133 107 } 134 108 135 /* We need an extra place for TDthat is currently assigned to hcd_ep*/109 /* we need one extra place for td that is currently assigned to hcd_ep*/ 136 110 data->tds = calloc(sizeof(td_t*), data->td_count + 1); 137 111 CHECK_NULL_DISPOSE_RETURN(data->tds, 138 112 "Failed to allocate transfer descriptors.\n"); 139 113 140 /* Add TD left over by the previous transfer */141 114 data->tds[0] = hcd_ep->td; 142 115 data->leave_td = 0; … … 150 123 data->ed = hcd_ep->ed; 151 124 152 /* NOTE: OHCI is capable of handling buffer that crosses page boundaries153 * it is, however, not capable of handling buffer that occupies more154 * than two pages (the first page is computed using start pointer, the155 * other using the end pointer) */156 125 if (setup_size + buffer_size > 0) { 157 126 data->device_buffer = malloc32(setup_size + buffer_size); … … 166 135 } 167 136 /*----------------------------------------------------------------------------*/ 168 /** Check batch TDs' status.169 *170 * @param[in] instance Batch structure to use.171 * @return False, if there is an active TD, true otherwise.172 *173 * Walk all TDs (usually there is just one). Stop with false if there is an174 * active TD. Stop with true if an error is found. Return true if the walk175 * completes with the last TD.176 */177 137 bool batch_is_complete(usb_transfer_batch_t *instance) 178 138 { … … 180 140 ohci_transfer_batch_t *data = instance->private_data; 181 141 assert(data); 142 size_t tds = data->td_count; 182 143 usb_log_debug("Batch(%p) checking %zu td(s) for completion.\n", 183 instance, data->td_count);144 instance, tds); 184 145 usb_log_debug("ED: %x:%x:%x:%x.\n", 185 146 data->ed->status, data->ed->td_head, data->ed->td_tail, … … 187 148 size_t i = 0; 188 149 instance->transfered_size = instance->buffer_size; 189 for (; i < data->td_count; ++i) {150 for (; i < tds; ++i) { 190 151 assert(data->tds[i] != NULL); 191 152 usb_log_debug("TD %zu: %x:%x:%x:%x.\n", i, … … 212 173 assert(hcd_ep); 213 174 hcd_ep->td = data->tds[i]; 214 assert(i > 0); 215 for (--i;i < data->td_count; ++i) 216 instance->transfered_size -= td_remain_size(data->tds[i]); 175 if (i > 0) 176 instance->transfered_size -= td_remain_size(data->tds[i - 1]); 217 177 218 178 /* Clear possible ED HALT */ 219 179 data->ed->td_head &= ~ED_TDHEAD_HALTED_FLAG; 220 constuint32_t pa = addr_to_phys(hcd_ep->td);180 uint32_t pa = addr_to_phys(hcd_ep->td); 221 181 assert(pa == (data->ed->td_head & ED_TDHEAD_PTR_MASK)); 222 182 assert(pa == (data->ed->td_tail & ED_TDTAIL_PTR_MASK)); … … 225 185 } 226 186 /*----------------------------------------------------------------------------*/ 227 /** Starts execution of the TD list228 *229 * @param[in] instance Batch structure to use230 */231 187 void batch_commit(usb_transfer_batch_t *instance) 232 188 { … … 237 193 } 238 194 /*----------------------------------------------------------------------------*/ 239 /** Prepares control write transfer.240 *241 * @param[in] instance Batch structure to use.242 *243 * Uses generic control transfer using direction OUT(data stage) and244 * IN(status stage).245 */246 195 void batch_control_write(usb_transfer_batch_t *instance) 247 196 { … … 254 203 } 255 204 /*----------------------------------------------------------------------------*/ 256 /** Prepares control read transfer.257 *258 * @param[in] instance Batch structure to use.259 *260 * Uses generic control transfer using direction IN(data stage) and261 * OUT(status stage).262 */263 205 void batch_control_read(usb_transfer_batch_t *instance) 264 206 { … … 269 211 } 270 212 /*----------------------------------------------------------------------------*/ 271 /** Prepare interrupt in transfer.272 *273 * @param[in] instance Batch structure to use.274 *275 * Data transfer.276 */277 213 void batch_interrupt_in(usb_transfer_batch_t *instance) 278 214 { … … 283 219 } 284 220 /*----------------------------------------------------------------------------*/ 285 /** Prepare interrupt out transfer.286 *287 * @param[in] instance Batch structure to use.288 *289 * Data transfer.290 */291 221 void batch_interrupt_out(usb_transfer_batch_t *instance) 292 222 { … … 299 229 } 300 230 /*----------------------------------------------------------------------------*/ 301 /** Prepare bulk in transfer.302 *303 * @param[in] instance Batch structure to use.304 *305 * Data transfer.306 */307 231 void batch_bulk_in(usb_transfer_batch_t *instance) 308 232 { … … 313 237 } 314 238 /*----------------------------------------------------------------------------*/ 315 /** Prepare bulk out transfer.316 *317 * @param[in] instance Batch structure to use.318 *319 * Data transfer.320 */321 239 void batch_bulk_out(usb_transfer_batch_t *instance) 322 240 { … … 329 247 } 330 248 /*----------------------------------------------------------------------------*/ 331 /** Prepare generic control transfer 332 * 333 * @param[in] instance Batch structure to use. 334 * @param[in] data_dir Direction to use for data stage. 335 * @param[in] status_dir Direction to use for status stage. 336 * 337 * Setup stage with toggle 0 and direction BOTH(SETUP_PID) 338 * Data stage with alternating toggle and direction supplied by parameter. 339 * Status stage with toggle 1 and direction supplied by parameter. 340 */ 249 ed_t * batch_ed(usb_transfer_batch_t *instance) 250 { 251 assert(instance); 252 ohci_transfer_batch_t *data = instance->private_data; 253 assert(data); 254 return data->ed; 255 } 256 /*----------------------------------------------------------------------------*/ 341 257 void batch_control(usb_transfer_batch_t *instance, 342 258 usb_direction_t data_dir, usb_direction_t status_dir) … … 387 303 } 388 304 /*----------------------------------------------------------------------------*/ 389 /** Prepare generic data transfer390 *391 * @param[in] instance Batch structure to use.392 *393 * Direction is supplied by the associated ep and toggle is maintained by the394 * OHCI hw in ED.395 */396 305 void batch_data(usb_transfer_batch_t *instance) 397 306 { -
uspace/drv/ohci/batch.h
rf58154c5 rb2995c3 41 41 #include <usb/host/batch.h> 42 42 43 #include "hw_struct/endpoint_descriptor.h" 44 43 45 usb_transfer_batch_t * batch_get( 44 46 ddf_fun_t *fun, endpoint_t *ep, char *buffer, size_t size, … … 63 65 64 66 void batch_bulk_out(usb_transfer_batch_t *instance); 67 68 ed_t * batch_ed(usb_transfer_batch_t *instance); 65 69 #endif 66 70 /** -
uspace/drv/ohci/endpoint_list.c
rf58154c5 rb2995c3 34 34 #include <errno.h> 35 35 #include <usb/debug.h> 36 #include <arch/barrier.h>37 36 38 37 #include "endpoint_list.h" … … 44 43 * @return Error code 45 44 * 46 * Allocates memory for internal ed_t structure.45 * Allocates memory for internal qh_t structure. 47 46 */ 48 47 int endpoint_list_init(endpoint_list_t *instance, const char *name) … … 69 68 * @param[in] instance List to lead. 70 69 * @param[in] next List to append. 71 * 72 * Does not check whether this replaces an existing list. 70 * @return Error code 71 * 72 * Does not check whether this replaces an existing list . 73 73 */ 74 74 void endpoint_list_set_next(endpoint_list_t *instance, endpoint_list_t *next) … … 79 79 } 80 80 /*----------------------------------------------------------------------------*/ 81 /** Add endpoint to the list and queue. 82 * 83 * @param[in] instance List to use. 84 * @param[in] endpoint Endpoint to add. 81 /** Submit transfer endpoint to the list and queue. 82 * 83 * @param[in] instance List to use. 84 * @param[in] endpoint Transfer endpoint to submit. 85 * @return Error code 85 86 * 86 87 * The endpoint is added to the end of the list and queue. … … 98 99 /* Add to the hardware queue. */ 99 100 if (list_empty(&instance->endpoint_list)) { 100 /* There are no active EDs*/101 /* There is nothing scheduled */ 101 102 last_ed = instance->list_head; 102 103 } else { 103 /* There are active EDs, get the last one*/104 /* There is something scheduled */ 104 105 hcd_endpoint_t *last = list_get_instance( 105 106 instance->endpoint_list.prev, hcd_endpoint_t, link); 106 assert(last);107 107 last_ed = last->ed; 108 108 } 109 /* Keep link */109 /* keep link */ 110 110 hcd_ep->ed->next = last_ed->next; 111 /* Make sure ED is written to the memory */112 write_barrier();113 114 /* Add ed to the hw queue */115 111 ed_append_ed(last_ed, hcd_ep->ed); 116 /* Make sure ED is updated */ 117 write_barrier();118 119 /* Add to the swlist */112 113 asm volatile ("": : :"memory"); 114 115 /* Add to the driver list */ 120 116 list_append(&hcd_ep->link, &instance->endpoint_list); 121 117 … … 133 129 } 134 130 /*----------------------------------------------------------------------------*/ 135 /** Remove endpoint from the list and queue. 136 * 137 * @param[in] instance List to use. 138 * @param[in] endpoint Endpoint to remove. 131 #if 0 132 /** Create list for finished endpoints. 133 * 134 * @param[in] instance List to use. 135 * @param[in] done list to fill 136 */ 137 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done) 138 { 139 assert(instance); 140 assert(done); 141 142 fibril_mutex_lock(&instance->guard); 143 usb_log_debug2("Checking list %s for completed endpointes(%d).\n", 144 instance->name, list_count(&instance->endpoint_list)); 145 link_t *current = instance->endpoint_list.next; 146 while (current != &instance->endpoint_list) { 147 link_t *next = current->next; 148 hcd_endpoint_t *endpoint = 149 list_get_instance(current, hcd_endpoint_t, link); 150 151 if (endpoint_is_complete(endpoint)) { 152 /* Save for post-processing */ 153 endpoint_list_remove_endpoint(instance, endpoint); 154 list_append(current, done); 155 } 156 current = next; 157 } 158 fibril_mutex_unlock(&instance->guard); 159 } 160 /*----------------------------------------------------------------------------*/ 161 /** Walk the list and abort all endpointes. 162 * 163 * @param[in] instance List to use. 164 */ 165 void endpoint_list_abort_all(endpoint_list_t *instance) 166 { 167 fibril_mutex_lock(&instance->guard); 168 while (!list_empty(&instance->endpoint_list)) { 169 link_t *current = instance->endpoint_list.next; 170 hcd_endpoint_t *endpoint = 171 list_get_instance(current, hcd_endpoint_t, link); 172 endpoint_list_remove_endpoint(instance, endpoint); 173 hcd_endpoint_finish_error(endpoint, EIO); 174 } 175 fibril_mutex_unlock(&instance->guard); 176 } 177 #endif 178 /*----------------------------------------------------------------------------*/ 179 /** Remove a transfer endpoint from the list and queue. 180 * 181 * @param[in] instance List to use. 182 * @param[in] endpoint Transfer endpoint to remove. 183 * @return Error code 184 * 185 * Does not lock the transfer list, caller is responsible for that. 139 186 */ 140 187 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep) … … 165 212 assert((prev_ed->next & ED_NEXT_PTR_MASK) == addr_to_phys(hcd_ep->ed)); 166 213 prev_ed->next = hcd_ep->ed->next; 167 /* Make sure ED is updated */ 168 write_barrier(); 169 214 215 asm volatile ("": : :"memory"); 170 216 usb_log_debug("HCD EP(%p) removed (%s) from %s, next %x.\n", 171 217 hcd_ep, qpos, instance->name, hcd_ep->ed->next); -
uspace/drv/ohci/endpoint_list.h
rf58154c5 rb2995c3 41 41 #include "utils/malloc32.h" 42 42 43 /** Structure maintains both OHCI queue and software list of active endpoints.*/ 44 typedef struct endpoint_list 45 { 46 /** Guard against add/remove races */ 43 typedef struct endpoint_list { 47 44 fibril_mutex_t guard; 48 /** OHCI hw structure at the beginning of the queue */49 45 ed_t *list_head; 50 /** Physical address of the first(dummy) ED */51 46 uint32_t list_head_pa; 52 /** Assigned name, provides nicer debug output */53 47 const char *name; 54 /** Sw list of all active EDs */55 48 link_t endpoint_list; 56 49 } endpoint_list_t; … … 60 53 * @param[in] instance Memory place to use. 61 54 * 62 * Frees memory of the internal ed_t structure.55 * Frees memory for internal qh_t structure. 63 56 */ 64 57 static inline void endpoint_list_fini(endpoint_list_t *instance) … … 75 68 76 69 void endpoint_list_remove_ep(endpoint_list_t *instance, hcd_endpoint_t *hcd_ep); 70 #if 0 71 void endpoint_list_remove_finished(endpoint_list_t *instance, link_t *done); 72 73 void endpoint_list_abort_all(endpoint_list_t *instance); 74 #endif 77 75 #endif 78 76 /** -
uspace/drv/ohci/hc.c
rf58154c5 rb2995c3 293 293 rh_interrupt(&instance->rh); 294 294 295 295 296 if (status & I_WDH) { 296 297 fibril_mutex_lock(&instance->guard); … … 315 316 fibril_mutex_unlock(&instance->guard); 316 317 } 317 318 if (status & I_UE) {319 hc_start_hw(instance);320 }321 322 318 } 323 319 /*----------------------------------------------------------------------------*/ … … 454 450 { 455 451 assert(instance); 452 456 453 #define SETUP_ENDPOINT_LIST(type) \ 457 454 do { \ … … 461 458 usb_log_error("Failed(%d) to setup %s endpoint list.\n", \ 462 459 ret, name); \ 463 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \460 endpoint_list_fini(&instance->lists[USB_TRANSFER_ISOCHRONOUS]); \ 464 461 endpoint_list_fini(&instance->lists[USB_TRANSFER_INTERRUPT]); \ 465 462 endpoint_list_fini(&instance->lists[USB_TRANSFER_CONTROL]); \ -
uspace/drv/ohci/hcd_endpoint.h
rf58154c5 rb2995c3 37 37 #include <assert.h> 38 38 #include <adt/list.h> 39 39 40 #include <usb/host/endpoint.h> 40 41 … … 42 43 #include "hw_struct/transfer_descriptor.h" 43 44 44 typedef struct hcd_endpoint 45 { 45 typedef struct hcd_endpoint { 46 46 ed_t *ed; 47 47 td_t *td; -
uspace/drv/ohci/hw_struct/transfer_descriptor.c
rf58154c5 rb2995c3 44 44 assert(instance); 45 45 bzero(instance, sizeof(td_t)); 46 instance-> status = 046 instance-> status = 0 47 47 | ((dp[dir] & TD_STATUS_DP_MASK) << TD_STATUS_DP_SHIFT) 48 48 | ((CC_NOACCESS2 & TD_STATUS_CC_MASK) << TD_STATUS_CC_SHIFT); -
uspace/drv/ohci/hw_struct/transfer_descriptor.h
rf58154c5 rb2995c3 41 41 #include "completion_codes.h" 42 42 43 /* OHCI TDs can handle up to 8KB buffers, however, it can use max 2 pages. 44 * Using 4KB buffers guarantees the page count condition. 45 * (OHCI assumes 4KB pages) */ 46 #define OHCI_TD_MAX_TRANSFER (4 * 1024) 43 /* OHCI TDs can handle up to 8KB buffers */ 44 #define OHCI_TD_MAX_TRANSFER (8 * 1024) 47 45 48 46 typedef struct td { -
uspace/drv/uhci-hcd/batch.c
rf58154c5 rb2995c3 45 45 #define DEFAULT_ERROR_COUNT 3 46 46 47 /** UHCI specific data required for USB transfer */48 47 typedef struct uhci_transfer_batch { 49 /** Queue head50 * This QH is used to maintain UHCI schedule structure and the element51 * pointer points to the first TD of this batch.52 */53 48 qh_t *qh; 54 /** List of TDs needed for the transfer */55 49 td_t *tds; 56 /** Number of TDs used by the transfer */50 void *device_buffer; 57 51 size_t td_count; 58 /** Data buffer, must be accessible by the UHCI hw */59 void *device_buffer;60 52 } uhci_transfer_batch_t; 61 53 /*----------------------------------------------------------------------------*/ 54 static void uhci_transfer_batch_dispose(void *uhci_batch) 55 { 56 uhci_transfer_batch_t *instance = uhci_batch; 57 assert(instance); 58 free32(instance->device_buffer); 59 free(instance); 60 } 61 /*----------------------------------------------------------------------------*/ 62 62 63 static void batch_control(usb_transfer_batch_t *instance, 63 64 usb_packet_id data_stage, usb_packet_id status_stage); 64 65 static void batch_data(usb_transfer_batch_t *instance, usb_packet_id pid); 65 /*----------------------------------------------------------------------------*/ 66 /** Safely destructs uhci_transfer_batch_t structure 67 * 68 * @param[in] uhci_batch Instance to destroy. 69 */ 70 static void uhci_transfer_batch_dispose(void *uhci_batch) 71 { 72 uhci_transfer_batch_t *instance = uhci_batch; 73 assert(instance); 74 free32(instance->device_buffer); 75 free(instance); 76 } 77 /*----------------------------------------------------------------------------*/ 66 78 67 /** Allocate memory and initialize internal data structure. 79 68 * … … 184 173 instance->error = td_status(&data->tds[i]); 185 174 if (instance->error != EOK) { 186 usb_log_debug("Batch(%p) found error TD(%zu):%" 187 PRIx32 ".\n",instance, i, data->tds[i].status);175 usb_log_debug("Batch(%p) found error TD(%zu):%" PRIx32 ".\n", 176 instance, i, data->tds[i].status); 188 177 td_print_status(&data->tds[i]); 189 178 … … 408 397 /*----------------------------------------------------------------------------*/ 409 398 /** Provides access to QH data structure. 410 *411 399 * @param[in] instance Batch pointer to use. 412 400 * @return Pointer to the QH used by the batch. -
uspace/drv/uhci-hcd/transfer_list.c
rf58154c5 rb2995c3 34 34 #include <errno.h> 35 35 #include <usb/debug.h> 36 #include <arch/barrier.h>37 36 38 37 #include "transfer_list.h" … … 72 71 * @param[in] instance Memory place to use. 73 72 * 74 * Frees memory of theinternal qh_t structure.73 * Frees memory for internal qh_t structure. 75 74 */ 76 75 void transfer_list_fini(transfer_list_t *instance) … … 127 126 assert((pa & LINK_POINTER_ADDRESS_MASK) == pa); 128 127 129 /* Make sure all data in the batch are written */130 write_barrier();131 132 128 /* keep link */ 133 129 batch_qh(batch)->next = last_qh->next; 134 130 qh_set_next_qh(last_qh, batch_qh(batch)); 135 131 136 /* Make sure the pointer is updated */ 137 write_barrier(); 132 asm volatile ("": : :"memory"); 138 133 139 134 /* Add to the driver list */ … … 227 222 == addr_to_phys(batch_qh(batch))); 228 223 prev_qh->next = batch_qh(batch)->next; 229 230 /* Make sure the pointer is updated */ 231 write_barrier(); 232 224 asm volatile ("": : :"memory"); 233 225 /* Remove from the batch list */ 234 226 list_remove(&batch->link); -
uspace/drv/uhci-hcd/utils/malloc32.h
rf58154c5 rb2995c3 74 74 if (size <= SLAB_ELEMENT_SIZE) 75 75 return slab_malloc_g(); 76 usb_log_warning("Requested %zu bytes, current allocator can't handle " 77 "that amount, pray that the standard malloc will suffice.", size); 76 assert(false); 78 77 return memalign(UHCI_STRCUTURES_ALIGNMENT, size); 79 78 } -
uspace/drv/uhci-rhd/port.c
rf58154c5 rb2995c3 227 227 while (uhci_port_read_status(port) & STATUS_IN_RESET); 228 228 } 229 /* PIO delay, should not be longer than 3ms as the device might230 * enter suspend state. */231 229 udelay(10); 232 230 /* Enable the port. */ 233 231 uhci_port_set_enabled(port, true); 232 233 /* Reset recovery period, 234 * devices do not have to respond during this period 235 */ 236 async_usleep(10000); 234 237 return EOK; 235 238 } -
uspace/lib/usbdev/src/hub.c
rf58154c5 rb2995c3 41 41 #include <assert.h> 42 42 #include <usb/debug.h> 43 #include <time.h>44 43 45 44 /** How much time to wait between attempts to register endpoint 0:0. … … 219 218 220 219 int rc; 221 struct timeval start_time;222 223 rc = gettimeofday(&start_time, NULL);224 if (rc != EOK) {225 return rc;226 }227 220 228 221 rc = usb_hc_connection_open(&hc_conn); … … 271 264 } 272 265 } while (rc != EOK); 273 struct timeval end_time;274 275 rc = gettimeofday(&end_time, NULL);276 if (rc != EOK) {277 goto leave_release_default_address;278 }279 280 /* According to the USB spec part 9.1.2 host allows 100ms time for281 * the insertion process to complete. According to 7.1.7.1 this is the282 * time between attach detected and port reset. However, the setup done283 * above might use much of this time so we should only wait to fill284 * up the 100ms quota*/285 suseconds_t elapsed = tv_sub(&end_time, &start_time);286 if (elapsed < 100000) {287 async_usleep(100000 - elapsed);288 }289 266 290 267 /* … … 296 273 goto leave_release_default_address; 297 274 } 298 /* USB spec 7.1.7.1: The USB System Software guarantees a minimum of299 * 10ms for reset recovery. Device response to any bus transactions300 * addressed to the default device address during the reset recovery301 * time is undefined.302 */303 async_usleep(10000);304 275 305 276 rc = usb_pipe_probe_default_control(&ctrl_pipe);
Note:
See TracChangeset
for help on using the changeset viewer.