📄 sony-laptop.c
字号:
sony_nc_acpi_device = device; strcpy(acpi_device_class(device), "sony/hotkey"); sony_nc_acpi_handle = device->handle; /* read device status */ result = acpi_bus_get_status(device); /* bail IFF the above call was successful and the device is not present */ if (!result && !device->status.present) { dprintk("Device not present\n"); result = -ENODEV; goto outwalk; } if (debug) { status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle, 1, sony_walk_callback, NULL, NULL); if (ACPI_FAILURE(status)) { printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n"); result = -ENODEV; goto outwalk; } } /* try to _INI the device if such method exists (ACPI spec 3.0-6.5.1 * should be respected as we already checked for the device presence above */ if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, METHOD_NAME__INI, &handle))) { dprintk("Invoking _INI\n"); if (ACPI_FAILURE(acpi_evaluate_object(sony_nc_acpi_handle, METHOD_NAME__INI, NULL, NULL))) dprintk("_INI Method failed\n"); } /* setup input devices and helper fifo */ result = sony_laptop_setup_input(device); if (result) { printk(KERN_ERR DRV_PFX "Unabe to create input devices.\n"); goto outwalk; } status = acpi_install_notify_handler(sony_nc_acpi_handle, ACPI_DEVICE_NOTIFY, sony_acpi_notify, NULL); if (ACPI_FAILURE(status)) { printk(KERN_WARNING DRV_PFX "unable to install notify handler (%u)\n", status); result = -ENODEV; goto outinput; } if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT", &handle))) { sony_backlight_device = backlight_device_register("sony", NULL, NULL, &sony_backlight_ops); if (IS_ERR(sony_backlight_device)) { printk(KERN_WARNING DRV_PFX "unable to register backlight device\n"); sony_backlight_device = NULL; } else { sony_backlight_device->props.brightness = sony_backlight_get_brightness (sony_backlight_device); sony_backlight_device->props.max_brightness = SONY_MAX_BRIGHTNESS - 1; } } /* initialize models with specific requirements */ dmi_check_system(sony_nc_ids); result = sony_pf_add(); if (result) goto outbacklight; /* create sony_pf sysfs attributes related to the SNC device */ for (item = sony_nc_values; item->name; ++item) { if (!debug && item->debug) continue; /* find the available acpiget as described in the DSDT */ for (; item->acpiget && *item->acpiget; ++item->acpiget) { if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, *item->acpiget, &handle))) { dprintk("Found %s getter: %s\n", item->name, *item->acpiget); item->devattr.attr.mode |= S_IRUGO; break; } } /* find the available acpiset as described in the DSDT */ for (; item->acpiset && *item->acpiset; ++item->acpiset) { if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, *item->acpiset, &handle))) { dprintk("Found %s setter: %s\n", item->name, *item->acpiset); item->devattr.attr.mode |= S_IWUSR; break; } } if (item->devattr.attr.mode != 0) { result = device_create_file(&sony_pf_device->dev, &item->devattr); if (result) goto out_sysfs; } } return 0; out_sysfs: for (item = sony_nc_values; item->name; ++item) { device_remove_file(&sony_pf_device->dev, &item->devattr); } sony_pf_remove(); outbacklight: if (sony_backlight_device) backlight_device_unregister(sony_backlight_device); status = acpi_remove_notify_handler(sony_nc_acpi_handle, ACPI_DEVICE_NOTIFY, sony_acpi_notify); if (ACPI_FAILURE(status)) printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n"); outinput: sony_laptop_remove_input(); outwalk: return result;}static int sony_nc_remove(struct acpi_device *device, int type){ acpi_status status; struct sony_nc_value *item; if (sony_backlight_device) backlight_device_unregister(sony_backlight_device); sony_nc_acpi_device = NULL; status = acpi_remove_notify_handler(sony_nc_acpi_handle, ACPI_DEVICE_NOTIFY, sony_acpi_notify); if (ACPI_FAILURE(status)) printk(KERN_WARNING DRV_PFX "unable to remove notify handler\n"); for (item = sony_nc_values; item->name; ++item) { device_remove_file(&sony_pf_device->dev, &item->devattr); } sony_pf_remove(); sony_laptop_remove_input(); dprintk(SONY_NC_DRIVER_NAME " removed.\n"); return 0;}static const struct acpi_device_id sony_device_ids[] = { {SONY_NC_HID, 0}, {SONY_PIC_HID, 0}, {"", 0},};MODULE_DEVICE_TABLE(acpi, sony_device_ids);static const struct acpi_device_id sony_nc_device_ids[] = { {SONY_NC_HID, 0}, {"", 0},};static struct acpi_driver sony_nc_driver = { .name = SONY_NC_DRIVER_NAME, .class = SONY_NC_CLASS, .ids = sony_nc_device_ids, .owner = THIS_MODULE, .ops = { .add = sony_nc_add, .remove = sony_nc_remove, .resume = sony_nc_resume, },};/*********** SPIC (SNY6001) Device ***********/#define SONYPI_DEVICE_TYPE1 0x00000001#define SONYPI_DEVICE_TYPE2 0x00000002#define SONYPI_DEVICE_TYPE3 0x00000004#define SONYPI_TYPE1_OFFSET 0x04#define SONYPI_TYPE2_OFFSET 0x12#define SONYPI_TYPE3_OFFSET 0x12struct sony_pic_ioport { struct acpi_resource_io io1; struct acpi_resource_io io2; struct list_head list;};struct sony_pic_irq { struct acpi_resource_irq irq; struct list_head list;};struct sony_pic_dev { int model; u16 evport_offset; u8 camera_power; u8 bluetooth_power; u8 wwan_power; struct acpi_device *acpi_dev; struct sony_pic_irq *cur_irq; struct sony_pic_ioport *cur_ioport; struct list_head interrupts; struct list_head ioports; struct mutex lock;};static struct sony_pic_dev spic_dev = { .interrupts = LIST_HEAD_INIT(spic_dev.interrupts), .ioports = LIST_HEAD_INIT(spic_dev.ioports),};/* Event masks */#define SONYPI_JOGGER_MASK 0x00000001#define SONYPI_CAPTURE_MASK 0x00000002#define SONYPI_FNKEY_MASK 0x00000004#define SONYPI_BLUETOOTH_MASK 0x00000008#define SONYPI_PKEY_MASK 0x00000010#define SONYPI_BACK_MASK 0x00000020#define SONYPI_HELP_MASK 0x00000040#define SONYPI_LID_MASK 0x00000080#define SONYPI_ZOOM_MASK 0x00000100#define SONYPI_THUMBPHRASE_MASK 0x00000200#define SONYPI_MEYE_MASK 0x00000400#define SONYPI_MEMORYSTICK_MASK 0x00000800#define SONYPI_BATTERY_MASK 0x00001000#define SONYPI_WIRELESS_MASK 0x00002000struct sonypi_event { u8 data; u8 event;};/* The set of possible button release events */static struct sonypi_event sonypi_releaseev[] = { { 0x00, SONYPI_EVENT_ANYBUTTON_RELEASED }, { 0, 0 }};/* The set of possible jogger events */static struct sonypi_event sonypi_joggerev[] = { { 0x1f, SONYPI_EVENT_JOGDIAL_UP }, { 0x01, SONYPI_EVENT_JOGDIAL_DOWN }, { 0x5f, SONYPI_EVENT_JOGDIAL_UP_PRESSED }, { 0x41, SONYPI_EVENT_JOGDIAL_DOWN_PRESSED }, { 0x1e, SONYPI_EVENT_JOGDIAL_FAST_UP }, { 0x02, SONYPI_EVENT_JOGDIAL_FAST_DOWN }, { 0x5e, SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED }, { 0x42, SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED }, { 0x1d, SONYPI_EVENT_JOGDIAL_VFAST_UP }, { 0x03, SONYPI_EVENT_JOGDIAL_VFAST_DOWN }, { 0x5d, SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED }, { 0x43, SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED }, { 0x40, SONYPI_EVENT_JOGDIAL_PRESSED }, { 0, 0 }};/* The set of possible capture button events */static struct sonypi_event sonypi_captureev[] = { { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED }, { 0x07, SONYPI_EVENT_CAPTURE_PRESSED }, { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED }, { 0, 0 }};/* The set of possible fnkeys events */static struct sonypi_event sonypi_fnkeyev[] = { { 0x10, SONYPI_EVENT_FNKEY_ESC }, { 0x11, SONYPI_EVENT_FNKEY_F1 }, { 0x12, SONYPI_EVENT_FNKEY_F2 }, { 0x13, SONYPI_EVENT_FNKEY_F3 }, { 0x14, SONYPI_EVENT_FNKEY_F4 }, { 0x15, SONYPI_EVENT_FNKEY_F5 }, { 0x16, SONYPI_EVENT_FNKEY_F6 }, { 0x17, SONYPI_EVENT_FNKEY_F7 }, { 0x18, SONYPI_EVENT_FNKEY_F8 }, { 0x19, SONYPI_EVENT_FNKEY_F9 }, { 0x1a, SONYPI_EVENT_FNKEY_F10 }, { 0x1b, SONYPI_EVENT_FNKEY_F11 }, { 0x1c, SONYPI_EVENT_FNKEY_F12 }, { 0x1f, SONYPI_EVENT_FNKEY_RELEASED }, { 0x21, SONYPI_EVENT_FNKEY_1 }, { 0x22, SONYPI_EVENT_FNKEY_2 }, { 0x31, SONYPI_EVENT_FNKEY_D }, { 0x32, SONYPI_EVENT_FNKEY_E }, { 0x33, SONYPI_EVENT_FNKEY_F }, { 0x34, SONYPI_EVENT_FNKEY_S }, { 0x35, SONYPI_EVENT_FNKEY_B }, { 0x36, SONYPI_EVENT_FNKEY_ONLY }, { 0, 0 }};/* The set of possible program key events */static struct sonypi_event sonypi_pkeyev[] = { { 0x01, SONYPI_EVENT_PKEY_P1 }, { 0x02, SONYPI_EVENT_PKEY_P2 }, { 0x04, SONYPI_EVENT_PKEY_P3 }, { 0x5c, SONYPI_EVENT_PKEY_P1 }, { 0, 0 }};/* The set of possible bluetooth events */static struct sonypi_event sonypi_blueev[] = { { 0x55, SONYPI_EVENT_BLUETOOTH_PRESSED }, { 0x59, SONYPI_EVENT_BLUETOOTH_ON }, { 0x5a, SONYPI_EVENT_BLUETOOTH_OFF }, { 0, 0 }};/* The set of possible wireless events */static struct sonypi_event sonypi_wlessev[] = { { 0x59, SONYPI_EVENT_WIRELESS_ON }, { 0x5a, SONYPI_EVENT_WIRELESS_OFF }, { 0, 0 }};/* The set of possible back button events */static struct sonypi_event sonypi_backev[] = { { 0x20, SONYPI_EVENT_BACK_PRESSED }, { 0, 0 }};/* The set of possible help button events */static struct sonypi_event sonypi_helpev[] = { { 0x3b, SONYPI_EVENT_HELP_PRESSED }, { 0, 0 }};/* The set of possible lid events */static struct sonypi_event sonypi_lidev[] = { { 0x51, SONYPI_EVENT_LID_CLOSED }, { 0x50, SONYPI_EVENT_LID_OPENED }, { 0, 0 }};/* The set of possible zoom events */static struct sonypi_event sonypi_zoomev[] = { { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, { 0, 0 }};/* The set of possible thumbphrase events */static struct sonypi_event sonypi_thumbphraseev[] = { { 0x3a, SONYPI_EVENT_THUMBPHRASE_PRESSED }, { 0, 0 }};/* The set of possible motioneye camera events */static struct sonypi_event sonypi_meyeev[] = { { 0x00, SONYPI_EVENT_MEYE_FACE }, { 0x01, SONYPI_EVENT_MEYE_OPPOSITE }, { 0, 0 }};/* The set of possible memorystick events */static struct sonypi_event sonypi_memorystickev[] = { { 0x53, SONYPI_EVENT_MEMORYSTICK_INSERT }, { 0x54, SONYPI_EVENT_MEMORYSTICK_EJECT }, { 0, 0 }};/* The set of possible battery events */static struct sonypi_event sonypi_batteryev[] = { { 0x20, SONYPI_EVENT_BATTERY_INSERT }, { 0x30, SONYPI_EVENT_BATTERY_REMOVE }, { 0, 0 }};static struct sonypi_eventtypes { int model; u8 data; unsigned long mask; struct sonypi_event * events;} sony_pic_eventtypes[] = { { SONYPI_DEVICE_TYPE1, 0, 0xffffffff, sonypi_releaseev }, { SONYPI_DEVICE_TYPE1, 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_LID_MASK, sonypi_lidev }, { SONYPI_DEVICE_TYPE1, 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, { SONYPI_DEVICE_TYPE1, 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, { SONYPI_DEVICE_TYPE1, 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev }, { SONYPI_DEVICE_TYPE2, 0, 0xffffffff, sonypi_releaseev }, { SONYPI_DEVICE_TYPE2, 0x38, SONYPI_LID_MASK, sonypi_lidev }, { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev }, { SONYPI_DEVICE_TYPE2, 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev }, { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, { SONYPI_DEVICE_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev }, { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev }, { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, { SONYPI_DEVICE_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { SONYPI_DEVICE_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, { SONYPI_DEVICE_TYPE3, 0, 0xffffffff, sonypi_releaseev }, { SONYPI_DEVICE_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, { SONYPI_DEVICE_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, { 0 }};static int sony_pic_detect_device_type(void){ struct pci_dev *pcidev; int model = 0; if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) model = SONYPI_DEVICE_TYPE1; else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) model = SONYPI_DEVICE_TYPE3; else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, NULL))) model = SONYPI_DEVICE_TYPE3; else model = SONYPI_DEVICE_TYPE2; if (pcidev) pci_dev_put(pcidev); printk(KERN_INFO DRV_PFX "detected Type%d model\n", model == SONYPI_DEVICE_TYPE1 ? 1 : model == SONYPI_DEVICE_TYPE2 ? 2 : 3); return model;}#define ITERATIONS_LONG 10000#define ITERATIONS_SHORT 10#define wait_on_command(command, iterations) { \ unsigned int n = iterations; \ while (--n && (command)) \ udelay(1); \ if (!n) \ dprintk("command failed at %s : %s (line %d)\n", \ __FILE__, __FUNCTION__, __LINE__); \}static u8 sony_pic_call1(u8 dev){ u8 v1, v2; wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); outb(dev, spic_dev.cur_ioport->io1.minimum + 4); v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4); v2 = inb_p(spic_dev.cur_ioport->io1.minimum); dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1); return v2;}static u8 sony_pic_call2(u8 dev, u8 fn){ u8 v1; wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); outb(dev, spic_dev.cur_ioport->io1.minimum + 4);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -