Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.62/13: Рейтинг темы: голосов - 13, средняя оценка - 4.62
0 / 0 / 0
Регистрация: 23.01.2009
Сообщений: 37
1

Отправка строки байт PCI-e устройству с использованием CreateFile() и WriteFile()

08.10.2014, 15:37. Показов 2526. Ответов 8
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Собственно имеется PCI-e плата, драйвер разработчика для нее и программа позволяющая просматривать память (BAR'ы) платы. Можно ли нормально передать этой плате строку байт при помощи CreateFile() и WriteFile()?
Есть код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
string Buffer; //строка, которая будет передана устройству
DWORD  Written; //количество переданных байт
 
void transfer()
{
    HANDLE Device; //дескриптор устройства
 
    Device = CreateFile("\\.\Device0",
                         GENERIC_WRITE,
                         0,
                         NULL,
                         CREATE_ALWAYS,
                         FILE_ATTRIBUTE_NORMAL,
                         NULL); //создание десктриптора
 
    WriteFile(Device,
              Buffer.c_str(),
              Buffer.length(),
              &Written,
              NULL); //запись
 
    CloseHandle(Device); //закрытие дескриптора устройства
}
По идее он должен отправлять строку устройству, но это не происходит. Вернее строка куда-то отправляется, но программа не показывает, что в памяти платы что-то изменилось. В чем может быть проблема?
Для начала - правильно ли я указал имя устройства "\\.\Device0"? В интернете я нашел только такой вариант для PCI устройств. Наша плата имеет адрес Bus 2, Device 0, но в системе есть еще сетевая карта с адресом Bus 4, Device 0, может информация уходит туда? И вообще - возможна ли такая передача, или я придумал полную хрень?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
08.10.2014, 15:37
Ответы с готовыми решениями:

CreateFile, WriteFile
Подскажите работающий код программы на с++, которая создаёт файл с помощью CreateFile

Функции CreateFile() и WriteFile()
Господа, помогите разобраться с функциями CreateFile() и WriteFile(). В следующем простом...

Createfile, readfile, writefile
Файл 4 создаётся,но данные из файла 1 не переносятся.Почему? HANDLE myFile; HANDLE myFile2;...

Функции Createfile Writefile
Доброго времени суток. Столкнулся я с одной проблемой... Раньше всегда использовал библиотеки...

8
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
08.10.2014, 16:25 2
Цитата Сообщение от LamerOnLine Посмотреть сообщение
Вернее строка куда-то отправляется, но программа не показывает, что в памяти платы что-то изменилось. В чем может быть проблема?
Сделайте проверку ошибок нормально.
Т.е. проверка, что CreateFile вернула не INVALID_HANDLE_VALUE, что
WriteFile вернула ненулевое значение и т.д.
Только так можно быть уверенным, что что-то куда-то записалось.

Добавлено через 37 секунд
Да, и правильно вот так, если уж на то пошло:
C++
1
"\\\\.\\DeviceName"
0
0 / 0 / 0
Регистрация: 23.01.2009
Сообщений: 37
08.10.2014, 16:52  [ТС] 3
Цитата Сообщение от Убежденный Посмотреть сообщение
Т.е. проверка, что CreateFile вернула не INVALID_HANDLE_VALUE, что
что-то вроде
C++
1
2
3
4
5
6
7
8
if (Device != INVALID_HANDLE_VALUE)
    {
        CreateFile();
    }
    else
    {
        ошибка
    }
?

Цитата Сообщение от Убежденный Посмотреть сообщение
WriteFile вернула ненулевое значение и т.д.
WriteFile у меня возвращает количество переданных байт в виде переменной Written, просто в другом месте, она глобальная. Или это не то?

Цитата Сообщение от Убежденный Посмотреть сообщение
Да, и правильно вот так, если уж на то пошло:
C++
1
"\\\\.\\DeviceName"
Так у меня было изначально, но так WriteFile возвращала, что записано 0 байт. В нынешнем виде код заявлял, что он что-то куда-то записал, я и оставил как получилось.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
08.10.2014, 20:58 4
Цитата Сообщение от LamerOnLine Посмотреть сообщение
что-то вроде
C++
1
2
3
4
5
6
HANDLE const hDevice = CreateFile(...);
 
if (INVALID_HANDLE_VALUE == hDevice)
{
    // Обработка ошибки.
}
И т.д.

Цитата Сообщение от LamerOnLine Посмотреть сообщение
Так у меня было изначально, но так WriteFile возвращала, что записано 0 байт. В нынешнем виде код заявлял, что он что-то куда-то записал, я и оставил как получилось.
Я больше чем уверен, что при "\\.\Device0" ничего не куда не
писалось и устройство вообще не было открыто.
1
0 / 0 / 0
Регистрация: 23.01.2009
Сообщений: 37
09.10.2014, 13:38  [ТС] 5
Цитата Сообщение от Убежденный Посмотреть сообщение
Я больше чем уверен, что при "\\.\Device0" ничего не куда не
писалось и устройство вообще не было открыто.
Нет, куда-то все таки писалось) А конкретнее - создавался файл Device0 и туда писалось, так как в CreateFile был параметр CREATE_ALWAYS.

Я добавил обработку ошибок:
C++
1
2
3
4
5
if (INVALID_HANDLE_VALUE == Device)
    {
        printf("%d", Device);
        printf("\n%d", GetLastError());
    }
выдает что handle -1 и ошибка 2
я так понимаю это код ошибки ERROR_FILE_NOT_FOUND, значит неправильно составлен handle?

попробовал его изменить аналогично handl'у для COM портов, но все равно та же ошибка.

C++
1
2
3
4
5
6
7
HANDLE const Device = CreateFile("\\\\.\\Device0",
                         GENERIC_READ | GENERIC_WRITE,
                         0,
                         NULL,
                         OPEN_EXISTING,
                         FILE_ATTRIBUTE_NORMAL,
                         NULL);
И что по поводу Device0? Я читал где-то в интернете, что первому устройству, поключенному через PCI присваивается имя Device0 (независимо от того, в какой порт оно вставлено), Следующему Device1 и т.д. Я пробовал менять имя на Device1, Device2, но все то же самое.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
09.10.2014, 21:44 6
Цитата Сообщение от LamerOnLine Посмотреть сообщение
выдает что handle -1 и ошибка 2
я так понимаю это код ошибки ERROR_FILE_NOT_FOUND, значит неправильно составлен handle?
Это значит, что пути, который Вы указываете, не существует.

Цитата Сообщение от LamerOnLine Посмотреть сообщение
И что по поводу Device0? Я читал где-то в интернете, что первому устройству, поключенному через PCI присваивается имя Device0 (независимо от того, в какой порт оно вставлено), Следующему Device1 и т.д. Я пробовал менять имя на Device1, Device2, но все то же самое.
Имя устройство (точнее, имя символьной ссылки на него) может быть произвольным.
Если у вас есть конкретный драйвер под конкретное устройство, к нему должна
быть документация, где все описано. Без документации эти попытки почти обречены.

Ну можно попробовать через Setup API (SetupDiGetClassDevs и далее) найти
подключенное к ПК устройство и запросить символьную ссылку на него.
И вот через эту ссылку уже можно его и открывать.
0
0 / 0 / 0
Регистрация: 23.01.2009
Сообщений: 37
14.10.2014, 11:31  [ТС] 7
Цитата Сообщение от Убежденный Посмотреть сообщение
Ну можно попробовать через Setup API (SetupDiGetClassDevs и далее) найти
подключенное к ПК устройство и запросить символьную ссылку на него.
И вот через эту ссылку уже можно его и открывать.
Пока получилось используя SetupDiGetClassDevs,SetupDiEnumDeviceInfo и SetupDiGetDeviceRegistryProperty получить список устройств подключенных через PCI, и среди них есть необходимая плата.

Можно ли использовать в качестве имени устройства информацию из диспетчера устройств? Код экземпляра устройства, код оборудования или совместимые коды?

Добавлено через 1 час 10 минут
UPD:
в итоге, использовав в SetupDiGetDeviceRegistryProperty параметр SPDRP_HARDWAREID, что выдало список тех же самых кодов оборудования, что и в диспетчере устройств. Использовал в CreateFile() различные варианты кода моей платы, но они все выдают ошибку 53 (ERROR_BAD_NETPATH)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
string Buffer; //строка, которая будет передана устройству
DWORD  Written; //количество переданных байт
 
void transfer()
{
    HANDLE Device = CreateFile("\\\\PCI\\VEN_1204&DEV_EC30&SUBSYS_30101204&REV_00",
                                GENERIC_READ | GENERIC_WRITE,
                                0,
                                NULL,
                                OPEN_EXISTING,
                                FILE_ATTRIBUTE_NORMAL,
                                NULL); //создание десктриптора
 
 
    if (INVALID_HANDLE_VALUE == Device)
    {
        printf("%d", Device);
        printf("\n%d", GetLastError());
    } 
 
    WriteFile(Device,
              Buffer.c_str(),
              Buffer.length(),
              &Written,
              NULL); //запись
 
    CloseHandle(Device); //закрытие дескриптора устройства
}
Только вот непонятно - на каком этапе ошибка, опять неправильный дескриптор? Или неправильно производится запись? Или уже плата или драйвер не могут по какой-то причине принять информацию?

P.S.
В исходниках драйвера и документации копался пока только поверхностно.
0
Ушел с форума
Эксперт С++
16473 / 7436 / 1187
Регистрация: 02.05.2013
Сообщений: 11,617
Записей в блоге: 1
14.10.2014, 14:52 8
Лучший ответ Сообщение было отмечено LamerOnLine как решение

Решение

Цитата Сообщение от LamerOnLine Посмотреть сообщение
Можно ли использовать в качестве имени устройства информацию из диспетчера устройств? Код экземпляра устройства, код оборудования или совместимые коды?
Нет.
Для имени устройства система формирует символьную ссылку с уникальным и
постоянным именем, получается она через SetupDiGetDeviceInterfaceDetail
(поле SP_DEVICE_INTERFACE_DETAIL_DATA::DevicePath).
1
0 / 0 / 0
Регистрация: 23.01.2009
Сообщений: 37
15.10.2014, 15:45  [ТС] 9
Цитата Сообщение от Убежденный Посмотреть сообщение
Для имени устройства система формирует символьную ссылку с уникальным и
постоянным именем, получается она через SetupDiGetDeviceInterfaceDetail
(поле SP_DEVICE_INTERFACE_DETAIL_DATA:evicePath).
Через DevicePath я получил строку
\\\\?\\pci#ven_1204&dev_ec30&subsys_30101204&rev_00#4&13cc24e9&0d&00e6#{c29fbbae-0864-4d2c-9c69-4ddb10d175db}
но если спользовать ее в качестве имени в CreateFile - он выдает 2ую ошибку (ERROR_FILE_NOT_FOUND)
)
Это вообще то, что нужно? Эта строка нашлась по GUID устройства, тут есть и vendorID и deviceID и сам GUID и это все соответствует моей плате, но CreateFile() все равно не хочет ее находить...

Добавлено через 53 минуты
Ох, проблема решена. Просто я первоначальном варианте хотел записать имя как константу и в процессе переписывания опечатался.
CreateFile() таки нашла мое устройство по данному имени, а WriteFile() возвращает значение переданных символов. Короче функция теперь работает как задумано, только вот на плате почему-то никаких изменений. Буду изучать документацию и исходники...
0
15.10.2014, 15:45
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.10.2014, 15:45
Помогаю со студенческими работами здесь

Функции win32 CreateFile WriteFile и ReadFile
В общем делаю небольшой проект. Необходимо считать данные из файла. Очевидно, что изначально в него...

WriteFile как передать команду устройству
Приветствую. Задача. Есть устройство на которое, для его последующей работы, нужно подать через...

Как работать с LPT портом через функции CreateFile, ReadFile, WriteFile?
Господа, научите работать с LPT портом через функции CreateFile, ReadFile, WriteFile (протокол ECP...

Работа с COM портами: сколько байт посылать устройству
Я никогда в жизни не работал с сом портами. нашел различные примеры, понял как отправлять и как...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru