Revision 280c6899

View differences:

scout_gumstix/encoder/encoder.c
7 7
#include <linux/semaphore.h>
8 8
#include <linux/interrupt.h>
9 9
#include <linux/gpio.h>
10
#include <asm/uaccess.h>
10
#include <asm/atomic.h>
11 11

  
12 12
MODULE_AUTHOR("Tom Mullins");
13 13
MODULE_LICENSE("GPL");
14 14

  
15
#define BUF_LEN 20
16 15
#define N_ENCODERS 4
17 16
const int enc_pins[N_ENCODERS][2] = {{78, 79}, {80, 81}, {82, 83}, {84, 85}};
18 17
struct class *enc_class = NULL;
19
dev_t first_dev;
20 18

  
21
struct enc_t
19
struct encoder_device
22 20
{
23
  char buf[BUF_LEN+1];
24
  struct cdev cdev;
25
  struct semaphore sem;
26 21
  struct device *device;
22
  int pins[2];
27 23
  int irq[2];
28 24
  int status;
29 25
  atomic_t value;
......
31 27
}
32 28
encs[N_ENCODERS];
33 29

  
34
static int enc_open(struct inode *inode, struct file *file);
35
static ssize_t enc_read(struct file *file, char __user *udata, size_t count,
36
    loff_t *offset);
37
static ssize_t enc_write(struct file *file, const char __user *udata,
38
    size_t count, loff_t *offset);
39
static void enc_free(struct enc_t *enc);
40
static int enc_init(dev_t dev, struct enc_t *enc);
30
static ssize_t enc_show(struct device *dev, struct device_attribute *attr,
31
    char *buf);
32
static ssize_t enc_store(struct device *dev, struct device_attribute *attr,
33
    const char *buf, size_t count);
34
static void enc_free(struct encoder_device *enc);
35
static int enc_init(dev_t dev, struct encoder_device *enc, const int *pins);
41 36

  
42
struct file_operations fops =
43
{
44
  .owner = THIS_MODULE,
45
  .open = enc_open,
46
  .read = enc_read,
47
  .write = enc_write
48
};
49

  
50
static int enc_open(struct inode *inode, struct file *file)
51
{
52
  int i = iminor(inode);
53
  if (i < 0 || i >= N_ENCODERS)
54
  {
55
    return -ENXIO;
56
  }
57
  file->private_data = &encs[i];
58
  return 0;
59
}
37
DEVICE_ATTR(ticks, S_IWUSR | S_IRUGO, enc_show, enc_store);
60 38

  
61
static ssize_t enc_read(struct file *file, char __user *udata, size_t count,
62
    loff_t *offset)
39
static ssize_t enc_show(struct device *dev, struct device_attribute *attr,
40
    char *buf)
63 41
{
64
  int len;
65
  struct enc_t *enc = file->private_data;
66
  if (down_interruptible(&enc->sem))
67
  {
68
    return -ERESTARTSYS;
69
  }
70
  len = snprintf(enc->buf, BUF_LEN+1, "%d\n", atomic_read(&enc->value));
71
  if (*offset > len)
72
  {
73
    return 0;
74
  }
75
  len -= *offset;
76
  if (len > count)
77
  {
78
    len = count;
79
  }
80
  copy_to_user(udata, enc->buf + *offset, len);
81
  *offset += len;
82
  up(&enc->sem);
83
  return len;
42
  size_t nwritten;
43
  struct encoder_device *enc = dev_get_drvdata(dev);
44
  nwritten = scnprintf(buf, PAGE_SIZE, "%d\n", atomic_read(&enc->value));
45
  return nwritten;
84 46
}
85 47

  
86
static ssize_t enc_write(struct file *file, const char __user *udata,
87
    size_t count, loff_t *offset)
48
static ssize_t enc_store(struct device *dev, struct device_attribute *attr,
49
    const char *buf, size_t count)
88 50
{
89 51
  char *end;
90
  int new_value;
91
  struct enc_t *enc = file->private_data;
92
  if (down_interruptible(&enc->sem))
93
  {
94
    return -ERESTARTSYS;
95
  }
96
  if (count > BUF_LEN)
97
  {
98
    count = BUF_LEN;
99
  }
100
  copy_from_user(enc->buf, udata, count);
101
  enc->buf[count] = '\0';
102
  new_value = simple_strtoi(enc->buf, &end, 10);
103
  atomic_set(&enc->value, new_value);
104
  *offset += count;
105
  up(&enc->sem);
52
  struct encoder_device *enc = dev_get_drvdata(dev);
53
  atomic_set(&enc->value, simple_strtol(buf, &end, 10));
106 54
  return count;
107 55
}
108 56

  
109
irqreturn_t intA(int irq, void *enc, struct pt_regs *regs) {
57
irqreturn_t intA(int irq, void *encp) {
58
  struct encoder_device *enc = encp;
110 59
  int this = gpio_get_value(enc->pins[0]);
111 60
  int other = gpio_get_value(enc->pins[1]);
112 61
  if (this == other) {
......
117 66
  return IRQ_HANDLED;
118 67
}
119 68

  
120
irqreturn_t intB(int irq, void *enc, struct pt_regs *regs) {
69
irqreturn_t intB(int irq, void *encp) {
70
  struct encoder_device *enc = encp;
121 71
  int this = gpio_get_value(enc->pins[1]);
122 72
  int other = gpio_get_value(enc->pins[0]);
123 73
  if (this == other) {
......
128 78
  return IRQ_HANDLED;
129 79
}
130 80

  
131
static int enc_init(dev_t dev, struct enc_t *enc, int *pins)
81
static int enc_init(dev_t dev, struct encoder_device *enc, const int *pins)
132 82
{
133
  int err, i;
83
  int i, err;
134 84

  
135 85
  // initialize members
136
  cdev_init(&enc->cdev, &fops);
137
  enc->cdev.owner = THIS_MODULE;
138 86
  enc->dev = dev;
139 87
  enc->status = 0;
140
  sema_init(&enc->sem, 1);
141

  
142
  // make cdev file operations accessible
143
  err = cdev_add(&enc->cdev, enc->dev, N_ENCODERS);
144
  if (err)
145
  {
146
    enc_free(enc);
147
    return err;
148
  }
149
  enc->status = 1;
150 88

  
151 89
  // register gpio and interrupts
152 90
  for (i = 0; i < 2; i++) {
......
166 104
      return 1;
167 105
    }
168 106

  
169
    err = request_irq(enc->irq[i], i? intB:intA, SA_INTERRUPT, "encoder", enc);
107
    err = request_irq(enc->irq[i], i? intB:intA, 0, "encoder", enc);
170 108
    if (err < 0) {
171 109
      printk("Error %d requesting irq %d\n", err, enc->irq[i]);
172 110
      return 1;
......
186 124
  return 0;
187 125
}
188 126

  
189
int enc_create_dev(struct enc_t *enc) {
127
int enc_create_dev(struct encoder_device *enc) {
128
  int err;
190 129

  
191 130
  // make file in /dev
192
  enc->device = device_create(enc_class, NULL, enc->dev, NULL, "enc%d",
131
  enc->device = device_create(enc_class, NULL, enc->dev, enc, "enc%d",
193 132
      MINOR(enc->dev));
194 133
  if (IS_ERR(enc->device))
195 134
  {
......
200 139
  }
201 140
  enc->status = 3;
202 141

  
142
  device_create_file(enc->device, &dev_attr_ticks);
143
  // TODO error check
144
  enc->status = 4;
145

  
203 146
  return 0;
204 147
}
205 148

  
206
static void enc_free(struct enc_t *enc)
149
static void enc_free(struct encoder_device *enc)
207 150
{
208 151
  switch (enc->status)
209 152
  {
153
    case 4:
154
      device_remove_file(enc->device, &dev_attr_ticks);
210 155
    case 3:
211 156
      device_destroy(enc_class, enc->dev);
212 157
      enc->device = NULL;
213 158
    case 2:
214 159
      free_irq(enc->irq[0], enc);
215 160
      free_irq(enc->irq[1], enc);
216
    case 1:
217
      cdev_del(&enc->cdev);
218 161
  }
219 162
  enc->status = 0;
220 163
}
......
230 173
    class_destroy(enc_class);
231 174
    enc_class = NULL;
232 175
  }
233
  unregister_chrdev_region(first_dev, N_ENCODERS);
234 176
}
235 177
module_exit(enc_exit_module);
236 178

  
......
238 180
{
239 181
  int i, err;
240 182

  
241
  // allocate character devices and get major number
242
  err = alloc_chrdev_region(&first_dev, 0, N_ENCODERS, "encoder");
243
  if (err)
244
  {
245
    printk(KERN_ALERT "Error %d in alloc_chrdev_region\n", err);
246
    return 1;
247
  }
248

  
249 183
  // initialize enc structures
250 184
  for (i = 0; i < N_ENCODERS; i++) {
251
    err = enc_init(first_dev + i, &encs[i], enc_pins[i]);
185
    err = enc_init(MKDEV(0, i), &encs[i], enc_pins[i]);
252 186
    if (err)
253 187
    {
254 188
      printk(KERN_WARNING "Error %d initializing encoder %d\n", err, i);
255 189
      enc_exit_module();
256
      return 1;
190
      return err;
257 191
    }
258 192
  }
259 193

  
......
274 208
      {
275 209
        printk(KERN_WARNING "Error %d creating enc%d\n", err, i);
276 210
        enc_exit_module();
277
        return 1;
211
        return err;
278 212
      }
279 213
    }
280 214
  }

Also available in: Unified diff