2 * Minix3 USB mass storage driver implementation
3 * using DDEkit, and libblockdriver
6 #include <sys/cdefs.h> /* __CTASSERT() */
7 #include <sys/ioc_disk.h> /* cases for mass_storage_ioctl */
8 #ifdef USB_STORAGE_SIGNAL
9 #include <sys/signal.h> /* signal handling */
12 #include <ddekit/minix/msg_queue.h>
13 #include <ddekit/thread.h>
14 #include <ddekit/usb.h>
16 #include <minix/blockdriver.h>
17 #include <minix/com.h> /* for msg_queue ranges */
18 #include <minix/drvlib.h> /* DEV_PER_DRIVE, partition */
19 #include <minix/ipc.h> /* message */
20 #include <minix/safecopies.h> /* GRANT_VALID */
21 #include <minix/sef.h>
22 #include <minix/sysutil.h> /* panic */
23 #include <minix/usb.h> /* structures like usb_ctrlrequest */
24 #include <minix/usb_ch9.h> /* descriptor structures */
27 #include <limits.h> /* ULONG_MAX */
28 #include <time.h> /* nanosleep */
32 #include "usb_storage.h"
33 #include "urb_helper.h"
37 /*---------------------------*
38 * declared functions *
39 *---------------------------*/
40 /* TODO: these are missing from DDE header files */
41 extern void ddekit_minix_wait_exit(void);
42 extern void ddekit_shutdown(void);
44 /* SCSI URB related prototypes */
45 static int mass_storage_send_scsi_cbw_out(int, scsi_transfer
*);
46 static int mass_storage_send_scsi_data_in(void *, unsigned int);
47 static int mass_storage_send_scsi_data_out(void *, unsigned int);
48 static int mass_storage_send_scsi_csw_in(void);
50 #ifdef MASS_RESET_RECOVERY
51 /* Bulk only URB related prototypes */
52 static int mass_storage_reset_recovery(void);
53 static int mass_storage_send_bulk_reset(void);
54 static int mass_storage_send_clear_feature(int, int);
57 /* SEF related functions */
58 static int mass_storage_sef_hdlr(int, sef_init_info_t
*);
59 static void mass_storage_signal_handler(int);
61 /* DDEKit IPC related */
62 static void ddekit_usb_task(void *);
64 /* Mass storage related prototypes */
65 static void mass_storage_task(void *);
66 static int mass_storage_test(void);
67 static int mass_storage_check_error(void);
68 static int mass_storage_try_first_open(void);
69 static int mass_storage_transfer_restrictions(u64_t
, unsigned long);
70 static ssize_t
mass_storage_write(unsigned long, endpoint_t
, iovec_t
*,
71 unsigned int, unsigned long);
72 static ssize_t
mass_storage_read(unsigned long, endpoint_t
, iovec_t
*,
73 unsigned int, unsigned long);
75 /* Minix's libblockdriver callbacks */
76 static int mass_storage_open(devminor_t
, int);
77 static int mass_storage_close(devminor_t
);
78 static ssize_t
mass_storage_transfer(devminor_t
, int, u64_t
, endpoint_t
,
79 iovec_t
*, unsigned int, int);
80 static int mass_storage_ioctl(devminor_t
, unsigned long, endpoint_t
,
81 cp_grant_id_t
, endpoint_t
);
82 static void mass_storage_cleanup(void);
83 static struct device
* mass_storage_part(devminor_t
);
84 static void mass_storage_geometry(devminor_t
, struct part_geom
*);
86 /* DDEKit's USB driver callbacks */
87 static void usb_driver_completion(void *);
88 static void usb_driver_connect(struct ddekit_usb_dev
*, unsigned int);
89 static void usb_driver_disconnect(struct ddekit_usb_dev
*);
91 /* Simplified enumeration method for endpoint resolution */
92 static int mass_storage_get_endpoints(urb_ep_config
*, urb_ep_config
*);
93 static int mass_storage_parse_endpoint(usb_descriptor_t
*, urb_ep_config
*,
95 static int mass_storage_parse_descriptors(char *, unsigned int, urb_ep_config
*,
99 /*---------------------------*
100 * defined variables *
101 *---------------------------*/
102 #define MASS_PACKED __attribute__((__packed__))
104 /* Mass Storage callback structure */
105 static struct blockdriver mass_storage
= {
106 .bdr_type
= BLOCKDRIVER_TYPE_DISK
,
107 .bdr_open
= mass_storage_open
,
108 .bdr_close
= mass_storage_close
,
109 .bdr_transfer
= mass_storage_transfer
,
110 .bdr_ioctl
= mass_storage_ioctl
,
111 .bdr_cleanup
= mass_storage_cleanup
,
112 .bdr_part
= mass_storage_part
,
113 .bdr_geometry
= mass_storage_geometry
,
120 /* USB callback structure */
121 static struct ddekit_usb_driver mass_storage_driver
= {
122 .completion
= usb_driver_completion
,
123 .connect
= usb_driver_connect
,
124 .disconnect
= usb_driver_disconnect
127 /* Instance of global driver information */
128 mass_storage_state driver_state
;
130 /* Tags used to pair CBW and CSW for bulk communication
131 * With this we can check if SCSI reply was meant for SCSI request */
132 static unsigned int current_cbw_tag
= 0; /* What shall be send next */
133 static unsigned int last_cbw_tag
= 0; /* What was sent recently */
135 /* Semaphore used to block mass storage thread to
136 * allow DDE dispatcher operation */
137 static ddekit_sem_t
* mass_storage_sem
= NULL
;
139 /* Mass storage (using libblockdriver) thread */
140 ddekit_thread_t
* mass_storage_thread
= NULL
;
142 /* DDEKit USB message handling thread */
143 ddekit_thread_t
* ddekit_usb_thread
= NULL
;
145 /* Static URB buffer size (must be multiple of SECTOR_SIZE) */
146 #define BUFFER_SIZE (64*SECTOR_SIZE)
148 /* Large buffer for URB read/write operations */
149 static unsigned char buffer
[BUFFER_SIZE
];
151 /* Length of local buffer where descriptors are temporarily stored */
152 #define MAX_DESCRIPTORS_LEN 128
154 /* Maximum 'Test Unit Ready' command retries */
155 #define MAX_TEST_RETRIES 3
157 /* 'Test Unit Ready' failure delay time (in nanoseconds) */
158 #define NEXT_TEST_DELAY 50000000 /* 50ms */
161 /*---------------------------*
162 * defined functions *
163 *---------------------------*/
164 /*===========================================================================*
166 *===========================================================================*/
168 main(int argc
, char * argv
[])
170 MASS_DEBUG_MSG("Starting...");
172 /* Store arguments for future parsing */
173 env_setargs(argc
, argv
);
175 /* Clear current state */
176 memset(&driver_state
, 0, sizeof(driver_state
));
178 /* Initialize SEF related callbacks */
179 sef_setcb_init_fresh(mass_storage_sef_hdlr
);
180 sef_setcb_init_lu(mass_storage_sef_hdlr
);
181 sef_setcb_init_restart(mass_storage_sef_hdlr
);
182 sef_setcb_signal_handler(mass_storage_signal_handler
);
184 /* Initialize DDEkit (involves sef_startup()) */
186 MASS_DEBUG_MSG("DDEkit ready...");
188 /* Semaphore initialization */
189 mass_storage_sem
= ddekit_sem_init(0);
190 if (NULL
== mass_storage_sem
)
191 panic("Initializing mass_storage_sem failed!");
193 /* Starting mass storage thread */
194 mass_storage_thread
= ddekit_thread_create(mass_storage_task
, NULL
,
195 "mass_storage_task");
196 if (NULL
== mass_storage_thread
)
197 panic("Initializing mass_storage_thread failed!");
199 MASS_DEBUG_MSG("Storage task (libblockdriver) ready...");
201 /* Run USB IPC task to collect messages */
202 ddekit_usb_thread
= ddekit_thread_create(ddekit_usb_task
, NULL
,
204 if (NULL
== ddekit_usb_thread
)
205 panic("Initializing ddekit_usb_thread failed!");
207 MASS_DEBUG_MSG("USB IPC task ready...");
209 /* Block and wait until exit signal is received */
210 ddekit_minix_wait_exit();
211 MASS_DEBUG_MSG("Exiting...");
213 /* Release objects that were explicitly allocated above */
214 ddekit_thread_terminate(ddekit_usb_thread
);
215 ddekit_thread_terminate(mass_storage_thread
);
216 ddekit_sem_deinit(mass_storage_sem
);
218 /* TODO: no ddekit_deinit for proper cleanup? */
220 MASS_DEBUG_MSG("Cleanup completed...");
226 /*===========================================================================*
227 * mass_storage_send_scsi_cbw_out *
228 *===========================================================================*/
230 mass_storage_send_scsi_cbw_out(int scsi_cmd
, scsi_transfer
* info
)
233 struct ddekit_usb_urb urb
;
235 /* CBW data buffer */
236 mass_storage_cbw cbw
;
240 /* Reset URB and assign given values */
241 init_urb(&urb
, driver_state
.cur_periph
->dev
,
242 &(driver_state
.cur_periph
->ep_out
));
244 /* Reset CBW and assign default values */
245 init_cbw(&cbw
, last_cbw_tag
= current_cbw_tag
++);
247 /* Fill CBW with SCSI command */
248 if (create_scsi_cmd(&cbw
, scsi_cmd
, info
))
251 /* Attach CBW to URB */
252 attach_urb_data(&urb
, URB_BUF_TYPE_DATA
, &cbw
, sizeof(cbw
));
254 /* Send and wait for response */
255 if (blocking_urb_submit(&urb
, mass_storage_sem
, URB_SUBMIT_CHECK_LEN
))
262 /*===========================================================================*
263 * mass_storage_send_scsi_data_in *
264 *===========================================================================*/
266 mass_storage_send_scsi_data_in(void * buf
, unsigned int in_len
)
269 struct ddekit_usb_urb urb
;
273 /* Reset URB and assign given values */
274 init_urb(&urb
, driver_state
.cur_periph
->dev
,
275 &(driver_state
.cur_periph
->ep_in
));
277 /* Attach buffer to URB */
278 attach_urb_data(&urb
, URB_BUF_TYPE_DATA
, buf
, in_len
);
280 /* Send and wait for response */
281 if (blocking_urb_submit(&urb
, mass_storage_sem
, URB_SUBMIT_CHECK_LEN
))
288 /*===========================================================================*
289 * mass_storage_send_scsi_data_out *
290 *===========================================================================*/
292 mass_storage_send_scsi_data_out(void * buf
, unsigned int out_len
)
295 struct ddekit_usb_urb urb
;
299 /* Reset URB and assign given values */
300 init_urb(&urb
, driver_state
.cur_periph
->dev
,
301 &(driver_state
.cur_periph
->ep_out
));
303 /* Attach buffer to URB */
304 attach_urb_data(&urb
, URB_BUF_TYPE_DATA
, buf
, out_len
);
306 /* Send and wait for response */
307 if (blocking_urb_submit(&urb
, mass_storage_sem
, URB_SUBMIT_CHECK_LEN
))
314 /*===========================================================================*
315 * mass_storage_send_scsi_csw_in *
316 *===========================================================================*/
318 mass_storage_send_scsi_csw_in(void)
321 struct ddekit_usb_urb urb
;
323 /* CBW data buffer */
324 mass_storage_csw csw
;
328 /* Reset URB and assign given values */
329 init_urb(&urb
, driver_state
.cur_periph
->dev
,
330 &(driver_state
.cur_periph
->ep_in
));
332 /* Clear CSW for receiving */
335 /* Attach CSW to URB */
336 attach_urb_data(&urb
, URB_BUF_TYPE_DATA
, &csw
, sizeof(csw
));
338 /* Send and wait for response */
339 if (blocking_urb_submit(&urb
, mass_storage_sem
, URB_SUBMIT_CHECK_LEN
))
342 /* Check for proper reply */
343 if (check_csw(&csw
, last_cbw_tag
))
350 #ifdef MASS_RESET_RECOVERY
351 /*===========================================================================*
352 * mass_storage_reset_recovery *
353 *===========================================================================*/
355 mass_storage_reset_recovery(void)
359 /* Bulk-Only Mass Storage Reset */
360 if (mass_storage_send_bulk_reset()) {
361 MASS_MSG("Bulk-only mass storage reset failed");
365 /* Clear Feature HALT to the Bulk-In endpoint */
366 if (URB_INVALID_EP
!= driver_state
.cur_periph
->ep_in
.ep_num
)
367 if (mass_storage_send_clear_feature(
368 driver_state
.cur_periph
->ep_in
.ep_num
,
370 MASS_MSG("Resetting IN EP failed");
374 /* Clear Feature HALT to the Bulk-Out endpoint */
375 if (URB_INVALID_EP
!= driver_state
.cur_periph
->ep_out
.ep_num
)
376 if (mass_storage_send_clear_feature(
377 driver_state
.cur_periph
->ep_out
.ep_num
,
379 MASS_MSG("Resetting OUT EP failed");
387 /*===========================================================================*
388 * mass_storage_send_bulk_reset *
389 *===========================================================================*/
391 mass_storage_send_bulk_reset(void)
394 struct ddekit_usb_urb urb
;
396 /* Setup buffer to be send */
397 struct usb_ctrlrequest bulk_setup
;
399 /* Control EP configuration */
400 urb_ep_config ep_conf
;
404 /* Initialize EP configuration */
406 ep_conf
.direction
= DDEKIT_USB_OUT
;
407 ep_conf
.type
= DDEKIT_USB_TRANSFER_CTL
;
408 ep_conf
.max_packet_size
= 0;
409 ep_conf
.interval
= 0;
411 /* Reset URB and assign given values */
412 init_urb(&urb
, driver_state
.cur_periph
->dev
, &ep_conf
);
414 /* Clear setup data */
415 memset(&bulk_setup
, 0, sizeof(bulk_setup
));
417 /* For explanation of these values see usbmassbulk_10.pdf */
418 /* 3.1 Bulk-Only Mass Storage Reset */
419 bulk_setup
.bRequestType
= 0x21; /* Class, Interface, host to device */
420 bulk_setup
.bRequest
= 0xff;
421 bulk_setup
.wValue
= 0x00;
422 bulk_setup
.wIndex
= 0x00; /* TODO: hard-coded interface 0 */
423 bulk_setup
.wLength
= 0x00;
425 /* Attach request to URB */
426 attach_urb_data(&urb
, URB_BUF_TYPE_SETUP
,
427 &bulk_setup
, sizeof(bulk_setup
));
429 /* Send and wait for response */
430 if (blocking_urb_submit(&urb
, mass_storage_sem
, URB_SUBMIT_CHECK_LEN
))
437 /*===========================================================================*
438 * mass_storage_send_clear_feature *
439 *===========================================================================*/
441 mass_storage_send_clear_feature(int ep_num
, int direction
)
444 struct ddekit_usb_urb urb
;
446 /* Setup buffer to be send */
447 struct usb_ctrlrequest bulk_setup
;
449 /* Control EP configuration */
450 urb_ep_config ep_conf
;
454 assert((ep_num
>= 0) && (ep_num
< 16));
455 assert((DDEKIT_USB_OUT
== direction
) || (DDEKIT_USB_IN
== direction
));
457 /* Initialize EP configuration */
459 ep_conf
.direction
= DDEKIT_USB_OUT
;
460 ep_conf
.type
= DDEKIT_USB_TRANSFER_CTL
;
461 ep_conf
.max_packet_size
= 0;
462 ep_conf
.interval
= 0;
464 /* Reset URB and assign given values */
465 init_urb(&urb
, driver_state
.cur_periph
->dev
, &ep_conf
);
467 /* Clear setup data */
468 memset(&bulk_setup
, 0, sizeof(bulk_setup
));
470 /* For explanation of these values see usbmassbulk_10.pdf */
471 /* 3.1 Bulk-Only Mass Storage Reset */
472 bulk_setup
.bRequestType
= 0x02; /* Standard, Endpoint, host to device */
473 bulk_setup
.bRequest
= 0x01; /* CLEAR_FEATURE */
474 bulk_setup
.wValue
= 0x00; /* Endpoint */
475 bulk_setup
.wIndex
= ep_num
; /* Endpoint number... */
476 if (DDEKIT_USB_IN
== direction
)
477 bulk_setup
.wIndex
|= UE_DIR_IN
; /* ...and direction bit */
478 bulk_setup
.wLength
= 0x00;
480 /* Attach request to URB */
481 attach_urb_data(&urb
, URB_BUF_TYPE_SETUP
,
482 &bulk_setup
, sizeof(bulk_setup
));
484 /* Send and wait for response */
485 if (blocking_urb_submit(&urb
, mass_storage_sem
, URB_SUBMIT_CHECK_LEN
))
493 /*===========================================================================*
494 * mass_storage_sef_hdlr *
495 *===========================================================================*/
497 mass_storage_sef_hdlr(int type
, sef_init_info_t
* UNUSED(info
))
503 /* Parse given environment */
504 env_res
= env_parse("instance", "d", 0,
505 &(driver_state
.instance
),0, 255);
507 /* Get instance number */
508 if (EP_UNSET
== env_res
) {
509 MASS_DEBUG_MSG("Instance number was not supplied");
510 driver_state
.instance
= 0;
512 /* Only SET and UNSET are allowed */
513 if (EP_SET
!= env_res
)
519 /* Announce we are up! */
520 blockdriver_announce(type
);
523 case SEF_INIT_RESTART
:
524 MASS_MSG("Only 'fresh' SEF initialization supported\n");
527 MASS_MSG("illegal SEF type\n");
535 /*===========================================================================*
536 * mass_storage_signal_handler *
537 *===========================================================================*/
539 mass_storage_signal_handler(int this_signal
)
543 #ifdef USB_STORAGE_SIGNAL
544 /* Only check for termination signal, ignore anything else. */
545 if (this_signal
!= SIGTERM
)
548 MASS_MSG("Handling signal 0x%X", this_signal
);
551 /* Try graceful DDEKit exit */
554 /* Unreachable, when ddekit_shutdown works correctly */
555 panic("Calling ddekit_shutdown failed!");
559 /*===========================================================================*
561 *===========================================================================*/
563 ddekit_usb_task(void * UNUSED(arg
))
567 /* TODO: This call was meant to return 'int' but loops forever instead,
568 * so no return value is checked */
569 ddekit_usb_init(&mass_storage_driver
, NULL
, NULL
);
573 /*===========================================================================*
574 * mass_storage_task *
575 *===========================================================================*/
577 mass_storage_task(void * UNUSED(unused
))
581 struct ddekit_minix_msg_q
* mq
;
585 mq
= ddekit_minix_create_msg_q(BDEV_RQ_BASE
, BDEV_RQ_BASE
+ 0xff);
588 ddekit_minix_rcv(mq
, &m
, &ipc_status
);
589 blockdriver_process(&mass_storage
, &m
, ipc_status
);
594 /*===========================================================================*
595 * mass_storage_test *
596 *===========================================================================*/
598 mass_storage_test(void)
603 struct timespec test_wait
;
607 /* Delay between consecutive test commands, in case of their failure */
608 test_wait
.tv_nsec
= NEXT_TEST_DELAY
;
609 test_wait
.tv_sec
= 0;
611 for (repeat
= 0; repeat
< MAX_TEST_RETRIES
; repeat
++) {
613 /* SCSI TEST UNIT READY OUT stage */
614 if (mass_storage_send_scsi_cbw_out(SCSI_TEST_UNIT_READY
, NULL
))
617 /* TODO: Only CSW failure should normally contribute to retry */
619 /* SCSI TEST UNIT READY IN stage */
620 if (EXIT_SUCCESS
== mass_storage_send_scsi_csw_in())
623 /* Check for errors */
624 if (EXIT_SUCCESS
!= (error
= mass_storage_check_error())) {
625 MASS_MSG("SCSI sense error checking failed");
629 /* Ignore potential signal interruption (no return value check),
630 * since it causes driver termination anyway */
631 if (nanosleep(&test_wait
, NULL
))
632 MASS_MSG("Calling nanosleep() failed");
639 /*===========================================================================*
640 * mass_storage_check_error *
641 *===========================================================================*/
643 mass_storage_check_error(void)
645 /* SCSI sense structure for local use */
646 typedef struct MASS_PACKED scsi_sense
{
650 uint8_t obsolete
: 8;
652 uint8_t reserved
: 1;
655 uint8_t filemark
: 1;
656 uint32_t information
: 32;
657 uint8_t additional_len
: 8;
658 uint32_t command_specific
: 32;
659 uint8_t additional_code
: 8;
660 uint8_t additional_qual
: 8;
661 uint8_t unit_code
: 8;
662 uint8_t key_specific1
: 7;
664 uint16_t key_specific2
: 16;
668 /* Sense variable to hold received data */
673 /* Check if bit-fields are packed correctly */
674 __CTASSERT(sizeof(sense
) == SCSI_REQUEST_SENSE_DATA_LEN
);
676 /* SCSI REQUEST SENSE OUT stage */
677 if (mass_storage_send_scsi_cbw_out(SCSI_REQUEST_SENSE
, NULL
))
680 /* SCSI REQUEST SENSE first IN stage */
681 if (mass_storage_send_scsi_data_in(&sense
, sizeof(sense
)))
684 /* SCSI REQUEST SENSE second IN stage */
685 if (mass_storage_send_scsi_csw_in())
688 /* When any sense code is present something may have failed */
691 MASS_MSG("SCSI sense: ");
692 MASS_MSG("code : %8X", sense
.code
);
693 MASS_MSG("valid : %8X", sense
.valid
);
694 MASS_MSG("obsolete : %8X", sense
.obsolete
);
695 MASS_MSG("sense : %8X", sense
.sense
);
696 MASS_MSG("reserved : %8X", sense
.reserved
);
697 MASS_MSG("ili : %8X", sense
.ili
);
698 MASS_MSG("eom : %8X", sense
.eom
);
699 MASS_MSG("filemark : %8X", sense
.filemark
);
700 MASS_MSG("information : %8X", sense
.information
);
701 MASS_MSG("additional_len : %8X", sense
.additional_len
);
702 MASS_MSG("command_specific : %8X", sense
.command_specific
);
703 MASS_MSG("additional_code : %8X", sense
.additional_code
);
704 MASS_MSG("additional_qual : %8X", sense
.additional_qual
);
705 MASS_MSG("unit_code : %8X", sense
.unit_code
);
706 MASS_MSG("key_specific1 : %8X", sense
.key_specific1
);
707 MASS_MSG("sksv : %8X", sense
.sksv
);
708 MASS_MSG("key_specific2 : %8X", sense
.key_specific2
);
710 MASS_MSG("SCSI sense: 0x%02X 0x%02X 0x%02X", sense
.sense
,
711 sense
.additional_code
, sense
.additional_qual
);
719 /*===========================================================================*
720 * mass_storage_try_first_open *
721 *===========================================================================*/
723 mass_storage_try_first_open()
727 unsigned char inquiry
[SCSI_INQUIRY_DATA_LEN
];
728 unsigned char capacity
[SCSI_READ_CAPACITY_DATA_LEN
];
732 assert(NULL
!= driver_state
.cur_drive
);
734 llba
= 0; /* Last logical block address */
735 blen
= 0; /* Block length (usually 512B) */
737 /* Run TEST UNIT READY before other SCSI command
738 * Some devices refuse to work without this */
739 if (mass_storage_test())
742 /* SCSI INQUIRY OUT stage */
743 if (mass_storage_send_scsi_cbw_out(SCSI_INQUIRY
, NULL
))
746 /* SCSI INQUIRY first IN stage */
747 if (mass_storage_send_scsi_data_in(inquiry
, sizeof(inquiry
)))
750 /* SCSI INQUIRY second IN stage */
751 if (mass_storage_send_scsi_csw_in())
754 /* Check for proper reply */
755 if (check_inquiry_reply(inquiry
))
758 /* Run TEST UNIT READY before other SCSI command
759 * Some devices refuse to work without this */
760 if (mass_storage_test())
763 /* SCSI READ CAPACITY OUT stage */
764 if (mass_storage_send_scsi_cbw_out(SCSI_READ_CAPACITY
, NULL
))
767 /* SCSI READ CAPACITY first IN stage */
768 if (mass_storage_send_scsi_data_in(capacity
, sizeof(capacity
)))
771 /* SCSI READ CAPACITY second IN stage */
772 if (mass_storage_send_scsi_csw_in())
775 /* Check for proper reply */
776 if (check_read_capacity_reply(capacity
, &llba
, &blen
))
779 /* For now only Minix's default SECTOR_SIZE is supported */
780 if (SECTOR_SIZE
!= blen
)
781 panic("Invalid block size used by USB device!");
783 /* Get information about capacity from reply */
784 driver_state
.cur_drive
->disk
.dv_base
= 0;
785 driver_state
.cur_drive
->disk
.dv_size
= llba
* blen
;
791 /*===========================================================================*
792 * mass_storage_transfer_restrictions *
793 *===========================================================================*/
795 mass_storage_transfer_restrictions(u64_t pos
, unsigned long bytes
)
799 assert(NULL
!= driver_state
.cur_device
);
801 /* Zero-length request must not be issued */
803 MASS_MSG("Transfer request length equals 0");
807 /* Starting position must be aligned to sector */
808 if (0 != (pos
% SECTOR_SIZE
)) {
809 MASS_MSG("Transfer position not divisible by %u", SECTOR_SIZE
);
813 /* Length must be integer multiple of sector sizes */
814 if (0 != (bytes
% SECTOR_SIZE
)) {
815 MASS_MSG("Data length not divisible by %u", SECTOR_SIZE
);
819 /* Guard against ridiculous 64B overflow */
820 if ((pos
+ bytes
) <= pos
) {
821 MASS_MSG("Request outside available address space");
829 /*===========================================================================*
830 * mass_storage_write *
831 *===========================================================================*/
833 mass_storage_write(unsigned long sector_number
,
836 unsigned int iov_count
,
837 unsigned long bytes_left
)
840 * This function writes whatever was put in 'iov' array
841 * (iov[0] : iov[iov_count]), into continuous region of mass storage,
842 * starting from sector 'sector_number'. Total amount of 'iov'
843 * data should be greater or equal to initial value of 'bytes_left'.
845 * Endpoint value 'endpt', determines if vectors 'iov' contain memory
846 * addresses for copying or grant IDs.
849 iov_state cur_iov
; /* Current state of vector copying */
850 unsigned long bytes_to_write
; /* To be written in this iteration */
851 ssize_t bytes_already_written
; /* Total amount written (retval) */
855 /* Initialize locals */
856 cur_iov
.remaining_bytes
= 0; /* No IO vector initially */
857 cur_iov
.iov_idx
= 0; /* Starting from first vector */
858 bytes_already_written
= 0; /* Nothing copied yet */
860 /* Mass storage operations are sector based */
861 assert(0 == (sizeof(buffer
) % SECTOR_SIZE
));
862 assert(0 == (bytes_left
% SECTOR_SIZE
));
864 while (bytes_left
> 0) {
866 /* Fill write buffer with data from IO Vectors */
868 unsigned long buf_offset
;
869 unsigned long copy_len
;
871 /* Start copying to the beginning of the buffer */
874 /* Copy as long as not copied vectors exist or
875 * buffer is not fully filled */
878 /* If entire previous vector
879 * was used get new one */
880 if (0 == cur_iov
.remaining_bytes
) {
881 /* Check if there are
882 * vectors to copied */
883 if (cur_iov
.iov_idx
< iov_count
) {
886 iov
[cur_iov
.iov_idx
].iov_addr
;
887 cur_iov
.remaining_bytes
=
888 iov
[cur_iov
.iov_idx
].iov_size
;
893 /* All vectors copied */
898 /* Copy as much as it is possible from vector
899 * and at most the amount that can be
901 copy_len
= MIN(sizeof(buffer
) - buf_offset
,
902 cur_iov
.remaining_bytes
);
904 /* This distinction is required as transfer can
905 * be used from within this process and meaning
906 * of IO vector'a address is different than
909 memcpy(&buffer
[buf_offset
],
910 (void*)(cur_iov
.base_addr
+
911 cur_iov
.offset
), copy_len
);
914 if ((copy_res
= sys_safecopyfrom(endpt
,
918 (&buffer
[buf_offset
]),
920 MASS_MSG("sys_safecopyfrom "
926 /* Alter current state of copying */
927 buf_offset
+= copy_len
;
928 cur_iov
.offset
+= copy_len
;
929 cur_iov
.remaining_bytes
-= copy_len
;
931 /* Buffer was filled */
932 if (sizeof(buffer
) == buf_offset
)
936 /* Determine how many bytes from copied buffer we wish
937 * to write, buf_offset represents total amount of
938 * bytes copied above */
939 if (bytes_left
>= buf_offset
) {
940 bytes_to_write
= buf_offset
;
941 bytes_left
-= buf_offset
;
943 bytes_to_write
= bytes_left
;
948 /* Send URB and alter sector number */
949 if (bytes_to_write
> 0) {
953 info
.length
= bytes_to_write
;
954 info
.lba
= sector_number
;
956 /* SCSI WRITE first OUT stage */
957 if (mass_storage_send_scsi_cbw_out(SCSI_WRITE
, &info
))
960 /* SCSI WRITE second OUT stage */
961 if (mass_storage_send_scsi_data_out(buffer
,
965 /* SCSI WRITE IN stage */
966 if (mass_storage_send_scsi_csw_in())
969 /* Writing completed so shift starting
970 * sector for next iteration */
971 sector_number
+= bytes_to_write
/ SECTOR_SIZE
;
973 /* Update amount of data already copied */
974 bytes_already_written
+= bytes_to_write
;
978 return bytes_already_written
;
982 /*===========================================================================*
983 * mass_storage_read *
984 *===========================================================================*/
986 mass_storage_read(unsigned long sector_number
,
989 unsigned int iov_count
,
990 unsigned long bytes_left
)
993 * This function reads 'bytes_left' bytes of mass storage data into
994 * 'iov' array (iov[0] : iov[iov_count]) starting from sector
995 * 'sector_number'. Total amount of 'iov' data should be greater or
996 * equal to initial value of 'bytes_left'.
998 * Endpoint value 'endpt', determines if vectors 'iov' contain memory
999 * addresses for copying or grant IDs.
1002 iov_state cur_iov
; /* Current state of vector copying */
1003 unsigned long bytes_to_read
; /* To be read in this iteration */
1004 ssize_t bytes_already_read
; /* Total amount read (retval) */
1008 /* Initialize locals */
1009 cur_iov
.remaining_bytes
= 0; /* No IO vector initially */
1010 cur_iov
.iov_idx
= 0; /* Starting from first vector */
1011 bytes_already_read
= 0; /* Nothing copied yet */
1013 /* Mass storage operations are sector based */
1014 assert(0 == (sizeof(buffer
) % SECTOR_SIZE
));
1015 assert(0 == (bytes_left
% SECTOR_SIZE
));
1017 while (bytes_left
> 0) {
1019 /* Decide read length and alter remaining bytes */
1021 /* Number of bytes to be read in next URB */
1022 if (bytes_left
> sizeof(buffer
)) {
1023 bytes_to_read
= sizeof(buffer
);
1025 bytes_to_read
= bytes_left
;
1028 bytes_left
-= bytes_to_read
;
1031 /* Send URB and alter sector number */
1035 info
.length
= bytes_to_read
;
1036 info
.lba
= sector_number
;
1038 /* SCSI READ OUT stage */
1039 if (mass_storage_send_scsi_cbw_out(SCSI_READ
, &info
))
1042 /* SCSI READ first IN stage */
1043 if (mass_storage_send_scsi_data_in(buffer
,
1047 /* SCSI READ second IN stage */
1048 if (mass_storage_send_scsi_csw_in())
1051 /* Reading completed so shift starting
1052 * sector for next iteration */
1053 sector_number
+= bytes_to_read
/ SECTOR_SIZE
;
1056 /* Fill IO Vectors with data from buffer */
1058 unsigned long buf_offset
;
1059 unsigned long copy_len
;
1061 /* Start copying from the beginning of the buffer */
1064 /* Copy as long as there are unfilled vectors
1065 * or data in buffer remains */
1068 /* If previous vector was filled get new one */
1069 if (0 == cur_iov
.remaining_bytes
) {
1070 /* Check if there are vectors
1072 if (cur_iov
.iov_idx
< iov_count
) {
1075 iov
[cur_iov
.iov_idx
].iov_addr
;
1076 cur_iov
.remaining_bytes
=
1077 iov
[cur_iov
.iov_idx
].iov_size
;
1082 /* Total length of vectors
1083 * should be greater or equal
1084 * to initial value of
1085 * bytes_left. Being here means
1086 * that everything should
1087 * have been copied already */
1088 assert(0 == bytes_left
);
1093 /* Copy as much as it is possible from buffer
1094 * and at most the amount that can be
1096 copy_len
= MIN(bytes_to_read
- buf_offset
,
1097 cur_iov
.remaining_bytes
);
1099 /* This distinction is required as transfer can
1100 * be used from within this process and meaning
1101 * of IO vector'a address is different than
1103 if (endpt
== SELF
) {
1104 memcpy((void*)(cur_iov
.base_addr
+
1106 &buffer
[buf_offset
],
1110 if ((copy_res
= sys_safecopyto(endpt
,
1114 (&buffer
[buf_offset
]),
1116 MASS_MSG("sys_safecopyto "
1122 /* Alter current state of copying */
1123 buf_offset
+= copy_len
;
1124 cur_iov
.offset
+= copy_len
;
1125 cur_iov
.remaining_bytes
-= copy_len
;
1127 /* Everything was copied */
1128 if (bytes_to_read
== buf_offset
)
1132 /* Update amount of data already copied */
1133 bytes_already_read
+= buf_offset
;
1137 return bytes_already_read
;
1141 /*===========================================================================*
1142 * mass_storage_open *
1143 *===========================================================================*/
1145 mass_storage_open(devminor_t minor
, int UNUSED(access
))
1147 mass_storage_drive
* d
;
1152 /* Decode minor into drive device information */
1153 if (NULL
== (mass_storage_part(minor
)))
1156 /* Copy evaluated current drive for simplified dereference */
1157 d
= driver_state
.cur_drive
;
1159 #ifdef MASS_RESET_RECOVERY
1160 /* In case of previous CBW mismatch */
1161 if (mass_storage_reset_recovery()) {
1162 MASS_MSG("Resetting mass storage device failed");
1167 /* In case of missing endpoint information, do simple
1168 * enumeration and hold it for future use */
1169 if ((URB_INVALID_EP
== driver_state
.cur_periph
->ep_in
.ep_num
) ||
1170 (URB_INVALID_EP
== driver_state
.cur_periph
->ep_out
.ep_num
)) {
1172 if (mass_storage_get_endpoints(&driver_state
.cur_periph
->ep_in
,
1173 &driver_state
.cur_periph
->ep_out
))
1177 /* If drive hasn't been opened yet, try to open it */
1178 if (d
->open_ct
== 0) {
1179 if ((r
= mass_storage_try_first_open())) {
1180 MASS_MSG("Opening mass storage device"
1181 " for the first time failed");
1183 /* Do one more test before failing, to output
1184 * sense errors in case they weren't dumped already */
1185 if (mass_storage_test())
1186 MASS_MSG("Final TEST UNIT READY failed");
1191 /* Clear remembered device state for current
1192 * drive before calling partition */
1193 memset(&d
->part
[0], 0, sizeof(d
->part
));
1194 memset(&d
->subpart
[0], 0, sizeof(d
->subpart
));
1196 /* Try parsing partition table (for entire drive) */
1197 /* Warning!! This call uses mass_storage_part with own minors
1198 * and alters global driver_state.cur_device! */
1199 partition(&mass_storage
, (d
->drive_idx
* DEV_PER_DRIVE
),
1202 /* Decode minor into UPDATED drive device information */
1203 if (NULL
== (mass_storage_part(minor
)))
1206 /* Decoded size must be positive or else
1207 * we assume device (partition) is unavailable */
1208 if (0 == driver_state
.cur_device
->dv_size
)
1212 /* Run TEST UNIT READY before further commands
1213 * Some devices refuse to work without this */
1214 if (mass_storage_test())
1217 /* Opening completed */
1220 return EXIT_SUCCESS
;
1224 /*===========================================================================*
1225 * mass_storage_close *
1226 *===========================================================================*/
1227 static int mass_storage_close(devminor_t minor
)
1231 /* Decode minor into drive device information */
1232 if (NULL
== (mass_storage_part(minor
)))
1235 /* If drive hasn't been opened yet */
1236 if (driver_state
.cur_drive
->open_ct
== 0) {
1237 MASS_MSG("Device was not opened yet");
1241 /* Act accordingly */
1242 driver_state
.cur_drive
->open_ct
--;
1244 return EXIT_SUCCESS
;
1248 /*===========================================================================*
1249 * mass_storage_transfer *
1250 *===========================================================================*/
1252 mass_storage_transfer(devminor_t minor
, /* device minor number */
1253 int do_write
, /* 1 write, 0 read */
1254 u64_t pos
, /* position of starting point */
1255 endpoint_t endpt
, /* endpoint */
1256 iovec_t
* iov
, /* vector */
1257 unsigned int iov_count
, /* how many vectors */
1258 int UNUSED(flags
)) /* transfer flags */
1260 u64_t temp_sector_number
;
1261 unsigned long bytes
;
1262 unsigned long sector_number
;
1263 unsigned int cur_iov_idx
;
1268 /* Decode minor into drive device information */
1269 if (NULL
== (mass_storage_part(minor
)))
1274 /* How much data is going to be transferred? */
1275 for (cur_iov_idx
= 0; cur_iov_idx
< iov_count
; ++cur_iov_idx
) {
1277 /* Check if grant ID was supplied
1278 * instead of address and if it is valid */
1280 if (!GRANT_VALID((cp_grant_id_t
)
1281 (iov
[cur_iov_idx
].iov_addr
)))
1284 /* All supplied vectors must have positive length */
1285 if ((signed long)(iov
[cur_iov_idx
].iov_size
) <= 0) {
1286 MASS_MSG("Transfer request length is not positive");
1290 /* Requirements were met, more bytes can be transferred */
1291 bytes
+= iov
[cur_iov_idx
].iov_size
;
1293 /* Request size must never overflow */
1294 if ((signed long)bytes
<= 0) {
1295 MASS_MSG("Transfer request length overflowed");
1300 /* Check if reading beyond device/partition */
1301 if (pos
>= driver_state
.cur_device
->dv_size
) {
1302 MASS_MSG("Request out of bounds for given device");
1303 return 0; /* No error and no bytes read */
1306 /* Check if arguments agree with accepted restriction
1307 * for parameters of transfer */
1308 if ((r
= mass_storage_transfer_restrictions(pos
, bytes
)))
1311 /* If 'hard' requirements above were met, do additional
1312 * limiting to device/partition boundary */
1313 if ((pos
+ bytes
) > driver_state
.cur_device
->dv_size
)
1314 bytes
= (driver_state
.cur_device
->dv_size
- pos
) &
1317 /* We have to obtain sector number of given position
1318 * and limit it to what URB can handle */
1319 temp_sector_number
= (driver_state
.cur_device
->dv_base
+ pos
) /
1321 assert(temp_sector_number
< ULONG_MAX
); /* LBA is limited to 32B */
1322 sector_number
= (unsigned long)temp_sector_number
;
1325 return mass_storage_write(sector_number
, endpt
, iov
,
1328 return mass_storage_read(sector_number
, endpt
, iov
,
1333 /*===========================================================================*
1334 * mass_storage_ioctl *
1335 *===========================================================================*/
1337 mass_storage_ioctl(devminor_t minor
, unsigned long request
, endpoint_t endpt
,
1338 cp_grant_id_t grant
, endpoint_t
UNUSED(user_endpt
))
1342 /* Decode minor into drive device information */
1343 if (NULL
== (mass_storage_part(minor
)))
1348 if (sys_safecopyto(endpt
, grant
, 0,
1349 (vir_bytes
) &(driver_state
.cur_drive
->open_ct
),
1350 sizeof(driver_state
.cur_drive
->open_ct
)))
1351 panic("sys_safecopyto failed!");
1353 return EXIT_SUCCESS
;
1356 MASS_MSG("Unimplemented IOCTL request: 0x%X",
1365 /*===========================================================================*
1366 * mass_storage_cleanup *
1367 *===========================================================================*/
1368 static void mass_storage_cleanup(void)
1375 /*===========================================================================*
1376 * mass_storage_part *
1377 *===========================================================================*/
1378 static struct device
*
1379 mass_storage_part(devminor_t minor
)
1381 unsigned long sel_drive
;
1382 unsigned long sel_device
;
1386 /* Override every time before further decision */
1387 driver_state
.cur_drive
= NULL
;
1388 driver_state
.cur_device
= NULL
;
1389 driver_state
.cur_periph
= NULL
;
1391 /* Decode 'minor' code to find which device file was used */
1392 if (minor
< MINOR_d0p0s0
) {
1394 /* No sub-partitions used */
1395 sel_drive
= minor
/ DEV_PER_DRIVE
;
1396 sel_device
= minor
% DEV_PER_DRIVE
;
1398 /* Only valid minors */
1399 if (sel_drive
< MAX_DRIVES
) {
1400 /* Associate minor (device/partition)
1401 * with peripheral number */
1403 * Proper peripheral selection based
1404 * on minor should be here: */
1405 driver_state
.cur_periph
= &driver_state
.periph
[0];
1407 /* Select drive entry for opening count etc. */
1408 driver_state
.cur_drive
=
1409 &(driver_state
.cur_periph
->drives
[sel_drive
]);
1411 /* Select device entry for given device file */
1412 /* Device 0 means entire drive.
1413 * Devices 1,2,3,4 mean partitions 0,1,2,3 */
1414 if (0 == sel_device
)
1415 driver_state
.cur_device
=
1416 &(driver_state
.cur_drive
->disk
);
1418 driver_state
.cur_device
=
1419 &(driver_state
.cur_drive
->part
1425 /* Shift values accordingly */
1426 minor
-= MINOR_d0p0s0
;
1428 /* Sub-partitions used */
1429 sel_drive
= minor
/ SUBPART_PER_DISK
;
1430 sel_device
= minor
% SUBPART_PER_DISK
;
1432 /* Only valid minors */
1433 if (sel_drive
< MAX_DRIVES
) {
1434 /* Leave in case of ridiculously high number */
1435 if (minor
< SUBPART_PER_DISK
) {
1436 /* Associate minor (device/partition)
1437 * with peripheral number */
1439 * Proper peripheral selection based
1440 * on minor should be here: */
1441 driver_state
.cur_periph
=
1442 &driver_state
.periph
[0];
1444 /* Select drive entry for opening count etc. */
1445 driver_state
.cur_drive
=
1446 &(driver_state
.cur_periph
->drives
1448 /* Select device entry for given
1449 * sub-partition device file */
1450 driver_state
.cur_device
=
1451 &(driver_state
.cur_drive
->subpart
1457 /* Check for success */
1458 if (NULL
== driver_state
.cur_device
) {
1459 MASS_MSG("Device for minor: %u not found", minor
);
1461 /* Assign index as well */
1462 driver_state
.cur_drive
->drive_idx
= sel_drive
;
1465 return driver_state
.cur_device
;
1469 /*===========================================================================*
1470 * mass_storage_geometry *
1471 *===========================================================================*/
1472 /* This command is optional for most mass storage devices
1473 * It should rather be used with USB floppy disk reader */
1474 #ifdef MASS_USE_GEOMETRY
1476 mass_storage_geometry(devminor_t minor
, struct part_geom
* part
)
1478 char flexible_disk_page
[SCSI_MODE_SENSE_FLEX_DATA_LEN
];
1482 /* Decode minor into drive device information */
1483 if (NULL
== (mass_storage_part(minor
)))
1486 /* SCSI MODE SENSE OUT stage */
1487 if (mass_storage_send_scsi_cbw_out(SCSI_MODE_SENSE
, NULL
))
1490 /* SCSI MODE SENSE first IN stage */
1491 if (mass_storage_send_scsi_data_in(flexible_disk_page
,
1492 sizeof(flexible_disk_page
)))
1495 /* SCSI MODE SENSE second IN stage */
1496 if (mass_storage_send_scsi_csw_in())
1499 /* Get geometry from reply */
1500 if (check_mode_sense_reply(flexible_disk_page
, &(part
->cylinders
),
1501 &(part
->heads
), &(part
->sectors
)))
1505 mass_storage_geometry(devminor_t
UNUSED(minor
), struct part_geom
* part
)
1509 part
->cylinders
= part
->size
/ SECTOR_SIZE
;
1516 /*===========================================================================*
1517 * usb_driver_completion *
1518 *===========================================================================*/
1520 usb_driver_completion(void * UNUSED(priv
))
1522 /* Last request was completed so allow continuing
1523 * execution from place where semaphore was downed */
1524 ddekit_sem_up(mass_storage_sem
);
1528 /*===========================================================================*
1529 * usb_driver_connect *
1530 *===========================================================================*/
1532 usb_driver_connect(struct ddekit_usb_dev
* dev
,
1533 unsigned int interfaces
)
1538 * Some sort of more complex peripheral assignment should be here */
1539 driver_state
.cur_periph
= &driver_state
.periph
[0];
1541 if (NULL
!= driver_state
.cur_periph
->dev
)
1542 panic("Only one peripheral can be connected!");
1544 /* Hold host information for future use */
1545 driver_state
.cur_periph
->dev
= dev
;
1546 driver_state
.cur_periph
->interfaces
= interfaces
;
1547 driver_state
.cur_periph
->ep_in
.ep_num
= URB_INVALID_EP
;
1548 driver_state
.cur_periph
->ep_out
.ep_num
= URB_INVALID_EP
;
1552 /*===========================================================================*
1553 * usb_driver_disconnect *
1554 *===========================================================================*/
1556 usb_driver_disconnect(struct ddekit_usb_dev
* UNUSED(dev
))
1561 * Some sort of peripheral discard should be here */
1562 driver_state
.cur_periph
= &driver_state
.periph
[0];
1564 assert(NULL
!= driver_state
.cur_periph
->dev
);
1567 driver_state
.cur_periph
->dev
= NULL
;
1568 driver_state
.cur_periph
->interfaces
= 0;
1569 driver_state
.cur_periph
->ep_in
.ep_num
= URB_INVALID_EP
;
1570 driver_state
.cur_periph
->ep_out
.ep_num
= URB_INVALID_EP
;
1574 /*===========================================================================*
1575 * mass_storage_get_endpoints *
1576 *===========================================================================*/
1578 mass_storage_get_endpoints(urb_ep_config
* ep_in
, urb_ep_config
* ep_out
)
1580 /* URB to be send */
1581 struct ddekit_usb_urb urb
;
1583 /* Setup buffer to be attached */
1584 struct usb_ctrlrequest setup_buf
;
1586 /* Control EP configuration */
1587 urb_ep_config ep_conf
;
1589 /* Descriptors' buffer */
1590 unsigned char descriptors
[MAX_DESCRIPTORS_LEN
];
1594 /* Initialize EP configuration */
1596 ep_conf
.direction
= DDEKIT_USB_IN
;
1597 ep_conf
.type
= DDEKIT_USB_TRANSFER_CTL
;
1598 ep_conf
.max_packet_size
= 0;
1599 ep_conf
.interval
= 0;
1601 /* Reset URB and assign given values */
1602 init_urb(&urb
, driver_state
.cur_periph
->dev
, &ep_conf
);
1604 /* Clear setup data */
1605 memset(&setup_buf
, 0, sizeof(setup_buf
));
1607 /* Standard get endpoint request */
1608 setup_buf
.bRequestType
= 0x80; /* Device to host */
1609 setup_buf
.bRequest
= UR_GET_DESCRIPTOR
;
1610 setup_buf
.wValue
= UDESC_CONFIG
<< 8; /* TODO: configuration 0 */
1611 setup_buf
.wIndex
= 0x00;
1612 setup_buf
.wLength
= MAX_DESCRIPTORS_LEN
;
1614 /* Attach buffers to URB */
1615 attach_urb_data(&urb
, URB_BUF_TYPE_SETUP
,
1616 &setup_buf
, sizeof(setup_buf
));
1617 attach_urb_data(&urb
, URB_BUF_TYPE_DATA
,
1618 descriptors
, sizeof(descriptors
));
1620 /* Send and wait for response */
1621 if (blocking_urb_submit(&urb
, mass_storage_sem
,
1622 URB_SUBMIT_ALLOW_MISMATCH
))
1623 return EXIT_FAILURE
;
1625 /* Check if buffer was supposed to hold more data */
1626 if (urb
.size
< urb
.actual_length
) {
1627 MASS_MSG("Too much descriptor data received");
1628 return EXIT_FAILURE
;
1631 return mass_storage_parse_descriptors(urb
.data
, urb
.actual_length
,
1636 /*===========================================================================*
1637 * mass_storage_parse_endpoint *
1638 *===========================================================================*/
1640 mass_storage_parse_endpoint(usb_descriptor_t
* cur_desc
,
1641 urb_ep_config
* ep_in
, urb_ep_config
* ep_out
)
1643 usb_endpoint_descriptor_t
* ep_desc
;
1645 urb_ep_config
* this_ep
;
1649 ep_desc
= (usb_endpoint_descriptor_t
*)cur_desc
;
1651 /* Only bulk with no other attributes are important */
1652 if (UE_BULK
== ep_desc
->bmAttributes
) {
1654 /* Check for direction */
1655 if (UE_DIR_IN
== UE_GET_DIR(ep_desc
->bEndpointAddress
)) {
1658 this_ep
->direction
= DDEKIT_USB_IN
;
1663 this_ep
->direction
= DDEKIT_USB_OUT
;
1666 /* Check if it was set before */
1667 if (URB_INVALID_EP
!= this_ep
->ep_num
) {
1668 MASS_MSG("BULK EP already set");
1669 return EXIT_FAILURE
;
1673 this_ep
->ep_num
= UE_GET_ADDR(ep_desc
->bEndpointAddress
);
1674 this_ep
->type
= DDEKIT_USB_TRANSFER_BLK
;
1675 this_ep
->max_packet_size
= UGETW(ep_desc
->wMaxPacketSize
);
1676 this_ep
->interval
= ep_desc
->bInterval
;
1679 /* EP type other than bulk, is also correct,
1680 * just no parsing is performed */
1681 return EXIT_SUCCESS
;
1684 /*===========================================================================*
1685 * mass_storage_parse_descriptors *
1686 *===========================================================================*/
1688 mass_storage_parse_descriptors(char * desc_buf
, unsigned int buf_len
,
1689 urb_ep_config
* ep_in
, urb_ep_config
* ep_out
)
1691 /* Currently parsed, descriptors */
1692 usb_descriptor_t
* cur_desc
;
1693 usb_interface_descriptor_t
* ifc_desc
;
1695 /* Byte counter for descriptor parsing */
1696 unsigned int cur_byte
;
1698 /* Non zero if recently parsed interface is valid for this device */
1699 int valid_interface
;
1703 /* Parse descriptors to get endpoints */
1704 ep_in
->ep_num
= URB_INVALID_EP
;
1705 ep_out
->ep_num
= URB_INVALID_EP
;
1706 valid_interface
= 0;
1709 while (cur_byte
< buf_len
) {
1711 /* Map descriptor to buffer */
1712 /* Structure is packed so alignment should not matter */
1713 cur_desc
= (usb_descriptor_t
*)&(desc_buf
[cur_byte
]);
1715 /* Check this so we won't be reading
1716 * memory outside the buffer */
1717 if ((cur_desc
->bLength
> 3) &&
1718 (cur_byte
+ cur_desc
->bLength
<= buf_len
)) {
1720 /* Parse based on descriptor type */
1721 switch (cur_desc
->bDescriptorType
) {
1723 case UDESC_CONFIG
: {
1724 if (USB_CONFIG_DESCRIPTOR_SIZE
!=
1725 cur_desc
->bLength
) {
1726 MASS_MSG("Wrong configuration"
1727 " descriptor length");
1728 return EXIT_FAILURE
;
1736 case UDESC_INTERFACE
: {
1738 (usb_interface_descriptor_t
*)cur_desc
;
1740 if (USB_INTERFACE_DESCRIPTOR_SIZE
!=
1741 cur_desc
->bLength
) {
1742 MASS_MSG("Wrong interface"
1743 " descriptor length");
1744 return EXIT_FAILURE
;
1747 /* Check if following data is meant
1748 * for our interfaces */
1749 if ((1 << ifc_desc
->bInterfaceNumber
) &
1750 driver_state
.cur_periph
->interfaces
)
1751 valid_interface
= 1;
1753 valid_interface
= 0;
1758 case UDESC_ENDPOINT
: {
1759 if (USB_ENDPOINT_DESCRIPTOR_SIZE
!=
1760 cur_desc
->bLength
) {
1761 MASS_MSG("Wrong endpoint"
1762 " descriptor length");
1763 return EXIT_FAILURE
;
1766 /* Previous interface was,
1767 * what we were looking for */
1768 if (valid_interface
) {
1770 mass_storage_parse_endpoint(
1771 cur_desc
, ep_in
, ep_out
))
1772 return EXIT_FAILURE
;
1780 MASS_MSG("Wrong descriptor type");
1781 return EXIT_FAILURE
;
1786 MASS_MSG("Invalid descriptor length");
1787 return EXIT_FAILURE
;
1790 /* Get next descriptor */
1791 cur_byte
+= cur_desc
->bLength
;
1794 /* Total length should match sum of all descriptors' lengths... */
1795 if (cur_byte
> buf_len
)
1796 return EXIT_FAILURE
;
1798 /* ...and descriptors should be valid */
1799 if ((URB_INVALID_EP
== ep_in
->ep_num
) ||
1800 (URB_INVALID_EP
== ep_out
->ep_num
)) {
1801 MASS_MSG("Valid bulk endpoints not found");
1802 return EXIT_FAILURE
;
1805 return EXIT_SUCCESS
;