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 int g15_raw_event(struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size) { /* * On initialization receive a 258 byte message with * data = 6 0 255 255 255 255 255 255 255 255 ... */ unsigned long irq_flags; struct gcommon_data *gdata = dev_get_gdata(&hdev->dev); struct g15_data *g15data = gdata->data; spin_lock_irqsave(&gdata->lock, irq_flags); if (unlikely(g15data->need_reset)) { g15_msg_send(hdev, 4, ~g15data->led, 0); g15data->need_reset = 0; spin_unlock_irqrestore(&gdata->lock, irq_flags); return 1; } if (unlikely(g15data->ready_stages != G15_READY_STAGE_3)) { switch (report->id) { case 6: if (!(g15data->ready_stages & G15_READY_SUBSTAGE_1)) g15data->ready_stages |= G15_READY_SUBSTAGE_1; else if (g15data->ready_stages & G15_READY_SUBSTAGE_4 && !(g15data->ready_stages & G15_READY_SUBSTAGE_5) ) g15data->ready_stages |= G15_READY_SUBSTAGE_5; else if (g15data->ready_stages & G15_READY_SUBSTAGE_6 && raw_data[1] >= 0x80) g15data->ready_stages |= G15_READY_SUBSTAGE_7; break; case 1: if (!(g15data->ready_stages & G15_READY_SUBSTAGE_2)) g15data->ready_stages |= G15_READY_SUBSTAGE_2; else g15data->ready_stages |= G15_READY_SUBSTAGE_3; break; } if (g15data->ready_stages == G15_READY_STAGE_1 || g15data->ready_stages == G15_READY_STAGE_2 || g15data->ready_stages == G15_READY_STAGE_3) complete_all(&g15data->ready); spin_unlock_irqrestore(&gdata->lock, irq_flags); return 1; } spin_unlock_irqrestore(&gdata->lock, irq_flags); if (likely(report->id == 2)) { g15_raw_event_process_input(hdev, gdata, raw_data); return 1; } return 0; }
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); }
/* change leds when the keymap was changed */ static void g15_notify_keymap_switched(struct gcommon_data * gdata, unsigned int index) { struct g15_data * g15data = gdata->data; g15data->led = 1 << index; g15_msg_send(gdata->hdev, 4, ~g15data->led, 0); }
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 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); }