/* * Updates the cached state of a character device * based on sensor data. Must be called with the * character device state lock held. */ static int lunix_chrdev_state_update(struct lunix_chrdev_state_struct *state) { //struct lunix_sensor_struct *sensor; unsigned long flags; int need_refresh, n; long int data; uint32_t raw_data, raw_time; char c; debug("entering lunix_chrdev_state_update\n"); /* * Grab the raw data quickly, hold the * spinlock for as little as possible. */ /* ? */ /* Why use spinlocks? See LDD3, p. 119 */ /* * Any new data available? */ /* ? */ need_refresh = lunix_chrdev_state_needs_refresh(state); if (need_refresh) { debug("Spinlock almost at hand.\n"); spin_lock_irqsave(&(state->sensor->lock), flags); debug("Spinlock at hand.\n"); raw_data = state->sensor->msr_data[state->type]->values[0]; raw_time = state->sensor->msr_data[state->type]->last_update; spin_unlock_irqrestore(&(state->sensor->lock), flags); } else { debug("Again!\n"); return -EAGAIN; /* No new data */ } /* * Now we can take our time to format them, * holding only the private state semaphore */ /* ? */ switch(state->type) { debug("case 0\n"); case BATT: data = lookup_voltage[raw_data]; break; debug("case 1\n"); case TEMP: data = lookup_temperature[raw_data]; break; debug("case 2\n"); case LIGHT: data = lookup_light[raw_data]; break; default: ; debug("case default\n"); } c = (data >= 0) ? '+' : '-'; data = (data > 0) ? data : (-data); n = sprintf(state->buf_data, "%c%ld.%ld\n", c, data/1000, data%1000 ); state->buf_timestamp = raw_time; state->buf_lim = n; debug("leaving\n"); return 0; }
static ssize_t lunix_chrdev_read(struct file *filp, char __user *usrbuf, size_t cnt, loff_t *f_pos) { ssize_t ret; struct lunix_sensor_struct *sensor; struct lunix_chrdev_state_struct *state; int di,bytes; debug("entering\n"); state = filp->private_data; WARN_ON(!state); sensor = state->sensor; WARN_ON(!sensor); /* Lock? */ di = down_interruptible(&(state->lock)); if (di) { /* Failed to V */ debug("failed down_interruptible\n"); ret = -EINTR; goto out; } /* * If the cached character device state needs to be * updated by actual sensor data (i.e. we need to report * on a "fresh" measurement, do so */ if (*f_pos == 0) { while (lunix_chrdev_state_update(state) == -EAGAIN) { /* ? */ /* The process needs to sleep */ /* See LDD3, page 153 for a hint */ up(&(state->lock)); if (wait_event_interruptible(sensor->wq, lunix_chrdev_state_needs_refresh(state))) return -ERESTARTSYS; /* signal: tell the fs layer to handle it */ di = down_interruptible(&(state->lock)); if (di) { /* Failed to V */ debug("failed down_interruptible\n"); ret = -EINTR; goto out; } } } debug("ready to copy_to_user\n"); bytes = (cnt < state->buf_lim - *f_pos) ? cnt : state->buf_lim-*f_pos; ret = copy_to_user(usrbuf, state->buf_data + *f_pos, bytes); if (ret) { /* Failed to copy */ debug("copy_to_user failed\n"); } /* Auto-rewind on EOF mode? */ /* ? */ (*f_pos)+=bytes; if(*f_pos >= state->buf_lim) *f_pos=0; ret = bytes; out: /* Unlock? */ up(&(state->lock)); return ret; }
/* * Updates the cached state of a character device * based on sensor data. Must be called with the * character device state lock held. */ static int lunix_chrdev_state_update(struct lunix_chrdev_state_struct *state) { struct lunix_sensor_struct *sensor; unsigned long flags; int new_data; uint16_t portion; /* fract_portion; */ long res ; /* res_fract */ uint32_t temp, temp1 ; unsigned char temp_buf[20]; /* * Grab the raw data quickly, hold the * spinlock for as little as possible. */ /* ? */ /* Why use spinlocks? See LDD3, p. 119 */ debug("going into lunix_chrdev_state_update \n "); spin_lock_irqsave(&sensor->lock, flags ); /* * Any new data available? */ /* ? */ new_data = lunix_chrdev_state_needs_refresh(&state); spin_unlock_irqrestore(&sensor->lock, flags); /* * Now we can take our time to format them, * holding only the private state semaphore */ /* ? */ if (down_interruptible(&state->lock)) { debug("Could not acquire lock\n"); return -ERESTARTSYS; } if ((new_data) == 1) { debug("there is new data") memcpy(&temp1,((sensor->msr_data[state->type])->values[0]), 4); temp = cpu_to_le32(temp1); memcpy(&portion,&temp,2); /* temp = temp >> 16; */ /* memcpy(&integ_portion,&temp,2); */ if ((state->type) == 0 ) { res = uint16_to_batt(portion); /* res_fract = uint16_to_batt(fract_portion); */ } if ((state->type) == 1 ){ res = uint16_to_temp(portion); /* res_fract = uint16_to_temp(fract_portion); */ } if ((state->type) == 2 ){ res = uint16_to_light(portion); /* res_fract = uint16_to_light(fract_portion); */ } up(&state->lock); sprintf(temp_buf, "%ld" , res); (state->buf_lim) = strlen(temp_buf); memcpy((state->buf_data), &temp_buf, (state->buf_lim)); return 0; } else { up(&state->lock); return -EAGAIN; } debug("leaving\n"); return 0; }