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