3 tasks to achieve:
1. Configure MPR121: initialize registers, configure buttons, leds, gpio, calculate parameters, etc
2. Create a thread and handler for IRQ
3. Create these sysFs for a dynamic configuration
Prepare data and allocate memory
static int __devinit mpr_touchkey_probe(struct i2c_client *client, const struct i2c_device_id *id){ const struct mpr121_platform_data *pdata=client->dev.platform_data;The client represent the device mpr121, the platform_data is predefined at board file.
struct mpr121_touchkey *mpr121; struct input_dev *input_dev;input_dev represent a device who produces the signal of input to the module ARM.
mpr121 = kzalloc(sizeof(struct mpr121_touchkey), GFP_KERNEL); input_dev = input_allocate_device();input_allocate_device() allocate memory for a new device and return a structure of input_dev.
mpr121->client = client; mpr121->input_dev = input_dev; mpr121->keycount = pdata->keymap; input_dev->name = "mpr121";//name of the device input_dev->id.bustype = BUS_I2C;//id of the device (struct input_id) input_dev->dev.parent = &client->dev;//driver model's view of this device input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP); //bitmap of types of events supported by the device (EV_KEY, EV_REL, etc.) /* EV_KEY:- Used to describe state changes of keyboards, buttons, or other key-like devices.*/ /* EV_REP:- Used for autorepeating devices.*/ input_dev->keycode = mpr121->keycodes; //map of scancodes to keycodes for this device input_dev->keycodesize = sizeof(mpr121->keycodes[0]); input_dev->keycodemax = mpr121->keycount;//size of keycode tableinput_dev->name is an important parameter which must be also the name of the keylayout file(mpr121.kl) and input device configure file(mpr121.idc).
for (i = 0; i < pdata->keymap_size; i++) { input_set_capability(input_dev, EV_KEY, pdata->keymap[i]); mpr121->keycodes[i] = pdata->keymap[i]; } //input_set_events_per_packet - mark device as capable of a certain event //dev: device that is capable of emitting or accepting event //type:type of the event (EV_KEY, EV_REL, etc...) //code:event code //In addition to setting up corresponding bit in appropriate capability bitmap // the function also adjusts dev->evbit.
Task 1: Configure MPR121
It's better to put all the configuration in an independent function mpr121_phys_init(pdata, mpr121, client)
initialize touch/release threshold
for (i = 0; i < keynum_config; i++) { addr = ELE0_TOUCH_THRESHOLD_ADDR + ((key_matrix[i] + i) * 2); ret = i2c_smbus_write_byte_data(client, addr, TOUCH_THRESHOLD); ret = i2c_smbus_write_byte_data(client, addr+1, RELEASE_THRESHOLD); }
configure GPIO
i2c_smbus_write_byte_data(client, GPIO_ENABLE_ADDR, gpio_config_value); i2c_smbus_write_byte_data(client, GPIO_DIRECTION_ADDR, gpio_config_value); i2c_smbus_write_byte_data(client, GPIO_CONTROL_0_ADDR, gpio_config_value); i2c_smbus_write_byte_data(client, GPIO_CONTROL_1_ADDR, gpio_config_value);
tache 2: Installer IRQ et handler
request_threaded_irq(client->irq, NULL, mpr_touchkey_interrupt, //handler IRQF_TRIGGER_FALLING, client->dev.driver->name, mpr121);
Registrer device avec input core
input_register_device(input_dev);
Mettre à jour MPR121(client)
i2c_set_clientdata(client, mpr121);
Configurer capacité de "wake-up"
device_init_wakeup(&client->dev, pdata->wakeup);
tache 3: Creer sysFs
ret = sysfs_create_group(&client->dev.kobj, &mpr121_attr_group);
Until now, a generic driver for mpr121 is done. With the sysfs, the parameters like threshold and touch mask could be configured dynamically in the console without recompiling the driver. And if the correspondence of the led and the buttons changes, a simple modification in the board file is enough.
No comments:
Post a Comment