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
300
301
302
303
304
305
306
307
308
309
310
|
/***************************************************************************
* 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> *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, version 2 of the License. *
* *
* This driver is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this software. If not see <http://www.gnu.org/licenses/>. *
***************************************************************************/
#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 usbhid_submit_report(a, b, c) \
do { \
picolcd_debug_out_report(hid_get_drvdata(a), a, b); \
usbhid_submit_report(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_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)
{
}
static inline void picolcd_debug_raw_event(struct picolcd_data *data,
struct hid_device *hdev, struct hid_report *report,
u8 *raw_data, int size)
{
}
#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_LIRC */
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);
|