Low-level API

While verbose, the low-level API can be used to send any arbitrary command to devices. SMARTie provides pre-defined enums and structures for many common commands, but you can also send any command you like by defining your own ctypes.Structure.

Warning

The low-level API can be dangerous - send the wrong command and you could permanently wipe or even physically damage your device. Do not use this API unless you are absolutely sure of what you are doing. No warranty is provided for any damage caused by using this API.

If you don’t know what kind of device you have, it may be dangerous to send arbitrary commands. You can simply use isinstance to determine the type of device you have:

from smartie.device import get_device
from smartie.scsi import SCSIDevice
from smartie.nvme import NVMEDevice

with get_device('\\\\.\\PhysicalDrive0') as device:
    if isinstance(device, SCSIDevice):
        print('SCSI device')
    elif isinstance(device, NVMEDevice):
        print('NVMe device')
    else:
        print('Unknown device type')

SCSI

To send an SCSI INQUIRY command to a device:

import ctypes

from smartie.scsi import structures
from smartie.device import get_device

with get_device('\\\\.\\PhysicalDrive0') as device:
    # The structure that will be populated with the response.
    inquiry = structures.InquiryResponse()

    response = device.issue_command(
        # The direction of the data transfer.
        structures.Direction.FROM,
        # The command to send.
        structures.InquiryCommand(
            operation_code=structures.OperationCode.INQUIRY,
            allocation_length=ctypes.sizeof(inquiry)
        ),
        inquiry
    )

    if response:
      print(inquiry.product_identification)

The response object we get back from our issue_command is an smartie.scsi.SCSIResponse object that contains some common cross-platform fields as well as the raw platform-specific header that was sent to the device. This can be useful for debugging or for extracting additional information from the response.

NVMe

To send an NVMe IDENTIFY command to a device:

import ctypes

from smartie.nvme import structures
from smartie.device import get_device

with get_device('/dev/nvme0') as device:
    # The structure that will be populated with the response.
    data = structures.NVMEIdentifyResponse()
    device.issue_admin_command(
        structures.NVMEAdminCommand(
            opcode=structures.NVMEAdminCommands.IDENTIFY,
            addr=ctypes.addressof(data),
            data_len=ctypes.sizeof(data),
            cdw10=1
        )
    )
    print(data.model_number)