static void g15_led_bl_set(struct led_classdev *led_cdev, enum led_brightness value) { struct device *dev; struct hid_device *hdev; struct g15_data *g15data; /* Get the device associated with the led */ dev = led_cdev->dev->parent; /* Get the hid associated with the device */ hdev = container_of(dev, struct hid_device, dev); /* Get the underlying data value */ g15data = hid_get_g15data(hdev); if (led_cdev == g15data->led_cdev[G15_LED_BL_KEYS]) { if (value > 2) value = 2; g15data->keys_bl = value; g15_msg_send(hdev, 0x01, g15data->keys_bl, 0); } else if (led_cdev == g15data->led_cdev[G15_LED_BL_SCREEN]) { if (value > 2) value = 2; g15data->screen_bl = value<<4; g15_msg_send(hdev, 0x02, g15data->screen_bl, 0); } else if (led_cdev == g15data->led_cdev[G15_LED_BL_CONTRAST]) { if (value > 63) value = 63; g15data->screen_contrast = value; g15_msg_send(hdev, 32, 129, g15data->screen_contrast); } else dev_info(dev, G15_NAME " error retrieving LED brightness\n"); }
static enum led_brightness g15_led_bl_get(struct led_classdev *led_cdev) { struct device *dev; struct hid_device *hdev; struct g15_data *g15data; /* Get the device associated with the led */ dev = led_cdev->dev->parent; /* Get the hid associated with the device */ hdev = container_of(dev, struct hid_device, dev); /* Get the underlying data value */ g15data = hid_get_g15data(hdev); if (led_cdev == g15data->led_cdev[G15_LED_BL_KEYS]) return g15data->keys_bl; else if (led_cdev == g15data->led_cdev[G15_LED_BL_SCREEN]) return g15data->screen_bl; else if (led_cdev == g15data->led_cdev[G15_LED_BL_CONTRAST]) return g15data->screen_contrast; else dev_info(dev, G15_NAME " error retrieving LED brightness\n"); return LED_OFF; }
static void g15_led_set(struct led_classdev *led_cdev, enum led_brightness value, int led_num) { struct device *dev; struct hid_device *hdev; struct g15_data *g15data; u8 mask; /* Get the device associated with the led */ dev = led_cdev->dev->parent; /* Get the hid associated with the device */ hdev = container_of(dev, struct hid_device, dev); /* Get the underlying data value */ g15data = hid_get_g15data(hdev); mask = 0x01<<led_num; if (value) g15data->led |= mask; else g15data->led &= ~mask; g15_msg_send(hdev, 0x04, ~(g15data->led), 0); }
static enum led_brightness g15_led_brightness_get(struct led_classdev *led_cdev) { struct device *dev; struct hid_device *hdev; struct g15_data *g15data; int value = 0; /* Get the device associated with the led */ dev = led_cdev->dev->parent; /* Get the hid associated with the device */ hdev = container_of(dev, struct hid_device, dev); /* Get the underlying data value */ g15data = hid_get_g15data(hdev); if (led_cdev == g15data->led_cdev[G15_LED_M1]) value = g15data->led & 0x01; else if (led_cdev == g15data->led_cdev[G15_LED_M2]) value = g15data->led & 0x02; else if (led_cdev == g15data->led_cdev[G15_LED_M3]) value = g15data->led & 0x04; else if (led_cdev == g15data->led_cdev[G15_LED_MR]) value = g15data->led & 0x08; else dev_info(dev, G15_NAME " error retrieving LED brightness\n"); if (value) return LED_FULL; return LED_OFF; }
static void g15v2_led_bl_send(struct hid_device *hdev) { struct g15v2_data *g15data = hid_get_g15data(hdev); g15v2_led_send(hdev, 0x01, g15data->backlight, 0); g15v2_led_send(hdev, 0x02, g15data->screen_bl, 0); g15v2_led_send(hdev, 0x20, 0x81, g15data->screen_contrast); }
static void g15_msg_send(struct hid_device *hdev, u8 msg, u8 value1, u8 value2) { struct g15_data *g15data = hid_get_g15data(hdev); g15data->led_report->field[0]->value[0] = msg; g15data->led_report->field[0]->value[1] = value1; g15data->led_report->field[0]->value[2] = value2; usbhid_submit_report(hdev, g15data->led_report, USB_DIR_OUT); }
static void g15v2_led_send(struct hid_device *hdev, u8 msg, u8 value1, u8 value2) { struct g15v2_data *g15data = hid_get_g15data(hdev); g15data->led_report->field[0]->value[0] = msg; g15data->led_report->field[0]->value[1] = value1; g15data->led_report->field[0]->value[2] = value2; hid_hw_request(hdev, g15data->led_report, HID_REQ_SET_REPORT); }
static ssize_t g15_set_keymap_switching(struct hid_device *hdev, unsigned k) { struct g15_data *data = hid_get_g15data(hdev); data->keymap_switching = k; if (data->keymap_switching) { data->led = 1 << data->curkeymap; g15_msg_send(hdev, 4, ~data->led, 0); } return 0; }
static ssize_t g15_set_keymap_index(struct hid_device *hdev, unsigned k) { int scancode; int offset_old; int offset_new; int keycode_old; int keycode_new; struct g15_data *data = hid_get_g15data(hdev); struct input_dev *idev = data->input_dev; if (k > 2) return -EINVAL; /* * Release all the pressed keys unless the new keymap has the same key * in the same scancode position. * * Also, clear the scancode state unless the new keymap has the same * key in the same scancode position. * * This allows a keycode mapped to the same scancode in two different * keymaps to remain pressed without a key up code when the keymap is * switched. */ offset_old = G15_KEYS * data->curkeymap; offset_new = G15_KEYS * k; for (scancode = 0; scancode < G15_KEYS; scancode++) { keycode_old = data->keycode[offset_old+scancode]; keycode_new = data->keycode[offset_new+scancode]; if (keycode_old != keycode_new) { if (keycode_old != KEY_RESERVED) input_report_key(idev, keycode_old, 0); data->scancode_state[scancode] = 0; } } data->curkeymap = k; if (data->keymap_switching) { data->led = 1 << k; g15_msg_send(hdev, 4, ~data->led, 0); } return 0; }
static void g15_feature_report_4_send(struct hid_device *hdev, int which) { struct g15_data *g15data = hid_get_g15data(hdev); if (which == G15_REPORT_4_INIT) { g15data->feature_report_4->field[0]->value[0] = 0x02; g15data->feature_report_4->field[0]->value[1] = 0x00; g15data->feature_report_4->field[0]->value[2] = 0x00; g15data->feature_report_4->field[0]->value[3] = 0x00; } else if (which == G15_REPORT_4_FINALIZE) { g15data->feature_report_4->field[0]->value[0] = 0x02; g15data->feature_report_4->field[0]->value[1] = 0x80; g15data->feature_report_4->field[0]->value[2] = 0x00; g15data->feature_report_4->field[0]->value[3] = 0xFF; } else { return; } usbhid_submit_report(hdev, g15data->feature_report_4, USB_DIR_OUT); }
static void g15v2_feature_report_4_send(struct hid_device *hdev, int which) { struct g15v2_data *gdata = hid_get_g15data(hdev); if (which == G15V2_REPORT_4_INIT) { gdata->feature_report_4->field[0]->value[0] = 0x02; gdata->feature_report_4->field[0]->value[1] = 0x00; gdata->feature_report_4->field[0]->value[2] = 0x00; gdata->feature_report_4->field[0]->value[3] = 0x00; } else if (which == G15V2_REPORT_4_FINALIZE) { gdata->feature_report_4->field[0]->value[0] = 0x02; gdata->feature_report_4->field[0]->value[1] = 0x80; gdata->feature_report_4->field[0]->value[2] = 0x00; gdata->feature_report_4->field[0]->value[3] = 0xFF; } else { return; } hid_hw_request(hdev, gdata->feature_report_4, HID_REQ_SET_REPORT); }
static void g15v2_led_mbtns_send(struct hid_device *hdev) { struct g15v2_data *g15data = hid_get_g15data(hdev); g15v2_led_send(hdev, 0x04, ~(g15data->led_mbtns), 0); }
static ssize_t g15_keymap_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct hid_device *hdev; int scanned; int consumed; int scancd; int keycd; int error; int set = 0; int gkey; int index; int good; struct g15_data *data; /* Get the hid associated with the device */ hdev = container_of(dev, struct hid_device, dev); /* If we have an invalid pointer we'll return ENODATA */ if (hdev == NULL || &(hdev->dev) != dev) return -ENODATA; /* Now, let's get the data structure */ data = hid_get_g15data(hdev); do { good = 0; /* Look for scancode keycode pair in hex */ scanned = sscanf(buf, "%x %x%n", &scancd, &keycd, &consumed); if (scanned == 2) { buf += consumed; error = g15_input_setkeycode(data->input_dev, scancd, keycd); if (error) goto err_input_setkeycode; set++; good = 1; } else { /* * Look for Gkey keycode pair and assign to current * keymap */ scanned = sscanf(buf, "G%d %x%n", &gkey, &keycd, &consumed); if (scanned == 2 && gkey > 0 && gkey <= G15_KEYS) { buf += consumed; scancd = data->curkeymap * G15_KEYS + gkey - 1; error = g15_input_setkeycode(data->input_dev, scancd, keycd); if (error) goto err_input_setkeycode; set++; good = 1; } else { /* * Look for Gkey-index keycode pair and assign * to indexed keymap */ scanned = sscanf(buf, "G%d-%d %x%n", &gkey, &index, &keycd, &consumed); if (scanned == 3 && gkey > 0 && gkey <= G15_KEYS && index >= 0 && index <= 2) { buf += consumed; scancd = index * G15_KEYS + gkey - 1; error = g15_input_setkeycode(data->input_dev, scancd, keycd); if (error) goto err_input_setkeycode; set++; good = 1; } } } } while (good); if (set == 0) { dev_warn(dev, G15_NAME " unrecognized keycode input: %s", buf); return -1; } return count; err_input_setkeycode: dev_warn(dev, G15_NAME " error setting scancode %d to keycode %d\n", scancd, keycd); return error; }
static int g15_input_get_keycode(struct input_dev * dev, unsigned int scancode, unsigned int * keycode) { int retval; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) struct input_keymap_entry ke = { .flags = 0, .len = sizeof(scancode), .index = scancode, .scancode = { scancode }, }; retval = input_get_keycode(dev, &ke); *keycode = ke.keycode; #else retval = input_get_keycode(dev, scancode, keycode); #endif return retval; } static void g15_msg_send(struct hid_device *hdev, u8 msg, u8 value1, u8 value2) { struct g15_data *data = hid_get_g15data(hdev); data->led_report->field[0]->value[0] = msg; data->led_report->field[0]->value[1] = value1; data->led_report->field[0]->value[2] = value2; usbhid_submit_report(hdev, data->led_report, USB_DIR_OUT); } static void g15_led_set(struct led_classdev *led_cdev, enum led_brightness value, int led_num) { struct device *dev; struct hid_device *hdev; struct g15_data *data; u8 mask; /* Get the device associated with the led */ dev = led_cdev->dev->parent; /* Get the hid associated with the device */ hdev = container_of(dev, struct hid_device, dev); /* Get the underlying data value */ data = hid_get_g15data(hdev); mask = 0x01<<led_num; if (value) data->led |= mask; else data->led &= ~mask; g15_msg_send(hdev, 0x04, ~(data->led), 0); } static void g15_led_m1_brightness_set(struct led_classdev *led_cdev, enum led_brightness value) { g15_led_set(led_cdev, value, G15_LED_M1); }