int wiiuse_io_write(struct wiimote_t* wm, byte* buf, int len) { DWORD bytes; int i; if (!wm || !WIIMOTE_IS_CONNECTED(wm)) return 0; switch (wm->stack) { case WIIUSE_STACK_UNKNOWN: { /* try to auto-detect the stack type */ if (i = WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap)) { /* bluesoleil will always return 1 here, even if it's not connected */ wm->stack = WIIUSE_STACK_BLUESOLEIL; return i; } if (i = HidD_SetOutputReport(wm->dev_handle, buf, len)) { wm->stack = WIIUSE_STACK_MS; return i; } WIIUSE_ERROR("Unable to determine bluetooth stack type."); return 0; } case WIIUSE_STACK_MS: return HidD_SetOutputReport(wm->dev_handle, buf, len); case WIIUSE_STACK_BLUESOLEIL: return WriteFile(wm->dev_handle, buf, 22, &bytes, &wm->hid_overlap); } return 0; }
int AIOTestAdapter::write(uint8 byte) { uint8 data[2]; data[0] = 0; data[1] = byte; if (INVALID_HANDLE_VALUE == writeHandle) return 0; HidD_SetOutputReport(writeHandle, data, sizeof(data)); Thread::sleep(100); BOOLEAN result = HidD_SetOutputReport(writeHandle, data, sizeof(data)); // send twice because of buffering somewhere -- quien sabes? return result; }
BOOL HidOutput( BOOL useSetOutputReport, HANDLE file, PCHAR buffer, ULONG bufferSize ) { ULONG bytesWritten; if (useSetOutputReport) { // // Send Hid report thru HidD_SetOutputReport API // if (!HidD_SetOutputReport(file, buffer, bufferSize)) { printf("failed HidD_SetOutputReport %d\n", GetLastError()); return FALSE; } } else { if (!WriteFile(file, buffer, bufferSize, &bytesWritten, NULL)) { printf("failed WriteFile %d\n", GetLastError()); return FALSE; } } return TRUE; }
BOOLEAN SwitchLogitech( __in LPTSTR lpDongleName, __in HANDLE hHidDevice, __in BOOL toHID ) { PHIDP_PREPARSED_DATA PreparsedData; if ( !HidD_GetPreparsedData( hHidDevice, &PreparsedData ) ) { LbtReportFunctionError( TEXT("HidD_GetPreparsedData") ); return FALSE; } HIDP_CAPS HidCaps; if ( !HidP_GetCaps( PreparsedData, &HidCaps ) ) { LbtReportFunctionError( TEXT("HidP_GetCaps") ); HidD_FreePreparsedData(PreparsedData); return FALSE; } if ( HidCaps.UsagePage != 0xFF00 || HidCaps.Usage != 0x0001 ) { HidD_FreePreparsedData(PreparsedData); return FALSE; } if ( HidCaps.OutputReportByteLength != sizeof(ToHCIReports[0]) ) { HidD_FreePreparsedData(PreparsedData); return FALSE; } DWORD noReports = toHID ? sizeof(ToHCIReports) / sizeof(ToHCIReports[0]) : sizeof(ToHIDReports) / sizeof(ToHIDReports[0]); for (DWORD i = 0; i < noReports; i++ ) { CHAR ReportBuffer[sizeof(ToHCIReports[0])]; RtlCopyMemory( ReportBuffer, toHID ? ToHCIReports[i] : ToHIDReports[i], sizeof( ToHCIReports[0] ) ); if (!HidD_SetOutputReport( hHidDevice, ReportBuffer, HidCaps.OutputReportByteLength ) ) { LbtReportFunctionError( TEXT("HidD_SetOutputReport") ); HidD_FreePreparsedData(PreparsedData); return FALSE; } } HidD_FreePreparsedData(PreparsedData); LbtReportDongleSwitch( lpDongleName, toHID ); return TRUE; }
bool device::write(const char_type* _data, size_t len) { DWORD bytes_written = 0; // not really used // TODO: lame std::array<char_type, max_packet_size> data; std::copy(_data, _data + len, data.begin()); ResetEvent(m_write_overlapped.hEvent); // TODO: event isn't being used if (m_use_writefile) { if (0 == WriteFile(m_device, &data[1], max_packet_size - 1, &bytes_written, &m_write_overlapped)) { // BlueSoleil always returns true, give HidD_SetOutputReport a try (MS stack) m_use_writefile = false; } else return true; } return (0 != HidD_SetOutputReport(m_device, &data[1], max_packet_size - 1)); }
BOOLEAN Hid::SetOutputReport(HANDLE HidDeviceObject, void *ReportBuffer, ULONG ReportBufferLength) { return HidD_SetOutputReport(HidDeviceObject, ReportBuffer, ReportBufferLength); }
static int hid_set_output_report(hid_device *dev, const unsigned char *data, size_t length) { // This copies the private structure inside the windows implementation of HidAPI struct hid_device_ { HANDLE device_handle; BOOL blocking; USHORT output_report_length; size_t input_report_length; void *last_error_str; DWORD last_error_num; BOOL read_pending; char *read_buf; OVERLAPPED ol; }; hid_device_ *dev_internal = (hid_device_ *)dev; DWORD bytes_written; unsigned char *buf; BOOL res; if (length >= dev_internal->output_report_length) { // The user passed the right number of bytes. Use the buffer as-is. buf = (unsigned char *)data; } else { // Create a temporary buffer and copy the user's data into it, padding the rest with zeros. buf = (unsigned char *)malloc(dev_internal->output_report_length); memcpy(buf, data, length); memset(buf + length, 0, dev_internal->output_report_length - length); length = dev_internal->output_report_length; } res = HidD_SetOutputReport(dev_internal->device_handle, buf, static_cast<ULONG>(length)); if (res == TRUE) { bytes_written = static_cast<DWORD>(length); } else { const DWORD error_code = GetLastError(); if (error_code != ERROR_IO_PENDING) { WCHAR *error_msg; FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&error_msg, 0/*sz*/, NULL); /* Store the message off in the Device entry so that the hid_error() function can pick it up. */ LocalFree(dev_internal->last_error_str); dev_internal->last_error_str = error_msg; bytes_written = -1; } } if (buf != data) { free(buf); } return bytes_written; }
// In theory, should be able to use WriteFile to create an asynchronous request using // an overlapped structure as shown in WriteOverlapped. // In practice, I couldn't get it to work, had to use output report executed immediately // for HID portals. BOOL WriteHID(HANDLE hPortalHandle, RWBlock *pb) { pb->buf[0] = 0; // Use report 0 return HidD_SetOutputReport(hPortalHandle, pb->buf, 0x21); }