Changeset 70c12d6 in mainline


Ignore:
Timestamp:
2011-05-11T19:20:06Z (13 years ago)
Author:
Vojtech Horky <vojtechhorky@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
cf002dbf
Parents:
19387b61
Message:

Fix inquiry of USB mass storage

The problem was bad endianness in SCSI command descriptor block
(damn, why we need different endianness at all?).

Location:
uspace/drv/usbmast
Files:
1 added
4 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/usbmast/Makefile

    r19387b61 r70c12d6  
    4141
    4242SOURCES = \
     43        inquiry.c \
    4344        main.c \
    4445        mast.c
  • uspace/drv/usbmast/main.c

    r19387b61 r70c12d6  
    7575};
    7676
    77 #define BITS_GET_MASK(type, bitcount) (((type)(1 << (bitcount)))-1)
    78 #define BITS_GET_MID_MASK(type, bitcount, offset) \
    79         ((type)( BITS_GET_MASK(type, (bitcount) + (offset)) - BITS_GET_MASK(type, bitcount) ))
    80 #define BITS_GET(type, number, bitcount, offset) \
    81         ((type)( (number) & (BITS_GET_MID_MASK(type, bitcount, offset)) ) >> (offset))
    82 
    83 #define INQUIRY_RESPONSE_LENGTH 35
    84 
    85 static void try_inquiry(usb_device_t *dev)
    86 {
    87         scsi_cmd_inquiry_t inquiry = {
    88                 .op_code = 0x12,
    89                 .lun_evpd = 0,
    90                 .page_code = 0,
    91                 .alloc_length = INQUIRY_RESPONSE_LENGTH,
    92                 .ctrl = 0
    93         };
    94         size_t response_len;
    95         uint8_t response[INQUIRY_RESPONSE_LENGTH];
    96 
    97         int rc;
    98 
    99         rc = usb_massstor_data_in(GET_BULK_IN(dev), GET_BULK_OUT(dev),
    100             0xDEADBEEF, 0, (uint8_t *) &inquiry, sizeof(inquiry),
    101             response, INQUIRY_RESPONSE_LENGTH, &response_len);
    102 
    103         if (rc != EOK) {
    104                 usb_log_error("Failed to probe device %s using %s: %s.\n",
    105                    dev->ddf_dev->name, "SCSI:INQUIRY", str_error(rc));
    106                 return;
    107         }
    108 
    109         if (response_len < 8) {
    110                 usb_log_error("The SCSI response is too short.\n");
    111                 return;
    112         }
    113 
    114         /*
    115          * This is an ugly part of the code. We will parse the returned
    116          * data by hand and try to get as many useful data as possible.
    117          */
    118         int device_type = BITS_GET(uint8_t, response[0], 5, 0);
    119         int removable = BITS_GET(uint8_t, response[1], 1, 7);
    120 
    121         usb_log_info("SCSI information for device `%s':\n", dev->ddf_dev->name);
    122         usb_log_info("  - peripheral device type: %d\n", device_type);
    123         usb_log_info("  - removable: %s\n", removable ? "yes" : "no");
    124 
    125         if (response_len < 32) {
    126                 return;
    127         }
    128 
    129         char dev_vendor[9];
    130         str_ncpy(dev_vendor, 9, (const char *) &response[8], 8);
    131         usb_log_info("  - vendor: '%s'\n", dev_vendor);
    132 
    133         char dev_product[9];
    134         str_ncpy(dev_product, 9, (const char *) &response[16], 8);
    135         usb_log_info("  - product: '%s'\n", dev_vendor);
    136 }
    137 
    13877/** Callback when new device is attached and recognized as a mass storage.
    13978 *
     
    168107            (size_t) dev->pipes[BULK_OUT_EP].descriptor->max_packet_size);
    169108
    170         try_inquiry(dev);
     109        int lun_count = usb_massstor_get_max_lun(dev);
     110        /* Return value:
     111         * rc < 0 => device does not know this request, only single LUN
     112         *     could be present
     113         * rc >= 0 - the rc is the maximum LUN, thus count is +1
     114         */
     115        if (lun_count < 0) {
     116                lun_count = 1;
     117        } else {
     118                lun_count++;
     119        }
     120
     121        usb_massstor_inquiry_result_t inquiry;
     122        rc = usb_massstor_inquiry(dev, BULK_IN_EP, BULK_OUT_EP, &inquiry);
     123        if (rc != EOK) {
     124                usb_log_warning("Failed to inquiry device `%s': %s.\n",
     125                    dev->ddf_dev->name, str_error(rc));
     126                return EOK;
     127        }
     128
     129        usb_log_info("Mass storage `%s': `%s' by `%s' is %s (%s), %d LUN(s).\n",
     130            dev->ddf_dev->name,
     131            inquiry.product_and_revision, inquiry.vendor_id,
     132            usb_str_masstor_scsi_peripheral_device_type(inquiry.peripheral_device_type),
     133            inquiry.removable ? "removable" : "non-removable",
     134            lun_count);
    171135
    172136        return EOK;
  • uspace/drv/usbmast/mast.c

    r19387b61 r70c12d6  
    4040#include <str_error.h>
    4141#include <usb/debug.h>
     42#include <usb/request.h>
    4243
    4344bool usb_mast_verbose = true;
     
    6364 * @return Error code.
    6465 */
    65 int usb_massstor_data_in(usb_pipe_t *bulk_in_pipe, usb_pipe_t *bulk_out_pipe,
     66int usb_massstor_data_in(usb_device_t *dev,
     67    size_t bulk_in_pipe_index, size_t bulk_out_pipe_index,
    6668    uint32_t tag, uint8_t lun, void *cmd, size_t cmd_size,
    6769    void *in_buffer, size_t in_buffer_size, size_t *received_size)
     
    6971        int rc;
    7072        size_t act_size;
     73        usb_pipe_t *bulk_in_pipe = dev->pipes[bulk_in_pipe_index].pipe;
     74        usb_pipe_t *bulk_out_pipe = dev->pipes[bulk_out_pipe_index].pipe;
    7175
    7276        /* Prepare CBW - command block wrapper */
     
    135139}
    136140
     141int usb_massstor_reset(usb_device_t *dev)
     142{
     143        return usb_control_request_set(&dev->ctrl_pipe,
     144            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     145            0xFF, 0, dev->interface_no, NULL, 0);
     146}
     147
     148void usb_massstor_reset_recovery(usb_device_t *dev,
     149    size_t bulk_in_idx, size_t bulk_out_idx)
     150{
     151        /* We would ignore errors here because if this fails
     152         * we are doomed anyway and any following transaction would fail.
     153         */
     154        usb_massstor_reset(dev);
     155        usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_in_idx].pipe);
     156        usb_pipe_clear_halt(&dev->ctrl_pipe, dev->pipes[bulk_out_idx].pipe);
     157}
     158
     159int usb_massstor_get_max_lun(usb_device_t *dev)
     160{
     161        uint8_t max_lun;
     162        size_t data_recv_len;
     163        int rc = usb_control_request_get(&dev->ctrl_pipe,
     164            USB_REQUEST_TYPE_CLASS, USB_REQUEST_RECIPIENT_INTERFACE,
     165            0xFE, 0, dev->interface_no, &max_lun, 1, &data_recv_len);
     166        if (rc != EOK) {
     167                return rc;
     168        }
     169        if (data_recv_len != 1) {
     170                return EEMPTY;
     171        }
     172        return (int) max_lun;
     173}
     174
    137175/**
    138176 * @}
  • uspace/drv/usbmast/mast.h

    r19387b61 r70c12d6  
    4040#include <usb/usb.h>
    4141#include <usb/pipes.h>
     42#include <usb/devdrv.h>
    4243
    43 int usb_massstor_data_in(usb_pipe_t *, usb_pipe_t *, uint32_t, uint8_t,
    44     void *, size_t, void *, size_t, size_t *);
     44typedef struct {
     45        int peripheral_device_type;
     46        bool removable;
     47        char vendor_id[9];
     48        char product_and_revision[12];
     49} usb_massstor_inquiry_result_t;
     50
     51int usb_massstor_data_in(usb_device_t *dev, size_t, size_t,
     52    uint32_t, uint8_t, void *, size_t, void *, size_t, size_t *);
     53int usb_massstor_reset(usb_device_t *);
     54void usb_massstor_reset_recovery(usb_device_t *, size_t, size_t);
     55int usb_massstor_get_max_lun(usb_device_t *);
     56int usb_massstor_inquiry(usb_device_t *, size_t, size_t,
     57    usb_massstor_inquiry_result_t *);
     58const char *usb_str_masstor_scsi_peripheral_device_type(int);
    4559
    4660#endif
Note: See TracChangeset for help on using the changeset viewer.