rmi_f19.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. /**
  2. *
  3. * Synaptics Register Mapped Interface (RMI4) Function $11 support for 2D.
  4. * Copyright (c) 2007 - 2011, Synaptics Incorporated
  5. *
  6. */
  7. /*
  8. * This file is licensed under the GPL2 license.
  9. *
  10. *#############################################################################
  11. * GPL
  12. *
  13. * This program is free software; you can redistribute it and/or modify it
  14. * under the terms of the GNU General Public License version 2 as published
  15. * by the Free Software Foundation.
  16. *
  17. * This program is distributed in the hope that it will be useful, but
  18. * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  19. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  20. * for more details.
  21. *
  22. *#############################################################################
  23. */
  24. #include <linux/kernel.h>
  25. #include <linux/device.h>
  26. #include <linux/delay.h>
  27. #include <linux/kthread.h>
  28. #include <linux/freezer.h>
  29. #include <linux/input.h>
  30. #include <linux/slab.h>
  31. #include <linux/input/rmi_platformdata.h>
  32. #include <linux/module.h>
  33. #include "rmi.h"
  34. #include "rmi_drvr.h"
  35. #include "rmi_bus.h"
  36. #include "rmi_sensor.h"
  37. #include "rmi_function.h"
  38. #include "rmi_f19.h"
  39. struct f19_instance_data {
  40. struct rmi_F19_query *deviceInfo;
  41. struct rmi_F19_control *controlRegisters;
  42. bool *buttonDown;
  43. unsigned char buttonDataBufferSize;
  44. unsigned char *buttonDataBuffer;
  45. unsigned char *buttonMap;
  46. int fn19ControlRegisterSize;
  47. int fn19regCountForBitPerButton;
  48. int fn19btnUsageandfilterModeOffset;
  49. int fn19intEnableOffset;
  50. int fn19intEnableLen;
  51. int fn19singleBtnCtrlLen;
  52. int fn19singleBtnCtrlOffset;
  53. int fn19sensorMapCtrlOffset;
  54. int fn19sensorMapCtrlLen;
  55. int fn19singleBtnSensOffset;
  56. int fn19singleBtnSensLen;
  57. int fn19globalSensOffset;
  58. int fn19globalHystThreshOffset;
  59. };
  60. static ssize_t rmi_f19_buttonCount_show(struct device *dev,
  61. struct device_attribute *attr, char *buf);
  62. static ssize_t rmi_f19_buttonCount_store(struct device *dev,
  63. struct device_attribute *attr,
  64. const char *buf, size_t count);
  65. DEVICE_ATTR(buttonCount, 0444, rmi_f19_buttonCount_show, rmi_f19_buttonCount_store); /* RO attr */
  66. static ssize_t rmi_f19_buttonMap_show(struct device *dev,
  67. struct device_attribute *attr, char *buf);
  68. static ssize_t rmi_f19_buttonMap_store(struct device *dev,
  69. struct device_attribute *attr,
  70. const char *buf, size_t count);
  71. DEVICE_ATTR(buttonMap, 0664, rmi_f19_buttonMap_show, rmi_f19_buttonMap_store); /* RW attr */
  72. /*
  73. * There is no attention function for F19 - it is left NULL
  74. * in the function table so it is not called.
  75. *
  76. */
  77. /*
  78. * This reads in a sample and reports the F19 source data to the
  79. * input subsystem. It is used for both polling and interrupt driven
  80. * operation. This is called a lot so don't put in any informational
  81. * printks since they will slow things way down!
  82. */
  83. void FN_19_inthandler(struct rmi_function_info *rmifninfo,
  84. unsigned int assertedIRQs)
  85. {
  86. struct rmi_function_device *function_device;
  87. struct f19_instance_data *instanceData;
  88. int button;
  89. instanceData = (struct f19_instance_data *) rmifninfo->fndata;
  90. function_device = rmifninfo->function_device;
  91. /* Read the button data. */
  92. if (rmi_read_multiple(rmifninfo->sensor, rmifninfo->funcDescriptor.dataBaseAddr,
  93. instanceData->buttonDataBuffer, instanceData->buttonDataBufferSize)) {
  94. printk(KERN_ERR "%s: Failed to read button data registers.\n", __func__);
  95. return;
  96. }
  97. /* Generate events for buttons that change state. */
  98. for (button = 0; button < instanceData->deviceInfo->buttonCount; button++) {
  99. int buttonReg;
  100. int buttonShift;
  101. bool buttonStatus;
  102. /* determine which data byte the button status is in */
  103. buttonReg = button/4;
  104. /* bit shift to get button's status */
  105. buttonShift = button % 8;
  106. buttonStatus = ((instanceData->buttonDataBuffer[buttonReg] >> buttonShift) & 0x01) != 0;
  107. /* if the button state changed from the last time report it and store the new state */
  108. if (buttonStatus != instanceData->buttonDown[button]) {
  109. printk(KERN_DEBUG "%s: Button %d (code %d) -> %d.", __func__, button, instanceData->buttonMap[button], buttonStatus);
  110. /* Generate an event here. */
  111. input_report_key(function_device->input,
  112. instanceData->buttonMap[button], buttonStatus);
  113. instanceData->buttonDown[button] = buttonStatus;
  114. }
  115. }
  116. input_sync(function_device->input); /* sync after groups of events */
  117. }
  118. EXPORT_SYMBOL(FN_19_inthandler);
  119. int FN_19_config(struct rmi_function_info *rmifninfo)
  120. {
  121. int retval = 0;
  122. pr_debug("%s: RMI4 F19 config\n", __func__);
  123. /* TODO: Perform configuration. In particular, write any cached control
  124. * register values to the device. */
  125. return retval;
  126. }
  127. EXPORT_SYMBOL(FN_19_config);
  128. /* Initialize any F19 specific params and settings - input
  129. * settings, device settings, etc.
  130. */
  131. int FN_19_init(struct rmi_function_device *function_device)
  132. {
  133. int i, retval = 0;
  134. struct f19_instance_data *instance_data = function_device->rfi->fndata;
  135. struct rmi_f19_functiondata *functiondata = rmi_sensor_get_functiondata(function_device->sensor, RMI_F19_INDEX);
  136. printk(KERN_DEBUG "%s: RMI4 F19 init\n", __func__);
  137. if (functiondata) {
  138. if (functiondata->button_map) {
  139. if (functiondata->button_map->nbuttons != instance_data->deviceInfo->buttonCount) {
  140. printk(KERN_WARNING "%s: Platformdata button map size (%d) != number of buttons on device (%d) - ignored.", __func__, functiondata->button_map->nbuttons, instance_data->deviceInfo->buttonCount);
  141. } else if (!functiondata->button_map->map) {
  142. printk(KERN_WARNING "%s: Platformdata button map is missing!", __func__);
  143. } else {
  144. for (i = 0; i < functiondata->button_map->nbuttons; i++)
  145. instance_data->buttonMap[i] = functiondata->button_map->map[i];
  146. }
  147. }
  148. }
  149. /* Set up any input events. */
  150. set_bit(EV_SYN, function_device->input->evbit);
  151. set_bit(EV_KEY, function_device->input->evbit);
  152. /* set bits for each button...*/
  153. for (i = 0; i < instance_data->deviceInfo->buttonCount; i++) {
  154. set_bit(instance_data->buttonMap[i], function_device->input->keybit);
  155. }
  156. printk(KERN_DEBUG "%s: Creating sysfs files.", __func__);
  157. retval = device_create_file(&function_device->dev, &dev_attr_buttonCount);
  158. if (retval) {
  159. printk(KERN_ERR "%s: Failed to create button count.", __func__);
  160. return retval;
  161. }
  162. retval = device_create_file(&function_device->dev, &dev_attr_buttonMap);
  163. if (retval) {
  164. printk(KERN_ERR "%s: Failed to create button map.", __func__);
  165. return retval;
  166. }
  167. return 0;
  168. }
  169. EXPORT_SYMBOL(FN_19_init);
  170. static int getControlRegisters(struct rmi_function_info *rmifninfo,
  171. struct rmi_function_descriptor *fndescr)
  172. {
  173. struct f19_instance_data *instanceData;
  174. unsigned char *fn19Control = NULL;
  175. int retval = 0;
  176. /* Get the instance data - it should have been allocated and stored in detect.*/
  177. instanceData = rmifninfo->fndata;
  178. /* Check to make sure instanceData is really there before using.*/
  179. if (!instanceData) {
  180. printk(KERN_ERR "%s: Error - instance data not initialized yet when getting fn19 control registers.\n", __func__);
  181. return -EINVAL;
  182. }
  183. /* Allocate memory for the control registers. */
  184. instanceData->controlRegisters = kzalloc(sizeof(struct rmi_F19_control), GFP_KERNEL);
  185. if (!instanceData->controlRegisters) {
  186. printk(KERN_ERR "%s: Error allocating F19 control registers.\n", __func__);
  187. return -ENOMEM;
  188. }
  189. instanceData->fn19regCountForBitPerButton = (instanceData->deviceInfo->buttonCount + 7)/8;
  190. /* Need to compute the amount of data to read since it varies with the
  191. * number of buttons */
  192. instanceData->fn19ControlRegisterSize = 1 /* 1 for filter mode and button usage bits */
  193. + 2*instanceData->fn19regCountForBitPerButton /* interrupt enable bits and single button participation bits */
  194. + 2*instanceData->deviceInfo->buttonCount /* sensormap registers + single button sensitivity registers */
  195. + 2; /* 1 for global sensitivity adjust + 1 for global hysteresis threshold */
  196. /* Allocate a temp memory buffer to read the control registers into */
  197. fn19Control = kzalloc(instanceData->fn19ControlRegisterSize, GFP_KERNEL);
  198. if (!fn19Control) {
  199. printk(KERN_ERR "%s: Error allocating temp storage to read fn19 control info.\n", __func__);
  200. return -ENOMEM;
  201. }
  202. /* Grab a copy of the control registers. */
  203. retval = rmi_read_multiple(rmifninfo->sensor, fndescr->controlBaseAddr,
  204. fn19Control, instanceData->fn19ControlRegisterSize);
  205. if (retval) {
  206. printk(KERN_ERR "%s: Failed to read F19 control registers.", __func__);
  207. return retval;
  208. }
  209. /* Copy over control registers data to the instance data */
  210. instanceData->fn19btnUsageandfilterModeOffset = 0;
  211. instanceData->controlRegisters->buttonUsage = fn19Control[instanceData->fn19btnUsageandfilterModeOffset] & 0x3;
  212. instanceData->controlRegisters->filterMode = fn19Control[instanceData->fn19btnUsageandfilterModeOffset] & 0xc;
  213. /* Fill in interrupt enable registers */
  214. instanceData->fn19intEnableOffset = 1;
  215. instanceData->fn19intEnableLen = instanceData->fn19regCountForBitPerButton;
  216. instanceData->controlRegisters->intEnableRegisters = kzalloc(instanceData->fn19intEnableLen, GFP_KERNEL);
  217. if (!instanceData->controlRegisters->intEnableRegisters) {
  218. printk(KERN_ERR "%s: Error allocating storage for interrupt enable control info.\n", __func__);
  219. return -ENOMEM;
  220. }
  221. memcpy(instanceData->controlRegisters->intEnableRegisters, &fn19Control[instanceData->fn19intEnableOffset],
  222. instanceData->fn19intEnableLen);
  223. /* Fill in single button control registers */
  224. instanceData->fn19singleBtnCtrlOffset = instanceData->fn19intEnableOffset + instanceData->fn19intEnableLen;
  225. instanceData->fn19singleBtnCtrlLen = instanceData->fn19regCountForBitPerButton;
  226. instanceData->controlRegisters->singleButtonControl = kzalloc(instanceData->fn19singleBtnCtrlLen, GFP_KERNEL);
  227. if (!instanceData->controlRegisters->singleButtonControl) {
  228. printk(KERN_ERR "%s: Error allocating storage for single button participation control info.\n", __func__);
  229. return -ENOMEM;
  230. }
  231. memcpy(instanceData->controlRegisters->singleButtonControl, &fn19Control[instanceData->fn19singleBtnCtrlOffset],
  232. instanceData->fn19singleBtnCtrlLen);
  233. /* Fill in sensor map registers */
  234. instanceData->fn19sensorMapCtrlOffset = instanceData->fn19singleBtnCtrlOffset + instanceData->fn19singleBtnCtrlLen;
  235. instanceData->fn19sensorMapCtrlLen = instanceData->deviceInfo->buttonCount;
  236. instanceData->controlRegisters->sensorMap = kzalloc(instanceData->fn19sensorMapCtrlLen, GFP_KERNEL);
  237. if (!instanceData->controlRegisters->sensorMap) {
  238. printk(KERN_ERR "%s: Error allocating storage for sensor map control info.\n", __func__);
  239. return -ENOMEM;
  240. }
  241. memcpy(instanceData->controlRegisters->sensorMap, &fn19Control[instanceData->fn19sensorMapCtrlOffset],
  242. instanceData->fn19sensorMapCtrlLen);
  243. /* Fill in single button sensitivity registers */
  244. instanceData->fn19singleBtnSensOffset = instanceData->fn19sensorMapCtrlOffset + instanceData->fn19sensorMapCtrlLen;
  245. instanceData->fn19singleBtnSensLen = instanceData->deviceInfo->buttonCount;
  246. instanceData->controlRegisters->singleButtonSensitivity = kzalloc(instanceData->fn19singleBtnSensLen, GFP_KERNEL);
  247. if (!instanceData->controlRegisters->intEnableRegisters) {
  248. printk(KERN_ERR "%s: Error allocating storage for single button sensitivity control info.\n", __func__);
  249. return -ENOMEM;
  250. }
  251. memcpy(instanceData->controlRegisters->singleButtonSensitivity, &fn19Control[instanceData->fn19singleBtnSensOffset],
  252. instanceData->fn19singleBtnSensLen);
  253. /* Fill in global sensitivity adjustment and global hysteresis threshold values */
  254. instanceData->fn19globalSensOffset = instanceData->fn19singleBtnSensOffset + instanceData->fn19singleBtnSensLen;
  255. instanceData->fn19globalHystThreshOffset = instanceData->fn19globalSensOffset + 1;
  256. instanceData->controlRegisters->globalSensitivityAdjustment = fn19Control[instanceData->fn19globalSensOffset] & 0x1f;
  257. instanceData->controlRegisters->globalHysteresisThreshold = fn19Control[instanceData->fn19globalHystThreshOffset] & 0x0f;
  258. /* Free up temp storage that held copy of control registers */
  259. kfree(fn19Control);
  260. return 0;
  261. }
  262. int FN_19_detect(struct rmi_function_info *rmifninfo,
  263. struct rmi_function_descriptor *fndescr, unsigned int interruptCount)
  264. {
  265. unsigned char fn19queries[2];
  266. int retval = 0;
  267. int i;
  268. struct f19_instance_data *instanceData;
  269. int fn19InterruptOffset;
  270. printk(KERN_DEBUG "%s: RMI4 F19 detect\n", __func__);
  271. instanceData = kzalloc(sizeof(struct f19_instance_data), GFP_KERNEL);
  272. if (!instanceData) {
  273. printk(KERN_ERR "%s: Error allocating F19 instance data.\n", __func__);
  274. return -ENOMEM;
  275. }
  276. instanceData->deviceInfo = kzalloc(sizeof(struct rmi_F19_query), GFP_KERNEL);
  277. if (!instanceData->deviceInfo) {
  278. printk(KERN_ERR "%s: Error allocating F19 device query.\n", __func__);
  279. return -ENOMEM;
  280. }
  281. rmifninfo->fndata = instanceData;
  282. /* Store addresses - used elsewhere to read data,
  283. * control, query, etc. */
  284. rmifninfo->funcDescriptor.queryBaseAddr = fndescr->queryBaseAddr;
  285. rmifninfo->funcDescriptor.commandBaseAddr = fndescr->commandBaseAddr;
  286. rmifninfo->funcDescriptor.controlBaseAddr = fndescr->controlBaseAddr;
  287. rmifninfo->funcDescriptor.dataBaseAddr = fndescr->dataBaseAddr;
  288. rmifninfo->funcDescriptor.interruptSrcCnt = fndescr->interruptSrcCnt;
  289. rmifninfo->funcDescriptor.functionNum = fndescr->functionNum;
  290. rmifninfo->numSources = fndescr->interruptSrcCnt;
  291. /* need to get number of fingers supported, data size, etc. -
  292. to be used when getting data since the number of registers to
  293. read depends on the number of fingers supported and data size. */
  294. retval = rmi_read_multiple(rmifninfo->sensor, fndescr->queryBaseAddr, fn19queries,
  295. sizeof(fn19queries));
  296. if (retval) {
  297. printk(KERN_ERR "%s: RMI4 F19 detect: "
  298. "Could not read function query registers 0x%x\n",
  299. __func__, rmifninfo->funcDescriptor.queryBaseAddr);
  300. return retval;
  301. }
  302. /* Extract device data. */
  303. instanceData->deviceInfo->configurable = fn19queries[0] & 0x01;
  304. instanceData->deviceInfo->hasSensitivityAdjust = fn19queries[0] & 0x02;
  305. instanceData->deviceInfo->hasHysteresisThreshold = fn19queries[0] & 0x04;
  306. instanceData->deviceInfo->buttonCount = fn19queries[1] & 0x01F;
  307. printk(KERN_DEBUG "%s: F19 device - %d buttons...", __func__, instanceData->deviceInfo->buttonCount);
  308. /* Need to get interrupt info to be used later when handling
  309. interrupts. */
  310. rmifninfo->interruptRegister = interruptCount/8;
  311. /* loop through interrupts for each source in fn $11 and or in a bit
  312. to the interrupt mask for each. */
  313. fn19InterruptOffset = interruptCount % 8;
  314. for (i = fn19InterruptOffset;
  315. i < ((fndescr->interruptSrcCnt & 0x7) + fn19InterruptOffset);
  316. i++)
  317. rmifninfo->interruptMask |= 1 << i;
  318. /* Figure out just how much data we'll need to read. */
  319. instanceData->buttonDown = kcalloc(instanceData->deviceInfo->buttonCount, sizeof(bool), GFP_KERNEL);
  320. if (!instanceData->buttonDown) {
  321. printk(KERN_ERR "%s: Error allocating F19 button state buffer.\n", __func__);
  322. return -ENOMEM;
  323. }
  324. instanceData->buttonDataBufferSize = (instanceData->deviceInfo->buttonCount + 7) / 8;
  325. instanceData->buttonDataBuffer = kcalloc(instanceData->buttonDataBufferSize, sizeof(unsigned char), GFP_KERNEL);
  326. if (!instanceData->buttonDataBuffer) {
  327. printk(KERN_ERR "%s: Failed to allocate button data buffer.", __func__);
  328. return -ENOMEM;
  329. }
  330. instanceData->buttonMap = kcalloc(instanceData->deviceInfo->buttonCount, sizeof(unsigned char), GFP_KERNEL);
  331. if (!instanceData->buttonMap) {
  332. printk(KERN_ERR "%s: Error allocating F19 button map.\n", __func__);
  333. return -ENOMEM;
  334. }
  335. for (i = 0; i < instanceData->deviceInfo->buttonCount; i++)
  336. instanceData->buttonMap[i] = BTN_0 + i; /* default values */
  337. /* Grab the control register info. */
  338. retval = getControlRegisters(rmifninfo, fndescr);
  339. if (retval) {
  340. printk(KERN_ERR "%s: Error %d getting fn19 control register info.\n", __func__, retval);
  341. return retval;
  342. }
  343. return 0;
  344. }
  345. EXPORT_SYMBOL(FN_19_detect);
  346. static ssize_t rmi_f19_buttonCount_show(struct device *dev,
  347. struct device_attribute *attr, char *buf)
  348. {
  349. struct rmi_function_device *fn = dev_get_drvdata(dev);
  350. struct f19_instance_data *instance_data = (struct f19_instance_data *)fn->rfi->fndata;
  351. return sprintf(buf, "%u\n", instance_data->deviceInfo->buttonCount);
  352. }
  353. static ssize_t rmi_f19_buttonCount_store(struct device *dev,
  354. struct device_attribute *attr,
  355. const char *buf, size_t count)
  356. {
  357. /* Not allowed. */
  358. return -EPERM;
  359. }
  360. static ssize_t rmi_f19_buttonMap_show(struct device *dev,
  361. struct device_attribute *attr, char *buf)
  362. {
  363. struct rmi_function_device *fn = dev_get_drvdata(dev);
  364. struct f19_instance_data *instance_data = (struct f19_instance_data *)fn->rfi->fndata;
  365. int i, len, totalLen = 0;
  366. /* loop through each button map value and copy it's string representation into buf */
  367. for (i = 0; i < instance_data->deviceInfo->buttonCount; i++) {
  368. /* get next button mapping value and write it to buf */
  369. len = sprintf(buf, "%u ", instance_data->buttonMap[i]);
  370. /* bump up ptr to next location in buf if the sprintf was valid */
  371. if (len > 0) {
  372. buf += len;
  373. totalLen += len;
  374. }
  375. }
  376. return totalLen;
  377. }
  378. static ssize_t rmi_f19_buttonMap_store(struct device *dev,
  379. struct device_attribute *attr,
  380. const char *buf, size_t count)
  381. {
  382. struct rmi_function_device *fn = dev_get_drvdata(dev);
  383. struct f19_instance_data *instance_data = (struct f19_instance_data *)fn->rfi->fndata;
  384. unsigned int button;
  385. int i;
  386. int retval = count;
  387. int buttonCount = 0;
  388. unsigned char *tmpButtonMap;
  389. /* Do validation on the button map data passed in. */
  390. /* Store button mappings into a temp buffer and then verify button count
  391. and data prior to clearing out old button mappings and storing the new ones. */
  392. tmpButtonMap = kzalloc(instance_data->deviceInfo->buttonCount, GFP_KERNEL);
  393. if (!tmpButtonMap) {
  394. printk(KERN_ERR "%s: Error allocating temp button map.\n", __func__);
  395. return -ENOMEM;
  396. }
  397. for (i = 0; i < instance_data->deviceInfo->buttonCount && *buf != 0; i++) {
  398. /* get next button mapping value and store and bump up to point to next item in buf */
  399. sscanf(buf, "%u", &button);
  400. /* Make sure the key is a valid key */
  401. if (button > KEY_MAX) {
  402. printk(KERN_ERR "%s: Error - button map for button %d is not a valid value 0x%x.\n",
  403. __func__, i, button);
  404. retval = -EINVAL;
  405. goto err_ret;
  406. }
  407. tmpButtonMap[i] = button;
  408. buttonCount++;
  409. /* bump up buf to point to next item to read */
  410. while (*buf != 0) {
  411. buf++;
  412. if (*(buf-1) == ' ')
  413. break;
  414. }
  415. }
  416. /* Make sure the button count matches */
  417. if (buttonCount != instance_data->deviceInfo->buttonCount) {
  418. printk(KERN_ERR "%s: Error - button map count of %d doesn't match device button count of %d.\n"
  419. , __func__, buttonCount, instance_data->deviceInfo->buttonCount);
  420. retval = -EINVAL;
  421. goto err_ret;
  422. }
  423. /* Clear out old buttonMap data */
  424. memset(instance_data->buttonMap, 0, buttonCount);
  425. /* Loop through the temp buffer and copy the button event and set the key bit for the new mapping. */
  426. for (i = 0; i < buttonCount; i++) {
  427. instance_data->buttonMap[i] = tmpButtonMap[1];
  428. set_bit(instance_data->buttonMap[i], fn->input->keybit);
  429. }
  430. err_ret:
  431. kfree(tmpButtonMap);
  432. return retval;
  433. }