Add a kernel driver and userland program for the Topfield TF5000PVR range

of digital video recorders popular in Europe and Australia.

These devices have a USB client port which can be used to upload and
download recordings (and other files, such as MIPS binaries for execution
on the DVR's CPU) to/from their internal hard disk, in addition to some
other operations on files and directories.
This commit is contained in:
scw 2006-04-03 08:15:48 +00:00
parent 842f766ad5
commit 34b4a96dbb
17 changed files with 3131 additions and 15 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.610 2006/04/01 04:13:21 tnozaki Exp $
# $NetBSD: mi,v 1.611 2006/04/03 08:15:49 scw Exp $
. base-sys-root
./altroot base-sys-root
./bin base-sys-root
@ -652,6 +652,7 @@
./usr/bin/usbhidaction base-util-bin
./usr/bin/usbhidctl base-util-bin
./usr/bin/users base-util-bin
./usr/bin/utoppya base-util-bin
./usr/bin/uucp base-uucp-bin uucp
./usr/bin/uudecode base-util-bin
./usr/bin/uuencode base-util-bin

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.867 2006/03/30 00:00:24 rtr Exp $
# $NetBSD: mi,v 1.868 2006/04/03 08:15:49 scw Exp $
./etc/mtree/set.comp comp-sys-root
./usr/bin/addr2line comp-debug-bin bfd
./usr/bin/ar comp-util-bin bfd
@ -469,6 +469,7 @@
./usr/include/dev/usb/usbcdc.h comp-obsolete obsolete
./usr/include/dev/usb/usbdevs.h comp-obsolete obsolete
./usr/include/dev/usb/usbhid.h comp-c-include
./usr/include/dev/usb/utoppy.h comp-c-include
./usr/include/dev/vinum/request.h comp-obsolete obsolete
./usr/include/dev/vinum/statetexts.h comp-obsolete obsolete
./usr/include/dev/vinum/vinumext.h comp-obsolete obsolete

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.872 2006/03/28 20:54:13 riz Exp $
# $NetBSD: mi,v 1.873 2006/04/03 08:15:50 scw Exp $
./etc/mtree/set.man man-sys-root
./usr/share/info/am-utils.info man-amd-info info
./usr/share/info/as.info man-computil-info bfd,info
@ -463,6 +463,7 @@
./usr/share/man/cat1/usbhidaction.0 man-util-catman .cat
./usr/share/man/cat1/usbhidctl.0 man-util-catman .cat
./usr/share/man/cat1/users.0 man-util-catman .cat
./usr/share/man/cat1/utoppya.0 man-util-catman .cat
./usr/share/man/cat1/uucp.0 man-uucp-catman uucp,.cat
./usr/share/man/cat1/uudecode.0 man-uucp-catman .cat
./usr/share/man/cat1/uuencode.0 man-uucp-catman .cat
@ -1364,6 +1365,7 @@
./usr/share/man/cat4/userconf.0 man-sys-catman .cat
./usr/share/man/cat4/usscanner.0 man-sys-catman .cat
./usr/share/man/cat4/ustir.0 man-sys-catman .cat
./usr/share/man/cat4/utoppy.0 man-sys-catman .cat
./usr/share/man/cat4/uvisor.0 man-sys-catman .cat
./usr/share/man/cat4/uvscom.0 man-sys-catman .cat
./usr/share/man/cat4/uyap.0 man-sys-catman .cat
@ -2776,6 +2778,7 @@
./usr/share/man/man1/usbhidaction.1 man-util-man .man
./usr/share/man/man1/usbhidctl.1 man-util-man .man
./usr/share/man/man1/users.1 man-util-man .man
./usr/share/man/man1/utoppya.1 man-util-man .man
./usr/share/man/man1/uucp.1 man-uucp-man uucp,.man
./usr/share/man/man1/uudecode.1 man-uucp-man .man
./usr/share/man/man1/uuencode.1 man-uucp-man .man
@ -3677,6 +3680,7 @@
./usr/share/man/man4/userconf.4 man-sys-man .man
./usr/share/man/man4/usscanner.4 man-sys-man .man
./usr/share/man/man4/ustir.4 man-sys-man .man
./usr/share/man/man4/utoppy.4 man-sys-man .man
./usr/share/man/man4/uvisor.4 man-sys-man .man
./usr/share/man/man4/uvscom.4 man-sys-man .man
./usr/share/man/man4/uyap.4 man-sys-man .man

View File

@ -1,5 +1,5 @@
#!/bin/sh -
# $NetBSD: MAKEDEV.tmpl,v 1.51 2006/03/25 17:19:02 christos Exp $
# $NetBSD: MAKEDEV.tmpl,v 1.52 2006/04/03 08:15:50 scw Exp $
#
# Copyright (c) 2003 The NetBSD Foundation, Inc.
# All rights reserved.
@ -505,6 +505,7 @@ usbs)
makedev ttyY0 ttyY1
makedev urio0
makedev uscanner0 uscanner1
makedev utoppy0 utoppy1
makedev ugen0
;;
@ -561,6 +562,11 @@ uscanner*)
mkdev uscanner$unit c %uscanner_chr% $unit
;;
utoppy*)
unit=${i#utoppy}
mkdev utoppy$unit c %utoppy_chr% $unit
;;
ttyY*)
unit=${i#ttyY}
mkdev ttyY$unit c %ucycom_chr% $(($unit + $dialin )) "" "" $u_uucp

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.380 2006/03/28 20:50:57 riz Exp $
# $NetBSD: Makefile,v 1.381 2006/04/03 08:15:49 scw Exp $
# @(#)Makefile 8.1 (Berkeley) 6/18/93
MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 adc.4 adt7467c.4 adv.4 \
@ -53,7 +53,7 @@ MAN+= uaudio.4 ubsa.4 ucom.4 ucycom.4 udsbr.4 uftdi.4 ugen.4 uhid.4 \
umass.4 umct.4 umidi.4 umodem.4 ums.4 uplcom.4 urio.4 usb.4 \
uscanner.4 usscanner.4 ustir.4 uvisor.4 uvscom.4 uyap.4 \
aue.4 atu.4 axe.4 cdce.4 cue.4 kue.4 upl.4 url.4 udav.4 \
ehci.4 ohci.4 slhci.4 uhci.4
ehci.4 ohci.4 slhci.4 uhci.4 utoppy.4
# Ir devices
MAN+= irframe.4 cir.4 irframetty.4 oboe.4

View File

@ -1,4 +1,4 @@
.\" $NetBSD: usb.4,v 1.80 2005/12/26 19:48:12 perry Exp $
.\" $NetBSD: usb.4,v 1.81 2006/04/03 08:15:49 scw Exp $
.\"
.\" Copyright (c) 1999-2005 The NetBSD Foundation, Inc.
.\" All rights reserved.
@ -34,7 +34,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd August 29, 2005
.Dd April 3, 2006
.Dt USB 4
.Os
.Sh NAME
@ -185,6 +185,8 @@ driver for some USB scanners.
driver for some SCSI-over-USB scanners.
.It ustir
driver for SigmaTel STIr4200 USB-IrDA bridges.
.It utoppy
driver for Topfield TF5000PVR range of digital video recorders.
.It uvisor
Handspring Visor driver.
.It uvscom
@ -543,6 +545,7 @@ specifications can be found at:
.Xr uscanner 4 ,
.Xr usscanner 4 ,
.Xr ustir 4 ,
.Xr utoppy 4 ,
.Xr uvisor 4 ,
.Xr usbdevs 8
.Sh HISTORY

312
share/man/man4/utoppy.4 Normal file
View File

@ -0,0 +1,312 @@
.\" $NetBSD: utoppy.4,v 1.1 2006/04/03 08:15:49 scw Exp $
.\"
.\" Copyright (c) 2006 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Steve C. Woodford.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd April 3, 2006
.Dt UTOPPY 4
.Os
.Sh NAME
.Nm utoppy
.Nd USB driver for the Topfield TF5000PVR range of digital video recorders
.Sh SYNOPSIS
.Cd "utoppy* at uhub? port ?"
.Pp
.In dev/usb/utoppy.h
.Sh DESCRIPTION
The
.Nm
driver provides support for the Topfield TF5000PVR range of DVB recorders
(nicknamed
.Ql Toppy )
which are popular in Europe and Australia.
These recorders have a
.Tn USB
device interface which can be used to transfer
recordings to and from the unit's hard disk.
The
.Tn USB
interface can also be used to upload binary images for execution
on the Toppy's MIPS cpu.
.Pp
The Toppy's
.Tn USB
protocol has not been officially documented by Topfield,
but the basic features have been reverse engineered by others in order
to write replacements for the official
.Ql Altair
download/upload program from Topfield.
.Pp
Existing replacements for Altair suffer from the fact that they are
ultimately built on top of
.Xr ugen 4 .
This has a number of detrimental side-effects:
.Bl -enum
.It
Performance suffers since all Toppy command packets have to cross the
user-kernel interface.
.It
The userland programs are full of clutter to deal with interpreting the
command/status packets, not to mention byte-swapping and host endian
issues.
.It
Signals can interrupt a data transfer at a critical point, leaving the
Toppy in an undefined state.
For example, interrupting a download with
.Ql Turbo
mode enabled will leave the Toppy completely unresponsive to the remote
control, and prevent timer-based recordings from starting.
.El
.Pp
The
.Nm
driver provides a clean and stable interface to the Toppy protocol, and
ensures that an interrupt caused by a signal does not leave the Toppy in
and undefined state.
.Sh UTOPPY INTERFACE
Use the following header file to get access to the
.Tn utoppy
specific structures and defines.
.Bd -literal
#include \*[Lt]dev/usb/utoppy.h\*[Gt]
.Ed
.Pp
The
.Nm
driver can be accessed through the
.Pa /dev/utoppyN
character device.
The primary means of controlling the driver is by issuing a series of
.Xr ioctl 2
system calls followed by
.Xr read 2
or
.Xr write 2
system calls as appropriate.
.Pp
The following
.Xr ioctl 2
commands are supported by the
.Nm
driver:
.Bl -tag -width xxxxxx
.It Dv UTOPPYIOTURBO Fa "int *mode"
This command can be used to enable or disable
.Ql Turbo
mode for subsequent
.Dv UTOPPYIOREADFILE
or
.Dv UTOPPYIOWRITEFILE
commands (see below). If
.Fa num
is non-zero, Turbo mode will be enabled.
Otherwise Turbo mode will be disabled.
In non-Turbo mode, the Toppy's
.Tn USB
interface is capable of sustaining around 5.6 Mbit/s during a file transfer.
With Turbo mode enabled, it can sustain just over 16 Mbit/s.
Of course, these figures are valid only if the Toppy is connected via a
.Tn USB
2.0 interface.
Performance using an older
.Tn USB
1 interface will be significantly lower.
.It Dv UTOPPYIOCANCEL Fa void
This command can be used to abort an in-progress
.Dv UTOPPYIOREADDIR ,
.Dv UTOPPYIOREADFILE ,
or
.Dv UTOPPYIOWRITEFILE
command.
.It Dv UTOPPYIOREBOOT Fa void
This command will cause the Toppy to reboot cleanly.
.It Dv UTOPPYIOSTATS Fa "struct utoppy_stats *stats"
This command retrieves statistics for the Toppy's hard disk.
.Bd -literal
struct utoppy_stats {
uint64_t us_hdd_size; /* Size of the disk, in bytes */
uint64_t us_hdd_free; /* Free space, in bytes */
};
.Ed
.It UTOPPYIORENAME Fa "struct utoppy_rename *rename"
This command is used to rename a file or directory on the Toppy's
hard disk.
The full pathname to each file must be provided.
.Bd -literal
struct utoppy_rename {
char *ur_old_path; /* Path to existing file */
char *ur_new_path; /* Path to new file */
};
.Ed
.It UTOPPYIOMKDIR Fa "char *path"
This command creates the directory specified by
.Fa path .
.It UTOPPYIODELETE Fa "char *path"
This command deletes the file or directory specified by
.Fa path .
.It UTOPPYIOREADDIR Fa "char *path"
This command initiates a read of the contents of the directory specified by
.Fa path .
After issuing this command, the directory contents must be read using
consecutive
.Xr read 2
system calls.
Each
.Xr read 2
will transfer one or more directory entries into the user-supplied buffer.
The buffer must be large enough to receive at least one directory entry.
When
.Xr read 2
returns zero, all directory entries have been read.
.Pp
A directory entry is described using the following data structure:
.Bd -literal
struct utoppy_dirent {
char ud_path[UTOPPY_MAX_FILENAME_LEN + 1];
enum {
UTOPPY_DIRENT_UNKNOWN,
UTOPPY_DIRENT_DIRECTORY,
UTOPPY_DIRENT_FILE
} ud_type;
off_t ud_size;
time_t ud_mtime;
uint32_t ud_attributes;
};
.Ed
.Pp
The
.Va ud_path
field contains the name of the directory entry.
.Pp
The
.Va ud_type
field specifies whether the entry corresponds to a file or a sub-directory.
.Pp
The
.Va ud_size
field is valid for files only, and specifies the file's size in bytes.
.Pp
The
.Va ud_mtime
field describes the file or directory's modification time, specified as
seconds from the Unix epoch.
The timestamp is relative to the current timezone, so
.Xr localtime 3
can be used to convert it into human readable form.
Note that the Toppy sets directory timestamps to a predefined value so
they are not particularly useful.
.Pp
The
.Va ud_attributes
field is not used at this time.
.It UTOPPYIOREADFILE Fa "struct utoppy_readfile *"
This command is used to initiate reading a file from the Toppy's hard disk.
The full pathname, together with the file offset at which to start reading,
is specified using the following data structure:
.Bd -literal
struct utoppy_readfile {
char *ur_path;
off_t ur_offset;
};
.Ed
.Pp
After issuing this command, the file must be read using consecutive
.Xr read 2
system calls.
When
.Xr read 2
returns zero, the entire file has been read.
.It UTOPPYIOWRITEFILE Fa "struct utoppy_writefile *"
This command is used to initiate writing to a file on the Toppy's hard disk.
The file to be written is described using the following data structure:
.Bd -literal
struct utoppy_writefile {
char *uw_path;
off_t uw_offset;
off_t uw_size;
time_t uw_mtime;
};
.Ed
.Pp
The
.Va uw_path
field specifies the full pathname of the file to be written.
.Pp
The
.Va uw_offset
field specifies the file offset at which to start writing, assuming the file
already exists.
Otherwise,
.Va uw_offset
must be zero.
.Pp
The protocol requires that the Toppy must be informed of a file's size in
advance of the file being written.
This is accomplished using the
.Va uw_size
field.
It may be possible to work around this limitation in a future version of
the driver.
.Pp
The
.Va uw_mtime
field specifies the file's timestamp expressed as seconds from the Unix epoch
in the local timezone.
.El
.Pp
Due to limitations with the protocol, a
.Nm
device can be opened by only one application at a time.
Also, only a single
.Dv UTOPPYIOREADDIR ,
.Dv UTOPPYIOREADFILE ,
or
.Dv UTOPPYIOWRITEFILE
command can be in progress at any given time.
.Sh FILES
.Bl -tag -width /dev/utoppy0 -compact
.It Pa /dev/utoppy0
device node
.El
.Sh SEE ALSO
.Xr utoppya 1 ,
.Xr usb 4
.Sh HISTORY
The
.Nm
driver
appeared in
.Nx 4.0 .
.Sh AUTHORS
.An Steve C. Woodford Aq scw@netbsd.org

View File

@ -1,4 +1,4 @@
# $NetBSD: majors,v 1.20 2006/02/25 17:16:45 christos Exp $
# $NetBSD: majors,v 1.21 2006/04/03 08:15:48 scw Exp $
#
# Device majors for Machine-Independent drivers.
#
@ -23,3 +23,4 @@ device-major veriexec char 170 veriexec
device-major fw char 171 ieee1394if
device-major ucycom char 172 ucycom
device-major gpio char 173 gpio
device-major utoppy char 174 utoppy

View File

@ -1,4 +1,4 @@
# $NetBSD: DEVNAMES,v 1.195 2006/03/23 16:20:59 he Exp $
# $NetBSD: DEVNAMES,v 1.196 2006/04/03 08:15:50 scw Exp $
#
# This file contains all used device names and defined attributes in
# alphabetical order. New devices added to the system somewhere should first
@ -1329,6 +1329,7 @@ uscanner MI
usscanner MI
ustir MI
ut vax
utoppy MI
uu vax
uvisor MI
uvscom MI

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.7 2005/12/11 12:24:00 christos Exp $
# $NetBSD: Makefile,v 1.8 2006/04/03 08:15:48 scw Exp $
# use 'make -f Makefile.usbdevs' to make usbdevs.h and usbdevs_data.h
# _after_ you committed usbdevs. See comment in Makefile.usbdevs
@ -6,6 +6,6 @@
INCSDIR= /usr/include/dev/usb
# Only install includes which are used by userland
INCS= ukyopon.h urio.h usb.h usbhid.h
INCS= ukyopon.h urio.h usb.h usbhid.h utoppy.h
.include <bsd.kinc.mk>

View File

@ -1,4 +1,4 @@
# $NetBSD: files.usb,v 1.65 2005/12/11 12:24:00 christos Exp $
# $NetBSD: files.usb,v 1.66 2006/04/03 08:15:48 scw Exp $
#
# Config file and device description for machine-independent USB code.
# Included by ports that need it. Ports that use it must provide
@ -262,3 +262,8 @@ file dev/usb/if_atu.c atu
# Ralink Technology RT2500USB
attach ral at uhub with ural
file dev/usb/if_ural.c ural
# Topfield digital PVRs
device utoppy
attach utoppy at uhub
file dev/usb/utoppy.c utoppy

1917
sys/dev/usb/utoppy.c Normal file

File diff suppressed because it is too large Load Diff

106
sys/dev/usb/utoppy.h Normal file
View File

@ -0,0 +1,106 @@
/* $NetBSD: utoppy.h,v 1.1 2006/04/03 08:15:48 scw Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _DEV_USB_UTOPPY_H_
#define _DEV_USB_UTOPPY_H_
#include <sys/ioccom.h>
#define UTOPPY_MAX_FILENAME_LEN 95
#define UTOPPY_MAX_PATHNAME_LEN ((UTOPPY_MAX_FILENAME_LEN + 1) * 6)
/* Set/clear turbo mode */
#define UTOPPYIOTURBO _IOW('t', 1, int)
/* Cancel previous op */
#define UTOPPYIOCANCEL _IO('t', 2)
/* Reboot the toppy */
#define UTOPPYIOREBOOT _IO('t', 3)
/* Get status of Toppy's hard disk drive */
#define UTOPPYIOSTATS _IOR('t', 4, struct utoppy_stats)
struct utoppy_stats {
uint64_t us_hdd_size;
uint64_t us_hdd_free;
};
/* Rename a file/directory */
#define UTOPPYIORENAME _IOW('t', 5, struct utoppy_rename)
struct utoppy_rename {
char *ur_old_path;
char *ur_new_path;
};
/* Create a directory */
#define UTOPPYIOMKDIR _IOW('t', 6, char *)
/* Delete a file/directory */
#define UTOPPYIODELETE _IOW('t', 7, char *)
/* Initiate reading of the contents of a directory */
#define UTOPPYIOREADDIR _IOW('t', 8, char *)
struct utoppy_dirent {
char ud_path[UTOPPY_MAX_FILENAME_LEN + 1];
enum {
UTOPPY_DIRENT_UNKNOWN,
UTOPPY_DIRENT_DIRECTORY,
UTOPPY_DIRENT_FILE
} ud_type;
off_t ud_size;
time_t ud_mtime;
uint32_t ud_attributes;
};
/* Initiate reading from a specific file */
#define UTOPPYIOREADFILE _IOW('t', 9, struct utoppy_readfile)
struct utoppy_readfile {
char *ur_path;
off_t ur_offset;
};
/* Initiate writing to a new file */
#define UTOPPYIOWRITEFILE _IOW('t', 10, struct utoppy_writefile)
struct utoppy_writefile {
char *uw_path;
off_t uw_offset;
off_t uw_size;
time_t uw_mtime;
};
#endif /* _DEV_USB_UTOPPY_H_ */

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.149 2006/01/24 19:01:45 elad Exp $
# $NetBSD: Makefile,v 1.150 2006/04/03 08:15:48 scw Exp $
# from: @(#)Makefile 8.3 (Berkeley) 1/7/94
.include <bsd.own.mk>
@ -24,7 +24,7 @@ SUBDIR= apply apropos asa at audio awk banner basename biff \
shuffle sockstat soelim sort spell split stat su systat tail talk \
tcopy tee telnet tftp time tip tn3270 top touch tput \
tr true tset tsort tty ul uname unexpand unifdef \
uniq units unvis usbhidaction usbhidctl users \
uniq units unvis usbhidaction usbhidctl users utoppya \
uudecode uuencode uuidgen vacation vgrind vi vis vmstat vndcompress w \
wall wc what whatis whereis who whois window \
write xargs xinstall xlint xstr yacc yes

12
usr.bin/utoppya/Makefile Normal file
View File

@ -0,0 +1,12 @@
# $NetBSD: Makefile,v 1.1 2006/04/03 08:15:48 scw Exp $
.include <bsd.own.mk>
PROG= utoppya
SRCS= utoppya.c progressbar.c
CPPFLAGS+=-I${NETBSDSRCDIR}/usr.bin/ftp -DSTANDALONE_PROGRESS
.PATH: ${NETBSDSRCDIR}/usr.bin/ftp
.include <bsd.prog.mk>

169
usr.bin/utoppya/utoppya.1 Normal file
View File

@ -0,0 +1,169 @@
.\" $NetBSD: utoppya.1,v 1.1 2006/04/03 08:15:49 scw Exp $
.\"
.\" Copyright (c) 2006 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
.\" by Steve C. Woodford.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the NetBSD
.\" Foundation, Inc. and its contributors.
.\" 4. Neither the name of The NetBSD Foundation nor the names of its
.\" contributors may be used to endorse or promote products derived
.\" from this software without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
.Dd April 3, 2006
.Dt UTOPPYA 1
.Os
.Sh NAME
.Nm utoppya
.Nd Topfield TF5000PVR file manipulation program
.Sh SYNOPSIS
.Nm
.Op Fl f Ar device
.Ar command ...
.Sh DESCRIPTION
.Nm
is the userland interface to the
.Xr utoppy 4
device driver.
.Pp
The options are as follows:
.Bl -tag -width Ds
.It Fl f
Communicate with
.Ar device
instead of the default
.Pa /dev/utoppy0 .
.El
.Pp
Using the services of the
.Xr utoppy 4
driver,
.Nm
can perform the following operations, specified by the
.Ar command
operand:
.Bl -tag -width Ds
.It Cm df
Display disk size and free space
.It Cm ls Op Ar directory
List the files in the specified
.Ar directory .
Default is the Toppy's root directory.
.It Cm mkdir Ao Ar directory Ac
Make the specified
.Ar directory .
You must supply the full pathname to
.Ar directory .
.It Cm rm Ao Ar pathname Ac
Delete the file or directory specified by
.Ar pathname .
.It Cm rename Ao Ar source Ac Ao Ar target Ac
Rename the file or directory specified by the
.Ar source
operand to the destination file or directory specified by the
.Ar target
operand.
.It Cm get Oo Fl prt Oc Ao Ar toppyfile Ac Oo Ar localfile Oc
Copy
.Ar toppyfile
from the Toppy to
.Ar localfile
on the local filesystem.
If
.Ar localfile
is omitted, the file will be copied into the current directory and will be
named using the last component of the
.Ar toppyfile
operand.
If
.Ar localfile
is -, then
.Ar toppyfile
will be copied to the standard output.
.Pp
The following options are available for the
.Nm get
command:
.Bl -tag -width Ds
.It Fl p
Display a progress bar.
.It Fl r
This option is useful if you wish to resume a previously interrupted
.Nm get
command.
Instead of restarting from the beginning of the file, the transfer will
resume where it left off.
.It Fl t
Enable
.Ql Turbo
mode.
This instructs the Toppy to drop everything and concentrate on transferring
the file as quickly as possible.
You will be able to watch live TV, but all other functions, including
changing channel via the remote control, will be inoperative.
.El
.It Cm put Oo Fl prt Oc Ao Ar localfile Ac Ao Ar toppyfile Ac
Copy
.Ar localfile
on the local filesystem to
.Ar toppyfile
on the Toppy.
If
.Ar toppyfile
specifies a directory on the Toppy, the last component of the
.Ar localfile
operand will be appended to the
.Ar toppyfile
operand.
.Pp
The options described for the
.Nm get
command (above) also apply to the
.Nm put
command.
.El
.Sh FILES
.Pa /dev/utoppy0
The default Topfield TF5000PVR instance.
.Sh SEE ALSO
.Xr utoppy 4 ,
.Xr usb 4
.Sh HISTORY
The
.Nm
command first appeared in
.Nx 4.0
and was inspired by
.Ql ftpd-topfield
written by Steve Bennett
.Aq msteveb at ozemail.com.au
and
.Ql puppy
written by Peter Urbanec
.Aq toppy at urbanec.net
.Sh AUTHORS
.An Steve C. Woodford Aq scw@netbsd.org

578
usr.bin/utoppya/utoppya.c Normal file
View File

@ -0,0 +1,578 @@
/* $NetBSD: utoppya.c,v 1.1 2006/04/03 08:15:48 scw Exp $ */
/*-
* Copyright (c) 2006 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by Steve C. Woodford.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the NetBSD
* Foundation, Inc. and its contributors.
* 4. Neither the name of The NetBSD Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <sysexits.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <time.h>
#include <dev/usb/utoppy.h>
#define GLOBAL
#include "progressbar.h"
#define _PATH_DEV_UTOPPY "/dev/utoppy0"
/*
* This looks weird for a reason. The toppy protocol allows for data to be
* transferred in 65535-byte chunks only. Anything more than this has to be
* split within the driver. The following value leaves enough space for the
* packet header plus some alignmnent slop.
*/
#define TOPPY_IO_SIZE 0xffec
static int toppy_fd;
static void cmd_df(int, char **);
static void cmd_ls(int, char **);
static void cmd_rm(int, char **);
static void cmd_mkdir(int, char **);
static void cmd_rename(int, char **);
static void cmd_get(int, char **);
static void cmd_put(int, char **);
static struct toppy_command {
const char *tc_cmd;
void (*tc_handler)(int, char **);
} toppy_commands[] = {
{"df", cmd_df},
{"ls", cmd_ls},
{"get", cmd_get},
{"mkdir", cmd_mkdir},
{"put", cmd_put},
{"rename", cmd_rename},
{"rm", cmd_rm},
{NULL, NULL}
};
static void
usage(void)
{
fprintf(stderr, "usage: %s [-f <path>] <cmd> ...\n",
getprogname());
exit(EX_USAGE);
}
int
main(int argc, char *argv[])
{
struct toppy_command *tc;
const char *devpath;
int ch;
setprogname(argv[0]);
devpath = _PATH_DEV_UTOPPY;
while ((ch = getopt(argc, argv, "f:")) != -1) {
switch (ch) {
case 'f':
devpath = optarg;
break;
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc == 0)
usage();
for (tc = toppy_commands; tc->tc_cmd != NULL; tc++)
if (strcasecmp(argv[0], tc->tc_cmd) == 0)
break;
if (tc->tc_cmd == NULL)
errx(EX_USAGE, "'%s' is not a valid command", argv[0]);
if ((toppy_fd = open(devpath, O_RDWR)) < 0)
err(EX_OSERR, "open(%s)", devpath);
(*tc->tc_handler)(argc, argv);
close(toppy_fd);
return (0);
}
static int
find_toppy_dirent(const char *path, struct utoppy_dirent *udp)
{
struct utoppy_dirent ud;
char *d, *b, dir[FILENAME_MAX];
ssize_t l;
strncpy(dir, path, sizeof(dir));
b = basename(dir);
d = dirname(dir);
if (strcmp(b, "/") == 0 || strcmp(b, ".") == 0 || strcmp(d, ".") == 0)
errx(EX_USAGE, "'%s' is not a valid Toppy pathname", path);
if (ioctl(toppy_fd, UTOPPYIOREADDIR, &d) < 0)
err(EX_OSERR, "ioctl(UTOPPYIOREADDIR, %s)", d);
if (udp == NULL)
udp = &ud;
while ((l = read(toppy_fd, udp, sizeof(*udp))) == sizeof(*udp)) {
if (strcmp(b, udp->ud_path) == 0)
break;
}
if (l < 0)
err(EX_OSERR, "read(TOPPYDIR, %s)", d);
if (l == 0)
return (0);
while (read(toppy_fd, &ud, sizeof(ud)) > 0)
;
return (1);
}
static void
cmd_df(int argc, char **argv)
{
struct utoppy_stats us;
if (ioctl(toppy_fd, UTOPPYIOSTATS, &us) < 0)
err(EX_OSERR, "ioctl(UTOPPYIOSTATS)");
printf("Hard Disk Size: %lld MB\n", us.us_hdd_size / (1024 * 1024));
printf("Hard Disk Free: %lld MB\n", us.us_hdd_free / (1024 * 1024));
}
static void
cmd_ls(int argc, char **argv)
{
struct utoppy_dirent ud;
struct tm *tm;
char *dir, *ext, dirbuf[2], ex, ft, tmbuf[32];
ssize_t l;
if (argc == 1) {
dirbuf[0] = '/';
dirbuf[1] = '\0';
dir = dirbuf;
} else
if (argc == 2)
dir = argv[1];
else
errx(EX_USAGE, "usage: ls [toppy-pathname]");
if (ioctl(toppy_fd, UTOPPYIOREADDIR, &dir) < 0)
err(EX_OSERR, "ioctl(UTOPPYIOREADDIR, %s)", dir);
while ((l = read(toppy_fd, &ud, sizeof(ud))) == sizeof(ud)) {
switch (ud.ud_type) {
default:
ft = '?';
break;
case UTOPPY_DIRENT_DIRECTORY:
ft = 'd';
break;
case UTOPPY_DIRENT_FILE:
ft = '-';
break;
}
if ((ext = strrchr(ud.ud_path, '.')) != NULL &&
strcasecmp(ext, ".tap") == 0)
ex = 'x';
else
ex = '-';
tm = localtime(&ud.ud_mtime);
strftime(tmbuf, sizeof(tmbuf), "%b %e %G %R", tm);
printf("%crw%c %11lld %s %s\n", ft, ex, ud.ud_size, tmbuf,
ud.ud_path);
}
if (l < 0)
err(EX_OSERR, "read(utoppy_dirent)");
}
static void
cmd_rm(int argc, char **argv)
{
char *path;
if (argc != 2)
errx(EX_USAGE, "usage: rm <toppy-pathname>");
path = argv[1];
if (ioctl(toppy_fd, UTOPPYIODELETE, &path) < 0)
err(EX_OSERR, "ioctl(UTOPPYIODELETE, %s)", path);
}
static void
cmd_mkdir(int argc, char **argv)
{
char *path;
if (argc != 2)
errx(EX_USAGE, "usage: mkdir <toppy-pathname>");
path = argv[1];
if (find_toppy_dirent(path, NULL))
errx(EX_DATAERR, "'%s' already exists", path);
if (ioctl(toppy_fd, UTOPPYIOMKDIR, &path) < 0)
err(EX_OSERR, "ioctl(UTOPPYIOMKDIR, %s)", path);
}
static void
cmd_rename(int argc, char **argv)
{
struct utoppy_dirent ud;
struct utoppy_rename ur;
char *oldpath, *newpath, *o, *n;
if (argc != 3)
errx(EX_USAGE, "usage: rename <from> <to>");
o = oldpath = argv[1];
n = newpath = argv[2];
for (o = oldpath; *o != '\0'; o++)
if (*o == '\\')
*o = '/';
for (n = newpath; *n != '\0'; n++)
if (*n == '\\')
*n = '/';
for (o = oldpath; *o && *o == '\\'; o++)
;
for (n = newpath; *n && *n == '\\'; n++)
;
if (strcmp(n, o) == 0)
errx(EX_DATAERR, "'%s' and '%s' refer to the same file\n",
oldpath, newpath);
if (find_toppy_dirent(oldpath, &ud) == 0)
errx(EX_DATAERR, "'%s' does not exist on the Toppy", oldpath);
if (ud.ud_type != UTOPPY_DIRENT_FILE)
errx(EX_DATAERR, "%s: not a regular file", oldpath);
if (find_toppy_dirent(newpath, &ud))
errx(EX_DATAERR, "'%s' already exists", newpath);
ur.ur_old_path = o;
ur.ur_new_path = n;
if (ioctl(toppy_fd, UTOPPYIORENAME, &ur) < 0)
err(EX_OSERR, "ioctl(UTOPPYIORENAME, %s, %s)", oldpath,
newpath);
}
static void
init_progress(FILE *to, char *f, off_t fsize, off_t restart)
{
struct ttysize ts;
if (ioctl(fileno(to), TIOCGSIZE, &ts) == -1)
ttywidth = 80;
else
ttywidth = ts.ts_cols;
ttyout = to;
progress = 1;
bytes = 0;
filesize = fsize;
restart_point = restart;
prefix = f;
}
static void
cmd_get(int argc, char **argv)
{
struct utoppy_readfile ur;
struct utoppy_dirent ud;
struct stat st;
char *dst, dstbuf[FILENAME_MAX];
uint8_t *buf;
ssize_t l;
size_t rv;
int ch, turbo_mode = 0, reget = 0, progbar = 0;
FILE *ofp, *to;
optind = 1;
optreset = 1;
while ((ch = getopt(argc, argv, "prt")) != -1) {
switch (ch) {
case 'p':
progbar = 1;
break;
case 'r':
reget = 1;
break;
case 't':
turbo_mode = 1;
break;
default:
get_usage:
errx(EX_USAGE, "usage: get [-prt] <toppy-pathname> "
"[file | directory]");
}
}
argc -= optind;
argv += optind;
if (argc == 1)
dst = basename(argv[0]);
else
if (argc == 2) {
dst = argv[1];
if (stat(dst, &st) == 0 && S_ISDIR(st.st_mode)) {
snprintf(dstbuf, sizeof(dstbuf), "%s/%s", dst,
basename(argv[0]));
dst = dstbuf;
}
} else
goto get_usage;
ur.ur_path = argv[0];
ur.ur_offset = 0;
if ((buf = malloc(TOPPY_IO_SIZE)) == NULL)
err(EX_OSERR, "malloc(TOPPY_IO_SIZE)");
if (strcmp(dst, "-") == 0) {
ofp = stdout;
to = stderr;
if (reget)
warnx("Ignoring -r option in combination with stdout");
} else {
to = stdout;
if (reget) {
if (stat(dst, &st) < 0) {
if (errno != ENOENT)
err(EX_OSERR, "stat(%s)", dst);
} else
if (!S_ISREG(st.st_mode))
errx(EX_DATAERR, "-r only works with regular "
"files");
else
ur.ur_offset = st.st_size;
}
if ((ofp = fopen(dst, reget ? "a" : "w")) == NULL)
err(EX_OSERR, "fopen(%s)", dst);
}
if (progbar) {
if (find_toppy_dirent(ur.ur_path, &ud) == 0)
ud.ud_size = 0;
init_progress(to, dst, ud.ud_size, ur.ur_offset);
}
if (ioctl(toppy_fd, UTOPPYIOTURBO, &turbo_mode) < 0)
err(EX_OSERR, "ioctl(UTOPPYIOTURBO, %d)", turbo_mode);
if (ioctl(toppy_fd, UTOPPYIOREADFILE, &ur) < 0)
err(EX_OSERR, "ioctl(UTOPPYIOREADFILE, %s)", ur.ur_path);
if (progbar)
progressmeter(-1);
for (;;) {
while ((l = read(toppy_fd, buf, TOPPY_IO_SIZE)) < 0 &&
errno == EINTR)
;
if (l <= 0)
break;
rv = fwrite(buf, 1, l, ofp);
if (rv != l) {
if (ofp != stdout)
fclose(ofp);
progressmeter(1);
err(EX_OSERR, "fwrite(%s)", dst);
}
bytes += l;
}
if (progbar)
progressmeter(1);
if (ofp != stdout)
fclose(ofp);
if (l < 0)
err(EX_OSERR, "read(TOPPY: ur.ur_path)");
free(buf);
}
static void
cmd_put(int argc, char **argv)
{
struct utoppy_writefile uw;
struct utoppy_dirent ud;
struct stat st;
char dstbuf[FILENAME_MAX];
char *src;
void *buf;
ssize_t rv;
size_t l;
int ch, turbo_mode = 0, reput = 0, progbar = 0;
FILE *ifp;
optind = 1;
optreset = 1;
while ((ch = getopt(argc, argv, "prt")) != -1) {
switch (ch) {
case 'p':
progbar = 1;
break;
case 'r':
reput = 1;
break;
case 't':
turbo_mode = 1;
break;
default:
put_usage:
errx(EX_USAGE, "usage: put [-prt] <local-pathname> "
"<toppy-pathname>");
}
}
argc -= optind;
argv += optind;
if (argc != 2)
goto put_usage;
src = argv[0];
uw.uw_path = argv[1];
if (stat(src, &st) < 0)
err(EX_OSERR, "%s", src);
if (!S_ISREG(st.st_mode))
errx(EX_DATAERR, "'%s' is not a regular file", src);
uw.uw_size = st.st_size;
uw.uw_mtime = st.st_mtime;
uw.uw_offset = 0;
if (find_toppy_dirent(uw.uw_path, &ud)) {
if (ud.ud_type == UTOPPY_DIRENT_DIRECTORY) {
snprintf(dstbuf, sizeof(dstbuf), "%s/%s", uw.uw_path,
basename(src));
uw.uw_path = dstbuf;
} else
if (ud.ud_type != UTOPPY_DIRENT_FILE)
errx(EX_DATAERR, "'%s' is not a regular file.",
uw.uw_path);
else
if (reput) {
if (ud.ud_size > uw.uw_size)
errx(EX_DATAERR, "'%s' is already larger than "
"'%s'", uw.uw_path, src);
uw.uw_size -= ud.ud_size;
uw.uw_offset = ud.ud_size;
}
}
if ((buf = malloc(TOPPY_IO_SIZE)) == NULL)
err(EX_OSERR, "malloc(TOPPY_IO_SIZE)");
if ((ifp = fopen(src, "r")) == NULL)
err(EX_OSERR, "fopen(%s)", src);
if (ioctl(toppy_fd, UTOPPYIOTURBO, &turbo_mode) < 0)
err(EX_OSERR, "ioctl(UTOPPYIOTURBO, %d)", turbo_mode);
if (ioctl(toppy_fd, UTOPPYIOWRITEFILE, &uw) < 0)
err(EX_OSERR, "ioctl(UTOPPYIOWRITEFILE, %s)", uw.uw_path);
if (progbar)
init_progress(stdout, src, st.st_size, uw.uw_offset);
if (progbar)
progressmeter(-1);
while ((l = fread(buf, 1, TOPPY_IO_SIZE, ifp)) > 0) {
rv = write(toppy_fd, buf, l);
if (rv != l) {
fclose(ifp);
if (progbar)
progressmeter(1);
err(EX_OSERR, "write(TOPPY: %s)", uw.uw_path);
}
bytes += l;
}
if (progbar)
progressmeter(1);
if (ferror(ifp))
err(EX_OSERR, "fread(%s)", src);
fclose(ifp);
free(buf);
}