static void lis3dh_suspend(struct early_suspend *h) { struct i2c_client *client = container_of(lis3dh_device.parent, struct i2c_client, dev); struct lis3dh_data *lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client); lis3dh_close(client); }
// Init lis3dh_context lis3dh_init(int bus, int addr, int cs) { lis3dh_context dev = (lis3dh_context) malloc(sizeof(struct _lis3dh_context)); if (!dev) { return NULL; } // Zero out context memset((void*) dev, 0, sizeof(struct _lis3dh_context)); // Make sure MRAA is initialized if (mraa_init() != MRAA_SUCCESS) { printf("%s: mraa_init() failed\n", __FUNCTION__); lis3dh_close(dev); return NULL; } if (addr < 0) { // SPI if (!(dev->spi = mraa_spi_init(bus))) { printf("%s: mraa_spi_init() for bus %d failed\n", __FUNCTION__, bus); lis3dh_close(dev); return NULL; } // Only create CS context if we are actually using a valid pin. // A hardware controlled pin should specify CS as -1. if (cs >= 0) { if (!(dev->gpioCS = mraa_gpio_init(cs))) { printf("%s: mraa_gpio_init() for CS pin %d failed\n", __FUNCTION__, cs); lis3dh_close(dev); return NULL; } mraa_gpio_dir(dev->gpioCS, MRAA_GPIO_OUT); } mraa_spi_mode(dev->spi, MRAA_SPI_MODE0); if (mraa_spi_frequency(dev->spi, 5000000)) { printf("%s: mraa_spi_frequency() failed\n", __FUNCTION__); lis3dh_close(dev); return NULL; } } else { // I2C if (!(dev->i2c = mraa_i2c_init(bus))) { printf("%s: mraa_i2c_init() for bus %d failed\n", __FUNCTION__, bus); lis3dh_close(dev); return NULL; } if (mraa_i2c_address(dev->i2c, addr)) { printf("%s: mraa_i2c_address() for address 0x%x failed\n", __FUNCTION__, addr); lis3dh_close(dev); return NULL; } } // Check the chip id uint8_t chipID = lis3dh_get_chip_id(dev); if (chipID != LIS3DH_CHIPID) { printf("%s: invalid chip id: %02x, expected %02x\n", __FUNCTION__, chipID, LIS3DH_CHIPID); lis3dh_close(dev); return NULL; } // Call devinit with default options if (lis3dh_devinit(dev, LIS3DH_ODR_100HZ, LIS3DH_FS_2G, true)) { printf("%s: lis3dh_devinit() failed\n", __FUNCTION__); lis3dh_close(dev); return NULL; } return dev; }
static long lis3dh_ioctl(struct file *file, unsigned int cmd,unsigned long arg) { int liRet = -1; char rate; void __user *argp = (void __user *)arg; struct lis3dh_axis sense_data = {0}; struct i2c_client *client = container_of(lis3dh_device.parent, struct i2c_client, dev); struct lis3dh_data* lis3dh = (struct lis3dh_data *)i2c_get_clientdata(client); switch (cmd) { case ST_IOCTL_APP_SET_RATE: if (copy_from_user(&rate, argp, sizeof(rate))) { return -EFAULT; } else { //nothing } break; default: break; } switch (cmd) { case ST_IOCTL_START: mutex_lock(&(lis3dh->operation_mutex) ); stprintkd("to perform 'ST_IOCTL_START', former 'start_count' is %d.", lis3dh->start_count); (lis3dh->start_count)++; if ( 1 == lis3dh->start_count ) { atomic_set(&(lis3dh->data_ready), 0); if ( (liRet = lis3dh_start(client, LIS3DH_RATE_12P5) ) < 0 ) { mutex_unlock(&(lis3dh->operation_mutex) ); return liRet; } else { //nothing } } else { //nothing } mutex_unlock(&(lis3dh->operation_mutex) ); stprintkd("finish 'ST_IOCTL_START', ret = %d.", liRet); return 0; case ST_IOCTL_CLOSE: mutex_lock(&(lis3dh->operation_mutex) ); stprintkd("to perform 'ST_IOCTL_CLOSE', former 'start_count' is %d, PID : %d", lis3dh->start_count, get_current()->pid); if ( 0 == (--(lis3dh->start_count) ) ) { atomic_set(&(lis3dh->data_ready), 0); if ( (liRet = lis3dh_close(client) ) < 0 ) { mutex_unlock(&(lis3dh->operation_mutex) ); return liRet; } else { //nothing } } mutex_unlock(&(lis3dh->operation_mutex) ); return 0; case ST_IOCTL_APP_SET_RATE: liRet = lis3dh_reset_rate(client, rate); if (liRet< 0) { return liRet; } else { //nothing } break; case ST_IOCTL_GETDATA: if ( (liRet = lis3dh_get_cached_data(client, &sense_data) ) < 0 ) { printk("failed to get cached sense data, ret = %d.", liRet); return liRet; } else { //nothing } break; default: return -ENOTTY; } switch (cmd) { case ST_IOCTL_GETDATA: if ( copy_to_user(argp, &sense_data, sizeof(sense_data) ) ) { printk("failed to copy sense data to user space."); return -EFAULT; } else { //npthing } break; default: break; } return 0; }