📄 miropcm20-rds-core.c
字号:
/* * Many thanks to Fred Seidel <seidel@metabox.de>, the * designer of the RDS decoder hardware. With his help * I was able to code this driver. * Thanks also to Norberto Pellicci, Dominic Mounteney * <DMounteney@pinnaclesys.com> and www.teleauskunft.de * for good hints on finding Fred. It was somewhat hard * to locate him here in Germany... [: * * Revision history: * * 2000-08-09 Robert Siemer <Robert.Siemer@gmx.de> * RDS support for MiroSound PCM20 radio */#define _NO_VERSION_/* #include <linux/kernel.h> */#include <linux/module.h>#include <linux/init.h>#include <linux/slab.h>#include <asm/semaphore.h>#include <asm/io.h>#include "../../sound/aci.h"#include "miropcm20-rds-core.h"#define DEBUG 0static struct semaphore aci_rds_sem;#define RDS_DATASHIFT 2 /* Bit 2 */#define RDS_DATAMASK (1 << RDS_DATASHIFT)#define RDS_BUSYMASK 0x10 /* Bit 4 */#define RDS_CLOCKMASK 0x08 /* Bit 3 */#define RDS_DATA(x) (((x) >> RDS_DATASHIFT) & 1) #if DEBUGstatic void print_matrix(char array[], unsigned int length){ int i, j; for (i=0; i<length; i++) { printk(KERN_DEBUG "aci-rds: "); for (j=7; j>=0; j--) { printk("%d", (array[i] >> j) & 0x1); } if (i%8 == 0) printk(" byte-border\n"); else printk("\n"); }}#endif /* DEBUG */static int byte2trans(unsigned char byte, unsigned char sendbuffer[], int size){ int i; if (size != 8) return -1; for (i = 7; i >= 0; i--) sendbuffer[7-i] = (byte & (1 << i)) ? RDS_DATAMASK : 0; sendbuffer[0] |= RDS_CLOCKMASK; return 0;}static int rds_waitread(void){ unsigned char byte; int i=2000; do { byte=inb(RDS_REGISTER); i--; } while ((byte & RDS_BUSYMASK) && i); if (i) { #if DEBUG printk(KERN_DEBUG "rds_waitread()"); print_matrix(&byte, 1); #endif return (byte); } else { printk(KERN_WARNING "aci-rds: rds_waitread() timeout...\n"); return -1; }}/* dont use any ..._nowait() function if you are not sure what you do... */static inline void rds_rawwrite_nowait(unsigned char byte){ #if DEBUG printk(KERN_DEBUG "rds_rawwrite()"); print_matrix(&byte, 1); #endif outb(byte, RDS_REGISTER);}static int rds_rawwrite(unsigned char byte){ if (rds_waitread() >= 0) { rds_rawwrite_nowait(byte); return 0; } else return -1;}static int rds_write(unsigned char cmd){ unsigned char sendbuffer[8]; int i; if (byte2trans(cmd, sendbuffer, 8) != 0){ return -1; } else { for (i=0; i<8; i++) { rds_rawwrite(sendbuffer[i]); } } return 0;}static int rds_readcycle_nowait(void){ rds_rawwrite_nowait(0); return rds_waitread();}static int rds_readcycle(void){ if (rds_rawwrite(0) < 0) return -1; return rds_waitread();}static int rds_read(unsigned char databuffer[], int datasize){ #define READSIZE (8*datasize) int i,j; if (datasize < 1) /* nothing to read */ return 0; /* to be able to use rds_readcycle_nowait() I have to waitread() here */ if (rds_waitread() < 0) return -1; memset(databuffer, 0, datasize); for (i=0; i< READSIZE; i++) if((j=rds_readcycle_nowait()) < 0) { return -1; } else { databuffer[i/8]|=(RDS_DATA(j) << (7-(i%8))); } return 0;}static int rds_ack(void){ int i=rds_readcycle(); if (i < 0) return -1; if (i & RDS_DATAMASK) { return 0; /* ACK */ } else { printk(KERN_DEBUG "aci-rds: NACK\n"); return 1; /* NACK */ }}int aci_rds_cmd(unsigned char cmd, unsigned char databuffer[], int datasize){ int ret; if (down_interruptible(&aci_rds_sem)) return -EINTR; rds_write(cmd); /* RDS_RESET doesn't need further processing */ if (cmd!=RDS_RESET && (rds_ack() || rds_read(databuffer, datasize))) ret = -1; else ret = 0; up(&aci_rds_sem); return ret;}EXPORT_SYMBOL(aci_rds_cmd);int __init attach_aci_rds(void){ init_MUTEX(&aci_rds_sem); return 0;}void __exit unload_aci_rds(void){}MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -