Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | /* SPDX-License-Identifier: GPL-2.0-only */ /*************************************************************************** * Copyright (C) 2010-2012 by Bruno Prémont <bonbons@linux-vserver.org> * * * * Based on Logitech G13 driver (v0.4) * * Copyright (C) 2009 by Rick L. Vinyard, Jr. <rvinyard@cs.nmsu.edu> * * * ***************************************************************************/ #define PICOLCD_NAME "PicoLCD (graphic)" /* Report numbers */ #define REPORT_ERROR_CODE 0x10 /* LCD: IN[16] */ #define ERR_SUCCESS 0x00 #define ERR_PARAMETER_MISSING 0x01 #define ERR_DATA_MISSING 0x02 #define ERR_BLOCK_READ_ONLY 0x03 #define ERR_BLOCK_NOT_ERASABLE 0x04 #define ERR_BLOCK_TOO_BIG 0x05 #define ERR_SECTION_OVERFLOW 0x06 #define ERR_INVALID_CMD_LEN 0x07 #define ERR_INVALID_DATA_LEN 0x08 #define REPORT_KEY_STATE 0x11 /* LCD: IN[2] */ #define REPORT_IR_DATA 0x21 /* LCD: IN[63] */ #define REPORT_EE_DATA 0x32 /* LCD: IN[63] */ #define REPORT_MEMORY 0x41 /* LCD: IN[63] */ #define REPORT_LED_STATE 0x81 /* LCD: OUT[1] */ #define REPORT_BRIGHTNESS 0x91 /* LCD: OUT[1] */ #define REPORT_CONTRAST 0x92 /* LCD: OUT[1] */ #define REPORT_RESET 0x93 /* LCD: OUT[2] */ #define REPORT_LCD_CMD 0x94 /* LCD: OUT[63] */ #define REPORT_LCD_DATA 0x95 /* LCD: OUT[63] */ #define REPORT_LCD_CMD_DATA 0x96 /* LCD: OUT[63] */ #define REPORT_EE_READ 0xa3 /* LCD: OUT[63] */ #define REPORT_EE_WRITE 0xa4 /* LCD: OUT[63] */ #define REPORT_ERASE_MEMORY 0xb2 /* LCD: OUT[2] */ #define REPORT_READ_MEMORY 0xb3 /* LCD: OUT[3] */ #define REPORT_WRITE_MEMORY 0xb4 /* LCD: OUT[63] */ #define REPORT_SPLASH_RESTART 0xc1 /* LCD: OUT[1] */ #define REPORT_EXIT_KEYBOARD 0xef /* LCD: OUT[2] */ #define REPORT_VERSION 0xf1 /* LCD: IN[2],OUT[1] Bootloader: IN[2],OUT[1] */ #define REPORT_BL_ERASE_MEMORY 0xf2 /* Bootloader: IN[36],OUT[4] */ #define REPORT_BL_READ_MEMORY 0xf3 /* Bootloader: IN[36],OUT[4] */ #define REPORT_BL_WRITE_MEMORY 0xf4 /* Bootloader: IN[36],OUT[36] */ #define REPORT_DEVID 0xf5 /* LCD: IN[5], OUT[1] Bootloader: IN[5],OUT[1] */ #define REPORT_SPLASH_SIZE 0xf6 /* LCD: IN[4], OUT[1] */ #define REPORT_HOOK_VERSION 0xf7 /* LCD: IN[2], OUT[1] */ #define REPORT_EXIT_FLASHER 0xff /* Bootloader: OUT[2] */ /* Description of in-progress IO operation, used for operations * that trigger response from device */ struct picolcd_pending { struct hid_report *out_report; struct hid_report *in_report; struct completion ready; int raw_size; u8 raw_data[64]; }; #define PICOLCD_KEYS 17 /* Per device data structure */ struct picolcd_data { struct hid_device *hdev; #ifdef CONFIG_DEBUG_FS struct dentry *debug_reset; struct dentry *debug_eeprom; struct dentry *debug_flash; struct mutex mutex_flash; int addr_sz; #endif u8 version[2]; unsigned short opmode_delay; /* input stuff */ u8 pressed_keys[2]; struct input_dev *input_keys; #ifdef CONFIG_HID_PICOLCD_CIR struct rc_dev *rc_dev; #endif unsigned short keycode[PICOLCD_KEYS]; #ifdef CONFIG_HID_PICOLCD_FB /* Framebuffer stuff */ struct fb_info *fb_info; #endif /* CONFIG_HID_PICOLCD_FB */ #ifdef CONFIG_HID_PICOLCD_LCD struct lcd_device *lcd; u8 lcd_contrast; #endif /* CONFIG_HID_PICOLCD_LCD */ #ifdef CONFIG_HID_PICOLCD_BACKLIGHT struct backlight_device *backlight; u8 lcd_brightness; u8 lcd_power; #endif /* CONFIG_HID_PICOLCD_BACKLIGHT */ #ifdef CONFIG_HID_PICOLCD_LEDS /* LED stuff */ u8 led_state; struct led_classdev *led[8]; #endif /* CONFIG_HID_PICOLCD_LEDS */ /* Housekeeping stuff */ spinlock_t lock; struct mutex mutex; struct picolcd_pending *pending; int status; #define PICOLCD_BOOTLOADER 1 #define PICOLCD_FAILED 2 #define PICOLCD_CIR_SHUN 4 }; #ifdef CONFIG_HID_PICOLCD_FB struct picolcd_fb_data { /* Framebuffer stuff */ spinlock_t lock; struct picolcd_data *picolcd; u8 update_rate; u8 bpp; u8 force; u8 ready; u8 *vbitmap; /* local copy of what was sent to PicoLCD */ u8 *bitmap; /* framebuffer */ }; #endif /* CONFIG_HID_PICOLCD_FB */ /* Find a given report */ #define picolcd_in_report(id, dev) picolcd_report(id, dev, HID_INPUT_REPORT) #define picolcd_out_report(id, dev) picolcd_report(id, dev, HID_OUTPUT_REPORT) struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir); #ifdef CONFIG_DEBUG_FS void picolcd_debug_out_report(struct picolcd_data *data, struct hid_device *hdev, struct hid_report *report); #define hid_hw_request(a, b, c) \ do { \ picolcd_debug_out_report(hid_get_drvdata(a), a, b); \ hid_hw_request(a, b, c); \ } while (0) void picolcd_debug_raw_event(struct picolcd_data *data, struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size); void picolcd_init_devfs(struct picolcd_data *data, struct hid_report *eeprom_r, struct hid_report *eeprom_w, struct hid_report *flash_r, struct hid_report *flash_w, struct hid_report *reset); void picolcd_exit_devfs(struct picolcd_data *data); #else static inline void picolcd_debug_out_report(struct picolcd_data *data, struct hid_device *hdev, struct hid_report *report) { } static inline void picolcd_debug_raw_event(struct picolcd_data *data, struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size) { } static inline void picolcd_init_devfs(struct picolcd_data *data, struct hid_report *eeprom_r, struct hid_report *eeprom_w, struct hid_report *flash_r, struct hid_report *flash_w, struct hid_report *reset) { } static inline void picolcd_exit_devfs(struct picolcd_data *data) { } #endif /* CONFIG_DEBUG_FS */ #ifdef CONFIG_HID_PICOLCD_FB int picolcd_fb_reset(struct picolcd_data *data, int clear); int picolcd_init_framebuffer(struct picolcd_data *data); void picolcd_exit_framebuffer(struct picolcd_data *data); void picolcd_fb_refresh(struct picolcd_data *data); #define picolcd_fbinfo(d) ((d)->fb_info) #else static inline int picolcd_fb_reset(struct picolcd_data *data, int clear) { return 0; } static inline int picolcd_init_framebuffer(struct picolcd_data *data) { return 0; } static inline void picolcd_exit_framebuffer(struct picolcd_data *data) { } static inline void picolcd_fb_refresh(struct picolcd_data *data) { } #define picolcd_fbinfo(d) NULL #endif /* CONFIG_HID_PICOLCD_FB */ #ifdef CONFIG_HID_PICOLCD_BACKLIGHT int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *report); void picolcd_exit_backlight(struct picolcd_data *data); int picolcd_resume_backlight(struct picolcd_data *data); void picolcd_suspend_backlight(struct picolcd_data *data); #else static inline int picolcd_init_backlight(struct picolcd_data *data, struct hid_report *report) { return 0; } static inline void picolcd_exit_backlight(struct picolcd_data *data) { } static inline int picolcd_resume_backlight(struct picolcd_data *data) { return 0; } static inline void picolcd_suspend_backlight(struct picolcd_data *data) { } #endif /* CONFIG_HID_PICOLCD_BACKLIGHT */ #ifdef CONFIG_HID_PICOLCD_LCD int picolcd_init_lcd(struct picolcd_data *data, struct hid_report *report); void picolcd_exit_lcd(struct picolcd_data *data); int picolcd_resume_lcd(struct picolcd_data *data); #else static inline int picolcd_init_lcd(struct picolcd_data *data, struct hid_report *report) { return 0; } static inline void picolcd_exit_lcd(struct picolcd_data *data) { } static inline int picolcd_resume_lcd(struct picolcd_data *data) { return 0; } #endif /* CONFIG_HID_PICOLCD_LCD */ #ifdef CONFIG_HID_PICOLCD_LEDS int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report); void picolcd_exit_leds(struct picolcd_data *data); void picolcd_leds_set(struct picolcd_data *data); #else static inline int picolcd_init_leds(struct picolcd_data *data, struct hid_report *report) { return 0; } static inline void picolcd_exit_leds(struct picolcd_data *data) { } static inline void picolcd_leds_set(struct picolcd_data *data) { } #endif /* CONFIG_HID_PICOLCD_LEDS */ #ifdef CONFIG_HID_PICOLCD_CIR int picolcd_raw_cir(struct picolcd_data *data, struct hid_report *report, u8 *raw_data, int size); int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report); void picolcd_exit_cir(struct picolcd_data *data); #else static inline int picolcd_raw_cir(struct picolcd_data *data, struct hid_report *report, u8 *raw_data, int size) { return 1; } static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report) { return 0; } static inline void picolcd_exit_cir(struct picolcd_data *data) { } #endif /* CONFIG_HID_PICOLCD_CIR */ int picolcd_reset(struct hid_device *hdev); struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, int report_id, const u8 *raw_data, int size); |