From: "Raju Rameshwar Uprade" <rajsingh@ncra.tifr.res.in>
To: Greg KH <gregkh@suse.de>,
Raju Rameshwar Uprade <rajsingh@ncra.tifr.res.in>
Cc: linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org
Subject: Re: Regarding USB-serial device driver
Date: Wed, 8 Sep 2010 14:21:22 +0530 [thread overview]
Message-ID: <20100908083315.M8048@admin-gateway.ncra.tifr.res.in> (raw)
In-Reply-To: <20100908061719.GA23233@suse.de>
[-- Attachment #1: Type: text/plain, Size: 2737 bytes --]
> Good.
thanks for appreciation.
> Something wrote it to the driver, did you try it with "debug=1" on the
> modprobe line to see what the driver thinks is happening?
Ya I tried with debug=1 on the modprobe line.
> > f6e80c00 4108452201 C Bo:7:003:2 0 1 >
> > f6e80900 4108453203 C Ii:7:003:1 0:1 10 = a1200000 00000200 0000
same status bytes I am also getting.
One thing I would like to ask why it is coming on Ii (Isochronous endpoint)?
> This was some status bytes coming back, are you sure you got the line
> settings correct?
>
> Your example .c file showed no line settings being set, so you have no
> idea what baud rate you are sending at, or what the flow control is, or
> anything else like that. Please be sure to set that up properly to
> verify that you really are getting the data out to the device properly.
>
Line settings,baud rate, flow control are implemented in mcmdriver.c ( UART driver)
which is attached for your ref.
I am trying to implement functionality of mcmdriver.c in pl2303.c, so that using USB
port I can communicated with various MCM devices connected via RS-485 interface card.
On oscilloscope I have verified that the data is out properly to the device.
output of usbmon :
eebcd000 2366447340 S Co:7:005:0 s 21 22 0003 0000 0000 0
eebcd000 2366449228 C Co:7:005:0 0 0
ee9e1500 2366449269 S Bo:7:005:2 -115 6 = 02110000 0100
ee9e1500 2366450226 C Bo:7:005:2 0 6 >
eebcd700 2366455282 S Co:7:005:0 s 21 22 0000 0000 0000 0
eebcd700 2366456225 C Co:7:005:0 0 0
ef7ebc80 2366456274 S Co:7:005:0 s 21 22 0003 0000 0000 0
ef7ebc80 2366457225 C Co:7:005:0 0 0
ee9e1980 2366458228 C Ii:7:005:1 0:1 10 = a1200000 00000200 1000
ee9e1980 2366458247 S Ii:7:005:1 -115:1 10 <
ee9e1500 2366458358 S Bo:7:005:2 -115 1 = 09
ee9e1500 2366459225 C Bo:7:005:2 0 1 >
eebcdb80 2366459368 S Co:7:005:0 s 21 22 0000 0000 0000 0
ee9e1980 2366460227 C Ii:7:005:1 0:1 10 = a1200000 00000200 0000
ee9e1980 2366460252 S Ii:7:005:1 -115:1 10 <
eebcdb80 2366460256 C Co:7:005:0 0 0
eebcdb80 2366460327 S Co:7:005:0 s 21 22 0003 0000 0000 0
eebcdb80 2366461226 C Co:7:005:0 0 0
ee9e1500 2366461279 S Bo:7:005:2 -115 11 = 00010000 00000000 0000e4
ee9e1500 2366462223 C Bo:7:005:2 0 11 >
eebcdb80 2366472294 S Co:7:005:0 s 21 22 0000 0000 0000 0
eebcdb80 2366474225 C Co:7:005:0 0 0
output of usbmon tell that data going out properly, but it's going in chunks,Ideally It
should go out in one chunk.I think I have to take care of RTS line. UART drivers works
in that way,RTS is enabled for complete data out ,then it is disabled so that we can get
device response.
kindly tell me how and where I can write RTS line enable and disable code in pl2303.c,
so that it can work as mcmdriver.c
Thanks,
Raj.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: mcmdriver.c --]
[-- Type: text/x-csrc; name="mcmdriver.c", Size: 10674 bytes --]
/*************************************************************************
* mcmdriver.c
* Linux kernel module, Serial port driver for MCM communications :
* through RS485 with 9 bit protocol
* requires RS232 / RS485 converter, associated Makefile
*
* under root in a console out of X:
* to install:
* make
* insmod mcmdriver.ko SerialPortNb=1 (or 2)
* mknod /dev/mcmdriver c ... (nbs answered from previous command)
* to uninstall: rmmod mcmdriver , rm -f /dev/mcmdriver
* to check: lsmod
* to test: ./mcmtest.o (compiled from mcmtest.c program)
*
* 20/09/05: modif write9(), no more trans MCM error.
* 01/03/06: modif for Kernel 2.6
* 16/09/2008: modif for FC9 (kernel version 2.6.25.11),it's not working fully but now I m able to get data from the device, there is some bytes lose,have to go thru the code & do the things...
* 23/09/2008: Now the device driver is working fine.I used twisted pair cable instead of single line wire,twisted pair cable reduced the noise level.
**************************************************************************/
//#define __KERNEL__ needed?
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/kdev_t.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
//#include <linux/tqueue.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
#include <asm/serial.h> //for BASE_BAUD
#include <linux/serial_reg.h> //for UART reg
#include <asm/io.h> // or sys/io.h for outb inb
//#include <unistd.h>
MODULE_LICENSE("Dual BSD/GPL");
uint inportb(int port);
void outportb(int port, char value);
void setbit(int port, char bits);
void clrbit(int port, char bits);
char cksum(char *buff);
void ckbaud(void);
void init_baud(unsigned long baud);
static int write9(const char *buff_wr);
irqreturn_t irq_handler(int irq, void *dev_id);
void hw_init(void);
/******************************************************************
* serial write and read functions with MCM
* reading via interruption
******************************************************************/
static char buf_ptr0[200];
static int siz; //must be char for device_read() return value
static int SerialPortNb=0, SerialPortAddr, IRQNb;
DECLARE_WAIT_QUEUE_HEAD(WaitQ);
module_param(SerialPortNb, int, S_IRUGO);
#define UART_IER_DISABLE 0x00 /*disable interrupts, is missing from serial-reg.h*/
#define UART_FCR_DISABLE_FIFO 0x00 /*disable fifo*/
#define UART_FIFO_SETUP (UART_FCR_ENABLE_FIFO | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT | UART_FCR_TRIGGER_1)
#define LCR_ADDR (UART_LCR_WLEN8 | UART_LCR_PARITY | UART_LCR_SPAR)
#define LCR_DATA (UART_LCR_WLEN8 | UART_LCR_PARITY | UART_LCR_SPAR | UART_LCR_EPAR)
/*------------ Macros -----------------------------------------------*/
uint inportb(int port) {return (uint)(inb(SerialPortAddr + port));}
void outportb(int port, char value) {outb(value, SerialPortAddr + port);}
void setbit(int port, char bits) {outportb(port, (inportb(port) | bits));}
void clrbit(int port, char bits) {outportb(port, inportb(port) & ~bits);}
/*---------- CheckSum function----------------------------------------*/
/*char cksum(char *buff)
{
char length, i, cs = 0;
if (siz < 3) return 1;
length = *(buff) + (*(buff+1)<<8);
for(i=0; i<length; i++)
{cs += *(buff+i);}
// printk(KERN_ALERT "cs %d\n", cs);
return cs;
}*/
/*---------- Baud init function--------------------------------------*/
void init_baud(unsigned long baud)
{
unsigned long divisor;
divisor = BASE_BAUD / baud;
printk(KERN_ALERT " I m in BAUD Init function\n");
printk(KERN_ALERT "divisor = %ld\n",divisor);
setbit(UART_LCR,UART_LCR_DLAB);
outportb(UART_DLL,(divisor & 0xff));
outportb(UART_DLM,((divisor >> 8) & 0xff));
clrbit(UART_LCR,UART_LCR_DLAB);
};
/*------------ write function----------------------------------------*/
int write9(const char *buff_wr)
{
int length, i;
// printk(KERN_ALERT "I M IN WRITE9");
length = *(buff_wr+1) + ((*(buff_wr+2))<<8);
setbit(UART_MCR, UART_MCR_RTS); // tx_on
//while (!(inportb(UART_MCR) & UART_MCR_RTS)) {;}
outportb(UART_LCR,LCR_ADDR); // addr parity
//while (!(inportb(UART_LCR) & LCR_ADDR)) {;}
while (!(inportb(UART_LSR) & UART_LSR_THRE)) {;}
outportb(UART_TX, *buff_wr);
while (!(inportb(UART_LSR) & UART_LSR_TEMT)) {;}
outportb(UART_LCR, LCR_DATA); // data parity
//while (!(inportb(UART_LCR) & LCR_DATA)) {;}
for (i=1; i<(length+1); i++) {
while (!(inportb(UART_LSR) & UART_LSR_THRE)) {;}
outportb(UART_TX, *(buff_wr+i));
}
while (!(inportb(UART_LSR) & UART_LSR_TEMT)) {;}
clrbit(UART_MCR, UART_MCR_RTS); // tx_off
//while ((inportb(UART_MCR) & UART_MCR_RTS)) {;}
siz = 0;
/* printk(KERN_ALERT "\nier %.2x\n", inportb(UART_IER));
printk(KERN_ALERT "iir %.2x\n", inportb(UART_IIR));
printk(KERN_ALERT "fcr %.2x\n", inportb(UART_FCR)); */
return 1;
}
/*------------ IRQ handler function-----------------------------------*/
irqreturn_t irq_handler(int irq, void *dev_id)
{
volatile int lsr=0, packsiz=0;
printk(KERN_ALERT "IRQ detected\n");
while(inportb(UART_IIR) & 0x04) {
lsr = inportb(UART_LSR);
if (lsr & 0x02)
{
buf_ptr0[siz] = inportb(UART_RX);
printk(KERN_ALERT "%x ", buf_ptr0[siz]);
} //Overrun
else if (lsr & 0x08)
{
buf_ptr0[siz] = inportb(UART_RX);
printk(KERN_ALERT "Framming Error \n");
printk(KERN_ALERT "%x ", buf_ptr0[siz]);
} //Framing Error
else {
buf_ptr0[siz] = inportb(UART_RX);siz++;
printk(KERN_ALERT "%x ", buf_ptr0[siz-1]);
}
}
if (siz>3) {
packsiz = (*(buf_ptr0+1)+(*(buf_ptr0+2)<<8)+1);
if (siz > 200) {printk(KERN_ALERT "siz error, packet reset\n"); siz = 0;}
else if (siz == packsiz)
wake_up_interruptible(&WaitQ);
}
return IRQ_HANDLED;
}
/*----------- hardware initialisation----------------------------------*/
void hw_init(void)
{
printk(KERN_ALERT "I m in Hw-Init");
outportb(UART_MCR, 0x00);
outportb(UART_IER, UART_IER_DISABLE);
outportb(UART_FCR, UART_FCR_DISABLE_FIFO);
outportb(UART_FCR, UART_FIFO_SETUP);
printk(KERN_ALERT "fcrsetup %.2x\n", UART_FIFO_SETUP);
printk(KERN_ALERT "fcr %.2x\n", inportb(UART_FCR));
outportb(UART_LCR, 0x00);
setbit(UART_MCR, UART_MCR_OUT2 | UART_MCR_RTS); //interrupt enabled
setbit(UART_IER, UART_IER_RDI | UART_IER_THRI| UART_IER_MSI ); // interrupt rx on
// while (!(inportb(UART_IER) & UART_IER_RDI)) {;}
while ((inportb(UART_IIR) & 0x01)==0) {
inportb(UART_LSR);
inportb(UART_MSR);
inportb(UART_RX);
}
init_baud(9600);
}
/******************************************************************
* Module functions for /dev/char driver
* redefines open, write, read and close (release)
******************************************************************/
static dev_t DevNb;
static struct cdev *CharDev; // struct for the internal representation of char devices in the kernel.
static int device_release(struct inode *inode, struct file *file)
{
//release_region(SerialPortNb, 1);
free_irq(IRQNb, NULL);
//MOD_DEC_USE_COUNT;
return 0;
}
static int device_open(struct inode *inode, struct file *file)
{
//if (request_region(SerialPortNb, 1, "mcmdriver") == NULL)
//{printk(KERN_ALERT "Requesting Port failed\n"); return -1;}
// if(request_irq(IRQNb, irq_handler, SA_INTERRUPT, "serial9", NULL))
// {printk(KERN_ALERT "irq request error\n"); return -1;}
printk(KERN_ALERT " I m in device_open function");
if(request_irq(IRQNb, irq_handler, IRQF_DISABLED, "serial9", NULL))
printk(KERN_ALERT " I m in device_open function");
// if(request_irq(IRQNb, irq_handler,IRQF_SHARED , "serial9", NULL))
hw_init();
//MOD_INC_USE_COUNT;
siz = 0;
return 0;
}
static ssize_t device_write(struct file *filp, const char __user *buffer, size_t length, loff_t *offset)
{
write9(buffer);
return 1;
}
/*blocking read with timeout*/
static ssize_t device_read(struct file *filp, char __user *buffer, size_t length, loff_t *offset)
{
int err;//, i;
if (siz < 3)
wait_event_interruptible_timeout(WaitQ, 0,150); // &WaitQ or WaitQ?, 1 or 0?
// wait_event_interruptible(WaitQ,0);
//for (i=0;i<siz;i++) printk(KERN_ALERT "%x ", (unsigned char)buf_ptr0[i]);
//printk(KERN_ALERT "\n");
/*if (cksum(buf_ptr0+1) && (siz > 3)) siz = -1;
else
err = */ copy_to_user(buffer, buf_ptr0, siz);
mdelay(50);
/* Hardware limitation: the driver cannot write 2 times successively in a too short period.
Delay necessary for rewriting just after, optimized for a write & read loop (just 1 printk),
with Set Anl Mask Cmd (the longest) and in a console outside X.
Delay placed here, CS/siz problems if placed before writing ?*/
return siz;
}
static struct file_operations fops = {
.owner = THIS_MODULE,
.open = device_open,
.release = device_release,
.read = device_read,
.write = device_write,
};
static int __init device_init(void)
{
int err;
err = alloc_chrdev_region(&DevNb, 0, 1, "mcmdriver");
if (err < 0)
{printk(KERN_ALERT "Allocating DevNb failed with %d\n", err); return err;}
CharDev = cdev_alloc();
cdev_init(CharDev, &fops);
CharDev->owner = THIS_MODULE;
CharDev->ops = &fops;
err = cdev_add(CharDev, DevNb, 1);
if (err)
{printk(KERN_ALERT "Registering CharDev failed with %d\n", err); return err;}
if (SerialPortNb == 1)
{SerialPortAddr = 0x3f8; IRQNb = 4;}
/* if (SerialPortNb == 1 )
{SerialPortAddr = 0xfe00; IRQNb = 16;} */
/** Changes did for USB to Serial for MCM communication, but lock the computer.......*****/
/**** if (SerialPortNb == 0)
{SerialPortAddr = 0x000; IRQNb = 0;} ***/
else if (SerialPortNb == 2)
{SerialPortAddr = 0x2f8; IRQNb = 3;}
printk(KERN_ALERT "Serial Port %d selected (address %x)\n", SerialPortNb, SerialPortAddr);
printk(KERN_ALERT "Create dev file with 'mknod /dev/mcmdriver c %d %d'.\n", MAJOR(DevNb), MINOR(DevNb));
return 0;
}
static void __exit device_exit(void)
{
cdev_del(CharDev);
unregister_chrdev_region(DevNb, 1);
}
module_init(device_init);
module_exit(device_exit);
next prev parent reply other threads:[~2010-09-08 8:51 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-09-07 6:14 Regarding USB-serial device driver Raju Rameshwar Uprade
2010-09-07 6:59 ` Greg KH
[not found] ` <20100907114913.M69542@admin-gateway.ncra.tifr.res.in>
2010-09-08 3:41 ` Raju Rameshwar Uprade
2010-09-08 6:17 ` Greg KH
2010-09-08 8:51 ` Raju Rameshwar Uprade [this message]
[not found] <20100819055329.M29689@admin-gateway.ncra.tifr.res.in>
[not found] ` <20100819061525.M24093@admin-gateway.ncra.tifr.res.in>
2010-08-19 7:38 ` Regarding USB-Serial Device driver Marek Vasut
2010-08-19 14:18 ` Greg KH
2010-08-20 3:42 ` Raju Rameshwar Uprade
2010-08-20 3:56 ` Greg KH
2010-08-20 6:56 ` Raju Rameshwar Uprade
2010-08-20 15:39 ` Greg KH
[not found] ` <AANLkTin8AiOj4CST5Dr_icnY4MugG1mhgP7=c1jgcJcA@mail.gmail.com>
2010-08-31 4:05 ` Greg KH
-- strict thread matches above, loose matches on Subject: below --
2010-08-19 6:28 Raju Rameshwar Uprade
2010-08-19 13:09 ` Oliver Neukum
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100908083315.M8048@admin-gateway.ncra.tifr.res.in \
--to=rajsingh@ncra.tifr.res.in \
--cc=gregkh@suse.de \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).