]>
Commit | Line | Data |
---|---|---|
874bcba6 MW |
1 | /* |
2 | * userspace interface for pi433 radio module | |
3 | * | |
4 | * Pi433 is a 433MHz radio module for the Raspberry Pi. | |
5 | * It is based on the HopeRf Module RFM69CW. Therefore inside of this | |
6 | * driver, you'll find an abstraction of the rf69 chip. | |
7 | * | |
8 | * If needed, this driver could be extended, to also support other | |
9 | * devices, basing on HopeRfs rf69. | |
10 | * | |
11 | * The driver can also be extended, to support other modules of | |
12 | * HopeRf with a similar interace - e. g. RFM69HCW, RFM12, RFM95, ... | |
13 | * | |
14 | * Copyright (C) 2016 Wolf-Entwicklungen | |
15 | * Marcus Wolf <linux@wolf-entwicklungen.de> | |
16 | * | |
17 | * This program is free software; you can redistribute it and/or modify | |
18 | * it under the terms of the GNU General Public License as published by | |
19 | * the Free Software Foundation; either version 2 of the License, or | |
20 | * (at your option) any later version. | |
21 | * | |
22 | * This program is distributed in the hope that it will be useful, | |
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | * GNU General Public License for more details. | |
26 | */ | |
27 | ||
28 | #undef DEBUG | |
29 | ||
30 | #include <linux/init.h> | |
31 | #include <linux/module.h> | |
32 | #include <linux/idr.h> | |
33 | #include <linux/ioctl.h> | |
34 | #include <linux/uaccess.h> | |
35 | #include <linux/fs.h> | |
36 | #include <linux/device.h> | |
37 | #include <linux/cdev.h> | |
38 | #include <linux/err.h> | |
39 | #include <linux/kfifo.h> | |
40 | #include <linux/errno.h> | |
41 | #include <linux/mutex.h> | |
42 | #include <linux/of.h> | |
43 | #include <linux/of_device.h> | |
44 | #include <linux/interrupt.h> | |
45 | #include <linux/irq.h> | |
46 | #include <linux/gpio/consumer.h> | |
47 | #include <linux/kthread.h> | |
48 | #include <linux/wait.h> | |
49 | #include <linux/spi/spi.h> | |
50 | #ifdef CONFIG_COMPAT | |
51 | #include <asm/compat.h> | |
52 | #endif | |
53 | ||
54 | #include "pi433_if.h" | |
55 | #include "rf69.h" | |
56 | ||
57 | ||
58 | #define N_PI433_MINORS (1U << MINORBITS) /*32*/ /* ... up to 256 */ | |
59 | #define MAX_MSG_SIZE 900 /* min: FIFO_SIZE! */ | |
60 | #define MSG_FIFO_SIZE 65536 /* 65536 = 2^16 */ | |
61 | #define NUM_DIO 2 | |
62 | ||
63 | static dev_t pi433_dev; | |
64 | static DEFINE_IDR(pi433_idr); | |
65 | static DEFINE_MUTEX(minor_lock); /* Protect idr accesses */ | |
66 | ||
67 | static struct class *pi433_class; /* mainly for udev to create /dev/pi433 */ | |
68 | ||
69 | /* tx config is instance specific | |
056eeda2 DR |
70 | * so with each open a new tx config struct is needed |
71 | */ | |
874bcba6 | 72 | /* rx config is device specific |
056eeda2 DR |
73 | * so we have just one rx config, ebedded in device struct |
74 | */ | |
874bcba6 MW |
75 | struct pi433_device { |
76 | /* device handling related values */ | |
77 | dev_t devt; | |
78 | int minor; | |
79 | struct device *dev; | |
80 | struct cdev *cdev; | |
81 | struct spi_device *spi; | |
82 | unsigned users; | |
83 | ||
84 | /* irq related values */ | |
85 | struct gpio_desc *gpiod[NUM_DIO]; | |
86 | int irq_num[NUM_DIO]; | |
87 | u8 irq_state[NUM_DIO]; | |
88 | ||
89 | /* tx related values */ | |
90 | STRUCT_KFIFO_REC_1(MSG_FIFO_SIZE) tx_fifo; | |
91 | struct mutex tx_fifo_lock; // TODO: check, whether necessary or obsolete | |
92 | struct task_struct *tx_task_struct; | |
93 | wait_queue_head_t tx_wait_queue; | |
94 | u8 free_in_fifo; | |
62f39d49 | 95 | char buffer[MAX_MSG_SIZE]; |
874bcba6 MW |
96 | |
97 | /* rx related values */ | |
98 | struct pi433_rx_cfg rx_cfg; | |
99 | u8 *rx_buffer; | |
100 | unsigned int rx_buffer_size; | |
101 | u32 rx_bytes_to_drop; | |
102 | u32 rx_bytes_dropped; | |
103 | unsigned int rx_position; | |
104 | struct mutex rx_lock; | |
105 | wait_queue_head_t rx_wait_queue; | |
106 | ||
107 | /* fifo wait queue */ | |
108 | struct task_struct *fifo_task_struct; | |
109 | wait_queue_head_t fifo_wait_queue; | |
110 | ||
111 | /* flags */ | |
112 | bool rx_active; | |
113 | bool tx_active; | |
114 | bool interrupt_rx_allowed; | |
115 | }; | |
116 | ||
117 | struct pi433_instance { | |
118 | struct pi433_device *device; | |
119 | struct pi433_tx_cfg tx_cfg; | |
120 | }; | |
121 | ||
122 | /*-------------------------------------------------------------------------*/ | |
123 | ||
124 | /* macro for checked access of registers of radio module */ | |
125 | #define SET_CHECKED(retval) \ | |
126 | if (retval < 0) \ | |
127 | return retval; | |
128 | ||
129 | /*-------------------------------------------------------------------------*/ | |
130 | ||
131 | /* GPIO interrupt handlers */ | |
ee26e236 | 132 | static irqreturn_t DIO0_irq_handler(int irq, void *dev_id) |
874bcba6 MW |
133 | { |
134 | struct pi433_device *device = dev_id; | |
135 | ||
136 | if (device->irq_state[DIO0] == DIO_PacketSent) | |
137 | { | |
138 | device->free_in_fifo = FIFO_SIZE; | |
5a60d7ba | 139 | dev_dbg(device->dev, "DIO0 irq: Packet sent\n"); |
874bcba6 MW |
140 | wake_up_interruptible(&device->fifo_wait_queue); |
141 | } | |
142 | else if (device->irq_state[DIO0] == DIO_Rssi_DIO0) | |
143 | { | |
5a60d7ba | 144 | dev_dbg(device->dev, "DIO0 irq: RSSI level over threshold\n"); |
874bcba6 MW |
145 | wake_up_interruptible(&device->rx_wait_queue); |
146 | } | |
147 | else if (device->irq_state[DIO0] == DIO_PayloadReady) | |
148 | { | |
5a60d7ba | 149 | dev_dbg(device->dev, "DIO0 irq: PayloadReady\n"); |
874bcba6 MW |
150 | device->free_in_fifo = 0; |
151 | wake_up_interruptible(&device->fifo_wait_queue); | |
152 | } | |
153 | ||
ee26e236 | 154 | return IRQ_HANDLED; |
874bcba6 MW |
155 | } |
156 | ||
ee26e236 | 157 | static irqreturn_t DIO1_irq_handler(int irq, void *dev_id) |
874bcba6 MW |
158 | { |
159 | struct pi433_device *device = dev_id; | |
160 | ||
161 | if (device->irq_state[DIO1] == DIO_FifoNotEmpty_DIO1) | |
162 | { | |
163 | device->free_in_fifo = FIFO_SIZE; | |
164 | } | |
165 | else if (device->irq_state[DIO1] == DIO_FifoLevel) | |
166 | { | |
167 | if (device->rx_active) device->free_in_fifo = FIFO_THRESHOLD - 1; | |
168 | else device->free_in_fifo = FIFO_SIZE - FIFO_THRESHOLD - 1; | |
169 | } | |
5a60d7ba HM |
170 | dev_dbg(device->dev, |
171 | "DIO1 irq: %d bytes free in fifo\n", device->free_in_fifo); | |
874bcba6 MW |
172 | wake_up_interruptible(&device->fifo_wait_queue); |
173 | ||
ee26e236 | 174 | return IRQ_HANDLED; |
874bcba6 MW |
175 | } |
176 | ||
874bcba6 MW |
177 | /*-------------------------------------------------------------------------*/ |
178 | ||
179 | static int | |
180 | rf69_set_rx_cfg(struct pi433_device *dev, struct pi433_rx_cfg *rx_cfg) | |
181 | { | |
125a452c | 182 | int ret; |
874bcba6 MW |
183 | int payload_length; |
184 | ||
185 | /* receiver config */ | |
186 | SET_CHECKED(rf69_set_frequency (dev->spi, rx_cfg->frequency)); | |
187 | SET_CHECKED(rf69_set_bit_rate (dev->spi, rx_cfg->bit_rate)); | |
188 | SET_CHECKED(rf69_set_modulation (dev->spi, rx_cfg->modulation)); | |
189 | SET_CHECKED(rf69_set_antenna_impedance (dev->spi, rx_cfg->antenna_impedance)); | |
190 | SET_CHECKED(rf69_set_rssi_threshold (dev->spi, rx_cfg->rssi_threshold)); | |
191 | SET_CHECKED(rf69_set_ook_threshold_dec (dev->spi, rx_cfg->thresholdDecrement)); | |
192 | SET_CHECKED(rf69_set_bandwidth (dev->spi, rx_cfg->bw_mantisse, rx_cfg->bw_exponent)); | |
193 | SET_CHECKED(rf69_set_bandwidth_during_afc(dev->spi, rx_cfg->bw_mantisse, rx_cfg->bw_exponent)); | |
194 | SET_CHECKED(rf69_set_dagc (dev->spi, rx_cfg->dagc)); | |
195 | ||
196 | dev->rx_bytes_to_drop = rx_cfg->bytes_to_drop; | |
197 | ||
198 | /* packet config */ | |
199 | /* enable */ | |
200 | SET_CHECKED(rf69_set_sync_enable(dev->spi, rx_cfg->enable_sync)); | |
201 | if (rx_cfg->enable_sync == optionOn) | |
202 | { | |
203 | SET_CHECKED(rf69_set_fifo_fill_condition(dev->spi, afterSyncInterrupt)); | |
204 | } | |
205 | else | |
206 | { | |
207 | SET_CHECKED(rf69_set_fifo_fill_condition(dev->spi, always)); | |
208 | } | |
125a452c EG |
209 | if (rx_cfg->enable_length_byte == optionOn) { |
210 | ret = rf69_set_packet_format(dev->spi, packetLengthVar); | |
211 | if (ret < 0) | |
212 | return ret; | |
213 | } else { | |
214 | ret = rf69_set_packet_format(dev->spi, packetLengthFix); | |
215 | if (ret < 0) | |
216 | return ret; | |
217 | } | |
874bcba6 MW |
218 | SET_CHECKED(rf69_set_adressFiltering(dev->spi, rx_cfg->enable_address_filtering)); |
219 | SET_CHECKED(rf69_set_crc_enable (dev->spi, rx_cfg->enable_crc)); | |
220 | ||
221 | /* lengths */ | |
222 | SET_CHECKED(rf69_set_sync_size(dev->spi, rx_cfg->sync_length)); | |
223 | if (rx_cfg->enable_length_byte == optionOn) | |
224 | { | |
225 | SET_CHECKED(rf69_set_payload_length(dev->spi, 0xff)); | |
226 | } | |
227 | else if (rx_cfg->fixed_message_length != 0) | |
228 | { | |
229 | payload_length = rx_cfg->fixed_message_length; | |
230 | if (rx_cfg->enable_length_byte == optionOn) payload_length++; | |
231 | if (rx_cfg->enable_address_filtering != filteringOff) payload_length++; | |
232 | SET_CHECKED(rf69_set_payload_length(dev->spi, payload_length)); | |
233 | } | |
234 | else | |
235 | { | |
236 | SET_CHECKED(rf69_set_payload_length(dev->spi, 0)); | |
237 | } | |
238 | ||
239 | /* values */ | |
240 | if (rx_cfg->enable_sync == optionOn) | |
241 | { | |
242 | SET_CHECKED(rf69_set_sync_values(dev->spi, rx_cfg->sync_pattern)); | |
243 | } | |
244 | if (rx_cfg->enable_address_filtering != filteringOff) | |
245 | { | |
246 | SET_CHECKED(rf69_set_node_address (dev->spi, rx_cfg->node_address)); | |
247 | SET_CHECKED(rf69_set_broadcast_address(dev->spi, rx_cfg->broadcast_address)); | |
248 | } | |
249 | ||
250 | return 0; | |
251 | } | |
252 | ||
253 | static int | |
254 | rf69_set_tx_cfg(struct pi433_device *dev, struct pi433_tx_cfg *tx_cfg) | |
255 | { | |
125a452c EG |
256 | int ret; |
257 | ||
874bcba6 MW |
258 | SET_CHECKED(rf69_set_frequency (dev->spi, tx_cfg->frequency)); |
259 | SET_CHECKED(rf69_set_bit_rate (dev->spi, tx_cfg->bit_rate)); | |
260 | SET_CHECKED(rf69_set_modulation (dev->spi, tx_cfg->modulation)); | |
261 | SET_CHECKED(rf69_set_deviation (dev->spi, tx_cfg->dev_frequency)); | |
262 | SET_CHECKED(rf69_set_pa_ramp (dev->spi, tx_cfg->pa_ramp)); | |
263 | SET_CHECKED(rf69_set_modulation_shaping(dev->spi, tx_cfg->modShaping)); | |
264 | SET_CHECKED(rf69_set_tx_start_condition(dev->spi, tx_cfg->tx_start_condition)); | |
265 | ||
266 | /* packet format enable */ | |
267 | if (tx_cfg->enable_preamble == optionOn) | |
268 | { | |
269 | SET_CHECKED(rf69_set_preamble_length(dev->spi, tx_cfg->preamble_length)); | |
270 | } | |
271 | else | |
272 | { | |
273 | SET_CHECKED(rf69_set_preamble_length(dev->spi, 0)); | |
274 | } | |
275 | SET_CHECKED(rf69_set_sync_enable (dev->spi, tx_cfg->enable_sync)); | |
125a452c EG |
276 | if (tx_cfg->enable_length_byte == optionOn) { |
277 | ret = rf69_set_packet_format(dev->spi, packetLengthVar); | |
278 | if (ret < 0) | |
279 | return ret; | |
280 | } else { | |
281 | ret = rf69_set_packet_format(dev->spi, packetLengthFix); | |
282 | if (ret < 0) | |
283 | return ret; | |
284 | } | |
874bcba6 MW |
285 | SET_CHECKED(rf69_set_crc_enable (dev->spi, tx_cfg->enable_crc)); |
286 | ||
287 | /* configure sync, if enabled */ | |
69af5d92 | 288 | if (tx_cfg->enable_sync == optionOn) { |
874bcba6 MW |
289 | SET_CHECKED(rf69_set_sync_size(dev->spi, tx_cfg->sync_length)); |
290 | SET_CHECKED(rf69_set_sync_values(dev->spi, tx_cfg->sync_pattern)); | |
291 | } | |
292 | ||
293 | return 0; | |
294 | } | |
295 | ||
296 | /*-------------------------------------------------------------------------*/ | |
297 | ||
298 | static int | |
299 | pi433_start_rx(struct pi433_device *dev) | |
300 | { | |
301 | int retval; | |
302 | ||
303 | /* return without action, if no pending read request */ | |
304 | if (!dev->rx_active) | |
305 | return 0; | |
306 | ||
307 | /* setup for receiving */ | |
308 | retval = rf69_set_rx_cfg(dev, &dev->rx_cfg); | |
309 | if (retval) return retval; | |
310 | ||
311 | /* setup rssi irq */ | |
312 | SET_CHECKED(rf69_set_dio_mapping(dev->spi, DIO0, DIO_Rssi_DIO0)); | |
313 | dev->irq_state[DIO0] = DIO_Rssi_DIO0; | |
314 | irq_set_irq_type(dev->irq_num[DIO0], IRQ_TYPE_EDGE_RISING); | |
315 | ||
316 | /* setup fifo level interrupt */ | |
317 | SET_CHECKED(rf69_set_fifo_threshold(dev->spi, FIFO_SIZE - FIFO_THRESHOLD)); | |
318 | SET_CHECKED(rf69_set_dio_mapping(dev->spi, DIO1, DIO_FifoLevel)); | |
319 | dev->irq_state[DIO1] = DIO_FifoLevel; | |
320 | irq_set_irq_type(dev->irq_num[DIO1], IRQ_TYPE_EDGE_RISING); | |
321 | ||
322 | /* set module to receiving mode */ | |
323 | SET_CHECKED(rf69_set_mode(dev->spi, receive)); | |
324 | ||
325 | return 0; | |
326 | } | |
327 | ||
328 | ||
329 | /*-------------------------------------------------------------------------*/ | |
330 | ||
7de77a39 | 331 | static int |
874bcba6 MW |
332 | pi433_receive(void *data) |
333 | { | |
334 | struct pi433_device *dev = data; | |
335 | struct spi_device *spi = dev->spi; /* needed for SET_CHECKED */ | |
336 | int bytes_to_read, bytes_total; | |
337 | int retval; | |
338 | ||
339 | dev->interrupt_rx_allowed = false; | |
340 | ||
341 | /* wait for any tx to finish */ | |
342 | dev_dbg(dev->dev,"rx: going to wait for any tx to finish"); | |
343 | retval = wait_event_interruptible(dev->rx_wait_queue, !dev->tx_active); | |
344 | if(retval) /* wait was interrupted */ | |
345 | { | |
346 | dev->interrupt_rx_allowed = true; | |
347 | wake_up_interruptible(&dev->tx_wait_queue); | |
348 | return retval; | |
349 | } | |
350 | ||
351 | /* prepare status vars */ | |
352 | dev->free_in_fifo = FIFO_SIZE; | |
353 | dev->rx_position = 0; | |
354 | dev->rx_bytes_dropped = 0; | |
355 | ||
356 | /* setup radio module to listen for something "in the air" */ | |
357 | retval = pi433_start_rx(dev); | |
358 | if (retval) | |
359 | return retval; | |
360 | ||
361 | /* now check RSSI, if low wait for getting high (RSSI interrupt) */ | |
362 | while ( !rf69_get_flag(dev->spi, rssiExceededThreshold) ) | |
363 | { | |
364 | /* allow tx to interrupt us while waiting for high RSSI */ | |
365 | dev->interrupt_rx_allowed = true; | |
366 | wake_up_interruptible(&dev->tx_wait_queue); | |
367 | ||
368 | /* wait for RSSI level to become high */ | |
369 | dev_dbg(dev->dev, "rx: going to wait for high RSSI level"); | |
370 | retval = wait_event_interruptible(dev->rx_wait_queue, | |
371 | rf69_get_flag(dev->spi, | |
372 | rssiExceededThreshold)); | |
373 | if (retval) goto abort; /* wait was interrupted */ | |
374 | dev->interrupt_rx_allowed = false; | |
375 | ||
376 | /* cross check for ongoing tx */ | |
377 | if (!dev->tx_active) break; | |
378 | } | |
379 | ||
380 | /* configure payload ready irq */ | |
381 | SET_CHECKED(rf69_set_dio_mapping(spi, DIO0, DIO_PayloadReady)); | |
382 | dev->irq_state[DIO0] = DIO_PayloadReady; | |
383 | irq_set_irq_type(dev->irq_num[DIO0], IRQ_TYPE_EDGE_RISING); | |
384 | ||
385 | /* fixed or unlimited length? */ | |
386 | if (dev->rx_cfg.fixed_message_length != 0) | |
387 | { | |
388 | if (dev->rx_cfg.fixed_message_length > dev->rx_buffer_size) | |
389 | { | |
390 | retval = -1; | |
391 | goto abort; | |
392 | } | |
393 | bytes_total = dev->rx_cfg.fixed_message_length; | |
394 | dev_dbg(dev->dev,"rx: msg len set to %d by fixed length", bytes_total); | |
395 | } | |
396 | else | |
397 | { | |
398 | bytes_total = dev->rx_buffer_size; | |
399 | dev_dbg(dev->dev, "rx: msg len set to %d as requested by read", bytes_total); | |
400 | } | |
401 | ||
402 | /* length byte enabled? */ | |
403 | if (dev->rx_cfg.enable_length_byte == optionOn) | |
404 | { | |
405 | retval = wait_event_interruptible(dev->fifo_wait_queue, | |
406 | dev->free_in_fifo < FIFO_SIZE); | |
407 | if (retval) goto abort; /* wait was interrupted */ | |
408 | ||
409 | rf69_read_fifo(spi, (u8 *)&bytes_total, 1); | |
69af5d92 | 410 | if (bytes_total > dev->rx_buffer_size) { |
874bcba6 MW |
411 | retval = -1; |
412 | goto abort; | |
413 | } | |
414 | dev->free_in_fifo++; | |
415 | dev_dbg(dev->dev, "rx: msg len reset to %d due to length byte", bytes_total); | |
416 | } | |
417 | ||
418 | /* address byte enabled? */ | |
419 | if (dev->rx_cfg.enable_address_filtering != filteringOff) | |
420 | { | |
421 | u8 dummy; | |
422 | ||
423 | bytes_total--; | |
424 | ||
425 | retval = wait_event_interruptible(dev->fifo_wait_queue, | |
426 | dev->free_in_fifo < FIFO_SIZE); | |
427 | if (retval) goto abort; /* wait was interrupted */ | |
428 | ||
429 | rf69_read_fifo(spi, &dummy, 1); | |
430 | dev->free_in_fifo++; | |
431 | dev_dbg(dev->dev, "rx: address byte stripped off"); | |
432 | } | |
433 | ||
434 | /* get payload */ | |
435 | while (dev->rx_position < bytes_total) | |
436 | { | |
437 | if ( !rf69_get_flag(dev->spi, payloadReady) ) | |
438 | { | |
439 | retval = wait_event_interruptible(dev->fifo_wait_queue, | |
440 | dev->free_in_fifo < FIFO_SIZE); | |
441 | if (retval) goto abort; /* wait was interrupted */ | |
442 | } | |
443 | ||
444 | /* need to drop bytes or acquire? */ | |
445 | if (dev->rx_bytes_to_drop > dev->rx_bytes_dropped) | |
446 | bytes_to_read = dev->rx_bytes_to_drop - dev->rx_bytes_dropped; | |
447 | else | |
448 | bytes_to_read = bytes_total - dev->rx_position; | |
449 | ||
450 | ||
451 | /* access the fifo */ | |
452 | if (bytes_to_read > FIFO_SIZE - dev->free_in_fifo) | |
453 | bytes_to_read = FIFO_SIZE - dev->free_in_fifo; | |
454 | retval = rf69_read_fifo(spi, | |
455 | &dev->rx_buffer[dev->rx_position], | |
456 | bytes_to_read); | |
457 | if (retval) goto abort; /* read failed */ | |
458 | dev->free_in_fifo += bytes_to_read; | |
459 | ||
460 | /* adjust status vars */ | |
461 | if (dev->rx_bytes_to_drop > dev->rx_bytes_dropped) | |
462 | dev->rx_bytes_dropped += bytes_to_read; | |
463 | else | |
464 | dev->rx_position += bytes_to_read; | |
465 | } | |
466 | ||
467 | ||
2ebd34ca | 468 | /* rx done, wait was interrupted or error occurred */ |
874bcba6 MW |
469 | abort: |
470 | dev->interrupt_rx_allowed = true; | |
471 | SET_CHECKED(rf69_set_mode(dev->spi, standby)); | |
472 | wake_up_interruptible(&dev->tx_wait_queue); | |
473 | ||
474 | if (retval) | |
475 | return retval; | |
476 | else | |
477 | return bytes_total; | |
478 | } | |
479 | ||
7de77a39 | 480 | static int |
874bcba6 MW |
481 | pi433_tx_thread(void *data) |
482 | { | |
483 | struct pi433_device *device = data; | |
484 | struct spi_device *spi = device->spi; /* needed for SET_CHECKED */ | |
485 | struct pi433_tx_cfg tx_cfg; | |
62f39d49 | 486 | u8 *buffer = device->buffer; |
874bcba6 MW |
487 | size_t size; |
488 | bool rx_interrupted = false; | |
489 | int position, repetitions; | |
490 | int retval; | |
491 | ||
492 | while (1) | |
493 | { | |
494 | /* wait for fifo to be populated or for request to terminate*/ | |
495 | dev_dbg(device->dev, "thread: going to wait for new messages"); | |
496 | wait_event_interruptible(device->tx_wait_queue, | |
497 | ( !kfifo_is_empty(&device->tx_fifo) || | |
498 | kthread_should_stop() )); | |
499 | if ( kthread_should_stop() ) | |
500 | return 0; | |
501 | ||
502 | /* get data from fifo in the following order: | |
056eeda2 DR |
503 | * - tx_cfg |
504 | * - size of message | |
505 | * - message | |
506 | */ | |
874bcba6 MW |
507 | mutex_lock(&device->tx_fifo_lock); |
508 | ||
509 | retval = kfifo_out(&device->tx_fifo, &tx_cfg, sizeof(tx_cfg)); | |
69af5d92 | 510 | if (retval != sizeof(tx_cfg)) { |
874bcba6 MW |
511 | dev_dbg(device->dev, "reading tx_cfg from fifo failed: got %d byte(s), expected %d", retval, (unsigned int)sizeof(tx_cfg) ); |
512 | mutex_unlock(&device->tx_fifo_lock); | |
513 | continue; | |
514 | } | |
515 | ||
516 | retval = kfifo_out(&device->tx_fifo, &size, sizeof(size_t)); | |
69af5d92 | 517 | if (retval != sizeof(size_t)) { |
874bcba6 MW |
518 | dev_dbg(device->dev, "reading msg size from fifo failed: got %d, expected %d", retval, (unsigned int)sizeof(size_t) ); |
519 | mutex_unlock(&device->tx_fifo_lock); | |
520 | continue; | |
521 | } | |
522 | ||
523 | /* use fixed message length, if requested */ | |
524 | if (tx_cfg.fixed_message_length != 0) | |
525 | size = tx_cfg.fixed_message_length; | |
526 | ||
527 | /* increase size, if len byte is requested */ | |
528 | if (tx_cfg.enable_length_byte == optionOn) | |
529 | size++; | |
530 | ||
531 | /* increase size, if adr byte is requested */ | |
532 | if (tx_cfg.enable_address_byte == optionOn) | |
533 | size++; | |
534 | ||
535 | /* prime buffer */ | |
536 | memset(buffer, 0, size); | |
537 | position = 0; | |
538 | ||
539 | /* add length byte, if requested */ | |
540 | if (tx_cfg.enable_length_byte == optionOn) | |
541 | buffer[position++] = size-1; /* according to spec length byte itself must be excluded from the length calculation */ | |
542 | ||
543 | /* add adr byte, if requested */ | |
544 | if (tx_cfg.enable_address_byte == optionOn) | |
545 | buffer[position++] = tx_cfg.address_byte; | |
546 | ||
547 | /* finally get message data from fifo */ | |
548 | retval = kfifo_out(&device->tx_fifo, &buffer[position], sizeof(buffer)-position ); | |
549 | dev_dbg(device->dev, "read %d message byte(s) from fifo queue.", retval); | |
550 | mutex_unlock(&device->tx_fifo_lock); | |
551 | ||
552 | /* if rx is active, we need to interrupt the waiting for | |
056eeda2 DR |
553 | * incoming telegrams, to be able to send something. |
554 | * We are only allowed, if currently no reception takes | |
555 | * place otherwise we need to wait for the incoming telegram | |
556 | * to finish | |
557 | */ | |
874bcba6 MW |
558 | wait_event_interruptible(device->tx_wait_queue, |
559 | !device->rx_active || | |
560 | device->interrupt_rx_allowed == true); | |
561 | ||
562 | /* prevent race conditions | |
056eeda2 DR |
563 | * irq will be reenabled after tx config is set |
564 | */ | |
874bcba6 MW |
565 | disable_irq(device->irq_num[DIO0]); |
566 | device->tx_active = true; | |
567 | ||
568 | if (device->rx_active && rx_interrupted == false) | |
569 | { | |
570 | /* rx is currently waiting for a telegram; | |
056eeda2 DR |
571 | * we need to set the radio module to standby |
572 | */ | |
874bcba6 MW |
573 | SET_CHECKED(rf69_set_mode(device->spi, standby)); |
574 | rx_interrupted = true; | |
575 | } | |
576 | ||
577 | /* clear fifo, set fifo threshold, set payload length */ | |
578 | SET_CHECKED(rf69_set_mode(spi, standby)); /* this clears the fifo */ | |
579 | SET_CHECKED(rf69_set_fifo_threshold(spi, FIFO_THRESHOLD)); | |
580 | if (tx_cfg.enable_length_byte == optionOn) | |
581 | { | |
582 | SET_CHECKED(rf69_set_payload_length(spi, size * tx_cfg.repetitions)); | |
583 | } | |
584 | else | |
585 | { | |
586 | SET_CHECKED(rf69_set_payload_length(spi, 0)); | |
587 | } | |
588 | ||
589 | /* configure the rf chip */ | |
590 | rf69_set_tx_cfg(device, &tx_cfg); | |
591 | ||
592 | /* enable fifo level interrupt */ | |
593 | SET_CHECKED(rf69_set_dio_mapping(spi, DIO1, DIO_FifoLevel)); | |
594 | device->irq_state[DIO1] = DIO_FifoLevel; | |
595 | irq_set_irq_type(device->irq_num[DIO1], IRQ_TYPE_EDGE_FALLING); | |
596 | ||
597 | /* enable packet sent interrupt */ | |
598 | SET_CHECKED(rf69_set_dio_mapping(spi, DIO0, DIO_PacketSent)); | |
599 | device->irq_state[DIO0] = DIO_PacketSent; | |
600 | irq_set_irq_type(device->irq_num[DIO0], IRQ_TYPE_EDGE_RISING); | |
601 | enable_irq(device->irq_num[DIO0]); /* was disabled by rx active check */ | |
602 | ||
603 | /* enable transmission */ | |
604 | SET_CHECKED(rf69_set_mode(spi, transmit)); | |
605 | ||
606 | /* transfer this msg (and repetitions) to chip fifo */ | |
607 | device->free_in_fifo = FIFO_SIZE; | |
608 | position = 0; | |
609 | repetitions = tx_cfg.repetitions; | |
610 | while( (repetitions > 0) && (size > position) ) | |
611 | { | |
612 | if ( (size - position) > device->free_in_fifo) | |
613 | { /* msg to big for fifo - take a part */ | |
614 | int temp = device->free_in_fifo; | |
615 | device->free_in_fifo = 0; | |
616 | rf69_write_fifo(spi, | |
617 | &buffer[position], | |
618 | temp); | |
619 | position +=temp; | |
620 | } | |
621 | else | |
622 | { /* msg fits into fifo - take all */ | |
623 | device->free_in_fifo -= size; | |
624 | repetitions--; | |
625 | rf69_write_fifo(spi, | |
626 | &buffer[position], | |
627 | (size - position) ); | |
628 | position = 0; /* reset for next repetition */ | |
629 | } | |
630 | ||
631 | retval = wait_event_interruptible(device->fifo_wait_queue, | |
632 | device->free_in_fifo > 0); | |
633 | if (retval) { printk("ABORT\n"); goto abort; } | |
634 | } | |
635 | ||
636 | /* we are done. Wait for packet to get sent */ | |
28eb8555 | 637 | dev_dbg(device->dev, "thread: wait for packet to get sent/fifo to be empty"); |
874bcba6 MW |
638 | wait_event_interruptible(device->fifo_wait_queue, |
639 | device->free_in_fifo == FIFO_SIZE || | |
640 | kthread_should_stop() ); | |
641 | if ( kthread_should_stop() ) printk("ABORT\n"); | |
642 | ||
643 | ||
644 | /* STOP_TRANSMISSION */ | |
645 | dev_dbg(device->dev, "thread: Packet sent. Set mode to stby."); | |
646 | SET_CHECKED(rf69_set_mode(spi, standby)); | |
647 | ||
648 | /* everything sent? */ | |
69af5d92 | 649 | if (kfifo_is_empty(&device->tx_fifo)) { |
874bcba6 MW |
650 | abort: |
651 | if (rx_interrupted) | |
652 | { | |
653 | rx_interrupted = false; | |
654 | pi433_start_rx(device); | |
655 | } | |
656 | device->tx_active = false; | |
657 | wake_up_interruptible(&device->rx_wait_queue); | |
658 | } | |
659 | } | |
660 | } | |
661 | ||
662 | /*-------------------------------------------------------------------------*/ | |
663 | ||
664 | static ssize_t | |
665 | pi433_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos) | |
666 | { | |
667 | struct pi433_instance *instance; | |
668 | struct pi433_device *device; | |
669 | int bytes_received; | |
670 | ssize_t retval; | |
671 | ||
672 | /* check, whether internal buffer is big enough for requested size */ | |
673 | if (size > MAX_MSG_SIZE) | |
674 | return -EMSGSIZE; | |
675 | ||
676 | instance = filp->private_data; | |
677 | device = instance->device; | |
678 | ||
679 | /* just one read request at a time */ | |
680 | mutex_lock(&device->rx_lock); | |
681 | if (device->rx_active) | |
682 | { | |
683 | mutex_unlock(&device->rx_lock); | |
684 | return -EAGAIN; | |
685 | } | |
686 | else | |
687 | { | |
688 | device->rx_active = true; | |
689 | mutex_unlock(&device->rx_lock); | |
690 | } | |
691 | ||
692 | /* start receiving */ | |
693 | /* will block until something was received*/ | |
694 | device->rx_buffer_size = size; | |
695 | bytes_received = pi433_receive(device); | |
696 | ||
697 | /* release rx */ | |
698 | mutex_lock(&device->rx_lock); | |
699 | device->rx_active = false; | |
700 | mutex_unlock(&device->rx_lock); | |
701 | ||
702 | /* if read was successful copy to user space*/ | |
69af5d92 | 703 | if (bytes_received > 0) { |
874bcba6 MW |
704 | retval = copy_to_user(buf, device->rx_buffer, bytes_received); |
705 | if (retval) | |
39ae5f1e | 706 | return -EFAULT; |
874bcba6 MW |
707 | } |
708 | ||
709 | return bytes_received; | |
710 | } | |
711 | ||
712 | ||
713 | static ssize_t | |
714 | pi433_write(struct file *filp, const char __user *buf, | |
715 | size_t count, loff_t *f_pos) | |
716 | { | |
717 | struct pi433_instance *instance; | |
718 | struct pi433_device *device; | |
719 | int copied, retval; | |
720 | ||
721 | instance = filp->private_data; | |
722 | device = instance->device; | |
723 | ||
724 | /* check, whether internal buffer (tx thread) is big enough for requested size */ | |
725 | if (count > MAX_MSG_SIZE) | |
726 | return -EMSGSIZE; | |
727 | ||
728 | /* write the following sequence into fifo: | |
056eeda2 DR |
729 | * - tx_cfg |
730 | * - size of message | |
731 | * - message | |
732 | */ | |
874bcba6 MW |
733 | mutex_lock(&device->tx_fifo_lock); |
734 | retval = kfifo_in(&device->tx_fifo, &instance->tx_cfg, sizeof(instance->tx_cfg)); | |
735 | if ( retval != sizeof(instance->tx_cfg) ) | |
736 | goto abort; | |
737 | ||
738 | retval = kfifo_in (&device->tx_fifo, &count, sizeof(size_t)); | |
739 | if ( retval != sizeof(size_t) ) | |
740 | goto abort; | |
741 | ||
742 | retval = kfifo_from_user(&device->tx_fifo, buf, count, &copied); | |
743 | if (retval || copied != count) | |
744 | goto abort; | |
745 | ||
746 | mutex_unlock(&device->tx_fifo_lock); | |
747 | ||
748 | /* start transfer */ | |
749 | wake_up_interruptible(&device->tx_wait_queue); | |
750 | dev_dbg(device->dev, "write: generated new msg with %d bytes.", copied); | |
751 | ||
752 | return 0; | |
753 | ||
754 | abort: | |
755 | dev_dbg(device->dev, "write to fifo failed: 0x%x", retval); | |
756 | kfifo_reset(&device->tx_fifo); // TODO: maybe find a solution, not to discard already stored, valid entries | |
757 | mutex_unlock(&device->tx_fifo_lock); | |
758 | return -EAGAIN; | |
759 | } | |
760 | ||
761 | ||
762 | static long | |
763 | pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |
764 | { | |
874bcba6 MW |
765 | int retval = 0; |
766 | struct pi433_instance *instance; | |
767 | struct pi433_device *device; | |
4982c470 | 768 | struct pi433_tx_cfg tx_cfg; |
50271d38 | 769 | void __user *argp = (void __user *)arg; |
874bcba6 MW |
770 | |
771 | /* Check type and command number */ | |
772 | if (_IOC_TYPE(cmd) != PI433_IOC_MAGIC) | |
773 | return -ENOTTY; | |
774 | ||
874bcba6 MW |
775 | /* TODO? guard against device removal before, or while, |
776 | * we issue this ioctl. --> device_get() | |
777 | */ | |
778 | instance = filp->private_data; | |
779 | device = instance->device; | |
780 | ||
781 | if (device == NULL) | |
782 | return -ESHUTDOWN; | |
783 | ||
784 | switch (cmd) { | |
785 | case PI433_IOC_RD_TX_CFG: | |
50271d38 AV |
786 | if (copy_to_user(argp, &instance->tx_cfg, |
787 | sizeof(struct pi433_tx_cfg))) | |
788 | return -EFAULT; | |
874bcba6 MW |
789 | break; |
790 | case PI433_IOC_WR_TX_CFG: | |
4982c470 | 791 | if (copy_from_user(&tx_cfg, argp, sizeof(struct pi433_tx_cfg))) |
50271d38 | 792 | return -EFAULT; |
4982c470 HL |
793 | mutex_lock(&device->tx_fifo_lock); |
794 | memcpy(&instance->tx_cfg, &tx_cfg, sizeof(struct pi433_tx_cfg)); | |
795 | mutex_unlock(&device->tx_fifo_lock); | |
874bcba6 | 796 | break; |
874bcba6 | 797 | case PI433_IOC_RD_RX_CFG: |
50271d38 AV |
798 | if (copy_to_user(argp, &device->rx_cfg, |
799 | sizeof(struct pi433_rx_cfg))) | |
800 | return -EFAULT; | |
874bcba6 MW |
801 | break; |
802 | case PI433_IOC_WR_RX_CFG: | |
874bcba6 MW |
803 | mutex_lock(&device->rx_lock); |
804 | ||
805 | /* during pendig read request, change of config not allowed */ | |
806 | if (device->rx_active) { | |
874bcba6 | 807 | mutex_unlock(&device->rx_lock); |
50271d38 | 808 | return -EAGAIN; |
874bcba6 MW |
809 | } |
810 | ||
50271d38 AV |
811 | if (copy_from_user(&device->rx_cfg, argp, |
812 | sizeof(struct pi433_rx_cfg))) { | |
874bcba6 | 813 | mutex_unlock(&device->rx_lock); |
50271d38 | 814 | return -EFAULT; |
874bcba6 MW |
815 | } |
816 | ||
817 | mutex_unlock(&device->rx_lock); | |
818 | break; | |
819 | default: | |
820 | retval = -EINVAL; | |
821 | } | |
822 | ||
823 | return retval; | |
824 | } | |
825 | ||
826 | #ifdef CONFIG_COMPAT | |
827 | static long | |
828 | pi433_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |
829 | { | |
830 | return pi433_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); | |
831 | } | |
832 | #else | |
833 | #define pi433_compat_ioctl NULL | |
834 | #endif /* CONFIG_COMPAT */ | |
835 | ||
836 | /*-------------------------------------------------------------------------*/ | |
837 | ||
838 | static int pi433_open(struct inode *inode, struct file *filp) | |
839 | { | |
840 | struct pi433_device *device; | |
841 | struct pi433_instance *instance; | |
842 | ||
843 | mutex_lock(&minor_lock); | |
844 | device = idr_find(&pi433_idr, iminor(inode)); | |
845 | mutex_unlock(&minor_lock); | |
846 | if (!device) { | |
847 | pr_debug("device: minor %d unknown.\n", iminor(inode)); | |
848 | return -ENODEV; | |
849 | } | |
850 | ||
851 | if (!device->rx_buffer) { | |
852 | device->rx_buffer = kmalloc(MAX_MSG_SIZE, GFP_KERNEL); | |
69af5d92 | 853 | if (!device->rx_buffer) { |
874bcba6 MW |
854 | dev_dbg(device->dev, "open/ENOMEM\n"); |
855 | return -ENOMEM; | |
856 | } | |
857 | } | |
858 | ||
859 | device->users++; | |
860 | instance = kzalloc(sizeof(*instance), GFP_KERNEL); | |
69af5d92 | 861 | if (!instance) { |
874bcba6 MW |
862 | kfree(device->rx_buffer); |
863 | device->rx_buffer = NULL; | |
864 | return -ENOMEM; | |
865 | } | |
866 | ||
867 | /* setup instance data*/ | |
868 | instance->device = device; | |
869 | instance->tx_cfg.bit_rate = 4711; | |
870 | // TODO: fill instance->tx_cfg; | |
871 | ||
872 | /* instance data as context */ | |
873 | filp->private_data = instance; | |
874 | nonseekable_open(inode, filp); | |
875 | ||
876 | return 0; | |
877 | } | |
878 | ||
879 | static int pi433_release(struct inode *inode, struct file *filp) | |
880 | { | |
881 | struct pi433_instance *instance; | |
882 | struct pi433_device *device; | |
883 | ||
884 | instance = filp->private_data; | |
885 | device = instance->device; | |
886 | kfree(instance); | |
887 | filp->private_data = NULL; | |
888 | ||
889 | /* last close? */ | |
890 | device->users--; | |
891 | ||
892 | if (!device->users) { | |
893 | kfree(device->rx_buffer); | |
894 | device->rx_buffer = NULL; | |
895 | if (device->spi == NULL) | |
896 | kfree(device); | |
897 | } | |
898 | ||
899 | return 0; | |
900 | } | |
901 | ||
902 | ||
903 | /*-------------------------------------------------------------------------*/ | |
904 | ||
905 | static int setup_GPIOs(struct pi433_device *device) | |
906 | { | |
907 | char name[5]; | |
908 | int retval; | |
909 | int i; | |
ee26e236 CA |
910 | const irq_handler_t DIO_irq_handler[NUM_DIO] = { |
911 | DIO0_irq_handler, | |
912 | DIO1_irq_handler | |
913 | }; | |
874bcba6 MW |
914 | |
915 | for (i=0; i<NUM_DIO; i++) | |
916 | { | |
917 | /* "construct" name and get the gpio descriptor */ | |
918 | snprintf(name, sizeof(name), "DIO%d", i); | |
919 | device->gpiod[i] = gpiod_get(&device->spi->dev, name, 0 /*GPIOD_IN*/); | |
920 | ||
69af5d92 | 921 | if (device->gpiod[i] == ERR_PTR(-ENOENT)) { |
874bcba6 MW |
922 | dev_dbg(&device->spi->dev, "Could not find entry for %s. Ignoring.", name); |
923 | continue; | |
924 | } | |
925 | ||
926 | if (device->gpiod[i] == ERR_PTR(-EBUSY)) | |
927 | dev_dbg(&device->spi->dev, "%s is busy.", name); | |
928 | ||
929 | if ( IS_ERR(device->gpiod[i]) ) | |
930 | { | |
931 | retval = PTR_ERR(device->gpiod[i]); | |
932 | /* release already allocated gpios */ | |
933 | for (i--; i>=0; i--) | |
934 | { | |
935 | free_irq(device->irq_num[i], device); | |
936 | gpiod_put(device->gpiod[i]); | |
937 | } | |
938 | return retval; | |
939 | } | |
940 | ||
941 | ||
942 | /* configure the pin */ | |
943 | gpiod_unexport(device->gpiod[i]); | |
944 | retval = gpiod_direction_input(device->gpiod[i]); | |
945 | if (retval) return retval; | |
946 | ||
947 | ||
948 | /* configure irq */ | |
949 | device->irq_num[i] = gpiod_to_irq(device->gpiod[i]); | |
69af5d92 | 950 | if (device->irq_num[i] < 0) { |
874bcba6 MW |
951 | device->gpiod[i] = ERR_PTR(-EINVAL);//(struct gpio_desc *)device->irq_num[i]; |
952 | return device->irq_num[i]; | |
953 | } | |
954 | retval = request_irq(device->irq_num[i], | |
955 | DIO_irq_handler[i], | |
956 | 0, /* flags */ | |
957 | name, | |
958 | device); | |
959 | ||
960 | if (retval) | |
961 | return retval; | |
962 | ||
2ebd34ca | 963 | dev_dbg(&device->spi->dev, "%s successfully configured", name); |
874bcba6 MW |
964 | } |
965 | ||
966 | return 0; | |
967 | } | |
968 | ||
969 | static void free_GPIOs(struct pi433_device *device) | |
970 | { | |
971 | int i; | |
972 | ||
973 | for (i=0; i<NUM_DIO; i++) | |
974 | { | |
975 | /* check if gpiod is valid */ | |
976 | if ( IS_ERR(device->gpiod[i]) ) | |
977 | continue; | |
978 | ||
979 | free_irq(device->irq_num[i], device); | |
980 | gpiod_put(device->gpiod[i]); | |
981 | } | |
982 | return; | |
983 | } | |
984 | ||
985 | static int pi433_get_minor(struct pi433_device *device) | |
986 | { | |
987 | int retval = -ENOMEM; | |
988 | ||
989 | mutex_lock(&minor_lock); | |
990 | retval = idr_alloc(&pi433_idr, device, 0, N_PI433_MINORS, GFP_KERNEL); | |
991 | if (retval >= 0) { | |
992 | device->minor = retval; | |
993 | retval = 0; | |
994 | } else if (retval == -ENOSPC) { | |
995 | dev_err(device->dev, "too many pi433 devices\n"); | |
996 | retval = -EINVAL; | |
997 | } | |
998 | mutex_unlock(&minor_lock); | |
999 | return retval; | |
1000 | } | |
1001 | ||
1002 | static void pi433_free_minor(struct pi433_device *dev) | |
1003 | { | |
1004 | mutex_lock(&minor_lock); | |
1005 | idr_remove(&pi433_idr, dev->minor); | |
1006 | mutex_unlock(&minor_lock); | |
1007 | } | |
1008 | /*-------------------------------------------------------------------------*/ | |
1009 | ||
1010 | static const struct file_operations pi433_fops = { | |
1011 | .owner = THIS_MODULE, | |
1012 | /* REVISIT switch to aio primitives, so that userspace | |
1013 | * gets more complete API coverage. It'll simplify things | |
1014 | * too, except for the locking. | |
1015 | */ | |
1016 | .write = pi433_write, | |
1017 | .read = pi433_read, | |
1018 | .unlocked_ioctl = pi433_ioctl, | |
1019 | .compat_ioctl = pi433_compat_ioctl, | |
1020 | .open = pi433_open, | |
1021 | .release = pi433_release, | |
1022 | .llseek = no_llseek, | |
1023 | }; | |
1024 | ||
1025 | /*-------------------------------------------------------------------------*/ | |
1026 | ||
1027 | static int pi433_probe(struct spi_device *spi) | |
1028 | { | |
1029 | struct pi433_device *device; | |
1030 | int retval; | |
1031 | ||
1032 | /* setup spi parameters */ | |
1033 | spi->mode = 0x00; | |
1034 | spi->bits_per_word = 8; | |
1035 | /* spi->max_speed_hz = 10000000; 1MHz already set by device tree overlay */ | |
1036 | ||
1037 | retval = spi_setup(spi); | |
1038 | if (retval) | |
1039 | { | |
1040 | dev_dbg(&spi->dev, "configuration of SPI interface failed!\n"); | |
1041 | return retval; | |
1042 | } | |
1043 | else | |
1044 | { | |
1045 | dev_dbg(&spi->dev, | |
1046 | "spi interface setup: mode 0x%2x, %d bits per word, %dhz max speed", | |
1047 | spi->mode, spi->bits_per_word, spi->max_speed_hz); | |
1048 | } | |
1049 | ||
1050 | /* Ping the chip by reading the version register */ | |
1051 | retval = spi_w8r8(spi, 0x10); | |
1052 | if (retval < 0) | |
1053 | return retval; | |
1054 | ||
6feb5c82 XZ |
1055 | switch (retval) { |
1056 | case 0x24: | |
1057 | dev_dbg(&spi->dev, "found pi433 (ver. 0x%x)", retval); | |
1058 | break; | |
1059 | default: | |
1060 | dev_dbg(&spi->dev, "unknown chip version: 0x%x", retval); | |
1061 | return -ENODEV; | |
874bcba6 MW |
1062 | } |
1063 | ||
1064 | /* Allocate driver data */ | |
1065 | device = kzalloc(sizeof(*device), GFP_KERNEL); | |
1066 | if (!device) | |
1067 | return -ENOMEM; | |
1068 | ||
1069 | /* Initialize the driver data */ | |
1070 | device->spi = spi; | |
1071 | device->rx_active = false; | |
1072 | device->tx_active = false; | |
1073 | device->interrupt_rx_allowed = false; | |
1074 | ||
1075 | /* init wait queues */ | |
1076 | init_waitqueue_head(&device->tx_wait_queue); | |
1077 | init_waitqueue_head(&device->rx_wait_queue); | |
1078 | init_waitqueue_head(&device->fifo_wait_queue); | |
1079 | ||
1080 | /* init fifo */ | |
1081 | INIT_KFIFO(device->tx_fifo); | |
1082 | ||
1083 | /* init mutexes and locks */ | |
1084 | mutex_init(&device->tx_fifo_lock); | |
1085 | mutex_init(&device->rx_lock); | |
1086 | ||
1087 | /* setup GPIO (including irq_handler) for the different DIOs */ | |
1088 | retval = setup_GPIOs(device); | |
69af5d92 | 1089 | if (retval) { |
874bcba6 MW |
1090 | dev_dbg(&spi->dev, "setup of GPIOs failed"); |
1091 | goto GPIO_failed; | |
1092 | } | |
1093 | ||
1094 | /* setup the radio module */ | |
1095 | SET_CHECKED(rf69_set_mode (spi, standby)); | |
1096 | SET_CHECKED(rf69_set_data_mode (spi, packet)); | |
1097 | SET_CHECKED(rf69_set_amplifier_0 (spi, optionOn)); | |
1098 | SET_CHECKED(rf69_set_amplifier_1 (spi, optionOff)); | |
1099 | SET_CHECKED(rf69_set_amplifier_2 (spi, optionOff)); | |
1100 | SET_CHECKED(rf69_set_output_power_level (spi, 13)); | |
1101 | SET_CHECKED(rf69_set_antenna_impedance (spi, fiftyOhm)); | |
1102 | ||
1103 | /* start tx thread */ | |
1104 | device->tx_task_struct = kthread_run(pi433_tx_thread, | |
1105 | device, | |
1106 | "pi433_tx_task"); | |
69af5d92 | 1107 | if (IS_ERR(device->tx_task_struct)) { |
874bcba6 MW |
1108 | dev_dbg(device->dev, "start of send thread failed"); |
1109 | goto send_thread_failed; | |
1110 | } | |
1111 | ||
1112 | /* determ minor number */ | |
1113 | retval = pi433_get_minor(device); | |
69af5d92 | 1114 | if (retval) { |
874bcba6 MW |
1115 | dev_dbg(device->dev, "get of minor number failed"); |
1116 | goto minor_failed; | |
1117 | } | |
1118 | ||
1119 | /* create device */ | |
1120 | device->devt = MKDEV(MAJOR(pi433_dev), device->minor); | |
1121 | device->dev = device_create(pi433_class, | |
1122 | &spi->dev, | |
1123 | device->devt, | |
1124 | device, | |
1125 | "pi433"); | |
1126 | if (IS_ERR(device->dev)) { | |
1127 | pr_err("pi433: device register failed\n"); | |
1128 | retval = PTR_ERR(device->dev); | |
1129 | goto device_create_failed; | |
1130 | } | |
1131 | else { | |
1132 | dev_dbg(device->dev, | |
1133 | "created device for major %d, minor %d\n", | |
1134 | MAJOR(pi433_dev), | |
1135 | device->minor); | |
1136 | } | |
1137 | ||
1138 | /* create cdev */ | |
1139 | device->cdev = cdev_alloc(); | |
1140 | device->cdev->owner = THIS_MODULE; | |
1141 | cdev_init(device->cdev, &pi433_fops); | |
1142 | retval = cdev_add(device->cdev, device->devt, 1); | |
69af5d92 | 1143 | if (retval) { |
874bcba6 MW |
1144 | dev_dbg(device->dev, "register of cdev failed"); |
1145 | goto cdev_failed; | |
1146 | } | |
1147 | ||
1148 | /* spi setup */ | |
1149 | spi_set_drvdata(spi, device); | |
1150 | ||
1151 | return 0; | |
1152 | ||
1153 | cdev_failed: | |
1154 | device_destroy(pi433_class, device->devt); | |
1155 | device_create_failed: | |
1156 | pi433_free_minor(device); | |
1157 | minor_failed: | |
1158 | kthread_stop(device->tx_task_struct); | |
1159 | send_thread_failed: | |
1160 | free_GPIOs(device); | |
1161 | GPIO_failed: | |
1162 | kfree(device); | |
1163 | ||
1164 | return retval; | |
1165 | } | |
1166 | ||
1167 | static int pi433_remove(struct spi_device *spi) | |
1168 | { | |
1169 | struct pi433_device *device = spi_get_drvdata(spi); | |
1170 | ||
1171 | /* free GPIOs */ | |
1172 | free_GPIOs(device); | |
1173 | ||
1174 | /* make sure ops on existing fds can abort cleanly */ | |
1175 | device->spi = NULL; | |
1176 | ||
1177 | kthread_stop(device->tx_task_struct); | |
1178 | ||
1179 | device_destroy(pi433_class, device->devt); | |
1180 | ||
1181 | cdev_del(device->cdev); | |
1182 | ||
1183 | pi433_free_minor(device); | |
1184 | ||
1185 | if (device->users == 0) | |
1186 | kfree(device); | |
1187 | ||
1188 | return 0; | |
1189 | } | |
1190 | ||
1191 | static const struct of_device_id pi433_dt_ids[] = { | |
1192 | { .compatible = "Smarthome-Wolf,pi433" }, | |
1193 | {}, | |
1194 | }; | |
1195 | ||
1196 | MODULE_DEVICE_TABLE(of, pi433_dt_ids); | |
1197 | ||
1198 | static struct spi_driver pi433_spi_driver = { | |
1199 | .driver = { | |
1200 | .name = "pi433", | |
1201 | .owner = THIS_MODULE, | |
1202 | .of_match_table = of_match_ptr(pi433_dt_ids), | |
1203 | }, | |
1204 | .probe = pi433_probe, | |
1205 | .remove = pi433_remove, | |
1206 | ||
1207 | /* NOTE: suspend/resume methods are not necessary here. | |
1208 | * We don't do anything except pass the requests to/from | |
1209 | * the underlying controller. The refrigerator handles | |
1210 | * most issues; the controller driver handles the rest. | |
1211 | */ | |
1212 | }; | |
1213 | ||
1214 | /*-------------------------------------------------------------------------*/ | |
1215 | ||
1216 | static int __init pi433_init(void) | |
1217 | { | |
1218 | int status; | |
1219 | ||
1220 | /* If MAX_MSG_SIZE is smaller then FIFO_SIZE, the driver won't | |
056eeda2 DR |
1221 | * work stable - risk of buffer overflow |
1222 | */ | |
874bcba6 MW |
1223 | if (MAX_MSG_SIZE < FIFO_SIZE) |
1224 | return -EINVAL; | |
1225 | ||
1226 | /* Claim device numbers. Then register a class | |
1227 | * that will key udev/mdev to add/remove /dev nodes. Last, register | |
1228 | * Last, register the driver which manages those device numbers. | |
1229 | */ | |
1230 | status = alloc_chrdev_region(&pi433_dev, 0 /*firstminor*/, N_PI433_MINORS /*count*/, "pi433" /*name*/); | |
1231 | if (status < 0) | |
1232 | return status; | |
1233 | ||
1234 | pi433_class = class_create(THIS_MODULE, "pi433"); | |
69af5d92 | 1235 | if (IS_ERR(pi433_class)) { |
874bcba6 MW |
1236 | unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); |
1237 | return PTR_ERR(pi433_class); | |
1238 | } | |
1239 | ||
1240 | status = spi_register_driver(&pi433_spi_driver); | |
69af5d92 | 1241 | if (status < 0) { |
874bcba6 MW |
1242 | class_destroy(pi433_class); |
1243 | unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); | |
1244 | } | |
1245 | ||
1246 | return status; | |
1247 | } | |
1248 | ||
1249 | module_init(pi433_init); | |
1250 | ||
1251 | static void __exit pi433_exit(void) | |
1252 | { | |
1253 | spi_unregister_driver(&pi433_spi_driver); | |
1254 | class_destroy(pi433_class); | |
1255 | unregister_chrdev(MAJOR(pi433_dev), pi433_spi_driver.driver.name); | |
1256 | } | |
1257 | module_exit(pi433_exit); | |
1258 | ||
1259 | MODULE_AUTHOR("Marcus Wolf, <linux@wolf-entwicklungen.de>"); | |
1260 | MODULE_DESCRIPTION("Driver for Pi433"); | |
1261 | MODULE_LICENSE("GPL"); | |
1262 | MODULE_ALIAS("spi:pi433"); |