static int __devinit matrix_keypad_probe(struct platform_device *pdev) { const struct matrix_keypad_platform_data *pdata; const struct matrix_keymap_data *keymap_data; struct matrix_keypad *keypad; struct input_dev *input_dev; unsigned short *keycodes; unsigned int row_shift; int err; pdata = pdev->dev.platform_data; if (!pdata) { dev_err(&pdev->dev, "no platform data defined\n"); return -EINVAL; } keymap_data = pdata->keymap_data; if (!keymap_data) { dev_err(&pdev->dev, "no keymap data defined\n"); return -EINVAL; } row_shift = get_count_order(pdata->num_col_gpios); keypad = kzalloc(sizeof(struct matrix_keypad), GFP_KERNEL); keycodes = kzalloc((pdata->num_row_gpios << row_shift) * sizeof(*keycodes), GFP_KERNEL); input_dev = input_allocate_device(); if (!keypad || !keycodes || !input_dev) { err = -ENOMEM; goto err_free_mem; } keypad->input_dev = input_dev; keypad->pdata = pdata; keypad->keycodes = keycodes; keypad->row_shift = row_shift; keypad->stopped = true; INIT_DELAYED_WORK(&keypad->work, matrix_keypad_scan); spin_lock_init(&keypad->lock); input_dev->name = pdev->name; input_dev->id.bustype = BUS_HOST; input_dev->dev.parent = &pdev->dev; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); input_dev->open = matrix_keypad_start; input_dev->close = matrix_keypad_stop; input_dev->keycode = keycodes; input_dev->keycodesize = sizeof(*keycodes); input_dev->keycodemax = pdata->num_row_gpios << row_shift; matrix_keypad_build_keymap(keymap_data, row_shift, input_dev->keycode, input_dev->keybit); input_set_capability(input_dev, EV_MSC, MSC_SCAN); input_set_drvdata(input_dev, keypad); err = init_matrix_gpio(pdev, keypad); if (err) goto err_free_mem; err = input_register_device(keypad->input_dev); if (err) goto err_free_mem; device_init_wakeup(&pdev->dev, pdata->wakeup); platform_set_drvdata(pdev, keypad); return 0; err_free_mem: input_free_device(input_dev); kfree(keycodes); kfree(keypad); return err; }
static int __devinit dock_keyboard_probe(struct platform_device *pdev) { // struct dock_keyboard_data *data = pdev->dev.platform_data; struct dock_keyboard_data *data; struct input_dev *input; int i, error; #if defined(ACC_INT_KBD) int gpio, irq; #endif struct device *keyboard_dev; data = kzalloc(sizeof(struct dock_keyboard_data), GFP_KERNEL); if(NULL == data) { error = -ENOMEM; goto err_free_mem; } INIT_WORK(&data->work_msg, key_event_work); INIT_WORK(&data->work_led, led_work); input = input_allocate_device(); if (!input) { printk(KERN_ERR "[Keyboard] Fail to allocate input device.\n"); error = -ENOMEM; goto err_free_mem; } data->input_dev = input; data->kl = UNKOWN_KEYLAYOUT; input->name = pdev->name; input->dev.parent = &pdev->dev; input->id.bustype = BUS_RS232; set_bit(EV_SYN, input->evbit); // set_bit(EV_REP, input->evbit); set_bit(EV_KEY, input->evbit); for(i = 0; i < KEYBOARD_SIZE; i++) { if( KEY_RESERVED != dock_keycodes[i].keycode) { input_set_capability(input, EV_KEY, dock_keycodes[i].keycode); } } /* for the UK keyboard */ input_set_capability(input, EV_KEY, KEY_NUMERIC_POUND); /* for the remaped keys */ input_set_capability(input, EV_KEY, KEY_NEXTSONG); input_set_capability(input, EV_KEY, KEY_PREVIOUSSONG); error = input_register_device(data->input_dev); if(error<0) { printk(KERN_ERR "[Keyboard] Fail to register input device.\n"); error = -ENOMEM; goto err_free_mem; } /* Accessory detect pin is used by dock accessory driver. */ #if defined(ACC_INT_KBD) gpio = GPIO_ACCESSORY_INT; s3c_gpio_cfgpin(gpio, S3C_GPIO_INPUT); s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE); irq = IRQ_EINT5; error = request_irq(irq, accessory_interrupt, IRQF_SAMPLE_RANDOM|IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING, "p1_keyboard", data); if(error) { printk(KERN_ERR "[Keyboard] Fail to request irq : %d\n", error); error = -EINTR; goto err_free_mem; } data->gpio = gpio; #else data->gpio = GPIO_ACCESSORY_INT; #endif g_data = data; keyboard_dev = device_create(sec_class, NULL, 0, NULL, "keyboard"); if (IS_ERR(keyboard_dev)) pr_err("Failed to create device(ts)!\n"); if (device_create_file(keyboard_dev, &dev_attr_keyboard_led) < 0) pr_err("Failed to create device file(%s)!\n", dev_attr_keyboard_led.attr.name); #ifdef CONFIG_HAS_EARLYSUSPEND data->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; data->early_suspend.suspend = keyboard_early_suspend; data->early_suspend.resume = keyboard_late_resume; register_early_suspend(&data->early_suspend); #endif /* CONFIG_HAS_EARLYSUSPEND */ init_timer(&data->timer); data->timer.expires = jiffies + HZ * 5; data->timer.function = keyboard_timer; /* timer handler */ add_timer(&data->timer); init_timer(&data->key_timer); data->key_timer.expires = jiffies + HZ/2; data->key_timer.function = remapkey_timer; add_timer(&data->key_timer); boot_time = jiffies_to_msecs(jiffies); return 0; err_free_mem: input_free_device(input); kfree(data); return error; }
static int __devinit tca6416_keypad_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct tca6416_keys_platform_data *pdata; struct tca6416_keypad_chip *chip; struct input_dev *input; int error; int i; /* Check functionality */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { dev_err(&client->dev, "%s adapter not supported\n", dev_driver_string(&client->adapter->dev)); return -ENODEV; } pdata = client->dev.platform_data; if (!pdata) { dev_dbg(&client->dev, "no platform data\n"); return -EINVAL; } chip = kzalloc(sizeof(struct tca6416_keypad_chip) + pdata->nbuttons * sizeof(struct tca6416_button), GFP_KERNEL); input = input_allocate_device(); if (!chip || !input) { error = -ENOMEM; goto fail1; } chip->client = client; chip->input = input; chip->io_size = id->driver_data; chip->pinmask = pdata->pinmask; chip->use_polling = pdata->use_polling; INIT_DELAYED_WORK(&chip->dwork, tca6416_keys_work_func); input->phys = "tca6416-keys/input0"; input->name = client->name; input->dev.parent = &client->dev; input->open = tca6416_keys_open; input->close = tca6416_keys_close; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0100; /* Enable auto repeat feature of Linux input subsystem */ if (pdata->rep) __set_bit(EV_REP, input->evbit); for (i = 0; i < pdata->nbuttons; i++) { unsigned int type; chip->buttons[i] = pdata->buttons[i]; type = (pdata->buttons[i].type) ?: EV_KEY; input_set_capability(input, type, pdata->buttons[i].code); } input_set_drvdata(input, chip); /* * Initialize cached registers from their original values. * we can't share this chip with another i2c master. */ error = tca6416_setup_registers(chip); if (error) goto fail1; if (!chip->use_polling) { if (pdata->irq_is_gpio) chip->irqnum = gpio_to_irq(client->irq); else chip->irqnum = client->irq; error = request_threaded_irq(chip->irqnum, NULL, tca6416_keys_isr, IRQF_TRIGGER_FALLING, "tca6416-keypad", chip); if (error) { dev_dbg(&client->dev, "Unable to claim irq %d; error %d\n", chip->irqnum, error); goto fail1; } disable_irq(chip->irqnum); } error = input_register_device(input); if (error) { dev_dbg(&client->dev, "Unable to register input device, error: %d\n", error); goto fail2; } i2c_set_clientdata(client, chip); return 0; fail2: if (!chip->use_polling) { free_irq(chip->irqnum, chip); enable_irq(chip->irqnum); } fail1: input_free_device(input); kfree(chip); return error; }
static int __devinit hs_probe(struct platform_device *pdev) { int rc = 0; struct input_dev *ipdev; hs = kzalloc(sizeof(struct msm_handset), GFP_KERNEL); if (!hs) return -ENOMEM; #ifndef CONFIG_LGE_HEADSET hs->sdev.name = "h2w"; hs->sdev.print_name = msm_headset_print_name; rc = switch_dev_register(&hs->sdev); if (rc) goto err_switch_dev_register; #endif ipdev = input_allocate_device(); if (!ipdev) { rc = -ENOMEM; goto err_alloc_input_dev; } input_set_drvdata(ipdev, hs); hs->ipdev = ipdev; if (pdev->dev.platform_data) hs->hs_pdata = pdev->dev.platform_data; if (hs->hs_pdata->hs_name) ipdev->name = hs->hs_pdata->hs_name; else ipdev->name = DRIVER_NAME; ipdev->id.vendor = 0x0001; ipdev->id.product = 1; ipdev->id.version = 1; input_set_capability(ipdev, EV_KEY, KEY_MEDIA); input_set_capability(ipdev, EV_KEY, KEY_VOLUMEUP); input_set_capability(ipdev, EV_KEY, KEY_VOLUMEDOWN); input_set_capability(ipdev, EV_SW, SW_HEADPHONE_INSERT); input_set_capability(ipdev, EV_KEY, KEY_POWER); input_set_capability(ipdev, EV_KEY, KEY_END); rc = input_register_device(ipdev); if (rc) { dev_err(&ipdev->dev, "hs_probe: input_register_device rc=%d\n", rc); goto err_reg_input_dev; } platform_set_drvdata(pdev, hs); rc = hs_rpc_init(); if (rc) { dev_err(&ipdev->dev, "rpc init failure\n"); goto err_hs_rpc_init; } return 0; err_hs_rpc_init: input_unregister_device(ipdev); ipdev = NULL; err_reg_input_dev: input_free_device(ipdev); err_alloc_input_dev: #ifndef CONFIG_LGE_HEADSET switch_dev_unregister(&hs->sdev); err_switch_dev_register: #endif kfree(hs); return rc; }
static int g19_probe(struct hid_device *hdev, const struct hid_device_id *id) { unsigned long irq_flags; int error; struct gcommon_data *gdata; struct g19_data *g19data; int i; int led_num; struct usb_interface *intf; struct usb_device *usbdev; struct list_head *feature_report_list = &hdev->report_enum[HID_FEATURE_REPORT].report_list; struct hid_report *report; char *led_name; dev_dbg(&hdev->dev, "Logitech G19 HID hardware probe..."); /* Get the usb device to send the start report on */ intf = to_usb_interface(hdev->dev.parent); usbdev = interface_to_usbdev(intf); /* * Let's allocate the g19 data structure, set some reasonable * defaults, and associate it with the device */ gdata = kzalloc(sizeof(struct gcommon_data), GFP_KERNEL); if (gdata == NULL) { dev_err(&hdev->dev, "can't allocate space for Logitech G19 device attributes\n"); error = -ENOMEM; goto err_no_cleanup; } g19data = kzalloc(sizeof(struct g19_data), GFP_KERNEL); if (g19data == NULL) { dev_err(&hdev->dev, "can't allocate space for Logitech G19 device attributes\n"); error = -ENOMEM; goto err_cleanup_gdata; } gdata->data = g19data; spin_lock_init(&gdata->lock); init_completion(&g19data->ready); gdata->hdev = hdev; g19data->ep1_urb = usb_alloc_urb(0, GFP_KERNEL); if (g19data->ep1_urb == NULL) { dev_err(&hdev->dev, G19_NAME ": ERROR: can't alloc ep1 urb stuff\n"); error = -ENOMEM; goto err_cleanup_g19data; } hid_set_drvdata(hdev, gdata); dbg_hid("Preparing to parse " G19_NAME " hid reports\n"); /* Parse the device reports and start it up */ error = hid_parse(hdev); if (error) { dev_err(&hdev->dev, G19_NAME " device report parse failed\n"); error = -EINVAL; goto err_cleanup_ep1_urb; } error = hid_hw_start(hdev, HID_CONNECT_DEFAULT | HID_CONNECT_HIDINPUT_FORCE); if (error) { dev_err(&hdev->dev, G19_NAME " hardware start failed\n"); error = -EINVAL; goto err_cleanup_ep1_urb; } dbg_hid(G19_NAME " claimed: %d\n", hdev->claimed); error = hdev->ll_driver->open(hdev); if (error) { dev_err(&hdev->dev, G19_NAME " failed to open input interrupt pipe for key and joystick events\n"); error = -EINVAL; goto err_cleanup_hw_start; } /* Set up the input device for the key I/O */ gdata->input_dev = input_allocate_device(); if (gdata->input_dev == NULL) { dev_err(&hdev->dev, G19_NAME " error initializing the input device"); error = -ENOMEM; goto err_cleanup_hw_start; } input_set_drvdata(gdata->input_dev, gdata); gdata->input_dev->name = G19_NAME; gdata->input_dev->phys = hdev->phys; gdata->input_dev->uniq = hdev->uniq; gdata->input_dev->id.bustype = hdev->bus; gdata->input_dev->id.vendor = hdev->vendor; gdata->input_dev->id.product = hdev->product; gdata->input_dev->id.version = hdev->version; gdata->input_dev->dev.parent = hdev->dev.parent; gdata->input_dev->keycode = gdata->input_data.keycode; gdata->input_dev->keycodemax = G19_KEYMAP_SIZE; gdata->input_dev->keycodesize = sizeof(unsigned int); gdata->input_dev->setkeycode = ginput_setkeycode; gdata->input_dev->getkeycode = ginput_getkeycode; input_set_capability(gdata->input_dev, EV_KEY, KEY_UNKNOWN); gdata->input_dev->evbit[0] |= BIT_MASK(EV_REP); gdata->input_data.notify_keymap_switched = g19_notify_keymap_switched; error = ginput_alloc(gdata, G19_KEYS); if (error) { dev_err(&hdev->dev, G19_NAME " error allocating memory for the input device"); goto err_cleanup_input_dev; } g19_initialize_keymap(gdata); error = input_register_device(gdata->input_dev); if (error) { dev_err(&hdev->dev, G19_NAME " error registering the input device"); error = -EINVAL; goto err_cleanup_input_dev_data; } if (list_empty(feature_report_list)) { dev_err(&hdev->dev, "no feature report found\n"); error = -ENODEV; goto err_cleanup_input_dev_reg; } dbg_hid(G19_NAME " feature report found\n"); list_for_each_entry(report, feature_report_list, list) { switch (report->id) { case 0x04: g19data->feature_report_4 = report; break; case 0x05: g19data->led_report = report; break; case 0x06: g19data->start_input_report = report; break; case 0x07: g19data->backlight_report = report; break; default: break; } dbg_hid(G19_NAME " Feature report: id=%u type=%u size=%u maxfield=%u report_count=%u\n", report->id, report->type, report->size, report->maxfield, report->field[0]->report_count); } dbg_hid("Found all reports\n"); /* Create the LED structures */ for (i = 0; i < LED_COUNT; i++) { g19data->led_cdev[i] = kzalloc(sizeof(struct led_classdev), GFP_KERNEL); if (g19data->led_cdev[i] == NULL) { dev_err(&hdev->dev, G19_NAME " error allocating memory for led %d", i); error = -ENOMEM; goto err_cleanup_led_structs; } /* Set the accessor functions by copying from template*/ *(g19data->led_cdev[i]) = g19_led_cdevs[i]; /* * Allocate memory for the LED name * * Since led_classdev->name is a const char* we'll use an * intermediate until the name is formatted with sprintf(). */ led_name = kzalloc(sizeof(char)*20, GFP_KERNEL); if (led_name == NULL) { dev_err(&hdev->dev, G19_NAME " error allocating memory for led %d name", i); error = -ENOMEM; goto err_cleanup_led_structs; } switch (i) { case G19_LED_M1: case G19_LED_M2: case G19_LED_M3: sprintf(led_name, "g19_%d:orange:m%d", hdev->minor, i+1); break; case G19_LED_MR: sprintf(led_name, "g19_%d:red:mr", hdev->minor); break; case G19_LED_BL_R: sprintf(led_name, "g19_%d:red:bl", hdev->minor); break; case G19_LED_BL_G: sprintf(led_name, "g19_%d:green:bl", hdev->minor); break; case G19_LED_BL_B: sprintf(led_name, "g19_%d:blue:bl", hdev->minor); break; case G19_LED_BL_SCREEN: sprintf(led_name, "g19_%d:white:screen", hdev->minor); break; } g19data->led_cdev[i]->name = led_name; } for (i = 0; i < LED_COUNT; i++) { led_num = i; error = led_classdev_register(&hdev->dev, g19data->led_cdev[i]); if (error < 0) { dev_err(&hdev->dev, G19_NAME " error registering led %d", i); error = -EINVAL; goto err_cleanup_registered_leds; } } gdata->gfb_data = gfb_probe(hdev, GFB_PANEL_TYPE_320_240_16); if (gdata->gfb_data == NULL) { dev_err(&hdev->dev, G19_NAME " error registering framebuffer\n"); goto err_cleanup_registered_leds; } dbg_hid("Waiting for G19 to activate\n"); /* Add the sysfs attributes */ error = sysfs_create_group(&(hdev->dev.kobj), &g19_attr_group); if (error) { dev_err(&hdev->dev, G19_NAME " failed to create sysfs group attributes\n"); goto err_cleanup_gfb; } /* * Wait here for stage 1 (substages 1-3) to complete */ wait_for_completion_timeout(&g19data->ready, HZ); /* Protect data->ready_stages before checking whether we're ready to proceed */ spin_lock_irqsave(&gdata->lock, irq_flags); if (g19data->ready_stages != G19_READY_STAGE_1) { dev_warn(&hdev->dev, G19_NAME " hasn't completed stage 1 yet, forging ahead with initialization\n"); /* Force the stage */ g19data->ready_stages = G19_READY_STAGE_1; } init_completion(&g19data->ready); g19data->ready_stages |= G19_READY_SUBSTAGE_4; spin_unlock_irqrestore(&gdata->lock, irq_flags); /* * Send the init report, then follow with the input report to trigger * report 6 and wait for us to get a response. */ g19_feature_report_4_send(hdev, G19_REPORT_4_INIT); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) hid_hw_request(hdev, g19data->start_input_report, HID_REQ_GET_REPORT); #else usbhid_submit_report(hdev, g19data->start_input_report, USB_DIR_IN); #endif wait_for_completion_timeout(&g19data->ready, HZ); /* Protect g19data->ready_stages before checking whether we're ready to proceed */ spin_lock_irqsave(&gdata->lock, irq_flags); if (g19data->ready_stages != G19_READY_STAGE_2) { dev_warn(&hdev->dev, G19_NAME " hasn't completed stage 2 yet, forging ahead with initialization\n"); /* Force the stage */ g19data->ready_stages = G19_READY_STAGE_2; } init_completion(&g19data->ready); g19data->ready_stages |= G19_READY_SUBSTAGE_6; spin_unlock_irqrestore(&gdata->lock, irq_flags); /* * Clear the LEDs */ g19_led_send(hdev); g19data->rgb[0] = G19_DEFAULT_RED; g19data->rgb[1] = G19_DEFAULT_GREEN; g19data->rgb[2] = G19_DEFAULT_BLUE; g19_rgb_send(hdev); g19data->screen_bl = G19_DEFAULT_BRIGHTNESS; g19_screen_bl_send(hdev); /* * Send the finalize report, then follow with the input report to trigger * report 6 and wait for us to get a response. */ g19_feature_report_4_send(hdev, G19_REPORT_4_FINALIZE); #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) hid_hw_request(hdev, g19data->start_input_report, HID_REQ_GET_REPORT); hid_hw_request(hdev, g19data->start_input_report, HID_REQ_GET_REPORT); #else usbhid_submit_report(hdev, g19data->start_input_report, USB_DIR_IN); usbhid_submit_report(hdev, g19data->start_input_report, USB_DIR_IN); #endif wait_for_completion_timeout(&g19data->ready, HZ); /* Protect data->ready_stages before checking whether we're ready to proceed */ spin_lock_irqsave(&gdata->lock, irq_flags); if (g19data->ready_stages != G19_READY_STAGE_3) { dev_warn(&hdev->dev, G19_NAME " hasn't completed stage 3 yet, forging ahead with initialization\n"); /* Force the stage */ g19data->ready_stages = G19_READY_STAGE_3; } else { dbg_hid(G19_NAME " stage 3 complete\n"); } spin_unlock_irqrestore(&gdata->lock, irq_flags); ginput_set_keymap_switching(gdata, 1); g19_ep1_read(hdev); dbg_hid("G19 activated and initialized\n"); /* Everything went well */ return 0; err_cleanup_gfb: gfb_remove(gdata->gfb_data); err_cleanup_registered_leds: for (i = 0; i < led_num; i++) led_classdev_unregister(g19data->led_cdev[i]); err_cleanup_led_structs: for (i = 0; i < LED_COUNT; i++) { if (g19data->led_cdev[i] != NULL) { if (g19data->led_cdev[i]->name != NULL) kfree(g19data->led_cdev[i]->name); kfree(g19data->led_cdev[i]); } } err_cleanup_input_dev_reg: input_unregister_device(gdata->input_dev); err_cleanup_input_dev_data: ginput_free(gdata); err_cleanup_input_dev: input_free_device(gdata->input_dev); err_cleanup_hw_start: hid_hw_stop(hdev); err_cleanup_ep1_urb: usb_free_urb(g19data->ep1_urb); err_cleanup_g19data: kfree(g19data); err_cleanup_gdata: kfree(gdata); err_no_cleanup: hid_set_drvdata(hdev, NULL); return error; }
static int __devinit pmic8xxx_kp_probe(struct platform_device *pdev) { const struct pm8xxx_keypad_platform_data *pdata = dev_get_platdata(&pdev->dev); const struct matrix_keymap_data *keymap_data; struct pmic8xxx_kp *kp; int rc; u8 ctrl_val; struct pm_gpio kypd_drv = { .direction = PM_GPIO_DIR_OUT, .output_buffer = PM_GPIO_OUT_BUF_OPEN_DRAIN, .output_value = 0, .pull = PM_GPIO_PULL_NO, .vin_sel = PM_GPIO_VIN_S4, .out_strength = PM_GPIO_STRENGTH_LOW, .function = PM_GPIO_FUNC_1, .inv_int_pol = 1, }; struct pm_gpio kypd_sns = { .direction = PM_GPIO_DIR_IN, .pull = PM_GPIO_PULL_UP_31P5, .vin_sel = PM_GPIO_VIN_S4, .out_strength = PM_GPIO_STRENGTH_NO, .function = PM_GPIO_FUNC_NORMAL, .inv_int_pol = 1, }; if (!pdata || !pdata->num_cols || !pdata->num_rows || pdata->num_cols > PM8XXX_MAX_COLS || pdata->num_rows > PM8XXX_MAX_ROWS || pdata->num_cols < PM8XXX_MIN_COLS) { dev_err(&pdev->dev, "invalid platform data\n"); return -EINVAL; } if (!pdata->scan_delay_ms || pdata->scan_delay_ms > MAX_SCAN_DELAY || pdata->scan_delay_ms < MIN_SCAN_DELAY || !is_power_of_2(pdata->scan_delay_ms)) { dev_err(&pdev->dev, "invalid keypad scan time supplied\n"); return -EINVAL; } if (!pdata->row_hold_ns || pdata->row_hold_ns > MAX_ROW_HOLD_DELAY || pdata->row_hold_ns < MIN_ROW_HOLD_DELAY || ((pdata->row_hold_ns % MIN_ROW_HOLD_DELAY) != 0)) { dev_err(&pdev->dev, "invalid keypad row hold time supplied\n"); return -EINVAL; } if (!pdata->debounce_ms || ((pdata->debounce_ms % 5) != 0) || pdata->debounce_ms > MAX_DEBOUNCE_TIME || pdata->debounce_ms < MIN_DEBOUNCE_TIME) { dev_err(&pdev->dev, "invalid debounce time supplied\n"); return -EINVAL; } keymap_data = pdata->keymap_data; if (!keymap_data) { dev_err(&pdev->dev, "no keymap data supplied\n"); return -EINVAL; } kp = kzalloc(sizeof(*kp), GFP_KERNEL); if (!kp) return -ENOMEM; platform_set_drvdata(pdev, kp); kp->pdata = pdata; kp->dev = &pdev->dev; kp->input = input_allocate_device(); if (!kp->input) { dev_err(&pdev->dev, "unable to allocate input device\n"); rc = -ENOMEM; goto err_alloc_device; } kp->key_sense_irq = platform_get_irq(pdev, 0); if (kp->key_sense_irq < 0) { dev_err(&pdev->dev, "unable to get keypad sense irq\n"); rc = -ENXIO; goto err_get_irq; } kp->key_stuck_irq = platform_get_irq(pdev, 1); if (kp->key_stuck_irq < 0) { dev_err(&pdev->dev, "unable to get keypad stuck irq\n"); rc = -ENXIO; goto err_get_irq; } kp->input->name = pdata->input_name ? : "PMIC8XXX keypad"; kp->input->phys = pdata->input_phys_device ? : "pmic8xxx_keypad/input0"; kp->input->dev.parent = &pdev->dev; kp->input->id.bustype = BUS_I2C; kp->input->id.version = 0x0001; kp->input->id.product = 0x0001; kp->input->id.vendor = 0x0001; kp->input->evbit[0] = BIT_MASK(EV_KEY); if (pdata->rep) __set_bit(EV_REP, kp->input->evbit); kp->input->keycode = kp->keycodes; kp->input->keycodemax = PM8XXX_MATRIX_MAX_SIZE; kp->input->keycodesize = sizeof(kp->keycodes); kp->input->open = pmic8xxx_kp_open; kp->input->close = pmic8xxx_kp_close; matrix_keypad_build_keymap(keymap_data, PM8XXX_ROW_SHIFT, kp->input->keycode, kp->input->keybit); input_set_capability(kp->input, EV_MSC, MSC_SCAN); input_set_drvdata(kp->input, kp); /* */ memset(kp->keystate, 0xff, sizeof(kp->keystate)); memset(kp->stuckstate, 0xff, sizeof(kp->stuckstate)); rc = pmic8xxx_kpd_init(kp); if (rc < 0) { dev_err(&pdev->dev, "unable to initialize keypad controller\n"); goto err_get_irq; } rc = pmic8xxx_kp_config_gpio(pdata->cols_gpio_start, pdata->num_cols, kp, &kypd_sns); if (rc < 0) { dev_err(&pdev->dev, "unable to configure keypad sense lines\n"); goto err_gpio_config; } rc = pmic8xxx_kp_config_gpio(pdata->rows_gpio_start, pdata->num_rows, kp, &kypd_drv); if (rc < 0) { dev_err(&pdev->dev, "unable to configure keypad drive lines\n"); goto err_gpio_config; } rc = request_any_context_irq(kp->key_sense_irq, pmic8xxx_kp_irq, IRQF_TRIGGER_RISING, "pmic-keypad", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad sense irq\n"); goto err_get_irq; } rc = request_any_context_irq(kp->key_stuck_irq, pmic8xxx_kp_stuck_irq, IRQF_TRIGGER_RISING, "pmic-keypad-stuck", kp); if (rc < 0) { dev_err(&pdev->dev, "failed to request keypad stuck irq\n"); goto err_req_stuck_irq; } rc = pmic8xxx_kp_read_u8(kp, &ctrl_val, KEYP_CTRL); if (rc < 0) { dev_err(&pdev->dev, "failed to read KEYP_CTRL register\n"); goto err_pmic_reg_read; } kp->ctrl_reg = ctrl_val; rc = input_register_device(kp->input); if (rc < 0) { dev_err(&pdev->dev, "unable to register keypad input device\n"); goto err_pmic_reg_read; } device_init_wakeup(&pdev->dev, pdata->wakeup); return 0; err_pmic_reg_read: free_irq(kp->key_stuck_irq, kp); err_req_stuck_irq: free_irq(kp->key_sense_irq, kp); err_gpio_config: err_get_irq: input_free_device(kp->input); err_alloc_device: platform_set_drvdata(pdev, NULL); kfree(kp); return rc; } static int __devexit pmic8xxx_kp_remove(struct platform_device *pdev) { struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); device_init_wakeup(&pdev->dev, 0); free_irq(kp->key_stuck_irq, kp); free_irq(kp->key_sense_irq, kp); input_unregister_device(kp->input); kfree(kp); platform_set_drvdata(pdev, NULL); return 0; } #ifdef CONFIG_PM_SLEEP static int pmic8xxx_kp_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); struct input_dev *input_dev = kp->input; if (device_may_wakeup(dev)) { enable_irq_wake(kp->key_sense_irq); } else { mutex_lock(&input_dev->mutex); if (input_dev->users) pmic8xxx_kp_disable(kp); mutex_unlock(&input_dev->mutex); } return 0; } static int pmic8xxx_kp_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct pmic8xxx_kp *kp = platform_get_drvdata(pdev); struct input_dev *input_dev = kp->input; if (device_may_wakeup(dev)) { disable_irq_wake(kp->key_sense_irq); } else { mutex_lock(&input_dev->mutex); if (input_dev->users) pmic8xxx_kp_enable(kp); mutex_unlock(&input_dev->mutex); } return 0; } #endif static SIMPLE_DEV_PM_OPS(pm8xxx_kp_pm_ops, pmic8xxx_kp_suspend, pmic8xxx_kp_resume); static struct platform_driver pmic8xxx_kp_driver = { .probe = pmic8xxx_kp_probe, .remove = __devexit_p(pmic8xxx_kp_remove), .driver = { .name = PM8XXX_KEYPAD_DEV_NAME, .owner = THIS_MODULE, .pm = &pm8xxx_kp_pm_ops, }, }; module_platform_driver(pmic8xxx_kp_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("PMIC8XXX keypad driver"); MODULE_VERSION("1.0"); MODULE_ALIAS("platform:pmic8xxx_keypad"); MODULE_AUTHOR("Trilok Soni <*****@*****.**>");
static int __devinit pmic8xxx_pwrkey_probe(struct platform_device *pdev) { struct input_dev *pwr; int key_release_irq = platform_get_irq(pdev, 0); int key_press_irq = platform_get_irq(pdev, 1); int err; unsigned int delay; u8 pon_cntl; struct pmic8xxx_pwrkey *pwrkey; const struct pm8xxx_pwrkey_platform_data *pdata = dev_get_platdata(&pdev->dev); if (!pdata) { dev_err(&pdev->dev, "power key platform data not supplied\n"); return -EINVAL; } /* Valid range of pwr key trigger delay is 1/64 sec to 2 seconds. */ if (pdata->kpd_trigger_delay_us > USEC_PER_SEC * 2 || pdata->kpd_trigger_delay_us < USEC_PER_SEC / 64) { dev_err(&pdev->dev, "invalid power key trigger delay\n"); return -EINVAL; } pwrkey = kzalloc(sizeof(*pwrkey), GFP_KERNEL); if (!pwrkey) return -ENOMEM; pwrkey->pdata = pdata; pwr = input_allocate_device(); if (!pwr) { dev_dbg(&pdev->dev, "Can't allocate power button\n"); err = -ENOMEM; goto free_pwrkey; } input_set_capability(pwr, EV_KEY, KEY_POWER); pwr->name = "pmic8xxx_pwrkey"; pwr->phys = "pmic8xxx_pwrkey/input0"; pwr->dev.parent = &pdev->dev; delay = (pdata->kpd_trigger_delay_us << 6) / USEC_PER_SEC; delay = ilog2(delay); err = pm8xxx_readb(pdev->dev.parent, PON_CNTL_1, &pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed reading PON_CNTL_1 err=%d\n", err); goto free_input_dev; } pon_cntl &= ~PON_CNTL_TRIG_DELAY_MASK; pon_cntl |= (delay & PON_CNTL_TRIG_DELAY_MASK); if (pdata->pull_up) pon_cntl |= PON_CNTL_PULL_UP; else pon_cntl &= ~PON_CNTL_PULL_UP; err = pm8xxx_writeb(pdev->dev.parent, PON_CNTL_1, pon_cntl); if (err < 0) { dev_err(&pdev->dev, "failed writing PON_CNTL_1 err=%d\n", err); goto free_input_dev; } err = input_register_device(pwr); if (err) { dev_dbg(&pdev->dev, "Can't register power key: %d\n", err); goto free_input_dev; } pwrkey->key_press_irq = key_press_irq; pwrkey->key_release_irq = key_release_irq; pwrkey->pwr = pwr; platform_set_drvdata(pdev, pwrkey); /* check power key status during boot */ err = pm8xxx_read_irq_stat(pdev->dev.parent, key_press_irq); if (err < 0) { dev_err(&pdev->dev, "reading irq status failed\n"); goto unreg_input_dev; } pwrkey->press = !!err; if (pwrkey->press) { input_report_key(pwrkey->pwr, KEY_POWER, 1); input_sync(pwrkey->pwr); } #ifdef CONFIG_TOUCHSCREEN_SWEEP2WAKE sweep2wake_setdev(pwr); printk(KERN_INFO "[sweep2wake]: set device %s\n", pwr->name); #endif err = request_any_context_irq(key_press_irq, pwrkey_press_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_press_irq, err); goto unreg_input_dev; } err = request_any_context_irq(key_release_irq, pwrkey_release_irq, IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_release", pwrkey); if (err < 0) { dev_dbg(&pdev->dev, "Can't get %d IRQ for pwrkey: %d\n", key_release_irq, err); goto free_press_irq; } device_init_wakeup(&pdev->dev, pdata->wakeup); return 0; free_press_irq: free_irq(key_press_irq, NULL); unreg_input_dev: platform_set_drvdata(pdev, NULL); input_unregister_device(pwr); pwr = NULL; free_input_dev: input_free_device(pwr); free_pwrkey: kfree(pwrkey); return err; }
static int __devinit fsa9485_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct fsa9485_usbsw *usbsw; int ret = 0; struct input_dev *input; struct device *switch_dev; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; input = input_allocate_device(); usbsw = kzalloc(sizeof(struct fsa9485_usbsw), GFP_KERNEL); if (!usbsw || !input) { dev_err(&client->dev, "failed to allocate driver data\n"); kfree(usbsw); return -ENOMEM; } usbsw->input = input; input->name = client->name; input->phys = "deskdock-key/input0"; input->dev.parent = &client->dev; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0001; /* Enable auto repeat feature of Linux input subsystem */ __set_bit(EV_REP, input->evbit); input_set_capability(input, EV_KEY, KEY_VOLUMEUP); input_set_capability(input, EV_KEY, KEY_VOLUMEDOWN); input_set_capability(input, EV_KEY, KEY_PLAYPAUSE); input_set_capability(input, EV_KEY, KEY_PREVIOUSSONG); input_set_capability(input, EV_KEY, KEY_NEXTSONG); ret = input_register_device(input); if (ret) { dev_err(&client->dev, "input_register_device %s: err %d\n", __func__, ret); input_free_device(input); kfree(usbsw); return ret; } usbsw->client = client; usbsw->pdata = client->dev.platform_data; if (!usbsw->pdata) goto fail1; i2c_set_clientdata(client, usbsw); mutex_init(&usbsw->mutex); local_usbsw = usbsw; if (usbsw->pdata->cfg_gpio) usbsw->pdata->cfg_gpio(); fsa9485_reg_init(usbsw); uart_connecting = 0; ret = sysfs_create_group(&client->dev.kobj, &fsa9485_group); if (ret) { dev_err(&client->dev, "failed to create fsa9485 attribute group\n"); goto fail2; } /* make sysfs node /sys/class/sec/switch/usb_state */ switch_dev = device_create(sec_class, NULL, 0, NULL, "switch"); if (IS_ERR(switch_dev)) { pr_err("[FSA9485] Failed to create device (switch_dev)!\n"); ret = PTR_ERR(switch_dev); goto fail2; } ret = device_create_file(switch_dev, &dev_attr_usb_state); if (ret < 0) { pr_err("[FSA9485] Failed to create file (usb_state)!\n"); goto err_create_file_state; } ret = device_create_file(switch_dev, &dev_attr_adc); if (ret < 0) { pr_err("[FSA9485] Failed to create file (adc)!\n"); goto err_create_file_adc; } ret = device_create_file(switch_dev, &dev_attr_reset_switch); if (ret < 0) { pr_err("[FSA9485] Failed to create file (reset_switch)!\n"); goto err_create_file_reset_switch; } dev_set_drvdata(switch_dev, usbsw); /* fsa9485 dock init*/ if (usbsw->pdata->dock_init) usbsw->pdata->dock_init(); /* fsa9485 reset */ if (usbsw->pdata->reset_cb) usbsw->pdata->reset_cb(); /* set fsa9485 init flag. */ if (usbsw->pdata->set_init_flag) usbsw->pdata->set_init_flag(); /* initial cable detection */ INIT_DELAYED_WORK(&usbsw->init_work, fsa9485_init_detect); schedule_delayed_work(&usbsw->init_work, msecs_to_jiffies(2700)); return 0; err_create_file_reset_switch: device_remove_file(switch_dev, &dev_attr_reset_switch); err_create_file_adc: device_remove_file(switch_dev, &dev_attr_adc); err_create_file_state: device_remove_file(switch_dev, &dev_attr_usb_state); fail2: if (client->irq) free_irq(client->irq, usbsw); fail1: input_unregister_device(input); mutex_destroy(&usbsw->mutex); kfree(usbsw); return ret; }
static int __devinit gpio_keys_probe(struct platform_device *pdev) { struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct gpio_keys_drvdata *ddata; struct device *dev = &pdev->dev; struct input_dev *input; int i, error; int wakeup = 0; ddata = kzalloc(sizeof(struct gpio_keys_drvdata) + pdata->nbuttons * sizeof(struct gpio_button_data), GFP_KERNEL); input = input_allocate_device(); if (!ddata || !input) { dev_err(dev, "failed to allocate state\n"); error = -ENOMEM; goto fail1; } #if defined(FEATURE_TW_TOUCH_AUTO_CAL) check_touch_cal=0; #endif ddata->input = input; ddata->n_buttons = pdata->nbuttons; ddata->enable = pdata->enable; ddata->disable = pdata->disable; mutex_init(&ddata->disable_lock); platform_set_drvdata(pdev, ddata); input_set_drvdata(input, ddata); input->name = pdata->name ? : pdev->name; input->phys = "gpio-keys/input0"; input->dev.parent = &pdev->dev; input->open = gpio_keys_open; input->close = gpio_keys_close; input->id.bustype = BUS_HOST; input->id.vendor = 0x0001; input->id.product = 0x0001; input->id.version = 0x0100; /* Enable auto repeat feature of Linux input subsystem */ if (pdata->rep) __set_bit(EV_REP, input->evbit); for (i = 0; i < pdata->nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons[i]; struct gpio_button_data *bdata = &ddata->data[i]; unsigned int type = button->type ?: EV_KEY; bdata->input = input; bdata->button = button; error = gpio_keys_setup_key(pdev, bdata, button); if (error) goto fail2; if (button->wakeup) wakeup = 1; input_set_capability(input, type, button->code); } error = sysfs_create_group(&pdev->dev.kobj, &gpio_keys_attr_group); if (error) { dev_err(dev, "Unable to export keys/switches, error: %d\n", error); goto fail2; } error = input_register_device(input); if (error) { dev_err(dev, "Unable to register input device, error: %d\n", error); goto fail3; } /* get current state of buttons */ for (i = 0; i < pdata->nbuttons; i++) gpio_keys_report_event(&ddata->data[i]); input_sync(input); device_init_wakeup(&pdev->dev, wakeup); return 0; fail3: sysfs_remove_group(&pdev->dev.kobj, &gpio_keys_attr_group); fail2: while (--i >= 0) { free_irq(gpio_to_irq(pdata->buttons[i].gpio), &ddata->data[i]); if (ddata->data[i].timer_debounce) del_timer_sync(&ddata->data[i].timer); cancel_work_sync(&ddata->data[i].work); gpio_free(pdata->buttons[i].gpio); } platform_set_drvdata(pdev, NULL); fail1: input_free_device(input); kfree(ddata); return error; }
static int cypress_touchkey_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; struct input_dev *input_dev; struct cypress_touchkey_devdata *devdata; u8 data[3]; int err; int cnt; #if defined(TOUCH_UPDATE) int ret; int retry = 10; #endif if (!dev->platform_data) { dev_err(dev, "%s: Platform data is NULL\n", __func__); return -EINVAL; } devdata = kzalloc(sizeof(*devdata), GFP_KERNEL); if (devdata == NULL) { dev_err(dev, "%s: failed to create our state\n", __func__); return -ENODEV; } devdata->client = client; i2c_set_clientdata(client, devdata); devdata->pdata = client->dev.platform_data; if (!devdata->pdata->keycode) { dev_err(dev, "%s: Invalid platform data\n", __func__); err = -EINVAL; goto err_null_keycodes; } strlcpy(devdata->client->name, DEVICE_NAME, I2C_NAME_SIZE); input_dev = input_allocate_device(); if (!input_dev) { err = -ENOMEM; goto err_input_alloc_dev; } devdata->input_dev = input_dev; dev_set_drvdata(&input_dev->dev, devdata); input_dev->name = DEVICE_NAME; input_dev->id.bustype = BUS_HOST; for (cnt = 0; cnt < devdata->pdata->keycode_cnt; cnt++) input_set_capability(input_dev, EV_KEY, devdata->pdata->keycode[cnt]); err = input_register_device(input_dev); if (err) goto err_input_reg_dev; devdata->is_powering_on = true; devdata->pdata->touchkey_onoff(TOUCHKEY_ON); err = i2c_master_recv(client, data, sizeof(data)); if (err < sizeof(data)) { if (err >= 0) err = -EIO; dev_err(dev, "%s: error reading hardware version\n", __func__); goto err_read; } dev_info(dev, "%s: hardware rev1 = %#02x, rev2 = %#02x\n", __func__, data[1], data[2]); devdata->backlight_on = BACKLIGHT_ON; devdata->backlight_off = BACKLIGHT_OFF; devdata->has_legacy_keycode = 1; #if 0 err = i2c_touchkey_write_byte(devdata, devdata->backlight_on); if (err) { dev_err(dev, "%s: touch keypad backlight on failed\n", __func__); goto err_backlight_on; } #endif if (request_threaded_irq(client->irq, touchkey_interrupt_handler, touchkey_interrupt_thread, IRQF_TRIGGER_FALLING, DEVICE_NAME, devdata)) { dev_err(dev, "%s: Can't allocate irq.\n", __func__); goto err_req_irq; } #ifdef CONFIG_HAS_EARLYSUSPEND devdata->early_suspend.suspend = cypress_touchkey_early_suspend; devdata->early_suspend.resume = cypress_touchkey_early_resume; #endif register_early_suspend(&devdata->early_suspend); devdata->is_powering_on = false; #if defined(TOUCH_UPDATE) ret = misc_register(&touchkey_update_device); if (ret) { printk("%s misc_register fail\n", __FUNCTION__); goto err_misc_reg; } dev_set_drvdata(touchkey_update_device.this_device, devdata); if (device_create_file (touchkey_update_device.this_device, &dev_attr_touch_version) < 0) { printk("%s device_create_file fail dev_attr_touch_version\n", __FUNCTION__); pr_err("Failed to create device file(%s)!\n", dev_attr_touch_version.attr.name); } if (device_create_file (touchkey_update_device.this_device, &dev_attr_touch_update) < 0) { printk("%s device_create_file fail dev_attr_touch_update\n", __FUNCTION__); pr_err("Failed to create device file(%s)!\n", dev_attr_touch_update.attr.name); } if (device_create_file (touchkey_update_device.this_device, &dev_attr_brightness) < 0) { printk("%s device_create_file fail dev_attr_touch_update\n", __FUNCTION__); pr_err("Failed to create device file(%s)!\n", dev_attr_brightness.attr.name); } if (device_create_file (touchkey_update_device.this_device, &dev_attr_enable_disable) < 0) { printk("%s device_create_file fail dev_attr_touch_update\n", __FUNCTION__); pr_err("Failed to create device file(%s)!\n", dev_attr_enable_disable.attr.name); } touchkey_wq = create_singlethread_workqueue(DEVICE_NAME); if (!touchkey_wq) goto err_create_wq; while (retry--) { if (get_touchkey_firmware(data) == 0) //melfas need delay for multiple read break; } printk("%s F/W version: 0x%x, Module version:0x%x\n", __FUNCTION__, data[1], data[2]); #endif return 0; err_create_wq: #if defined(TOUCH_UPDATE) misc_deregister(&touchkey_update_device); #endif err_misc_reg: err_req_irq: err_backlight_on: err_read: devdata->pdata->touchkey_onoff(TOUCHKEY_OFF); input_unregister_device(input_dev); goto err_input_alloc_dev; err_input_reg_dev: input_free_device(input_dev); err_input_alloc_dev: err_null_keycodes: kfree(devdata); return err; }
static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { struct mt_device *td = hid_get_drvdata(hdev); struct mt_class *cls = &td->mtclass; int code; /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application == HID_DG_TOUCHSCREEN) set_bit(INPUT_PROP_DIRECT, hi->input->propbit); else if (field->application != HID_DG_TOUCHPAD) return 0; /* In case of an indirect device (touchpad), we need to add * specific BTN_TOOL_* to be handled by the synaptics xorg * driver. * We also consider that touchscreens providing buttons are touchpads. */ if (field->application == HID_DG_TOUCHPAD || (usage->hid & HID_USAGE_PAGE) == HID_UP_BUTTON || cls->is_indirect) { set_bit(INPUT_PROP_POINTER, hi->input->propbit); set_bit(BTN_TOOL_FINGER, hi->input->keybit); set_bit(BTN_TOOL_DOUBLETAP, hi->input->keybit); set_bit(BTN_TOOL_TRIPLETAP, hi->input->keybit); set_bit(BTN_TOOL_QUADTAP, hi->input->keybit); } /* eGalax devices provide a Digitizer.Stylus input which overrides * the correct Digitizers.Finger X/Y ranges. * Let's just ignore this input. */ if (field->physical == HID_DG_STYLUS) return -1; /* Only map fields from TouchScreen or TouchPad collections. * We need to ignore fields that belong to other collections * such as Mouse that might have the same GenericDesktop usages. */ if (field->application == HID_DG_TOUCHSCREEN) set_bit(INPUT_PROP_DIRECT, hi->input->propbit); else if (field->application == HID_DG_TOUCHPAD) set_bit(INPUT_PROP_POINTER, hi->input->propbit); else return 0; switch (usage->hid & HID_USAGE_PAGE) { case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_X); set_abs(hi->input, ABS_MT_POSITION_X, field, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_X, field, cls->sn_move); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_GD_Y: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_POSITION_Y); set_abs(hi->input, ABS_MT_POSITION_Y, field, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_Y, field, cls->sn_move); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; } return 0; case HID_UP_DIGITIZER: switch (usage->hid) { case HID_DG_INRANGE: mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONFIDENCE: mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_TIPSWITCH: hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONTACTID: if (!td->maxcontacts) td->maxcontacts = MT_DEFAULT_MAXCONTACT; input_mt_init_slots(hi->input, td->maxcontacts); mt_store_field(usage, td, hi); td->last_field_index = field->index; td->touches_by_report++; return 1; case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR); set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, cls->sn_width); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MINOR); set_abs(hi->input, ABS_MT_TOUCH_MINOR, field, cls->sn_height); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 0, 1, 0, 0); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_TIPPRESSURE: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_PRESSURE); set_abs(hi->input, ABS_MT_PRESSURE, field, cls->sn_pressure); /* touchscreen emulation */ set_abs(hi->input, ABS_PRESSURE, field, cls->sn_pressure); mt_store_field(usage, td, hi); td->last_field_index = field->index; return 1; case HID_DG_CONTACTCOUNT: td->last_field_index = field->index; return 1; case HID_DG_CONTACTMAX: /* we don't set td->last_slot_field as contactcount and * contact max are global to the report */ td->last_field_index = field->index; return -1; } case HID_DG_TOUCH: /* Legacy devices use TIPSWITCH and not TOUCH. * Let's just ignore this field. */ return -1; /* let hid-input decide for the others */ return 0; case HID_UP_BUTTON: code = BTN_MOUSE + ((usage->hid - 1) & HID_USAGE); hid_map_usage(hi, usage, bit, max, EV_KEY, code); input_set_capability(hi->input, EV_KEY, code); return 1; case 0xff000000: /* we do not want to map these: no input-oriented meaning */ return -1; } return 0; }