static void g19_led_set(struct led_classdev *led_cdev, enum led_brightness value, int led_num) { struct device *dev; struct hid_device *hdev; struct g19_data *g19data; 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 */ g19data = hid_get_g19data(hdev); mask = 0x80>>led_num; if (value) g19data->led |= mask; else g19data->led &= ~mask; g19_led_send(hdev); }
static void g19_led_bl_brightness_set(struct led_classdev *led_cdev, enum led_brightness value) { struct device *dev; struct hid_device *hdev; struct g19_data *data; /* 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_g19data(hdev); if (led_cdev == data->led_cdev[G19_LED_BL_R]) data->rgb[0] = value; else if (led_cdev == data->led_cdev[G19_LED_BL_G]) data->rgb[1] = value; else if (led_cdev == data->led_cdev[G19_LED_BL_B]) data->rgb[2] = value; g19_rgb_send(hdev); }
static enum led_brightness g19_led_bl_brightness_get(struct led_classdev *led_cdev) { struct device *dev; struct hid_device *hdev; struct g19_data *data; /* 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_g19data(hdev); if (led_cdev == data->led_cdev[G19_LED_BL_R]) return data->rgb[0]; else if (led_cdev == data->led_cdev[G19_LED_BL_G]) return data->rgb[1]; else if (led_cdev == data->led_cdev[G19_LED_BL_B]) return data->rgb[2]; else dev_info(dev, G19_NAME " error retrieving LED brightness\n"); return LED_OFF; }
static int g19_ep1_read(struct hid_device *hdev) { struct usb_interface *intf; struct usb_device *usb_dev; struct g19_data *data = hid_get_g19data(hdev); struct usb_host_endpoint *ep; unsigned int pipe; int retval = 0; /* Get the usb device to send the image on */ intf = to_usb_interface(hdev->dev.parent); usb_dev = interface_to_usbdev(intf); pipe = usb_rcvintpipe(usb_dev, 0x01); ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)[usb_pipeendpoint(pipe)]; if (unlikely(!ep)) return -EINVAL; usb_fill_int_urb(data->ep1_urb, usb_dev, pipe, data->ep1keys, 2, g19_ep1_urb_completion, NULL, 10); data->ep1_urb->context = hdev; data->ep1_urb->actual_length = 0; retval = usb_submit_urb(data->ep1_urb, GFP_KERNEL); return retval; }
static void g19_led_screen_bl_send(struct hid_device *hdev) { struct usb_interface *intf; struct usb_device *usb_dev; struct g19_data *g19data = hid_get_g19data(hdev); unsigned int pipe; int i = 0; unsigned char cp[9]; cp[0] = g19data->screen_bl; cp[1] = 0xe2; cp[2] = 0x12; cp[3] = 0x00; cp[4] = 0x8c; cp[5] = 0x11; cp[6] = 0x00; cp[7] = 0x10; cp[8] = 0x00; intf = to_usb_interface(hdev->dev.parent); usb_dev = interface_to_usbdev(intf); pipe = usb_sndctrlpipe(usb_dev, 0x00); i = usb_control_msg(usb_dev, pipe, 0x0a, USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, cp, sizeof(cp), 1 * HZ); if (i < 0) { dev_warn(&hdev->dev, G19_NAME " error setting LCD backlight level %d\n", i); } }
static void g19_feature_report_4_send(struct hid_device *hdev, int which) { struct g19_data *g19data = hid_get_g19data(hdev); if (which == G19_REPORT_4_INIT) { g19data->feature_report_4->field[0]->value[0] = 0x02; g19data->feature_report_4->field[0]->value[1] = 0x00; g19data->feature_report_4->field[0]->value[2] = 0x00; g19data->feature_report_4->field[0]->value[3] = 0x00; } else if (which == G19_REPORT_4_FINALIZE) { g19data->feature_report_4->field[0]->value[0] = 0x02; g19data->feature_report_4->field[0]->value[1] = 0x80; g19data->feature_report_4->field[0]->value[2] = 0x00; g19data->feature_report_4->field[0]->value[3] = 0xFF; } else { return; } #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) hid_hw_request(hdev, g19data->feature_report_4, HID_REQ_SET_REPORT); #else usbhid_submit_report(hdev, g19data->feature_report_4, USB_DIR_OUT); #endif }
static enum led_brightness g19_led_brightness_get(struct led_classdev *led_cdev) { struct device *dev; struct hid_device *hdev; struct g19_data *data; 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 */ data = hid_get_g19data(hdev); if (led_cdev == data->led_cdev[G19_LED_M1]) value = data->led & 0x80; else if (led_cdev == data->led_cdev[G19_LED_M2]) value = data->led & 0x40; else if (led_cdev == data->led_cdev[G19_LED_M3]) value = data->led & 0x20; else if (led_cdev == data->led_cdev[G19_LED_MR]) value = data->led & 0x10; else dev_info(dev, G19_NAME " error retrieving LED brightness\n"); if (value) return LED_FULL; return LED_OFF; }
static void g19_led_mbtns_send(struct hid_device *hdev) { struct g19_data *g19data = hid_get_g19data(hdev); g19data->led_report->field[0]->value[0] = g19data->led_mbtns & 0xFF; hid_hw_request(hdev, g19data->led_report, HID_REQ_SET_REPORT); }
static void g19_post_reset_start(struct hid_device *hdev) { unsigned long irq_flags; struct g19_data *data = hid_get_g19data(hdev); spin_lock_irqsave(&data->lock, irq_flags); data->need_reset = 1; spin_unlock_irqrestore(&data->lock, irq_flags); }
static void g19_led_bl_send(struct hid_device *hdev) { struct g19_data *g19data = hid_get_g19data(hdev); struct hid_field *field0 = g19data->backlight_report->field[0]; field0->value[0] = g19data->backlight_rgb[0]; field0->value[1] = g19data->backlight_rgb[1]; field0->value[2] = g19data->backlight_rgb[2]; hid_hw_request(hdev, g19data->backlight_report, HID_REQ_SET_REPORT); }
static ssize_t g19_set_keymap_switching(struct hid_device *hdev, unsigned k) { struct g19_data *data = hid_get_g19data(hdev); data->keymap_switching = k; if (data->keymap_switching) { data->led = 1 << data->curkeymap; g19_led_send(hdev); } return 0; }
static void g19_led_send(struct hid_device *hdev) { struct g19_data *g19data = hid_get_g19data(hdev); g19data->led_report->field[0]->value[0] = g19data->led&0xFF; #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) hid_hw_request(hdev, g19data->led_report, HID_REQ_SET_REPORT); #else usbhid_submit_report(hdev, g19data->led_report, USB_DIR_OUT); #endif }
/* Unlock the urb so we can reuse it */ static void g19_ep1_urb_completion(struct urb *urb) { /* don't process unlinked or failed urbs */ if (likely(urb->status == 0)) { struct hid_device *hdev = urb->context; struct g19_data *data = hid_get_g19data(hdev); struct input_dev *idev = data->input_dev; int i; for (i = 0; i < 8; i++) g19_handle_key_event(data, idev, 24+i, data->ep1keys[0]&(1<<i)); input_sync(idev); usb_submit_urb(urb, GFP_ATOMIC); } }
static ssize_t g19_set_keymap_index(struct hid_device *hdev, unsigned k) { int scancode; int offset_old; int offset_new; int keycode_old; int keycode_new; struct g19_data *data = hid_get_g19data(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 = G19_KEYS * data->curkeymap; offset_new = G19_KEYS * k; for (scancode = 0; scancode < G19_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; g19_led_send(hdev); } return 0; }
static void g19_feature_report_4_send(struct hid_device *hdev, int which) { struct g19_data *data = hid_get_g19data(hdev); if (which == G19_REPORT_4_INIT) { data->feature_report_4->field[0]->value[0] = 0x02; data->feature_report_4->field[0]->value[1] = 0x00; data->feature_report_4->field[0]->value[2] = 0x00; data->feature_report_4->field[0]->value[3] = 0x00; } else if (which == G19_REPORT_4_FINALIZE) { data->feature_report_4->field[0]->value[0] = 0x02; data->feature_report_4->field[0]->value[1] = 0x80; data->feature_report_4->field[0]->value[2] = 0x00; data->feature_report_4->field[0]->value[3] = 0xFF; } else { return; } usbhid_submit_report(hdev, data->feature_report_4, USB_DIR_OUT); }
static void g19_feature_report_4_send(struct hid_device *hdev, int which) { struct g19_data *g19data = hid_get_g19data(hdev); if (which == G19_REPORT_4_INIT) { g19data->feature_report_4->field[0]->value[0] = 0x02; g19data->feature_report_4->field[0]->value[1] = 0x00; g19data->feature_report_4->field[0]->value[2] = 0x00; g19data->feature_report_4->field[0]->value[3] = 0x00; } else if (which == G19_REPORT_4_FINALIZE) { g19data->feature_report_4->field[0]->value[0] = 0x02; g19data->feature_report_4->field[0]->value[1] = 0x80; g19data->feature_report_4->field[0]->value[2] = 0x00; g19data->feature_report_4->field[0]->value[3] = 0xFF; } else { return; } hid_hw_request(hdev, g19data->feature_report_4, HID_REQ_SET_REPORT); }
static void g19_screen_bl_set(struct led_classdev *led_cdev, enum led_brightness value) { struct device *dev; struct hid_device *hdev; struct g19_data *data; /* Get the device associated with the led */ dev = led_cdev->dev->parent; // TEMPORARY /* Get the hid associated with the device */ hdev = container_of(dev, struct hid_device, dev); /* Get the underlying data value */ data = hid_get_g19data(hdev); // data = [val, 0xe2, 0x12, 0x00, 0x8c, 0x11, 0x00, 0x10, 0x00] // rtype = usb.TYPE_VENDOR | usb.RECIP_INTERFACE // self.__usbDeviceMutex.acquire() // try: // self.__usbDevice.handleIf1.controlMsg(rtype, 0x0a, data, 0x0, 0x0, self.__write_timeout) // finally: // self.__usbDeviceMutex.release() if (led_cdev == data->led_cdev[G19_LED_BL_SCREEN]) { if (value > 100) value = 100; // TEMPORARY data->screen_bl = value; g19_screen_bl_send(hdev); } else dev_info(dev, G19_NAME " error retrieving LED brightness\n"); }
static ssize_t g19_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 g19_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_g19data(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 = g19_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 <= G19_KEYS) { buf += consumed; scancd = data->curkeymap * G19_KEYS + gkey - 1; error = g19_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 <= G19_KEYS && index >= 0 && index <= 2) { buf += consumed; scancd = index * G19_KEYS + gkey - 1; error = g19_input_setkeycode(data->input_dev, scancd, keycd); if (error) goto err_input_setkeycode; set++; good = 1; } } } } while (good); if (set == 0) { dev_warn(dev, G19_NAME " unrecognized keycode input: %s", buf); return -1; } return count; err_input_setkeycode: dev_warn(dev, G19_NAME " error setting scancode %d to keycode %d\n", scancd, keycd); return error; }
static int g19_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 g19_led_send(struct hid_device *hdev) { struct g19_data *data = hid_get_g19data(hdev); data->led_report->field[0]->value[0] = data->led&0xFF; usbhid_submit_report(hdev, data->led_report, USB_DIR_OUT); } static void g19_screen_bl_send(struct hid_device *hdev) { struct usb_interface *intf; struct usb_device *usb_dev; struct g19_data *data = hid_get_g19data(hdev); unsigned int pipe; int i = 0; unsigned char cp[9]; cp[0] = data->screen_bl; cp[1] = 0xe2; cp[2] = 0x12; cp[3] = 0x00; cp[4] = 0x8c; cp[5] = 0x11; cp[6] = 0x00; cp[7] = 0x10; cp[8] = 0x00; intf = to_usb_interface(hdev->dev.parent); usb_dev = interface_to_usbdev(intf); pipe = usb_sndctrlpipe(usb_dev, 0x00); i = usb_control_msg(usb_dev, pipe, 0x0a, USB_TYPE_VENDOR | USB_RECIP_INTERFACE, 0, 0, cp, sizeof(cp), 1 * HZ); if (i < 0) { dev_warn(&hdev->dev, G19_NAME " error setting LCD backlight level %d\n", i); } } static void g19_rgb_send(struct hid_device *hdev) { struct g19_data *data = hid_get_g19data(hdev); data->backlight_report->field[0]->value[0] = data->rgb[0]; data->backlight_report->field[0]->value[1] = data->rgb[1]; data->backlight_report->field[0]->value[2] = data->rgb[2]; usbhid_submit_report(hdev, data->backlight_report, USB_DIR_OUT); } static void g19_led_set(struct led_classdev *led_cdev, enum led_brightness value, int led_num) { struct device *dev; struct hid_device *hdev; struct g19_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_g19data(hdev); mask = 0x80>>led_num; if (value) data->led |= mask; else data->led &= ~mask; g19_led_send(hdev); } static void g19_led_m1_brightness_set(struct led_classdev *led_cdev, enum led_brightness value) { g19_led_set(led_cdev, value, G19_LED_M1); }