blob: 13953dd4989e3fbb8c458d047d2de5a0f1468000 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* arch/arm/mach-msm/rpc_server_handset.c
2 *
Duy Truong790f06d2013-02-13 16:38:12 -08003 * Copyright (c) 2008-2010,2012 The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07004 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 and
7 * only version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/slab.h>
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/platform_device.h>
19#include <linux/input.h>
20#include <linux/switch.h>
21
22#include <asm/mach-types.h>
23
24#include <mach/msm_rpcrouter.h>
25#include <mach/board.h>
26#include <mach/rpc_server_handset.h>
27
28#define DRIVER_NAME "msm-handset"
29
30#define HS_SERVER_PROG 0x30000062
31#define HS_SERVER_VERS 0x00010001
32
33#define HS_RPC_PROG 0x30000091
34
35#define HS_PROCESS_CMD_PROC 0x02
36#define HS_SUBSCRIBE_SRVC_PROC 0x03
37#define HS_REPORT_EVNT_PROC 0x05
38#define HS_EVENT_CB_PROC 1
39#define HS_EVENT_DATA_VER 1
40
41#define RPC_KEYPAD_NULL_PROC 0
42#define RPC_KEYPAD_PASS_KEY_CODE_PROC 2
43#define RPC_KEYPAD_SET_PWR_KEY_STATE_PROC 3
44
45#define HS_PWR_K 0x6F /* Power key */
46#define HS_END_K 0x51 /* End key or Power key */
47#define HS_STEREO_HEADSET_K 0x82
48#define HS_HEADSET_SWITCH_K 0x84
49#define HS_HEADSET_SWITCH_2_K 0xF0
50#define HS_HEADSET_SWITCH_3_K 0xF1
51#define HS_HEADSET_HEADPHONE_K 0xF6
52#define HS_HEADSET_MICROPHONE_K 0xF7
53#define HS_REL_K 0xFF /* key release */
54
55#define SW_HEADPHONE_INSERT_W_MIC 1 /* HS with mic */
56
57#define KEY(hs_key, input_key) ((hs_key << 24) | input_key)
58
59enum hs_event {
60 HS_EVNT_EXT_PWR = 0, /* External Power status */
61 HS_EVNT_HSD, /* Headset Detection */
62 HS_EVNT_HSTD, /* Headset Type Detection */
63 HS_EVNT_HSSD, /* Headset Switch Detection */
64 HS_EVNT_KPD,
65 HS_EVNT_FLIP, /* Flip / Clamshell status (open/close) */
66 HS_EVNT_CHARGER, /* Battery is being charged or not */
67 HS_EVNT_ENV, /* Events from runtime environment like DEM */
68 HS_EVNT_REM, /* Events received from HS counterpart on a
69 remote processor*/
70 HS_EVNT_DIAG, /* Diag Events */
71 HS_EVNT_LAST, /* Should always be the last event type */
72 HS_EVNT_MAX /* Force enum to be an 32-bit number */
73};
74
75enum hs_src_state {
76 HS_SRC_STATE_UNKWN = 0,
77 HS_SRC_STATE_LO,
78 HS_SRC_STATE_HI,
79};
80
81struct hs_event_data {
82 uint32_t ver; /* Version number */
83 enum hs_event event_type; /* Event Type */
84 enum hs_event enum_disc; /* discriminator */
85 uint32_t data_length; /* length of the next field */
86 enum hs_src_state data; /* Pointer to data */
87 uint32_t data_size; /* Elements to be processed in data */
88};
89
90enum hs_return_value {
91 HS_EKPDLOCKED = -2, /* Operation failed because keypad is locked */
92 HS_ENOTSUPPORTED = -1, /* Functionality not supported */
93 HS_FALSE = 0, /* Inquired condition is not true */
94 HS_FAILURE = 0, /* Requested operation was not successful */
95 HS_TRUE = 1, /* Inquired condition is true */
96 HS_SUCCESS = 1, /* Requested operation was successful */
97 HS_MAX_RETURN = 0x7FFFFFFF/* Force enum to be a 32 bit number */
98};
99
100struct hs_key_data {
101 uint32_t ver; /* Version number to track sturcture changes */
102 uint32_t code; /* which key? */
103 uint32_t parm; /* key status. Up/down or pressed/released */
104};
105
106enum hs_subs_srvc {
107 HS_SUBS_SEND_CMD = 0, /* Subscribe to send commands to HS */
108 HS_SUBS_RCV_EVNT, /* Subscribe to receive Events from HS */
109 HS_SUBS_SRVC_MAX
110};
111
112enum hs_subs_req {
113 HS_SUBS_REGISTER, /* Subscribe */
114 HS_SUBS_CANCEL, /* Unsubscribe */
115 HS_SUB_STATUS_MAX
116};
117
118enum hs_event_class {
119 HS_EVNT_CLASS_ALL = 0, /* All HS events */
120 HS_EVNT_CLASS_LAST, /* Should always be the last class type */
121 HS_EVNT_CLASS_MAX
122};
123
124enum hs_cmd_class {
125 HS_CMD_CLASS_LCD = 0, /* Send LCD related commands */
126 HS_CMD_CLASS_KPD, /* Send KPD related commands */
127 HS_CMD_CLASS_LAST, /* Should always be the last class type */
128 HS_CMD_CLASS_MAX
129};
130
131/*
132 * Receive events or send command
133 */
134union hs_subs_class {
135 enum hs_event_class evnt;
136 enum hs_cmd_class cmd;
137};
138
139struct hs_subs {
140 uint32_t ver;
141 enum hs_subs_srvc srvc; /* commands or events */
142 enum hs_subs_req req; /* subscribe or unsubscribe */
143 uint32_t host_os;
144 enum hs_subs_req disc; /* discriminator */
145 union hs_subs_class id;
146};
147
148struct hs_event_cb_recv {
149 uint32_t cb_id;
150 uint32_t hs_key_data_ptr;
151 struct hs_key_data key;
152};
153enum hs_ext_cmd_type {
154 HS_EXT_CMD_KPD_SEND_KEY = 0, /* Send Key */
155 HS_EXT_CMD_KPD_BKLT_CTRL, /* Keypad backlight intensity */
156 HS_EXT_CMD_LCD_BKLT_CTRL, /* LCD Backlight intensity */
157 HS_EXT_CMD_DIAG_KEYMAP, /* Emulating a Diag key sequence */
158 HS_EXT_CMD_DIAG_LOCK, /* Device Lock/Unlock */
159 HS_EXT_CMD_GET_EVNT_STATUS, /* Get the status for one of the drivers */
160 HS_EXT_CMD_KPD_GET_KEYS_STATUS,/* Get a list of keys status */
161 HS_EXT_CMD_KPD_SET_PWR_KEY_RST_THOLD, /* PWR Key HW Reset duration */
162 HS_EXT_CMD_KPD_SET_PWR_KEY_THOLD, /* Set pwr key threshold duration */
163 HS_EXT_CMD_LAST, /* Should always be the last command type */
164 HS_EXT_CMD_MAX = 0x7FFFFFFF /* Force enum to be an 32-bit number */
165};
166
167struct hs_cmd_data_type {
168 uint32_t hs_cmd_data_type_ptr; /* hs_cmd_data_type ptr length */
169 uint32_t ver; /* version */
170 enum hs_ext_cmd_type id; /* command id */
171 uint32_t handle; /* handle returned from subscribe proc */
172 enum hs_ext_cmd_type disc_id1; /* discriminator id */
173 uint32_t input_ptr; /* input ptr length */
174 uint32_t input_val; /* command specific data */
175 uint32_t input_len; /* length of command input */
176 enum hs_ext_cmd_type disc_id2; /* discriminator id */
177 uint32_t output_len; /* length of output data */
178 uint32_t delayed; /* execution context for modem
179 true - caller context
180 false - hs task context*/
181};
182
183static const uint32_t hs_key_map[] = {
184 KEY(HS_PWR_K, KEY_POWER),
185 KEY(HS_END_K, KEY_END),
186 KEY(HS_STEREO_HEADSET_K, SW_HEADPHONE_INSERT_W_MIC),
187 KEY(HS_HEADSET_HEADPHONE_K, SW_HEADPHONE_INSERT),
188 KEY(HS_HEADSET_MICROPHONE_K, SW_MICROPHONE_INSERT),
189 KEY(HS_HEADSET_SWITCH_K, KEY_MEDIA),
190 KEY(HS_HEADSET_SWITCH_2_K, KEY_VOLUMEUP),
191 KEY(HS_HEADSET_SWITCH_3_K, KEY_VOLUMEDOWN),
192 0
193};
194
195enum {
196 NO_DEVICE = 0,
197 MSM_HEADSET = 1,
198};
199/* Add newer versions at the top of array */
200static const unsigned int rpc_vers[] = {
201 0x00030001,
202 0x00020001,
203 0x00010001,
204};
205/* hs subscription request parameters */
206struct hs_subs_rpc_req {
207 uint32_t hs_subs_ptr;
208 struct hs_subs hs_subs;
209 uint32_t hs_cb_id;
210 uint32_t hs_handle_ptr;
211 uint32_t hs_handle_data;
212};
213
214static struct hs_subs_rpc_req *hs_subs_req;
215
216struct msm_handset {
217 struct input_dev *ipdev;
218 struct switch_dev sdev;
219 struct msm_handset_platform_data *hs_pdata;
220 bool mic_on, hs_on;
221};
222
223static struct msm_rpc_client *rpc_client;
224static struct msm_handset *hs;
225
226static int hs_find_key(uint32_t hscode)
227{
228 int i, key;
229
230 key = KEY(hscode, 0);
231
232 for (i = 0; hs_key_map[i] != 0; i++) {
233 if ((hs_key_map[i] & 0xff000000) == key)
234 return hs_key_map[i] & 0x00ffffff;
235 }
236 return -1;
237}
238
239static void update_state(void)
240{
241 int state;
242
243 if (hs->mic_on && hs->hs_on)
244 state = 1 << 0;
245 else if (hs->hs_on)
246 state = 1 << 1;
247 else if (hs->mic_on)
248 state = 1 << 2;
249 else
250 state = 0;
251
252 switch_set_state(&hs->sdev, state);
253}
254
255/*
256 * tuple format: (key_code, key_param)
257 *
258 * old-architecture:
259 * key-press = (key_code, 0)
260 * key-release = (0xff, key_code)
261 *
262 * new-architecutre:
263 * key-press = (key_code, 0)
264 * key-release = (key_code, 0xff)
265 */
266static void report_hs_key(uint32_t key_code, uint32_t key_parm)
267{
268 int key, temp_key_code;
269
270 if (key_code == HS_REL_K)
271 key = hs_find_key(key_parm);
272 else
273 key = hs_find_key(key_code);
274
275 temp_key_code = key_code;
276
277 if (key_parm == HS_REL_K)
278 key_code = key_parm;
279
280 switch (key) {
281 case KEY_POWER:
282 case KEY_END:
Mohan Pallaka902ffda2012-12-04 22:35:43 +0530283 if (hs->hs_pdata->ignore_end_key)
284 input_report_key(hs->ipdev, KEY_POWER,
285 (key_code != HS_REL_K));
286 else
287 input_report_key(hs->ipdev, key,
288 (key_code != HS_REL_K));
289 break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290 case KEY_MEDIA:
291 case KEY_VOLUMEUP:
292 case KEY_VOLUMEDOWN:
293 input_report_key(hs->ipdev, key, (key_code != HS_REL_K));
294 break;
295 case SW_HEADPHONE_INSERT_W_MIC:
296 hs->mic_on = hs->hs_on = (key_code != HS_REL_K) ? 1 : 0;
297 input_report_switch(hs->ipdev, SW_HEADPHONE_INSERT,
298 hs->hs_on);
299 input_report_switch(hs->ipdev, SW_MICROPHONE_INSERT,
300 hs->mic_on);
301 update_state();
302 break;
303
304 case SW_HEADPHONE_INSERT:
305 hs->hs_on = (key_code != HS_REL_K) ? 1 : 0;
306 input_report_switch(hs->ipdev, key, hs->hs_on);
307 update_state();
308 break;
309 case SW_MICROPHONE_INSERT:
310 hs->mic_on = (key_code != HS_REL_K) ? 1 : 0;
311 input_report_switch(hs->ipdev, key, hs->mic_on);
312 update_state();
313 break;
314 case -1:
315 printk(KERN_ERR "%s: No mapping for remote handset event %d\n",
316 __func__, temp_key_code);
317 return;
318 }
319 input_sync(hs->ipdev);
320}
321
322static int handle_hs_rpc_call(struct msm_rpc_server *server,
323 struct rpc_request_hdr *req, unsigned len)
324{
325 struct rpc_keypad_pass_key_code_args {
326 uint32_t key_code;
327 uint32_t key_parm;
328 };
329
330 switch (req->procedure) {
331 case RPC_KEYPAD_NULL_PROC:
332 return 0;
333
334 case RPC_KEYPAD_PASS_KEY_CODE_PROC: {
335 struct rpc_keypad_pass_key_code_args *args;
336
337 args = (struct rpc_keypad_pass_key_code_args *)(req + 1);
338 args->key_code = be32_to_cpu(args->key_code);
339 args->key_parm = be32_to_cpu(args->key_parm);
340
341 report_hs_key(args->key_code, args->key_parm);
342
343 return 0;
344 }
345
346 case RPC_KEYPAD_SET_PWR_KEY_STATE_PROC:
347 /* This RPC function must be available for the ARM9
348 * to function properly. This function is redundant
349 * when RPC_KEYPAD_PASS_KEY_CODE_PROC is handled. So
350 * input_report_key is not needed.
351 */
352 return 0;
353 default:
354 return -ENODEV;
355 }
356}
357
358static struct msm_rpc_server hs_rpc_server = {
359 .prog = HS_SERVER_PROG,
360 .vers = HS_SERVER_VERS,
361 .rpc_call = handle_hs_rpc_call,
362};
363
364static int process_subs_srvc_callback(struct hs_event_cb_recv *recv)
365{
366 if (!recv)
367 return -ENODATA;
368
369 report_hs_key(be32_to_cpu(recv->key.code), be32_to_cpu(recv->key.parm));
370
371 return 0;
372}
373
374static void process_hs_rpc_request(uint32_t proc, void *data)
375{
376 if (proc == HS_EVENT_CB_PROC)
377 process_subs_srvc_callback(data);
378 else
379 pr_err("%s: unknown rpc proc %d\n", __func__, proc);
380}
381
382static int hs_rpc_report_event_arg(struct msm_rpc_client *client,
383 void *buffer, void *data)
384{
385 struct hs_event_rpc_req {
386 uint32_t hs_event_data_ptr;
387 struct hs_event_data data;
388 };
389
390 struct hs_event_rpc_req *req = buffer;
391
392 req->hs_event_data_ptr = cpu_to_be32(0x1);
393 req->data.ver = cpu_to_be32(HS_EVENT_DATA_VER);
394 req->data.event_type = cpu_to_be32(HS_EVNT_HSD);
395 req->data.enum_disc = cpu_to_be32(HS_EVNT_HSD);
396 req->data.data_length = cpu_to_be32(0x1);
397 req->data.data = cpu_to_be32(*(enum hs_src_state *)data);
398 req->data.data_size = cpu_to_be32(sizeof(enum hs_src_state));
399
400 return sizeof(*req);
401}
402
403static int hs_rpc_report_event_res(struct msm_rpc_client *client,
404 void *buffer, void *data)
405{
406 enum hs_return_value result;
407
408 result = be32_to_cpu(*(enum hs_return_value *)buffer);
409 pr_debug("%s: request completed: 0x%x\n", __func__, result);
410
411 if (result == HS_SUCCESS)
412 return 0;
413
414 return 1;
415}
416
417void report_headset_status(bool connected)
418{
419 int rc = -1;
420 enum hs_src_state status;
421
422 if (connected == true)
423 status = HS_SRC_STATE_HI;
424 else
425 status = HS_SRC_STATE_LO;
426
427 rc = msm_rpc_client_req(rpc_client, HS_REPORT_EVNT_PROC,
428 hs_rpc_report_event_arg, &status,
429 hs_rpc_report_event_res, NULL, -1);
430
431 if (rc)
432 pr_err("%s: couldn't send rpc client request\n", __func__);
433}
434EXPORT_SYMBOL(report_headset_status);
435
436static int hs_rpc_pwr_cmd_arg(struct msm_rpc_client *client,
437 void *buffer, void *data)
438{
439 struct hs_cmd_data_type *hs_pwr_cmd = buffer;
440
441 hs_pwr_cmd->hs_cmd_data_type_ptr = cpu_to_be32(0x01);
442
443 hs_pwr_cmd->ver = cpu_to_be32(0x03);
444 hs_pwr_cmd->id = cpu_to_be32(HS_EXT_CMD_KPD_SET_PWR_KEY_THOLD);
445 hs_pwr_cmd->handle = cpu_to_be32(hs_subs_req->hs_handle_data);
446 hs_pwr_cmd->disc_id1 = cpu_to_be32(HS_EXT_CMD_KPD_SET_PWR_KEY_THOLD);
447 hs_pwr_cmd->input_ptr = cpu_to_be32(0x01);
448 hs_pwr_cmd->input_val = cpu_to_be32(hs->hs_pdata->pwr_key_delay_ms);
449 hs_pwr_cmd->input_len = cpu_to_be32(0x01);
450 hs_pwr_cmd->disc_id2 = cpu_to_be32(HS_EXT_CMD_KPD_SET_PWR_KEY_THOLD);
451 hs_pwr_cmd->output_len = cpu_to_be32(0x00);
452 hs_pwr_cmd->delayed = cpu_to_be32(0x00);
453
454 return sizeof(*hs_pwr_cmd);
455}
456
457static int hs_rpc_pwr_cmd_res(struct msm_rpc_client *client,
458 void *buffer, void *data)
459{
460 uint32_t result;
461
462 result = be32_to_cpu(*((uint32_t *)buffer));
463 pr_debug("%s: request completed: 0x%x\n", __func__, result);
464
465 return 0;
466}
467
468static int hs_rpc_register_subs_arg(struct msm_rpc_client *client,
469 void *buffer, void *data)
470{
471 hs_subs_req = buffer;
472
473 hs_subs_req->hs_subs_ptr = cpu_to_be32(0x1);
474 hs_subs_req->hs_subs.ver = cpu_to_be32(0x1);
475 hs_subs_req->hs_subs.srvc = cpu_to_be32(HS_SUBS_RCV_EVNT);
476 hs_subs_req->hs_subs.req = cpu_to_be32(HS_SUBS_REGISTER);
477 hs_subs_req->hs_subs.host_os = cpu_to_be32(0x4); /* linux */
478 hs_subs_req->hs_subs.disc = cpu_to_be32(HS_SUBS_RCV_EVNT);
479 hs_subs_req->hs_subs.id.evnt = cpu_to_be32(HS_EVNT_CLASS_ALL);
480
481 hs_subs_req->hs_cb_id = cpu_to_be32(0x1);
482
483 hs_subs_req->hs_handle_ptr = cpu_to_be32(0x1);
484 hs_subs_req->hs_handle_data = cpu_to_be32(0x0);
485
486 return sizeof(*hs_subs_req);
487}
488
489static int hs_rpc_register_subs_res(struct msm_rpc_client *client,
490 void *buffer, void *data)
491{
492 uint32_t result;
493
494 result = be32_to_cpu(*((uint32_t *)buffer));
495 pr_debug("%s: request completed: 0x%x\n", __func__, result);
496
497 return 0;
498}
499
500static int hs_cb_func(struct msm_rpc_client *client, void *buffer, int in_size)
501{
502 int rc = -1;
503
504 struct rpc_request_hdr *hdr = buffer;
505
506 hdr->type = be32_to_cpu(hdr->type);
507 hdr->xid = be32_to_cpu(hdr->xid);
508 hdr->rpc_vers = be32_to_cpu(hdr->rpc_vers);
509 hdr->prog = be32_to_cpu(hdr->prog);
510 hdr->vers = be32_to_cpu(hdr->vers);
511 hdr->procedure = be32_to_cpu(hdr->procedure);
512
513 process_hs_rpc_request(hdr->procedure,
514 (void *) (hdr + 1));
515
516 msm_rpc_start_accepted_reply(client, hdr->xid,
517 RPC_ACCEPTSTAT_SUCCESS);
518 rc = msm_rpc_send_accepted_reply(client, 0);
519 if (rc) {
520 pr_err("%s: sending reply failed: %d\n", __func__, rc);
521 return rc;
522 }
523
524 return 0;
525}
526
Stephen Boyd24db6432012-04-25 11:40:08 -0700527static int __devinit hs_rpc_cb_init(void)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700528{
529 int rc = 0, i, num_vers;
530
531 num_vers = ARRAY_SIZE(rpc_vers);
532
533 for (i = 0; i < num_vers; i++) {
534 rpc_client = msm_rpc_register_client("hs",
535 HS_RPC_PROG, rpc_vers[i], 0, hs_cb_func);
536
537 if (IS_ERR(rpc_client))
538 pr_debug("%s: RPC Client version %d failed, fallback\n",
539 __func__, rpc_vers[i]);
540 else
541 break;
542 }
543
544 if (IS_ERR(rpc_client)) {
545 pr_err("%s: Incompatible RPC version error %ld\n",
546 __func__, PTR_ERR(rpc_client));
547 return PTR_ERR(rpc_client);
548 }
549
550 rc = msm_rpc_client_req(rpc_client, HS_SUBSCRIBE_SRVC_PROC,
551 hs_rpc_register_subs_arg, NULL,
552 hs_rpc_register_subs_res, NULL, -1);
553 if (rc) {
554 pr_err("%s: RPC client request failed for subscribe services\n",
555 __func__);
556 goto err_client_req;
557 }
558
559 rc = msm_rpc_client_req(rpc_client, HS_PROCESS_CMD_PROC,
560 hs_rpc_pwr_cmd_arg, NULL,
561 hs_rpc_pwr_cmd_res, NULL, -1);
562 if (rc)
563 pr_err("%s: RPC client request failed for pwr key"
564 " delay cmd, using normal mode\n", __func__);
565 return 0;
566err_client_req:
567 msm_rpc_unregister_client(rpc_client);
568 return rc;
569}
570
571static int __devinit hs_rpc_init(void)
572{
573 int rc;
574
575 rc = hs_rpc_cb_init();
576 if (rc) {
577 pr_err("%s: failed to initialize rpc client, try server...\n",
578 __func__);
579
580 rc = msm_rpc_create_server(&hs_rpc_server);
581 if (rc) {
582 pr_err("%s: failed to create rpc server\n", __func__);
583 return rc;
584 }
585 }
586
587 return rc;
588}
589
590static void __devexit hs_rpc_deinit(void)
591{
592 if (rpc_client)
593 msm_rpc_unregister_client(rpc_client);
594}
595
596static ssize_t msm_headset_print_name(struct switch_dev *sdev, char *buf)
597{
598 switch (switch_get_state(&hs->sdev)) {
599 case NO_DEVICE:
600 return sprintf(buf, "No Device\n");
601 case MSM_HEADSET:
602 return sprintf(buf, "Headset\n");
603 }
604 return -EINVAL;
605}
606
607static int __devinit hs_probe(struct platform_device *pdev)
608{
609 int rc = 0;
610 struct input_dev *ipdev;
611
612 hs = kzalloc(sizeof(struct msm_handset), GFP_KERNEL);
613 if (!hs)
614 return -ENOMEM;
615
616 hs->sdev.name = "h2w";
617 hs->sdev.print_name = msm_headset_print_name;
618
619 rc = switch_dev_register(&hs->sdev);
620 if (rc)
621 goto err_switch_dev_register;
622
623 ipdev = input_allocate_device();
624 if (!ipdev) {
625 rc = -ENOMEM;
626 goto err_alloc_input_dev;
627 }
628 input_set_drvdata(ipdev, hs);
629
630 hs->ipdev = ipdev;
631
632 if (pdev->dev.platform_data)
633 hs->hs_pdata = pdev->dev.platform_data;
634
635 if (hs->hs_pdata->hs_name)
636 ipdev->name = hs->hs_pdata->hs_name;
637 else
638 ipdev->name = DRIVER_NAME;
639
640 ipdev->id.vendor = 0x0001;
641 ipdev->id.product = 1;
642 ipdev->id.version = 1;
643
644 input_set_capability(ipdev, EV_KEY, KEY_MEDIA);
645 input_set_capability(ipdev, EV_KEY, KEY_VOLUMEUP);
646 input_set_capability(ipdev, EV_KEY, KEY_VOLUMEDOWN);
647 input_set_capability(ipdev, EV_SW, SW_HEADPHONE_INSERT);
648 input_set_capability(ipdev, EV_SW, SW_MICROPHONE_INSERT);
649 input_set_capability(ipdev, EV_KEY, KEY_POWER);
650 input_set_capability(ipdev, EV_KEY, KEY_END);
651
652 rc = input_register_device(ipdev);
653 if (rc) {
654 dev_err(&ipdev->dev,
655 "hs_probe: input_register_device rc=%d\n", rc);
656 goto err_reg_input_dev;
657 }
658
659 platform_set_drvdata(pdev, hs);
660
661 rc = hs_rpc_init();
662 if (rc) {
663 dev_err(&ipdev->dev, "rpc init failure\n");
664 goto err_hs_rpc_init;
665 }
666
667 return 0;
668
669err_hs_rpc_init:
670 input_unregister_device(ipdev);
671 ipdev = NULL;
672err_reg_input_dev:
673 input_free_device(ipdev);
674err_alloc_input_dev:
675 switch_dev_unregister(&hs->sdev);
676err_switch_dev_register:
677 kfree(hs);
678 return rc;
679}
680
681static int __devexit hs_remove(struct platform_device *pdev)
682{
683 struct msm_handset *hs = platform_get_drvdata(pdev);
684
685 input_unregister_device(hs->ipdev);
686 switch_dev_unregister(&hs->sdev);
687 kfree(hs);
688 hs_rpc_deinit();
689 return 0;
690}
691
692static struct platform_driver hs_driver = {
693 .probe = hs_probe,
694 .remove = __devexit_p(hs_remove),
695 .driver = {
696 .name = DRIVER_NAME,
697 .owner = THIS_MODULE,
698 },
699};
700
701static int __init hs_init(void)
702{
703 return platform_driver_register(&hs_driver);
704}
705late_initcall(hs_init);
706
707static void __exit hs_exit(void)
708{
709 platform_driver_unregister(&hs_driver);
710}
711module_exit(hs_exit);
712
713MODULE_LICENSE("GPL v2");
714MODULE_ALIAS("platform:msm-handset");