static status_t usb_hid_free(void *cookie) { TRACE("free(%p)\n", cookie); mutex_lock(&sDriverLock); HIDDevice *device = ((ProtocolHandler *)cookie)->Device(); if (device->IsOpen()) { // another handler of this device is still open so we can't free it } else if (device->IsRemoved()) { // the parent device is removed already and none of its handlers are // open anymore so we can free it here for (uint32 i = 0;; i++) { ProtocolHandler *handler = device->ProtocolHandlerAt(i); if (handler == NULL) break; gDeviceList->RemoveDevice(NULL, handler); } delete device; } mutex_unlock(&sDriverLock); return B_OK; }
QString HID::inputInfo(quint32 input) { QString str; str += QString("<HTML>"); str += QString("<HEAD>"); str += QString("<TITLE>%1</TITLE>").arg(name()); str += QString("</HEAD>"); str += QString("<BODY>"); str += QString("<H3>%1</H3>").arg(name()); if (input == QLCIOPlugin::invalidLine()) { /* Plugin or just an invalid input selected. Display generic information. */ str += QString("<P>"); str += tr("This plugin provides input support for HID-based joysticks."); str += QString("</P>"); } else { /* A specific input line selected. Display its information if available. */ HIDDevice* dev = device(input); if (dev != NULL) str += dev->infoText(); } str += QString("</BODY>"); str += QString("</HTML>"); return str; }
void InputHandler_MacOSX_HID::QueueCallback( void *target, int result, void *refcon, void *sender ) { // The result seems useless as you can't actually return anything... // refcon is the Device number RageTimer now; InputHandler_MacOSX_HID *This = (InputHandler_MacOSX_HID *)target; IOHIDQueueInterface **queue = (IOHIDQueueInterface **)sender; IOHIDEventStruct event; AbsoluteTime zeroTime = { 0, 0 }; HIDDevice *dev = This->m_vDevices[size_t( refcon )]; vector<DeviceInput> vPresses; while( (result = CALL(queue, getNextEvent, &event, zeroTime, 0)) == kIOReturnSuccess ) { if( event.longValueSize != 0 && event.longValue != NULL ) { free( event.longValue ); continue; } //LOG->Trace( "Got event with cookie %p, value %d", event.elementCookie, int(event.value) ); dev->GetButtonPresses( vPresses, event.elementCookie, event.value, now ); } FOREACH_CONST( DeviceInput, vPresses, i ) INPUTFILTER->ButtonPressed( *i ); }
/********************************************************************* * Outputs *********************************************************************/ void HIDPlugin::openOutput(quint32 output) { HIDDevice* dev = device(output); if (dev != NULL) dev->openOutput(); else qDebug() << name() << "has no output number:" << output; }
void HID::closeOutput(quint32 output) { HIDDevice* dev = device(output); if (dev != NULL) dev->closeOutput(); else qDebug() << name() << "has no output number:" << output; }
int GetFirmwareProps(const char * deviceFile, std::string &props, bool configid) { HIDDevice rmidevice; int rc = UPDATE_SUCCESS; std::stringstream ss; rc = rmidevice.Open(deviceFile); if (rc) return rc; rmidevice.ScanPDT(0x1); rmidevice.QueryBasicProperties(); if (configid) { ss << std::hex << rmidevice.GetConfigID(); } else { ss << rmidevice.GetFirmwareVersionMajor() << "." << rmidevice.GetFirmwareVersionMinor() << "." << std::hex << rmidevice.GetFirmwareID(); if (rmidevice.InBootloader()) ss << " bootloader"; } props = ss.str(); return rc; }
void HID::writeUniverse(quint32 universe, quint32 output, const QByteArray &data) { Q_UNUSED(universe); if (output != QLCIOPlugin::invalidLine()) { HIDDevice* dev = device(output); if (dev != NULL) dev->outputDMX(data); } }
void HIDPlugin::closeOutput(quint32 output, quint32 universe) { HIDDevice* dev = deviceOutput(output); if (dev != NULL) { removeFromMap(output, universe, Output); dev->closeOutput(); } else qDebug() << name() << "has no output number:" << output; }
void HIDDevice::staticHIDReportCallback(void* pContext, IOReturn result, void* pSender, IOHIDReportType reportType, uint32_t reportId, uint8_t* pReport, CFIndex reportLength) { HIDDevice* pDevice = (HIDDevice*) pContext; return pDevice->hidReportCallback(pReport, (UInt32)reportLength); }
/********************************************************************* * Outputs *********************************************************************/ bool HIDPlugin::openOutput(quint32 output, quint32 universe) { HIDDevice* dev = deviceOutput(output); if (dev != NULL) { addToMap(universe, output, Output); return dev->openOutput(); } else qDebug() << name() << "has no output number:" << output; return false; }
void HID::closeInput(quint32 input) { HIDDevice* dev = device(input); if (dev != NULL) { dev->closeInput(); disconnect(dev, SIGNAL(valueChanged(quint32,quint32,uchar)), this, SIGNAL(valueChanged(quint32,quint32,uchar))); } else qDebug() << name() << "has no input number:" << input; }
void InputHandler_MacOSX_HID::AddDevices( int usagePage, int usage, InputDevice &id ) { io_iterator_t iter; CFDictionaryRef dict = GetMatchingDictionary( usagePage, usage ); kern_return_t ret = IOServiceAddMatchingNotification( m_NotifyPort, kIOFirstMatchNotification, dict, InputHandler_MacOSX_HID::DeviceAdded, this, &iter ); io_object_t device; if( ret != KERN_SUCCESS ) return; m_vIters.push_back( iter ); // Iterate over the devices and add them while( (device = IOIteratorNext(iter)) ) { LOG->Trace( "\tFound device %d", id ); HIDDevice *dev = MakeDevice( id ); int num; if( !dev ) { LOG->Trace( "\t\tInvalid id, deleting device" ); IOObjectRelease( device ); continue; } if( !dev->Open(device) || (num = dev->AssignIDs(id)) == -1 ) { LOG->Trace( "\tFailed top open or assign id, deleting device" ); delete dev; IOObjectRelease( device ); continue; } io_iterator_t i; enum_add( id, num ); m_vDevices.push_back( dev ); ret = IOServiceAddInterestNotification( m_NotifyPort, device, kIOGeneralInterest, InputHandler_MacOSX_HID::DeviceChanged, this, &i ); if( ret == KERN_SUCCESS ) m_vIters.push_back( i ); else LOG->Trace( "\t\tFailed to add device changed notification, deleting device" ); IOObjectRelease( device ); } }
HIDDevice* HID::device(const QString& path) { QListIterator <HIDDevice*> it(m_devices); while (it.hasNext() == true) { HIDDevice* dev = it.next(); if (dev->path() == path) return dev; } return NULL; }
void HIDPlugin::closeInput(quint32 input, quint32 universe) { HIDDevice* dev = device(input); if (dev != NULL) { removeFromMap(input, universe, Input); dev->closeInput(); disconnect(dev, SIGNAL(valueChanged(quint32,quint32,quint32,uchar)), this, SIGNAL(valueChanged(quint32,quint32,quint32,uchar))); } else qDebug() << name() << "has no input number:" << input; }
QStringList HID::outputs() { QStringList list; QListIterator <HIDDevice*> it(m_devices); while (it.hasNext() == true) { HIDDevice* dev = it.next(); if (dev->hasOutput()) list << dev->name(); } return list; }
bool HIDPlugin::openInput(quint32 input, quint32 universe) { HIDDevice* dev = device(input); if (dev != NULL) { connect(dev, SIGNAL(valueChanged(quint32,quint32,quint32,uchar)), this, SIGNAL(valueChanged(quint32,quint32,quint32,uchar))); addToMap(universe, input, Input); return dev->openInput(); } else qDebug() << name() << "has no input number:" << input; return false; }
QString HID::outputInfo(quint32 output) { QString str; if (output != QLCIOPlugin::invalidLine()) { /* A specific output line selected. Display its information if available. */ HIDDevice* dev = device(output); if (dev != NULL) str += dev->infoText(); } str += QString("</BODY>"); str += QString("</HTML>"); return str; }
void JoystickProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection, ProtocolHandler *&handlerList) { if (collection.UsagePage() != B_HID_USAGE_PAGE_GENERIC_DESKTOP || (collection.UsageID() != B_HID_UID_GD_JOYSTICK && collection.UsageID() != B_HID_UID_GD_GAMEPAD && collection.UsageID() != B_HID_UID_GD_MULTIAXIS)) { TRACE("collection not a joystick or gamepad\n"); return; } HIDParser &parser = device.Parser(); uint32 maxReportCount = parser.CountReports(HID_REPORT_TYPE_INPUT); if (maxReportCount == 0) return; uint32 inputReportCount = 0; HIDReport *inputReports[maxReportCount]; collection.BuildReportList(HID_REPORT_TYPE_INPUT, inputReports, inputReportCount); for (uint32 i = 0; i < inputReportCount; i++) { HIDReport *inputReport = inputReports[i]; // try to find at least one axis bool foundAxis = false; for (uint32 j = 0; j < inputReport->CountItems(); j++) { HIDReportItem *item = inputReport->ItemAt(j); if (item == NULL || !item->HasData()) continue; if (item->UsagePage() != B_HID_USAGE_PAGE_GENERIC_DESKTOP) continue; if (item->UsageID() >= B_HID_UID_GD_X && item->UsageID() <= B_HID_UID_GD_RZ) { foundAxis = true; break; } } if (!foundAxis) continue; ProtocolHandler *newHandler = new(std::nothrow) JoystickProtocolHandler(*inputReport); if (newHandler == NULL) { TRACE("failed to allocated joystick protocol handler\n"); continue; } newHandler->SetNextHandler(handlerList); handlerList = newHandler; } }
int RunF54Test(const char * deviceFile, f54_report_types reportType, bool continuousMode, bool noReset) { int rc; HIDDevice rmidevice; Display * display; if (continuousMode) { display = new AnsiConsole(); } else { display = new Display(); } display->Clear(); rc = rmidevice.Open(deviceFile); if (rc) return rc; F54Test f54Test(rmidevice, *display); rc = f54Test.Prepare(reportType); if (rc) return rc; stopRequested = false; do { rc = f54Test.Run(); } while (continuousMode && !stopRequested); if (!noReset) rmidevice.Reset(); rmidevice.Close(); delete display; return rc; }
void ConfigureHID::refreshList() { QString s; m_list->clear(); for (int i = 0; i < m_plugin->m_devices.count(); i++) { HIDDevice* dev; QTreeWidgetItem* item; dev = m_plugin->device(i); Q_ASSERT(dev != NULL); item = new QTreeWidgetItem(m_list); item->setText(KColumnNumber, s.setNum(i + 1)); item->setText(KColumnName, dev->name()); item->setFlags(item->flags() | Qt::ItemIsUserCheckable); } m_list->header()->resizeSections(QHeaderView::ResizeToContents); }
static status_t usb_hid_free(void *_cookie) { device_cookie *cookie = (device_cookie *)_cookie; TRACE("free(%p)\n", cookie); mutex_lock(&sDriverLock); HIDDevice *device = cookie->handler->Device(); if (device->IsOpen()) { // another handler of this device is still open so we can't free it } else if (device->IsRemoved()) { // the parent device is removed already and none of its handlers are // open anymore so we can free it here delete device; } mutex_unlock(&sDriverLock); delete cookie; return B_OK; }
status_t usb_hid_device_removed(void *cookie) { mutex_lock(&sDriverLock); int32 parentCookie = (int32)cookie; TRACE("device_removed(%ld)\n", parentCookie); for (int32 i = 0; i < gDeviceList->CountDevices(); i++) { ProtocolHandler *handler = (ProtocolHandler *)gDeviceList->DeviceAt(i); if (!handler) continue; HIDDevice *device = handler->Device(); if (device->ParentCookie() != parentCookie) continue; // this handler's device belongs to the one removed if (device->IsOpen()) { // the device and it's handlers will be deleted in the free hook device->Removed(); break; } // remove all the handlers for (uint32 i = 0;; i++) { handler = device->ProtocolHandlerAt(i); if (handler == NULL) break; gDeviceList->RemoveDevice(NULL, handler); } delete device; break; } mutex_unlock(&sDriverLock); return B_OK; }
void TabletProtocolHandler::AddHandlers(HIDDevice &device, HIDCollection &collection, ProtocolHandler *&handlerList) { bool supported = false; switch (collection.UsagePage()) { case B_HID_USAGE_PAGE_GENERIC_DESKTOP: { switch (collection.UsageID()) { case B_HID_UID_GD_MOUSE: case B_HID_UID_GD_POINTER: // NOTE: Maybe it is supported if X-axis and Y-axis are // absolute. This is determined below by scanning the // report items for absolute X and Y axis. supported = true; break; } break; } case B_HID_USAGE_PAGE_DIGITIZER: { switch (collection.UsageID()) { case B_HID_UID_DIG_DIGITIZER: case B_HID_UID_DIG_PEN: case B_HID_UID_DIG_LIGHT_PEN: case B_HID_UID_DIG_TOUCH_SCREEN: case B_HID_UID_DIG_TOUCH_PAD: case B_HID_UID_DIG_WHITE_BOARD: TRACE("found tablet/digitizer\n"); supported = true; break; } break; } } if (!supported) { TRACE("collection not a tablet/digitizer\n"); return; } HIDParser &parser = device.Parser(); uint32 maxReportCount = parser.CountReports(HID_REPORT_TYPE_INPUT); if (maxReportCount == 0) return; uint32 inputReportCount = 0; HIDReport *inputReports[maxReportCount]; collection.BuildReportList(HID_REPORT_TYPE_INPUT, inputReports, inputReportCount); for (uint32 i = 0; i < inputReportCount; i++) { HIDReport *inputReport = inputReports[i]; // try to find at least an absolute x and y axis HIDReportItem *xAxis = inputReport->FindItem( B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_X); if (xAxis == NULL || xAxis->Relative()) continue; HIDReportItem *yAxis = inputReport->FindItem( B_HID_USAGE_PAGE_GENERIC_DESKTOP, B_HID_UID_GD_Y); if (yAxis == NULL || yAxis->Relative()) continue; ProtocolHandler *newHandler = new(std::nothrow) TabletProtocolHandler( *inputReport, *xAxis, *yAxis); if (newHandler == NULL) { TRACE("failed to allocated tablet protocol handler\n"); continue; } newHandler->SetNextHandler(handlerList); handlerList = newHandler; } }
status_t usb_hid_device_added(usb_device device, void **cookie) { TRACE("device_added()\n"); const usb_device_descriptor *deviceDescriptor = gUSBModule->get_device_descriptor(device); TRACE("vendor id: 0x%04x; product id: 0x%04x\n", deviceDescriptor->vendor_id, deviceDescriptor->product_id); for (int32 i = 0; i < gBlackListedDeviceCount; i++) { usb_support_descriptor &entry = gBlackListedDevices[i]; if ((entry.vendor != 0 && deviceDescriptor->vendor_id != entry.vendor) || (entry.product != 0 && deviceDescriptor->product_id != entry.product)) { continue; } return B_ERROR; } const usb_configuration_info *config = gUSBModule->get_nth_configuration(device, USB_DEFAULT_CONFIGURATION); if (config == NULL) { TRACE_ALWAYS("cannot get default configuration\n"); return B_ERROR; } // ensure default configuration is set status_t result = gUSBModule->set_configuration(device, config); if (result != B_OK) { TRACE_ALWAYS("set_configuration() failed 0x%08" B_PRIx32 "\n", result); return result; } // refresh config config = gUSBModule->get_configuration(device); if (config == NULL) { TRACE_ALWAYS("cannot get current configuration\n"); return B_ERROR; } bool devicesFound = false; int32 parentCookie = atomic_add(&sParentCookie, 1); for (size_t i = 0; i < config->interface_count; i++) { const usb_interface_info *interface = config->interface[i].active; uint8 interfaceClass = interface->descr->interface_class; TRACE("interface %" B_PRIuSIZE ": class: %u; subclass: %u; protocol: " "%u\n", i, interfaceClass, interface->descr->interface_subclass, interface->descr->interface_protocol); // check for quirky devices first int32 quirkyIndex = -1; for (int32 j = 0; j < gQuirkyDeviceCount; j++) { usb_hid_quirky_device &quirky = gQuirkyDevices[j]; if ((quirky.vendor_id != 0 && deviceDescriptor->vendor_id != quirky.vendor_id) || (quirky.product_id != 0 && deviceDescriptor->product_id != quirky.product_id) || (quirky.device_class != 0 && interfaceClass != quirky.device_class) || (quirky.device_subclass != 0 && interface->descr->interface_subclass != quirky.device_subclass) || (quirky.device_protocol != 0 && interface->descr->interface_protocol != quirky.device_protocol)) { continue; } quirkyIndex = j; break; } if (quirkyIndex >= 0 || interfaceClass == USB_INTERFACE_CLASS_HID) { mutex_lock(&sDriverLock); HIDDevice *hidDevice = new(std::nothrow) HIDDevice(device, config, i, quirkyIndex); if (hidDevice != NULL && hidDevice->InitCheck() == B_OK) { hidDevice->SetParentCookie(parentCookie); for (uint32 i = 0;; i++) { ProtocolHandler *handler = hidDevice->ProtocolHandlerAt(i); if (handler == NULL) break; // As devices can be un- and replugged at will, we cannot // simply rely on a device count. If there is just one // keyboard, this does not mean that it uses the 0 name. // There might have been two keyboards and the one using 0 // might have been unplugged. So we just generate names // until we find one that is not currently in use. int32 index = 0; char pathBuffer[128]; const char *basePath = handler->BasePath(); while (true) { sprintf(pathBuffer, "%s%" B_PRId32, basePath, index++); if (gDeviceList->FindDevice(pathBuffer) == NULL) { // this name is still free, use it handler->SetPublishPath(strdup(pathBuffer)); break; } } gDeviceList->AddDevice(handler->PublishPath(), handler); devicesFound = true; } } else delete hidDevice; mutex_unlock(&sDriverLock); } } if (!devicesFound) return B_ERROR; *cookie = (void *)(addr_t)parentCookie; return B_OK; }
void on_data_received(size_t bytes, vrpn_uint8 *buffer) { _container->send_data_signal(bytes, reinterpret_cast<char *>(buffer)); }
status_t usb_hid_device_added(usb_device device, void **cookie) { TRACE("device_added()\n"); const usb_device_descriptor *deviceDescriptor = gUSBModule->get_device_descriptor(device); TRACE("vendor id: 0x%04x; product id: 0x%04x\n", deviceDescriptor->vendor_id, deviceDescriptor->product_id); // wacom devices are handled by the dedicated wacom driver if (deviceDescriptor->vendor_id == USB_VENDOR_WACOM) return B_ERROR; const usb_configuration_info *config = gUSBModule->get_nth_configuration(device, USB_DEFAULT_CONFIGURATION); if (config == NULL) { TRACE_ALWAYS("cannot get default configuration\n"); return B_ERROR; } // ensure default configuration is set status_t result = gUSBModule->set_configuration(device, config); if (result != B_OK) { TRACE_ALWAYS("set_configuration() failed 0x%08lx\n", result); return result; } // refresh config config = gUSBModule->get_configuration(device); if (config == NULL) { TRACE_ALWAYS("cannot get current configuration\n"); return B_ERROR; } bool devicesFound = false; int32 parentCookie = atomic_add(&sParentCookie, 1); for (size_t i = 0; i < config->interface_count; i++) { const usb_interface_info *interface = config->interface[i].active; uint8 interfaceClass = interface->descr->interface_class; TRACE("interface %lu: class: %u; subclass: %u; protocol: %u\n", i, interfaceClass, interface->descr->interface_subclass, interface->descr->interface_protocol); if (interfaceClass == USB_INTERFACE_CLASS_HID) { mutex_lock(&sDriverLock); HIDDevice *hidDevice = new(std::nothrow) HIDDevice(device, config, i); if (hidDevice != NULL && hidDevice->InitCheck() == B_OK) { hidDevice->SetParentCookie(parentCookie); for (uint32 i = 0;; i++) { ProtocolHandler *handler = hidDevice->ProtocolHandlerAt(i); if (handler == NULL) break; // As devices can be un- and replugged at will, we cannot // simply rely on a device count. If there is just one // keyboard, this does not mean that it uses the 0 name. // There might have been two keyboards and the one using 0 // might have been unplugged. So we just generate names // until we find one that is not currently in use. int32 index = 0; char pathBuffer[128]; const char *basePath = handler->BasePath(); while (true) { sprintf(pathBuffer, "%s%ld", basePath, index++); if (gDeviceList->FindDevice(pathBuffer) == NULL) { // this name is still free, use it handler->SetPublishPath(strdup(pathBuffer)); break; } } gDeviceList->AddDevice(handler->PublishPath(), handler); devicesFound = true; } } else delete hidDevice; mutex_unlock(&sDriverLock); } } if (!devicesFound) return B_ERROR; *cookie = (void *)parentCookie; return B_OK; }
int main(int argc, char **argv) { int rc; FirmwareImage image; int opt; int index; char *deviceName = NULL; const char *firmwareName = NULL; bool force = false; static struct option long_options[] = { {"help", 0, NULL, 'h'}, {"force", 0, NULL, 'f'}, {"device", 1, NULL, 'd'}, {"fw-props", 0, NULL, 'p'}, {"config-id", 0, NULL, 'c'}, {"lockdown", 0, NULL, 'l'}, {"version", 0, NULL, 'v'}, {"device-type", 1, NULL, 't'}, {0, 0, 0, 0}, }; bool printFirmwareProps = false; bool printConfigid = false; bool performLockdown = false; HIDDevice device; enum RMIDeviceType deviceType = RMI_DEVICE_TYPE_ANY; while ((opt = getopt_long(argc, argv, RMI4UPDATE_GETOPTS, long_options, &index)) != -1) { switch (opt) { case 'h': printHelp(argv[0]); return 0; case 'f': force = true; break; case 'd': deviceName = optarg; break; case 'p': printFirmwareProps = true; break; case 'c': printFirmwareProps = true; printConfigid = true; break; case 'l': performLockdown = true; break; case 't': if (!strcasecmp((const char *)optarg, "touchpad")) deviceType = RMI_DEVICE_TYPE_TOUCHPAD; else if (!strcasecmp((const char *)optarg, "touchscreen")) deviceType = RMI_DEVICE_TYPE_TOUCHSCREEN; break; case 'v': printVersion(); return 0; default: break; } } if (printFirmwareProps) { std::string props; if (!deviceName) { fprintf(stderr, "Specifiy which device to query\n"); return 1; } rc = GetFirmwareProps(deviceName, props, printConfigid); if (rc) { fprintf(stderr, "Failed to read properties from device: %s\n", update_err_to_string(rc)); return 1; } fprintf(stdout, "%s\n", props.c_str()); return 0; } if (optind < argc) { firmwareName = argv[optind]; } else { printHelp(argv[0]); return -1; } rc = image.Initialize(firmwareName); if (rc != UPDATE_SUCCESS) { fprintf(stderr, "Failed to initialize the firmware image: %s\n", update_err_to_string(rc)); return 1; } if (deviceName) { rc = device.Open(deviceName); if (rc) { fprintf(stderr, "%s: failed to initialize rmi device (%d): %s\n", argv[0], errno, strerror(errno)); return 1; } } else { if (!device.FindDevice(deviceType)) return 1; } RMI4Update update(device, image); rc = update.UpdateFirmware(force, performLockdown); if (rc != UPDATE_SUCCESS) { device.Reset(); return 1; } return 0; }
void HIDDevice::staticDeviceAddedCallback(void* pContext, io_iterator_t iterator) { HIDDevice* pDevice = (HIDDevice*) pContext; pDevice->deviceAddedCallback(iterator); }
void HIDDevice::staticDeviceRemovedCallback(void* pContext, IOReturn result, void* pSender) { HIDDevice* pDevice = (HIDDevice*) pContext; pDevice->deviceRemovedCallback(); }