January 21, 2007

Capturing HDV stream from camera in Linux over FireWire

Things are a bit in disarray in the HDV Linux department. While there are some good Linux applications out there supporting HD video editing (such as Cinelerra), getting HDV stream out of the camera via ieee1394 aka FireWire aka iLink proved to be a formiddable task.

Anyway, after getting hold of HDV-capable Canon HV10 digital video camera, I quickly found that dvgrab utility which was supposed to take care of my grabbing needs, doesn't work with HDV streams (which are in essence just 1440x1080i MPEG2 streams on a standard miniDV tape casette). Some googling later, it appears an utility with rather dull name test-mpeg2 (a part of libiec61883-utils RPM in Fedora Core Linux) should help me to capture the Firewire stream. But it didn't. It printed the hopeful "Starting to receive" message and just sat there doing nothing.

Another round of googling revealed another utility: mpg1394grab which worked despite being tiny (less than 200 lines), 4 years old and written for another video camera altogether. The compiling instructions are in the .c file itself.

Cutting some googling and trying, test-mpeg2 worked in the end, too. I had to provide an id of the ieee1394 node corresponing to my video camera as reported by plugreport:
test-mpeg2 -r 0 > capture.m2t
but before that, run this bit of magic:
plugctl -n 0 oPCR[0].n_p2p_connections=1
What does it do? -n 0 specifies an id of your camera FireWire node from plugreport, and the rest tells adapter to enable the use of Point2Point (p2p) connection for the output (oPCR) instead of a broadcast connection (bcast_connection from plugreport).

Unfortunately, after camera disconnect it has to be set up again. I haven't been able to write an udev rule to make it automatic because apparently udev doesn't catch connect/disconnect events on the FireWire bus (as monitored by udevmonitor).

So there it is, a single 1.5GB file containing 8 minutes of HDV video. Too bad dvgrab with its autosplitting doesn't work with HDV. Though it worked flawlessly in the combination with Kino when the camera was set to output a DV stream, so at least the DV capturing (and editing) looks quite solid in Linux.

January 15, 2007

Mobile Action 8730P USB Cable And Linux

More than an year ago, I had to use GPRS as a mean of Internet connectivity while travelling. It turned out the only option to connect my Siemens C75 phone to the notebook was a special USB cable. I double checked the Linux support, and bought the MA-8730P made by Mobile Action. It is based on pl2303 USB<->serial converter chip which is well supported in Linux.

Little I knew that the "P" version (meaning it can charge a phone directly from the USB while it is connected) had a little quirk: to start operating, a small unique sequence must be sent to the converter. Under Windows it is done by a bloaty "Phone Manager" supplied by Mobile Action. Under Linux, the device was recognized by the system but any connection attempts to the USB modem failed.

Some guys have captured this secret sequence under Windows and hacked together a tiny program which enables the cable operation. Since it will undoubtefully
be useful for those unfortunate souls who want to use the MobileAction USB cables under Linux, I'm posting it here (1k). Apparently it also works for the MA-8720P cable.

To compile, run
$ gcc -Wall -o chargerma chargerma.c
To use it, first connect the cable. You should see something like this in your dmesg output:
usb 4-1: new full speed USB device using uhci_hcd and address 3
usb 4-1: configuration #1 chosen from 1 choice
pl2303 4-1:1.0: pl2303 converter detected
usb 4-1: pl2303 converter now attached to ttyUSB0
usb 4-1: New USB device found, idVendor=067b, idProduct=2303
usb 4-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 4-1: Product: USB-Serial Controller
usb 4-1: Manufacturer: Prolific Technology Inc.
Now run (as root)
# ./chargerma /dev/ttyUSB0
Note that you have to run it every time after a cable disconnect to restore the modem functionality. I guess by making use of some udev/hotplug rules this program could be run automatically on each cable connect, but my hotplug-fu is not that strong yet.
Below is the full program text for the reference.

#include  <stdio.h>
#include <termio.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char* argv[])
{
int fd;
int status, result;
char *buf = "\x55\x55\x55\x55\x04\x01\r\x0";
struct termios options;

if (argc == 1) {
printf("usage: chargerma /dev/ttyUSB0\n");
return 0;
}

fd = open(argv[1], O_RDWR | O_NDELAY);
if (fd == -1) {
perror("open_port: Unable to open port\n");
return -1;
}

// Init the port
ioctl(fd, TIOCMGET, &status);
status |= TIOCM_RTS;
status &= ~TIOCM_DTR;
result = ioctl(fd, TIOCMSET, &status);
tcgetattr(fd, &options);
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;

// Send the secret sequence
result = write(fd, buf, 8);
if (result < 0)
fputs("write failed!\n", stderr);
tcsetattr(fd, TCSAFLUSH, &options);
close(fd);
return 0;
}


UPDATE: Some quick googling showed that exactly the same technique works also for the MA-8230P and MA-8910P USB cables. I would guess it'll work for all "P" variations of the Mobile Action cables (MA-8020P, 8250P, 8260P, 8270P, 8280P, 8290P, 8830P, 8310P, 8320P) in Linux. You're welcome to test it out!