Project

General

Profile

Revision 280c6899

ID280c68998acecf0ff9e8e44a35562cab91e439b0
Parent c0b686d7
Child 4807b056

Added by Thomas Mullins over 11 years ago

Changes to the encoder driver

It now uses an entry in sysfs instead of /dev. Also it now compiles.

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