summaryrefslogtreecommitdiff
path: root/include/keyboard_scan.h
Commit message (Collapse)AuthorAgeFilesLines
* keyboard_scan: Add consts needed for factory test to headerRob Barnes2021-07-281-0/+10
| | | | | | | | | | | | | | | | | Add keyboard_factory_scan_pins and keyboard_factory_scan_pins_used to keyboard_scan header so they do not need to be declared as extern by individual boards. These constants need to be defined if CONFIG_KEYBOARD_FACTORY_TEST is enabled. BUG=None TEST=Build BRANCH=None Change-Id: I1a100f626b3cea251ca72703d17b2d27db0f8f28 Signed-off-by: Rob Barnes <robbarnes@google.com> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3053101 Commit-Queue: Diana Z <dzigterman@chromium.org> Reviewed-by: Diana Z <dzigterman@chromium.org>
* keyboard: Use __override for keyboard_scan_configDaisuke Nojiri2021-07-231-1/+1
| | | | | | | | | | | | | | | | | Currently keyboard_scan_config is defined by each board using CONFIG_KEYBOARD_BOARD_CONFIG. This patch makes it defined as __override hence removes CONFIG_KEYBOARD_BOARD_CONFIG. BUG=None BRANCH=None TEST=buildall Change-Id: I53a356741ba4d00e829ca59b74ee6dc704188728 Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3044403 Tested-by: Gwendal Grignou <gwendal@chromium.org> Commit-Queue: Gwendal Grignou <gwendal@chromium.org> Reviewed-by: Gwendal Grignou <gwendal@chromium.org>
* common/vivaldi: Make the "Alt+VolUp+r" work on vivaldi keyboardsRajat Jain2020-04-211-0/+6
| | | | | | | | | | | | | | | Since the VolUp button location can vary now, take that into account. Signed-off-by: Rajat Jain <rajatja@google.com> BUG=b:146501925,b:154167876 TEST=TEst Alt + VolUp + r on Jinlon BRANCH=firmware-hatch-12672.B Change-Id: I4dbc8692f6418fd786e5d33053e8c368cc5529ac Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2151854 Commit-Queue: Rajat Jain <rajatja@google.com> Tested-by: Rajat Jain <rajatja@google.com> Reviewed-by: Jett Rink <jettrink@chromium.org>
* LICENSE: remove unnecessary (c) after CopyrightTom Hughes2019-06-191-1/+1
| | | | | | | | | | | | | | | | Ran the following command: git grep -l 'Copyright (c)' | \ xargs sed -i 's/Copyright (c)/Copyright/g' BRANCH=none BUG=none TEST=make buildall -j Change-Id: I6cc4a0f7e8b30d5b5f97d53c031c299f3e164ca7 Signed-off-by: Tom Hughes <tomhughes@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1663262 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Aseda Aboagye <aaboagye@chromium.org>
* common: replace 1 << digits, with BIT(digits)Gwendal Grignou2019-03-261-3/+3
| | | | | | | | | | | | | | | | Requested for linux integration, use BIT instead of 1 << First step replace bit operation with operand containing only digits. Fix an error in motion_lid try to set bit 31 of a signed integer. BUG=None BRANCH=None TEST=compile Change-Id: Ie843611f2f68e241f0f40d4067f7ade726951d29 Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1518659 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
* common: Include compile_time_macros.h when neededGwendal Grignou2019-03-261-0/+1
| | | | | | | | | | | | | Include compile_time_macros.h to files that will use BIT macro. BUG=None BRANCH=None TEST=unit tests. Change-Id: I9d44f4b588620f6770f8d522d422f5dd0d237903 Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1525156 Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
* Keyboard: Allow keyboard size to be set at run timeDaisuke Nojiri2018-10-191-2/+2
| | | | | | | | | | | | | | | | | | | | | | | Currently, the keyboard size (i.e. number of columns) is static. This patch allows it to be configured at run time. It's required to support a keyboard with/without keypad in a single image. KEYBOARD_COLS_MAX has the build time col size. It's used to allocate exact spaces for arrays. Actual keyboard scanning is done using keyboard_cols, which holds a runtime col size. Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> BUG=b:117126568 BRANCH=none TEST=Verify keyboard functionality on Sona and Veyron. Change-Id: I4b3552be0b4b315c3fe5a6884cf25e10aba8be7c Reviewed-on: https://chromium-review.googlesource.com/1285292 Commit-Ready: Daisuke Nojiri <dnojiri@chromium.org> Tested-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org>
* ec/google: Add command to fetch keyboard ID from ECparis_yeh2018-06-201-0/+10
| | | | | | | | | | | | | | | | | Sort k-prefix host commands and descriptions in alphabetical order BRANCH=master BUG=b:80168723 TEST=Check 'ectool kbid' on a reworked DUT using keyboard samples Change-Id: If2ad654e5ef269d03365db7c3286c2281aa9d9ef Signed-off-by: paris_yeh <pyeh@google.com> Reviewed-on: https://chromium-review.googlesource.com/1097997 Commit-Ready: Paris Yeh <pyeh@chromium.org> Tested-by: Paris Yeh <pyeh@chromium.org> Reviewed-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Paris Yeh <pyeh@chromium.org> Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
* keyboard_scan: Disable when USB is suspended without wakeNicolas Boichat2018-02-051-0/+1
| | | | | | | | | | | | | | | | Keyboard matrix scanning can be disabled when the USB interface is disabled without setting the remote wake feature (USB_REQ_FEATURE_DEVICE_REMOTE_WAKEUP), as events would be ignored anyway. BRANCH=none BUG=b:72683995 TEST=keyboard matrix scanning is disabled when lid is closed. Change-Id: I0b2346cc3426b9ef51127424f9953fd5c20ecd49 Signed-off-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/897068 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
* keyboard_scan: Add option to not handle boot key combinationsNicolas Boichat2017-05-081-1/+1
| | | | | | | | | | | | | | | | | | On some boards, the boot key combinations do not make a lot of sense, so we can just not process them and save a little bit of code space. BRANCH=none BUG=b:37422577 TEST=Flash hammer TEST=make newsizes shows we save 156 bytes in hammer RW. Change-Id: Ic96d7ed1dbee10f44f8b08568ab70b2f20961842 Reviewed-on: https://chromium-review.googlesource.com/495968 Commit-Ready: Nicolas Boichat <drinkcat@chromium.org> Tested-by: Nicolas Boichat <drinkcat@chromium.org> Reviewed-by: Furquan Shaikh <furquan@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
* keyboard: Clear typematic when disabling keyboardDaisuke Nojiri2017-05-031-0/+5
| | | | | | | | | | | | | | | | This patch clears the typematic buffer when disabling keyboard scan. When the device goes to tablet mode with a key being pressed, this should prevent keyboard_protocol_task from sending scan codes to the host. BUG=b:35585725 BRANCH=none TEST=make buildall. Tested on Electro. Change-Id: I73e9d2948b472458814967307412aebeb410ff2e Signed-off-by: Daisuke Nojiri <dnojiri@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/425075 Reviewed-by: Aaron Durbin <adurbin@chromium.org>
* common: Add new recovery mode button combinationFurquan Shaikh2016-11-081-9/+16
| | | | | | | | | | | | | | | | | | This adds new key combination (Left_Shift+Esc+Refresh+Power) that triggers recovery mode by setting a new host event EC_HOST_EVENT_KEYBOARD_RECOVERY_HW_REINIT. This host event can be used whenever user wants to request entry into recovery mode by reinitializing all the hardware state (e.g. memory retraining). BUG=chrome-os-partner:56643,chrome-os-partner:59352 BRANCH=None TEST=Verified that device retrains memory in recovery mode with (Left_Shift+Esc+Refresh+Power) on reef. Change-Id: I2e08997acfd9e22270b8ce7a5b589cd5630645f8 Signed-off-by: Furquan Shaikh <furquan@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/407827 Reviewed-by: Randall Spangler <rspangler@chromium.org>
* Refactored keyboard scan enable flag to allow for multiple disable reasonsAlec Berg2014-04-111-8/+15
| | | | | | | | | | | | | | | | | | | | | | Refactored keyboard scan enable/disable flag such that it is a mask of potential disable sources. When all disable sources are off, scanning is enabled, otherwise scanning is disabled. This fixes a recently introduced bug in which enabling/disabling keyboard scanning due to lid angle in S3 was interfering with enabling/disabling keyboard scanning due to power button. This also allows for easy expansion for future causes for disabling keyboard scanning. BUG=chrome-os-partner:27851 BRANCH=rambi TEST=Manual tests with a glimmer. Used the ksstate console command to check state of keyboard scanning under all permutations of power button pressed/unpressed, lid switch open/closed, and lid angle in tablet position vs. laptop positon. Change-Id: Ied4c5ebb94510b1078cd81d71373c0f1bd0d6678 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/194287 Reviewed-by: Randall Spangler <rspangler@chromium.org>
* rambi: glimmer: Disable key scanning in suspend when lid is openAlec Berg2014-03-271-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | Added ability to disable the keyboard to wake from suspend when the lid is outside a certain angle range. This has been added to glimmer by defining CONFIG_LID_ANGLE_KEY_SCAN in its board.h. Also modified the lid angle calculation to include a reliability flag which can be used to tell when the hinge aligns too closely with gravity and the lid angle value is unreliable. BUG=none BRANCH=rambi TEST=Tested on a glimmer: In S3, verified that when the lid is open past ~180 deg, the keyboard does not wake the machine. Also verified that if you align hinge with gravity, the keyboard enabled/disabled status remains the same (since we can't actually trust the lid angle value). Change-Id: I45b2c7c3c4bbcae61d3a0f8b5baa461ab8dabfb0 Original-Change-Id: If1a1592d259902d38941936961854b81b3a75b95 Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/190061 Reviewed-on: https://chromium-review.googlesource.com/191612 Reviewed-by: Randall Spangler <rspangler@chromium.org>
* Replace generated CONFIG_TASK_ macros with HAS_TASK_Bill Richardson2013-04-241-2/+2
| | | | | | | | | | | | | | | CONFIG_ macros should be set directly. Expanding the task names in the same way made it difficult to tell what was a configuration choice and what was due to changes in ec.tasklist BUG=chrome-os-partner:18343 TEST=build all, run link BRANCH=none Change-Id: Ib82e34f974238ee2dd216f33b701b6f4c6a4f1f1 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/49098 Reviewed-by: Randall Spangler <rspangler@chromium.org>
* Allow keyboard_scan_config to be customized per-boardBill Richardson2013-04-241-0/+4
| | | | | | | | | | | | | | By default it's not, but if you #define CONFIG_CUSTOM_KEYSCAN, you can add your own settings in board.c BUG=chrome-os-partner:18343 TEST=build link, bds BRANCH=none Change-Id: I2a9dd48fd7f4610bc39dcc59e59a3fedec539e28 Signed-off-by: Bill Richardson <wfrichar@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/48994 Reviewed-by: Randall Spangler <rspangler@chromium.org>
* Fix test compilation error for linkVic Yang2013-04-131-0/+11
| | | | | | | | | | | | | Now pingpong and mutex tests compile. Still need some more work to handle the i8042-specific KEYPROTO task for keyboard tests. BUG=chrome-os-partner:18598 TEST=Build tests for link BRANCH=None Change-Id: I9ee35d4edb811f17b9a81beb799484a07c0bef14 Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/47981
* Merge lm4 and stm32 implementations of keyboard_scanRandall Spangler2013-03-291-0/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Scanning is now performed identically on all platforms. keyboard_scan talks to chip-specific keyboard_raw on the bottom end, and 8042 or mkbp keyboard protocol on the top end. 8042 can now take advantage of CONFIG_KEYBOARD_TEST to simulate scan results. BUG=chrome-os-partner:18360 BRANCH=none TEST=compile all boards; test keyboard on spring and link 1) Type on keyboard. Should produce keystrokes. 2) At EC console: kbpress 3 7 1 kbpress 3 7 0 Should produce 'r' keystroke(s); key repeat should kick in if you wait a while between the commands. 3) Hold power button while typing. Should not produce keystrokes. 4) Reboot with power+refresh+esc. Should go to recovery mode. 5) While the system is up, alt+volup+R should reboot the AP. Change-Id: I48e0bca15b869162672b5f54ffcb561f6fcf0f45 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/46666 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
* Move files in preparation for merging keyboard_scan modulesRandall Spangler2013-03-271-15/+8
| | | | | | | | | | | | | | | | | | This is part one of a series to merge the keyboard scan interface to be common across all platforms. This change just moves and renames files and APIs and removes some read code, and sets up protocol-specific CONFIG options. It makes the next CL which actually merges keyboard scanning easier to parse. BUG=chrome-os-partner:18360 BRANCH=none TEST=compile all boards; test keyboard on spring and link Change-Id: I815a40aae4e5d5f333b8501aff9656080533d913 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/46549 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
* Add keyboard_raw interfaceRandall Spangler2013-03-221-12/+0
| | | | | | | | | | | | | | | | | | | | This is the low-level platform-dependent interface to drive keyboard columns, read rows, and handle keyboard interrupts. Both lm4 and stm32 had something like this before, but the interfaces weren't fully explicit or compatible. BUG=chrome-os-partner:18360 BRANCH=none TEST=manual - Build all platforms. - Boot system and test typing on keyboard. - Hold power+refresh+esc to test boot key detection; should go to recovery. Change-Id: Ie3bcc1d066a4da5204f0e236daeb52c4064a6213 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/46156
* Use common declaration of keyboard_scan_interrupt()Randall Spangler2013-03-191-7/+29
| | | | | | | | | | | | | | | | Code cleanup: declare keyboard_scan_interrupt() once, not per board; the implementation is common anyway. No functional changes; just renaming. BUG=none BRANCH=none TEST=build daisy,snow,spring,mccrosskey Change-Id: I1e33cbe2c868bc47b641d36d26f07c3b5a7ba3c7 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/45874 Reviewed-by: Bill Richardson <wfrichar@chromium.org>
* spring: stm32: Generate battery key when charging status changes.Todd Broch2013-03-131-0/+3
| | | | | | | | | | | | | | | | | | | | | | | In order to update charger status we have added a virtual keystroke to signal change to the kernel via the MKBP interface. CL creates the virtual key press and calls it from within the USB charging code. Signed-off-by: Todd Broch <tbroch@chromium.org> BUG=chrome-os-partner:17927 BRANCH=spring TEST=manual 1. Compile for daisy,snow,spring. 2. Test on spring. Change-Id: I0afa0fc82c96fa3fd8119523a113b5028c8f64a3 Reviewed-on: https://gerrit.chromium.org/gerrit/45126 Reviewed-by: Vincent Palatin <vpalatin@chromium.org> Tested-by: Todd Broch <tbroch@chromium.org> Commit-Queue: Todd Broch <tbroch@chromium.org>
* Clean up keyboard_scan moduleRandall Spangler2012-10-231-1/+1
| | | | | | | | | | | | | We only have one scan mask and no capability to change scan masks, so don't reserve space for masks we're not using. BUG=chrome-os-partner:15579 BRANCH=none TEST=type on keyboard; should still work Change-Id: I8ad0c5c894f93c2a79ca646e7666b3279c90a63c Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/36347
* Refactor runtime special key combination codeRandall Spangler2012-09-101-2/+0
| | | | | | | | | | | | | | | | | | The code for warm reboot is overly specialized, and makes it hard to add other key cominations for testing. BUG=chrome-os-partner:13763 BRANCH=link TEST=manual 1. boot system 2. hold down (in order) R+T+alt+VolUp. System does not reboot. 3. let go of T (so only R+alt+volup are pressed). System reboots. Change-Id: I14cdb7f790e8a772712085a77eaf4299487788db Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/32439 Reviewed-by: Simon Glass <sjg@chromium.org>
* Remove old code to clear boot keyRandall Spangler2012-09-101-3/+0
| | | | | | | | | | | | | | | | | This has been deprecated in favor of a host event to trigger recovery mode. BUG=none BRANCH=link TEST=manual 1. Power+Esc+Refresh -> recovery mode 2. Press power -> off 3. Press power -> boots normally (NOT recovery) Change-Id: I9288785ce1c0a446867dc54d1b6ec2f556896688 Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/32426 Reviewed-by: Simon Glass <sjg@chromium.org>
* Refactor boot key detectionRandall Spangler2012-06-261-3/+23
| | | | | | | | | | | | | | | | | | | | | Keyboard scan module now owns the recovery key state on all platforms. And clean up a few comments to linux kernel style BUG=chrome-os-partner:10890 TEST=manual - Power on system. Should boot normally. - Power+Refresh+D. Should turn dev switch on. - Power+Refresh+F. Should turn dev switch off. - Power+Esc. Should reboot system. Power button should power on normally. - Power+Refresh+Esc. Should power on into recovery mode. - Then press power to shut system down. - Power button should power on normally (not back into recovery mode). Change-Id: I4d16e1e8b039efeacbd41e8acec115844bc8457d Signed-off-by: Randall Spangler <rspangler@chromium.org> Reviewed-on: https://gerrit.chromium.org/gerrit/26147 Reviewed-by: Simon Glass <sjg@chromium.org>
* Release keyboard recovery button on next power-onRandall Spangler2012-06-041-4/+3
| | | | | | | | | | | | | | | | | | | | | | | | Keyboard recovery used to persist until the next time the EC was reset. It should release the next time the user turns on the system via the lid or power button. Signed-off-by: Randall Spangler <rspangler@chromium.org> BUG=chrome-os-partner:10034 TEST=manual 1. power system on normally. not in recovery. 2. press Power+Esc+Refresh. System turns on into recovery. 3. shut system down 4. power system on with lid-open. System boots normally. 5. repeat steps 2-3, then power system on with power button. System boots normally. Change-Id: I455c7191d128614629c50ba27d7ef977e414fe90 Reviewed-on: https://gerrit.chromium.org/gerrit/24409 Commit-Ready: Randall Spangler <rspangler@chromium.org> Tested-by: Randall Spangler <rspangler@chromium.org> Reviewed-by: Simon Glass <sjg@chromium.org>
* Keyboard scan must stop driving columns when power button is pressed.Louis Yung-Chieh Lo2012-05-241-0/+5
| | | | | | | | | | | | | | | | | | | Tristage all columns as soon as possible right after the power button is pressed. This can avoid the silego chip to reset the EC. Resume the interrupt mode after power button is released so that the deasserted columns doesn't trigger EC reset. Also change some function names for export. BUG=chrome-os-partner:7486 TEST= press g first, then power button. repeat many times. system is not rebooted. press power button first, then g. repeat many times. system is not rebooted. ESC+power is still reseting system. The long press power button still shutdowns system. Change-Id: Ie5dec20ec3d3c4ffbd4acf5a4dd7f63eec38af56
* Use common host command processing for Daisy I2CVincent Palatin2012-05-181-15/+0
| | | | | | | | | | | | This also updates the communication protocol between the EC and the AP in a non backward compatible way. Signed-off-by: Vincent Palatin <vpalatin@chromium.org> BUG=chrome-os-partner:9614 TEST=on Daisy with updated kernel driver, use the keyboard in ChromeOS Change-Id: I5a50e9a74b9891153a37ea79318c8a66a1b0c5ca
* stm32: add a FIFO for keyboard usageDavid Hendricks2012-05-161-0/+3
| | | | | | | | | | | | | | | This CL adds a simple FIFO to store keystrokes. The keyboard_scan() function will push keystrokes into the FIFO and is the only producer, while keyboard_get_scan() will pop entries and is the only consumer. BUG=chrome-os-partner:9594 TEST=tested on daisy Signed-off-by: David Hendricks <dhendrix@chromium.org> Testing was mostly subjectively done by typing a sentence quickly at the Chrome UI. Change-Id: I6faff41b0f16b75d6426df13a239f84eb62634ec
* Update keyboard scanning for stm32 to use messagesSimon Glass2012-04-111-0/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | Provide the required plumbing for the stm32 keyboard scan code so that the message layer will pick up keyboard scans. The design is as follows: - When a change in keyboard state is detected, the keyboard matrix scanning code will call the board-specific board_keyboard_scan_ready() function to interrupt the AP. - The AP will initiate a CMDC_KEY_STATE transaction over SPI or I2C - The SPI or I2C driver will call message_process_cmd() to process the command - This in turn will call keyboard_get_scan() to get the latest scan data For SPI: - The AP will initiate an 20-byte (or longer) SPI transaction - The EC will see the command, and provide the keyboard state in response, with the response being part of the same transaction For I2C: - The AP will initiate a 1-byte write to set the EC mode. - The AP will then initiate an 18-byte read, and the EC will send the message including keyboard state BUG=chromium-os:28925 TEST=build on daisy and discovery; run on daisy Change-Id: I905ef9d567e43d85fb851052f67586eff58e1167 Signed-off-by: Simon Glass <sjg@chromium.org>
* Check for recovery key sequence at initRandall Spangler2012-02-141-1/+4
| | | | | | | | | | | | Signed-off-by: Randall Spangler <rspangler@chromium.org> BUG=chrome-os-partner:7451 TEST=hold down no keys; KB init state should be blank hold down reload (F3); KB init should indicate recovery key pressed hold down F3 + ESC; same hold down F3 + F2 + ESC; KB init should NOT indicate recovery key pressed Change-Id: I0fbf15407b20669396f667e6499ee5a9d545a4d5
* Initial sources import 1/3Randall Spangler2011-12-071-0/+16
source files mainly done by Randall. Signed-off-by: Randall Spangler <rspangler@chromium.org> Change-Id: Iaff83a842b17f3350fb6f2a3f1597ad4c29bd12a