Beispiel #1
0
def send_mass_storage_command(handle, endpoint, lun, cdb, direction,
                              data_length, ret_tag):

    global _tag

    #int i, r;

    cbw = command_block_wrapper()

    if not cdb:
        return -1

    if endpoint & usb.LIBUSB_ENDPOINT_IN:
        perr("send_mass_storage_command: cannot send command on IN endpoint\n")
        return -1

#ct.c_uint8 cdb_len;
    cdb_len = cdb_length[cdb[0]]
    if cdb_len == 0 or cdb_len > ct.sizeof(cbw.CBWCB):
        perr(
            "send_mass_storage_command: don't know how to handle this command ({:02X}, length {})\n",
            cdb[0], cdb_len)
        return -1

    cbw.dCBWSignature[0] = 'U'
    cbw.dCBWSignature[1] = 'S'
    cbw.dCBWSignature[2] = 'B'
    cbw.dCBWSignature[3] = 'C'
    ret_tag[0] = _tag
    cbw.dCBWTag = _tag
    cbw.dCBWDataTransferLength = data_length
    cbw.bmCBWFlags = direction
    cbw.bCBWLUN = lun
    _tag += 1
    # Subclass is 1 or 6 => cdb_len
    cbw.bCBWCBLength = cdb_len
    memcpy(cbw.CBWCB, cdb, cdb_len)

    i = 0
    while True:
        # The transfer length must always be exactly 31 bytes.
        size = ct.c_int()
        r = usb.bulk_transfer(handle, endpoint,
                              ct.cast(ct.pointer(cbw), ct.POINTER(ct.c_ubyte)),
                              31, ct.byref(size), 1000)
        if r == usb.LIBUSB_ERROR_PIPE:
            usb.clear_halt(handle, endpoint)
        i += 1
        if r != usb.LIBUSB_ERROR_PIPE or i >= RETRY_MAX:
            break
    if r != usb.LIBUSB_SUCCESS:
        perr("   send_mass_storage_command: {}\n", usb.strerror(usb.error(r)))
        return -1

    print("   sent {} CDB bytes".format(cdb_len))
    return 0
Beispiel #2
0
def get_mass_storage_status(handle, endpoint, expected_tag):

    #int r;

    csw = command_status_wrapper()

    # The device is allowed to STALL this transfer. If it does, you have to
    # clear the stall and try again.
    i = 0
    while True:
        size = ct.c_int()
        r = usb.bulk_transfer(handle, endpoint,
                              ct.cast(ct.pointer(csw), ct.POINTER(ct.c_ubyte)),
                              13, ct.byref(size), 1000)
        if r == usb.LIBUSB_ERROR_PIPE:
            usb.clear_halt(handle, endpoint)
        i += 1
        if r != usb.LIBUSB_ERROR_PIPE or i >= RETRY_MAX:
            break
    if r != usb.LIBUSB_SUCCESS:
        perr("   get_mass_storage_status: {}\n", usb.strerror(usb.error(r)))
        return -1
    size = size.value
    if size != 13:
        perr("   get_mass_storage_status: received {} bytes (expected 13)\n",
             size)
        return -1
    if csw.dCSWTag != expected_tag:
        perr(
            "   get_mass_storage_status: mismatched tags (expected {:08X}, received {:08X})\n",
            expected_tag, csw.dCSWTag)
        return -1
    # For this test, we ignore the dCSWSignature check for validity...
    print("   Mass Storage Status: {:02X} ({})".format(
        csw.bCSWStatus, "FAILED" if csw.bCSWStatus else "Success"))
    if csw.dCSWTag != expected_tag:
        return -1
    if csw.bCSWStatus:
        # REQUEST SENSE is appropriate only if bCSWStatus is 1, meaning that the
        # command failed somehow.  Larger values (2 in particular) mean that
        # the command couldn't be understood.
        if csw.bCSWStatus == 1:
            return -2  # request Get Sense
        else:
            return -1

    # In theory we also should check dCSWDataResidue.  But lots of devices
    # set it wrongly.
    return 0
Beispiel #3
0
def test_hid(handle, endpoint_in):

    global binary_dump
    global binary_name

    #int r;

    hid_report_descriptor = (ct.c_uint8 * 256)()
    report_buffer = ct.POINTER(ct.c_uint8)

    print("\nReading HID Report Descriptors:")
    descriptor_size = usb.control_transfer(handle,
                                           usb.LIBUSB_ENDPOINT_IN |
                                           usb.LIBUSB_REQUEST_TYPE_STANDARD |
                                           usb.LIBUSB_RECIPIENT_INTERFACE,
                                           usb.LIBUSB_REQUEST_GET_DESCRIPTOR,
                                           usb.LIBUSB_DT_REPORT << 8, 0,
                                           hid_report_descriptor,
                                           ct.sizeof(hid_report_descriptor),
                                           1000)
    if descriptor_size < 0:
        print("   Failed")
        return -1
    display_buffer_hex(hid_report_descriptor, descriptor_size)
    if binary_dump:
        try:
            fd = open(binary_name, "w")
        except: pass
        else:
            with fd:
                if fd.fwrite(hid_report_descriptor, descriptor_size) != descriptor_size:
                    print("   Error writing descriptor to file")

    size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_FEATURE)
    if size <= 0:
        print("\nSkipping Feature Report readout (None detected)")
    else:
        report_buffer = ct.cast(calloc(size, 1), ct.POINTER(ct.c_uint8))
        if not report_buffer:
            return -1

        print("\nReading Feature Report (length {})...".format(size))
        r = usb.control_transfer(handle,
                                 usb.LIBUSB_ENDPOINT_IN |
                                 usb.LIBUSB_REQUEST_TYPE_CLASS |
                                 usb.LIBUSB_RECIPIENT_INTERFACE,
                                 HID_GET_REPORT,
                                 (HID_REPORT_TYPE_FEATURE << 8) | 0, 0,
                                 report_buffer, ct.c_uint16(size),
                                 5000)
        if r >= 0:
            display_buffer_hex(report_buffer, size)
        else:
            if r == usb.LIBUSB_ERROR_NOT_FOUND:
                print("   No Feature Report available for this device")
            elif r == usb.LIBUSB_ERROR_PIPE:
                print("   Detected stall - resetting pipe...")
                usb.clear_halt(handle, 0)
            else:
                print("   Error: {}".format(usb.strerror(usb.error(r))))

        free(report_buffer)

    size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_REPORT_TYPE_INPUT)
    if size <= 0:
        print("\nSkipping Input Report readout (None detected)")
    else:
        report_buffer = ct.cast(calloc(size, 1), ct.POINTER(ct.c_uint8))
        if not report_buffer:
            return -1

        print("\nReading Input Report (length {})...".format(size))
        r = usb.control_transfer(handle,
                                 usb.LIBUSB_ENDPOINT_IN |
                                 usb.LIBUSB_REQUEST_TYPE_CLASS |
                                 usb.LIBUSB_RECIPIENT_INTERFACE,
                                 HID_GET_REPORT,
                                 (HID_REPORT_TYPE_INPUT << 8) | 0x00, 0,
                                 report_buffer, ct.c_uint16(size),
                                 5000)
        if r >= 0:
            display_buffer_hex(report_buffer, size)
        else:
            if r == usb.LIBUSB_ERROR_TIMEOUT:
                print("   Timeout! Please make sure you act on the device within the 5 seconds allocated...")
            elif r == usb.LIBUSB_ERROR_PIPE:
                print("   Detected stall - resetting pipe...")
                usb.clear_halt(handle, 0)
            else:
                print("   Error: {}".format(usb.strerror(usb.error(r))))

        # Attempt a bulk read from endpoint 0 (this should just return a raw input report)
        print("\nTesting interrupt read using endpoint {:02X}...".format(endpoint_in))
        r = usb.interrupt_transfer(handle, endpoint_in, report_buffer, size, ct.byref(size), 5000)
        if r >= 0:
            display_buffer_hex(report_buffer, size)
        else:
            print("   {}".format(usb.strerror(usb.error(r))))

        free(report_buffer)

    return 0