How to find the base address of usb to parallel port device in Linux? - c

I am doing IO programming in C in Ubuntu. And I need the base address of the port to write data.
My laptop dont have a parallel port. So I bought a USB to Parallel port connector. I plugged in the device and its getting detected in /dev/usb/lp0
I ran "lsusb" to see the list of devices and I can see the ID also. But how can I get the base address ? For the usual hardware parallel devices, the base address is 0x0378. this address is not getting detected while using USB to Parallel device.
Please help.

A USB parallel port doesn't have a base address - it's not a meaningful concept for USB. I'm afraid the days of doing I/O on PC hardware via in and out instructions ended a few years ago, though lots of old tutorials still survive on the web.
You can write bytes to the parallel port as a character device, and these will appear on the printer port pins. The USB adapter will expect the other end to handshake data exactly like a printer. If you want to do general I/O prototyping, you're probably better off with a simple USB microcontroller like an Arduino.
Further discussion here.

If you are still interested to use this USB-to-parallel-printer device for your own bit-banging, it's important to know that their built-in firmware always allows controlling of D0..D7, INIT (as outputs), /ERR, ONL, PE (as inputs), but never for /ACK, BUSY (inputs), /STB, /AF, /SEL (outputs) pins.
And you need an 8-bit latch (e.g. 74HCT574) for catching data while strobing.
See here (https://www-user.tu-chemnitz.de/~ygu/bastelecke/PC/USB2LPT/faq#DIY)
especially for possible data rates.
Accessing from software side is a bit complicated but possible, and you may have to re-structure your software and hardware for making such adapters useable. I don't know for Linux case how to access, but IMHO you don't need to write a kernel-mode driver.

Related

How do I increase the speed of my USB cdc device?

I am upgrading the processor in an embedded system for work. This is all in C, with no OS. Part of that upgrade includes migrating the processor-PC communications interface from IEEE-488 to USB. I finally got the USB firmware written, and have been testing it. It was going great until I tried to push through lots of data only to discover my USB connection is slower than the old IEEE-488 connection. I have the USB device enumerating as a CDC device with a baud rate of 115200 bps, but it is clear that I am not even reaching that throughput, and I thought that number was a dummy value that is a holdover from RS232 days, but I might be wrong. I control every aspect of this from the front end on the PC to the firmware on the embedded system.
I am assuming my issue is how I write to the USB on the embedded system side. Right now my USB_Write function is run in free time, and is just a while loop that writes one char to the USB port until the write buffer is empty. Is there a more efficient way to do this?
One of my concerns that I have, is that in the old system we had a board in the system dedicated to communications. The CPU would just write data across a bus to this board, and it would handle communications, which means that the CPU didn't have to waste free time handling the actual communications, but could offload the communications to a "co processor" (not a CPU but functionally the same here). Even with this concern though I figured I should be getting faster speeds given that full speed USB is on the order of MB/s while IEEE-488 is on the order of kB/s.
In short is this more likely a fundamental system constraint or a software optimization issue?
I thought that number was a dummy value that is a holdover from RS232 days, but I might be wrong.
You are correct, the baud number is a dummy value. If you create a CDC/RS232 adapter you would use this to configure your RS232 hardware, in this case it means nothing.
Is there a more efficient way to do this?
Absolutely! You should be writing chunks of data the same size as your USB endpoint for maximum transfer speed. Depending on the device you are using your stream of single byte writes may be gathered into a single packet before sending but from my experience (and your results) this is unlikely.
Depending on your latency requirements you can stick in a circular buffer and only issue data from it to the USB_Write function when you have ENDPOINT_SZ number of byes. If this results in excessive latency or your interface is not always communicating you may want to implement Nagles algorithm.
One of my concerns that I have, is that in the old system we had a board in the system dedicated to communications.
The NXP part you mentioned in the comments is without a doubt fast enough to saturate a USB full speed connection.
In short is this more likely a fundamental system constraint or a software optimization issue?
I would consider this a software design issue rather than an optimisation one, but no, it is unlikely you are fundamentally stuck.
Do take care to figure out exactly what sort of USB connection you are using though, if you are using USB 1.1 you will be limited to 64KB/s, USB 2.0 full speed you will be limited to 512KB/s. If you require higher throughput you should migrate to using a separate bulk endpoint for the data transfer.
I would recommend reading through the USB made simple site to get a good overview of the various USB speeds and their capabilities.
One final issue, vendor CDC libraries are not always the best and implementations of the CDC standard can vary. You can theoretically get more data through a CDC endpoint by using larger endpoints, I have seen this bring host side drivers to their knees though - if you go this route create a custom driver using bulk endpoints.
Try testing your device on multiple systems, you may find you get quite different results between windows and linux. This will help to point the finger at the host end.
And finally, make sure you are doing big buffered reads on the host side, USB will stop transferring data once the host side buffers are full.

Linux - How to upload code to a dedicated freescale chip NIC on my motherboard?

I have bought a Gigabyte g1.guerilla motherboard and the NIC is a dedicated freescale chip on the motherboard. It is connected to the PCI bus.
I am running Linux and unfortunately there is no driver for it. I am working to write one, however I am hitting a basic problem: How to communicate and upload code to its dedicated CPU-RAM?
Much help appreciated.
I am running on ubuntu and the chip is a mpc8308vmagd PowerQuicc II pro
I don't know anything about your specific motherboard or the processor, but are you totally sure you need to upload any code to the processor?
Usually, if a peripheral needs any code (firmware), it's already present on a ROM or a flash chip and you only need to touch it if you specifically want to write your own firmware for it. AFAIK the way it usually works is that the peripheral exposes a set of registers on the PCI bus and you interact with it by poking the registers (usually with MMIO). That is, you don't write code for the peripheral, but you write a kernel driver that pokes the registers (ie. the API for the peripheral) when it wants the device to do something.
Now, in general the register descriptions aren't often freely available, which can make writing drivers really hard.
If you really want/need to write your own firmware for the thing, it probably depends on where the code is stored. If it sits in ROM or in an inaccessible flash, you'll probably need to do some soldering. If the firmware is updatable, I'd probably try to reverse-engineer the software they provide for updating the firmware, if one is available. (Unless it allows uploading arbitrary files already, of course)

Linux USB device driver misconception

My question is going to be rather vague but I will try to explain as detailed as I can what I am trying to resolve.
Trying to learn Linux kernel USB stack I have started to think of making a simple USB driver for my Atmel evaluation board based on ARM M0+ MCU to run away from Windows tools (Visual Studio plugin).
I have spent few days learning kernel's USB API and come to conclusion of how to make this. My driver aims to make my board connected to PC through USB cable act like a simple USB flash drive. Making that I then can easily program it with a new version of firmware written by me.
I have found that I need to find out specific interface (I am talking about interface in terms of USB specification, not interface we used to use as a code abstraction) that holds an endpoint (pipe) responsible for interaction with flash memory. And then I can map it to character device and interact with it using standard I/O operations that are described in struct file_operations structure.
Simply using cat on /proc/* file descriptor that was created by USB Core subsystem I have investigated that interface responsible for interaction with flash memory holds bulk endpoint (likewise, this terms come from USB specification, CMIIAW) that act as a "descriptor". Linux kernel USB Core subsystem gives neat interfaces to talk to different kind of endpoints whether it control, interrupt, bulk or asynchronous endpoint.
Now I have come closer to my very question.
Also the main transfer unit in communication between two USB devices is abstraction called urb - you allocate it, you fill it, you send it to USB Core subsystem, you read it if it was IN type of urb and, finally, you free it. What is confusing for me and tightly related to my question is the next API include/linux/usb.h:
static inline void usb_fill_bulk_urb(struct urb *urb,
struct usb_device *dev,
unsigned int pipe,
void *transfer_buffer,
int buffer_length,
usb_complete_t complete_fn,
void *context)
Assume I have obtained an information from board's datasheet about where to write a program code. Let's say, we have 0x00100 - 0x10000 memory region. I will compile my code, obtain a binary and then using standard Linux tools or writing a simple user-space wrapper application I will use lseek to set file's offset to 0x00100 and write system call provided with a buffer (binary compiled previously) and it's length.
In kernel space, I will have to allocate urb in write system call handler, fill it with a buffer sent from user space and submit this urb to USB Core.
BUT I can not find a way how to specify an OFFSET set earlier by lseek. Do I miss something? Maybe I missed some concepts or, perhaps, I am watching in a wrong way?
When your embedded Linux device acts as a USB mass storage device, the flash as a peripheral on Linux device is unmounted, and the gadget driver is loaded. Linux then loses control to the flash, and now the PC connected to your Linux device fully controls the flash. This is because a flash as a USB device can only has one USb host.
The gadget driver works purely in kernel space. It does not receive or transmit data from/to user space. It calls vfs_read() and vfs_write() to access the files on the flash, with an field offset. The offset is got from the USB commands sent from your host - Windows PC.
There is no way to specify offset using USB subsystem's API. I misunderstood whole conception of USB as communication protocol, unwise me. You must first learn underlying protocol your device uses to communicate with others.
If your device acts as a USB HID device then learning specification of how to exchange data with USB HID device is the way to go. If there is something proprietary then you can do nothing but reverse engineer it (listening USB packets with a sniffer on system where a driver for your device exists).
As for my board it has embedded debugger that serves as a communication module besides being debugger itself. Specifically, my device is equipped with EDBG and here is a link on description of protocol it uses for communication.

Is there a suitable Two wire interface / I2C reading writing library in Contiki OS for Atmega128 platform?

I wish to read the EUI64 address from an AT24MAC602 memory chip interfaced to an Atmega128rfa1 MCU over the Two wire interface. I tried to modify the I2C master drivers which are available for other platforms to suit my need. However, I wasn't able to carry out these modifications successfully as the program stopped responding as soon as the slave address was written to the twi bus with Write flag set. I failed to uncover the underlying reasons for the same.
As Contiki OS is quite popular, i thought someone might have already come up with contiki specific libraries for reading writing over TWI interface for Atmega128rfa1 MCU. If so, please provide pointers to the twi drivers or documentation for the same, or suggest factors that should be considered for developing such drivers. Thank you.
If you don't have any luck finding/creating a driver for the TWI peripheral, you might consider emulating it by configuring the SDA/SCL pins as general I/O and then implementing the TWI protocol yourself. If you're just doing a one-time read of a chip ID then speed probably isn't a big concern, so this could work if you get desperate. Google should throw up a few examples of emulated TWI.

Which IO port for coding engines, sensors

I would like to control some physical engines, switches on/off, lights through a self written C API.
I already have a very general overview of how to achieve this:
Use the kernels abstraction, write a driver on it and use this as control. The driver itself has to manage incoming bytes and interpret them (depends on port).
I personally would prefer to use a USB port because I can use my MacBook to develope.
But I know that the protocol is quite complicated. However here are my specific questions:
Which port is good to use (is USB a suitable option?)
Could I simply wire a engine to the USBs power cables and connect the data cables to a power swith or do I require an extra board?
Are there better docs for OS X, BSD or gnu/Linux?
Bodo
To control physical engines, you have to add at least a power supply board, there is no way that your USB port drive a DC motor (maybe a LED).
The easiest I/O port on a computer is the LPT (parallel port), but this is a 'very' old thing. I agree that USB port is most convenient but in order to work easily with it I advise you to buy a small card.
This Usb board (or anything of the same kind) can do the trick.
I hope it could help you,

Resources