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 */ 62struct 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 */ 74struct 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 123struct 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 140struct hid_report *picolcd_report(int id, struct hid_device *hdev, int dir); 141 142#ifdef CONFIG_DEBUG_FS 143void 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 151void picolcd_debug_raw_event(struct picolcd_data *data, 152 struct hid_device *hdev, struct hid_report *report, 153 u8 *raw_data, int size); 154 155void 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 160void picolcd_exit_devfs(struct picolcd_data *data); 161#else 162static inline void picolcd_debug_out_report(struct picolcd_data *data, 163 struct hid_device *hdev, struct hid_report *report) 164{ 165} 166static 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} 171static 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} 177static inline void picolcd_exit_devfs(struct picolcd_data *data) 178{ 179} 180#endif /* CONFIG_DEBUG_FS */ 181 182 183#ifdef CONFIG_HID_PICOLCD_FB 184int picolcd_fb_reset(struct picolcd_data *data, int clear); 185 186int picolcd_init_framebuffer(struct picolcd_data *data); 187 188void picolcd_exit_framebuffer(struct picolcd_data *data); 189 190void picolcd_fb_refresh(struct picolcd_data *data); 191#define picolcd_fbinfo(d) ((d)->fb_info) 192#else 193static inline int picolcd_fb_reset(struct picolcd_data *data, int clear) 194{ 195 return 0; 196} 197static inline int picolcd_init_framebuffer(struct picolcd_data *data) 198{ 199 return 0; 200} 201static inline void picolcd_exit_framebuffer(struct picolcd_data *data) 202{ 203} 204static 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 212int picolcd_init_backlight(struct picolcd_data *data, 213 struct hid_report *report); 214 215void picolcd_exit_backlight(struct picolcd_data *data); 216 217int picolcd_resume_backlight(struct picolcd_data *data); 218 219void picolcd_suspend_backlight(struct picolcd_data *data); 220#else 221static inline int picolcd_init_backlight(struct picolcd_data *data, 222 struct hid_report *report) 223{ 224 return 0; 225} 226static inline void picolcd_exit_backlight(struct picolcd_data *data) 227{ 228} 229static inline int picolcd_resume_backlight(struct picolcd_data *data) 230{ 231 return 0; 232} 233static 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 241int picolcd_init_lcd(struct picolcd_data *data, 242 struct hid_report *report); 243 244void picolcd_exit_lcd(struct picolcd_data *data); 245 246int picolcd_resume_lcd(struct picolcd_data *data); 247#else 248static inline int picolcd_init_lcd(struct picolcd_data *data, 249 struct hid_report *report) 250{ 251 return 0; 252} 253static inline void picolcd_exit_lcd(struct picolcd_data *data) 254{ 255} 256static 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 264int picolcd_init_leds(struct picolcd_data *data, 265 struct hid_report *report); 266 267void picolcd_exit_leds(struct picolcd_data *data); 268 269void picolcd_leds_set(struct picolcd_data *data); 270#else 271static inline int picolcd_init_leds(struct picolcd_data *data, 272 struct hid_report *report) 273{ 274 return 0; 275} 276static inline void picolcd_exit_leds(struct picolcd_data *data) 277{ 278} 279static 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 286int picolcd_raw_cir(struct picolcd_data *data, 287 struct hid_report *report, u8 *raw_data, int size); 288 289int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report); 290 291void picolcd_exit_cir(struct picolcd_data *data); 292#else 293static inline int picolcd_raw_cir(struct picolcd_data *data, 294 struct hid_report *report, u8 *raw_data, int size) 295{ 296 return 1; 297} 298static inline int picolcd_init_cir(struct picolcd_data *data, struct hid_report *report) 299{ 300 return 0; 301} 302static inline void picolcd_exit_cir(struct picolcd_data *data) 303{ 304} 305#endif /* CONFIG_HID_PICOLCD_CIR */ 306 307int picolcd_reset(struct hid_device *hdev); 308struct picolcd_pending *picolcd_send_and_wait(struct hid_device *hdev, 309 int report_id, const u8 *raw_data, int size); 310