static int nvec_mouse_suspend(struct platform_device *pdev, pm_message_t state) { struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); /* disable mouse */ nvec_write_async(nvec, "\x06\xf4", 2); /* send cancel autoreceive */ nvec_write_async(nvec, "\x06\x04", 2); return 0; }
static int __devinit nvec_mouse_probe(struct platform_device *pdev) { struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); struct serio *ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL); ser_dev->id.type = SERIO_PS_PSTHRU; ser_dev->write = ps2_sendcommand; ser_dev->start = ps2_startstreaming; ser_dev->stop = ps2_stopstreaming; strlcpy(ser_dev->name, "nvec mouse", sizeof(ser_dev->name)); strlcpy(ser_dev->phys, "nvec", sizeof(ser_dev->phys)); ps2_dev.ser_dev = ser_dev; ps2_dev.notifier.notifier_call = nvec_ps2_notifier; ps2_dev.nvec = nvec; nvec_register_notifier(nvec, &ps2_dev.notifier, 0); serio_register_port(ser_dev); /* mouse reset */ nvec_write_async(nvec, MOUSE_RESET, 4); return 0; }
/** * nvec_write_sync - Write a message to nvec and read the response * @nvec: An &struct nvec_chip * @data: The data to write * @size: The size of @data * * This is similar to nvec_write_async(), but waits for the * request to be answered before returning. This function * uses a mutex and can thus not be called from e.g. * interrupt handlers. * * Returns: A pointer to the response message on success, * %NULL on failure. Free with nvec_msg_free() once no longer * used. */ struct nvec_msg *nvec_write_sync(struct nvec_chip *nvec, const unsigned char *data, short size) { struct nvec_msg *msg; mutex_lock(&nvec->sync_write_mutex); nvec->sync_write_pending = (data[1] << 8) + data[0]; if (nvec_write_async(nvec, data, size) < 0) { mutex_unlock(&nvec->sync_write_mutex); return NULL; } dev_dbg(nvec->dev, "nvec_sync_write: 0x%04x\n", nvec->sync_write_pending); if (!(wait_for_completion_timeout(&nvec->sync_write, msecs_to_jiffies(2000)))) { dev_warn(nvec->dev, "timeout waiting for sync write to complete\n"); mutex_unlock(&nvec->sync_write_mutex); return NULL; } dev_dbg(nvec->dev, "nvec_sync_write: pong!\n"); msg = nvec->last_sync_msg; mutex_unlock(&nvec->sync_write_mutex); return msg; }
static int nvec_mouse_probe(struct platform_device *pdev) { struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); struct serio *ser_dev; char mouse_reset[] = { NVEC_PS2, SEND_COMMAND, PSMOUSE_RST, 3 }; ser_dev = devm_kzalloc(&pdev->dev, sizeof(struct serio), GFP_KERNEL); if (ser_dev == NULL) return -ENOMEM; ser_dev->id.type = SERIO_PS_PSTHRU; ser_dev->write = ps2_sendcommand; ser_dev->start = ps2_startstreaming; ser_dev->stop = ps2_stopstreaming; strlcpy(ser_dev->name, "nvec mouse", sizeof(ser_dev->name)); strlcpy(ser_dev->phys, "nvec", sizeof(ser_dev->phys)); ps2_dev.ser_dev = ser_dev; ps2_dev.notifier.notifier_call = nvec_ps2_notifier; ps2_dev.nvec = nvec; nvec_register_notifier(nvec, &ps2_dev.notifier, 0); serio_register_port(ser_dev); /* mouse reset */ nvec_write_async(nvec, mouse_reset, sizeof(mouse_reset)); return 0; }
static int ps2_sendcommand(struct serio *ser_dev, unsigned char cmd) { unsigned char buf[] = SEND_COMMAND; buf[2] = cmd & 0xff; dev_dbg(&ser_dev->dev, "Sending ps2 cmd %02x\n", cmd); return nvec_write_async(ps2_dev.nvec, buf, sizeof(buf)); }
static int nvec_mouse_resume(struct platform_device *pdev) { struct nvec_chip *nvec = dev_get_drvdata(pdev->dev.parent); ps2_startstreaming(ps2_dev.ser_dev); /* enable mouse */ nvec_write_async(nvec, "\x06\xf5", 2); return 0; }
static void nvec_led_brightness_set(struct led_classdev *led_cdev, enum led_brightness value) { struct nvec_led *led = to_nvec_led(led_cdev); unsigned char buf[] = NVEC_LED_REQ; buf[4] = value; nvec_write_async(led->nvec, buf, sizeof(buf)); led->cdev.brightness = value; }
static void nvec_kbd_toggle_led(void) { char buf[] = { NVEC_KBD, SET_LEDS, 0 }; keys_dev.caps_lock = !keys_dev.caps_lock; if (keys_dev.caps_lock) /* should be BIT(0) only, firmware bug? */ buf[2] = BIT(0) | BIT(1) | BIT(2); nvec_write_async(keys_dev.nvec, buf, sizeof(buf)); }
int __init nvec_ps2(struct nvec_chip *nvec) { struct serio *ser_dev = kzalloc(sizeof(struct serio), GFP_KERNEL); ser_dev->id.type=SERIO_8042; ser_dev->write=ps2_sendcommand; ser_dev->open=ps2_startstreaming; ser_dev->close=ps2_stopstreaming; strlcpy(ser_dev->name, "NVEC PS2", sizeof(ser_dev->name)); strlcpy(ser_dev->phys, "NVEC I2C slave", sizeof(ser_dev->phys)); ps2_dev.ser_dev = ser_dev; ps2_dev.notifier.notifier_call = nvec_ps2_notifier; ps2_dev.nvec = nvec; nvec_register_notifier(nvec, &ps2_dev.notifier, 0); serio_register_port(ser_dev); /* mouse reset */ nvec_write_async(nvec, "\x06\x01\xff\x03", 4); return 0; }
static void ps2_stopstreaming(struct serio *ser_dev) { unsigned char buf[] = STOP_STREAMING; nvec_write_async(ps2_dev.nvec, buf, sizeof(buf)); }
static int ps2_startstreaming(struct serio *ser_dev) { unsigned char buf[] = START_STREAMING; return nvec_write_async(ps2_dev.nvec, buf, sizeof(buf)); }
/** * nvec_toggle_global_events - enables or disables global event reporting * @nvec: nvec handle * @state: true for enable, false for disable * * This switches on/off global event reports by the embedded controller. */ static void nvec_toggle_global_events(struct nvec_chip *nvec, bool state) { unsigned char global_events[] = { NVEC_SLEEP, GLOBAL_EVENTS, state }; nvec_write_async(nvec, global_events, 3); }
static void ps2_stopstreaming(struct serio *ser_dev) { unsigned char buf[] = { NVEC_PS2, CANCEL_AUTO_RECEIVE }; nvec_write_async(ps2_dev.nvec, buf, sizeof(buf)); }
static int ps2_startstreaming(struct serio *ser_dev) { unsigned char buf[] = { NVEC_PS2, AUTO_RECEIVE_N, PACKET_SIZE }; return nvec_write_async(ps2_dev.nvec, buf, sizeof(buf)); }