VOID CyapaBootWorkItem( IN WDFWORKITEM WorkItem ) { WDFDEVICE Device = (WDFDEVICE)WdfWorkItemGetParentObject(WorkItem); PDEVICE_CONTEXT pDevice = GetDeviceContext(Device); cyapa_boot_regs boot; csgesture_softc *sc = &pDevice->sc; if (!sc->infoSetup) { struct cyapa_cap cap; SpbReadDataSynchronously(&pDevice->I2CContext, CMD_QUERY_CAPABILITIES, &cap, sizeof(cap)); if (strncmp((const char *)cap.prod_ida, "CYTRA", 5) != 0) { CyapaPrint(DEBUG_LEVEL_ERROR, DBG_PNP, "[cyapainit] Product ID \"%5.5s\" mismatch\n", cap.prod_ida); SpbReadDataSynchronously(&pDevice->I2CContext, CMD_QUERY_CAPABILITIES, &cap, sizeof(cap)); } sc->resx = ((cap.max_abs_xy_high << 4) & 0x0F00) | cap.max_abs_x_low; sc->resy = ((cap.max_abs_xy_high << 8) & 0x0F00) | cap.max_abs_y_low; sc->phyx = ((cap.phy_siz_xy_high << 4) & 0x0F00) | cap.phy_siz_x_low; sc->phyy = ((cap.phy_siz_xy_high << 8) & 0x0F00) | cap.phy_siz_y_low; CyapaPrint(DEBUG_LEVEL_INFO, DBG_PNP, "[cyapainit] %5.5s-%6.6s-%2.2s buttons=%c%c%c res=%dx%d\n", cap.prod_ida, cap.prod_idb, cap.prod_idc, ((cap.buttons & CYAPA_FNGR_LEFT) ? 'L' : '-'), ((cap.buttons & CYAPA_FNGR_MIDDLE) ? 'M' : '-'), ((cap.buttons & CYAPA_FNGR_RIGHT) ? 'R' : '-'), sc->resx, sc->resy); for (int i = 0; i < 5; i++) { sc->product_id[i] = cap.prod_ida[i]; } sc->product_id[5] = '-'; for (int i = 0; i < 6; i++) { sc->product_id[i + 6] = cap.prod_idb[i]; } sc->product_id[12] = '-'; for (int i = 0; i < 2; i++) { sc->product_id[i + 13] = cap.prod_idc[i]; } sc->product_id[15] = '\0'; sprintf(sc->firmware_version, "%d.%d", cap.fw_maj_ver, cap.fw_min_ver); sc->infoSetup = true; } cyapa_set_power_mode(pDevice, CMD_POWER_MODE_FULL); SpbReadDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, &boot, sizeof(boot)); WdfObjectDelete(WorkItem); }
void cyapa_set_power_mode(_In_ PDEVICE_CONTEXT pDevice, _In_ uint8_t power_mode) { int ret; uint8_t power; SpbReadDataSynchronously(&pDevice->I2CContext, CMD_POWER_MODE, &ret, 1); if (ret < 0) return; power = (ret & ~0xFC); power |= power_mode & 0xFc; SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_POWER_MODE, &power, 1); }
BOOLEAN OnInterruptIsr( WDFINTERRUPT Interrupt, ULONG MessageID){ UNREFERENCED_PARAMETER(MessageID); WDFDEVICE Device = WdfInterruptGetDevice(Interrupt); PDEVICE_CONTEXT pDevice = GetDeviceContext(Device); if (!pDevice->ConnectInterrupt) return true; struct cyapa_regs regs; SpbReadDataSynchronously(&pDevice->I2CContext, 0, ®s, sizeof(regs)); pDevice->lastregs = regs; pDevice->RegsSet = true; return true; }
NTSTATUS BOOTTRACKPAD( _In_ PDEVICE_CONTEXT pDevice ) { NTSTATUS status = 0; static char bl_exit[] = { 0x00, 0xff, 0xa5, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; static char bl_deactivate[] = { 0x00, 0xff, 0x3b, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 }; cyapa_boot_regs boot; FuncEntry(TRACE_FLAG_WDFLOADING); SpbReadDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, &boot, sizeof(boot)); if ((boot.stat & CYAPA_STAT_RUNNING) == 0) { if (boot.error & CYAPA_ERROR_BOOTLOADER) SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, bl_deactivate, sizeof(bl_deactivate)); else SpbWriteDataSynchronously(&pDevice->I2CContext, CMD_BOOT_STATUS, bl_exit, sizeof(bl_exit)); } WDF_TIMER_CONFIG timerConfig; WDFTIMER hTimer; WDF_OBJECT_ATTRIBUTES attributes; WDF_TIMER_CONFIG_INIT(&timerConfig, CyapaBootTimer); WDF_OBJECT_ATTRIBUTES_INIT(&attributes); attributes.ParentObject = pDevice->FxDevice; status = WdfTimerCreate(&timerConfig, &attributes, &hTimer); WdfTimerStart(hTimer, WDF_REL_TIMEOUT_IN_MS(75)); FuncExit(TRACE_FLAG_WDFLOADING); return status; }
NTSTATUS RmiChangeSleepState( IN RMI4_CONTROLLER_CONTEXT* ControllerContext, IN SPB_CONTEXT *SpbContext, IN UCHAR SleepState ) /*++ Routine Description: Changes the SleepMode bits on the controller as specified Arguments: ControllerContext - Touch controller context SpbContext - A pointer to the current i2c context SleepState - Either RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_OPERATING or RMI4_F11_DEVICE_CONTROL_SLEEP_MODE_SLEEPING Return Value: NTSTATUS indicating success or failure --*/ { RMI4_F01_CTRL_REGISTERS* controlF01; UCHAR deviceControl; int index; NTSTATUS status; controlF01 = (RMI4_F01_CTRL_REGISTERS*) &deviceControl; // // Find RMI device control function housing sleep settings // index = RmiGetFunctionIndex( ControllerContext->Descriptors, ControllerContext->FunctionCount, RMI4_F01_RMI_DEVICE_CONTROL); if (index == ControllerContext->FunctionCount) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_POWER, "Power change failure - RMI Function 01 missing"); status = STATUS_INVALID_DEVICE_STATE; goto exit; } status = RmiChangePage( ControllerContext, SpbContext, ControllerContext->FunctionOnPage[index]); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_POWER, "Could not change register page"); goto exit; } // // Read Device Control register // status = SpbReadDataSynchronously( SpbContext, ControllerContext->Descriptors[index].ControlBase, &deviceControl, sizeof(deviceControl) ); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_POWER, "Could not read sleep register - %!STATUS!", status); goto exit; } // // Assign new sleep state // controlF01->DeviceControl.SleepMode = SleepState; // // Write setting back to the controller // status = SpbWriteDataSynchronously( SpbContext, ControllerContext->Descriptors[index].ControlBase, &deviceControl, sizeof(deviceControl) ); if (!NT_SUCCESS(status)) { Trace( TRACE_LEVEL_ERROR, TRACE_FLAG_POWER, "Could not write sleep register - %X", status); goto exit; } exit: return status; }
NTSTATUS BOOTTRACKPAD( _In_ PDEVICE_CONTEXT pDevice ) { if (deviceLoaded) return 0; NTSTATUS status = 0; FuncEntry(TRACE_FLAG_WDFLOADING); elan_i2c_write_cmd(pDevice, ETP_I2C_STAND_CMD, ETP_I2C_RESET); uint8_t val[256]; SpbReadDataSynchronously(&pDevice->I2CContext, 0x00, &val, ETP_I2C_INF_LENGTH); SpbReadDataSynchronously16(&pDevice->I2CContext, ETP_I2C_DESC_CMD, &val, ETP_I2C_DESC_LENGTH); SpbReadDataSynchronously16(&pDevice->I2CContext, ETP_I2C_REPORT_DESC_CMD, &val, ETP_I2C_REPORT_DESC_LENGTH); elan_i2c_write_cmd(pDevice, ETP_I2C_SET_CMD, ETP_ENABLE_ABS); elan_i2c_write_cmd(pDevice, ETP_I2C_STAND_CMD, ETP_I2C_WAKE_UP); uint8_t val2[3]; elan_i2c_read_cmd(pDevice, ETP_I2C_UNIQUEID_CMD, val2); uint8_t prodid = val2[0]; elan_i2c_read_cmd(pDevice, ETP_I2C_FW_VERSION_CMD, val2); uint8_t version = val2[0]; elan_i2c_read_cmd(pDevice, ETP_I2C_FW_CHECKSUM_CMD, val2); uint16_t csum = *((uint16_t *)val2); elan_i2c_read_cmd(pDevice, ETP_I2C_SM_VERSION_CMD, val2); uint8_t smvers = val2[0]; elan_i2c_read_cmd(pDevice, ETP_I2C_IAP_VERSION_CMD, val2); uint8_t iapversion = val2[0]; elan_i2c_read_cmd(pDevice, ETP_I2C_PRESSURE_CMD, val2); elan_i2c_read_cmd(pDevice, ETP_I2C_MAX_X_AXIS_CMD, val2); uint16_t max_x = (*((uint16_t *)val2)) & 0x0fff; elan_i2c_read_cmd(pDevice, ETP_I2C_MAX_Y_AXIS_CMD, val2); uint16_t max_y = (*((uint16_t *)val2)) & 0x0fff; elan_i2c_read_cmd(pDevice, ETP_I2C_XY_TRACENUM_CMD, val2); uint8_t x_traces = val2[0]; uint8_t y_traces = val2[1]; pDevice->max_y = max_y; csgesture_softc *sc = &pDevice->sc; sc->resx = max_x; sc->resy = max_y; sc->phyx = max_x / x_traces; sc->phyy = max_y / y_traces; ElanPrint(DEBUG_LEVEL_INFO, DBG_PNP, "[etp] ProdID: %d Vers: %d Csum: %d SmVers: %d IAPVers: %d Max X: %d Max Y: %d\n", prodid, version, csum, smvers, iapversion, max_x, max_y); elan_i2c_write_cmd(pDevice, ETP_I2C_SET_CMD, ETP_ENABLE_CALIBRATE | ETP_ENABLE_ABS); elan_i2c_write_cmd(pDevice, ETP_I2C_STAND_CMD, ETP_I2C_WAKE_UP); elan_i2c_write_cmd(pDevice, ETP_I2C_CALIBRATE_CMD, 1); SpbReadDataSynchronously16(&pDevice->I2CContext, ETP_I2C_CALIBRATE_CMD, &val2, 1); elan_i2c_write_cmd(pDevice, ETP_I2C_SET_CMD, ETP_ENABLE_ABS); deviceLoaded = true; FuncExit(TRACE_FLAG_WDFLOADING); return status; }