Introduction to Android G sensor I²C Driver on Android Bo-Yi Wu 2010.06.04 Gemtek Technology Co., Ltd
Outline What’s G sensor ? I²C Driver Kernel Patch Issue Reference
What’s G sensor & Application As accelerometers are more and more present in mobile devices, new features are developed. Portrait & Landscape is one of them. It allows devices to display the information in the right orientation depending on how it is held.
Orientation estimation
Orientation estimation
Stability check  STABLE_THRES STABLE_COUNT_MIN calling rate? bigger or smaller?
Code Review
I²C : detection capability set i2c address value detect call back function detect address fill the structure i2c_board_info
New-style drivers vs Legacy drivers Legacy drivers  duplicate a lot of code . The code needed in each driver to implement a detect callback is way  smaller  than the code needed to implement a legacy driver.
New-style drivers: initial function  module_init ( BMA150_init ); return   i2c_add_driver (&bma150_driver); module_exit ( BMA150_exit ); i2c_del_driver (&bma150_driver); __exit  &&  __init  (Kernel built in or module)
G Sensor: bma150_driver structure New-style driver Legacy driver probe: Callback for device binding (new-style drivers)  remove: Callback for device unbinding (new-style drivers) class :  What kind of i2c device we instantiate (for detect)  (1<<0) for sensor address_data: The I2C addresses to probe, ignore or force (for detect) id_table: List of I2C devices supported by this driver
Legacy driver: address_data
New-style drivers: address_data /* Internal numbers to terminate lists */ I2C_CLIENT_END :  0xfffeU I2C_CLIENT_INSMOD_1  ~  I2C_CLIENT_INSMOD_8 I2C_CLIENT_INSMOD_COMMON : define   structure address_data normal_i2c, probe, ignore value
I2c Driver: i2c_register_driver 1.  new style driver methods can't mix with legacy ones /* check bma150_driver is news style driver or not */ is_newstyle_driver (driver) 2.  /* check bma150_driver is Legacy style driver or not */ driver->attach_adapter || driver->detach_adapter || driver->detach_client 4.  /* add bma150 driver to list for i2c only */ INIT_LIST_HEAD (&driver->clients) 5.  /* Walk the adapters that are already present   */ class_for_each_device struct i2c_adapter *adapter = to_i2c_adapter(dev); struct i2c_driver *driver = data; 3.  /*  register driver with bus, and use  bus_add_driver () to add bus driver */ driver_register (&driver->driver);
I2c Driver: __attach_adapter Call  __attach_adapter  function New style driver: i2c_detect (adapter, driver); Legacy driver: driver-> attach_adapter (adapter); /* Because Legacy driver don’t have detect function */ if (!driver-> detect  || !address_data) return 0;
I2c Driver: i2c_detect /* initial i2c client structure */ struct i2c_client *temp_client; temp_client->adapter = adapter; /* get address from i2c_client_address_data*/ address_data  =  driver ->address_data; /* check if Legacy driver */ if (! driver ->detect || ! address_data ) /* check normal_i2c ignore probe address */ for(i = 0;  address_data ->normal_i2c[i] != I2C_CLIENT_END ; i += 1)
I2c Driver: i2c_detect_address /* Make sure the address is valid */ ( addr  <  0x03  ||  addr  >  0x77 ) /* Make sure there is something at this address */ i2c_smbus_xfer (adapter, addr, 0, 0, 0,  I2C_SMBUS_QUICK , NULL) /* Finally call the custom detection function */ memset(&info, 0, sizeof(struct i2c_board_info)); driver-> detect (temp_client, kind, &info); use info.type[0] == '\0‘ to check driver->detect function /* Detection succeeded, instantiate the device */ client =  i2c_new_device (adapter, &info); list_add_tail (&client->detected, &driver->clients);
I2c Driver: i2c_new_device Set  i2c_client  info from  i2c_board_info  structure strlcpy (client->name, info->type, sizeof(client->name)); client->addr = info->addr; client->irq = info->irq; ……… ..
I2c Driver: i2c_device_match  I2c_bus_type  is used on new-style driver i2c_device_match   match client i2c_device_id  table && i2c_client table id i2c_device_probe   Call  bma150_probe  function if you defined driver’s probe.
I2c Driver:bma150_probe /* bma150 device create ok if return 0*/ misc_register (&bma_device); /* initial data */ data->smb380. bus_write  = bma150_i2c_write; data->smb380. bus_read  = bma150_i2c_read; data->smb380. delay_msec  = bma150_i2c_delay; data->smb380. dev_addr  = client->addr; smb380_init(&(data->smb380));
I2c Driver: file_operations
Build Linux Kernel Edit Kconfig & Makefile Patch all files(bma150_drivers.c…) Make menuconfig Make uImage
Issue: can’t create device /* Make sure there is something at this address */ i2c_smbus_xfer (adapter, addr, 0, 0, 0,  I2C_SMBUS_QUICK , NULL) Please edit  i2c_smbus_xfer_emulated  function and Change message data length: 0 -> 1
Demo To Do: jni module
Reference Linux Device Drivers, Third Edition
Thank You.

Introduction to Android G Sensor I²C Driver on Android

  • 1.
    Introduction to AndroidG sensor I²C Driver on Android Bo-Yi Wu 2010.06.04 Gemtek Technology Co., Ltd
  • 2.
    Outline What’s Gsensor ? I²C Driver Kernel Patch Issue Reference
  • 3.
    What’s G sensor& Application As accelerometers are more and more present in mobile devices, new features are developed. Portrait & Landscape is one of them. It allows devices to display the information in the right orientation depending on how it is held.
  • 4.
  • 5.
  • 6.
    Stability check STABLE_THRES STABLE_COUNT_MIN calling rate? bigger or smaller?
  • 7.
  • 8.
    I²C : detectioncapability set i2c address value detect call back function detect address fill the structure i2c_board_info
  • 9.
    New-style drivers vsLegacy drivers Legacy drivers duplicate a lot of code . The code needed in each driver to implement a detect callback is way smaller than the code needed to implement a legacy driver.
  • 10.
    New-style drivers: initialfunction module_init ( BMA150_init ); return i2c_add_driver (&bma150_driver); module_exit ( BMA150_exit ); i2c_del_driver (&bma150_driver); __exit && __init (Kernel built in or module)
  • 11.
    G Sensor: bma150_driverstructure New-style driver Legacy driver probe: Callback for device binding (new-style drivers) remove: Callback for device unbinding (new-style drivers) class : What kind of i2c device we instantiate (for detect) (1<<0) for sensor address_data: The I2C addresses to probe, ignore or force (for detect) id_table: List of I2C devices supported by this driver
  • 12.
  • 13.
    New-style drivers: address_data/* Internal numbers to terminate lists */ I2C_CLIENT_END : 0xfffeU I2C_CLIENT_INSMOD_1 ~ I2C_CLIENT_INSMOD_8 I2C_CLIENT_INSMOD_COMMON : define structure address_data normal_i2c, probe, ignore value
  • 14.
    I2c Driver: i2c_register_driver1. new style driver methods can't mix with legacy ones /* check bma150_driver is news style driver or not */ is_newstyle_driver (driver) 2. /* check bma150_driver is Legacy style driver or not */ driver->attach_adapter || driver->detach_adapter || driver->detach_client 4. /* add bma150 driver to list for i2c only */ INIT_LIST_HEAD (&driver->clients) 5. /* Walk the adapters that are already present */ class_for_each_device struct i2c_adapter *adapter = to_i2c_adapter(dev); struct i2c_driver *driver = data; 3. /* register driver with bus, and use bus_add_driver () to add bus driver */ driver_register (&driver->driver);
  • 15.
    I2c Driver: __attach_adapterCall __attach_adapter function New style driver: i2c_detect (adapter, driver); Legacy driver: driver-> attach_adapter (adapter); /* Because Legacy driver don’t have detect function */ if (!driver-> detect || !address_data) return 0;
  • 16.
    I2c Driver: i2c_detect/* initial i2c client structure */ struct i2c_client *temp_client; temp_client->adapter = adapter; /* get address from i2c_client_address_data*/ address_data = driver ->address_data; /* check if Legacy driver */ if (! driver ->detect || ! address_data ) /* check normal_i2c ignore probe address */ for(i = 0; address_data ->normal_i2c[i] != I2C_CLIENT_END ; i += 1)
  • 17.
    I2c Driver: i2c_detect_address/* Make sure the address is valid */ ( addr < 0x03 || addr > 0x77 ) /* Make sure there is something at this address */ i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK , NULL) /* Finally call the custom detection function */ memset(&info, 0, sizeof(struct i2c_board_info)); driver-> detect (temp_client, kind, &info); use info.type[0] == '\0‘ to check driver->detect function /* Detection succeeded, instantiate the device */ client = i2c_new_device (adapter, &info); list_add_tail (&client->detected, &driver->clients);
  • 18.
    I2c Driver: i2c_new_deviceSet i2c_client info from i2c_board_info structure strlcpy (client->name, info->type, sizeof(client->name)); client->addr = info->addr; client->irq = info->irq; ……… ..
  • 19.
    I2c Driver: i2c_device_match I2c_bus_type is used on new-style driver i2c_device_match match client i2c_device_id  table && i2c_client table id i2c_device_probe Call bma150_probe function if you defined driver’s probe.
  • 20.
    I2c Driver:bma150_probe /*bma150 device create ok if return 0*/ misc_register (&bma_device); /* initial data */ data->smb380. bus_write = bma150_i2c_write; data->smb380. bus_read = bma150_i2c_read; data->smb380. delay_msec = bma150_i2c_delay; data->smb380. dev_addr = client->addr; smb380_init(&(data->smb380));
  • 21.
  • 22.
    Build Linux KernelEdit Kconfig & Makefile Patch all files(bma150_drivers.c…) Make menuconfig Make uImage
  • 23.
    Issue: can’t createdevice /* Make sure there is something at this address */ i2c_smbus_xfer (adapter, addr, 0, 0, 0, I2C_SMBUS_QUICK , NULL) Please edit i2c_smbus_xfer_emulated function and Change message data length: 0 -> 1
  • 24.
    Demo To Do:jni module
  • 25.
    Reference Linux DeviceDrivers, Third Edition
  • 26.