File indexing completed on 2024-05-26 04:05:40

0001 /*
0002     SPDX-FileCopyrightText: 2013 Patrick von Reth <vonreth@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "winopticaldrive.h"
0008 
0009 #include <ntddcdrm.h>
0010 #include <ntddmmc.h>
0011 
0012 using namespace Solid::Backends::Win;
0013 
0014 WinOpticalDrive::WinOpticalDrive(WinDevice *device)
0015     : WinStorageDrive(device)
0016 {
0017     const QMap<ulong, MediaProfiles> profiles = MediaProfiles::profiles(WinBlock::driveLetterFromUdi(m_device->udi()));
0018     for (const MediaProfiles &p : profiles) {
0019         m_supportedTypes |= p.type;
0020     }
0021 }
0022 
0023 WinOpticalDrive::~WinOpticalDrive()
0024 {
0025 }
0026 
0027 Solid::OpticalDrive::MediumTypes WinOpticalDrive::supportedMedia() const
0028 {
0029     return m_supportedTypes;
0030 }
0031 
0032 bool WinOpticalDrive::eject()
0033 {
0034     WinDeviceManager::deviceAction(WinBlock::driveLetterFromUdi(m_device->udi()), IOCTL_STORAGE_EJECT_MEDIA);
0035     return true;
0036 }
0037 
0038 QList<int> WinOpticalDrive::writeSpeeds() const
0039 {
0040     return QList<int>();
0041 }
0042 
0043 int WinOpticalDrive::writeSpeed() const
0044 {
0045     return 0;
0046 }
0047 
0048 int WinOpticalDrive::readSpeed() const
0049 {
0050     return 0;
0051 }
0052 
0053 MediaProfiles::MediaProfiles()
0054     : profile(0)
0055     , type(0)
0056     , active(false)
0057 {
0058 }
0059 
0060 MediaProfiles::MediaProfiles(ulong profile, Solid::OpticalDrive::MediumTypes type, QString name)
0061     : profile(profile)
0062     , type(type)
0063     , name(name)
0064     , active(false)
0065 {
0066 }
0067 
0068 MediaProfiles::MediaProfiles(FEATURE_DATA_PROFILE_LIST_EX *feature)
0069     : profile(0)
0070     , type(0)
0071     , active(false)
0072 {
0073     ulong val = (feature->ProfileNumber[0] << 8 | feature->ProfileNumber[1] << 0);
0074     MediaProfiles p = MediaProfiles::getProfile(val);
0075     if (!p.isNull()) {
0076         profile = p.profile;
0077         type = p.type;
0078         name = p.name;
0079         active = feature->Current;
0080     }
0081 }
0082 
0083 bool MediaProfiles::isNull()
0084 {
0085     return name.isNull();
0086 }
0087 
0088 QMap<ulong, MediaProfiles> MediaProfiles::profiles(const QString &drive)
0089 {
0090     // thx to http://www.adras.com/Determine-optical-drive-type-and-capabilities.t6826-144-1.html
0091 
0092     QMap<ulong, MediaProfiles> out;
0093     DWORD buffSize = 1024;
0094     char buffer[1024];
0095     GET_CONFIGURATION_IOCTL_INPUT input;
0096     ZeroMemory(&input, sizeof(GET_CONFIGURATION_IOCTL_INPUT));
0097     input.Feature = FeatureProfileList;
0098     input.RequestType = SCSI_GET_CONFIGURATION_REQUEST_TYPE_ALL;
0099 
0100     WinDeviceManager::getDeviceInfo<char, GET_CONFIGURATION_IOCTL_INPUT>(drive, IOCTL_CDROM_GET_CONFIGURATION, buffer, buffSize, &input);
0101 
0102     GET_CONFIGURATION_HEADER *info = (GET_CONFIGURATION_HEADER *)buffer;
0103     FEATURE_DATA_PROFILE_LIST *profile = (FEATURE_DATA_PROFILE_LIST *)info->Data;
0104     FEATURE_DATA_PROFILE_LIST_EX *feature = profile->Profiles;
0105     for (int i = 0; i < profile->Header.AdditionalLength / 4; ++feature, ++i) {
0106         MediaProfiles p = MediaProfiles(feature);
0107         if (!p.isNull()) {
0108             out.insert(p.profile, p);
0109         }
0110     }
0111 
0112     return out;
0113 }
0114 
0115 const MediaProfiles MediaProfiles::getProfile(ulong val)
0116 {
0117 #define AddProfile(profile, type) profiles.insert(profile, MediaProfiles(profile, type, #profile))
0118     static QMap<ulong, MediaProfiles> profiles;
0119     if (profiles.isEmpty()) {
0120         AddProfile(ProfileCdrom, Solid::OpticalDrive::UnknownMediumType);
0121         AddProfile(ProfileCdRecordable, Solid::OpticalDrive::Cdr);
0122         AddProfile(ProfileCdRewritable, Solid::OpticalDrive::Cdrw);
0123         AddProfile(ProfileDvdRom, Solid::OpticalDrive::Dvd);
0124         AddProfile(ProfileDvdRecordable, Solid::OpticalDrive::Dvdr);
0125         AddProfile(ProfileDvdRewritable, Solid::OpticalDrive::Dvdrw);
0126         AddProfile(ProfileDvdRam, Solid::OpticalDrive::Dvdram);
0127         AddProfile(ProfileDvdPlusR, Solid::OpticalDrive::Dvdplusr);
0128         AddProfile(ProfileDvdPlusRW, Solid::OpticalDrive::Dvdplusrw);
0129         AddProfile(ProfileDvdPlusRDualLayer, Solid::OpticalDrive::Dvdplusdl);
0130         AddProfile(ProfileDvdPlusRWDualLayer, Solid::OpticalDrive::Dvdplusdlrw);
0131         AddProfile(ProfileBDRom, Solid::OpticalDrive::Bd);
0132         AddProfile(ProfileBDRRandomWritable, Solid::OpticalDrive::Bdr);
0133         AddProfile(ProfileBDRSequentialWritable, Solid::OpticalDrive::Bdr);
0134         AddProfile(ProfileBDRewritable, Solid::OpticalDrive::Bdre);
0135         AddProfile(ProfileHDDVDRom, Solid::OpticalDrive::HdDvd);
0136         AddProfile(ProfileHDDVDRecordable, Solid::OpticalDrive::HdDvdr);
0137         AddProfile(ProfileHDDVDRewritable, Solid::OpticalDrive::HdDvdrw);
0138     }
0139     return profiles[val];
0140 }
0141 
0142 #include "moc_winopticaldrive.cpp"