V4L/DVB (7062): radio-si570x: Some fixes and new USB ID addition
- avoid poss. locking when doing copy_to_user which may sleep - RDS is automatically activated on read now - code cleaned of unnecessary rds_commands - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified (thanks to Guillaume RAMOUSSE) Signed-off-by: Tobias Lorenz <tobias.lorenz@gmx.net> Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
8bf5e5ca39
commit
2fb8840663
@@ -55,13 +55,17 @@
|
|||||||
* - applied all checkpatch.pl v1.12 suggestions
|
* - applied all checkpatch.pl v1.12 suggestions
|
||||||
* except the warning about the too long lines with bit comments
|
* except the warning about the too long lines with bit comments
|
||||||
* - renamed FMRADIO to RADIO to cut line length (checkpatch.pl)
|
* - renamed FMRADIO to RADIO to cut line length (checkpatch.pl)
|
||||||
|
* 2008-01-22 Tobias Lorenz <tobias.lorenz@gmx.net>
|
||||||
|
* Version 1.0.4
|
||||||
|
* - avoid poss. locking when doing copy_to_user which may sleep
|
||||||
|
* - RDS is automatically activated on read now
|
||||||
|
* - code cleaned of unnecessary rds_commands
|
||||||
|
* - USB Vendor/Product ID for ADS/Tech FM Radio Receiver verified
|
||||||
|
* (thanks to Guillaume RAMOUSSE)
|
||||||
*
|
*
|
||||||
* ToDo:
|
* ToDo:
|
||||||
* - check USB Vendor/Product ID for ADS/Tech FM Radio Receiver
|
|
||||||
* (formerly Instant FM Music) (RDX-155-EF) is 06e1:a155
|
|
||||||
* - add seeking support
|
* - add seeking support
|
||||||
* - add firmware download/update support
|
* - add firmware download/update support
|
||||||
* - add possibility to switch off RDS
|
|
||||||
* - RDS support: interrupt mode, instead of polling
|
* - RDS support: interrupt mode, instead of polling
|
||||||
* - add LED status output (check if that's not already done in firmware)
|
* - add LED status output (check if that's not already done in firmware)
|
||||||
*/
|
*/
|
||||||
@@ -70,7 +74,7 @@
|
|||||||
/* driver definitions */
|
/* driver definitions */
|
||||||
#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
|
#define DRIVER_AUTHOR "Tobias Lorenz <tobias.lorenz@gmx.net>"
|
||||||
#define DRIVER_NAME "radio-si470x"
|
#define DRIVER_NAME "radio-si470x"
|
||||||
#define DRIVER_VERSION KERNEL_VERSION(1, 0, 3)
|
#define DRIVER_VERSION KERNEL_VERSION(1, 0, 4)
|
||||||
#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
|
#define DRIVER_CARD "Silicon Labs Si470x FM Radio Receiver"
|
||||||
#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
|
#define DRIVER_DESC "USB radio driver for Si470x FM Radio Receivers"
|
||||||
|
|
||||||
@@ -93,6 +97,8 @@
|
|||||||
static struct usb_device_id si470x_usb_driver_id_table[] = {
|
static struct usb_device_id si470x_usb_driver_id_table[] = {
|
||||||
/* Silicon Labs USB FM Radio Reference Design */
|
/* Silicon Labs USB FM Radio Reference Design */
|
||||||
{ USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x10c4, 0x818a, USB_CLASS_HID, 0, 0) },
|
||||||
|
/* ADS/Tech FM Radio Receiver (formerly Instant FM Music) */
|
||||||
|
{ USB_DEVICE_AND_INTERFACE_INFO(0x06e1, 0xa155, USB_CLASS_HID, 0, 0) },
|
||||||
/* Terminating entry */
|
/* Terminating entry */
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
@@ -159,6 +165,7 @@ MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
|
|||||||
/* RDS poll frequency */
|
/* RDS poll frequency */
|
||||||
static int rds_poll_time = 40;
|
static int rds_poll_time = 40;
|
||||||
/* 40 is used by the original USBRadio.exe */
|
/* 40 is used by the original USBRadio.exe */
|
||||||
|
/* 50 is used by radio-cadet */
|
||||||
/* 75 should be okay */
|
/* 75 should be okay */
|
||||||
/* 80 is the usual RDS receive interval */
|
/* 80 is the usual RDS receive interval */
|
||||||
module_param(rds_poll_time, int, 0);
|
module_param(rds_poll_time, int, 0);
|
||||||
@@ -399,16 +406,13 @@ struct si470x_device {
|
|||||||
|
|
||||||
/* RDS receive buffer */
|
/* RDS receive buffer */
|
||||||
struct work_struct work;
|
struct work_struct work;
|
||||||
|
wait_queue_head_t read_queue;
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
spinlock_t lock; /* buffer locking */
|
spinlock_t lock; /* buffer locking */
|
||||||
unsigned char *buffer;
|
unsigned char *buffer; /* size is always multiple of three */
|
||||||
unsigned int buf_size;
|
unsigned int buf_size;
|
||||||
unsigned int rd_index;
|
unsigned int rd_index;
|
||||||
unsigned int wr_index;
|
unsigned int wr_index;
|
||||||
unsigned int block_count;
|
|
||||||
unsigned char last_blocknum;
|
|
||||||
wait_queue_head_t read_queue;
|
|
||||||
int data_available_for_read;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -658,8 +662,7 @@ static int si470x_start(struct si470x_device *radio)
|
|||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
/* sysconfig 1 */
|
/* sysconfig 1 */
|
||||||
radio->registers[SYSCONFIG1] =
|
radio->registers[SYSCONFIG1] = SYSCONFIG1_DE;
|
||||||
SYSCONFIG1_DE | SYSCONFIG1_RDS;
|
|
||||||
retval = si470x_set_register(radio, SYSCONFIG1);
|
retval = si470x_set_register(radio, SYSCONFIG1);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
return retval;
|
return retval;
|
||||||
@@ -685,6 +688,14 @@ static int si470x_start(struct si470x_device *radio)
|
|||||||
*/
|
*/
|
||||||
static int si470x_stop(struct si470x_device *radio)
|
static int si470x_stop(struct si470x_device *radio)
|
||||||
{
|
{
|
||||||
|
int retval;
|
||||||
|
|
||||||
|
/* sysconfig 1 */
|
||||||
|
radio->registers[SYSCONFIG1] &= ~SYSCONFIG1_RDS;
|
||||||
|
retval = si470x_set_register(radio, SYSCONFIG1);
|
||||||
|
if (retval < 0)
|
||||||
|
return retval;
|
||||||
|
|
||||||
/* powercfg */
|
/* powercfg */
|
||||||
radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
|
radio->registers[POWERCFG] &= ~POWERCFG_DMUTE;
|
||||||
/* POWERCFG_ENABLE has to automatically go low */
|
/* POWERCFG_ENABLE has to automatically go low */
|
||||||
@@ -693,6 +704,17 @@ static int si470x_stop(struct si470x_device *radio)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* si470x_rds_on - switch on rds reception
|
||||||
|
*/
|
||||||
|
static int si470x_rds_on(struct si470x_device *radio)
|
||||||
|
{
|
||||||
|
/* sysconfig 1 */
|
||||||
|
radio->registers[SYSCONFIG1] |= SYSCONFIG1_RDS;
|
||||||
|
return si470x_set_register(radio, SYSCONFIG1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* RDS Driver Functions
|
* RDS Driver Functions
|
||||||
@@ -703,15 +725,13 @@ static int si470x_stop(struct si470x_device *radio)
|
|||||||
*/
|
*/
|
||||||
static void si470x_rds(struct si470x_device *radio)
|
static void si470x_rds(struct si470x_device *radio)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
unsigned char tmpbuf[3];
|
unsigned char tmpbuf[3];
|
||||||
unsigned char blocknum;
|
unsigned char blocknum;
|
||||||
unsigned char bler; /* RDS block errors */
|
unsigned char bler; /* rds block errors */
|
||||||
unsigned short rds;
|
unsigned short rds;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (radio->users == 0)
|
/* get rds blocks */
|
||||||
return;
|
|
||||||
if (si470x_get_rds_registers(radio) < 0)
|
if (si470x_get_rds_registers(radio) < 0)
|
||||||
return;
|
return;
|
||||||
if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) {
|
if ((radio->registers[STATUSRSSI] & STATUSRSSI_RDSR) == 0) {
|
||||||
@@ -723,63 +743,67 @@ static void si470x_rds(struct si470x_device *radio)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (blocknum = 0; blocknum < 4; blocknum++) {
|
/* copy four RDS blocks to internal buffer */
|
||||||
switch (blocknum) {
|
if (spin_trylock(&radio->lock)) {
|
||||||
default:
|
/* process each rds block */
|
||||||
bler = (radio->registers[STATUSRSSI] &
|
for (blocknum = 0; blocknum < 4; blocknum++) {
|
||||||
STATUSRSSI_BLERA) >> 9;
|
switch (blocknum) {
|
||||||
rds = radio->registers[RDSA];
|
default:
|
||||||
break;
|
bler = (radio->registers[STATUSRSSI] &
|
||||||
case 1:
|
STATUSRSSI_BLERA) >> 9;
|
||||||
bler = (radio->registers[READCHAN] &
|
rds = radio->registers[RDSA];
|
||||||
READCHAN_BLERB) >> 14;
|
break;
|
||||||
rds = radio->registers[RDSB];
|
case 1:
|
||||||
break;
|
bler = (radio->registers[READCHAN] &
|
||||||
case 2:
|
READCHAN_BLERB) >> 14;
|
||||||
bler = (radio->registers[READCHAN] &
|
rds = radio->registers[RDSB];
|
||||||
READCHAN_BLERC) >> 12;
|
break;
|
||||||
rds = radio->registers[RDSC];
|
case 2:
|
||||||
break;
|
bler = (radio->registers[READCHAN] &
|
||||||
case 3:
|
READCHAN_BLERC) >> 12;
|
||||||
bler = (radio->registers[READCHAN] &
|
rds = radio->registers[RDSC];
|
||||||
READCHAN_BLERD) >> 10;
|
break;
|
||||||
rds = radio->registers[RDSD];
|
case 3:
|
||||||
break;
|
bler = (radio->registers[READCHAN] &
|
||||||
};
|
READCHAN_BLERD) >> 10;
|
||||||
|
rds = radio->registers[RDSD];
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
|
||||||
/* Fill the V4L2 RDS buffer */
|
/* Fill the V4L2 RDS buffer */
|
||||||
tmpbuf[0] = rds & 0x00ff; /* LSB */
|
tmpbuf[0] = rds & 0x00ff; /* LSB */
|
||||||
tmpbuf[1] = (rds & 0xff00) >> 8;/* MSB */
|
tmpbuf[1] = (rds & 0xff00) >> 8;/* MSB */
|
||||||
tmpbuf[2] = blocknum; /* offset name */
|
tmpbuf[2] = blocknum; /* offset name */
|
||||||
tmpbuf[2] |= blocknum << 3; /* received offset */
|
tmpbuf[2] |= blocknum << 3; /* received offset */
|
||||||
if (bler > max_rds_errors)
|
if (bler > max_rds_errors)
|
||||||
tmpbuf[2] |= 0x80; /* uncorrectable errors */
|
tmpbuf[2] |= 0x80; /* uncorrectable errors */
|
||||||
else if (bler > 0)
|
else if (bler > 0)
|
||||||
tmpbuf[2] |= 0x40; /* corrected error(s) */
|
tmpbuf[2] |= 0x40; /* corrected error(s) */
|
||||||
|
|
||||||
spin_lock_irqsave(&radio->lock, flags);
|
/* copy RDS block to internal buffer */
|
||||||
|
for (i = 0; i < 3; i++) {
|
||||||
|
radio->buffer[radio->wr_index] = tmpbuf[i];
|
||||||
|
radio->wr_index++;
|
||||||
|
}
|
||||||
|
|
||||||
/* copy RDS block to internal buffer */
|
/* wrap write pointer */
|
||||||
for (i = 0; i < 3; i++) {
|
if (radio->wr_index >= radio->buf_size)
|
||||||
radio->buffer[radio->wr_index] = tmpbuf[i];
|
radio->wr_index = 0;
|
||||||
radio->wr_index++;
|
|
||||||
|
/* check for overflow */
|
||||||
|
if (radio->wr_index == radio->rd_index) {
|
||||||
|
/* increment and wrap read pointer */
|
||||||
|
radio->rd_index += 3;
|
||||||
|
if (radio->rd_index >= radio->buf_size)
|
||||||
|
radio->rd_index = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
spin_unlock(&radio->lock);
|
||||||
if (radio->wr_index >= radio->buf_size)
|
|
||||||
radio->wr_index = 0;
|
|
||||||
|
|
||||||
if (radio->wr_index == radio->rd_index) {
|
|
||||||
radio->rd_index += 3;
|
|
||||||
if (radio->rd_index >= radio->buf_size)
|
|
||||||
radio->rd_index = 0;
|
|
||||||
} else
|
|
||||||
radio->block_count++;
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&radio->lock, flags);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
radio->data_available_for_read = 1;
|
/* wake up read queue */
|
||||||
wake_up_interruptible(&radio->read_queue);
|
if (radio->wr_index != radio->rd_index)
|
||||||
|
wake_up_interruptible(&radio->read_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -795,14 +819,14 @@ static void si470x_timer(unsigned long data)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* si470x_timer - rds work function
|
* si470x_work - rds work function
|
||||||
*/
|
*/
|
||||||
static void si470x_work(struct work_struct *work)
|
static void si470x_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct si470x_device *radio = container_of(work, struct si470x_device,
|
struct si470x_device *radio = container_of(work, struct si470x_device,
|
||||||
work);
|
work);
|
||||||
|
|
||||||
if (radio->users == 0)
|
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
si470x_rds(radio);
|
si470x_rds(radio);
|
||||||
@@ -822,53 +846,52 @@ static ssize_t si470x_fops_read(struct file *file, char __user *buf,
|
|||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
|
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
|
||||||
struct rds_command cmd;
|
int retval = 0;
|
||||||
unsigned long flags;
|
unsigned int block_count = 0;
|
||||||
unsigned int i;
|
|
||||||
unsigned int rd_blocks;
|
|
||||||
|
|
||||||
cmd.block_count = count / 3; /* each RDS block needs 3 bytes */
|
/* switch on rds reception */
|
||||||
cmd.result = 0;
|
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
|
||||||
cmd.buffer = buf;
|
si470x_rds_on(radio);
|
||||||
cmd.instance = file;
|
schedule_work(&radio->work);
|
||||||
|
|
||||||
/* copy RDS block out of internal buffer */
|
|
||||||
while (!radio->data_available_for_read) {
|
|
||||||
if (wait_event_interruptible(radio->read_queue,
|
|
||||||
radio->data_available_for_read) < 0)
|
|
||||||
return -EINTR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&radio->lock, flags);
|
/* block if no new data available */
|
||||||
rd_blocks = cmd.block_count;
|
while (radio->wr_index == radio->rd_index) {
|
||||||
if (rd_blocks > radio->block_count)
|
if (file->f_flags & O_NONBLOCK)
|
||||||
rd_blocks = radio->block_count;
|
return -EWOULDBLOCK;
|
||||||
|
interruptible_sleep_on(&radio->read_queue);
|
||||||
if (!rd_blocks) {
|
|
||||||
spin_unlock_irqrestore(&radio->lock, flags);
|
|
||||||
return cmd.result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < rd_blocks; i++) {
|
/* calculate block count from byte count */
|
||||||
/* copy RDS block to user buffer */
|
count /= 3;
|
||||||
if (radio->rd_index == radio->wr_index)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
|
/* copy RDS block out of internal buffer and to user buffer */
|
||||||
break;
|
if (spin_trylock(&radio->lock)) {
|
||||||
|
while (block_count < count) {
|
||||||
|
if (radio->rd_index == radio->wr_index)
|
||||||
|
break;
|
||||||
|
|
||||||
radio->rd_index += 3;
|
/* always transfer rds complete blocks */
|
||||||
if (radio->rd_index >= radio->buf_size)
|
if (copy_to_user(buf,
|
||||||
radio->rd_index = 0;
|
&radio->buffer[radio->rd_index], 3))
|
||||||
radio->block_count--;
|
/* retval = -EFAULT; */
|
||||||
|
break;
|
||||||
|
|
||||||
buf += 3;
|
/* increment and wrap read pointer */
|
||||||
cmd.result += 3;
|
radio->rd_index += 3;
|
||||||
|
if (radio->rd_index >= radio->buf_size)
|
||||||
|
radio->rd_index = 0;
|
||||||
|
|
||||||
|
/* increment counters */
|
||||||
|
block_count++;
|
||||||
|
buf += 3;
|
||||||
|
retval += 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_unlock(&radio->lock);
|
||||||
}
|
}
|
||||||
radio->data_available_for_read = (radio->block_count > 0);
|
|
||||||
spin_unlock_irqrestore(&radio->lock, flags);
|
|
||||||
|
|
||||||
return cmd.result;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -879,14 +902,19 @@ static unsigned int si470x_fops_poll(struct file *file,
|
|||||||
struct poll_table_struct *pts)
|
struct poll_table_struct *pts)
|
||||||
{
|
{
|
||||||
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
|
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
|
||||||
int retval;
|
|
||||||
|
|
||||||
retval = 0;
|
/* switch on rds reception */
|
||||||
if (radio->data_available_for_read)
|
if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0) {
|
||||||
retval = POLLIN | POLLRDNORM;
|
si470x_rds_on(radio);
|
||||||
|
schedule_work(&radio->work);
|
||||||
|
}
|
||||||
|
|
||||||
poll_wait(file, &radio->read_queue, pts);
|
poll_wait(file, &radio->read_queue, pts);
|
||||||
|
|
||||||
return retval;
|
if (radio->rd_index != radio->wr_index)
|
||||||
|
return POLLIN | POLLRDNORM;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -895,17 +923,11 @@ static unsigned int si470x_fops_poll(struct file *file,
|
|||||||
*/
|
*/
|
||||||
static int si470x_fops_open(struct inode *inode, struct file *file)
|
static int si470x_fops_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
int retval;
|
|
||||||
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
|
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
|
||||||
|
|
||||||
radio->users++;
|
radio->users++;
|
||||||
if (radio->users == 1) {
|
if (radio->users == 1)
|
||||||
retval = si470x_start(radio);
|
return si470x_start(radio);
|
||||||
if (retval < 0)
|
|
||||||
return retval;
|
|
||||||
|
|
||||||
schedule_work(&radio->work);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -916,7 +938,6 @@ static int si470x_fops_open(struct inode *inode, struct file *file)
|
|||||||
*/
|
*/
|
||||||
static int si470x_fops_release(struct inode *inode, struct file *file)
|
static int si470x_fops_release(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
int retval;
|
|
||||||
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
|
struct si470x_device *radio = video_get_drvdata(video_devdata(file));
|
||||||
|
|
||||||
if (!radio)
|
if (!radio)
|
||||||
@@ -924,12 +945,14 @@ static int si470x_fops_release(struct inode *inode, struct file *file)
|
|||||||
|
|
||||||
radio->users--;
|
radio->users--;
|
||||||
if (radio->users == 0) {
|
if (radio->users == 0) {
|
||||||
radio->data_available_for_read = 1; /* ? */
|
/* stop rds reception */
|
||||||
wake_up_interruptible(&radio->read_queue); /* ? */
|
del_timer_sync(&radio->timer);
|
||||||
|
flush_scheduled_work();
|
||||||
|
|
||||||
retval = si470x_stop(radio);
|
/* cancel read processes */
|
||||||
if (retval < 0)
|
wake_up_interruptible(&radio->read_queue);
|
||||||
return retval;
|
|
||||||
|
return si470x_stop(radio);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1314,9 +1337,10 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
|
|||||||
< RADIO_SW_VERSION_CURRENT)
|
< RADIO_SW_VERSION_CURRENT)
|
||||||
printk(KERN_WARNING DRIVER_NAME
|
printk(KERN_WARNING DRIVER_NAME
|
||||||
": This driver is known to work with chip version %d, "
|
": This driver is known to work with chip version %d, "
|
||||||
"but the device has firmware %d. If you have some "
|
"but the device has firmware %d.\n"
|
||||||
"trouble using this driver, please report to V4L ML "
|
DRIVER_NAME
|
||||||
"at video4linux-list@redhat.com\n",
|
"If you have some trouble using this driver, please "
|
||||||
|
"report to V4L ML at video4linux-list@redhat.com\n",
|
||||||
radio->registers[CHIPID] & CHIPID_FIRMWARE,
|
radio->registers[CHIPID] & CHIPID_FIRMWARE,
|
||||||
RADIO_SW_VERSION_CURRENT);
|
RADIO_SW_VERSION_CURRENT);
|
||||||
|
|
||||||
@@ -1331,12 +1355,9 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
|
|||||||
kfree(radio);
|
kfree(radio);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
radio->block_count = 0;
|
|
||||||
radio->wr_index = 0;
|
radio->wr_index = 0;
|
||||||
radio->rd_index = 0;
|
radio->rd_index = 0;
|
||||||
radio->last_blocknum = 0xff;
|
|
||||||
init_waitqueue_head(&radio->read_queue);
|
init_waitqueue_head(&radio->read_queue);
|
||||||
radio->data_available_for_read = 0;
|
|
||||||
|
|
||||||
/* prepare polling via eventd */
|
/* prepare polling via eventd */
|
||||||
INIT_WORK(&radio->work, si470x_work);
|
INIT_WORK(&radio->work, si470x_work);
|
||||||
@@ -1408,4 +1429,4 @@ module_exit(si470x_module_exit);
|
|||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
MODULE_VERSION("1.0.3");
|
MODULE_VERSION("1.0.4");
|
||||||
|
Reference in New Issue
Block a user