aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/input
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2013-02-02 14:26:13 -0500
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2013-03-12 11:50:22 -0400
commit628329d52474323938a03826941e166bc7c8eff4 (patch)
tree109e1e37653253ef0ec80c2ed3996c7762f74c14 /drivers/input
parent5a1bbf21325bd4f2641f6141fb8c47f6095578dd (diff)
Input: add IMS Passenger Control Unit driver
The PCU is a device installed in the armrest of a plane seat and is connected to IMS Rave Entertainment System. It has a set of control buttons (Volume Up/Down, Attendant, Lights, etc) on one side and gamepad-like controls on the other side. Originally the device was handled from userspace and because of that it presents itself on USB bus as a CDC-ACM modem device that however can not make calls. However the custom handling is not as convenient as using standard input subsystem facilities. If it was pure input device it would be possible to continue using userspace solution (moving it over to uinput), but the device also has backlighted keys which can not be supported via uinput. Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r--drivers/input/misc/Kconfig10
-rw-r--r--drivers/input/misc/Makefile1
-rw-r--r--drivers/input/misc/ims-pcu.c1900
3 files changed, 1911 insertions, 0 deletions
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 2a1647ef5610..3ec8887ce451 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -580,6 +580,16 @@ config INPUT_ADXL34X_SPI
580 To compile this driver as a module, choose M here: the 580 To compile this driver as a module, choose M here: the
581 module will be called adxl34x-spi. 581 module will be called adxl34x-spi.
582 582
583config INPUT_IMS_PCU
584 tristate "IMS Passenger Control Unit driver"
585 depends on USB
586 depends on LEDS_CLASS
587 help
588 Say Y here if you have system with IMS Rave Passenger Control Unit.
589
590 To compile this driver as a module, choose M here: the module will be
591 called ims_pcu.
592
583config INPUT_CMA3000 593config INPUT_CMA3000
584 tristate "VTI CMA3000 Tri-axis accelerometer" 594 tristate "VTI CMA3000 Tri-axis accelerometer"
585 help 595 help
diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile
index 1f874afeea6a..d6873433ba71 100644
--- a/drivers/input/misc/Makefile
+++ b/drivers/input/misc/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_INPUT_DM355EVM) += dm355evm_keys.o
28obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o 28obj-$(CONFIG_INPUT_GP2A) += gp2ap002a00f.o
29obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o 29obj-$(CONFIG_INPUT_GPIO_TILT_POLLED) += gpio_tilt_polled.o
30obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o 30obj-$(CONFIG_HP_SDC_RTC) += hp_sdc_rtc.o
31obj-$(CONFIG_INPUT_IMS_PCU) += ims-pcu.o
31obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o 32obj-$(CONFIG_INPUT_IXP4XX_BEEPER) += ixp4xx-beeper.o
32obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o 33obj-$(CONFIG_INPUT_KEYSPAN_REMOTE) += keyspan_remote.o
33obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o 34obj-$(CONFIG_INPUT_KXTJ9) += kxtj9.o
diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c
new file mode 100644
index 000000000000..1b044b99da66
--- /dev/null
+++ b/drivers/input/misc/ims-pcu.c
@@ -0,0 +1,1900 @@
1/*
2 * Driver for IMS Passenger Control Unit Devices
3 *
4 * Copyright (C) 2013 The IMS Company
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
9 */
10
11#include <linux/completion.h>
12#include <linux/device.h>
13#include <linux/firmware.h>
14#include <linux/ihex.h>
15#include <linux/input.h>
16#include <linux/kernel.h>
17#include <linux/leds.h>
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/types.h>
21#include <linux/usb/input.h>
22#include <linux/usb/cdc.h>
23#include <asm/unaligned.h>
24
25#define IMS_PCU_KEYMAP_LEN 32
26
27struct ims_pcu_buttons {
28 struct input_dev *input;
29 char name[32];
30 char phys[32];
31 unsigned short keymap[IMS_PCU_KEYMAP_LEN];
32};
33
34struct ims_pcu_gamepad {
35 struct input_dev *input;
36 char name[32];
37 char phys[32];
38};
39
40struct ims_pcu_backlight {
41 struct led_classdev cdev;
42 struct work_struct work;
43 enum led_brightness desired_brightness;
44 char name[32];
45};
46
47#define IMS_PCU_PART_NUMBER_LEN 15
48#define IMS_PCU_SERIAL_NUMBER_LEN 8
49#define IMS_PCU_DOM_LEN 8
50#define IMS_PCU_FW_VERSION_LEN (9 + 1)
51#define IMS_PCU_BL_VERSION_LEN (9 + 1)
52#define IMS_PCU_BL_RESET_REASON_LEN (2 + 1)
53
54#define IMS_PCU_BUF_SIZE 128
55
56struct ims_pcu {
57 struct usb_device *udev;
58 struct device *dev; /* control interface's device, used for logging */
59
60 unsigned int device_no;
61
62 bool bootloader_mode;
63
64 char part_number[IMS_PCU_PART_NUMBER_LEN];
65 char serial_number[IMS_PCU_SERIAL_NUMBER_LEN];
66 char date_of_manufacturing[IMS_PCU_DOM_LEN];
67 char fw_version[IMS_PCU_FW_VERSION_LEN];
68 char bl_version[IMS_PCU_BL_VERSION_LEN];
69 char reset_reason[IMS_PCU_BL_RESET_REASON_LEN];
70 int update_firmware_status;
71
72 struct usb_interface *ctrl_intf;
73
74 struct usb_endpoint_descriptor *ep_ctrl;
75 struct urb *urb_ctrl;
76 u8 *urb_ctrl_buf;
77 dma_addr_t ctrl_dma;
78 size_t max_ctrl_size;
79
80 struct usb_interface *data_intf;
81
82 struct usb_endpoint_descriptor *ep_in;
83 struct urb *urb_in;
84 u8 *urb_in_buf;
85 dma_addr_t read_dma;
86 size_t max_in_size;
87
88 struct usb_endpoint_descriptor *ep_out;
89 u8 *urb_out_buf;
90 size_t max_out_size;
91
92 u8 read_buf[IMS_PCU_BUF_SIZE];
93 u8 read_pos;
94 u8 check_sum;
95 bool have_stx;
96 bool have_dle;
97
98 u8 cmd_buf[IMS_PCU_BUF_SIZE];
99 u8 ack_id;
100 u8 expected_response;
101 u8 cmd_buf_len;
102 struct completion cmd_done;
103 struct mutex cmd_mutex;
104
105 u32 fw_start_addr;
106 u32 fw_end_addr;
107 struct completion async_firmware_done;
108
109 struct ims_pcu_buttons buttons;
110 struct ims_pcu_gamepad *gamepad;
111 struct ims_pcu_backlight backlight;
112
113 bool setup_complete; /* Input and LED devices have been created */
114};
115
116
117/*********************************************************************
118 * Buttons Input device support *
119 *********************************************************************/
120
121static const unsigned short ims_pcu_keymap_1[] = {
122 [1] = KEY_ATTENDANT_OFF,
123 [2] = KEY_ATTENDANT_ON,
124 [3] = KEY_LIGHTS_TOGGLE,
125 [4] = KEY_VOLUMEUP,
126 [5] = KEY_VOLUMEDOWN,
127 [6] = KEY_INFO,
128};
129
130static const unsigned short ims_pcu_keymap_2[] = {
131 [4] = KEY_VOLUMEUP,
132 [5] = KEY_VOLUMEDOWN,
133 [6] = KEY_INFO,
134};
135
136static const unsigned short ims_pcu_keymap_3[] = {
137 [1] = KEY_HOMEPAGE,
138 [2] = KEY_ATTENDANT_TOGGLE,
139 [3] = KEY_LIGHTS_TOGGLE,
140 [4] = KEY_VOLUMEUP,
141 [5] = KEY_VOLUMEDOWN,
142 [6] = KEY_DISPLAYTOGGLE,
143 [18] = KEY_PLAYPAUSE,
144};
145
146static const unsigned short ims_pcu_keymap_4[] = {
147 [1] = KEY_ATTENDANT_OFF,
148 [2] = KEY_ATTENDANT_ON,
149 [3] = KEY_LIGHTS_TOGGLE,
150 [4] = KEY_VOLUMEUP,
151 [5] = KEY_VOLUMEDOWN,
152 [6] = KEY_INFO,
153 [18] = KEY_PLAYPAUSE,
154};
155
156static const unsigned short ims_pcu_keymap_5[] = {
157 [1] = KEY_ATTENDANT_OFF,
158 [2] = KEY_ATTENDANT_ON,
159 [3] = KEY_LIGHTS_TOGGLE,
160};
161
162struct ims_pcu_device_info {
163 const unsigned short *keymap;
164 size_t keymap_len;
165 bool has_gamepad;
166};
167
168#define IMS_PCU_DEVINFO(_n, _gamepad) \
169 [_n] = { \
170 .keymap = ims_pcu_keymap_##_n, \
171 .keymap_len = ARRAY_SIZE(ims_pcu_keymap_##_n), \
172 .has_gamepad = _gamepad, \
173 }
174
175static const struct ims_pcu_device_info ims_pcu_device_info[] = {
176 IMS_PCU_DEVINFO(1, true),
177 IMS_PCU_DEVINFO(2, true),
178 IMS_PCU_DEVINFO(3, true),
179 IMS_PCU_DEVINFO(4, true),
180 IMS_PCU_DEVINFO(5, false),
181};
182
183static void ims_pcu_buttons_report(struct ims_pcu *pcu, u32 data)
184{
185 struct ims_pcu_buttons *buttons = &pcu->buttons;
186 struct input_dev *input = buttons->input;
187 int i;
188
189 for (i = 0; i < 32; i++) {
190 unsigned short keycode = buttons->keymap[i];
191
192 if (keycode != KEY_RESERVED)
193 input_report_key(input, keycode, data & (1UL << i));
194 }
195
196 input_sync(input);
197}
198
199static int ims_pcu_setup_buttons(struct ims_pcu *pcu,
200 const unsigned short *keymap,
201 size_t keymap_len)
202{
203 struct ims_pcu_buttons *buttons = &pcu->buttons;
204 struct input_dev *input;
205 int i;
206 int error;
207
208 input = input_allocate_device();
209 if (!input) {
210 dev_err(pcu->dev,
211 "Not enough memory for input input device\n");
212 return -ENOMEM;
213 }
214
215 snprintf(buttons->name, sizeof(buttons->name),
216 "IMS PCU#%d Button Interface", pcu->device_no);
217
218 usb_make_path(pcu->udev, buttons->phys, sizeof(buttons->phys));
219 strlcat(buttons->phys, "/input0", sizeof(buttons->phys));
220
221 memcpy(buttons->keymap, keymap, sizeof(*keymap) * keymap_len);
222
223 input->name = buttons->name;
224 input->phys = buttons->phys;
225 usb_to_input_id(pcu->udev, &input->id);
226 input->dev.parent = &pcu->ctrl_intf->dev;
227
228 input->keycode = buttons->keymap;
229 input->keycodemax = ARRAY_SIZE(buttons->keymap);
230 input->keycodesize = sizeof(buttons->keymap[0]);
231
232 __set_bit(EV_KEY, input->evbit);
233 for (i = 0; i < IMS_PCU_KEYMAP_LEN; i++)
234 __set_bit(buttons->keymap[i], input->keybit);
235 __clear_bit(KEY_RESERVED, input->keybit);
236
237 error = input_register_device(input);
238 if (error) {
239 dev_err(pcu->dev,
240 "Failed to register buttons input device: %d\n",
241 error);
242 input_free_device(input);
243 return error;
244 }
245
246 buttons->input = input;
247 return 0;
248}
249
250static void ims_pcu_destroy_buttons(struct ims_pcu *pcu)
251{
252 struct ims_pcu_buttons *buttons = &pcu->buttons;
253
254 input_unregister_device(buttons->input);
255}
256
257
258/*********************************************************************
259 * Gamepad Input device support *
260 *********************************************************************/
261
262static void ims_pcu_gamepad_report(struct ims_pcu *pcu, u32 data)
263{
264 struct ims_pcu_gamepad *gamepad = pcu->gamepad;
265 struct input_dev *input = gamepad->input;
266 int x, y;
267
268 x = !!(data & (1 << 14)) - !!(data & (1 << 13));
269 y = !!(data & (1 << 12)) - !!(data & (1 << 11));
270
271 input_report_abs(input, ABS_X, x);
272 input_report_abs(input, ABS_Y, y);
273
274 input_report_key(input, BTN_A, data & (1 << 7));
275 input_report_key(input, BTN_B, data & (1 << 8));
276 input_report_key(input, BTN_X, data & (1 << 9));
277 input_report_key(input, BTN_Y, data & (1 << 10));
278 input_report_key(input, BTN_START, data & (1 << 15));
279 input_report_key(input, BTN_SELECT, data & (1 << 16));
280
281 input_sync(input);
282}
283
284static int ims_pcu_setup_gamepad(struct ims_pcu *pcu)
285{
286 struct ims_pcu_gamepad *gamepad;
287 struct input_dev *input;
288 int error;
289
290 gamepad = kzalloc(sizeof(struct ims_pcu_gamepad), GFP_KERNEL);
291 input = input_allocate_device();
292 if (!gamepad || !input) {
293 dev_err(pcu->dev,
294 "Not enough memory for gamepad device\n");
295 return -ENOMEM;
296 }
297
298 gamepad->input = input;
299
300 snprintf(gamepad->name, sizeof(gamepad->name),
301 "IMS PCU#%d Gamepad Interface", pcu->device_no);
302
303 usb_make_path(pcu->udev, gamepad->phys, sizeof(gamepad->phys));
304 strlcat(gamepad->phys, "/input1", sizeof(gamepad->phys));
305
306 input->name = gamepad->name;
307 input->phys = gamepad->phys;
308 usb_to_input_id(pcu->udev, &input->id);
309 input->dev.parent = &pcu->ctrl_intf->dev;
310
311 __set_bit(EV_KEY, input->evbit);
312 __set_bit(BTN_A, input->keybit);
313 __set_bit(BTN_B, input->keybit);
314 __set_bit(BTN_X, input->keybit);
315 __set_bit(BTN_Y, input->keybit);
316 __set_bit(BTN_START, input->keybit);
317 __set_bit(BTN_SELECT, input->keybit);
318
319 __set_bit(EV_ABS, input->evbit);
320 input_set_abs_params(input, ABS_X, -1, 1, 0, 0);
321 input_set_abs_params(input, ABS_Y, -1, 1, 0, 0);
322
323 error = input_register_device(input);
324 if (error) {
325 dev_err(pcu->dev,
326 "Failed to register gamepad input device: %d\n",
327 error);
328 goto err_free_mem;
329 }
330
331 pcu->gamepad = gamepad;
332 return 0;
333
334err_free_mem:
335 input_free_device(input);
336 kfree(gamepad);
337 return -ENOMEM;
338}
339
340static void ims_pcu_destroy_gamepad(struct ims_pcu *pcu)
341{
342 struct ims_pcu_gamepad *gamepad = pcu->gamepad;
343
344 input_unregister_device(gamepad->input);
345 kfree(gamepad);
346}
347
348
349/*********************************************************************
350 * PCU Communication protocol handling *
351 *********************************************************************/
352
353#define IMS_PCU_PROTOCOL_STX 0x02
354#define IMS_PCU_PROTOCOL_ETX 0x03
355#define IMS_PCU_PROTOCOL_DLE 0x10
356
357/* PCU commands */
358#define IMS_PCU_CMD_STATUS 0xa0
359#define IMS_PCU_CMD_PCU_RESET 0xa1
360#define IMS_PCU_CMD_RESET_REASON 0xa2
361#define IMS_PCU_CMD_SEND_BUTTONS 0xa3
362#define IMS_PCU_CMD_JUMP_TO_BTLDR 0xa4
363#define IMS_PCU_CMD_GET_INFO 0xa5
364#define IMS_PCU_CMD_SET_BRIGHTNESS 0xa6
365#define IMS_PCU_CMD_EEPROM 0xa7
366#define IMS_PCU_CMD_GET_FW_VERSION 0xa8
367#define IMS_PCU_CMD_GET_BL_VERSION 0xa9
368#define IMS_PCU_CMD_SET_INFO 0xab
369#define IMS_PCU_CMD_GET_BRIGHTNESS 0xac
370#define IMS_PCU_CMD_GET_DEVICE_ID 0xae
371#define IMS_PCU_CMD_SPECIAL_INFO 0xb0
372#define IMS_PCU_CMD_BOOTLOADER 0xb1 /* Pass data to bootloader */
373
374/* PCU responses */
375#define IMS_PCU_RSP_STATUS 0xc0
376#define IMS_PCU_RSP_PCU_RESET 0 /* Originally 0xc1 */
377#define IMS_PCU_RSP_RESET_REASON 0xc2
378#define IMS_PCU_RSP_SEND_BUTTONS 0xc3
379#define IMS_PCU_RSP_JUMP_TO_BTLDR 0 /* Originally 0xc4 */
380#define IMS_PCU_RSP_GET_INFO 0xc5
381#define IMS_PCU_RSP_SET_BRIGHTNESS 0xc6
382#define IMS_PCU_RSP_EEPROM 0xc7
383#define IMS_PCU_RSP_GET_FW_VERSION 0xc8
384#define IMS_PCU_RSP_GET_BL_VERSION 0xc9
385#define IMS_PCU_RSP_SET_INFO 0xcb
386#define IMS_PCU_RSP_GET_BRIGHTNESS 0xcc
387#define IMS_PCU_RSP_CMD_INVALID 0xcd
388#define IMS_PCU_RSP_GET_DEVICE_ID 0xce
389#define IMS_PCU_RSP_SPECIAL_INFO 0xd0
390#define IMS_PCU_RSP_BOOTLOADER 0xd1 /* Bootloader response */
391
392#define IMS_PCU_RSP_EVNT_BUTTONS 0xe0 /* Unsolicited, button state */
393#define IMS_PCU_GAMEPAD_MASK 0x0001ff80UL /* Bits 7 through 16 */
394
395
396#define IMS_PCU_MIN_PACKET_LEN 3
397#define IMS_PCU_DATA_OFFSET 2
398
399#define IMS_PCU_CMD_WRITE_TIMEOUT 100 /* msec */
400#define IMS_PCU_CMD_RESPONSE_TIMEOUT 500 /* msec */
401
402static void ims_pcu_report_events(struct ims_pcu *pcu)
403{
404 u32 data = get_unaligned_be32(&pcu->read_buf[3]);
405
406 ims_pcu_buttons_report(pcu, data & ~IMS_PCU_GAMEPAD_MASK);
407 if (pcu->gamepad)
408 ims_pcu_gamepad_report(pcu, data);
409}
410
411static void ims_pcu_handle_response(struct ims_pcu *pcu)
412{
413 switch (pcu->read_buf[0]) {
414 case IMS_PCU_RSP_EVNT_BUTTONS:
415 if (likely(pcu->setup_complete))
416 ims_pcu_report_events(pcu);
417 break;
418
419 default:
420 /*
421 * See if we got command completion.
422 * If both the sequence and response code match save
423 * the data and signal completion.
424 */
425 if (pcu->read_buf[0] == pcu->expected_response &&
426 pcu->read_buf[1] == pcu->ack_id - 1) {
427
428 memcpy(pcu->cmd_buf, pcu->read_buf, pcu->read_pos);
429 pcu->cmd_buf_len = pcu->read_pos;
430 complete(&pcu->cmd_done);
431 }
432 break;
433 }
434}
435
436static void ims_pcu_process_data(struct ims_pcu *pcu, struct urb *urb)
437{
438 int i;
439
440 for (i = 0; i < urb->actual_length; i++) {
441 u8 data = pcu->urb_in_buf[i];
442
443 /* Skip everything until we get Start Xmit */
444 if (!pcu->have_stx && data != IMS_PCU_PROTOCOL_STX)
445 continue;
446
447 if (pcu->have_dle) {
448 pcu->have_dle = false;
449 pcu->read_buf[pcu->read_pos++] = data;
450 pcu->check_sum += data;
451 continue;
452 }
453
454 switch (data) {
455 case IMS_PCU_PROTOCOL_STX:
456 if (pcu->have_stx)
457 dev_warn(pcu->dev,
458 "Unexpected STX at byte %d, discarding old data\n",
459 pcu->read_pos);
460 pcu->have_stx = true;
461 pcu->have_dle = false;
462 pcu->read_pos = 0;
463 pcu->check_sum = 0;
464 break;
465
466 case IMS_PCU_PROTOCOL_DLE:
467 pcu->have_dle = true;
468 break;
469
470 case IMS_PCU_PROTOCOL_ETX:
471 if (pcu->read_pos < IMS_PCU_MIN_PACKET_LEN) {
472 dev_warn(pcu->dev,
473 "Short packet received (%d bytes), ignoring\n",
474 pcu->read_pos);
475 } else if (pcu->check_sum != 0) {
476 dev_warn(pcu->dev,
477 "Invalid checksum in packet (%d bytes), ignoring\n",
478 pcu->read_pos);
479 } else {
480 ims_pcu_handle_response(pcu);
481 }
482
483 pcu->have_stx = false;
484 pcu->have_dle = false;
485 pcu->read_pos = 0;
486 break;
487
488 default:
489 pcu->read_buf[pcu->read_pos++] = data;
490 pcu->check_sum += data;
491 break;
492 }
493 }
494}
495
496static bool ims_pcu_byte_needs_escape(u8 byte)
497{
498 return byte == IMS_PCU_PROTOCOL_STX ||
499 byte == IMS_PCU_PROTOCOL_ETX ||
500 byte == IMS_PCU_PROTOCOL_DLE;
501}
502
503static int ims_pcu_send_cmd_chunk(struct ims_pcu *pcu,
504 u8 command, int chunk, int len)
505{
506 int error;
507
508 error = usb_bulk_msg(pcu->udev,
509 usb_sndbulkpipe(pcu->udev,
510 pcu->ep_out->bEndpointAddress),
511 pcu->urb_out_buf, len,
512 NULL, IMS_PCU_CMD_WRITE_TIMEOUT);
513 if (error < 0) {
514 dev_dbg(pcu->dev,
515 "Sending 0x%02x command failed at chunk %d: %d\n",
516 command, chunk, error);
517 return error;
518 }
519
520 return 0;
521}
522
523static int ims_pcu_send_command(struct ims_pcu *pcu,
524 u8 command, const u8 *data, int len)
525{
526 int count = 0;
527 int chunk = 0;
528 int delta;
529 int i;
530 int error;
531 u8 csum = 0;
532 u8 ack_id;
533
534 pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_STX;
535
536 /* We know the command need not be escaped */
537 pcu->urb_out_buf[count++] = command;
538 csum += command;
539
540 ack_id = pcu->ack_id++;
541 if (ack_id == 0xff)
542 ack_id = pcu->ack_id++;
543
544 if (ims_pcu_byte_needs_escape(ack_id))
545 pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_DLE;
546
547 pcu->urb_out_buf[count++] = ack_id;
548 csum += ack_id;
549
550 for (i = 0; i < len; i++) {
551
552 delta = ims_pcu_byte_needs_escape(data[i]) ? 2 : 1;
553 if (count + delta >= pcu->max_out_size) {
554 error = ims_pcu_send_cmd_chunk(pcu, command,
555 ++chunk, count);
556 if (error)
557 return error;
558
559 count = 0;
560 }
561
562 if (delta == 2)
563 pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_DLE;
564
565 pcu->urb_out_buf[count++] = data[i];
566 csum += data[i];
567 }
568
569 csum = 1 + ~csum;
570
571 delta = ims_pcu_byte_needs_escape(csum) ? 3 : 2;
572 if (count + delta >= pcu->max_out_size) {
573 error = ims_pcu_send_cmd_chunk(pcu, command, ++chunk, count);
574 if (error)
575 return error;
576
577 count = 0;
578 }
579
580 if (delta == 3)
581 pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_DLE;
582
583 pcu->urb_out_buf[count++] = csum;
584 pcu->urb_out_buf[count++] = IMS_PCU_PROTOCOL_ETX;
585
586 return ims_pcu_send_cmd_chunk(pcu, command, ++chunk, count);
587}
588
589static int __ims_pcu_execute_command(struct ims_pcu *pcu,
590 u8 command, const void *data, size_t len,
591 u8 expected_response, int response_time)
592{
593 int error;
594
595 pcu->expected_response = expected_response;
596 init_completion(&pcu->cmd_done);
597
598 error = ims_pcu_send_command(pcu, command, data, len);
599 if (error)
600 return error;
601
602 if (expected_response &&
603 !wait_for_completion_timeout(&pcu->cmd_done,
604 msecs_to_jiffies(response_time))) {
605 dev_dbg(pcu->dev, "Command 0x%02x timed out\n", command);
606 return -ETIMEDOUT;
607 }
608
609 return 0;
610}
611
612#define ims_pcu_execute_command(pcu, code, data, len) \
613 __ims_pcu_execute_command(pcu, \
614 IMS_PCU_CMD_##code, data, len, \
615 IMS_PCU_RSP_##code, \
616 IMS_PCU_CMD_RESPONSE_TIMEOUT)
617
618#define ims_pcu_execute_query(pcu, code) \
619 ims_pcu_execute_command(pcu, code, NULL, 0)
620
621/* Bootloader commands */
622#define IMS_PCU_BL_CMD_QUERY_DEVICE 0xa1
623#define IMS_PCU_BL_CMD_UNLOCK_CONFIG 0xa2
624#define IMS_PCU_BL_CMD_ERASE_APP 0xa3
625#define IMS_PCU_BL_CMD_PROGRAM_DEVICE 0xa4
626#define IMS_PCU_BL_CMD_PROGRAM_COMPLETE 0xa5
627#define IMS_PCU_BL_CMD_READ_APP 0xa6
628#define IMS_PCU_BL_CMD_RESET_DEVICE 0xa7
629#define IMS_PCU_BL_CMD_LAUNCH_APP 0xa8
630
631/* Bootloader commands */
632#define IMS_PCU_BL_RSP_QUERY_DEVICE 0xc1
633#define IMS_PCU_BL_RSP_UNLOCK_CONFIG 0xc2
634#define IMS_PCU_BL_RSP_ERASE_APP 0xc3
635#define IMS_PCU_BL_RSP_PROGRAM_DEVICE 0xc4
636#define IMS_PCU_BL_RSP_PROGRAM_COMPLETE 0xc5
637#define IMS_PCU_BL_RSP_READ_APP 0xc6
638#define IMS_PCU_BL_RSP_RESET_DEVICE 0 /* originally 0xa7 */
639#define IMS_PCU_BL_RSP_LAUNCH_APP 0 /* originally 0xa8 */
640
641#define IMS_PCU_BL_DATA_OFFSET 3
642
643static int __ims_pcu_execute_bl_command(struct ims_pcu *pcu,
644 u8 command, const void *data, size_t len,
645 u8 expected_response, int response_time)
646{
647 int error;
648
649 pcu->cmd_buf[0] = command;
650 if (data)
651 memcpy(&pcu->cmd_buf[1], data, len);
652
653 error = __ims_pcu_execute_command(pcu,
654 IMS_PCU_CMD_BOOTLOADER, pcu->cmd_buf, len + 1,
655 expected_response ? IMS_PCU_RSP_BOOTLOADER : 0,
656 response_time);
657 if (error) {
658 dev_err(pcu->dev,
659 "Failure when sending 0x%02x command to bootloader, error: %d\n",
660 pcu->cmd_buf[0], error);
661 return error;
662 }
663
664 if (expected_response && pcu->cmd_buf[2] != expected_response) {
665 dev_err(pcu->dev,
666 "Unexpected response from bootloader: 0x%02x, wanted 0x%02x\n",
667 pcu->cmd_buf[2], expected_response);
668 return -EINVAL;
669 }
670
671 return 0;
672}
673
674#define ims_pcu_execute_bl_command(pcu, code, data, len, timeout) \
675 __ims_pcu_execute_bl_command(pcu, \
676 IMS_PCU_BL_CMD_##code, data, len, \
677 IMS_PCU_BL_RSP_##code, timeout) \
678
679#define IMS_PCU_INFO_PART_OFFSET 2
680#define IMS_PCU_INFO_DOM_OFFSET 17
681#define IMS_PCU_INFO_SERIAL_OFFSET 25
682
683#define IMS_PCU_SET_INFO_SIZE 31
684
685static int ims_pcu_get_info(struct ims_pcu *pcu)
686{
687 int error;
688
689 error = ims_pcu_execute_query(pcu, GET_INFO);
690 if (error) {
691 dev_err(pcu->dev,
692 "GET_INFO command failed, error: %d\n", error);
693 return error;
694 }
695
696 memcpy(pcu->part_number,
697 &pcu->cmd_buf[IMS_PCU_INFO_PART_OFFSET],
698 sizeof(pcu->part_number));
699 memcpy(pcu->date_of_manufacturing,
700 &pcu->cmd_buf[IMS_PCU_INFO_DOM_OFFSET],
701 sizeof(pcu->date_of_manufacturing));
702 memcpy(pcu->serial_number,
703 &pcu->cmd_buf[IMS_PCU_INFO_SERIAL_OFFSET],
704 sizeof(pcu->serial_number));
705
706 return 0;
707}
708
709static int ims_pcu_set_info(struct ims_pcu *pcu)
710{
711 int error;
712
713 memcpy(&pcu->cmd_buf[IMS_PCU_INFO_PART_OFFSET],
714 pcu->part_number, sizeof(pcu->part_number));
715 memcpy(&pcu->cmd_buf[IMS_PCU_INFO_DOM_OFFSET],
716 pcu->date_of_manufacturing, sizeof(pcu->date_of_manufacturing));
717 memcpy(&pcu->cmd_buf[IMS_PCU_INFO_SERIAL_OFFSET],
718 pcu->serial_number, sizeof(pcu->serial_number));
719
720 error = ims_pcu_execute_command(pcu, SET_INFO,
721 &pcu->cmd_buf[IMS_PCU_DATA_OFFSET],
722 IMS_PCU_SET_INFO_SIZE);
723 if (error) {
724 dev_err(pcu->dev,
725 "Failed to update device information, error: %d\n",
726 error);
727 return error;
728 }
729
730 return 0;
731}
732
733static int ims_pcu_switch_to_bootloader(struct ims_pcu *pcu)
734{
735 int error;
736
737 /* Execute jump to the bootoloader */
738 error = ims_pcu_execute_command(pcu, JUMP_TO_BTLDR, NULL, 0);
739 if (error) {
740 dev_err(pcu->dev,
741 "Failure when sending JUMP TO BOOLTLOADER command, error: %d\n",
742 error);
743 return error;
744 }
745
746 return 0;
747}
748
749/*********************************************************************
750 * Firmware Update handling *
751 *********************************************************************/
752
753#define IMS_PCU_FIRMWARE_NAME "imspcu.fw"
754
755struct ims_pcu_flash_fmt {
756 __le32 addr;
757 u8 len;
758 u8 data[];
759};
760
761static unsigned int ims_pcu_count_fw_records(const struct firmware *fw)
762{
763 const struct ihex_binrec *rec = (const struct ihex_binrec *)fw->data;
764 unsigned int count = 0;
765
766 while (rec) {
767 count++;
768 rec = ihex_next_binrec(rec);
769 }
770
771 return count;
772}
773
774static int ims_pcu_verify_block(struct ims_pcu *pcu,
775 u32 addr, u8 len, const u8 *data)
776{
777 struct ims_pcu_flash_fmt *fragment;
778 int error;
779
780 fragment = (void *)&pcu->cmd_buf[1];
781 put_unaligned_le32(addr, &fragment->addr);
782 fragment->len = len;
783
784 error = ims_pcu_execute_bl_command(pcu, READ_APP, NULL, 5,
785 IMS_PCU_CMD_RESPONSE_TIMEOUT);
786 if (error) {
787 dev_err(pcu->dev,
788 "Failed to retrieve block at 0x%08x, len %d, error: %d\n",
789 addr, len, error);
790 return error;
791 }
792
793 fragment = (void *)&pcu->cmd_buf[IMS_PCU_BL_DATA_OFFSET];
794 if (get_unaligned_le32(&fragment->addr) != addr ||
795 fragment->len != len) {
796 dev_err(pcu->dev,
797 "Wrong block when retrieving 0x%08x (0x%08x), len %d (%d)\n",
798 addr, get_unaligned_le32(&fragment->addr),
799 len, fragment->len);
800 return -EINVAL;
801 }
802
803 if (memcmp(fragment->data, data, len)) {
804 dev_err(pcu->dev,
805 "Mismatch in block at 0x%08x, len %d\n",
806 addr, len);
807 return -EINVAL;
808 }
809
810 return 0;
811}
812
813static int ims_pcu_flash_firmware(struct ims_pcu *pcu,
814 const struct firmware *fw,
815 unsigned int n_fw_records)
816{
817 const struct ihex_binrec *rec = (const struct ihex_binrec *)fw->data;
818 struct ims_pcu_flash_fmt *fragment;
819 unsigned int count = 0;
820 u32 addr;
821 u8 len;
822 int error;
823
824 error = ims_pcu_execute_bl_command(pcu, ERASE_APP, NULL, 0, 2000);
825 if (error) {
826 dev_err(pcu->dev,
827 "Failed to erase application image, error: %d\n",
828 error);
829 return error;
830 }
831
832 while (rec) {
833 /*
834 * The firmware format is messed up for some reason.
835 * The address twice that of what is needed for some
836 * reason and we end up overwriting half of the data
837 * with the next record.
838 */
839 addr = be32_to_cpu(rec->addr) / 2;
840 len = be16_to_cpu(rec->len);
841
842 fragment = (void *)&pcu->cmd_buf[1];
843 put_unaligned_le32(addr, &fragment->addr);
844 fragment->len = len;
845 memcpy(fragment->data, rec->data, len);
846
847 error = ims_pcu_execute_bl_command(pcu, PROGRAM_DEVICE,
848 NULL, len + 5,
849 IMS_PCU_CMD_RESPONSE_TIMEOUT);
850 if (error) {
851 dev_err(pcu->dev,
852 "Failed to write block at 0x%08x, len %d, error: %d\n",
853 addr, len, error);
854 return error;
855 }
856
857 if (addr >= pcu->fw_start_addr && addr < pcu->fw_end_addr) {
858 error = ims_pcu_verify_block(pcu, addr, len, rec->data);
859 if (error)
860 return error;
861 }
862
863 count++;
864 pcu->update_firmware_status = (count * 100) / n_fw_records;
865
866 rec = ihex_next_binrec(rec);
867 }
868
869 error = ims_pcu_execute_bl_command(pcu, PROGRAM_COMPLETE,
870 NULL, 0, 2000);
871 if (error)
872 dev_err(pcu->dev,
873 "Failed to send PROGRAM_COMPLETE, error: %d\n",
874 error);
875
876 return 0;
877}
878
879static int ims_pcu_handle_firmware_update(struct ims_pcu *pcu,
880 const struct firmware *fw)
881{
882 unsigned int n_fw_records;
883 int retval;
884
885 dev_info(pcu->dev, "Updating firmware %s, size: %zu\n",
886 IMS_PCU_FIRMWARE_NAME, fw->size);
887
888 n_fw_records = ims_pcu_count_fw_records(fw);
889
890 retval = ims_pcu_flash_firmware(pcu, fw, n_fw_records);
891 if (retval)
892 goto out;
893
894 retval = ims_pcu_execute_bl_command(pcu, LAUNCH_APP, NULL, 0, 0);
895 if (retval)
896 dev_err(pcu->dev,
897 "Failed to start application image, error: %d\n",
898 retval);
899
900out:
901 pcu->update_firmware_status = retval;
902 sysfs_notify(&pcu->dev->kobj, NULL, "update_firmware_status");
903 return retval;
904}
905
906static void ims_pcu_process_async_firmware(const struct firmware *fw,
907 void *context)
908{
909 struct ims_pcu *pcu = context;
910 int error;
911
912 if (!fw) {
913 dev_err(pcu->dev, "Failed to get firmware %s\n",
914 IMS_PCU_FIRMWARE_NAME);
915 goto out;
916 }
917
918 error = ihex_validate_fw(fw);
919 if (error) {
920 dev_err(pcu->dev, "Firmware %s is invalid\n",
921 IMS_PCU_FIRMWARE_NAME);
922 goto out;
923 }
924
925 mutex_lock(&pcu->cmd_mutex);
926 ims_pcu_handle_firmware_update(pcu, fw);
927 mutex_unlock(&pcu->cmd_mutex);
928
929 release_firmware(fw);
930
931out:
932 complete(&pcu->async_firmware_done);
933}
934
935/*********************************************************************
936 * Backlight LED device support *
937 *********************************************************************/
938
939#define IMS_PCU_MAX_BRIGHTNESS 31998
940
941static void ims_pcu_backlight_work(struct work_struct *work)
942{
943 struct ims_pcu_backlight *backlight =
944 container_of(work, struct ims_pcu_backlight, work);
945 struct ims_pcu *pcu =
946 container_of(backlight, struct ims_pcu, backlight);
947 int desired_brightness = backlight->desired_brightness;
948 __le16 br_val = cpu_to_le16(desired_brightness);
949 int error;
950
951 mutex_lock(&pcu->cmd_mutex);
952
953 error = ims_pcu_execute_command(pcu, SET_BRIGHTNESS,
954 &br_val, sizeof(br_val));
955 if (error && error != -ENODEV)
956 dev_warn(pcu->dev,
957 "Failed to set desired brightness %u, error: %d\n",
958 desired_brightness, error);
959
960 mutex_unlock(&pcu->cmd_mutex);
961}
962
963static void ims_pcu_backlight_set_brightness(struct led_classdev *cdev,
964 enum led_brightness value)
965{
966 struct ims_pcu_backlight *backlight =
967 container_of(cdev, struct ims_pcu_backlight, cdev);
968
969 backlight->desired_brightness = value;
970 schedule_work(&backlight->work);
971}
972
973static enum led_brightness
974ims_pcu_backlight_get_brightness(struct led_classdev *cdev)
975{
976 struct ims_pcu_backlight *backlight =
977 container_of(cdev, struct ims_pcu_backlight, cdev);
978 struct ims_pcu *pcu =
979 container_of(backlight, struct ims_pcu, backlight);
980 int brightness;
981 int error;
982
983 mutex_lock(&pcu->cmd_mutex);
984
985 error = ims_pcu_execute_query(pcu, GET_BRIGHTNESS);
986 if (error) {
987 dev_warn(pcu->dev,
988 "Failed to get current brightness, error: %d\n",
989 error);
990 /* Assume the LED is OFF */
991 brightness = LED_OFF;
992 } else {
993 brightness =
994 get_unaligned_le16(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET]);
995 }
996
997 mutex_unlock(&pcu->cmd_mutex);
998
999 return brightness;
1000}
1001
1002static int ims_pcu_setup_backlight(struct ims_pcu *pcu)
1003{
1004 struct ims_pcu_backlight *backlight = &pcu->backlight;
1005 int error;
1006
1007 INIT_WORK(&backlight->work, ims_pcu_backlight_work);
1008 snprintf(backlight->name, sizeof(backlight->name),
1009 "pcu%d::kbd_backlight", pcu->device_no);
1010
1011 backlight->cdev.name = backlight->name;
1012 backlight->cdev.max_brightness = IMS_PCU_MAX_BRIGHTNESS;
1013 backlight->cdev.brightness_get = ims_pcu_backlight_get_brightness;
1014 backlight->cdev.brightness_set = ims_pcu_backlight_set_brightness;
1015
1016 error = led_classdev_register(pcu->dev, &backlight->cdev);
1017 if (error) {
1018 dev_err(pcu->dev,
1019 "Failed to register backlight LED device, error: %d\n",
1020 error);
1021 return error;
1022 }
1023
1024 return 0;
1025}
1026
1027static void ims_pcu_destroy_backlight(struct ims_pcu *pcu)
1028{
1029 struct ims_pcu_backlight *backlight = &pcu->backlight;
1030
1031 led_classdev_unregister(&backlight->cdev);
1032 cancel_work_sync(&backlight->work);
1033}
1034
1035
1036/*********************************************************************
1037 * Sysfs attributes handling *
1038 *********************************************************************/
1039
1040struct ims_pcu_attribute {
1041 struct device_attribute dattr;
1042 size_t field_offset;
1043 int field_length;
1044};
1045
1046static ssize_t ims_pcu_attribute_show(struct device *dev,
1047 struct device_attribute *dattr,
1048 char *buf)
1049{
1050 struct usb_interface *intf = to_usb_interface(dev);
1051 struct ims_pcu *pcu = usb_get_intfdata(intf);
1052 struct ims_pcu_attribute *attr =
1053 container_of(dattr, struct ims_pcu_attribute, dattr);
1054 char *field = (char *)pcu + attr->field_offset;
1055
1056 return scnprintf(buf, PAGE_SIZE, "%.*s\n", attr->field_length, field);
1057}
1058
1059static ssize_t ims_pcu_attribute_store(struct device *dev,
1060 struct device_attribute *dattr,
1061 const char *buf, size_t count)
1062{
1063
1064 struct usb_interface *intf = to_usb_interface(dev);
1065 struct ims_pcu *pcu = usb_get_intfdata(intf);
1066 struct ims_pcu_attribute *attr =
1067 container_of(dattr, struct ims_pcu_attribute, dattr);
1068 char *field = (char *)pcu + attr->field_offset;
1069 size_t data_len;
1070 int error;
1071
1072 if (count > attr->field_length)
1073 return -EINVAL;
1074
1075 data_len = strnlen(buf, attr->field_length);
1076 if (data_len > attr->field_length)
1077 return -EINVAL;
1078
1079 error = mutex_lock_interruptible(&pcu->cmd_mutex);
1080 if (error)
1081 return error;
1082
1083 memset(field, 0, attr->field_length);
1084 memcpy(field, buf, data_len);
1085
1086 error = ims_pcu_set_info(pcu);
1087
1088 /*
1089 * Even if update failed, let's fetch the info again as we just
1090 * clobbered one of the fields.
1091 */
1092 ims_pcu_get_info(pcu);
1093
1094 mutex_unlock(&pcu->cmd_mutex);
1095
1096 return error < 0 ? error : count;
1097}
1098
1099#define IMS_PCU_ATTR(_field, _mode) \
1100struct ims_pcu_attribute ims_pcu_attr_##_field = { \
1101 .dattr = __ATTR(_field, _mode, \
1102 ims_pcu_attribute_show, \
1103 ims_pcu_attribute_store), \
1104 .field_offset = offsetof(struct ims_pcu, _field), \
1105 .field_length = sizeof(((struct ims_pcu *)NULL)->_field), \
1106}
1107
1108#define IMS_PCU_RO_ATTR(_field) \
1109 IMS_PCU_ATTR(_field, S_IRUGO)
1110#define IMS_PCU_RW_ATTR(_field) \
1111 IMS_PCU_ATTR(_field, S_IRUGO | S_IWUSR)
1112
1113static IMS_PCU_RW_ATTR(part_number);
1114static IMS_PCU_RW_ATTR(serial_number);
1115static IMS_PCU_RW_ATTR(date_of_manufacturing);
1116
1117static IMS_PCU_RO_ATTR(fw_version);
1118static IMS_PCU_RO_ATTR(bl_version);
1119static IMS_PCU_RO_ATTR(reset_reason);
1120
1121static ssize_t ims_pcu_reset_device(struct device *dev,
1122 struct device_attribute *dattr,
1123 const char *buf, size_t count)
1124{
1125 static const u8 reset_byte = 1;
1126 struct usb_interface *intf = to_usb_interface(dev);
1127 struct ims_pcu *pcu = usb_get_intfdata(intf);
1128 int value;
1129 int error;
1130
1131 error = kstrtoint(buf, 0, &value);
1132 if (error)
1133 return error;
1134
1135 if (value != 1)
1136 return -EINVAL;
1137
1138 dev_info(pcu->dev, "Attempting to reset device\n");
1139
1140 error = ims_pcu_execute_command(pcu, PCU_RESET, &reset_byte, 1);
1141 if (error) {
1142 dev_info(pcu->dev,
1143 "Failed to reset device, error: %d\n",
1144 error);
1145 return error;
1146 }
1147
1148 return count;
1149}
1150
1151static DEVICE_ATTR(reset_device, S_IWUSR, NULL, ims_pcu_reset_device);
1152
1153static ssize_t ims_pcu_update_firmware_store(struct device *dev,
1154 struct device_attribute *dattr,
1155 const char *buf, size_t count)
1156{
1157 struct usb_interface *intf = to_usb_interface(dev);
1158 struct ims_pcu *pcu = usb_get_intfdata(intf);
1159 const struct firmware *fw;
1160 int value;
1161 int error;
1162
1163 error = kstrtoint(buf, 0, &value);
1164 if (error)
1165 return error;
1166
1167 if (value != 1)
1168 return -EINVAL;
1169
1170 error = mutex_lock_interruptible(&pcu->cmd_mutex);
1171 if (error)
1172 return error;
1173
1174 error = request_ihex_firmware(&fw, IMS_PCU_FIRMWARE_NAME, pcu->dev);
1175 if (error) {
1176 dev_err(pcu->dev, "Failed to request firmware %s, error: %d\n",
1177 IMS_PCU_FIRMWARE_NAME, error);
1178 goto out;
1179 }
1180
1181 /*
1182 * If we are already in bootloader mode we can proceed with
1183 * flashing the firmware.
1184 *
1185 * If we are in application mode, then we need to switch into
1186 * bootloader mode, which will cause the device to disconnect
1187 * and reconnect as different device.
1188 */
1189 if (pcu->bootloader_mode)
1190 error = ims_pcu_handle_firmware_update(pcu, fw);
1191 else
1192 error = ims_pcu_switch_to_bootloader(pcu);
1193
1194 release_firmware(fw);
1195
1196out:
1197 mutex_unlock(&pcu->cmd_mutex);
1198 return error ?: count;
1199}
1200
1201static DEVICE_ATTR(update_firmware, S_IWUSR,
1202 NULL, ims_pcu_update_firmware_store);
1203
1204static ssize_t
1205ims_pcu_update_firmware_status_show(struct device *dev,
1206 struct device_attribute *dattr,
1207 char *buf)
1208{
1209 struct usb_interface *intf = to_usb_interface(dev);
1210 struct ims_pcu *pcu = usb_get_intfdata(intf);
1211
1212 return scnprintf(buf, PAGE_SIZE, "%d\n", pcu->update_firmware_status);
1213}
1214
1215static DEVICE_ATTR(update_firmware_status, S_IRUGO,
1216 ims_pcu_update_firmware_status_show, NULL);
1217
1218static struct attribute *ims_pcu_attrs[] = {
1219 &ims_pcu_attr_part_number.dattr.attr,
1220 &ims_pcu_attr_serial_number.dattr.attr,
1221 &ims_pcu_attr_date_of_manufacturing.dattr.attr,
1222 &ims_pcu_attr_fw_version.dattr.attr,
1223 &ims_pcu_attr_bl_version.dattr.attr,
1224 &ims_pcu_attr_reset_reason.dattr.attr,
1225 &dev_attr_reset_device.attr,
1226 &dev_attr_update_firmware.attr,
1227 &dev_attr_update_firmware_status.attr,
1228 NULL
1229};
1230
1231static umode_t ims_pcu_is_attr_visible(struct kobject *kobj,
1232 struct attribute *attr, int n)
1233{
1234 struct device *dev = container_of(kobj, struct device, kobj);
1235 struct usb_interface *intf = to_usb_interface(dev);
1236 struct ims_pcu *pcu = usb_get_intfdata(intf);
1237 umode_t mode = attr->mode;
1238
1239 if (pcu->bootloader_mode) {
1240 if (attr != &dev_attr_update_firmware_status.attr &&
1241 attr != &dev_attr_update_firmware.attr &&
1242 attr != &dev_attr_reset_device.attr) {
1243 mode = 0;
1244 }
1245 } else {
1246 if (attr == &dev_attr_update_firmware_status.attr)
1247 mode = 0;
1248 }
1249
1250 return mode;
1251}
1252
1253static struct attribute_group ims_pcu_attr_group = {
1254 .is_visible = ims_pcu_is_attr_visible,
1255 .attrs = ims_pcu_attrs,
1256};
1257
1258static void ims_pcu_irq(struct urb *urb)
1259{
1260 struct ims_pcu *pcu = urb->context;
1261 int retval, status;
1262
1263 status = urb->status;
1264
1265 switch (status) {
1266 case 0:
1267 /* success */
1268 break;
1269 case -ECONNRESET:
1270 case -ENOENT:
1271 case -ESHUTDOWN:
1272 /* this urb is terminated, clean up */
1273 dev_dbg(pcu->dev, "%s - urb shutting down with status: %d\n",
1274 __func__, status);
1275 return;
1276 default:
1277 dev_dbg(pcu->dev, "%s - nonzero urb status received: %d\n",
1278 __func__, status);
1279 goto exit;
1280 }
1281
1282 dev_dbg(pcu->dev, "%s: received %d: %*ph\n", __func__,
1283 urb->actual_length, urb->actual_length, pcu->urb_in_buf);
1284
1285 if (urb == pcu->urb_in)
1286 ims_pcu_process_data(pcu, urb);
1287
1288exit:
1289 retval = usb_submit_urb(urb, GFP_ATOMIC);
1290 if (retval && retval != -ENODEV)
1291 dev_err(pcu->dev, "%s - usb_submit_urb failed with result %d\n",
1292 __func__, retval);
1293}
1294
1295static int ims_pcu_buffers_alloc(struct ims_pcu *pcu)
1296{
1297 int error;
1298
1299 pcu->urb_in_buf = usb_alloc_coherent(pcu->udev, pcu->max_in_size,
1300 GFP_KERNEL, &pcu->read_dma);
1301 if (!pcu->urb_in_buf) {
1302 dev_err(pcu->dev,
1303 "Failed to allocate memory for read buffer\n");
1304 return -ENOMEM;
1305 }
1306
1307 pcu->urb_in = usb_alloc_urb(0, GFP_KERNEL);
1308 if (!pcu->urb_in) {
1309 dev_err(pcu->dev, "Failed to allocate input URB\n");
1310 error = -ENOMEM;
1311 goto err_free_urb_in_buf;
1312 }
1313
1314 pcu->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1315 pcu->urb_in->transfer_dma = pcu->read_dma;
1316
1317 usb_fill_bulk_urb(pcu->urb_in, pcu->udev,
1318 usb_rcvbulkpipe(pcu->udev,
1319 pcu->ep_in->bEndpointAddress),
1320 pcu->urb_in_buf, pcu->max_in_size,
1321 ims_pcu_irq, pcu);
1322
1323 /*
1324 * We are using usb_bulk_msg() for sending so there is no point
1325 * in allocating memory with usb_alloc_coherent().
1326 */
1327 pcu->urb_out_buf = kmalloc(pcu->max_out_size, GFP_KERNEL);
1328 if (!pcu->urb_out_buf) {
1329 dev_err(pcu->dev, "Failed to allocate memory for write buffer\n");
1330 error = -ENOMEM;
1331 goto err_free_in_urb;
1332 }
1333
1334 pcu->urb_ctrl_buf = usb_alloc_coherent(pcu->udev, pcu->max_ctrl_size,
1335 GFP_KERNEL, &pcu->ctrl_dma);
1336 if (!pcu->urb_ctrl_buf) {
1337 dev_err(pcu->dev,
1338 "Failed to allocate memory for read buffer\n");
1339 goto err_free_urb_out_buf;
1340 }
1341
1342 pcu->urb_ctrl = usb_alloc_urb(0, GFP_KERNEL);
1343 if (!pcu->urb_ctrl) {
1344 dev_err(pcu->dev, "Failed to allocate input URB\n");
1345 error = -ENOMEM;
1346 goto err_free_urb_ctrl_buf;
1347 }
1348
1349 pcu->urb_ctrl->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
1350 pcu->urb_ctrl->transfer_dma = pcu->ctrl_dma;
1351
1352 usb_fill_int_urb(pcu->urb_ctrl, pcu->udev,
1353 usb_rcvintpipe(pcu->udev,
1354 pcu->ep_ctrl->bEndpointAddress),
1355 pcu->urb_ctrl_buf, pcu->max_ctrl_size,
1356 ims_pcu_irq, pcu, pcu->ep_ctrl->bInterval);
1357
1358 return 0;
1359
1360err_free_urb_ctrl_buf:
1361 usb_free_coherent(pcu->udev, pcu->max_ctrl_size,
1362 pcu->urb_ctrl_buf, pcu->ctrl_dma);
1363err_free_urb_out_buf:
1364 kfree(pcu->urb_out_buf);
1365err_free_in_urb:
1366 usb_free_urb(pcu->urb_in);
1367err_free_urb_in_buf:
1368 usb_free_coherent(pcu->udev, pcu->max_in_size,
1369 pcu->urb_in_buf, pcu->read_dma);
1370 return error;
1371}
1372
1373static void ims_pcu_buffers_free(struct ims_pcu *pcu)
1374{
1375 usb_kill_urb(pcu->urb_in);
1376 usb_free_urb(pcu->urb_in);
1377
1378 usb_free_coherent(pcu->udev, pcu->max_out_size,
1379 pcu->urb_in_buf, pcu->read_dma);
1380
1381 kfree(pcu->urb_out_buf);
1382
1383 usb_kill_urb(pcu->urb_ctrl);
1384 usb_free_urb(pcu->urb_ctrl);
1385
1386 usb_free_coherent(pcu->udev, pcu->max_ctrl_size,
1387 pcu->urb_ctrl_buf, pcu->ctrl_dma);
1388}
1389
1390static const struct usb_cdc_union_desc *
1391ims_pcu_get_cdc_union_desc(struct usb_interface *intf)
1392{
1393 const void *buf = intf->altsetting->extra;
1394 size_t buflen = intf->altsetting->extralen;
1395 struct usb_cdc_union_desc *union_desc;
1396
1397 if (!buf) {
1398 dev_err(&intf->dev, "Missing descriptor data\n");
1399 return NULL;
1400 }
1401
1402 if (!buflen) {
1403 dev_err(&intf->dev, "Zero length descriptor\n");
1404 return NULL;
1405 }
1406
1407 while (buflen > 0) {
1408 union_desc = (struct usb_cdc_union_desc *)buf;
1409
1410 if (union_desc->bDescriptorType == USB_DT_CS_INTERFACE &&
1411 union_desc->bDescriptorSubType == USB_CDC_UNION_TYPE) {
1412 dev_dbg(&intf->dev, "Found union header\n");
1413 return union_desc;
1414 }
1415
1416 buflen -= union_desc->bLength;
1417 buf += union_desc->bLength;
1418 }
1419
1420 dev_err(&intf->dev, "Missing CDC union descriptor\n");
1421 return NULL;
1422}
1423
1424static int ims_pcu_parse_cdc_data(struct usb_interface *intf, struct ims_pcu *pcu)
1425{
1426 const struct usb_cdc_union_desc *union_desc;
1427 struct usb_host_interface *alt;
1428
1429 union_desc = ims_pcu_get_cdc_union_desc(intf);
1430 if (!union_desc)
1431 return -EINVAL;
1432
1433 pcu->ctrl_intf = usb_ifnum_to_if(pcu->udev,
1434 union_desc->bMasterInterface0);
1435
1436 alt = pcu->ctrl_intf->cur_altsetting;
1437 pcu->ep_ctrl = &alt->endpoint[0].desc;
1438 pcu->max_ctrl_size = usb_endpoint_maxp(pcu->ep_ctrl);
1439
1440 pcu->data_intf = usb_ifnum_to_if(pcu->udev,
1441 union_desc->bSlaveInterface0);
1442
1443 alt = pcu->data_intf->cur_altsetting;
1444 if (alt->desc.bNumEndpoints != 2) {
1445 dev_err(pcu->dev,
1446 "Incorrect number of endpoints on data interface (%d)\n",
1447 alt->desc.bNumEndpoints);
1448 return -EINVAL;
1449 }
1450
1451 pcu->ep_out = &alt->endpoint[0].desc;
1452 if (!usb_endpoint_is_bulk_out(pcu->ep_out)) {
1453 dev_err(pcu->dev,
1454 "First endpoint on data interface is not BULK OUT\n");
1455 return -EINVAL;
1456 }
1457
1458 pcu->max_out_size = usb_endpoint_maxp(pcu->ep_out);
1459 if (pcu->max_out_size < 8) {
1460 dev_err(pcu->dev,
1461 "Max OUT packet size is too small (%zd)\n",
1462 pcu->max_out_size);
1463 return -EINVAL;
1464 }
1465
1466 pcu->ep_in = &alt->endpoint[1].desc;
1467 if (!usb_endpoint_is_bulk_in(pcu->ep_in)) {
1468 dev_err(pcu->dev,
1469 "Second endpoint on data interface is not BULK IN\n");
1470 return -EINVAL;
1471 }
1472
1473 pcu->max_in_size = usb_endpoint_maxp(pcu->ep_in);
1474 if (pcu->max_in_size < 8) {
1475 dev_err(pcu->dev,
1476 "Max IN packet size is too small (%zd)\n",
1477 pcu->max_in_size);
1478 return -EINVAL;
1479 }
1480
1481 return 0;
1482}
1483
1484static int ims_pcu_start_io(struct ims_pcu *pcu)
1485{
1486 int error;
1487
1488 error = usb_submit_urb(pcu->urb_ctrl, GFP_KERNEL);
1489 if (error) {
1490 dev_err(pcu->dev,
1491 "Failed to start control IO - usb_submit_urb failed with result: %d\n",
1492 error);
1493 return -EIO;
1494 }
1495
1496 error = usb_submit_urb(pcu->urb_in, GFP_KERNEL);
1497 if (error) {
1498 dev_err(pcu->dev,
1499 "Failed to start IO - usb_submit_urb failed with result: %d\n",
1500 error);
1501 usb_kill_urb(pcu->urb_ctrl);
1502 return -EIO;
1503 }
1504
1505 return 0;
1506}
1507
1508static void ims_pcu_stop_io(struct ims_pcu *pcu)
1509{
1510 usb_kill_urb(pcu->urb_in);
1511 usb_kill_urb(pcu->urb_ctrl);
1512}
1513
1514static int ims_pcu_line_setup(struct ims_pcu *pcu)
1515{
1516 struct usb_host_interface *interface = pcu->ctrl_intf->cur_altsetting;
1517 struct usb_cdc_line_coding *line = (void *)pcu->cmd_buf;
1518 int error;
1519
1520 memset(line, 0, sizeof(*line));
1521 line->dwDTERate = cpu_to_le32(57600);
1522 line->bDataBits = 8;
1523
1524 error = usb_control_msg(pcu->udev, usb_sndctrlpipe(pcu->udev, 0),
1525 USB_CDC_REQ_SET_LINE_CODING,
1526 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1527 0, interface->desc.bInterfaceNumber,
1528 line, sizeof(struct usb_cdc_line_coding),
1529 5000);
1530 if (error < 0) {
1531 dev_err(pcu->dev, "Failed to set line coding, error: %d\n",
1532 error);
1533 return error;
1534 }
1535
1536 error = usb_control_msg(pcu->udev, usb_sndctrlpipe(pcu->udev, 0),
1537 USB_CDC_REQ_SET_CONTROL_LINE_STATE,
1538 USB_TYPE_CLASS | USB_RECIP_INTERFACE,
1539 0x03, interface->desc.bInterfaceNumber,
1540 NULL, 0, 5000);
1541 if (error < 0) {
1542 dev_err(pcu->dev, "Failed to set line state, error: %d\n",
1543 error);
1544 return error;
1545 }
1546
1547 return 0;
1548}
1549
1550static int ims_pcu_get_device_info(struct ims_pcu *pcu)
1551{
1552 int error;
1553
1554 error = ims_pcu_get_info(pcu);
1555 if (error)
1556 return error;
1557
1558 error = ims_pcu_execute_query(pcu, GET_FW_VERSION);
1559 if (error) {
1560 dev_err(pcu->dev,
1561 "GET_FW_VERSION command failed, error: %d\n", error);
1562 return error;
1563 }
1564
1565 snprintf(pcu->fw_version, sizeof(pcu->fw_version),
1566 "%02d%02d%02d%02d.%c%c",
1567 pcu->cmd_buf[2], pcu->cmd_buf[3], pcu->cmd_buf[4], pcu->cmd_buf[5],
1568 pcu->cmd_buf[6], pcu->cmd_buf[7]);
1569
1570 error = ims_pcu_execute_query(pcu, GET_BL_VERSION);
1571 if (error) {
1572 dev_err(pcu->dev,
1573 "GET_BL_VERSION command failed, error: %d\n", error);
1574 return error;
1575 }
1576
1577 snprintf(pcu->bl_version, sizeof(pcu->bl_version),
1578 "%02d%02d%02d%02d.%c%c",
1579 pcu->cmd_buf[2], pcu->cmd_buf[3], pcu->cmd_buf[4], pcu->cmd_buf[5],
1580 pcu->cmd_buf[6], pcu->cmd_buf[7]);
1581
1582 error = ims_pcu_execute_query(pcu, RESET_REASON);
1583 if (error) {
1584 dev_err(pcu->dev,
1585 "RESET_REASON command failed, error: %d\n", error);
1586 return error;
1587 }
1588
1589 snprintf(pcu->reset_reason, sizeof(pcu->reset_reason),
1590 "%02x", pcu->cmd_buf[IMS_PCU_DATA_OFFSET]);
1591
1592 dev_dbg(pcu->dev,
1593 "P/N: %s, MD: %s, S/N: %s, FW: %s, BL: %s, RR: %s\n",
1594 pcu->part_number,
1595 pcu->date_of_manufacturing,
1596 pcu->serial_number,
1597 pcu->fw_version,
1598 pcu->bl_version,
1599 pcu->reset_reason);
1600
1601 return 0;
1602}
1603
1604static int ims_pcu_identify_type(struct ims_pcu *pcu, u8 *device_id)
1605{
1606 int error;
1607
1608 error = ims_pcu_execute_query(pcu, GET_DEVICE_ID);
1609 if (error) {
1610 dev_err(pcu->dev,
1611 "GET_DEVICE_ID command failed, error: %d\n", error);
1612 return error;
1613 }
1614
1615 *device_id = pcu->cmd_buf[IMS_PCU_DATA_OFFSET];
1616 dev_dbg(pcu->dev, "Detected device ID: %d\n", *device_id);
1617
1618 return 0;
1619}
1620
1621static int ims_pcu_init_application_mode(struct ims_pcu *pcu)
1622{
1623 static atomic_t device_no = ATOMIC_INIT(0);
1624
1625 const struct ims_pcu_device_info *info;
1626 u8 device_id;
1627 int error;
1628
1629 error = ims_pcu_get_device_info(pcu);
1630 if (error) {
1631 /* Device does not respond to basic queries, hopeless */
1632 return error;
1633 }
1634
1635 error = ims_pcu_identify_type(pcu, &device_id);
1636 if (error) {
1637 dev_err(pcu->dev,
1638 "Failed to identify device, error: %d\n", error);
1639 /*
1640 * Do not signal error, but do not create input nor
1641 * backlight devices either, let userspace figure this
1642 * out (flash a new firmware?).
1643 */
1644 return 0;
1645 }
1646
1647 if (device_id >= ARRAY_SIZE(ims_pcu_device_info) ||
1648 !ims_pcu_device_info[device_id].keymap) {
1649 dev_err(pcu->dev, "Device ID %d is not valid\n", device_id);
1650 /* Same as above, punt to userspace */
1651 return 0;
1652 }
1653
1654 /* Device appears to be operable, complete initialization */
1655 pcu->device_no = atomic_inc_return(&device_no) - 1;
1656
1657 error = ims_pcu_setup_backlight(pcu);
1658 if (error)
1659 return error;
1660
1661 info = &ims_pcu_device_info[device_id];
1662 error = ims_pcu_setup_buttons(pcu, info->keymap, info->keymap_len);
1663 if (error)
1664 goto err_destroy_backlight;
1665
1666 if (info->has_gamepad) {
1667 error = ims_pcu_setup_gamepad(pcu);
1668 if (error)
1669 goto err_destroy_buttons;
1670 }
1671
1672 pcu->setup_complete = true;
1673
1674 return 0;
1675
1676err_destroy_backlight:
1677 ims_pcu_destroy_backlight(pcu);
1678err_destroy_buttons:
1679 ims_pcu_destroy_buttons(pcu);
1680 return error;
1681}
1682
1683static void ims_pcu_destroy_application_mode(struct ims_pcu *pcu)
1684{
1685 if (pcu->setup_complete) {
1686 pcu->setup_complete = false;
1687 mb(); /* make sure flag setting is not reordered */
1688
1689 if (pcu->gamepad)
1690 ims_pcu_destroy_gamepad(pcu);
1691 ims_pcu_destroy_buttons(pcu);
1692 ims_pcu_destroy_backlight(pcu);
1693 }
1694}
1695
1696static int ims_pcu_init_bootloader_mode(struct ims_pcu *pcu)
1697{
1698 int error;
1699
1700 error = ims_pcu_execute_bl_command(pcu, QUERY_DEVICE, NULL, 0,
1701 IMS_PCU_CMD_RESPONSE_TIMEOUT);
1702 if (error) {
1703 dev_err(pcu->dev, "Bootloader does not respond, aborting\n");
1704 return error;
1705 }
1706
1707 pcu->fw_start_addr =
1708 get_unaligned_le32(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET + 11]);
1709 pcu->fw_end_addr =
1710 get_unaligned_le32(&pcu->cmd_buf[IMS_PCU_DATA_OFFSET + 15]);
1711
1712 dev_info(pcu->dev,
1713 "Device is in bootloader mode (addr 0x%08x-0x%08x), requesting firmware\n",
1714 pcu->fw_start_addr, pcu->fw_end_addr);
1715
1716 error = request_firmware_nowait(THIS_MODULE, true,
1717 IMS_PCU_FIRMWARE_NAME,
1718 pcu->dev, GFP_KERNEL, pcu,
1719 ims_pcu_process_async_firmware);
1720 if (error) {
1721 /* This error is not fatal, let userspace have another chance */
1722 complete(&pcu->async_firmware_done);
1723 }
1724
1725 return 0;
1726}
1727
1728static void ims_pcu_destroy_bootloader_mode(struct ims_pcu *pcu)
1729{
1730 /* Make sure our initial firmware request has completed */
1731 wait_for_completion(&pcu->async_firmware_done);
1732}
1733
1734#define IMS_PCU_APPLICATION_MODE 0
1735#define IMS_PCU_BOOTLOADER_MODE 1
1736
1737static struct usb_driver ims_pcu_driver;
1738
1739static int ims_pcu_probe(struct usb_interface *intf,
1740 const struct usb_device_id *id)
1741{
1742 struct usb_device *udev = interface_to_usbdev(intf);
1743 struct ims_pcu *pcu;
1744 int error;
1745
1746 pcu = kzalloc(sizeof(struct ims_pcu), GFP_KERNEL);
1747 if (!pcu)
1748 return -ENOMEM;
1749
1750 pcu->dev = &intf->dev;
1751 pcu->udev = udev;
1752 pcu->bootloader_mode = id->driver_info == IMS_PCU_BOOTLOADER_MODE;
1753 mutex_init(&pcu->cmd_mutex);
1754 init_completion(&pcu->cmd_done);
1755 init_completion(&pcu->async_firmware_done);
1756
1757 error = ims_pcu_parse_cdc_data(intf, pcu);
1758 if (error)
1759 goto err_free_mem;
1760
1761 error = usb_driver_claim_interface(&ims_pcu_driver,
1762 pcu->data_intf, pcu);
1763 if (error) {
1764 dev_err(&intf->dev,
1765 "Unable to claim corresponding data interface: %d\n",
1766 error);
1767 goto err_free_mem;
1768 }
1769
1770 usb_set_intfdata(pcu->ctrl_intf, pcu);
1771 usb_set_intfdata(pcu->data_intf, pcu);
1772
1773 error = ims_pcu_buffers_alloc(pcu);
1774 if (error)
1775 goto err_unclaim_intf;
1776
1777 error = ims_pcu_start_io(pcu);
1778 if (error)
1779 goto err_free_buffers;
1780
1781 error = ims_pcu_line_setup(pcu);
1782 if (error)
1783 goto err_stop_io;
1784
1785 error = sysfs_create_group(&intf->dev.kobj, &ims_pcu_attr_group);
1786 if (error)
1787 goto err_stop_io;
1788
1789 error = pcu->bootloader_mode ?
1790 ims_pcu_init_bootloader_mode(pcu) :
1791 ims_pcu_init_application_mode(pcu);
1792 if (error)
1793 goto err_remove_sysfs;
1794
1795 return 0;
1796
1797err_remove_sysfs:
1798 sysfs_remove_group(&intf->dev.kobj, &ims_pcu_attr_group);
1799err_stop_io:
1800 ims_pcu_stop_io(pcu);
1801err_free_buffers:
1802 ims_pcu_buffers_free(pcu);
1803err_unclaim_intf:
1804 usb_driver_release_interface(&ims_pcu_driver, pcu->data_intf);
1805err_free_mem:
1806 kfree(pcu);
1807 return error;
1808}
1809
1810static void ims_pcu_disconnect(struct usb_interface *intf)
1811{
1812 struct ims_pcu *pcu = usb_get_intfdata(intf);
1813 struct usb_host_interface *alt = intf->cur_altsetting;
1814
1815 usb_set_intfdata(intf, NULL);
1816
1817 /*
1818 * See if we are dealing with control or data interface. The cleanup
1819 * happens when we unbind primary (control) interface.
1820 */
1821 if (alt->desc.bInterfaceClass != USB_CLASS_COMM)
1822 return;
1823
1824 sysfs_remove_group(&intf->dev.kobj, &ims_pcu_attr_group);
1825
1826 ims_pcu_stop_io(pcu);
1827
1828 if (pcu->bootloader_mode)
1829 ims_pcu_destroy_bootloader_mode(pcu);
1830 else
1831 ims_pcu_destroy_application_mode(pcu);
1832
1833 ims_pcu_buffers_free(pcu);
1834 kfree(pcu);
1835}
1836
1837#ifdef CONFIG_PM
1838static int ims_pcu_suspend(struct usb_interface *intf,
1839 pm_message_t message)
1840{
1841 struct ims_pcu *pcu = usb_get_intfdata(intf);
1842 struct usb_host_interface *alt = intf->cur_altsetting;
1843
1844 if (alt->desc.bInterfaceClass == USB_CLASS_COMM)
1845 ims_pcu_stop_io(pcu);
1846
1847 return 0;
1848}
1849
1850static int ims_pcu_resume(struct usb_interface *intf)
1851{
1852 struct ims_pcu *pcu = usb_get_intfdata(intf);
1853 struct usb_host_interface *alt = intf->cur_altsetting;
1854 int retval = 0;
1855
1856 if (alt->desc.bInterfaceClass == USB_CLASS_COMM) {
1857 retval = ims_pcu_start_io(pcu);
1858 if (retval == 0)
1859 retval = ims_pcu_line_setup(pcu);
1860 }
1861
1862 return retval;
1863}
1864#endif
1865
1866static const struct usb_device_id ims_pcu_id_table[] = {
1867 {
1868 USB_DEVICE_AND_INTERFACE_INFO(0x04d8, 0x0082,
1869 USB_CLASS_COMM,
1870 USB_CDC_SUBCLASS_ACM,
1871 USB_CDC_ACM_PROTO_AT_V25TER),
1872 .driver_info = IMS_PCU_APPLICATION_MODE,
1873 },
1874 {
1875 USB_DEVICE_AND_INTERFACE_INFO(0x04d8, 0x0083,
1876 USB_CLASS_COMM,
1877 USB_CDC_SUBCLASS_ACM,
1878 USB_CDC_ACM_PROTO_AT_V25TER),
1879 .driver_info = IMS_PCU_BOOTLOADER_MODE,
1880 },
1881 { }
1882};
1883
1884static struct usb_driver ims_pcu_driver = {
1885 .name = "ims_pcu",
1886 .id_table = ims_pcu_id_table,
1887 .probe = ims_pcu_probe,
1888 .disconnect = ims_pcu_disconnect,
1889#ifdef CONFIG_PM
1890 .suspend = ims_pcu_suspend,
1891 .resume = ims_pcu_resume,
1892 .reset_resume = ims_pcu_resume,
1893#endif
1894};
1895
1896module_usb_driver(ims_pcu_driver);
1897
1898MODULE_DESCRIPTION("IMS Passenger Control Unit driver");
1899MODULE_AUTHOR("Dmitry Torokhov <dmitry.torokhov@gmail.com>");
1900MODULE_LICENSE("GPL");