#xcode #macos #usb #iokit
#xcode #macos #usb #iokit
Вопрос:
Я минимально знаком с xcode и I / Okit framework. Я видел дескриптор устройства и дескриптор конфигурации USB-устройства в USB prober.
Я написал программу xcode, используя фреймворк I / O kit, который выдает имя usb-устройства в качестве выходных данных, когда мы вводим идентификатор продукта и идентификатор поставщика этого устройства в качестве входных данных.
/*Take the vendor and product id from console*/
printf("nEnter the vendor id : ");
scanf("%lx",amp;usbVendor);
printf("nEnter the product id :");
scanf("%lx",amp;usbProduct);
/* Set up a matching dictionary for the class */
matchingDict = IOServiceMatching(kIOUSBDeviceClassName);
if (matchingDict == NULL)
{
return -1; // fail
}
// Create a CFNumber for the idVendor and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, amp;usbVendor);
CFDictionarySetValue(matchingDict,
CFSTR(kUSBVendorID),
numberRef);
CFRelease(numberRef);
// Create a CFNumber for the idProduct and set the value in the dictionary
numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, amp;usbProduct);
CFDictionarySetValue(matchingDict,
CFSTR(kUSBProductID),
numberRef);
CFRelease(numberRef);
numberRef = NULL;
/*Get an iterator.*/
kr = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDict, amp;iter);
if (kr != KERN_SUCCESS)
{
return -1;// fail
}
/* iterate */
while ((device = IOIteratorNext(iter)))
{
/*Display the device names */
io_name_t deviceName;
kr = IORegistryEntryGetName(device, deviceName);
if (KERN_SUCCESS != kr) {
deviceName[0] = '';
}
printf("ndeviceName:%s",deviceName);
/*Free the reference taken before continuing to the next item */
IOObjectRelease(device);
}
/*Release the iterator */
IOObjectRelease(iter);
return 0;
}
Мне нужно изменить это, чтобы при указании идентификатора поставщика и продукта usb-устройства я получал дескриптор устройства и дескриптор конфигурации (как показано в USB prober) в качестве выходных данных.
Здесь я только что привел пример, код может измениться, но на выходе должен быть дескриптор (по крайней мере, дескриптор устройства).
Заранее спасибо…
Комментарии:
1. Есть ли какая-либо встроенная функция для получения дескриптора устройства, дескриптора конфигурации, дескриптора интерфейса?
2. В usb.h есть USBDeviceDescriptor. Я попытался вызвать указатель этого типа, чтобы получить все параметры, но мне это не удалось. Любая помощь?
3. Я также пробовал использовать функции, доступные с помощью IOUSBDeviceInterface. Но он не предоставляет функций для извлечения всех параметров
4. Затем я попытался использовать IORegistryEntryCreateCFProperty, но и здесь не удалось получить все параметры. Есть идеи по этому поводу, пожалуйста, ответьте
5. Для получения указателя на дескриптор конфигурации мы можем использовать GetConfigurationDescriptor() в интерфейсе IOUSBDeviceInterface. developer.apple.com/library/mac/#documentation/Darwin/Reference /. …
Ответ №1:
Я думаю, вам следует загрузить исходный код USBProber, а не разбираться в этом самостоятельно.
Всю информацию, представленную в USBProber, вы могли бы получить рано или поздно, проанализировав исходный код.
Вот ссылка для загрузки исходного кода IOUSBFamily с USBProber внутри него. http://opensource.apple.com/tarballs/IOUSBFamily /
Комментарии:
1. я устал от USBprober. Я не мог правильно понять его поток, так как я искал простую программу. Я попробовал функции, предоставляемые классами под USB на Mac.
2. Я написал пример, чтобы получить всю информацию, отображаемую в пробнике USB-> USB-зонд, то, что вы хотите получить, находится внутри него.<br/> Ниже приведен основной шаг для создания демонстрации.<br/> 1. Импортируйте исходные файлы из проекта USB Prober. Не забывайте USBVendor.txt , который используется для расшифровки поставщика.<br/>2. Импортируйте необходимую структуру, просто следуйте проекту USB Prober.<br />3. Добавьте интерфейс для вывода журнала в BusProbeController. Вы можете выполнить поиск «IvanDebug», чтобы найти интерфейс.<br />4. Напишите файл main.m для использования BusProbeController. <br/>
3. Дайте мне знать, как отправить вам демо-версию, если это необходимо. 0_-
4. Пожалуйста, отправьте демо на мой mail:mdileep1989@gmail.com . Это будет очень полезно.
Ответ №2:
Чтобы получить дескрипторы конфигурации, вы можете использовать следующий код:
IOUSBDeviceInterface650** dev = ...;
IOUSBConfigurationDescriptor* configDesc = nullptr;
// Get the configuration descriptor for the first configuration (configuration 0).
kern_return_t kr = (*dev)->GetConfigurationDescriptorPtr(dev, 0, amp;configDesc);
if (kr != kIOReturnSuccess)
return an_error;
// Now use configDesc->...
К сожалению, похоже, что нет функции для получения дескриптора устройства. Есть функции, чтобы получить некоторые из них:
kr = (*dev)->GetDeviceClass(dev, amp;desc.bDeviceClass);
kr = (*dev)->GetDeviceSubClass(dev, amp;desc.bDeviceSubClass);
kr = (*dev)->GetDeviceProtocol(dev, amp;desc.bDeviceProtocol);
kr = (*dev)->GetDeviceVendor(dev, amp;desc.idVendor);
kr = (*dev)->GetDeviceProduct(dev, amp;desc.idProduct);
kr = (*dev)->GetDeviceReleaseNumber(dev, amp;desc.bcdDevice);
kr = (*dev)->GetNumberOfConfigurations(dev, amp;desc.bNumConfigurations);
Но я не вижу способа получить iManufacturer
, iProduct
, iSerial
, bMaxPacketSize0
, или bcdUSB
.
Есть способ обойти это — вместо использования встроенных функций вы можете просто выполнить запрос управления, чтобы получить дескриптор устройства (и дескрипторы конфигурации, если хотите) вручную, используя передачу управления.
Спецификация USB 2.0 описывает, как это сделать. В основном вы:
-
Выполните передачу элемента управления с
bmRequestType = Device | Standard | In
помощью ,bRequest = USB_GET_DESCRIPTOR_REQUEST
,wValue = (USB_DEVICE_DESCRIPTOR_TYPE << 8)
,wIndex = 0
,wLength = 2
. Это приведет к сбою, потому что дескриптор длиннее 2, но он возвращает вам заголовок дескриптора, который включает его длину. -
Повторите этот запрос, но с правильной длиной.
-
Для дескрипторов конфигурации выполните третий запрос с длиной
wTotalLength
.
Вы можете сделать это с одним меньшим запросом, поскольку вы заранее знаете размер дескрипторов, но мне нравится делать это так, потому что тогда вы можете обернуть это в очень общий getDescriptor()
метод.
Теоретически вы можете сделать это так просто:
IOUSBDeviceDescriptor devDesc;
IOUSBDevRequest request;
request.bmRequestType = USBmakebmRequestType(kUSBIn, kUSBStandard, kUSBDevice);
request.bRequest = kUSBRqGetDescriptor;
request.wValue = kUSBDeviceDesc << 8;
request.wIndex = 0;
request.wLength = sizeof(devDesc); // 18
request.pData = amp;devDesc;
request.wLenDone = 0;
kern_return_t kr = (*dev)->DeviceRequest(dev, amp;request);
Но по какой-то причине это выдает kIOUSBPipeStalled
ошибку. Не уверен, почему.
Редактировать: я забыл << 8
. Теперь это работает. 🙂
Ответ №3:
Заголовок IOKit/usb/USBSpec.h
содержит документированный список ключей свойств, соответствующих значениям внутри разных дескрипторов. Вы можете использовать их с IORegistryEntrySearchCFProperty
(или аналогичными функциями) для получения значений дескриптора. Таким образом, вам не нужен запрос устройства от an IOUSBDeviceInterface
, что выгодно, потому что:
- в документации (комментариях) говорится, что для всех запросов устройств требуется открытое USB-устройство, и у вас может не быть разрешения на это для всех устройств (возможно, документация неверна, по крайней мере, для запросов дескрипторов, но у меня нет гарантии этого, и, похоже, лучше следовать ей в любом случае)
- запросы устройств могут блокироваться на неопределенное время
- строки производителя, продукта и серийного номера (на которые ссылается дескриптор устройства, но технически не являются его частью) не извлекаются в этом запросе
Ответ №4:
Для получения дескриптора устройства и дескриптора конфигурации мы можем использовать функции в классе IOUSBDeviceInterface
Для получения дескриптора интерфейса и дескриптора конечной точки мы можем использовать функции в классе IOUSBInterfaceInterface