NUC472_NUC442_BSP V3.03.004
The Board Support Package for NUC472/NUC442
UmasTransport.c
Go to the documentation of this file.
1/* Driver for USB Mass Storage compliant devices
2 *
3 * $Id: transport.c,v 1.38 2000/11/21 00:52:10 mdharm Exp $
4 *
5 * Current development and maintenance by:
6 * (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net)
7 *
8 * Developed with the assistance of:
9 * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org)
10 * (c) 2000 Stephen J. Gowdy (SGowdy@lbl.gov)
11 *
12 * Initial work by:
13 * (c) 1999 Michael Gee (michael@linuxspecific.com)
14 *
15 * This driver is based on the 'USB Mass Storage Class' document. This
16 * describes in detail the protocol used to communicate with such
17 * devices. Clearly, the designers had SCSI and ATAPI commands in
18 * mind when they created this document. The commands are all very
19 * similar to commands in the SCSI-II and ATAPI specifications.
20 *
21 * It is important to note that in a number of cases this class
22 * exhibits class-specific exemptions from the USB specification.
23 * Notably the usage of NAK, STALL and ACK differs from the norm, in
24 * that they are used to communicate wait, failed and OK on commands.
25 *
26 * Also, for certain devices, the interrupt endpoint is used to convey
27 * status of a command.
28 *
29 * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more
30 * information about this driver.
31 *
32 * This program is free software; you can redistribute it and/or modify it
33 * under the terms of the GNU General Public License as published by the
34 * Free Software Foundation; either version 2, or (at your option) any
35 * later version.
36 *
37 * This program is distributed in the hope that it will be useful, but
38 * WITHOUT ANY WARRANTY; without even the implied warranty of
39 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
40 * General Public License for more details.
41 *
42 * You should have received a copy of the GNU General Public License along
43 * with this program; if not, write to the Free Software Foundation, Inc.,
44 * 675 Mass Ave, Cambridge, MA 02139, USA.
45 */
46
47/**************************************************************************/
57#include <stdio.h>
58#include <string.h>
59
60#include "NUC472_442.h"
61#include "usbh_core.h"
62
63#include "Umas.h"
64
66
67/***********************************************************************
68 * Helper routines
69 ***********************************************************************/
70/*
71 * Calculate the length of the data transfer (not the command) for any
72 * given SCSI command
73 */
74static uint32_t usb_stor_transfer_length(SCSI_CMD_T *srb)
75{
76 int i;
77 int doDefault = 0;
78 uint32_t len = 0;
79 uint32_t total = 0;
80 SCATTER_LIST_T *sg;
81
82 /*
83 * This table tells umas:
84 * X = command not supported
85 * L = return length in cmnd[4] (8 bits).
86 * M = return length in cmnd[8] (8 bits).
87 * G = return length in cmnd[3] and cmnd[4] (16 bits)
88 * H = return length in cmnd[7] and cmnd[8] (16 bits)
89 * I = return length in cmnd[8] and cmnd[9] (16 bits)
90 * C = return length in cmnd[2] to cmnd[5] (32 bits)
91 * D = return length in cmnd[6] to cmnd[9] (32 bits)
92 * B = return length in blocksize so we use buff_len
93 * R = return length in cmnd[2] to cmnd[4] (24 bits)
94 * S = return length in cmnd[3] to cmnd[5] (24 bits)
95 * T = return length in cmnd[6] to cmnd[8] (24 bits)
96 * U = return length in cmnd[7] to cmnd[9] (24 bits)
97 * 0-9 = fixed return length
98 * V = 20 bytes
99 * W = 24 bytes
100 * Z = return length is mode dependant or not in command, use buff_len
101 */
102
103 static char *lengths = /* 0123456789ABCDEF 0123456789ABCDEF */
104 "00XLZ6XZBXBBXXXB" "00LBBLG0R0L0GG0X" /* 00-1F */
105 "XXXXT8XXB4B0BBBB" "ZZZ0B00HCSSZTBHH" /* 20-3F */
106 "M0HHB0X000H0HH0X" "XHH0HHXX0TH0H0XX" /* 40-5F */
107 "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 60-7F */
108 "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* 80-9F */
109 "X0XXX00XB0BXBXBB" "ZZZ0XUIDU000XHBX" /* A0-BF */
110 "XXXXXXXXXXXXXXXX" "XXXXXXXXXXXXXXXX" /* C0-DF */
111 "XDXXXXXXXXXXXXXX" "XXW00HXXXXXXXXXX"; /* E0-FF */
112
113 /* Commands checked in table:
114 * CHANGE_DEFINITION 40
115 * COMPARE 39
116 * COPY 18
117 * COPY_AND_VERIFY 3a
118 * ERASE 19
119 * ERASE_10 2c
120 * ERASE_12 ac
121 * EXCHANGE_MEDIUM a6
122 * FORMAT_UNIT 04
123 * GET_DATA_BUFFER_STATUS 34
124 * GET_MESSAGE_10 28
125 * GET_MESSAGE_12 a8
126 * GET_WINDOW 25 !!! Has more data than READ_CAPACITY, need to fix table
127 * INITIALIZE_ELEMENT_STATUS 07 !!! REASSIGN_BLOCKS luckily uses buff_len
128 * INQUIRY 12
129 * LOAD_UNLOAD 1b
130 * LOCATE 2b
131 * LOCK_UNLOCK_CACHE 36
132 * LOG_SELECT 4c
133 * LOG_SENSE 4d
134 * MEDIUM_SCAN 38 !!! This was M
135 * MODE_SELECT6 15
136 * MODE_SELECT_10 55
137 * MODE_SENSE_6 1a
138 * MODE_SENSE_10 5a
139 * MOVE_MEDIUM a5
140 * OBJECT_POSITION 31 !!! Same as SEARCH_DATA_EQUAL
141 * PAUSE_RESUME 4b
142 * PLAY_AUDIO_10 45
143 * PLAY_AUDIO_12 a5
144 * PLAY_AUDIO_MSF 47
145 * PLAY_AUDIO_TRACK_INDEX 48
146 * PLAY_AUDIO_TRACK_RELATIVE_10 49
147 * PLAY_AUDIO_TRACK_RELATIVE_12 a9
148 * POSITION_TO_ELEMENT 2b
149 * PRE-FETCH 34
150 * PREVENT_ALLOW_MEDIUM_REMOVAL 1e
151 * PRINT 0a !!! Same as WRITE_6 but is always in bytes
152 * READ_6 08
153 * READ_10 28
154 * READ_12 a8
155 * READ_BLOCK_LIMITS 05
156 * READ_BUFFER 3c
157 * READ_CAPACITY 25
158 * READ_CDROM_CAPACITY 25
159 * READ_DEFECT_DATA 37
160 * READ_DEFECT_DATA_12 b7
161 * READ_ELEMENT_STATUS b8 !!! Think this is in bytes
162 * READ_GENERATION 29 !!! Could also be M?
163 * READ_HEADER 44 !!! This was L
164 * READ_LONG 3e
165 * READ_POSITION 34 !!! This should be V but conflicts with PRE-FETCH
166 * READ_REVERSE 0f
167 * READ_SUB-CHANNEL 42 !!! Is this in bytes?
168 * READ_TOC 43 !!! Is this in bytes?
169 * READ_UPDATED_BLOCK 2d
170 * REASSIGN_BLOCKS 07
171 * RECEIVE 08 !!! Same as READ_6 probably in bytes though
172 * RECEIVE_DIAGNOSTIC_RESULTS 1c
173 * RECOVER_BUFFERED_DATA 14 !!! For PRINTERs this is bytes
174 * RELEASE_UNIT 17
175 * REQUEST_SENSE 03
176 * REQUEST_VOLUME_ELEMENT_ADDRESS b5 !!! Think this is in bytes
177 * RESERVE_UNIT 16
178 * REWIND 01
179 * REZERO_UNIT 01
180 * SCAN 1b !!! Conflicts with various commands, should be L
181 * SEARCH_DATA_EQUAL 31
182 * SEARCH_DATA_EQUAL_12 b1
183 * SEARCH_DATA_LOW 30
184 * SEARCH_DATA_LOW_12 b0
185 * SEARCH_DATA_HIGH 32
186 * SEARCH_DATA_HIGH_12 b2
187 * SEEK_6 0b !!! Conflicts with SLEW_AND_PRINT
188 * SEEK_10 2b
189 * SEND 0a !!! Same as WRITE_6, probably in bytes though
190 * SEND 2a !!! Similar to WRITE_10 but for scanners
191 * SEND_DIAGNOSTIC 1d
192 * SEND_MESSAGE_6 0a !!! Same as WRITE_6 - is in bytes
193 * SEND_MESSAGE_10 2a !!! Same as WRITE_10 - is in bytes
194 * SEND_MESSAGE_12 aa !!! Same as WRITE_12 - is in bytes
195 * SEND_OPC 54
196 * SEND_VOLUME_TAG b6 !!! Think this is in bytes
197 * SET_LIMITS 33
198 * SET_LIMITS_12 b3
199 * SET_WINDOW 24
200 * SLEW_AND_PRINT 0b !!! Conflicts with SEEK_6
201 * SPACE 11
202 * START_STOP_UNIT 1b
203 * STOP_PRINT 1b
204 * SYNCHRONIZE_BUFFER 10
205 * SYNCHRONIZE_CACHE 35
206 * TEST_UNIT_READY 00
207 * UPDATE_BLOCK 3d
208 * VERIFY 13
209 * VERIFY 2f
210 * VERIFY_12 af
211 * WRITE_6 0a
212 * WRITE_10 2a
213 * WRITE_12 aa
214 * WRITE_AND_VERIFY 2e
215 * WRITE_AND_VERIFY_12 ae
216 * WRITE_BUFFER 3b
217 * WRITE_FILEMARKS 10
218 * WRITE_LONG 3f
219 * WRITE_SAME 41
220 */
221
222 if (srb->sc_data_direction == SCSI_DATA_WRITE)
223 doDefault = 1;
224 else
225 {
226 switch (lengths[srb->cmnd[0]])
227 {
228 case 'L':
229 len = srb->cmnd[4];
230 break;
231 case 'M':
232 len = srb->cmnd[8];
233 break;
234 case '0':
235 case '1':
236 case '2':
237 case '3':
238 case '4':
239 case '5':
240 case '6':
241 case '7':
242 case '8':
243 case '9':
244 len = lengths[srb->cmnd[0]]-'0';
245 break;
246 case 'G':
247 len = (((uint32_t)srb->cmnd[3])<<8) | srb->cmnd[4];
248 break;
249 case 'H':
250 len = (((uint32_t)srb->cmnd[7])<<8) | srb->cmnd[8];
251 break;
252 case 'I':
253 len = (((uint32_t)srb->cmnd[8])<<8) | srb->cmnd[9];
254 break;
255 case 'R':
256 len = (((uint32_t)srb->cmnd[2])<<16) |
257 (((uint32_t)srb->cmnd[3])<<8) | srb->cmnd[4];
258 break;
259 case 'S':
260 len = (((uint32_t)srb->cmnd[3])<<16) |
261 (((uint32_t)srb->cmnd[4])<<8) | srb->cmnd[5];
262 break;
263 case 'T':
264 len = (((uint32_t)srb->cmnd[6])<<16) |
265 (((uint32_t)srb->cmnd[7])<<8) | srb->cmnd[8];
266 break;
267 case 'U':
268 len = (((uint32_t)srb->cmnd[7])<<16) |
269 (((uint32_t)srb->cmnd[8])<<8) | srb->cmnd[9];
270 break;
271 case 'C':
272 len = (((uint32_t)srb->cmnd[2])<<24) |
273 (((uint32_t)srb->cmnd[3])<<16) |
274 (((uint32_t)srb->cmnd[4])<<8) | srb->cmnd[5];
275 break;
276 case 'D':
277 len = (((uint32_t)srb->cmnd[6])<<24) |
278 (((uint32_t)srb->cmnd[7])<<16) |
279 (((uint32_t)srb->cmnd[8])<<8) | srb->cmnd[9];
280 break;
281 case 'V':
282 len = 20;
283 break;
284 case 'W':
285 len = 24;
286 break;
287 case 'B':
288 /* Use buffer size due to different block sizes */
289 doDefault = 1;
290 break;
291 case 'X':
292 UMAS_DEBUG("Error: UNSUPPORTED COMMAND %02X\n", srb->cmnd[0]);
293 doDefault = 1;
294 break;
295 case 'Z':
296 /* Use buffer size due to mode dependence */
297 doDefault = 1;
298 break;
299 default:
300 UMAS_DEBUG("Error: COMMAND %02X out of range or table inconsistent (%c).\n",
301 srb->cmnd[0], lengths[srb->cmnd[0]] );
302 doDefault = 1;
303 } /* end of switch */
304 }
305
306 if (doDefault == 1)
307 {
308 /* Are we going to scatter gather? */
309 if (srb->use_sg)
310 {
311 /* Add up the sizes of all the sg segments */
312 sg = (SCATTER_LIST_T *) srb->request_buff;
313 for (i=0; i<srb->use_sg; i++)
314 total += sg[i].length;
315 len = total;
316 }
317 else
318 /* Just return the length of the buffer */
319 len = srb->request_bufflen;
320 }
321 return len;
322}
323
324
325
326/* This is a version of usb_clear_halt() that doesn't read the status from
327 * the device -- this is because some devices crash their internal firmware
328 * when the status is requested after a halt
329 */
330static int clear_halt(USB_DEV_T *dev, int pipe)
331{
332 int result;
333 int endp = usb_pipeendpoint(pipe) | (usb_pipein(pipe) << 7);
334
335 UMAS_DEBUG("clear_halt!\n");
336 result = USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
337 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0,
338 endp, NULL, 0, 0);
339 /* this is a failure case */
340 if (result < 0)
341 {
342 UMAS_DEBUG("clear_halt failed!!\n");
343 return result;
344 }
345
346 /* reset the toggles and endpoint flags */
347 usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
348 usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0x1000);
349
350 return 0;
351}
352
353
354volatile static int _UmasUrbComplete;
355
356int is_urb_completed(void)
357{
358 return _UmasUrbComplete;
359}
360
361/***********************************************************************
362 * Data transfer routines
363 ***********************************************************************/
364/*
365 * This is the completion handler which will wake us up when an URB
366 * completes.
367 */
368static void usb_stor_blocking_completion(URB_T *urb)
369{
370 _UmasUrbComplete = 1;
371
372#ifdef CONFIG_USB_STORAGE_DEBUG
373 UMAS_DEBUG("usb_stor_blocking_completion called...\n");
374#endif
375}
376
377
378
379/*
380 * This is our function to emulate USBH_SendCtrlMsg() but give us enough
381 * access to make aborts/resets work
382 */
383static int usb_stor_control_msg(UMAS_DATA_T *umas, uint32_t pipe,
384 uint8_t request, uint8_t requesttype, uint16_t value,
385 uint16_t index, void *data, uint16_t size)
386{
387 URB_T *urb = umas->current_urb;
388 int status;
389 volatile int t0;
390 DEV_REQ_T dr;
391
392 /* fill in the structure */
393 dr.requesttype = requesttype;
394 dr.request = request;
395 dr.value = value;
396 dr.index = index;
397 dr.length = size;
398
399 /* fill the URB */
400 FILL_CONTROL_URB(urb, umas->pusb_dev, pipe, (uint8_t *)&dr, data, size,
401 usb_stor_blocking_completion, NULL);
402 urb->actual_length = 0;
403 urb->error_count = 0;
404 urb->transfer_flags = USB_ASYNC_UNLINK;
405
406 _UmasUrbComplete = 0;
407
408 /* submit the URB */
409 status = USBH_SubmitUrb(urb);
410 if (status)
411 return status;
412
413 /* wait for the completion of the URB */
414#if 1
415 for (t0 = 0; t0 < 0x8000000; t0++)
416 {
417 if (is_urb_completed())
418 break;
419 }
420 if (t0 >= 0x8000000)
421#else
422 t0 = umas_get_ticks();
423 while (umas_get_ticks() - t0 < 300)
424 {
425 if (is_urb_completed())
426 break;
427 }
428
429 if (umas_get_ticks() - t0 >= 300)
430#endif
431 {
432 UMAS_DEBUG("usb_stor_control_msg time-out failed!\n");
433 return USB_ERR_TIMEOUT;
434 }
435
436 /* return the actual length of the data transferred if no error*/
437 status = urb->status;
438 if (status >= 0)
439 status = urb->actual_length;
440
441 return status;
442}
443
444
445/*
446 * This is our function to emulate usb_bulk_msg() but give us enough
447 * access to make aborts/resets work
448 */
449static int usb_stor_bulk_msg(UMAS_DATA_T *umas, void *data, int pipe,
450 uint32_t len, uint32_t *act_len)
451{
452 URB_T *urb = umas->current_urb;
453 volatile int t0;
454 int status;
455
456 /* fill the URB */
457 FILL_BULK_URB(urb, umas->pusb_dev, pipe, data, len,
458 usb_stor_blocking_completion, NULL);
459 urb->actual_length = 0;
460 urb->error_count = 0;
461 urb->transfer_flags = USB_ASYNC_UNLINK;
462
463 _UmasUrbComplete = 0;
464
465 /* submit the URB */
466 status = USBH_SubmitUrb(urb);
467 if (status)
468 return status;
469
470#if 1
471 for (t0 = 0; t0 < 0x1000000; t0++)
472 {
473 if (is_urb_completed())
474 break;
475 }
476 if (t0 >= 0x8000000)
477#else
478 t0 = umas_get_ticks();
479 while (umas_get_ticks() - t0 < 500)
480 {
481 if (is_urb_completed())
482 break;
483 }
484 if (umas_get_ticks() - t0 >= 500)
485#endif
486 {
487 UMAS_DEBUG("usb_stor_bulk_msg time-out failed!\n");
488 return USB_ERR_TIMEOUT;
489 }
490
491 /* return the actual length of the data transferred */
492 *act_len = urb->actual_length;
493
494 return urb->status;
495}
496
497
498
499/*
500 * Transfer one SCSI scatter-gather buffer via bulk transfer
501 *
502 * Note that this function is necessary because we want the ability to
503 * use scatter-gather memory. Good performance is achieved by a combination
504 * of scatter-gather and clustering (which makes each chunk bigger).
505 *
506 * Note that the lower layer will always retry when a NAK occurs, up to the
507 * timeout limit. Thus we don't have to worry about it for individual
508 * packets.
509 */
510static int usb_stor_transfer_partial(UMAS_DATA_T *umas, char *buf, int length)
511{
512 int result;
513 uint32_t partial;
514 int pipe;
515
516 /* calculate the appropriate pipe information */
517 if (umas->srb.sc_data_direction == SCSI_DATA_READ)
518 pipe = usb_rcvbulkpipe(umas->pusb_dev, umas->ep_in);
519 else
520 pipe = usb_sndbulkpipe(umas->pusb_dev, umas->ep_out);
521
522 /* transfer the data */
523 UMAS_VDEBUG("usb_stor_transfer_partial - xfer %d bytes\n", length);
524 result = usb_stor_bulk_msg(umas, buf, pipe, length, &partial);
525 UMAS_VDEBUG("usb_stor_bulk_msg() returned %d xferred %d/%d\n", result, partial, length);
526 //UMAS_DEBUG("usb_stor_bulk_msg() returned %d xferred %d/%d\n", result, partial, length);
527
528 /* if we stall, we need to clear it before we go on */
529 if (result == USB_ERR_PIPE)
530 {
531 UMAS_DEBUG("usb_stor_transfer_partial - clearing endpoint halt for pipe 0x%x\n", pipe);
532 clear_halt(umas->pusb_dev, pipe);
533 }
534
535 /* did we send all the data? */
536 if (partial == length)
537 {
538 UMAS_VDEBUG("usb_stor_transfer_partial - transfer complete\n");
539 return UMAS_BULK_TRANSFER_GOOD;
540 }
541
542 /* uh oh... we have an error code, so something went wrong. */
543 if (result)
544 {
545 /* NAK - that means we've retried a few times already */
546 if (result == USB_ERR_TIMEOUT)
547 {
548 UMAS_DEBUG("usb_stor_transfer_partial - device NAKed\n");
549 return UMAS_BULK_TRANSFER_FAILED;
550 }
551
552 /* USB_ERR_NOENT -- we canceled this transfer */
553 if (result == USB_ERR_NOENT)
554 {
555 UMAS_DEBUG("usb_stor_transfer_partial - transfer aborted\n");
556 return UMAS_BULK_TRANSFER_ABORTED;
557 }
558
559 /* the catch-all case */
560 UMAS_DEBUG("usb_stor_transfer_partial - unknown error\n");
561 return UMAS_BULK_TRANSFER_FAILED;
562 }
563
564 /* no error code, so we must have transferred some data, just not all of it */
565 return UMAS_BULK_TRANSFER_SHORT;
566}
567
568
569
570/*
571 * Transfer an entire SCSI command's worth of data payload over the bulk pipe.
572 *
573 * Note that this uses usb_stor_transfer_partial to achieve it's goals -- this
574 * function simply determines if we're going to use scatter-gather or not,
575 * and acts appropriately. For now, it also re-interprets the error codes.
576 */
577static void us_transfer(SCSI_CMD_T *srb, UMAS_DATA_T* umas)
578{
579 int i;
580 int result = -1;
581 uint32_t total_transferred = 0;
582 uint32_t transfer_amount;
583 SCATTER_LIST_T *sg;
584
585 /* calculate how much we want to transfer */
586 transfer_amount = usb_stor_transfer_length(srb);
587
588 /* Was someone foolish enough to request more data than available buffer space? */
589 if (transfer_amount > srb->request_bufflen)
590 transfer_amount = srb->request_bufflen;
591
592 /* are we scatter-gathering? */
593 if (srb->use_sg)
594 {
595 /*
596 * loop over all the scatter gather structures and
597 * make the appropriate requests for each, until done
598 */
599 sg = (SCATTER_LIST_T *) srb->request_buff;
600 for (i = 0; i < srb->use_sg; i++)
601 {
602 /* transfer the lesser of the next buffer or the remaining data */
603 if (transfer_amount - total_transferred >= sg[i].length)
604 {
605 result = usb_stor_transfer_partial(umas, sg[i].address, sg[i].length);
606 total_transferred += sg[i].length;
607 }
608 else
609 result = usb_stor_transfer_partial(umas, sg[i].address,
610 transfer_amount - total_transferred);
611 /* if we get an error, end the loop here */
612 if (result)
613 break;
614 }
615 }
616 else /* no scatter-gather, just make the request */
617 result = usb_stor_transfer_partial(umas, (char *)srb->request_buff, transfer_amount);
618
619 /* return the result in the data structure itself */
620 srb->result = result;
621}
622
623
624
625/***********************************************************************
626 * Transport routines
627 ***********************************************************************/
628
629/*
630 * Invoke the transport and basic error-handling/recovery methods
631 *
632 * This is used by the protocol layers to actually send the message to
633 * the device and receive the response.
634 */
635void UMAS_InvokeTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas)
636{
637 int need_auto_sense;
638 int result;
639
640 /* send the command to the transport layer */
641 result = umas->transport(srb, umas);
642
643 /*
644 * If the command gets aborted by the higher layers, we need to
645 * short-circuit all other processing
646 */
647 if (result == USB_STOR_TRANSPORT_ABORTED)
648 {
649 UMAS_DEBUG("UMAS_InvokeTransport - transport indicates command was aborted\n");
650 srb->result = DID_ABORT << 16;
651 return;
652 }
653
654 /*
655 * Determine if we need to auto-sense
656 *
657 * I normally don't use a flag like this, but it's almost impossible
658 * to understand what's going on here if I don't.
659 */
660 need_auto_sense = 0;
661
662 /*
663 * If we're running the CB transport, which is incapable
664 * of determining status on it's own, we need to auto-sense almost
665 * every time.
666 */
667 if ((umas->protocol == UMAS_PR_CB) || (umas->protocol == UMAS_PR_DPCM_USB))
668 {
669 UMAS_VDEBUG("UMAS_InvokeTransport - CB transport device requiring auto-sense\n");
670 need_auto_sense = 1;
671
672 /*
673 * There are some exceptions to this. Notably, if this is
674 * a UFI device and the command is REQUEST_SENSE or INQUIRY,
675 * then it is impossible to truly determine status.
676 */
677 if ((umas->subclass == UMAS_SC_UFI) &&
678 ((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY)))
679 {
680 UMAS_DEBUG("UMAS_InvokeTransport - no auto-sense for a special command\n");
681 need_auto_sense = 0;
682 }
683 }
684
685 /*
686 * If we have an error, we're going to do a REQUEST_SENSE
687 * automatically. Note that we differentiate between a command
688 * "failure" and an "error" in the transport mechanism.
689 */
690 if (result == USB_STOR_TRANSPORT_FAILED)
691 {
692 UMAS_VDEBUG("UMAS_InvokeTransport - transport indicates command failure\n");
693 need_auto_sense = 1;
694 }
695 if (result == USB_STOR_TRANSPORT_ERROR)
696 {
697#if 1 /* YCHuang, 2003.06.30 */
698 umas->transport_reset(umas);
699 UMAS_DEBUG("UMAS_InvokeTransport - transport indicates transport error\n");
700#endif
701 need_auto_sense = 0;
702 srb->result = DID_ERROR << 16;
703 return;
704 }
705
706 /*
707 * Also, if we have a short transfer on a command that can't have
708 * a short transfer, we're going to do this.
709 */
710 if ((srb->result == UMAS_BULK_TRANSFER_SHORT) &&
711 !((srb->cmnd[0] == REQUEST_SENSE) ||
712 (srb->cmnd[0] == INQUIRY) ||
713 (srb->cmnd[0] == MODE_SENSE) ||
714 (srb->cmnd[0] == LOG_SENSE) ||
715 (srb->cmnd[0] == MODE_SENSE_10)))
716 {
717 UMAS_DEBUG("UMAS_InvokeTransport - unexpectedly short transfer\n");
718 need_auto_sense = 1;
719 }
720
721 /* Now, if we need to do the auto-sense, let's do it */
722 if (need_auto_sense)
723 {
724 int temp_result;
725 void *old_request_buffer;
726 uint16_t old_sg;
727 uint32_t old_request_bufflen;
728 uint8_t old_sc_data_direction;
729 uint8_t old_cmnd[MAX_COMMAND_SIZE];
730
731 UMAS_VDEBUG("UMAS_InvokeTransport - Issuing auto-REQUEST_SENSE\n");
732
733 /* save the old command */
734 memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE);
735
736 /* set the command and the LUN */
737 srb->cmnd[0] = REQUEST_SENSE;
738 srb->cmnd[1] = old_cmnd[1] & 0xE0;
739 srb->cmnd[2] = 0;
740 srb->cmnd[3] = 0;
741 srb->cmnd[4] = 18;
742 srb->cmnd[5] = 0;
743
744 /* set the transfer direction */
745 old_sc_data_direction = srb->sc_data_direction;
746 srb->sc_data_direction = SCSI_DATA_READ;
747
748 /* use the new buffer we have */
749 old_request_buffer = srb->request_buff;
750 srb->request_buff = srb->sense_buffer;
751
752 /* set the buffer length for transfer */
753 old_request_bufflen = srb->request_bufflen;
754 srb->request_bufflen = 18;
755
756 /* set up for no scatter-gather use */
757 old_sg = srb->use_sg;
758 srb->use_sg = 0;
759
760 /* issue the auto-sense command */
761 temp_result = umas->transport(&umas->srb, umas);
762 if (temp_result != USB_STOR_TRANSPORT_GOOD)
763 {
764 UMAS_DEBUG("-- auto-sense failure\n");
765
766 /*
767 * we skip the reset if this happens to be a
768 * multi-target device, since failure of an
769 * auto-sense is perfectly valid
770 */
771 if (!(umas->flags & UMAS_FL_SCM_MULT_TARG))
772 {
773 umas->transport_reset(umas);
774 }
775 srb->result = DID_ERROR << 16;
776 return;
777 }
778
779 UMAS_VDEBUG("-- Result from auto-sense is %d\n", temp_result);
780 UMAS_VDEBUG("-- code: 0x%x, key: 0x%x, ASC: 0x%x, ASCQ: 0x%x\n",
781 srb->sense_buffer[0], srb->sense_buffer[2] & 0xf,
782 srb->sense_buffer[12], srb->sense_buffer[13]);
783
784 /* set the result so the higher layers expect this data */
785 srb->result = CHECK_CONDITION << 1;
786
787 /* we're done here, let's clean up */
788 srb->request_buff = old_request_buffer;
789 srb->request_bufflen = old_request_bufflen;
790 srb->use_sg = old_sg;
791 srb->sc_data_direction = old_sc_data_direction;
792 memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE);
793
794 /* If things are really okay, then let's show that */
795 if ((srb->sense_buffer[2] & 0xf) == 0x0)
796 srb->result = GOOD << 1;
797 }
798 else /* if (need_auto_sense) */
799 srb->result = GOOD << 1;
800
801 /*
802 * Regardless of auto-sense, if we _know_ we have an error
803 * condition, show that in the result code
804 */
805 if (result == USB_STOR_TRANSPORT_FAILED)
806 srb->result = CHECK_CONDITION << 1;
807
808 /*
809 * If we think we're good, then make sure the sense data shows it.
810 * This is necessary because the auto-sense for some devices always
811 * sets byte 0 == 0x70, even if there is no error
812 */
813 if ((umas->protocol == UMAS_PR_CB || umas->protocol == UMAS_PR_DPCM_USB) &&
814 (result == USB_STOR_TRANSPORT_GOOD) && ((srb->sense_buffer[2] & 0xf) == 0x0))
815 srb->sense_buffer[0] = 0x0;
816}
817
818
819
820/*
821 * Control/Bulk/Interrupt transport
822 */
823
824/* The interrupt handler for CBI devices */
825void UMAS_CbiIrq(URB_T *urb)
826{
827 UMAS_DATA_T *umas = (UMAS_DATA_T *)urb->context;
828
829 /* reject improper IRQs */
830 if (urb->actual_length != 2)
831 {
832 UMAS_DEBUG("-- IRQ too short\n");
833 return;
834 }
835
836 /* is the device removed? */
837 if (urb->status == USB_ERR_NOENT)
838 {
839 UMAS_DEBUG("-- device has been removed\n");
840 return;
841 }
842
843 /* was this a command-completion interrupt? */
844 if (umas->irqbuf[0] && (umas->subclass != UMAS_SC_UFI))
845 {
846 UMAS_DEBUG("-- not a command-completion IRQ\n");
847 return;
848 }
849
850#if 0
851 /* was this a wanted interrupt? */
852 if (!umas->ip_wanted)
853 {
854 UMAS_DEBUG("ERROR: Unwanted interrupt received!\n");
855 return;
856 }
857#endif
858 umas->ip_wanted = 0 ;
859
860 /* copy the valid data */
861 umas->irqdata[0] = umas->irqbuf[0];
862 umas->irqdata[1] = umas->irqbuf[1];
863}
864
865
866
867int UMAS_CbiTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas)
868{
869 int result;
870
871 /* Set up for status notification */
872 umas->ip_wanted = 1;
873
874 /* re-initialize the mutex so that we avoid any races with
875 * early/late IRQs from previous commands */
876
877 /* COMMAND STAGE */
878 /* let's send the command via the control pipe */
879 result = usb_stor_control_msg(umas, usb_sndctrlpipe(umas->pusb_dev,0),
880 US_CBI_ADSC,
881 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
882 umas->ifnum, srb->cmnd, srb->cmd_len);
883
884 /* check the return code for the command */
885 UMAS_VDEBUG("Call to usb_stor_control_msg() returned %d\n", result);
886 if (result < 0)
887 {
888 /* if the command was aborted, indicate that */
889 if (result == USB_ERR_NOENT)
890 return USB_STOR_TRANSPORT_ABORTED;
891
892 /* STALL must be cleared when they are detected */
893 if (result == USB_ERR_PIPE)
894 {
895 UMAS_VDEBUG("-- Stall on control pipe. Clearing\n");
896 result = clear_halt(umas->pusb_dev, usb_sndctrlpipe(umas->pusb_dev, 0));
897 UMAS_VDEBUG("-- clear_halt() returns %d\n", result);
898 return USB_STOR_TRANSPORT_FAILED;
899 }
900
901 /* Uh oh... serious problem here */
902 return USB_STOR_TRANSPORT_ERROR;
903 }
904
905 /* DATA STAGE */
906 /* transfer the data payload for this command, if one exists*/
907 if (usb_stor_transfer_length(srb))
908 {
909 us_transfer(srb, umas);
910 UMAS_VDEBUG("CBI data stage result is 0x%x\n", srb->result);
911
912 /* if it was aborted, we need to indicate that */
913 if (srb->result == USB_STOR_TRANSPORT_ABORTED)
914 return USB_STOR_TRANSPORT_ABORTED;
915
916 }
917
918 /* STATUS STAGE */
919
920 //UMAS_VDEBUG("Current value of ip_waitq is: %d\n", umas->ip_waitq.count);
921
922 /* if we were woken up by an abort instead of the actual interrupt */
923 if (umas->ip_wanted)
924 {
925 UMAS_DEBUG("Did not get interrupt on CBI\n");
926 umas->ip_wanted = 0;
927 return USB_STOR_TRANSPORT_ABORTED;
928 }
929
930 UMAS_VDEBUG("Got interrupt data (0x%x, 0x%x)\n", umas->irqdata[0], umas->irqdata[1]);
931
932 /*
933 * UFI gives umas ASC and ASCQ, like a request sense
934 *
935 * REQUEST_SENSE and INQUIRY don't affect the sense data on UFI
936 * devices, so we ignore the information for those commands. Note
937 * that this means we could be ignoring a real error on these
938 * commands, but that can't be helped.
939 */
940 if (umas->subclass == UMAS_SC_UFI)
941 {
942 if ((srb->cmnd[0] == REQUEST_SENSE) || (srb->cmnd[0] == INQUIRY))
943 return USB_STOR_TRANSPORT_GOOD;
944 else
945 {
946 if (((uint8_t*)umas->irq_urb->transfer_buffer)[0])
947 return USB_STOR_TRANSPORT_FAILED;
948 else
949 return USB_STOR_TRANSPORT_GOOD;
950 }
951 }
952
953 /*
954 * If not UFI, we interpret the data as a result code
955 * The first byte should always be a 0x0
956 * The second byte & 0x0F should be 0x0 for good, otherwise error
957 */
958 if (umas->irqdata[0])
959 {
960 UMAS_VDEBUG("CBI IRQ data showed reserved bType %d\n", umas->irqdata[0]);
961 return USB_STOR_TRANSPORT_ERROR;
962 }
963
964 switch (umas->irqdata[1] & 0x0F)
965 {
966 case 0x00:
967 return USB_STOR_TRANSPORT_GOOD;
968 case 0x01:
969 return USB_STOR_TRANSPORT_FAILED;
970 default:
971 return USB_STOR_TRANSPORT_ERROR;
972 }
973}
974
975
976
977/*
978 * Control/Bulk transport
979 */
980int UMAS_CbTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas)
981{
982 int result;
983
984 /* COMMAND STAGE */
985 /* let's send the command via the control pipe */
986 result = usb_stor_control_msg(umas, usb_sndctrlpipe(umas->pusb_dev,0),
987 US_CBI_ADSC,
988 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0,
989 umas->ifnum, srb->cmnd, srb->cmd_len);
990
991 /* check the return code for the command */
992 UMAS_VDEBUG("UMAS_CbTransport - Call to usb_stor_control_msg() returned %d\n", result);
993 if (result < 0)
994 {
995 /* if the command was aborted, indicate that */
996 if (result == USB_ERR_NOENT)
997 return USB_STOR_TRANSPORT_ABORTED;
998
999 /* a stall is a fatal condition from the device */
1000 if (result == USB_ERR_PIPE)
1001 {
1002 UMAS_DEBUG("UMAS_CbTransport - Stall on control pipe. Clearing\n");
1003 result = clear_halt(umas->pusb_dev, usb_sndctrlpipe(umas->pusb_dev, 0));
1004 UMAS_DEBUG("UMAS_CbTransport - clear_halt() returns %d\n", result);
1005 return USB_STOR_TRANSPORT_FAILED;
1006 }
1007
1008 /* Uh oh... serious problem here */
1009 return USB_STOR_TRANSPORT_ERROR;
1010 }
1011
1012 /* DATA STAGE */
1013 /* transfer the data payload for this command, if one exists */
1014 if (usb_stor_transfer_length(srb))
1015 {
1016 us_transfer(srb, umas);
1017 UMAS_VDEBUG("UMAS_CbTransport - CB data stage result is 0x%x\n", srb->result);
1018
1019 /* if it was aborted, we need to indicate that */
1020 if (srb->result == USB_STOR_TRANSPORT_ABORTED)
1021 return USB_STOR_TRANSPORT_ABORTED;
1022 }
1023
1024 /* STATUS STAGE */
1025 /* NOTE: CB does not have a status stage. Silly, I know. So
1026 * we have to catch this at a higher level.
1027 */
1028 return USB_STOR_TRANSPORT_GOOD;
1029}
1030
1031
1032
1033/*
1034 * Bulk only transport
1035 */
1036
1037/* Determine what the maximum LUN supported is */
1038int UMAS_BulkMaxLun(UMAS_DATA_T *umas)
1039{
1040 uint8_t data;
1041 int result;
1042 int pipe;
1043 uint8_t dma_buff[4];
1044
1045 /* issue the command */
1046 pipe = usb_rcvctrlpipe(umas->pusb_dev, 0);
1047 result = USBH_SendCtrlMsg(umas->pusb_dev, pipe, UMAS_BULK_GET_MAX_LUN,
1048 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1049 0, umas->ifnum, dma_buff, 1, 0);
1050
1051 data = dma_buff[0];
1052
1053 UMAS_DEBUG("GetMaxLUN command result is %d, data is %d\n", result, data);
1054
1055 /* if we have a successful request, return the result */
1056 if (result == 1)
1057 return data;
1058
1059 /* if we get a STALL, clear the stall */
1060 if (result == USB_ERR_PIPE)
1061 {
1062 UMAS_DEBUG("clearing endpoint halt for pipe 0x%x\n", pipe);
1063 clear_halt(umas->pusb_dev, pipe);
1064 }
1065
1066 /* return the default -- no LUNs */
1067 return 0;
1068}
1069
1070
1071
1072int UMAS_BulkTransport(SCSI_CMD_T *srb, UMAS_DATA_T *umas)
1073{
1074 int result, status = 0;
1075 int pipe;
1076 uint32_t partial;
1077 struct bulk_cb_wrap bcb;
1078 struct bulk_cs_wrap bcs;
1079
1080 /* if the device was removed, then we're already reset */
1081 if (!umas->pusb_dev)
1082 return SUCCESS;
1083
1084 /* set up the command wrapper */
1085 bcb.Signature = UMAS_BULK_CB_SIGN;
1086 bcb.DataTransferLength = usb_stor_transfer_length(srb);
1087 bcb.Flags = srb->sc_data_direction == SCSI_DATA_READ ? 1 << 7 : 0;
1088 bcb.Tag = srb->serial_number;
1089 bcb.Lun = srb->cmnd[1] >> 5;
1090
1091 if (umas->flags & UMAS_FL_SCM_MULT_TARG)
1092 bcb.Lun |= srb->target << 4;
1093 bcb.Length = srb->cmd_len;
1094
1095 /* construct the pipe handle */
1096 pipe = usb_sndbulkpipe(umas->pusb_dev, umas->ep_out);
1097
1098 /* copy the command payload */
1099 memset(bcb.CDB, 0, sizeof(bcb.CDB));
1100 memcpy(bcb.CDB, srb->cmnd, bcb.Length);
1101
1102 /* send it to out endpoint */
1103 UMAS_VDEBUG("Bulk command S 0x%x T 0x%x Trg %d LUN %d L %d F %d CL %d\n",
1104 bcb.Signature, bcb.Tag, (bcb.Lun >> 4), (bcb.Lun & 0x0F),
1105 bcb.DataTransferLength, bcb.Flags, bcb.Length);
1106 result = usb_stor_bulk_msg(umas, &bcb, pipe, UMAS_BULK_CB_WRAP_LEN, &partial);
1107 UMAS_VDEBUG("Bulk command transfer result=%d\n", result);
1108
1109 /* if the command was aborted, indicate that */
1110 if (result == USB_ERR_NOENT)
1111 return USB_STOR_TRANSPORT_ABORTED;
1112
1113 /* if we stall, we need to clear it before we go on */
1114 if (result == USB_ERR_PIPE)
1115 {
1116 UMAS_DEBUG("UMAS_BulkTransport - 1 clearing endpoint halt for pipe 0x%x\n", pipe);
1117 clear_halt(umas->pusb_dev, pipe);
1118 }
1119 else if (result)
1120 {
1121 /* unknown error -- we've got a problem */
1122 status = USB_STOR_TRANSPORT_ERROR;
1123 goto bulk_error;
1124 }
1125
1126 /* if the command transferred well, then we go to the data stage */
1127 if (result == 0)
1128 {
1129 /* send/receive data payload, if there is any */
1130 if (bcb.DataTransferLength)
1131 {
1132 us_transfer(srb, umas);
1133
1134 /* if it was aborted, we need to indicate that */
1135 if (srb->result == USB_STOR_TRANSPORT_ABORTED)
1136 {
1137 status = USB_STOR_TRANSPORT_ABORTED;
1138 goto bulk_error;
1139 }
1140 }
1141 }
1142
1143 /*
1144 * See flow chart on pg 15 of the Bulk Only Transport spec for
1145 * an explanation of how this code works.
1146 */
1147
1148 /* construct the pipe handle */
1149 pipe = usb_rcvbulkpipe(umas->pusb_dev, umas->ep_in);
1150
1151 /* get CSW for device status */
1152 UMAS_VDEBUG("Attempting to get CSW...\n");
1153 result = usb_stor_bulk_msg(umas, (char *)&bcs, pipe, UMAS_BULK_CS_WRAP_LEN, &partial);
1154
1155 /* if the command was aborted, indicate that */
1156 if (result == USB_ERR_NOENT)
1157 {
1158 status = USB_STOR_TRANSPORT_ABORTED;
1159 goto bulk_error;
1160 }
1161
1162 /* did the attempt to read the CSW fail? */
1163 if (result == USB_ERR_PIPE)
1164 {
1165 UMAS_DEBUG("get CSW failed - clearing endpoint halt for pipe 0x%x\n", pipe);
1166 clear_halt(umas->pusb_dev, pipe);
1167
1168 /* get the status again */
1169 UMAS_DEBUG("Attempting to get CSW (2nd try)...\n");
1170 result = usb_stor_bulk_msg(umas, &bcs, pipe, UMAS_BULK_CS_WRAP_LEN, &partial);
1171
1172 /* if the command was aborted, indicate that */
1173 if (result == USB_ERR_NOENT)
1174 {
1175 UMAS_DEBUG("get CSW Command was aborted!\n");
1176 status = USB_STOR_TRANSPORT_ABORTED;
1177 goto bulk_error;
1178 }
1179
1180 /* if it fails again, we need a reset and return an error*/
1181 if (result == USB_ERR_PIPE)
1182 {
1183 UMAS_DEBUG("get CSW command 2nd try failed - clearing halt for pipe 0x%x\n", pipe);
1184 clear_halt(umas->pusb_dev, pipe);
1185 status = USB_STOR_TRANSPORT_ERROR;
1186 goto bulk_error;
1187 }
1188 }
1189
1190 /* if we still have a failure at this point, we're in trouble */
1191 UMAS_VDEBUG("Bulk status result = %d\n", result);
1192 if (result)
1193 {
1194 status = USB_STOR_TRANSPORT_ERROR;
1195 goto bulk_error;
1196 }
1197
1198 /* check bulk status */
1199 UMAS_VDEBUG("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
1200 USB_SWAP32(bcs.Signature), bcs.Tag, bcs.Residue, bcs.Status);
1201 if ((bcs.Signature != UMAS_BULK_CS_SIGN) || (bcs.Tag != bcb.Tag) ||
1202 (bcs.Status > UMAS_BULK_STAT_PHASE) || (partial != 13))
1203 {
1204 UMAS_DEBUG("Bulk status Sig 0x%x T 0x%x R %d Stat 0x%x\n",
1205 USB_SWAP32(bcs.Signature), bcs.Tag, bcs.Residue, bcs.Status);
1206 status = USB_STOR_TRANSPORT_ERROR;
1207 goto bulk_error;
1208 }
1209
1210 /* based on the status code, we report good or bad */
1211 switch (bcs.Status)
1212 {
1213 case UMAS_BULK_STAT_OK:
1214 /* command good -- note that data could be short */
1215 return USB_STOR_TRANSPORT_GOOD;
1216
1217 case UMAS_BULK_STAT_FAIL:
1218 /* command failed */
1219 status = USB_STOR_TRANSPORT_FAILED;
1220 goto bulk_error;
1221
1222 case UMAS_BULK_STAT_PHASE:
1223 /* phase error -- note that a transport reset will be
1224 * invoked by the invoke_transport() function
1225 */
1226 status = USB_STOR_TRANSPORT_ERROR;
1227 goto bulk_error;
1228 }
1229 /* we should never get here, but if we do, we're in trouble */
1230
1231bulk_error:
1232 return status;
1233}
1234
1235
1236
1237
1238/***********************************************************************
1239 * Reset routines
1240 ***********************************************************************/
1241
1242/*
1243 * This issues a CB[I] Reset to the device in question
1244 */
1245int UMAS_CbReset(UMAS_DATA_T *umas)
1246{
1247 uint8_t cmd[12];
1248 int result;
1249
1250 /* if the device was removed, then we're already reset */
1251 if (!umas->pusb_dev)
1252 return SUCCESS;
1253
1254 memset(cmd, 0xFF, sizeof(cmd));
1255 cmd[0] = SEND_DIAGNOSTIC;
1256 cmd[1] = 4;
1257 result = USBH_SendCtrlMsg(umas->pusb_dev, usb_sndctrlpipe(umas->pusb_dev,0),
1258 US_CBI_ADSC, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1259 0, umas->ifnum, cmd, sizeof(cmd), 0);
1260 if (result < 0)
1261 {
1262 UMAS_DEBUG("UMAS_CbReset - CB[I] soft reset failed %d\n", result);
1263 return FAILED;
1264 }
1265
1266 UMAS_VDEBUG("UMAS_CbReset - clearing endpoint halt\n");
1267 clear_halt(umas->pusb_dev, usb_rcvbulkpipe(umas->pusb_dev, umas->ep_in));
1268 clear_halt(umas->pusb_dev, usb_rcvbulkpipe(umas->pusb_dev, umas->ep_out));
1269
1270 UMAS_VDEBUG("UMAS_CbReset - done\n");
1271 /* return a result code based on the result of the control message */
1272 return SUCCESS;
1273}
1274
1275
1276
1277/*
1278 * This issues a Bulk-only Reset to the device in question, including
1279 * clearing the subsequent endpoint halts that may occur.
1280 */
1281int UMAS_BulkReset(UMAS_DATA_T *umas)
1282{
1283 int result;
1284
1285 UMAS_VDEBUG("Bulk reset requested\n");
1286 printf("UMAS_BulkReset!\n");
1287
1288 /* if the device was removed, then we're already reset */
1289 if (!umas->pusb_dev)
1290 return SUCCESS;
1291
1292 result = USBH_SendCtrlMsg(umas->pusb_dev,
1293 usb_sndctrlpipe(umas->pusb_dev,0), UMAS_BULK_RESET_REQUEST,
1294 USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, umas->ifnum,
1295 NULL, 0, 0);
1296 if (result < 0)
1297 {
1298 UMAS_DEBUG("Bulk soft reset failed %d\n", result);
1299 return FAILED;
1300 }
1301
1302 clear_halt(umas->pusb_dev, usb_rcvbulkpipe(umas->pusb_dev, umas->ep_in));
1303 clear_halt(umas->pusb_dev, usb_sndbulkpipe(umas->pusb_dev, umas->ep_out));
1304
1305 UMAS_VDEBUG("Bulk soft reset completed\n");
1306 return SUCCESS;
1307}
1308
1310
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
#define USB_ERR_TIMEOUT
Definition: usbh_err_code.h:30
#define USB_ERR_NOENT
Definition: usbh_err_code.h:17
#define USB_ERR_PIPE
Definition: usbh_err_code.h:25
int status
Definition: usbh_core.h:543
int32_t USBH_SubmitUrb(URB_T *urb)
Submit an URB to USB core for transfer data.
Definition: usbh_core.c:218
int actual_length
Definition: usbh_core.h:547
uint32_t transfer_flags
Definition: usbh_core.h:544
int error_count
Definition: usbh_core.h:552
int32_t USBH_SendCtrlMsg(USB_DEV_T *dev, uint32_t pipe, uint8_t request, uint8_t requesttype, uint16_t value, uint16_t index, void *data, uint16_t size, int timeout)
Execute a control transfer.
Definition: usbh_core.c:378
void * context
Definition: usbh_core.h:554
DEV_REQ_T
Definition: usbh_core.h:190
HIDDEN_SYMBOLS struct usb_device USB_DEV_T
#define NULL
NULL pointer.
Definition: NUC472_442.h:29018
return value
Definition: semihosting.h:98
USB Host core driver header file.